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