1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* ONC_PLUS EXTRACT START */ 23 /* 24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 /* 34 * Transport Interface Library cooperating module - issue 2 35 */ 36 37 /* ONC_PLUS EXTRACT END */ 38 #include <sys/param.h> 39 #include <sys/types.h> 40 #include <sys/stream.h> 41 #include <sys/stropts.h> 42 #include <sys/strsubr.h> 43 #define _SUN_TPI_VERSION 2 44 #include <sys/tihdr.h> 45 #include <sys/timod.h> 46 #include <sys/suntpi.h> 47 #include <sys/debug.h> 48 #include <sys/strlog.h> 49 #include <sys/errno.h> 50 #include <sys/cred.h> 51 #include <sys/cmn_err.h> 52 #include <sys/kmem.h> 53 #include <sys/sysmacros.h> 54 #include <sys/ddi.h> 55 #include <sys/sunddi.h> 56 #include <sys/strsun.h> 57 #include <c2/audit.h> 58 59 /* 60 * This is the loadable module wrapper. 61 */ 62 #include <sys/conf.h> 63 #include <sys/modctl.h> 64 65 static struct streamtab timinfo; 66 67 static struct fmodsw fsw = { 68 "timod", 69 &timinfo, 70 D_MTQPAIR | D_MP, 71 }; 72 73 /* 74 * Module linkage information for the kernel. 75 */ 76 77 static struct modlstrmod modlstrmod = { 78 &mod_strmodops, "transport interface str mod", &fsw 79 }; 80 81 static struct modlinkage modlinkage = { 82 MODREV_1, &modlstrmod, NULL 83 }; 84 85 static krwlock_t tim_list_rwlock; 86 87 /* 88 * This module keeps track of capabilities of underlying transport. Information 89 * is persistent through module invocations (open/close). Currently it remembers 90 * whether underlying transport supports TI_GET{MY,PEER}NAME ioctls and 91 * T_CAPABILITY_REQ message. This module either passes ioctl/messages to the 92 * transport or emulates it when transport doesn't understand these 93 * ioctl/messages. 94 * 95 * It is assumed that transport supports T_CAPABILITY_REQ when timod receives 96 * T_CAPABILITY_ACK from the transport. There is no current standard describing 97 * transport behaviour when it receives unknown message type, so following 98 * reactions are expected and handled: 99 * 100 * 1) Transport drops unknown T_CAPABILITY_REQ message type. In this case timod 101 * will wait for tcap_wait time and assume that transport doesn't provide 102 * this message type. T_CAPABILITY_REQ should never travel over the wire, so 103 * timeout value should only take into consideration internal processing time 104 * for the message. From user standpoint it may mean that an application will 105 * hang for TCAP_WAIT time in the kernel the first time this message is used 106 * with some particular transport (e.g. TCP/IP) during system uptime. 107 * 108 * 2) Transport responds with T_ERROR_ACK specifying T_CAPABILITY_REQ as 109 * original message type. In this case it is assumed that transport doesn't 110 * support it (which may not always be true - some transports return 111 * T_ERROR_ACK in other cases like lack of system memory). 112 * 113 * 3) Transport responds with M_ERROR, effectively shutting down the 114 * stream. Unfortunately there is no standard way to pass the reason of 115 * M_ERROR message back to the caller, so it is assumed that if M_ERROR was 116 * sent in response to T_CAPABILITY_REQ message, transport doesn't support 117 * it. 118 * 119 * It is possible under certain circumstances that timod will incorrectly assume 120 * that underlying transport doesn't provide T_CAPABILITY_REQ message type. In 121 * this "worst-case" scenario timod will emulate its functionality by itself and 122 * will provide only TC1_INFO capability. All other bits in CAP_bits1 field are 123 * cleaned. TC1_INFO is emulated by sending T_INFO_REQ down to transport 124 * provider. 125 */ 126 127 /* 128 * Notes about locking: 129 * 130 * tim_list_rwlock protects the list of tim_tim structures itself. When this 131 * lock is held, the list itself is stable, but the contents of the entries 132 * themselves might not be. 133 * 134 * The rest of the members are generally protected by D_MTQPAIR, which 135 * specifies a default exclusive inner perimeter. If you're looking at 136 * q->q_ptr, then it's stable. 137 * 138 * There's one exception to this rule: tim_peer{maxlen,len,name}. These members 139 * are touched without entering the associated STREAMS perimeter because we 140 * get the pointer via tim_findlink() rather than q_ptr. These are protected 141 * by tim_mutex instead. If you don't hold that lock, don't look at them. 142 * 143 * (It would be possible to separate out the 'set by T_CONN_RES' cases from the 144 * others, but there appears to be no reason to do so.) 145 */ 146 struct tim_tim { 147 uint32_t tim_flags; 148 t_uscalar_t tim_backlog; 149 mblk_t *tim_iocsave; 150 t_scalar_t tim_mymaxlen; 151 t_scalar_t tim_mylen; 152 caddr_t tim_myname; 153 t_scalar_t tim_peermaxlen; 154 t_scalar_t tim_peerlen; 155 caddr_t tim_peername; 156 cred_t *tim_peercred; 157 mblk_t *tim_consave; 158 bufcall_id_t tim_wbufcid; 159 bufcall_id_t tim_rbufcid; 160 timeout_id_t tim_wtimoutid; 161 timeout_id_t tim_rtimoutid; 162 /* Protected by the global tim_list_rwlock for all instances */ 163 struct tim_tim *tim_next; 164 struct tim_tim **tim_ptpn; 165 t_uscalar_t tim_acceptor; 166 t_scalar_t tim_saved_prim; /* Primitive from message */ 167 /* part of ioctl. */ 168 timeout_id_t tim_tcap_timoutid; /* For T_CAP_REQ timeout */ 169 tpi_provinfo_t *tim_provinfo; /* Transport description */ 170 kmutex_t tim_mutex; /* protect tim_peer* */ 171 pid_t tim_cpid; 172 }; 173 174 175 /* 176 * Local flags used with tim_flags field in instance structure of 177 * type 'struct _ti_user' declared above. 178 * Historical note: 179 * This namespace constants were previously declared in a 180 * a very messed up namespace in timod.h 181 * 182 * There may be 3 states for transport: 183 * 184 * 1) It provides T_CAPABILITY_REQ 185 * 2) It does not provide T_CAPABILITY_REQ 186 * 3) It is not known yet whether transport provides T_CAPABILITY_REQ or not. 187 * 188 * It is assumed that the underlying transport either provides 189 * T_CAPABILITY_REQ or not and this does not changes during the 190 * system lifetime. 191 * 192 */ 193 #define PEEK_RDQ_EXPIND 0x0001 /* look for expinds on stream rd queues */ 194 #define WAITIOCACK 0x0002 /* waiting for info for ioctl act */ 195 #define CLTS 0x0004 /* connectionless transport */ 196 #define COTS 0x0008 /* connection-oriented transport */ 197 #define CONNWAIT 0x0010 /* waiting for connect confirmation */ 198 #define LOCORDREL 0x0020 /* local end has orderly released */ 199 #define REMORDREL 0x0040 /* remote end had orderly released */ 200 #define NAMEPROC 0x0080 /* processing a NAME ioctl */ 201 /* ONC_PLUS EXTRACT START */ 202 #define DO_MYNAME 0x0100 /* timod handles TI_GETMYNAME */ 203 /* ONC_PLUS EXTRACT END */ 204 #define DO_PEERNAME 0x0200 /* timod handles TI_GETPEERNAME */ 205 #define TI_CAP_RECVD 0x0400 /* TI_CAPABILITY received */ 206 #define CAP_WANTS_INFO 0x0800 /* TI_CAPABILITY has TC1_INFO set */ 207 #define WAIT_IOCINFOACK 0x1000 /* T_INFO_REQ generated from ioctl */ 208 #define WAIT_CONNRESACK 0x2000 /* waiting for T_OK_ACK to T_CONN_RES */ 209 210 211 /* Debugging facilities */ 212 /* 213 * Logging needed for debugging timod should only appear in DEBUG kernel. 214 */ 215 #ifdef DEBUG 216 #define TILOG(msg, arg) tilog((msg), (arg)) 217 #define TILOGP(msg, arg) tilogp((msg), (arg)) 218 #else 219 #define TILOG(msg, arg) 220 #define TILOGP(msg, arg) 221 #endif 222 223 224 /* 225 * Sleep timeout for T_CAPABILITY_REQ. This message never travels across 226 * network, so timeout value should be enough to cover all internal processing 227 * time. 228 */ 229 clock_t tim_tcap_wait = 2; 230 231 /* Sleep timeout in tim_recover() */ 232 #define TIMWAIT (1*hz) 233 /* Sleep timeout in tim_ioctl_retry() 0.2 seconds */ 234 #define TIMIOCWAIT (200*hz/1000) 235 236 /* 237 * Return values for ti_doname(). 238 */ 239 #define DONAME_FAIL 0 /* failing ioctl (done) */ 240 #define DONAME_DONE 1 /* done processing */ 241 #define DONAME_CONT 2 /* continue proceesing (not done yet) */ 242 243 /* 244 * Function prototypes 245 */ 246 static int ti_doname(queue_t *, mblk_t *); 247 static int ti_expind_on_rdqueues(queue_t *); 248 static void tim_ioctl_send_reply(queue_t *, mblk_t *, mblk_t *); 249 static void tim_send_ioc_error_ack(queue_t *, struct tim_tim *, mblk_t *); 250 static void tim_tcap_timer(void *); 251 static void tim_tcap_genreply(queue_t *, struct tim_tim *); 252 static void tim_send_reply(queue_t *, mblk_t *, struct tim_tim *, t_scalar_t); 253 static void tim_answer_ti_sync(queue_t *, mblk_t *, struct tim_tim *, 254 mblk_t *, uint32_t); 255 static void tim_send_ioctl_tpi_msg(queue_t *, mblk_t *, struct tim_tim *, 256 struct iocblk *); 257 static void tim_clear_peer(struct tim_tim *); 258 259 int 260 _init(void) 261 { 262 int error; 263 264 rw_init(&tim_list_rwlock, NULL, RW_DRIVER, NULL); 265 error = mod_install(&modlinkage); 266 if (error != 0) { 267 rw_destroy(&tim_list_rwlock); 268 return (error); 269 } 270 271 return (0); 272 } 273 274 int 275 _fini(void) 276 { 277 int error; 278 279 error = mod_remove(&modlinkage); 280 if (error != 0) 281 return (error); 282 rw_destroy(&tim_list_rwlock); 283 return (0); 284 } 285 286 int 287 _info(struct modinfo *modinfop) 288 { 289 return (mod_info(&modlinkage, modinfop)); 290 } 291 292 293 /* 294 * Hash list for all instances. Used to find tim_tim structure based on 295 * ACCEPTOR_id in T_CONN_RES. Protected by tim_list_rwlock. 296 */ 297 #define TIM_HASH_SIZE 256 298 #ifdef _ILP32 299 #define TIM_HASH(id) (((uintptr_t)(id) >> 8) % TIM_HASH_SIZE) 300 #else 301 #define TIM_HASH(id) ((uintptr_t)(id) % TIM_HASH_SIZE) 302 #endif /* _ILP32 */ 303 static struct tim_tim *tim_hash[TIM_HASH_SIZE]; 304 int tim_cnt = 0; 305 306 static void tilog(char *, t_scalar_t); 307 static void tilogp(char *, uintptr_t); 308 static mblk_t *tim_filladdr(queue_t *, mblk_t *, boolean_t); 309 static void tim_addlink(struct tim_tim *); 310 static void tim_dellink(struct tim_tim *); 311 static struct tim_tim *tim_findlink(t_uscalar_t); 312 static void tim_recover(queue_t *, mblk_t *, t_scalar_t); 313 static void tim_ioctl_retry(queue_t *); 314 315 int dotilog = 0; 316 317 #define TIMOD_ID 3 318 319 /* ONC_PLUS EXTRACT START */ 320 static int timodopen(queue_t *, dev_t *, int, int, cred_t *); 321 /* ONC_PLUS EXTRACT END */ 322 static int timodclose(queue_t *, int, cred_t *); 323 static void timodwput(queue_t *, mblk_t *); 324 static void timodrput(queue_t *, mblk_t *); 325 /* ONC_PLUS EXTRACT START */ 326 static void timodrsrv(queue_t *); 327 /* ONC_PLUS EXTRACT END */ 328 static void timodwsrv(queue_t *); 329 /* ONC_PLUS EXTRACT START */ 330 static int timodrproc(queue_t *, mblk_t *); 331 static int timodwproc(queue_t *, mblk_t *); 332 /* ONC_PLUS EXTRACT END */ 333 334 /* stream data structure definitions */ 335 336 static struct module_info timod_info = 337 {TIMOD_ID, "timod", 0, INFPSZ, 512, 128}; 338 static struct qinit timodrinit = { 339 (int (*)())timodrput, 340 (int (*)())timodrsrv, 341 timodopen, 342 timodclose, 343 nulldev, 344 &timod_info, 345 NULL 346 }; 347 static struct qinit timodwinit = { 348 (int (*)())timodwput, 349 (int (*)())timodwsrv, 350 timodopen, 351 timodclose, 352 nulldev, 353 &timod_info, 354 NULL 355 }; 356 static struct streamtab timinfo = { &timodrinit, &timodwinit, NULL, NULL }; 357 358 /* ONC_PLUS EXTRACT START */ 359 /* 360 * timodopen - open routine gets called when the module gets pushed 361 * onto the stream. 362 */ 363 /*ARGSUSED*/ 364 static int 365 timodopen( 366 queue_t *q, 367 dev_t *devp, 368 int flag, 369 int sflag, 370 cred_t *crp) 371 { 372 struct tim_tim *tp; 373 struct stroptions *sop; 374 mblk_t *bp; 375 376 ASSERT(q != NULL); 377 378 if (q->q_ptr) { 379 return (0); 380 } 381 382 if ((bp = allocb(sizeof (struct stroptions), BPRI_MED)) == 0) 383 return (ENOMEM); 384 385 tp = kmem_zalloc(sizeof (struct tim_tim), KM_SLEEP); 386 387 tp->tim_cpid = -1; 388 tp->tim_saved_prim = -1; 389 390 mutex_init(&tp->tim_mutex, NULL, MUTEX_DEFAULT, NULL); 391 392 q->q_ptr = (caddr_t)tp; 393 WR(q)->q_ptr = (caddr_t)tp; 394 395 tilogp("timodopen: Allocated for tp %lx\n", (uintptr_t)tp); 396 tilogp("timodopen: Allocated for q %lx\n", (uintptr_t)q); 397 398 /* Must be done before tpi_findprov and _ILP32 q_next walk below */ 399 qprocson(q); 400 401 tp->tim_provinfo = tpi_findprov(q); 402 403 /* 404 * Defer allocation of the buffers for the local address and 405 * the peer's address until we need them. 406 * Assume that timod has to handle getname until we here 407 * an iocack from the transport provider or we know that 408 * transport provider doesn't understand it. 409 */ 410 if (tp->tim_provinfo->tpi_myname != PI_YES) { 411 TILOG("timodopen: setting DO_MYNAME\n", 0); 412 tp->tim_flags |= DO_MYNAME; 413 } 414 415 if (tp->tim_provinfo->tpi_peername != PI_YES) { 416 TILOG("timodopen: setting DO_PEERNAME\n", 0); 417 tp->tim_flags |= DO_PEERNAME; 418 } 419 420 #ifdef _ILP32 421 { 422 queue_t *driverq; 423 424 /* 425 * Find my driver's read queue (for T_CONN_RES handling) 426 */ 427 driverq = WR(q); 428 while (SAMESTR(driverq)) 429 driverq = driverq->q_next; 430 431 tp->tim_acceptor = (t_uscalar_t)RD(driverq); 432 } 433 #else 434 tp->tim_acceptor = (t_uscalar_t)getminor(*devp); 435 #endif /* _ILP32 */ 436 437 /* 438 * Add this one to the list. 439 */ 440 tim_addlink(tp); 441 442 /* 443 * Send M_SETOPTS to stream head to make sure M_PCPROTO messages 444 * are not flushed. This prevents application deadlocks. 445 */ 446 bp->b_datap->db_type = M_SETOPTS; 447 bp->b_wptr += sizeof (struct stroptions); 448 sop = (struct stroptions *)bp->b_rptr; 449 sop->so_flags = SO_READOPT; 450 sop->so_readopt = RFLUSHPCPROT; 451 452 putnext(q, bp); 453 454 return (0); 455 } 456 457 static void 458 tim_timer(void *arg) 459 { 460 queue_t *q = arg; 461 struct tim_tim *tp = (struct tim_tim *)q->q_ptr; 462 463 ASSERT(tp); 464 465 if (q->q_flag & QREADR) { 466 ASSERT(tp->tim_rtimoutid); 467 tp->tim_rtimoutid = 0; 468 } else { 469 ASSERT(tp->tim_wtimoutid); 470 tp->tim_wtimoutid = 0; 471 } 472 enableok(q); 473 qenable(q); 474 } 475 476 static void 477 tim_buffer(void *arg) 478 { 479 queue_t *q = arg; 480 struct tim_tim *tp = (struct tim_tim *)q->q_ptr; 481 482 ASSERT(tp); 483 484 if (q->q_flag & QREADR) { 485 ASSERT(tp->tim_rbufcid); 486 tp->tim_rbufcid = 0; 487 } else { 488 ASSERT(tp->tim_wbufcid); 489 tp->tim_wbufcid = 0; 490 } 491 enableok(q); 492 qenable(q); 493 } 494 /* ONC_PLUS EXTRACT END */ 495 496 /* 497 * timodclose - This routine gets called when the module gets popped 498 * off of the stream. 499 */ 500 /*ARGSUSED*/ 501 static int 502 timodclose( 503 queue_t *q, 504 int flag, 505 cred_t *crp) 506 { 507 struct tim_tim *tp; 508 mblk_t *mp; 509 mblk_t *nmp; 510 511 ASSERT(q != NULL); 512 513 tp = (struct tim_tim *)q->q_ptr; 514 q->q_ptr = NULL; 515 516 ASSERT(tp != NULL); 517 518 tilogp("timodclose: Entered for tp %lx\n", (uintptr_t)tp); 519 tilogp("timodclose: Entered for q %lx\n", (uintptr_t)q); 520 521 qprocsoff(q); 522 tim_dellink(tp); 523 524 /* 525 * Cancel any outstanding bufcall 526 * or timeout requests. 527 */ 528 if (tp->tim_wbufcid) { 529 qunbufcall(q, tp->tim_wbufcid); 530 tp->tim_wbufcid = 0; 531 } 532 if (tp->tim_rbufcid) { 533 qunbufcall(q, tp->tim_rbufcid); 534 tp->tim_rbufcid = 0; 535 } 536 if (tp->tim_wtimoutid) { 537 (void) quntimeout(q, tp->tim_wtimoutid); 538 tp->tim_wtimoutid = 0; 539 } 540 if (tp->tim_rtimoutid) { 541 (void) quntimeout(q, tp->tim_rtimoutid); 542 tp->tim_rtimoutid = 0; 543 } 544 545 if (tp->tim_tcap_timoutid != 0) { 546 (void) quntimeout(q, tp->tim_tcap_timoutid); 547 tp->tim_tcap_timoutid = 0; 548 } 549 550 if (tp->tim_iocsave != NULL) 551 freemsg(tp->tim_iocsave); 552 mp = tp->tim_consave; 553 while (mp) { 554 nmp = mp->b_next; 555 mp->b_next = NULL; 556 freemsg(mp); 557 mp = nmp; 558 } 559 ASSERT(tp->tim_mymaxlen >= 0); 560 if (tp->tim_mymaxlen != 0) 561 kmem_free(tp->tim_myname, (size_t)tp->tim_mymaxlen); 562 ASSERT(tp->tim_peermaxlen >= 0); 563 if (tp->tim_peermaxlen != 0) 564 kmem_free(tp->tim_peername, (size_t)tp->tim_peermaxlen); 565 566 q->q_ptr = WR(q)->q_ptr = NULL; 567 568 mutex_destroy(&tp->tim_mutex); 569 570 if (tp->tim_peercred != NULL) 571 crfree(tp->tim_peercred); 572 573 kmem_free(tp, sizeof (struct tim_tim)); 574 575 return (0); 576 } 577 578 /* 579 * timodrput - Module read put procedure. This is called from 580 * the module, driver, or stream head upstream/downstream. 581 * Handles M_FLUSH, M_DATA and some M_PROTO (T_DATA_IND, 582 * and T_UNITDATA_IND) messages. All others are queued to 583 * be handled by the service procedures. 584 */ 585 static void 586 timodrput(queue_t *q, mblk_t *mp) 587 { 588 union T_primitives *pptr; 589 590 /* 591 * During flow control and other instances when messages 592 * are on queue, queue up a non high priority message 593 */ 594 if (q->q_first != 0 && mp->b_datap->db_type < QPCTL) { 595 (void) putq(q, mp); 596 return; 597 } 598 599 /* 600 * Inline processing of data (to avoid additional procedure call). 601 * Rest is handled in timodrproc. 602 */ 603 604 switch (mp->b_datap->db_type) { 605 case M_DATA: 606 if (bcanputnext(q, mp->b_band)) 607 putnext(q, mp); 608 else 609 (void) putq(q, mp); 610 break; 611 case M_PROTO: 612 case M_PCPROTO: 613 if (MBLKL(mp) < sizeof (t_scalar_t)) { 614 if (mp->b_datap->db_type == M_PCPROTO || 615 bcanputnext(q, mp->b_band)) { 616 putnext(q, mp); 617 } else { 618 (void) putq(q, mp); 619 } 620 break; 621 } 622 pptr = (union T_primitives *)mp->b_rptr; 623 switch (pptr->type) { 624 case T_EXDATA_IND: 625 case T_DATA_IND: 626 case T_UNITDATA_IND: 627 if (bcanputnext(q, mp->b_band)) 628 putnext(q, mp); 629 else 630 (void) putq(q, mp); 631 break; 632 default: 633 (void) timodrproc(q, mp); 634 break; 635 } 636 break; 637 default: 638 (void) timodrproc(q, mp); 639 break; 640 } 641 } 642 643 /* ONC_PLUS EXTRACT START */ 644 /* 645 * timodrsrv - Module read queue service procedure. This is called when 646 * messages are placed on an empty queue, when high priority 647 * messages are placed on the queue, and when flow control 648 * restrictions subside. This code used to be included in a 649 * put procedure, but it was moved to a service procedure 650 * because several points were added where memory allocation 651 * could fail, and there is no reasonable recovery mechanism 652 * from the put procedure. 653 */ 654 /*ARGSUSED*/ 655 static void 656 timodrsrv(queue_t *q) 657 { 658 /* ONC_PLUS EXTRACT END */ 659 mblk_t *mp; 660 struct tim_tim *tp; 661 662 ASSERT(q != NULL); 663 664 tp = (struct tim_tim *)q->q_ptr; 665 if (!tp) 666 return; 667 668 while ((mp = getq(q)) != NULL) { 669 if (timodrproc(q, mp)) { 670 /* 671 * timodrproc did a putbq - stop processing 672 * messages. 673 */ 674 return; 675 } 676 } 677 /* ONC_PLUS EXTRACT START */ 678 } 679 680 /* 681 * Perform common processing when a T_CAPABILITY_ACK or T_INFO_ACK 682 * arrive. Set the queue properties and adjust the tim_flags according 683 * to the service type. 684 */ 685 static void 686 timodprocessinfo(queue_t *q, struct tim_tim *tp, struct T_info_ack *tia) 687 { 688 TILOG("timodprocessinfo: strqset(%d)\n", tia->TIDU_size); 689 (void) strqset(q, QMAXPSZ, 0, tia->TIDU_size); 690 (void) strqset(OTHERQ(q), QMAXPSZ, 0, tia->TIDU_size); 691 692 if ((tia->SERV_type == T_COTS) || (tia->SERV_type == T_COTS_ORD)) 693 tp->tim_flags = (tp->tim_flags & ~CLTS) | COTS; 694 else if (tia->SERV_type == T_CLTS) 695 tp->tim_flags = (tp->tim_flags & ~COTS) | CLTS; 696 } 697 698 static int 699 timodrproc(queue_t *q, mblk_t *mp) 700 { 701 union T_primitives *pptr; 702 struct tim_tim *tp; 703 struct iocblk *iocbp; 704 mblk_t *nbp; 705 size_t blen; 706 /* ONC_PLUS EXTRACT END */ 707 708 tp = (struct tim_tim *)q->q_ptr; 709 710 /* ONC_PLUS EXTRACT START */ 711 switch (mp->b_datap->db_type) { 712 default: 713 putnext(q, mp); 714 break; 715 716 case M_ERROR: 717 TILOG("timodrproc: Got M_ERROR, flags = %x\n", tp->tim_flags); 718 /* 719 * There is no specified standard response for driver when it 720 * receives unknown message type and M_ERROR is one 721 * possibility. If we send T_CAPABILITY_REQ down and transport 722 * provider responds with M_ERROR we assume that it doesn't 723 * understand this message type. This assumption may be 724 * sometimes incorrect (transport may reply with M_ERROR for 725 * some other reason) but there is no way for us to distinguish 726 * between different cases. In the worst case timod and everyone 727 * else sharing global transport description with it may end up 728 * emulating T_CAPABILITY_REQ. 729 */ 730 731 /* 732 * Check that we are waiting for T_CAPABILITY_ACK and 733 * T_CAPABILITY_REQ is not implemented by transport or emulated 734 * by timod. 735 */ 736 if ((tp->tim_provinfo->tpi_capability == PI_DONTKNOW) && 737 ((tp->tim_flags & TI_CAP_RECVD) != 0)) { 738 /* 739 * Good chances that this transport doesn't provide 740 * T_CAPABILITY_REQ. Mark this information permanently 741 * for the module + transport combination. 742 */ 743 PI_PROVLOCK(tp->tim_provinfo); 744 if (tp->tim_provinfo->tpi_capability == PI_DONTKNOW) 745 tp->tim_provinfo->tpi_capability = PI_NO; 746 PI_PROVUNLOCK(tp->tim_provinfo); 747 if (tp->tim_tcap_timoutid != 0) { 748 (void) quntimeout(q, tp->tim_tcap_timoutid); 749 tp->tim_tcap_timoutid = 0; 750 } 751 } 752 putnext(q, mp); 753 break; 754 case M_DATA: 755 if (!bcanputnext(q, mp->b_band)) { 756 (void) putbq(q, mp); 757 return (1); 758 } 759 putnext(q, mp); 760 break; 761 762 case M_PROTO: 763 case M_PCPROTO: 764 blen = MBLKL(mp); 765 if (blen < sizeof (t_scalar_t)) { 766 /* 767 * Note: it's not actually possible to get 768 * here with db_type M_PCPROTO, because 769 * timodrput has already checked MBLKL, and 770 * thus the assertion below. If the length 771 * was too short, then the message would have 772 * already been putnext'd, and would thus 773 * never appear here. Just the same, the code 774 * below handles the impossible case since 775 * it's easy to do and saves future 776 * maintainers from unfortunate accidents. 777 */ 778 ASSERT(mp->b_datap->db_type == M_PROTO); 779 if (mp->b_datap->db_type == M_PROTO && 780 !bcanputnext(q, mp->b_band)) { 781 (void) putbq(q, mp); 782 return (1); 783 } 784 putnext(q, mp); 785 break; 786 } 787 788 pptr = (union T_primitives *)mp->b_rptr; 789 switch (pptr->type) { 790 default: 791 /* ONC_PLUS EXTRACT END */ 792 793 #ifdef C2_AUDIT 794 if (audit_active) 795 audit_sock(T_UNITDATA_IND, q, mp, TIMOD_ID); 796 #endif 797 /* ONC_PLUS EXTRACT START */ 798 putnext(q, mp); 799 break; 800 /* ONC_PLUS EXTRACT END */ 801 802 case T_ERROR_ACK: 803 /* Restore db_type - recover() might have changed it */ 804 mp->b_datap->db_type = M_PCPROTO; 805 if (blen < sizeof (struct T_error_ack)) { 806 putnext(q, mp); 807 break; 808 } 809 810 tilog("timodrproc: Got T_ERROR_ACK, flags = %x\n", 811 tp->tim_flags); 812 813 if ((tp->tim_flags & WAIT_CONNRESACK) && 814 tp->tim_saved_prim == pptr->error_ack.ERROR_prim) { 815 tp->tim_flags &= 816 ~(WAIT_CONNRESACK | WAITIOCACK); 817 freemsg(tp->tim_iocsave); 818 tp->tim_iocsave = NULL; 819 tp->tim_saved_prim = -1; 820 putnext(q, mp); 821 } else if (tp->tim_flags & WAITIOCACK) { 822 tim_send_ioc_error_ack(q, tp, mp); 823 } else { 824 putnext(q, mp); 825 } 826 break; 827 828 case T_OK_ACK: 829 if (blen < sizeof (pptr->ok_ack)) { 830 mp->b_datap->db_type = M_PCPROTO; 831 putnext(q, mp); 832 break; 833 } 834 835 tilog("timodrproc: Got T_OK_ACK\n", 0); 836 837 if (pptr->ok_ack.CORRECT_prim == T_UNBIND_REQ) 838 tp->tim_mylen = 0; 839 840 if ((tp->tim_flags & WAIT_CONNRESACK) && 841 tp->tim_saved_prim == pptr->ok_ack.CORRECT_prim) { 842 struct T_conn_res *resp; 843 struct T_conn_ind *indp; 844 struct tim_tim *ntp; 845 caddr_t ptr; 846 847 rw_enter(&tim_list_rwlock, RW_READER); 848 resp = (struct T_conn_res *) 849 tp->tim_iocsave->b_rptr; 850 ntp = tim_findlink(resp->ACCEPTOR_id); 851 if (ntp == NULL) 852 goto cresackout; 853 854 mutex_enter(&ntp->tim_mutex); 855 if (ntp->tim_peercred != NULL) 856 crfree(ntp->tim_peercred); 857 ntp->tim_peercred = 858 DB_CRED(tp->tim_iocsave->b_cont); 859 ntp->tim_cpid = 860 DB_CPID(tp->tim_iocsave->b_cont); 861 if (ntp->tim_peercred != NULL) 862 crhold(ntp->tim_peercred); 863 864 if (!(ntp->tim_flags & DO_PEERNAME)) { 865 mutex_exit(&ntp->tim_mutex); 866 goto cresackout; 867 } 868 869 indp = (struct T_conn_ind *) 870 tp->tim_iocsave->b_cont->b_rptr; 871 /* true as message is put on list */ 872 ASSERT(indp->SRC_length >= 0); 873 874 if (indp->SRC_length > ntp->tim_peermaxlen) { 875 ptr = kmem_alloc(indp->SRC_length, 876 KM_NOSLEEP); 877 if (ptr == NULL) { 878 mutex_exit(&ntp->tim_mutex); 879 rw_exit(&tim_list_rwlock); 880 tilog("timodwproc: kmem_alloc " 881 "failed, attempting " 882 "recovery\n", 0); 883 tim_recover(q, mp, 884 indp->SRC_length); 885 return (1); 886 } 887 if (ntp->tim_peermaxlen > 0) 888 kmem_free(ntp->tim_peername, 889 ntp->tim_peermaxlen); 890 ntp->tim_peername = ptr; 891 ntp->tim_peermaxlen = indp->SRC_length; 892 } 893 ntp->tim_peerlen = indp->SRC_length; 894 ptr = (caddr_t)indp + indp->SRC_offset; 895 bcopy(ptr, ntp->tim_peername, ntp->tim_peerlen); 896 897 mutex_exit(&ntp->tim_mutex); 898 899 cresackout: 900 rw_exit(&tim_list_rwlock); 901 tp->tim_flags &= 902 ~(WAIT_CONNRESACK | WAITIOCACK); 903 freemsg(tp->tim_iocsave); 904 tp->tim_iocsave = NULL; 905 tp->tim_saved_prim = -1; 906 } 907 908 tim_send_reply(q, mp, tp, pptr->ok_ack.CORRECT_prim); 909 break; 910 911 /* ONC_PLUS EXTRACT START */ 912 case T_BIND_ACK: { 913 struct T_bind_ack *ackp = 914 (struct T_bind_ack *)mp->b_rptr; 915 916 /* Restore db_type - recover() might have changed it */ 917 mp->b_datap->db_type = M_PCPROTO; 918 if (blen < sizeof (*ackp)) { 919 putnext(q, mp); 920 break; 921 } 922 923 /* save negotiated backlog */ 924 tp->tim_backlog = ackp->CONIND_number; 925 926 if (((tp->tim_flags & WAITIOCACK) == 0) || 927 ((tp->tim_saved_prim != O_T_BIND_REQ) && 928 (tp->tim_saved_prim != T_BIND_REQ))) { 929 putnext(q, mp); 930 break; 931 } 932 ASSERT(tp->tim_iocsave != NULL); 933 934 if (tp->tim_flags & DO_MYNAME) { 935 caddr_t p; 936 937 if (ackp->ADDR_length < 0 || 938 mp->b_rptr + ackp->ADDR_offset + 939 ackp->ADDR_length > mp->b_wptr) { 940 putnext(q, mp); 941 break; 942 } 943 if (ackp->ADDR_length > tp->tim_mymaxlen) { 944 p = kmem_alloc(ackp->ADDR_length, 945 KM_NOSLEEP); 946 if (p == NULL) { 947 tilog("timodrproc: kmem_alloc " 948 "failed attempt recovery", 949 0); 950 951 tim_recover(q, mp, 952 ackp->ADDR_length); 953 return (1); 954 } 955 ASSERT(tp->tim_mymaxlen >= 0); 956 if (tp->tim_mymaxlen != NULL) { 957 kmem_free(tp->tim_myname, 958 tp->tim_mymaxlen); 959 } 960 tp->tim_myname = p; 961 tp->tim_mymaxlen = ackp->ADDR_length; 962 } 963 tp->tim_mylen = ackp->ADDR_length; 964 bcopy(mp->b_rptr + ackp->ADDR_offset, 965 tp->tim_myname, tp->tim_mylen); 966 } 967 tim_ioctl_send_reply(q, tp->tim_iocsave, mp); 968 tp->tim_iocsave = NULL; 969 tp->tim_saved_prim = -1; 970 tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 971 TI_CAP_RECVD | CAP_WANTS_INFO); 972 break; 973 } 974 975 /* ONC_PLUS EXTRACT END */ 976 case T_OPTMGMT_ACK: 977 978 tilog("timodrproc: Got T_OPTMGMT_ACK\n", 0); 979 980 /* Restore db_type - recover() might have change it */ 981 mp->b_datap->db_type = M_PCPROTO; 982 983 if (((tp->tim_flags & WAITIOCACK) == 0) || 984 ((tp->tim_saved_prim != T_SVR4_OPTMGMT_REQ) && 985 (tp->tim_saved_prim != T_OPTMGMT_REQ))) { 986 putnext(q, mp); 987 } else { 988 ASSERT(tp->tim_iocsave != NULL); 989 tim_ioctl_send_reply(q, tp->tim_iocsave, mp); 990 tp->tim_iocsave = NULL; 991 tp->tim_saved_prim = -1; 992 tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 993 TI_CAP_RECVD | CAP_WANTS_INFO); 994 } 995 break; 996 997 case T_INFO_ACK: { 998 struct T_info_ack *tia = (struct T_info_ack *)pptr; 999 1000 /* Restore db_type - recover() might have changed it */ 1001 mp->b_datap->db_type = M_PCPROTO; 1002 1003 if (blen < sizeof (*tia)) { 1004 putnext(q, mp); 1005 break; 1006 } 1007 1008 tilog("timodrproc: Got T_INFO_ACK, flags = %x\n", 1009 tp->tim_flags); 1010 1011 timodprocessinfo(q, tp, tia); 1012 1013 TILOG("timodrproc: flags = %x\n", tp->tim_flags); 1014 if ((tp->tim_flags & WAITIOCACK) != 0) { 1015 size_t expected_ack_size; 1016 ssize_t deficit; 1017 int ioc_cmd; 1018 struct T_capability_ack *tcap; 1019 1020 /* 1021 * The only case when T_INFO_ACK may be received back 1022 * when we are waiting for ioctl to complete is when 1023 * this ioctl sent T_INFO_REQ down. 1024 */ 1025 if (!(tp->tim_flags & WAIT_IOCINFOACK)) { 1026 putnext(q, mp); 1027 break; 1028 } 1029 ASSERT(tp->tim_iocsave != NULL); 1030 1031 iocbp = (struct iocblk *)tp->tim_iocsave->b_rptr; 1032 ioc_cmd = iocbp->ioc_cmd; 1033 1034 /* 1035 * Was it sent from TI_CAPABILITY emulation? 1036 */ 1037 if (ioc_cmd == TI_CAPABILITY) { 1038 struct T_info_ack saved_info; 1039 1040 /* 1041 * Perform sanity checks. The only case when we 1042 * send T_INFO_REQ from TI_CAPABILITY is when 1043 * timod emulates T_CAPABILITY_REQ and CAP_bits1 1044 * has TC1_INFO set. 1045 */ 1046 if ((tp->tim_flags & 1047 (TI_CAP_RECVD | CAP_WANTS_INFO)) != 1048 (TI_CAP_RECVD | CAP_WANTS_INFO)) { 1049 putnext(q, mp); 1050 break; 1051 } 1052 1053 TILOG("timodrproc: emulating TI_CAPABILITY/" 1054 "info\n", 0); 1055 1056 /* Save info & reuse mp for T_CAPABILITY_ACK */ 1057 saved_info = *tia; 1058 1059 mp = tpi_ack_alloc(mp, 1060 sizeof (struct T_capability_ack), 1061 M_PCPROTO, T_CAPABILITY_ACK); 1062 1063 if (mp == NULL) { 1064 tilog("timodrproc: realloc failed, " 1065 "no recovery attempted\n", 0); 1066 return (1); 1067 } 1068 1069 /* 1070 * Copy T_INFO information into T_CAPABILITY_ACK 1071 */ 1072 tcap = (struct T_capability_ack *)mp->b_rptr; 1073 tcap->CAP_bits1 = TC1_INFO; 1074 tcap->INFO_ack = saved_info; 1075 tp->tim_flags &= ~(WAITIOCACK | 1076 WAIT_IOCINFOACK | TI_CAP_RECVD | 1077 CAP_WANTS_INFO); 1078 tim_ioctl_send_reply(q, tp->tim_iocsave, mp); 1079 tp->tim_iocsave = NULL; 1080 tp->tim_saved_prim = -1; 1081 break; 1082 } 1083 1084 /* 1085 * The code for TI_SYNC/TI_GETINFO is left here only for 1086 * backward compatibility with staticaly linked old 1087 * applications. New TLI/XTI code should use 1088 * TI_CAPABILITY for getting transport info and should 1089 * not use TI_GETINFO/TI_SYNC for this purpose. 1090 */ 1091 1092 /* 1093 * make sure the message sent back is the size of 1094 * the "expected ack" 1095 * For TI_GETINFO, expected ack size is 1096 * sizeof (T_info_ack) 1097 * For TI_SYNC, expected ack size is 1098 * sizeof (struct ti_sync_ack); 1099 */ 1100 if (ioc_cmd != TI_GETINFO && ioc_cmd != TI_SYNC) { 1101 putnext(q, mp); 1102 break; 1103 } 1104 1105 expected_ack_size = 1106 sizeof (struct T_info_ack); /* TI_GETINFO */ 1107 if (iocbp->ioc_cmd == TI_SYNC) { 1108 expected_ack_size = 2 * sizeof (uint32_t) + 1109 sizeof (struct ti_sync_ack); 1110 } 1111 deficit = expected_ack_size - blen; 1112 1113 if (deficit != 0) { 1114 if (mp->b_datap->db_lim - mp->b_wptr < 1115 deficit) { 1116 mblk_t *tmp = allocb(expected_ack_size, 1117 BPRI_HI); 1118 if (tmp == NULL) { 1119 ASSERT((mp->b_datap->db_lim - 1120 mp->b_datap->db_base) < 1121 sizeof (struct T_error_ack)); 1122 1123 tilog("timodrproc: allocb failed no " 1124 "recovery attempt\n", 0); 1125 1126 mp->b_rptr = mp->b_datap->db_base; 1127 pptr = (union T_primitives *) 1128 mp->b_rptr; 1129 pptr->error_ack.ERROR_prim = T_INFO_ACK; 1130 pptr->error_ack.TLI_error = TSYSERR; 1131 pptr->error_ack.UNIX_error = EAGAIN; 1132 pptr->error_ack.PRIM_type = T_ERROR_ACK; 1133 mp->b_datap->db_type = M_PCPROTO; 1134 tim_send_ioc_error_ack(q, tp, mp); 1135 break; 1136 } else { 1137 bcopy(mp->b_rptr, tmp->b_rptr, blen); 1138 tmp->b_wptr += blen; 1139 pptr = (union T_primitives *) 1140 tmp->b_rptr; 1141 freemsg(mp); 1142 mp = tmp; 1143 } 1144 } 1145 } 1146 /* 1147 * We now have "mp" which has enough space for an 1148 * appropriate ack and contains struct T_info_ack 1149 * that the transport provider returned. We now 1150 * stuff it with more stuff to fullfill 1151 * TI_SYNC ioctl needs, as necessary 1152 */ 1153 if (iocbp->ioc_cmd == TI_SYNC) { 1154 /* 1155 * Assumes struct T_info_ack is first embedded 1156 * type in struct ti_sync_ack so it is 1157 * automatically there. 1158 */ 1159 struct ti_sync_ack *tsap = 1160 (struct ti_sync_ack *)mp->b_rptr; 1161 1162 /* 1163 * tsap->tsa_qlen needs to be set only if 1164 * TSRF_QLEN_REQ flag is set, but for 1165 * compatibility with statically linked 1166 * applications it is set here regardless of the 1167 * flag since old XTI library expected it to be 1168 * set. 1169 */ 1170 tsap->tsa_qlen = tp->tim_backlog; 1171 tsap->tsa_flags = 0x0; /* intialize clear */ 1172 if (tp->tim_flags & PEEK_RDQ_EXPIND) { 1173 /* 1174 * Request to peek for EXPIND in 1175 * rcvbuf. 1176 */ 1177 if (ti_expind_on_rdqueues(q)) { 1178 /* 1179 * Expedited data is 1180 * queued on the stream 1181 * read side 1182 */ 1183 tsap->tsa_flags |= 1184 TSAF_EXP_QUEUED; 1185 } 1186 tp->tim_flags &= 1187 ~PEEK_RDQ_EXPIND; 1188 } 1189 mp->b_wptr += 2*sizeof (uint32_t); 1190 } 1191 tim_ioctl_send_reply(q, tp->tim_iocsave, mp); 1192 tp->tim_iocsave = NULL; 1193 tp->tim_saved_prim = -1; 1194 tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 1195 TI_CAP_RECVD | CAP_WANTS_INFO); 1196 break; 1197 } 1198 } 1199 1200 putnext(q, mp); 1201 break; 1202 1203 case T_ADDR_ACK: 1204 tilog("timodrproc: Got T_ADDR_ACK\n", 0); 1205 tim_send_reply(q, mp, tp, T_ADDR_REQ); 1206 break; 1207 1208 /* ONC_PLUS EXTRACT START */ 1209 case T_CONN_IND: { 1210 struct T_conn_ind *tcip = 1211 (struct T_conn_ind *)mp->b_rptr; 1212 1213 tilog("timodrproc: Got T_CONN_IND\n", 0); 1214 1215 if (blen >= sizeof (*tcip) && 1216 MBLKIN(mp, tcip->SRC_offset, tcip->SRC_length)) { 1217 if (((nbp = dupmsg(mp)) != NULL) || 1218 ((nbp = copymsg(mp)) != NULL)) { 1219 nbp->b_next = tp->tim_consave; 1220 tp->tim_consave = nbp; 1221 } else { 1222 tim_recover(q, mp, 1223 (t_scalar_t)sizeof (mblk_t)); 1224 return (1); 1225 } 1226 } 1227 /* ONC_PLUS EXTRACT END */ 1228 #ifdef C2_AUDIT 1229 if (audit_active) 1230 audit_sock(T_CONN_IND, q, mp, TIMOD_ID); 1231 #endif 1232 /* ONC_PLUS EXTRACT START */ 1233 putnext(q, mp); 1234 break; 1235 } 1236 1237 /* ONC_PLUS EXTRACT END */ 1238 case T_CONN_CON: 1239 mutex_enter(&tp->tim_mutex); 1240 if (tp->tim_peercred != NULL) 1241 crfree(tp->tim_peercred); 1242 tp->tim_peercred = DB_CRED(mp); 1243 if (tp->tim_peercred != NULL) 1244 crhold(tp->tim_peercred); 1245 tp->tim_cpid = DB_CPID(mp); 1246 mutex_exit(&tp->tim_mutex); 1247 1248 tilog("timodrproc: Got T_CONN_CON\n", 0); 1249 1250 tp->tim_flags &= ~CONNWAIT; 1251 putnext(q, mp); 1252 break; 1253 1254 case T_DISCON_IND: { 1255 struct T_discon_ind *disp; 1256 struct T_conn_ind *conp; 1257 mblk_t *pbp = NULL; 1258 1259 if (q->q_first != 0) 1260 tilog("timodrput: T_DISCON_IND - flow control\n", 0); 1261 1262 if (blen < sizeof (*disp)) { 1263 putnext(q, mp); 1264 break; 1265 } 1266 1267 disp = (struct T_discon_ind *)mp->b_rptr; 1268 1269 tilog("timodrproc: Got T_DISCON_IND Reason: %d\n", 1270 disp->DISCON_reason); 1271 1272 tp->tim_flags &= ~(CONNWAIT|LOCORDREL|REMORDREL); 1273 tim_clear_peer(tp); 1274 for (nbp = tp->tim_consave; nbp; nbp = nbp->b_next) { 1275 conp = (struct T_conn_ind *)nbp->b_rptr; 1276 if (conp->SEQ_number == disp->SEQ_number) 1277 break; 1278 pbp = nbp; 1279 } 1280 if (nbp) { 1281 if (pbp) 1282 pbp->b_next = nbp->b_next; 1283 else 1284 tp->tim_consave = nbp->b_next; 1285 nbp->b_next = NULL; 1286 freemsg(nbp); 1287 } 1288 putnext(q, mp); 1289 break; 1290 } 1291 1292 case T_ORDREL_IND: 1293 1294 tilog("timodrproc: Got T_ORDREL_IND\n", 0); 1295 1296 if (tp->tim_flags & LOCORDREL) { 1297 tp->tim_flags &= ~(LOCORDREL|REMORDREL); 1298 tim_clear_peer(tp); 1299 } else { 1300 tp->tim_flags |= REMORDREL; 1301 } 1302 putnext(q, mp); 1303 break; 1304 1305 case T_EXDATA_IND: 1306 case T_DATA_IND: 1307 case T_UNITDATA_IND: 1308 if (pptr->type == T_EXDATA_IND) 1309 tilog("timodrproc: Got T_EXDATA_IND\n", 0); 1310 1311 if (!bcanputnext(q, mp->b_band)) { 1312 (void) putbq(q, mp); 1313 return (1); 1314 } 1315 putnext(q, mp); 1316 break; 1317 1318 case T_CAPABILITY_ACK: { 1319 struct T_capability_ack *tca; 1320 1321 if (blen < sizeof (*tca)) { 1322 putnext(q, mp); 1323 break; 1324 } 1325 1326 /* This transport supports T_CAPABILITY_REQ */ 1327 tilog("timodrproc: Got T_CAPABILITY_ACK\n", 0); 1328 1329 PI_PROVLOCK(tp->tim_provinfo); 1330 if (tp->tim_provinfo->tpi_capability != PI_YES) 1331 tp->tim_provinfo->tpi_capability = PI_YES; 1332 PI_PROVUNLOCK(tp->tim_provinfo); 1333 1334 /* Reset possible pending timeout */ 1335 if (tp->tim_tcap_timoutid != 0) { 1336 (void) quntimeout(q, tp->tim_tcap_timoutid); 1337 tp->tim_tcap_timoutid = 0; 1338 } 1339 1340 tca = (struct T_capability_ack *)mp->b_rptr; 1341 1342 if (tca->CAP_bits1 & TC1_INFO) 1343 timodprocessinfo(q, tp, &tca->INFO_ack); 1344 1345 tim_send_reply(q, mp, tp, T_CAPABILITY_REQ); 1346 } 1347 break; 1348 } 1349 break; 1350 1351 /* ONC_PLUS EXTRACT START */ 1352 case M_FLUSH: 1353 1354 tilog("timodrproc: Got M_FLUSH\n", 0); 1355 1356 if (*mp->b_rptr & FLUSHR) { 1357 if (*mp->b_rptr & FLUSHBAND) 1358 flushband(q, *(mp->b_rptr + 1), FLUSHDATA); 1359 else 1360 flushq(q, FLUSHDATA); 1361 } 1362 putnext(q, mp); 1363 break; 1364 /* ONC_PLUS EXTRACT END */ 1365 1366 case M_IOCACK: 1367 iocbp = (struct iocblk *)mp->b_rptr; 1368 1369 tilog("timodrproc: Got M_IOCACK\n", 0); 1370 1371 if (iocbp->ioc_cmd == TI_GETMYNAME) { 1372 1373 /* 1374 * Transport provider supports this ioctl, 1375 * so I don't have to. 1376 */ 1377 if ((tp->tim_flags & DO_MYNAME) != 0) { 1378 tp->tim_flags &= ~DO_MYNAME; 1379 PI_PROVLOCK(tp->tim_provinfo); 1380 tp->tim_provinfo->tpi_myname = PI_YES; 1381 PI_PROVUNLOCK(tp->tim_provinfo); 1382 } 1383 1384 ASSERT(tp->tim_mymaxlen >= 0); 1385 if (tp->tim_mymaxlen != 0) { 1386 kmem_free(tp->tim_myname, (size_t)tp->tim_mymaxlen); 1387 tp->tim_myname = NULL; 1388 tp->tim_mymaxlen = 0; 1389 } 1390 /* tim_iocsave may already be overwritten. */ 1391 if (tp->tim_saved_prim == -1) { 1392 freemsg(tp->tim_iocsave); 1393 tp->tim_iocsave = NULL; 1394 } 1395 } else if (iocbp->ioc_cmd == TI_GETPEERNAME) { 1396 boolean_t clearit; 1397 1398 /* 1399 * Transport provider supports this ioctl, 1400 * so I don't have to. 1401 */ 1402 if ((tp->tim_flags & DO_PEERNAME) != 0) { 1403 tp->tim_flags &= ~DO_PEERNAME; 1404 PI_PROVLOCK(tp->tim_provinfo); 1405 tp->tim_provinfo->tpi_peername = PI_YES; 1406 PI_PROVUNLOCK(tp->tim_provinfo); 1407 } 1408 1409 mutex_enter(&tp->tim_mutex); 1410 ASSERT(tp->tim_peermaxlen >= 0); 1411 clearit = tp->tim_peermaxlen != 0; 1412 if (clearit) { 1413 kmem_free(tp->tim_peername, tp->tim_peermaxlen); 1414 tp->tim_peername = NULL; 1415 tp->tim_peermaxlen = 0; 1416 tp->tim_peerlen = 0; 1417 } 1418 mutex_exit(&tp->tim_mutex); 1419 if (clearit) { 1420 mblk_t *bp; 1421 1422 bp = tp->tim_consave; 1423 while (bp != NULL) { 1424 nbp = bp->b_next; 1425 bp->b_next = NULL; 1426 freemsg(bp); 1427 bp = nbp; 1428 } 1429 tp->tim_consave = NULL; 1430 } 1431 /* tim_iocsave may already be overwritten. */ 1432 if (tp->tim_saved_prim == -1) { 1433 freemsg(tp->tim_iocsave); 1434 tp->tim_iocsave = NULL; 1435 } 1436 } 1437 putnext(q, mp); 1438 break; 1439 1440 /* ONC_PLUS EXTRACT START */ 1441 case M_IOCNAK: 1442 1443 tilog("timodrproc: Got M_IOCNAK\n", 0); 1444 1445 iocbp = (struct iocblk *)mp->b_rptr; 1446 if (((iocbp->ioc_cmd == TI_GETMYNAME) || 1447 (iocbp->ioc_cmd == TI_GETPEERNAME)) && 1448 ((iocbp->ioc_error == EINVAL) || (iocbp->ioc_error == 0))) { 1449 PI_PROVLOCK(tp->tim_provinfo); 1450 if (iocbp->ioc_cmd == TI_GETMYNAME) { 1451 if (tp->tim_provinfo->tpi_myname == PI_DONTKNOW) 1452 tp->tim_provinfo->tpi_myname = PI_NO; 1453 } else if (iocbp->ioc_cmd == TI_GETPEERNAME) { 1454 if (tp->tim_provinfo->tpi_peername == PI_DONTKNOW) 1455 tp->tim_provinfo->tpi_peername = PI_NO; 1456 } 1457 PI_PROVUNLOCK(tp->tim_provinfo); 1458 /* tim_iocsave may already be overwritten. */ 1459 if ((tp->tim_iocsave != NULL) && 1460 (tp->tim_saved_prim == -1)) { 1461 freemsg(mp); 1462 mp = tp->tim_iocsave; 1463 tp->tim_iocsave = NULL; 1464 tp->tim_flags |= NAMEPROC; 1465 if (ti_doname(WR(q), mp) != DONAME_CONT) { 1466 tp->tim_flags &= ~NAMEPROC; 1467 } 1468 break; 1469 } 1470 } 1471 putnext(q, mp); 1472 break; 1473 /* ONC_PLUS EXTRACT END */ 1474 } 1475 1476 return (0); 1477 } 1478 1479 /* ONC_PLUS EXTRACT START */ 1480 /* 1481 * timodwput - Module write put procedure. This is called from 1482 * the module, driver, or stream head upstream/downstream. 1483 * Handles M_FLUSH, M_DATA and some M_PROTO (T_DATA_REQ, 1484 * and T_UNITDATA_REQ) messages. All others are queued to 1485 * be handled by the service procedures. 1486 */ 1487 1488 static void 1489 timodwput(queue_t *q, mblk_t *mp) 1490 { 1491 union T_primitives *pptr; 1492 struct tim_tim *tp; 1493 struct iocblk *iocbp; 1494 1495 /* 1496 * Enqueue normal-priority messages if our queue already 1497 * holds some messages for deferred processing but don't 1498 * enqueue those M_IOCTLs which will result in an 1499 * M_PCPROTO (ie, high priority) message being created. 1500 */ 1501 /* ONC_PLUS EXTRACT END */ 1502 if (q->q_first != 0 && mp->b_datap->db_type < QPCTL) { 1503 if (mp->b_datap->db_type == M_IOCTL) { 1504 iocbp = (struct iocblk *)mp->b_rptr; 1505 switch (iocbp->ioc_cmd) { 1506 default: 1507 (void) putq(q, mp); 1508 return; 1509 1510 case TI_GETINFO: 1511 case TI_SYNC: 1512 case TI_CAPABILITY: 1513 break; 1514 } 1515 } else { 1516 (void) putq(q, mp); 1517 return; 1518 } 1519 } 1520 /* ONC_PLUS EXTRACT START */ 1521 /* 1522 * Inline processing of data (to avoid additional procedure call). 1523 * Rest is handled in timodwproc. 1524 */ 1525 1526 switch (mp->b_datap->db_type) { 1527 case M_DATA: 1528 tp = (struct tim_tim *)q->q_ptr; 1529 ASSERT(tp); 1530 if (tp->tim_flags & CLTS) { 1531 mblk_t *tmp; 1532 1533 if ((tmp = tim_filladdr(q, mp, B_FALSE)) == NULL) { 1534 (void) putq(q, mp); 1535 break; 1536 } else { 1537 mp = tmp; 1538 } 1539 } 1540 if (bcanputnext(q, mp->b_band)) 1541 putnext(q, mp); 1542 else 1543 (void) putq(q, mp); 1544 break; 1545 case M_PROTO: 1546 case M_PCPROTO: 1547 pptr = (union T_primitives *)mp->b_rptr; 1548 switch (pptr->type) { 1549 /* ONC_PLUS EXTRACT END */ 1550 case T_UNITDATA_REQ: 1551 tp = (struct tim_tim *)q->q_ptr; 1552 ASSERT(tp); 1553 if (tp->tim_flags & CLTS) { 1554 mblk_t *tmp; 1555 1556 tmp = tim_filladdr(q, mp, B_FALSE); 1557 if (tmp == NULL) { 1558 (void) putq(q, mp); 1559 break; 1560 } else { 1561 mp = tmp; 1562 } 1563 } 1564 if (bcanputnext(q, mp->b_band)) 1565 putnext(q, mp); 1566 else 1567 (void) putq(q, mp); 1568 break; 1569 1570 case T_DATA_REQ: 1571 case T_EXDATA_REQ: 1572 if (bcanputnext(q, mp->b_band)) 1573 putnext(q, mp); 1574 else 1575 (void) putq(q, mp); 1576 break; 1577 default: 1578 (void) timodwproc(q, mp); 1579 break; 1580 } 1581 break; 1582 /* ONC_PLUS EXTRACT START */ 1583 default: 1584 (void) timodwproc(q, mp); 1585 break; 1586 } 1587 } 1588 /* 1589 * timodwsrv - Module write queue service procedure. 1590 * This is called when messages are placed on an empty queue, 1591 * when high priority messages are placed on the queue, and 1592 * when flow control restrictions subside. This code used to 1593 * be included in a put procedure, but it was moved to a 1594 * service procedure because several points were added where 1595 * memory allocation could fail, and there is no reasonable 1596 * recovery mechanism from the put procedure. 1597 */ 1598 static void 1599 timodwsrv(queue_t *q) 1600 { 1601 mblk_t *mp; 1602 1603 ASSERT(q != NULL); 1604 if (q->q_ptr == NULL) 1605 return; 1606 1607 while ((mp = getq(q)) != NULL) { 1608 if (timodwproc(q, mp)) { 1609 /* 1610 * timodwproc did a putbq - stop processing 1611 * messages. 1612 */ 1613 return; 1614 } 1615 } 1616 } 1617 1618 /* 1619 * Common routine to process write side messages 1620 */ 1621 1622 static int 1623 timodwproc(queue_t *q, mblk_t *mp) 1624 { 1625 union T_primitives *pptr; 1626 struct tim_tim *tp; 1627 mblk_t *tmp; 1628 struct iocblk *iocbp; 1629 int error; 1630 1631 tp = (struct tim_tim *)q->q_ptr; 1632 1633 switch (mp->b_datap->db_type) { 1634 default: 1635 putnext(q, mp); 1636 break; 1637 /* ONC_PLUS EXTRACT END */ 1638 1639 case M_DATA: 1640 if (tp->tim_flags & CLTS) { 1641 if ((tmp = tim_filladdr(q, mp, B_TRUE)) == NULL) { 1642 return (1); 1643 } else { 1644 mp = tmp; 1645 } 1646 } 1647 if (!bcanputnext(q, mp->b_band)) { 1648 (void) putbq(q, mp); 1649 return (1); 1650 } 1651 putnext(q, mp); 1652 break; 1653 1654 /* ONC_PLUS EXTRACT START */ 1655 case M_IOCTL: 1656 1657 iocbp = (struct iocblk *)mp->b_rptr; 1658 TILOG("timodwproc: Got M_IOCTL(%d)\n", iocbp->ioc_cmd); 1659 1660 ASSERT(MBLKL(mp) == sizeof (struct iocblk)); 1661 1662 /* 1663 * TPI requires we await response to a previously sent message 1664 * before handling another, put it back on the head of queue. 1665 * Since putbq() may see QWANTR unset when called from the 1666 * service procedure, the queue must be explicitly scheduled 1667 * for service, as no backenable will occur for this case. 1668 * tim_ioctl_retry() sets a timer to handle the qenable. 1669 */ 1670 if (tp->tim_flags & WAITIOCACK) { 1671 TILOG("timodwproc: putbq M_IOCTL(%d)\n", 1672 iocbp->ioc_cmd); 1673 (void) putbq(q, mp); 1674 /* Called from timodwsrv() and messages on queue */ 1675 if (!(q->q_flag & QWANTR)) 1676 tim_ioctl_retry(q); 1677 return (1); 1678 } 1679 /* ONC_PLUS EXTRACT END */ 1680 1681 switch (iocbp->ioc_cmd) { 1682 default: 1683 putnext(q, mp); 1684 break; 1685 1686 case _I_GETPEERCRED: 1687 if ((tp->tim_flags & COTS) == 0) { 1688 miocnak(q, mp, 0, ENOTSUP); 1689 } else { 1690 mblk_t *cmp = mp->b_cont; 1691 k_peercred_t *kp = NULL; 1692 1693 mutex_enter(&tp->tim_mutex); 1694 if (cmp != NULL && 1695 iocbp->ioc_flag == IOC_NATIVE && 1696 (tp->tim_flags & 1697 (CONNWAIT|LOCORDREL|REMORDREL)) == 0 && 1698 tp->tim_peercred != NULL && 1699 DB_TYPE(cmp) == M_DATA && 1700 MBLKL(cmp) == sizeof (k_peercred_t)) { 1701 kp = (k_peercred_t *)cmp->b_rptr; 1702 crhold(kp->pc_cr = tp->tim_peercred); 1703 kp->pc_cpid = tp->tim_cpid; 1704 } 1705 mutex_exit(&tp->tim_mutex); 1706 if (kp != NULL) 1707 miocack(q, mp, sizeof (*kp), 0); 1708 else 1709 miocnak(q, mp, 0, ENOTCONN); 1710 } 1711 break; 1712 case TI_BIND: 1713 case TI_UNBIND: 1714 case TI_OPTMGMT: 1715 case TI_GETADDRS: 1716 TILOG("timodwproc: TI_{BIND|UNBIND|OPTMGMT|GETADDRS}" 1717 "\n", 0); 1718 1719 /* 1720 * We know that tim_send_ioctl_tpi_msg() is only 1721 * going to examine the `type' field, so we only 1722 * check that we can access that much data. 1723 */ 1724 error = miocpullup(mp, sizeof (t_scalar_t)); 1725 if (error != 0) { 1726 miocnak(q, mp, 0, error); 1727 break; 1728 } 1729 tim_send_ioctl_tpi_msg(q, mp, tp, iocbp); 1730 break; 1731 1732 case TI_GETINFO: 1733 TILOG("timodwproc: TI_GETINFO\n", 0); 1734 error = miocpullup(mp, sizeof (struct T_info_req)); 1735 if (error != 0) { 1736 miocnak(q, mp, 0, error); 1737 break; 1738 } 1739 tp->tim_flags |= WAIT_IOCINFOACK; 1740 tim_send_ioctl_tpi_msg(q, mp, tp, iocbp); 1741 break; 1742 1743 case TI_SYNC: { 1744 mblk_t *tsr_mp; 1745 struct ti_sync_req *tsr; 1746 uint32_t tsr_flags; 1747 1748 error = miocpullup(mp, sizeof (struct ti_sync_req)); 1749 if (error != 0) { 1750 miocnak(q, mp, 0, error); 1751 break; 1752 } 1753 1754 tsr_mp = mp->b_cont; 1755 tsr = (struct ti_sync_req *)tsr_mp->b_rptr; 1756 TILOG("timodwproc: TI_SYNC(%x)\n", tsr->tsr_flags); 1757 1758 /* 1759 * Save out the value of tsr_flags, in case we 1760 * reallocb() tsr_mp (below). 1761 */ 1762 tsr_flags = tsr->tsr_flags; 1763 if ((tsr_flags & TSRF_INFO_REQ) == 0) { 1764 mblk_t *ack_mp = reallocb(tsr_mp, 1765 sizeof (struct ti_sync_ack), 0); 1766 1767 /* Can reply immediately. */ 1768 mp->b_cont = NULL; 1769 if (ack_mp == NULL) { 1770 tilog("timodwproc: allocb failed no " 1771 "recovery attempt\n", 0); 1772 freemsg(tsr_mp); 1773 miocnak(q, mp, 0, ENOMEM); 1774 } else { 1775 tim_answer_ti_sync(q, mp, tp, 1776 ack_mp, tsr_flags); 1777 } 1778 break; 1779 } 1780 1781 /* 1782 * This code is retained for compatibility with 1783 * old statically linked applications. New code 1784 * should use TI_CAPABILITY for all TPI 1785 * information and should not use TSRF_INFO_REQ 1786 * flag. 1787 * 1788 * defer processsing necessary to rput procedure 1789 * as we need to get information from transport 1790 * driver. Set flags that will tell the read 1791 * side the work needed on this request. 1792 */ 1793 1794 if (tsr_flags & TSRF_IS_EXP_IN_RCVBUF) 1795 tp->tim_flags |= PEEK_RDQ_EXPIND; 1796 1797 /* 1798 * Convert message to a T_INFO_REQ message; relies 1799 * on sizeof (struct ti_sync_req) >= sizeof (struct 1800 * T_info_req)). 1801 */ 1802 ASSERT(MBLKL(tsr_mp) >= sizeof (struct T_info_req)); 1803 1804 ((struct T_info_req *)tsr_mp->b_rptr)->PRIM_type = 1805 T_INFO_REQ; 1806 tsr_mp->b_wptr = tsr_mp->b_rptr + 1807 sizeof (struct T_info_req); 1808 tp->tim_flags |= WAIT_IOCINFOACK; 1809 tim_send_ioctl_tpi_msg(q, mp, tp, iocbp); 1810 } 1811 break; 1812 1813 case TI_CAPABILITY: { 1814 mblk_t *tcsr_mp; 1815 struct T_capability_req *tcr; 1816 1817 error = miocpullup(mp, sizeof (*tcr)); 1818 if (error != 0) { 1819 miocnak(q, mp, 0, error); 1820 break; 1821 } 1822 1823 tcsr_mp = mp->b_cont; 1824 tcr = (struct T_capability_req *)tcsr_mp->b_rptr; 1825 TILOG("timodwproc: TI_CAPABILITY(CAP_bits1 = %x)\n", 1826 tcr->CAP_bits1); 1827 1828 if (tcr->PRIM_type != T_CAPABILITY_REQ) { 1829 TILOG("timodwproc: invalid msg type %d\n", 1830 tcr->PRIM_type); 1831 miocnak(q, mp, 0, EPROTO); 1832 break; 1833 } 1834 1835 switch (tp->tim_provinfo->tpi_capability) { 1836 case PI_YES: 1837 /* Just send T_CAPABILITY_REQ down */ 1838 tim_send_ioctl_tpi_msg(q, mp, tp, iocbp); 1839 break; 1840 1841 case PI_DONTKNOW: 1842 /* 1843 * It is unknown yet whether transport provides 1844 * T_CAPABILITY_REQ or not. Send message down 1845 * and wait for reply. 1846 */ 1847 1848 ASSERT(tp->tim_tcap_timoutid == 0); 1849 if ((tcr->CAP_bits1 & TC1_INFO) == 0) { 1850 tp->tim_flags |= TI_CAP_RECVD; 1851 } else { 1852 tp->tim_flags |= (TI_CAP_RECVD | 1853 CAP_WANTS_INFO); 1854 } 1855 1856 tp->tim_tcap_timoutid = qtimeout(q, 1857 tim_tcap_timer, q, tim_tcap_wait * hz); 1858 tim_send_ioctl_tpi_msg(q, mp, tp, iocbp); 1859 break; 1860 1861 case PI_NO: 1862 /* 1863 * Transport doesn't support T_CAPABILITY_REQ. 1864 * Either reply immediately or send T_INFO_REQ 1865 * if needed. 1866 */ 1867 if ((tcr->CAP_bits1 & TC1_INFO) != 0) { 1868 tp->tim_flags |= (TI_CAP_RECVD | 1869 CAP_WANTS_INFO | WAIT_IOCINFOACK); 1870 TILOG("timodwproc: sending down " 1871 "T_INFO_REQ, flags = %x\n", 1872 tp->tim_flags); 1873 1874 /* 1875 * Generate T_INFO_REQ message and send 1876 * it down 1877 */ 1878 ((struct T_info_req *)tcsr_mp->b_rptr)-> 1879 PRIM_type = T_INFO_REQ; 1880 tcsr_mp->b_wptr = tcsr_mp->b_rptr + 1881 sizeof (struct T_info_req); 1882 tim_send_ioctl_tpi_msg(q, mp, tp, 1883 iocbp); 1884 break; 1885 } 1886 1887 1888 /* 1889 * Can reply immediately. Just send back 1890 * T_CAPABILITY_ACK with CAP_bits1 set to 0. 1891 */ 1892 mp->b_cont = tcsr_mp = tpi_ack_alloc(mp->b_cont, 1893 sizeof (struct T_capability_ack), M_PCPROTO, 1894 T_CAPABILITY_ACK); 1895 1896 if (tcsr_mp == NULL) { 1897 tilog("timodwproc: allocb failed no " 1898 "recovery attempt\n", 0); 1899 miocnak(q, mp, 0, ENOMEM); 1900 break; 1901 } 1902 1903 tp->tim_flags &= ~(WAITIOCACK | TI_CAP_RECVD | 1904 WAIT_IOCINFOACK | CAP_WANTS_INFO); 1905 ((struct T_capability_ack *) 1906 tcsr_mp->b_rptr)->CAP_bits1 = 0; 1907 tim_ioctl_send_reply(q, mp, tcsr_mp); 1908 1909 /* 1910 * It could happen when timod is awaiting ack 1911 * for TI_GETPEERNAME/TI_GETMYNAME. 1912 */ 1913 if (tp->tim_iocsave != NULL) { 1914 freemsg(tp->tim_iocsave); 1915 tp->tim_iocsave = NULL; 1916 tp->tim_saved_prim = -1; 1917 } 1918 break; 1919 1920 default: 1921 cmn_err(CE_PANIC, 1922 "timodwproc: unknown tpi_capability value " 1923 "%d\n", tp->tim_provinfo->tpi_capability); 1924 break; 1925 } 1926 } 1927 break; 1928 1929 /* ONC_PLUS EXTRACT START */ 1930 case TI_GETMYNAME: 1931 1932 tilog("timodwproc: Got TI_GETMYNAME\n", 0); 1933 1934 if (tp->tim_provinfo->tpi_myname == PI_YES) { 1935 putnext(q, mp); 1936 break; 1937 } 1938 goto getname; 1939 1940 case TI_GETPEERNAME: 1941 1942 tilog("timodwproc: Got TI_GETPEERNAME\n", 0); 1943 1944 if (tp->tim_provinfo->tpi_peername == PI_YES) { 1945 putnext(q, mp); 1946 break; 1947 } 1948 getname: 1949 if ((tmp = copymsg(mp)) == NULL) { 1950 tim_recover(q, mp, msgsize(mp)); 1951 return (1); 1952 } 1953 /* 1954 * tim_iocsave may be non-NULL when timod is awaiting 1955 * ack for another TI_GETPEERNAME/TI_GETMYNAME. 1956 */ 1957 freemsg(tp->tim_iocsave); 1958 tp->tim_iocsave = mp; 1959 tp->tim_saved_prim = -1; 1960 putnext(q, tmp); 1961 break; 1962 } 1963 break; 1964 1965 case M_IOCDATA: 1966 1967 if (tp->tim_flags & NAMEPROC) { 1968 if (ti_doname(q, mp) != DONAME_CONT) { 1969 tp->tim_flags &= ~NAMEPROC; 1970 } 1971 } else 1972 putnext(q, mp); 1973 break; 1974 1975 case M_PROTO: 1976 case M_PCPROTO: 1977 if (MBLKL(mp) < sizeof (t_scalar_t)) { 1978 merror(q, mp, EPROTO); 1979 return (1); 1980 } 1981 1982 pptr = (union T_primitives *)mp->b_rptr; 1983 switch (pptr->type) { 1984 default: 1985 putnext(q, mp); 1986 break; 1987 1988 case T_EXDATA_REQ: 1989 case T_DATA_REQ: 1990 if (pptr->type == T_EXDATA_REQ) 1991 tilog("timodwproc: Got T_EXDATA_REQ\n", 0); 1992 1993 if (!bcanputnext(q, mp->b_band)) { 1994 (void) putbq(q, mp); 1995 return (1); 1996 } 1997 putnext(q, mp); 1998 break; 1999 /* ONC_PLUS EXTRACT END */ 2000 2001 case T_UNITDATA_REQ: 2002 if (tp->tim_flags & CLTS) { 2003 tmp = tim_filladdr(q, mp, B_TRUE); 2004 if (tmp == NULL) { 2005 return (1); 2006 } else { 2007 mp = tmp; 2008 } 2009 } 2010 #ifdef C2_AUDIT 2011 if (audit_active) 2012 audit_sock(T_UNITDATA_REQ, q, mp, TIMOD_ID); 2013 #endif 2014 if (!bcanputnext(q, mp->b_band)) { 2015 (void) putbq(q, mp); 2016 return (1); 2017 } 2018 putnext(q, mp); 2019 break; 2020 2021 /* ONC_PLUS EXTRACT START */ 2022 case T_CONN_REQ: { 2023 struct T_conn_req *reqp = (struct T_conn_req *) 2024 mp->b_rptr; 2025 void *p; 2026 2027 tilog("timodwproc: Got T_CONN_REQ\n", 0); 2028 2029 if (MBLKL(mp) < sizeof (struct T_conn_req)) { 2030 merror(q, mp, EPROTO); 2031 return (1); 2032 } 2033 2034 if (tp->tim_flags & DO_PEERNAME) { 2035 if (!MBLKIN(mp, reqp->DEST_offset, 2036 reqp->DEST_length)) { 2037 merror(q, mp, EPROTO); 2038 return (1); 2039 } 2040 ASSERT(reqp->DEST_length >= 0); 2041 mutex_enter(&tp->tim_mutex); 2042 if (reqp->DEST_length > tp->tim_peermaxlen) { 2043 p = kmem_alloc(reqp->DEST_length, 2044 KM_NOSLEEP); 2045 if (p == NULL) { 2046 mutex_exit(&tp->tim_mutex); 2047 tilog("timodwproc: kmem_alloc " 2048 "failed, attempting " 2049 "recovery\n", 0); 2050 tim_recover(q, mp, 2051 reqp->DEST_length); 2052 return (1); 2053 } 2054 if (tp->tim_peermaxlen) 2055 kmem_free(tp->tim_peername, 2056 tp->tim_peermaxlen); 2057 tp->tim_peername = p; 2058 tp->tim_peermaxlen = reqp->DEST_length; 2059 } 2060 tp->tim_peerlen = reqp->DEST_length; 2061 p = mp->b_rptr + reqp->DEST_offset; 2062 bcopy(p, tp->tim_peername, tp->tim_peerlen); 2063 mutex_exit(&tp->tim_mutex); 2064 } 2065 if (tp->tim_flags & COTS) 2066 tp->tim_flags |= CONNWAIT; 2067 /* ONC_PLUS EXTRACT END */ 2068 #ifdef C2_AUDIT 2069 if (audit_active) 2070 audit_sock(T_CONN_REQ, q, mp, TIMOD_ID); 2071 #endif 2072 /* ONC_PLUS EXTRACT START */ 2073 putnext(q, mp); 2074 break; 2075 } 2076 2077 case O_T_CONN_RES: 2078 case T_CONN_RES: { 2079 struct T_conn_res *resp; 2080 struct T_conn_ind *indp; 2081 mblk_t *pmp = NULL; 2082 mblk_t *nbp; 2083 2084 if (MBLKL(mp) < sizeof (struct T_conn_res) || 2085 (tp->tim_flags & WAITIOCACK)) { 2086 merror(q, mp, EPROTO); 2087 return (1); 2088 } 2089 2090 resp = (struct T_conn_res *)mp->b_rptr; 2091 for (tmp = tp->tim_consave; tmp != NULL; 2092 tmp = tmp->b_next) { 2093 indp = (struct T_conn_ind *)tmp->b_rptr; 2094 if (indp->SEQ_number == resp->SEQ_number) 2095 break; 2096 pmp = tmp; 2097 } 2098 if (tmp == NULL) 2099 goto cresout; 2100 2101 if ((nbp = dupb(mp)) == NULL && 2102 (nbp = copyb(mp)) == NULL) { 2103 tim_recover(q, mp, msgsize(mp)); 2104 return (1); 2105 } 2106 2107 if (pmp != NULL) 2108 pmp->b_next = tmp->b_next; 2109 else 2110 tp->tim_consave = tmp->b_next; 2111 tmp->b_next = NULL; 2112 2113 /* 2114 * Construct a list with: 2115 * nbp - copy of user's original request 2116 * tmp - the extracted T_conn_ind 2117 */ 2118 nbp->b_cont = tmp; 2119 /* 2120 * tim_iocsave may be non-NULL when timod is awaiting 2121 * ack for TI_GETPEERNAME/TI_GETMYNAME. 2122 */ 2123 freemsg(tp->tim_iocsave); 2124 tp->tim_iocsave = nbp; 2125 tp->tim_saved_prim = pptr->type; 2126 tp->tim_flags |= WAIT_CONNRESACK | WAITIOCACK; 2127 2128 cresout: 2129 putnext(q, mp); 2130 break; 2131 } 2132 2133 /* ONC_PLUS EXTRACT END */ 2134 case T_DISCON_REQ: { 2135 struct T_discon_req *disp; 2136 struct T_conn_ind *conp; 2137 mblk_t *pmp = NULL; 2138 2139 if (MBLKL(mp) < sizeof (struct T_discon_req)) { 2140 merror(q, mp, EPROTO); 2141 return (1); 2142 } 2143 2144 disp = (struct T_discon_req *)mp->b_rptr; 2145 tp->tim_flags &= ~(CONNWAIT|LOCORDREL|REMORDREL); 2146 tim_clear_peer(tp); 2147 2148 /* 2149 * If we are already connected, there won't 2150 * be any messages on tim_consave. 2151 */ 2152 for (tmp = tp->tim_consave; tmp; tmp = tmp->b_next) { 2153 conp = (struct T_conn_ind *)tmp->b_rptr; 2154 if (conp->SEQ_number == disp->SEQ_number) 2155 break; 2156 pmp = tmp; 2157 } 2158 if (tmp) { 2159 if (pmp) 2160 pmp->b_next = tmp->b_next; 2161 else 2162 tp->tim_consave = tmp->b_next; 2163 tmp->b_next = NULL; 2164 freemsg(tmp); 2165 } 2166 putnext(q, mp); 2167 break; 2168 } 2169 2170 case T_ORDREL_REQ: 2171 if (tp->tim_flags & REMORDREL) { 2172 tp->tim_flags &= ~(LOCORDREL|REMORDREL); 2173 tim_clear_peer(tp); 2174 } else { 2175 tp->tim_flags |= LOCORDREL; 2176 } 2177 putnext(q, mp); 2178 break; 2179 2180 case T_CAPABILITY_REQ: 2181 tilog("timodwproc: Got T_CAPABILITY_REQ\n", 0); 2182 /* 2183 * XXX: We may know at this point whether transport 2184 * provides T_CAPABILITY_REQ or not and we may utilise 2185 * this knowledge here. 2186 */ 2187 putnext(q, mp); 2188 break; 2189 /* ONC_PLUS EXTRACT START */ 2190 } 2191 break; 2192 case M_FLUSH: 2193 2194 tilog("timodwproc: Got M_FLUSH\n", 0); 2195 2196 if (*mp->b_rptr & FLUSHW) { 2197 if (*mp->b_rptr & FLUSHBAND) 2198 flushband(q, *(mp->b_rptr + 1), FLUSHDATA); 2199 else 2200 flushq(q, FLUSHDATA); 2201 } 2202 putnext(q, mp); 2203 break; 2204 } 2205 2206 return (0); 2207 } 2208 2209 static void 2210 tilog(char *str, t_scalar_t arg) 2211 { 2212 if (dotilog) { 2213 if (dotilog & 2) 2214 cmn_err(CE_CONT, str, arg); 2215 if (dotilog & 4) 2216 (void) strlog(TIMOD_ID, -1, 0, SL_TRACE | SL_ERROR, 2217 str, arg); 2218 else 2219 (void) strlog(TIMOD_ID, -1, 0, SL_TRACE, str, arg); 2220 } 2221 } 2222 2223 static void 2224 tilogp(char *str, uintptr_t arg) 2225 { 2226 if (dotilog) { 2227 if (dotilog & 2) 2228 cmn_err(CE_CONT, str, arg); 2229 if (dotilog & 4) 2230 (void) strlog(TIMOD_ID, -1, 0, SL_TRACE | SL_ERROR, 2231 str, arg); 2232 else 2233 (void) strlog(TIMOD_ID, -1, 0, SL_TRACE, str, arg); 2234 } 2235 } 2236 2237 2238 /* 2239 * Process the TI_GETNAME ioctl. If no name exists, return len = 0 2240 * in strbuf structures. The state transitions are determined by what 2241 * is hung of cq_private (cp_private) in the copyresp (copyreq) structure. 2242 * The high-level steps in the ioctl processing are as follows: 2243 * 2244 * 1) we recieve an transparent M_IOCTL with the arg in the second message 2245 * block of the message. 2246 * 2) we send up an M_COPYIN request for the strbuf structure pointed to 2247 * by arg. The block containing arg is hung off cq_private. 2248 * 3) we receive an M_IOCDATA response with cp->cp_private->b_cont == NULL. 2249 * This means that the strbuf structure is found in the message block 2250 * mp->b_cont. 2251 * 4) we send up an M_COPYOUT request with the strbuf message hung off 2252 * cq_private->b_cont. The address we are copying to is strbuf.buf. 2253 * we set strbuf.len to 0 to indicate that we should copy the strbuf 2254 * structure the next time. The message mp->b_cont contains the 2255 * address info. 2256 * 5) we receive an M_IOCDATA with cp_private->b_cont != NULL and 2257 * strbuf.len == 0. Restore strbuf.len to either tp->tim_mylen or 2258 * tp->tim_peerlen. 2259 * 6) we send up an M_COPYOUT request with a copy of the strbuf message 2260 * hung off mp->b_cont. In the strbuf structure in the message hung 2261 * off cq_private->b_cont, we set strbuf.len to 0 and strbuf.maxlen 2262 * to 0. This means that the next step is to ACK the ioctl. 2263 * 7) we receive an M_IOCDATA message with cp_private->b_cont != NULL and 2264 * strbuf.len == 0 and strbuf.maxlen == 0. Free up cp->private and 2265 * send an M_IOCACK upstream, and we are done. 2266 * 2267 */ 2268 static int 2269 ti_doname( 2270 queue_t *q, /* queue message arrived at */ 2271 mblk_t *mp) /* M_IOCTL or M_IOCDATA message only */ 2272 { 2273 struct iocblk *iocp; 2274 struct copyreq *cqp; 2275 STRUCT_HANDLE(strbuf, sb); 2276 struct copyresp *csp; 2277 int ret; 2278 mblk_t *bp; 2279 struct tim_tim *tp = q->q_ptr; 2280 boolean_t getpeer; 2281 2282 switch (mp->b_datap->db_type) { 2283 case M_IOCTL: 2284 iocp = (struct iocblk *)mp->b_rptr; 2285 if ((iocp->ioc_cmd != TI_GETMYNAME) && 2286 (iocp->ioc_cmd != TI_GETPEERNAME)) { 2287 tilog("ti_doname: bad M_IOCTL command\n", 0); 2288 miocnak(q, mp, 0, EINVAL); 2289 ret = DONAME_FAIL; 2290 break; 2291 } 2292 if ((iocp->ioc_count != TRANSPARENT)) { 2293 miocnak(q, mp, 0, EINVAL); 2294 ret = DONAME_FAIL; 2295 break; 2296 } 2297 2298 cqp = (struct copyreq *)mp->b_rptr; 2299 cqp->cq_private = mp->b_cont; 2300 cqp->cq_addr = (caddr_t)*(intptr_t *)mp->b_cont->b_rptr; 2301 mp->b_cont = NULL; 2302 cqp->cq_size = SIZEOF_STRUCT(strbuf, iocp->ioc_flag); 2303 cqp->cq_flag = 0; 2304 mp->b_datap->db_type = M_COPYIN; 2305 mp->b_wptr = mp->b_rptr + sizeof (struct copyreq); 2306 qreply(q, mp); 2307 ret = DONAME_CONT; 2308 break; 2309 2310 case M_IOCDATA: 2311 csp = (struct copyresp *)mp->b_rptr; 2312 iocp = (struct iocblk *)mp->b_rptr; 2313 cqp = (struct copyreq *)mp->b_rptr; 2314 if ((csp->cp_cmd != TI_GETMYNAME) && 2315 (csp->cp_cmd != TI_GETPEERNAME)) { 2316 cmn_err(CE_WARN, "ti_doname: bad M_IOCDATA command\n"); 2317 miocnak(q, mp, 0, EINVAL); 2318 ret = DONAME_FAIL; 2319 break; 2320 } 2321 if (csp->cp_rval) { /* error */ 2322 freemsg(csp->cp_private); 2323 freemsg(mp); 2324 ret = DONAME_FAIL; 2325 break; 2326 } 2327 ASSERT(csp->cp_private != NULL); 2328 getpeer = csp->cp_cmd == TI_GETPEERNAME; 2329 if (getpeer) 2330 mutex_enter(&tp->tim_mutex); 2331 if (csp->cp_private->b_cont == NULL) { /* got strbuf */ 2332 ASSERT(mp->b_cont); 2333 STRUCT_SET_HANDLE(sb, iocp->ioc_flag, 2334 (void *)mp->b_cont->b_rptr); 2335 if (getpeer) { 2336 if (tp->tim_peerlen == 0) { 2337 /* copy just strbuf */ 2338 STRUCT_FSET(sb, len, 0); 2339 } else if (tp->tim_peerlen > 2340 STRUCT_FGET(sb, maxlen)) { 2341 mutex_exit(&tp->tim_mutex); 2342 miocnak(q, mp, 0, ENAMETOOLONG); 2343 ret = DONAME_FAIL; 2344 break; 2345 } else { 2346 /* copy buffer */ 2347 STRUCT_FSET(sb, len, tp->tim_peerlen); 2348 } 2349 } else { 2350 if (tp->tim_mylen == 0) { 2351 /* copy just strbuf */ 2352 STRUCT_FSET(sb, len, 0); 2353 } else if (tp->tim_mylen > 2354 STRUCT_FGET(sb, maxlen)) { 2355 freemsg(csp->cp_private); 2356 miocnak(q, mp, 0, ENAMETOOLONG); 2357 ret = DONAME_FAIL; 2358 break; 2359 } else { 2360 /* copy buffer */ 2361 STRUCT_FSET(sb, len, tp->tim_mylen); 2362 } 2363 } 2364 csp->cp_private->b_cont = mp->b_cont; 2365 mp->b_cont = NULL; 2366 } 2367 STRUCT_SET_HANDLE(sb, iocp->ioc_flag, 2368 (void *)csp->cp_private->b_cont->b_rptr); 2369 if (STRUCT_FGET(sb, len) == 0) { 2370 /* 2371 * restore strbuf.len 2372 */ 2373 if (getpeer) 2374 STRUCT_FSET(sb, len, tp->tim_peerlen); 2375 else 2376 STRUCT_FSET(sb, len, tp->tim_mylen); 2377 2378 if (getpeer) 2379 mutex_exit(&tp->tim_mutex); 2380 if (STRUCT_FGET(sb, maxlen) == 0) { 2381 2382 /* 2383 * ack the ioctl 2384 */ 2385 freemsg(csp->cp_private); 2386 tim_ioctl_send_reply(q, mp, NULL); 2387 ret = DONAME_DONE; 2388 break; 2389 } 2390 2391 if ((bp = allocb(STRUCT_SIZE(sb), BPRI_MED)) == NULL) { 2392 2393 tilog( 2394 "ti_doname: allocb failed no recovery attempt\n", 0); 2395 2396 freemsg(csp->cp_private); 2397 miocnak(q, mp, 0, EAGAIN); 2398 ret = DONAME_FAIL; 2399 break; 2400 } 2401 bp->b_wptr += STRUCT_SIZE(sb); 2402 bcopy(STRUCT_BUF(sb), bp->b_rptr, STRUCT_SIZE(sb)); 2403 cqp->cq_addr = 2404 (caddr_t)*(intptr_t *)csp->cp_private->b_rptr; 2405 cqp->cq_size = STRUCT_SIZE(sb); 2406 cqp->cq_flag = 0; 2407 mp->b_datap->db_type = M_COPYOUT; 2408 mp->b_cont = bp; 2409 STRUCT_FSET(sb, len, 0); 2410 STRUCT_FSET(sb, maxlen, 0); /* ack next time around */ 2411 qreply(q, mp); 2412 ret = DONAME_CONT; 2413 break; 2414 } 2415 2416 /* 2417 * copy the address to the user 2418 */ 2419 if ((bp = allocb((size_t)STRUCT_FGET(sb, len), BPRI_MED)) 2420 == NULL) { 2421 if (getpeer) 2422 mutex_exit(&tp->tim_mutex); 2423 2424 tilog("ti_doname: allocb failed no recovery attempt\n", 2425 0); 2426 2427 freemsg(csp->cp_private); 2428 miocnak(q, mp, 0, EAGAIN); 2429 ret = DONAME_FAIL; 2430 break; 2431 } 2432 bp->b_wptr += STRUCT_FGET(sb, len); 2433 if (getpeer) { 2434 bcopy(tp->tim_peername, bp->b_rptr, 2435 STRUCT_FGET(sb, len)); 2436 mutex_exit(&tp->tim_mutex); 2437 } else { 2438 bcopy(tp->tim_myname, bp->b_rptr, STRUCT_FGET(sb, len)); 2439 } 2440 cqp->cq_addr = (caddr_t)STRUCT_FGETP(sb, buf); 2441 cqp->cq_size = STRUCT_FGET(sb, len); 2442 cqp->cq_flag = 0; 2443 mp->b_datap->db_type = M_COPYOUT; 2444 mp->b_cont = bp; 2445 STRUCT_FSET(sb, len, 0); /* copy the strbuf next time around */ 2446 qreply(q, mp); 2447 ret = DONAME_CONT; 2448 break; 2449 2450 default: 2451 tilog("ti_doname: freeing bad message type = %d\n", 2452 mp->b_datap->db_type); 2453 freemsg(mp); 2454 ret = DONAME_FAIL; 2455 break; 2456 } 2457 return (ret); 2458 } 2459 2460 /* ONC_PLUS EXTRACT END */ 2461 2462 /* 2463 * Fill in the address of a connectionless data packet if a connect 2464 * had been done on this endpoint. 2465 */ 2466 static mblk_t * 2467 tim_filladdr(queue_t *q, mblk_t *mp, boolean_t dorecover) 2468 { 2469 mblk_t *bp; 2470 struct tim_tim *tp; 2471 struct T_unitdata_req *up; 2472 struct T_unitdata_req *nup; 2473 size_t plen; 2474 2475 tp = (struct tim_tim *)q->q_ptr; 2476 if (mp->b_datap->db_type == M_DATA) { 2477 mutex_enter(&tp->tim_mutex); 2478 bp = allocb(sizeof (struct T_unitdata_req) + tp->tim_peerlen, 2479 BPRI_MED); 2480 if (bp != NULL) { 2481 bp->b_datap->db_type = M_PROTO; 2482 up = (struct T_unitdata_req *)bp->b_rptr; 2483 up->PRIM_type = T_UNITDATA_REQ; 2484 up->DEST_length = tp->tim_peerlen; 2485 bp->b_wptr += sizeof (struct T_unitdata_req); 2486 up->DEST_offset = sizeof (struct T_unitdata_req); 2487 up->OPT_length = 0; 2488 up->OPT_offset = 0; 2489 if (tp->tim_peerlen > 0) { 2490 bcopy(tp->tim_peername, bp->b_wptr, 2491 tp->tim_peerlen); 2492 bp->b_wptr += tp->tim_peerlen; 2493 } 2494 bp->b_cont = mp; 2495 } 2496 } else { 2497 ASSERT(mp->b_datap->db_type == M_PROTO); 2498 up = (struct T_unitdata_req *)mp->b_rptr; 2499 ASSERT(up->PRIM_type == T_UNITDATA_REQ); 2500 if (up->DEST_length != 0) 2501 return (mp); 2502 mutex_enter(&tp->tim_mutex); 2503 bp = allocb(sizeof (struct T_unitdata_req) + up->OPT_length + 2504 tp->tim_peerlen, BPRI_MED); 2505 if (bp != NULL) { 2506 bp->b_datap->db_type = M_PROTO; 2507 nup = (struct T_unitdata_req *)bp->b_rptr; 2508 nup->PRIM_type = T_UNITDATA_REQ; 2509 nup->DEST_length = plen = tp->tim_peerlen; 2510 bp->b_wptr += sizeof (struct T_unitdata_req); 2511 nup->DEST_offset = sizeof (struct T_unitdata_req); 2512 if (plen > 0) { 2513 bcopy(tp->tim_peername, bp->b_wptr, plen); 2514 bp->b_wptr += plen; 2515 } 2516 mutex_exit(&tp->tim_mutex); 2517 if (up->OPT_length == 0) { 2518 nup->OPT_length = 0; 2519 nup->OPT_offset = 0; 2520 } else { 2521 nup->OPT_length = up->OPT_length; 2522 nup->OPT_offset = 2523 sizeof (struct T_unitdata_req) + plen; 2524 bcopy((mp->b_wptr + up->OPT_offset), bp->b_wptr, 2525 up->OPT_length); 2526 bp->b_wptr += up->OPT_length; 2527 } 2528 bp->b_cont = mp->b_cont; 2529 mp->b_cont = NULL; 2530 freeb(mp); 2531 return (bp); 2532 } 2533 } 2534 ASSERT(MUTEX_HELD(&tp->tim_mutex)); 2535 if (bp == NULL && dorecover) { 2536 tim_recover(q, mp, 2537 sizeof (struct T_unitdata_req) + tp->tim_peerlen); 2538 } 2539 mutex_exit(&tp->tim_mutex); 2540 return (bp); 2541 } 2542 2543 static void 2544 tim_addlink(struct tim_tim *tp) 2545 { 2546 struct tim_tim **tpp; 2547 struct tim_tim *next; 2548 2549 tpp = &tim_hash[TIM_HASH(tp->tim_acceptor)]; 2550 rw_enter(&tim_list_rwlock, RW_WRITER); 2551 2552 if ((next = *tpp) != NULL) 2553 next->tim_ptpn = &tp->tim_next; 2554 tp->tim_next = next; 2555 tp->tim_ptpn = tpp; 2556 *tpp = tp; 2557 2558 tim_cnt++; 2559 2560 rw_exit(&tim_list_rwlock); 2561 } 2562 2563 static void 2564 tim_dellink(struct tim_tim *tp) 2565 { 2566 struct tim_tim *next; 2567 2568 rw_enter(&tim_list_rwlock, RW_WRITER); 2569 2570 if ((next = tp->tim_next) != NULL) 2571 next->tim_ptpn = tp->tim_ptpn; 2572 *(tp->tim_ptpn) = next; 2573 2574 tim_cnt--; 2575 2576 rw_exit(&tim_list_rwlock); 2577 } 2578 2579 static struct tim_tim * 2580 tim_findlink(t_uscalar_t id) 2581 { 2582 struct tim_tim *tp; 2583 2584 ASSERT(rw_lock_held(&tim_list_rwlock)); 2585 2586 for (tp = tim_hash[TIM_HASH(id)]; tp != NULL; tp = tp->tim_next) { 2587 if (tp->tim_acceptor == id) { 2588 break; 2589 } 2590 } 2591 return (tp); 2592 } 2593 2594 /* ONC_PLUS EXTRACT START */ 2595 static void 2596 tim_recover(queue_t *q, mblk_t *mp, t_scalar_t size) 2597 { 2598 struct tim_tim *tp; 2599 bufcall_id_t bid; 2600 timeout_id_t tid; 2601 2602 tp = (struct tim_tim *)q->q_ptr; 2603 2604 /* 2605 * Avoid re-enabling the queue. 2606 */ 2607 if (mp->b_datap->db_type == M_PCPROTO) 2608 mp->b_datap->db_type = M_PROTO; 2609 noenable(q); 2610 (void) putbq(q, mp); 2611 2612 /* 2613 * Make sure there is at most one outstanding request per queue. 2614 */ 2615 if (q->q_flag & QREADR) { 2616 if (tp->tim_rtimoutid || tp->tim_rbufcid) 2617 return; 2618 } else { 2619 if (tp->tim_wtimoutid || tp->tim_wbufcid) 2620 return; 2621 } 2622 if (!(bid = qbufcall(RD(q), (size_t)size, BPRI_MED, tim_buffer, q))) { 2623 tid = qtimeout(RD(q), tim_timer, q, TIMWAIT); 2624 if (q->q_flag & QREADR) 2625 tp->tim_rtimoutid = tid; 2626 else 2627 tp->tim_wtimoutid = tid; 2628 } else { 2629 if (q->q_flag & QREADR) 2630 tp->tim_rbufcid = bid; 2631 else 2632 tp->tim_wbufcid = bid; 2633 } 2634 } 2635 2636 /* 2637 * Timod is waiting on a downstream ioctl reply, come back soon 2638 * to reschedule the write side service routine, which will check 2639 * if the ioctl is done and another can proceed. 2640 */ 2641 static void 2642 tim_ioctl_retry(queue_t *q) 2643 { 2644 struct tim_tim *tp; 2645 2646 tp = (struct tim_tim *)q->q_ptr; 2647 2648 /* 2649 * Make sure there is at most one outstanding request per wqueue. 2650 */ 2651 if (tp->tim_wtimoutid || tp->tim_wbufcid) 2652 return; 2653 2654 tp->tim_wtimoutid = qtimeout(RD(q), tim_timer, q, TIMIOCWAIT); 2655 } 2656 2657 /* 2658 * Inspect the data on read queues starting from read queues passed as 2659 * paramter (timod read queue) and traverse until 2660 * q_next is NULL (stream head). Look for a TPI T_EXDATA_IND message 2661 * reutrn 1 if found, 0 if not found. 2662 */ 2663 static int 2664 ti_expind_on_rdqueues(queue_t *rq) 2665 { 2666 mblk_t *bp; 2667 queue_t *q; 2668 2669 q = rq; 2670 /* 2671 * We are going to walk q_next, so protect stream from plumbing 2672 * changes. 2673 */ 2674 claimstr(q); 2675 do { 2676 /* 2677 * Hold QLOCK while referencing data on queues 2678 */ 2679 mutex_enter(QLOCK(rq)); 2680 bp = rq->q_first; 2681 while (bp != NULL) { 2682 /* 2683 * Walk the messages on the queue looking 2684 * for a possible T_EXDATA_IND 2685 */ 2686 if ((bp->b_datap->db_type == M_PROTO) && 2687 ((bp->b_wptr - bp->b_rptr) >= 2688 sizeof (struct T_exdata_ind)) && 2689 (((struct T_exdata_ind *)bp->b_rptr)->PRIM_type 2690 == T_EXDATA_IND)) { 2691 /* bp is T_EXDATA_IND */ 2692 mutex_exit(QLOCK(rq)); 2693 releasestr(q); /* decrement sd_refcnt */ 2694 return (1); /* expdata is on a read queue */ 2695 } 2696 bp = bp->b_next; /* next message */ 2697 } 2698 mutex_exit(QLOCK(rq)); 2699 rq = rq->q_next; /* next upstream queue */ 2700 } while (rq != NULL); 2701 releasestr(q); 2702 return (0); /* no expdata on read queues */ 2703 } 2704 2705 /* ONC_PLUS EXTRACT END */ 2706 static void 2707 tim_tcap_timer(void *q_ptr) 2708 { 2709 queue_t *q = (queue_t *)q_ptr; 2710 struct tim_tim *tp = (struct tim_tim *)q->q_ptr; 2711 2712 ASSERT(tp != NULL && tp->tim_tcap_timoutid != 0); 2713 ASSERT((tp->tim_flags & TI_CAP_RECVD) != 0); 2714 2715 tp->tim_tcap_timoutid = 0; 2716 TILOG("tim_tcap_timer: fired\n", 0); 2717 tim_tcap_genreply(q, tp); 2718 } 2719 2720 /* 2721 * tim_tcap_genreply() is called either from timeout routine or when 2722 * T_ERROR_ACK is received. In both cases it means that underlying 2723 * transport doesn't provide T_CAPABILITY_REQ. 2724 */ 2725 static void 2726 tim_tcap_genreply(queue_t *q, struct tim_tim *tp) 2727 { 2728 mblk_t *mp = tp->tim_iocsave; 2729 struct iocblk *iocbp; 2730 2731 TILOG("timodrproc: tim_tcap_genreply\n", 0); 2732 2733 ASSERT(tp == (struct tim_tim *)q->q_ptr); 2734 ASSERT(mp != NULL); 2735 2736 iocbp = (struct iocblk *)mp->b_rptr; 2737 ASSERT(iocbp != NULL); 2738 ASSERT(MBLKL(mp) == sizeof (struct iocblk)); 2739 ASSERT(iocbp->ioc_cmd == TI_CAPABILITY); 2740 ASSERT(mp->b_cont == NULL); 2741 2742 /* Save this information permanently in the module */ 2743 PI_PROVLOCK(tp->tim_provinfo); 2744 if (tp->tim_provinfo->tpi_capability == PI_DONTKNOW) 2745 tp->tim_provinfo->tpi_capability = PI_NO; 2746 PI_PROVUNLOCK(tp->tim_provinfo); 2747 2748 if (tp->tim_tcap_timoutid != 0) { 2749 (void) quntimeout(q, tp->tim_tcap_timoutid); 2750 tp->tim_tcap_timoutid = 0; 2751 } 2752 2753 if ((tp->tim_flags & CAP_WANTS_INFO) != 0) { 2754 /* Send T_INFO_REQ down */ 2755 mblk_t *tirmp = tpi_ack_alloc(NULL, 2756 sizeof (struct T_info_req), M_PCPROTO, T_INFO_REQ); 2757 2758 if (tirmp != NULL) { 2759 /* Emulate TC1_INFO */ 2760 TILOG("emulate_tcap_ioc_req: sending T_INFO_REQ\n", 0); 2761 tp->tim_flags |= WAIT_IOCINFOACK; 2762 putnext(WR(q), tirmp); 2763 } else { 2764 tilog("emulate_tcap_req: allocb fail, " 2765 "no recovery attmpt\n", 0); 2766 tp->tim_iocsave = NULL; 2767 tp->tim_saved_prim = -1; 2768 tp->tim_flags &= ~(TI_CAP_RECVD | WAITIOCACK | 2769 CAP_WANTS_INFO | WAIT_IOCINFOACK); 2770 miocnak(q, mp, 0, ENOMEM); 2771 } 2772 } else { 2773 /* Reply immediately */ 2774 mblk_t *ackmp = tpi_ack_alloc(NULL, 2775 sizeof (struct T_capability_ack), M_PCPROTO, 2776 T_CAPABILITY_ACK); 2777 2778 mp->b_cont = ackmp; 2779 2780 if (ackmp != NULL) { 2781 ((struct T_capability_ack *) 2782 ackmp->b_rptr)->CAP_bits1 = 0; 2783 tim_ioctl_send_reply(q, mp, ackmp); 2784 tp->tim_iocsave = NULL; 2785 tp->tim_saved_prim = -1; 2786 tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 2787 TI_CAP_RECVD | CAP_WANTS_INFO); 2788 } else { 2789 tilog("timodwproc:allocb failed no " 2790 "recovery attempt\n", 0); 2791 tp->tim_iocsave = NULL; 2792 tp->tim_saved_prim = -1; 2793 tp->tim_flags &= ~(TI_CAP_RECVD | WAITIOCACK | 2794 CAP_WANTS_INFO | WAIT_IOCINFOACK); 2795 miocnak(q, mp, 0, ENOMEM); 2796 } 2797 } 2798 } 2799 2800 2801 static void 2802 tim_ioctl_send_reply(queue_t *q, mblk_t *ioc_mp, mblk_t *mp) 2803 { 2804 struct iocblk *iocbp; 2805 2806 ASSERT(q != NULL && ioc_mp != NULL); 2807 2808 ioc_mp->b_datap->db_type = M_IOCACK; 2809 if (mp != NULL) 2810 mp->b_datap->db_type = M_DATA; 2811 2812 if (ioc_mp->b_cont != mp) { 2813 /* It is safe to call freemsg for NULL pointers */ 2814 freemsg(ioc_mp->b_cont); 2815 ioc_mp->b_cont = mp; 2816 } 2817 iocbp = (struct iocblk *)ioc_mp->b_rptr; 2818 iocbp->ioc_error = 0; 2819 iocbp->ioc_rval = 0; 2820 /* 2821 * All ioctl's may return more data than was specified by 2822 * count arg. For TI_CAPABILITY count is treated as maximum data size. 2823 */ 2824 if (mp == NULL) 2825 iocbp->ioc_count = 0; 2826 else if (iocbp->ioc_cmd != TI_CAPABILITY) 2827 iocbp->ioc_count = msgsize(mp); 2828 else { 2829 iocbp->ioc_count = MIN(MBLKL(mp), iocbp->ioc_count); 2830 /* Truncate message if too large */ 2831 mp->b_wptr = mp->b_rptr + iocbp->ioc_count; 2832 } 2833 2834 TILOG("iosendreply: ioc_cmd = %d, ", iocbp->ioc_cmd); 2835 putnext(RD(q), ioc_mp); 2836 } 2837 2838 /* 2839 * Send M_IOCACK for errors. 2840 */ 2841 static void 2842 tim_send_ioc_error_ack(queue_t *q, struct tim_tim *tp, mblk_t *mp) 2843 { 2844 struct T_error_ack *tea = (struct T_error_ack *)mp->b_rptr; 2845 t_scalar_t error_prim; 2846 2847 mp->b_wptr = mp->b_rptr + sizeof (struct T_error_ack); 2848 ASSERT(mp->b_wptr <= mp->b_datap->db_lim); 2849 error_prim = tea->ERROR_prim; 2850 2851 ASSERT(tp->tim_iocsave != NULL); 2852 ASSERT(tp->tim_iocsave->b_cont != mp); 2853 2854 /* Always send this to the read side of the queue */ 2855 q = RD(q); 2856 2857 TILOG("tim_send_ioc_error_ack: prim = %d\n", tp->tim_saved_prim); 2858 2859 if (tp->tim_saved_prim != error_prim) { 2860 putnext(q, mp); 2861 } else if (error_prim == T_CAPABILITY_REQ) { 2862 TILOG("timodrproc: T_ERROR_ACK/T_CAPABILITY_REQ\n", 0); 2863 ASSERT(tp->tim_iocsave->b_cont == NULL); 2864 2865 tim_tcap_genreply(q, tp); 2866 freemsg(mp); 2867 } else { 2868 struct iocblk *iocbp = (struct iocblk *)tp->tim_iocsave->b_rptr; 2869 2870 TILOG("tim_send_ioc_error_ack: T_ERROR_ACK: prim %d\n", 2871 error_prim); 2872 ASSERT(tp->tim_iocsave->b_cont == NULL); 2873 2874 switch (error_prim) { 2875 default: 2876 TILOG("timodrproc: Unknown T_ERROR_ACK: tlierror %d\n", 2877 tea->TLI_error); 2878 2879 putnext(q, mp); 2880 break; 2881 2882 case T_INFO_REQ: 2883 case T_SVR4_OPTMGMT_REQ: 2884 case T_OPTMGMT_REQ: 2885 case O_T_BIND_REQ: 2886 case T_BIND_REQ: 2887 case T_UNBIND_REQ: 2888 case T_ADDR_REQ: 2889 case T_CAPABILITY_REQ: 2890 2891 TILOG("ioc_err_ack: T_ERROR_ACK: tlierror %x\n", 2892 tea->TLI_error); 2893 2894 /* get saved ioctl msg and set values */ 2895 iocbp->ioc_count = 0; 2896 iocbp->ioc_error = 0; 2897 iocbp->ioc_rval = tea->TLI_error; 2898 if (iocbp->ioc_rval == TSYSERR) 2899 iocbp->ioc_rval |= tea->UNIX_error << 8; 2900 tp->tim_iocsave->b_datap->db_type = M_IOCACK; 2901 freemsg(mp); 2902 putnext(q, tp->tim_iocsave); 2903 tp->tim_iocsave = NULL; 2904 tp->tim_saved_prim = -1; 2905 tp->tim_flags &= ~(WAITIOCACK | TI_CAP_RECVD | 2906 CAP_WANTS_INFO | WAIT_IOCINFOACK); 2907 break; 2908 } 2909 } 2910 } 2911 2912 /* 2913 * Send reply to a usual message or ioctl message upstream. 2914 * Should be called from the read side only. 2915 */ 2916 static void 2917 tim_send_reply(queue_t *q, mblk_t *mp, struct tim_tim *tp, t_scalar_t prim) 2918 { 2919 ASSERT(mp != NULL && q != NULL && tp != NULL); 2920 ASSERT(q == RD(q)); 2921 2922 /* Restore db_type - recover() might have changed it */ 2923 mp->b_datap->db_type = M_PCPROTO; 2924 2925 if (((tp->tim_flags & WAITIOCACK) == 0) || (tp->tim_saved_prim != prim)) 2926 putnext(q, mp); 2927 else { 2928 ASSERT(tp->tim_iocsave != NULL); 2929 tim_ioctl_send_reply(q, tp->tim_iocsave, mp); 2930 tp->tim_iocsave = NULL; 2931 tp->tim_saved_prim = -1; 2932 tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 2933 TI_CAP_RECVD | CAP_WANTS_INFO); 2934 } 2935 } 2936 2937 /* 2938 * Reply to TI_SYNC reequest without sending anything downstream. 2939 */ 2940 static void 2941 tim_answer_ti_sync(queue_t *q, mblk_t *mp, struct tim_tim *tp, 2942 mblk_t *ackmp, uint32_t tsr_flags) 2943 { 2944 struct ti_sync_ack *tsap; 2945 2946 ASSERT(q != NULL && q == WR(q) && ackmp != NULL); 2947 2948 tsap = (struct ti_sync_ack *)ackmp->b_rptr; 2949 bzero(tsap, sizeof (struct ti_sync_ack)); 2950 ackmp->b_wptr = ackmp->b_rptr + sizeof (struct ti_sync_ack); 2951 2952 if (tsr_flags == 0 || 2953 (tsr_flags & ~(TSRF_QLEN_REQ | TSRF_IS_EXP_IN_RCVBUF)) != 0) { 2954 /* 2955 * unsupported/bad flag setting 2956 * or no flag set. 2957 */ 2958 TILOG("timodwproc: unsupported/bad flag setting %x\n", 2959 tsr_flags); 2960 freemsg(ackmp); 2961 miocnak(q, mp, 0, EINVAL); 2962 return; 2963 } 2964 2965 if ((tsr_flags & TSRF_QLEN_REQ) != 0) 2966 tsap->tsa_qlen = tp->tim_backlog; 2967 2968 if ((tsr_flags & TSRF_IS_EXP_IN_RCVBUF) != 0 && 2969 ti_expind_on_rdqueues(RD(q))) { 2970 /* 2971 * Expedited data is queued on 2972 * the stream read side 2973 */ 2974 tsap->tsa_flags |= TSAF_EXP_QUEUED; 2975 } 2976 2977 tim_ioctl_send_reply(q, mp, ackmp); 2978 tp->tim_iocsave = NULL; 2979 tp->tim_saved_prim = -1; 2980 tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 2981 TI_CAP_RECVD | CAP_WANTS_INFO); 2982 } 2983 2984 /* 2985 * Send TPI message from IOCTL message, ssave original ioctl header and TPI 2986 * message type. Should be called from write side only. 2987 */ 2988 static void 2989 tim_send_ioctl_tpi_msg(queue_t *q, mblk_t *mp, struct tim_tim *tp, 2990 struct iocblk *iocb) 2991 { 2992 mblk_t *tmp; 2993 int ioc_cmd = iocb->ioc_cmd; 2994 2995 ASSERT(q != NULL && mp != NULL && tp != NULL); 2996 ASSERT(q == WR(q)); 2997 ASSERT(mp->b_cont != NULL); 2998 2999 tp->tim_iocsave = mp; 3000 tmp = mp->b_cont; 3001 3002 mp->b_cont = NULL; 3003 tp->tim_flags |= WAITIOCACK; 3004 tp->tim_saved_prim = ((union T_primitives *)tmp->b_rptr)->type; 3005 3006 /* 3007 * For TI_GETINFO, the attached message is a T_INFO_REQ 3008 * For TI_SYNC, we generate the T_INFO_REQ message above 3009 * For TI_CAPABILITY the attached message is either 3010 * T_CAPABILITY_REQ or T_INFO_REQ. 3011 * Among TPI request messages possible, 3012 * T_INFO_REQ/T_CAPABILITY_ACK messages are a M_PCPROTO, rest 3013 * are M_PROTO 3014 */ 3015 if (ioc_cmd == TI_GETINFO || ioc_cmd == TI_SYNC || 3016 ioc_cmd == TI_CAPABILITY) { 3017 tmp->b_datap->db_type = M_PCPROTO; 3018 } else { 3019 tmp->b_datap->db_type = M_PROTO; 3020 } 3021 3022 /* Verify credentials in STREAM */ 3023 ASSERT(iocb->ioc_cr == NULL || iocb->ioc_cr == DB_CRED(tmp)); 3024 3025 TILOG("timodwproc: sending down %d\n", tp->tim_saved_prim); 3026 putnext(q, tmp); 3027 } 3028 3029 static void 3030 tim_clear_peer(struct tim_tim *tp) 3031 { 3032 mutex_enter(&tp->tim_mutex); 3033 if (tp->tim_peercred != NULL) { 3034 crfree(tp->tim_peercred); 3035 tp->tim_peercred = NULL; 3036 } 3037 tp->tim_peerlen = 0; 3038 mutex_exit(&tp->tim_mutex); 3039 } 3040