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