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 2007 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 if (audit_active) 793 audit_sock(T_UNITDATA_IND, q, mp, TIMOD_ID); 794 /* ONC_PLUS EXTRACT START */ 795 putnext(q, mp); 796 break; 797 /* ONC_PLUS EXTRACT END */ 798 799 case T_ERROR_ACK: 800 /* Restore db_type - recover() might have changed it */ 801 mp->b_datap->db_type = M_PCPROTO; 802 if (blen < sizeof (struct T_error_ack)) { 803 putnext(q, mp); 804 break; 805 } 806 807 tilog("timodrproc: Got T_ERROR_ACK, flags = %x\n", 808 tp->tim_flags); 809 810 if ((tp->tim_flags & WAIT_CONNRESACK) && 811 tp->tim_saved_prim == pptr->error_ack.ERROR_prim) { 812 tp->tim_flags &= 813 ~(WAIT_CONNRESACK | WAITIOCACK); 814 freemsg(tp->tim_iocsave); 815 tp->tim_iocsave = NULL; 816 tp->tim_saved_prim = -1; 817 putnext(q, mp); 818 } else if (tp->tim_flags & WAITIOCACK) { 819 tim_send_ioc_error_ack(q, tp, mp); 820 } else { 821 putnext(q, mp); 822 } 823 break; 824 825 case T_OK_ACK: 826 if (blen < sizeof (pptr->ok_ack)) { 827 mp->b_datap->db_type = M_PCPROTO; 828 putnext(q, mp); 829 break; 830 } 831 832 tilog("timodrproc: Got T_OK_ACK\n", 0); 833 834 if (pptr->ok_ack.CORRECT_prim == T_UNBIND_REQ) 835 tp->tim_mylen = 0; 836 837 if ((tp->tim_flags & WAIT_CONNRESACK) && 838 tp->tim_saved_prim == pptr->ok_ack.CORRECT_prim) { 839 struct T_conn_res *resp; 840 struct T_conn_ind *indp; 841 struct tim_tim *ntp; 842 caddr_t ptr; 843 844 rw_enter(&tim_list_rwlock, RW_READER); 845 resp = (struct T_conn_res *) 846 tp->tim_iocsave->b_rptr; 847 ntp = tim_findlink(resp->ACCEPTOR_id); 848 if (ntp == NULL) 849 goto cresackout; 850 851 mutex_enter(&ntp->tim_mutex); 852 if (ntp->tim_peercred != NULL) 853 crfree(ntp->tim_peercred); 854 ntp->tim_peercred = 855 DB_CRED(tp->tim_iocsave->b_cont); 856 ntp->tim_cpid = 857 DB_CPID(tp->tim_iocsave->b_cont); 858 if (ntp->tim_peercred != NULL) 859 crhold(ntp->tim_peercred); 860 861 if (!(ntp->tim_flags & DO_PEERNAME)) { 862 mutex_exit(&ntp->tim_mutex); 863 goto cresackout; 864 } 865 866 indp = (struct T_conn_ind *) 867 tp->tim_iocsave->b_cont->b_rptr; 868 /* true as message is put on list */ 869 ASSERT(indp->SRC_length >= 0); 870 871 if (indp->SRC_length > ntp->tim_peermaxlen) { 872 ptr = kmem_alloc(indp->SRC_length, 873 KM_NOSLEEP); 874 if (ptr == NULL) { 875 mutex_exit(&ntp->tim_mutex); 876 rw_exit(&tim_list_rwlock); 877 tilog("timodwproc: kmem_alloc " 878 "failed, attempting " 879 "recovery\n", 0); 880 tim_recover(q, mp, 881 indp->SRC_length); 882 return (1); 883 } 884 if (ntp->tim_peermaxlen > 0) 885 kmem_free(ntp->tim_peername, 886 ntp->tim_peermaxlen); 887 ntp->tim_peername = ptr; 888 ntp->tim_peermaxlen = indp->SRC_length; 889 } 890 ntp->tim_peerlen = indp->SRC_length; 891 ptr = (caddr_t)indp + indp->SRC_offset; 892 bcopy(ptr, ntp->tim_peername, ntp->tim_peerlen); 893 894 mutex_exit(&ntp->tim_mutex); 895 896 cresackout: 897 rw_exit(&tim_list_rwlock); 898 tp->tim_flags &= 899 ~(WAIT_CONNRESACK | WAITIOCACK); 900 freemsg(tp->tim_iocsave); 901 tp->tim_iocsave = NULL; 902 tp->tim_saved_prim = -1; 903 } 904 905 tim_send_reply(q, mp, tp, pptr->ok_ack.CORRECT_prim); 906 break; 907 908 /* ONC_PLUS EXTRACT START */ 909 case T_BIND_ACK: { 910 struct T_bind_ack *ackp = 911 (struct T_bind_ack *)mp->b_rptr; 912 913 /* Restore db_type - recover() might have changed it */ 914 mp->b_datap->db_type = M_PCPROTO; 915 if (blen < sizeof (*ackp)) { 916 putnext(q, mp); 917 break; 918 } 919 920 /* save negotiated backlog */ 921 tp->tim_backlog = ackp->CONIND_number; 922 923 if (((tp->tim_flags & WAITIOCACK) == 0) || 924 ((tp->tim_saved_prim != O_T_BIND_REQ) && 925 (tp->tim_saved_prim != T_BIND_REQ))) { 926 putnext(q, mp); 927 break; 928 } 929 ASSERT(tp->tim_iocsave != NULL); 930 931 if (tp->tim_flags & DO_MYNAME) { 932 caddr_t p; 933 934 if (ackp->ADDR_length < 0 || 935 mp->b_rptr + ackp->ADDR_offset + 936 ackp->ADDR_length > mp->b_wptr) { 937 putnext(q, mp); 938 break; 939 } 940 if (ackp->ADDR_length > tp->tim_mymaxlen) { 941 p = kmem_alloc(ackp->ADDR_length, 942 KM_NOSLEEP); 943 if (p == NULL) { 944 tilog("timodrproc: kmem_alloc " 945 "failed attempt recovery", 946 0); 947 948 tim_recover(q, mp, 949 ackp->ADDR_length); 950 return (1); 951 } 952 ASSERT(tp->tim_mymaxlen >= 0); 953 if (tp->tim_mymaxlen != NULL) { 954 kmem_free(tp->tim_myname, 955 tp->tim_mymaxlen); 956 } 957 tp->tim_myname = p; 958 tp->tim_mymaxlen = ackp->ADDR_length; 959 } 960 tp->tim_mylen = ackp->ADDR_length; 961 bcopy(mp->b_rptr + ackp->ADDR_offset, 962 tp->tim_myname, tp->tim_mylen); 963 } 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 | WAIT_IOCINFOACK | 968 TI_CAP_RECVD | CAP_WANTS_INFO); 969 break; 970 } 971 972 /* ONC_PLUS EXTRACT END */ 973 case T_OPTMGMT_ACK: 974 975 tilog("timodrproc: Got T_OPTMGMT_ACK\n", 0); 976 977 /* Restore db_type - recover() might have change it */ 978 mp->b_datap->db_type = M_PCPROTO; 979 980 if (((tp->tim_flags & WAITIOCACK) == 0) || 981 ((tp->tim_saved_prim != T_SVR4_OPTMGMT_REQ) && 982 (tp->tim_saved_prim != T_OPTMGMT_REQ))) { 983 putnext(q, mp); 984 } else { 985 ASSERT(tp->tim_iocsave != NULL); 986 tim_ioctl_send_reply(q, tp->tim_iocsave, mp); 987 tp->tim_iocsave = NULL; 988 tp->tim_saved_prim = -1; 989 tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 990 TI_CAP_RECVD | CAP_WANTS_INFO); 991 } 992 break; 993 994 case T_INFO_ACK: { 995 struct T_info_ack *tia = (struct T_info_ack *)pptr; 996 997 /* Restore db_type - recover() might have changed it */ 998 mp->b_datap->db_type = M_PCPROTO; 999 1000 if (blen < sizeof (*tia)) { 1001 putnext(q, mp); 1002 break; 1003 } 1004 1005 tilog("timodrproc: Got T_INFO_ACK, flags = %x\n", 1006 tp->tim_flags); 1007 1008 timodprocessinfo(q, tp, tia); 1009 1010 TILOG("timodrproc: flags = %x\n", tp->tim_flags); 1011 if ((tp->tim_flags & WAITIOCACK) != 0) { 1012 size_t expected_ack_size; 1013 ssize_t deficit; 1014 int ioc_cmd; 1015 struct T_capability_ack *tcap; 1016 1017 /* 1018 * The only case when T_INFO_ACK may be received back 1019 * when we are waiting for ioctl to complete is when 1020 * this ioctl sent T_INFO_REQ down. 1021 */ 1022 if (!(tp->tim_flags & WAIT_IOCINFOACK)) { 1023 putnext(q, mp); 1024 break; 1025 } 1026 ASSERT(tp->tim_iocsave != NULL); 1027 1028 iocbp = (struct iocblk *)tp->tim_iocsave->b_rptr; 1029 ioc_cmd = iocbp->ioc_cmd; 1030 1031 /* 1032 * Was it sent from TI_CAPABILITY emulation? 1033 */ 1034 if (ioc_cmd == TI_CAPABILITY) { 1035 struct T_info_ack saved_info; 1036 1037 /* 1038 * Perform sanity checks. The only case when we 1039 * send T_INFO_REQ from TI_CAPABILITY is when 1040 * timod emulates T_CAPABILITY_REQ and CAP_bits1 1041 * has TC1_INFO set. 1042 */ 1043 if ((tp->tim_flags & 1044 (TI_CAP_RECVD | CAP_WANTS_INFO)) != 1045 (TI_CAP_RECVD | CAP_WANTS_INFO)) { 1046 putnext(q, mp); 1047 break; 1048 } 1049 1050 TILOG("timodrproc: emulating TI_CAPABILITY/" 1051 "info\n", 0); 1052 1053 /* Save info & reuse mp for T_CAPABILITY_ACK */ 1054 saved_info = *tia; 1055 1056 mp = tpi_ack_alloc(mp, 1057 sizeof (struct T_capability_ack), 1058 M_PCPROTO, T_CAPABILITY_ACK); 1059 1060 if (mp == NULL) { 1061 tilog("timodrproc: realloc failed, " 1062 "no recovery attempted\n", 0); 1063 return (1); 1064 } 1065 1066 /* 1067 * Copy T_INFO information into T_CAPABILITY_ACK 1068 */ 1069 tcap = (struct T_capability_ack *)mp->b_rptr; 1070 tcap->CAP_bits1 = TC1_INFO; 1071 tcap->INFO_ack = saved_info; 1072 tp->tim_flags &= ~(WAITIOCACK | 1073 WAIT_IOCINFOACK | TI_CAP_RECVD | 1074 CAP_WANTS_INFO); 1075 tim_ioctl_send_reply(q, tp->tim_iocsave, mp); 1076 tp->tim_iocsave = NULL; 1077 tp->tim_saved_prim = -1; 1078 break; 1079 } 1080 1081 /* 1082 * The code for TI_SYNC/TI_GETINFO is left here only for 1083 * backward compatibility with staticaly linked old 1084 * applications. New TLI/XTI code should use 1085 * TI_CAPABILITY for getting transport info and should 1086 * not use TI_GETINFO/TI_SYNC for this purpose. 1087 */ 1088 1089 /* 1090 * make sure the message sent back is the size of 1091 * the "expected ack" 1092 * For TI_GETINFO, expected ack size is 1093 * sizeof (T_info_ack) 1094 * For TI_SYNC, expected ack size is 1095 * sizeof (struct ti_sync_ack); 1096 */ 1097 if (ioc_cmd != TI_GETINFO && ioc_cmd != TI_SYNC) { 1098 putnext(q, mp); 1099 break; 1100 } 1101 1102 expected_ack_size = 1103 sizeof (struct T_info_ack); /* TI_GETINFO */ 1104 if (iocbp->ioc_cmd == TI_SYNC) { 1105 expected_ack_size = 2 * sizeof (uint32_t) + 1106 sizeof (struct ti_sync_ack); 1107 } 1108 deficit = expected_ack_size - blen; 1109 1110 if (deficit != 0) { 1111 if (mp->b_datap->db_lim - mp->b_wptr < 1112 deficit) { 1113 mblk_t *tmp = allocb(expected_ack_size, 1114 BPRI_HI); 1115 if (tmp == NULL) { 1116 ASSERT(MBLKSIZE(mp) >= 1117 sizeof (struct T_error_ack)); 1118 1119 tilog("timodrproc: allocb failed no " 1120 "recovery attempt\n", 0); 1121 1122 mp->b_rptr = mp->b_datap->db_base; 1123 pptr = (union T_primitives *) 1124 mp->b_rptr; 1125 pptr->error_ack.ERROR_prim = T_INFO_REQ; 1126 pptr->error_ack.TLI_error = TSYSERR; 1127 pptr->error_ack.UNIX_error = EAGAIN; 1128 pptr->error_ack.PRIM_type = T_ERROR_ACK; 1129 mp->b_datap->db_type = M_PCPROTO; 1130 tim_send_ioc_error_ack(q, tp, mp); 1131 break; 1132 } else { 1133 bcopy(mp->b_rptr, tmp->b_rptr, blen); 1134 tmp->b_wptr += blen; 1135 pptr = (union T_primitives *) 1136 tmp->b_rptr; 1137 freemsg(mp); 1138 mp = tmp; 1139 } 1140 } 1141 } 1142 /* 1143 * We now have "mp" which has enough space for an 1144 * appropriate ack and contains struct T_info_ack 1145 * that the transport provider returned. We now 1146 * stuff it with more stuff to fullfill 1147 * TI_SYNC ioctl needs, as necessary 1148 */ 1149 if (iocbp->ioc_cmd == TI_SYNC) { 1150 /* 1151 * Assumes struct T_info_ack is first embedded 1152 * type in struct ti_sync_ack so it is 1153 * automatically there. 1154 */ 1155 struct ti_sync_ack *tsap = 1156 (struct ti_sync_ack *)mp->b_rptr; 1157 1158 /* 1159 * tsap->tsa_qlen needs to be set only if 1160 * TSRF_QLEN_REQ flag is set, but for 1161 * compatibility with statically linked 1162 * applications it is set here regardless of the 1163 * flag since old XTI library expected it to be 1164 * set. 1165 */ 1166 tsap->tsa_qlen = tp->tim_backlog; 1167 tsap->tsa_flags = 0x0; /* intialize clear */ 1168 if (tp->tim_flags & PEEK_RDQ_EXPIND) { 1169 /* 1170 * Request to peek for EXPIND in 1171 * rcvbuf. 1172 */ 1173 if (ti_expind_on_rdqueues(q)) { 1174 /* 1175 * Expedited data is 1176 * queued on the stream 1177 * read side 1178 */ 1179 tsap->tsa_flags |= 1180 TSAF_EXP_QUEUED; 1181 } 1182 tp->tim_flags &= 1183 ~PEEK_RDQ_EXPIND; 1184 } 1185 mp->b_wptr += 2*sizeof (uint32_t); 1186 } 1187 tim_ioctl_send_reply(q, tp->tim_iocsave, mp); 1188 tp->tim_iocsave = NULL; 1189 tp->tim_saved_prim = -1; 1190 tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 1191 TI_CAP_RECVD | CAP_WANTS_INFO); 1192 break; 1193 } 1194 } 1195 1196 putnext(q, mp); 1197 break; 1198 1199 case T_ADDR_ACK: 1200 tilog("timodrproc: Got T_ADDR_ACK\n", 0); 1201 tim_send_reply(q, mp, tp, T_ADDR_REQ); 1202 break; 1203 1204 /* ONC_PLUS EXTRACT START */ 1205 case T_CONN_IND: { 1206 struct T_conn_ind *tcip = 1207 (struct T_conn_ind *)mp->b_rptr; 1208 1209 tilog("timodrproc: Got T_CONN_IND\n", 0); 1210 1211 if (blen >= sizeof (*tcip) && 1212 MBLKIN(mp, tcip->SRC_offset, tcip->SRC_length)) { 1213 if (((nbp = dupmsg(mp)) != NULL) || 1214 ((nbp = copymsg(mp)) != NULL)) { 1215 nbp->b_next = tp->tim_consave; 1216 tp->tim_consave = nbp; 1217 } else { 1218 tim_recover(q, mp, 1219 (t_scalar_t)sizeof (mblk_t)); 1220 return (1); 1221 } 1222 } 1223 /* ONC_PLUS EXTRACT END */ 1224 if (audit_active) 1225 audit_sock(T_CONN_IND, q, mp, TIMOD_ID); 1226 /* ONC_PLUS EXTRACT START */ 1227 putnext(q, mp); 1228 break; 1229 } 1230 1231 /* ONC_PLUS EXTRACT END */ 1232 case T_CONN_CON: 1233 mutex_enter(&tp->tim_mutex); 1234 if (tp->tim_peercred != NULL) 1235 crfree(tp->tim_peercred); 1236 tp->tim_peercred = DB_CRED(mp); 1237 if (tp->tim_peercred != NULL) 1238 crhold(tp->tim_peercred); 1239 tp->tim_cpid = DB_CPID(mp); 1240 mutex_exit(&tp->tim_mutex); 1241 1242 tilog("timodrproc: Got T_CONN_CON\n", 0); 1243 1244 tp->tim_flags &= ~CONNWAIT; 1245 putnext(q, mp); 1246 break; 1247 1248 case T_DISCON_IND: { 1249 struct T_discon_ind *disp; 1250 struct T_conn_ind *conp; 1251 mblk_t *pbp = NULL; 1252 1253 if (q->q_first != 0) 1254 tilog("timodrput: T_DISCON_IND - flow control\n", 0); 1255 1256 if (blen < sizeof (*disp)) { 1257 putnext(q, mp); 1258 break; 1259 } 1260 1261 disp = (struct T_discon_ind *)mp->b_rptr; 1262 1263 tilog("timodrproc: Got T_DISCON_IND Reason: %d\n", 1264 disp->DISCON_reason); 1265 1266 tp->tim_flags &= ~(CONNWAIT|LOCORDREL|REMORDREL); 1267 tim_clear_peer(tp); 1268 for (nbp = tp->tim_consave; nbp; nbp = nbp->b_next) { 1269 conp = (struct T_conn_ind *)nbp->b_rptr; 1270 if (conp->SEQ_number == disp->SEQ_number) 1271 break; 1272 pbp = nbp; 1273 } 1274 if (nbp) { 1275 if (pbp) 1276 pbp->b_next = nbp->b_next; 1277 else 1278 tp->tim_consave = nbp->b_next; 1279 nbp->b_next = NULL; 1280 freemsg(nbp); 1281 } 1282 putnext(q, mp); 1283 break; 1284 } 1285 1286 case T_ORDREL_IND: 1287 1288 tilog("timodrproc: Got T_ORDREL_IND\n", 0); 1289 1290 if (tp->tim_flags & LOCORDREL) { 1291 tp->tim_flags &= ~(LOCORDREL|REMORDREL); 1292 tim_clear_peer(tp); 1293 } else { 1294 tp->tim_flags |= REMORDREL; 1295 } 1296 putnext(q, mp); 1297 break; 1298 1299 case T_EXDATA_IND: 1300 case T_DATA_IND: 1301 case T_UNITDATA_IND: 1302 if (pptr->type == T_EXDATA_IND) 1303 tilog("timodrproc: Got T_EXDATA_IND\n", 0); 1304 1305 if (!bcanputnext(q, mp->b_band)) { 1306 (void) putbq(q, mp); 1307 return (1); 1308 } 1309 putnext(q, mp); 1310 break; 1311 1312 case T_CAPABILITY_ACK: { 1313 struct T_capability_ack *tca; 1314 1315 if (blen < sizeof (*tca)) { 1316 putnext(q, mp); 1317 break; 1318 } 1319 1320 /* This transport supports T_CAPABILITY_REQ */ 1321 tilog("timodrproc: Got T_CAPABILITY_ACK\n", 0); 1322 1323 PI_PROVLOCK(tp->tim_provinfo); 1324 if (tp->tim_provinfo->tpi_capability != PI_YES) 1325 tp->tim_provinfo->tpi_capability = PI_YES; 1326 PI_PROVUNLOCK(tp->tim_provinfo); 1327 1328 /* Reset possible pending timeout */ 1329 if (tp->tim_tcap_timoutid != 0) { 1330 (void) quntimeout(q, tp->tim_tcap_timoutid); 1331 tp->tim_tcap_timoutid = 0; 1332 } 1333 1334 tca = (struct T_capability_ack *)mp->b_rptr; 1335 1336 if (tca->CAP_bits1 & TC1_INFO) 1337 timodprocessinfo(q, tp, &tca->INFO_ack); 1338 1339 tim_send_reply(q, mp, tp, T_CAPABILITY_REQ); 1340 } 1341 break; 1342 } 1343 break; 1344 1345 /* ONC_PLUS EXTRACT START */ 1346 case M_FLUSH: 1347 1348 tilog("timodrproc: Got M_FLUSH\n", 0); 1349 1350 if (*mp->b_rptr & FLUSHR) { 1351 if (*mp->b_rptr & FLUSHBAND) 1352 flushband(q, *(mp->b_rptr + 1), FLUSHDATA); 1353 else 1354 flushq(q, FLUSHDATA); 1355 } 1356 putnext(q, mp); 1357 break; 1358 /* ONC_PLUS EXTRACT END */ 1359 1360 case M_IOCACK: 1361 iocbp = (struct iocblk *)mp->b_rptr; 1362 1363 tilog("timodrproc: Got M_IOCACK\n", 0); 1364 1365 if (iocbp->ioc_cmd == TI_GETMYNAME) { 1366 1367 /* 1368 * Transport provider supports this ioctl, 1369 * so I don't have to. 1370 */ 1371 if ((tp->tim_flags & DO_MYNAME) != 0) { 1372 tp->tim_flags &= ~DO_MYNAME; 1373 PI_PROVLOCK(tp->tim_provinfo); 1374 tp->tim_provinfo->tpi_myname = PI_YES; 1375 PI_PROVUNLOCK(tp->tim_provinfo); 1376 } 1377 1378 ASSERT(tp->tim_mymaxlen >= 0); 1379 if (tp->tim_mymaxlen != 0) { 1380 kmem_free(tp->tim_myname, (size_t)tp->tim_mymaxlen); 1381 tp->tim_myname = NULL; 1382 tp->tim_mymaxlen = 0; 1383 } 1384 /* tim_iocsave may already be overwritten. */ 1385 if (tp->tim_saved_prim == -1) { 1386 freemsg(tp->tim_iocsave); 1387 tp->tim_iocsave = NULL; 1388 } 1389 } else if (iocbp->ioc_cmd == TI_GETPEERNAME) { 1390 boolean_t clearit; 1391 1392 /* 1393 * Transport provider supports this ioctl, 1394 * so I don't have to. 1395 */ 1396 if ((tp->tim_flags & DO_PEERNAME) != 0) { 1397 tp->tim_flags &= ~DO_PEERNAME; 1398 PI_PROVLOCK(tp->tim_provinfo); 1399 tp->tim_provinfo->tpi_peername = PI_YES; 1400 PI_PROVUNLOCK(tp->tim_provinfo); 1401 } 1402 1403 mutex_enter(&tp->tim_mutex); 1404 ASSERT(tp->tim_peermaxlen >= 0); 1405 clearit = tp->tim_peermaxlen != 0; 1406 if (clearit) { 1407 kmem_free(tp->tim_peername, tp->tim_peermaxlen); 1408 tp->tim_peername = NULL; 1409 tp->tim_peermaxlen = 0; 1410 tp->tim_peerlen = 0; 1411 } 1412 mutex_exit(&tp->tim_mutex); 1413 if (clearit) { 1414 mblk_t *bp; 1415 1416 bp = tp->tim_consave; 1417 while (bp != NULL) { 1418 nbp = bp->b_next; 1419 bp->b_next = NULL; 1420 freemsg(bp); 1421 bp = nbp; 1422 } 1423 tp->tim_consave = NULL; 1424 } 1425 /* tim_iocsave may already be overwritten. */ 1426 if (tp->tim_saved_prim == -1) { 1427 freemsg(tp->tim_iocsave); 1428 tp->tim_iocsave = NULL; 1429 } 1430 } 1431 putnext(q, mp); 1432 break; 1433 1434 /* ONC_PLUS EXTRACT START */ 1435 case M_IOCNAK: 1436 1437 tilog("timodrproc: Got M_IOCNAK\n", 0); 1438 1439 iocbp = (struct iocblk *)mp->b_rptr; 1440 if (((iocbp->ioc_cmd == TI_GETMYNAME) || 1441 (iocbp->ioc_cmd == TI_GETPEERNAME)) && 1442 ((iocbp->ioc_error == EINVAL) || (iocbp->ioc_error == 0))) { 1443 PI_PROVLOCK(tp->tim_provinfo); 1444 if (iocbp->ioc_cmd == TI_GETMYNAME) { 1445 if (tp->tim_provinfo->tpi_myname == PI_DONTKNOW) 1446 tp->tim_provinfo->tpi_myname = PI_NO; 1447 } else if (iocbp->ioc_cmd == TI_GETPEERNAME) { 1448 if (tp->tim_provinfo->tpi_peername == PI_DONTKNOW) 1449 tp->tim_provinfo->tpi_peername = PI_NO; 1450 } 1451 PI_PROVUNLOCK(tp->tim_provinfo); 1452 /* tim_iocsave may already be overwritten. */ 1453 if ((tp->tim_iocsave != NULL) && 1454 (tp->tim_saved_prim == -1)) { 1455 freemsg(mp); 1456 mp = tp->tim_iocsave; 1457 tp->tim_iocsave = NULL; 1458 tp->tim_flags |= NAMEPROC; 1459 if (ti_doname(WR(q), mp) != DONAME_CONT) { 1460 tp->tim_flags &= ~NAMEPROC; 1461 } 1462 break; 1463 } 1464 } 1465 putnext(q, mp); 1466 break; 1467 /* ONC_PLUS EXTRACT END */ 1468 } 1469 1470 return (0); 1471 } 1472 1473 /* ONC_PLUS EXTRACT START */ 1474 /* 1475 * timodwput - Module write put procedure. This is called from 1476 * the module, driver, or stream head upstream/downstream. 1477 * Handles M_FLUSH, M_DATA and some M_PROTO (T_DATA_REQ, 1478 * and T_UNITDATA_REQ) messages. All others are queued to 1479 * be handled by the service procedures. 1480 */ 1481 1482 static void 1483 timodwput(queue_t *q, mblk_t *mp) 1484 { 1485 union T_primitives *pptr; 1486 struct tim_tim *tp; 1487 struct iocblk *iocbp; 1488 1489 /* 1490 * Enqueue normal-priority messages if our queue already 1491 * holds some messages for deferred processing but don't 1492 * enqueue those M_IOCTLs which will result in an 1493 * M_PCPROTO (ie, high priority) message being created. 1494 */ 1495 /* ONC_PLUS EXTRACT END */ 1496 if (q->q_first != 0 && mp->b_datap->db_type < QPCTL) { 1497 if (mp->b_datap->db_type == M_IOCTL) { 1498 iocbp = (struct iocblk *)mp->b_rptr; 1499 switch (iocbp->ioc_cmd) { 1500 default: 1501 (void) putq(q, mp); 1502 return; 1503 1504 case TI_GETINFO: 1505 case TI_SYNC: 1506 case TI_CAPABILITY: 1507 break; 1508 } 1509 } else { 1510 (void) putq(q, mp); 1511 return; 1512 } 1513 } 1514 /* ONC_PLUS EXTRACT START */ 1515 /* 1516 * Inline processing of data (to avoid additional procedure call). 1517 * Rest is handled in timodwproc. 1518 */ 1519 1520 switch (mp->b_datap->db_type) { 1521 case M_DATA: 1522 tp = (struct tim_tim *)q->q_ptr; 1523 ASSERT(tp); 1524 if (tp->tim_flags & CLTS) { 1525 mblk_t *tmp; 1526 1527 if ((tmp = tim_filladdr(q, mp, B_FALSE)) == NULL) { 1528 (void) putq(q, mp); 1529 break; 1530 } else { 1531 mp = tmp; 1532 } 1533 } 1534 if (bcanputnext(q, mp->b_band)) 1535 putnext(q, mp); 1536 else 1537 (void) putq(q, mp); 1538 break; 1539 case M_PROTO: 1540 case M_PCPROTO: 1541 pptr = (union T_primitives *)mp->b_rptr; 1542 switch (pptr->type) { 1543 /* ONC_PLUS EXTRACT END */ 1544 case T_UNITDATA_REQ: 1545 tp = (struct tim_tim *)q->q_ptr; 1546 ASSERT(tp); 1547 if (tp->tim_flags & CLTS) { 1548 mblk_t *tmp; 1549 1550 tmp = tim_filladdr(q, mp, B_FALSE); 1551 if (tmp == NULL) { 1552 (void) putq(q, mp); 1553 break; 1554 } else { 1555 mp = tmp; 1556 } 1557 } 1558 if (bcanputnext(q, mp->b_band)) 1559 putnext(q, mp); 1560 else 1561 (void) putq(q, mp); 1562 break; 1563 1564 case T_DATA_REQ: 1565 case T_EXDATA_REQ: 1566 if (bcanputnext(q, mp->b_band)) 1567 putnext(q, mp); 1568 else 1569 (void) putq(q, mp); 1570 break; 1571 default: 1572 (void) timodwproc(q, mp); 1573 break; 1574 } 1575 break; 1576 /* ONC_PLUS EXTRACT START */ 1577 default: 1578 (void) timodwproc(q, mp); 1579 break; 1580 } 1581 } 1582 /* 1583 * timodwsrv - Module write queue service procedure. 1584 * This is called when messages are placed on an empty queue, 1585 * when high priority messages are placed on the queue, and 1586 * when flow control restrictions subside. This code used to 1587 * be included in a put procedure, but it was moved to a 1588 * service procedure because several points were added where 1589 * memory allocation could fail, and there is no reasonable 1590 * recovery mechanism from the put procedure. 1591 */ 1592 static void 1593 timodwsrv(queue_t *q) 1594 { 1595 mblk_t *mp; 1596 1597 ASSERT(q != NULL); 1598 if (q->q_ptr == NULL) 1599 return; 1600 1601 while ((mp = getq(q)) != NULL) { 1602 if (timodwproc(q, mp)) { 1603 /* 1604 * timodwproc did a putbq - stop processing 1605 * messages. 1606 */ 1607 return; 1608 } 1609 } 1610 } 1611 1612 /* 1613 * Common routine to process write side messages 1614 */ 1615 1616 static int 1617 timodwproc(queue_t *q, mblk_t *mp) 1618 { 1619 union T_primitives *pptr; 1620 struct tim_tim *tp; 1621 mblk_t *tmp; 1622 struct iocblk *iocbp; 1623 int error; 1624 1625 tp = (struct tim_tim *)q->q_ptr; 1626 1627 switch (mp->b_datap->db_type) { 1628 default: 1629 putnext(q, mp); 1630 break; 1631 /* ONC_PLUS EXTRACT END */ 1632 1633 case M_DATA: 1634 if (tp->tim_flags & CLTS) { 1635 if ((tmp = tim_filladdr(q, mp, B_TRUE)) == NULL) { 1636 return (1); 1637 } else { 1638 mp = tmp; 1639 } 1640 } 1641 if (!bcanputnext(q, mp->b_band)) { 1642 (void) putbq(q, mp); 1643 return (1); 1644 } 1645 putnext(q, mp); 1646 break; 1647 1648 /* ONC_PLUS EXTRACT START */ 1649 case M_IOCTL: 1650 1651 iocbp = (struct iocblk *)mp->b_rptr; 1652 TILOG("timodwproc: Got M_IOCTL(%d)\n", iocbp->ioc_cmd); 1653 1654 ASSERT(MBLKL(mp) == sizeof (struct iocblk)); 1655 1656 /* 1657 * TPI requires we await response to a previously sent message 1658 * before handling another, put it back on the head of queue. 1659 * Since putbq() may see QWANTR unset when called from the 1660 * service procedure, the queue must be explicitly scheduled 1661 * for service, as no backenable will occur for this case. 1662 * tim_ioctl_retry() sets a timer to handle the qenable. 1663 */ 1664 if (tp->tim_flags & WAITIOCACK) { 1665 TILOG("timodwproc: putbq M_IOCTL(%d)\n", 1666 iocbp->ioc_cmd); 1667 (void) putbq(q, mp); 1668 /* Called from timodwsrv() and messages on queue */ 1669 if (!(q->q_flag & QWANTR)) 1670 tim_ioctl_retry(q); 1671 return (1); 1672 } 1673 /* ONC_PLUS EXTRACT END */ 1674 1675 switch (iocbp->ioc_cmd) { 1676 default: 1677 putnext(q, mp); 1678 break; 1679 1680 case _I_GETPEERCRED: 1681 if ((tp->tim_flags & COTS) == 0) { 1682 miocnak(q, mp, 0, ENOTSUP); 1683 } else { 1684 mblk_t *cmp = mp->b_cont; 1685 k_peercred_t *kp = NULL; 1686 1687 mutex_enter(&tp->tim_mutex); 1688 if (cmp != NULL && 1689 iocbp->ioc_flag == IOC_NATIVE && 1690 (tp->tim_flags & 1691 (CONNWAIT|LOCORDREL|REMORDREL)) == 0 && 1692 tp->tim_peercred != NULL && 1693 DB_TYPE(cmp) == M_DATA && 1694 MBLKL(cmp) == sizeof (k_peercred_t)) { 1695 kp = (k_peercred_t *)cmp->b_rptr; 1696 crhold(kp->pc_cr = tp->tim_peercred); 1697 kp->pc_cpid = tp->tim_cpid; 1698 } 1699 mutex_exit(&tp->tim_mutex); 1700 if (kp != NULL) 1701 miocack(q, mp, sizeof (*kp), 0); 1702 else 1703 miocnak(q, mp, 0, ENOTCONN); 1704 } 1705 break; 1706 case TI_BIND: 1707 case TI_UNBIND: 1708 case TI_OPTMGMT: 1709 case TI_GETADDRS: 1710 TILOG("timodwproc: TI_{BIND|UNBIND|OPTMGMT|GETADDRS}" 1711 "\n", 0); 1712 1713 /* 1714 * We know that tim_send_ioctl_tpi_msg() is only 1715 * going to examine the `type' field, so we only 1716 * check that we can access that much data. 1717 */ 1718 error = miocpullup(mp, sizeof (t_scalar_t)); 1719 if (error != 0) { 1720 miocnak(q, mp, 0, error); 1721 break; 1722 } 1723 tim_send_ioctl_tpi_msg(q, mp, tp, iocbp); 1724 break; 1725 1726 case TI_GETINFO: 1727 TILOG("timodwproc: TI_GETINFO\n", 0); 1728 error = miocpullup(mp, sizeof (struct T_info_req)); 1729 if (error != 0) { 1730 miocnak(q, mp, 0, error); 1731 break; 1732 } 1733 tp->tim_flags |= WAIT_IOCINFOACK; 1734 tim_send_ioctl_tpi_msg(q, mp, tp, iocbp); 1735 break; 1736 1737 case TI_SYNC: { 1738 mblk_t *tsr_mp; 1739 struct ti_sync_req *tsr; 1740 uint32_t tsr_flags; 1741 1742 error = miocpullup(mp, sizeof (struct ti_sync_req)); 1743 if (error != 0) { 1744 miocnak(q, mp, 0, error); 1745 break; 1746 } 1747 1748 tsr_mp = mp->b_cont; 1749 tsr = (struct ti_sync_req *)tsr_mp->b_rptr; 1750 TILOG("timodwproc: TI_SYNC(%x)\n", tsr->tsr_flags); 1751 1752 /* 1753 * Save out the value of tsr_flags, in case we 1754 * reallocb() tsr_mp (below). 1755 */ 1756 tsr_flags = tsr->tsr_flags; 1757 if ((tsr_flags & TSRF_INFO_REQ) == 0) { 1758 mblk_t *ack_mp = reallocb(tsr_mp, 1759 sizeof (struct ti_sync_ack), 0); 1760 1761 /* Can reply immediately. */ 1762 mp->b_cont = NULL; 1763 if (ack_mp == NULL) { 1764 tilog("timodwproc: allocb failed no " 1765 "recovery attempt\n", 0); 1766 freemsg(tsr_mp); 1767 miocnak(q, mp, 0, ENOMEM); 1768 } else { 1769 tim_answer_ti_sync(q, mp, tp, 1770 ack_mp, tsr_flags); 1771 } 1772 break; 1773 } 1774 1775 /* 1776 * This code is retained for compatibility with 1777 * old statically linked applications. New code 1778 * should use TI_CAPABILITY for all TPI 1779 * information and should not use TSRF_INFO_REQ 1780 * flag. 1781 * 1782 * defer processsing necessary to rput procedure 1783 * as we need to get information from transport 1784 * driver. Set flags that will tell the read 1785 * side the work needed on this request. 1786 */ 1787 1788 if (tsr_flags & TSRF_IS_EXP_IN_RCVBUF) 1789 tp->tim_flags |= PEEK_RDQ_EXPIND; 1790 1791 /* 1792 * Convert message to a T_INFO_REQ message; relies 1793 * on sizeof (struct ti_sync_req) >= sizeof (struct 1794 * T_info_req)). 1795 */ 1796 ASSERT(MBLKL(tsr_mp) >= sizeof (struct T_info_req)); 1797 1798 ((struct T_info_req *)tsr_mp->b_rptr)->PRIM_type = 1799 T_INFO_REQ; 1800 tsr_mp->b_wptr = tsr_mp->b_rptr + 1801 sizeof (struct T_info_req); 1802 tp->tim_flags |= WAIT_IOCINFOACK; 1803 tim_send_ioctl_tpi_msg(q, mp, tp, iocbp); 1804 } 1805 break; 1806 1807 case TI_CAPABILITY: { 1808 mblk_t *tcsr_mp; 1809 struct T_capability_req *tcr; 1810 1811 error = miocpullup(mp, sizeof (*tcr)); 1812 if (error != 0) { 1813 miocnak(q, mp, 0, error); 1814 break; 1815 } 1816 1817 tcsr_mp = mp->b_cont; 1818 tcr = (struct T_capability_req *)tcsr_mp->b_rptr; 1819 TILOG("timodwproc: TI_CAPABILITY(CAP_bits1 = %x)\n", 1820 tcr->CAP_bits1); 1821 1822 if (tcr->PRIM_type != T_CAPABILITY_REQ) { 1823 TILOG("timodwproc: invalid msg type %d\n", 1824 tcr->PRIM_type); 1825 miocnak(q, mp, 0, EPROTO); 1826 break; 1827 } 1828 1829 switch (tp->tim_provinfo->tpi_capability) { 1830 case PI_YES: 1831 /* Just send T_CAPABILITY_REQ down */ 1832 tim_send_ioctl_tpi_msg(q, mp, tp, iocbp); 1833 break; 1834 1835 case PI_DONTKNOW: 1836 /* 1837 * It is unknown yet whether transport provides 1838 * T_CAPABILITY_REQ or not. Send message down 1839 * and wait for reply. 1840 */ 1841 1842 ASSERT(tp->tim_tcap_timoutid == 0); 1843 if ((tcr->CAP_bits1 & TC1_INFO) == 0) { 1844 tp->tim_flags |= TI_CAP_RECVD; 1845 } else { 1846 tp->tim_flags |= (TI_CAP_RECVD | 1847 CAP_WANTS_INFO); 1848 } 1849 1850 tp->tim_tcap_timoutid = qtimeout(q, 1851 tim_tcap_timer, q, tim_tcap_wait * hz); 1852 tim_send_ioctl_tpi_msg(q, mp, tp, iocbp); 1853 break; 1854 1855 case PI_NO: 1856 /* 1857 * Transport doesn't support T_CAPABILITY_REQ. 1858 * Either reply immediately or send T_INFO_REQ 1859 * if needed. 1860 */ 1861 if ((tcr->CAP_bits1 & TC1_INFO) != 0) { 1862 tp->tim_flags |= (TI_CAP_RECVD | 1863 CAP_WANTS_INFO | WAIT_IOCINFOACK); 1864 TILOG("timodwproc: sending down " 1865 "T_INFO_REQ, flags = %x\n", 1866 tp->tim_flags); 1867 1868 /* 1869 * Generate T_INFO_REQ message and send 1870 * it down 1871 */ 1872 ((struct T_info_req *)tcsr_mp->b_rptr)-> 1873 PRIM_type = T_INFO_REQ; 1874 tcsr_mp->b_wptr = tcsr_mp->b_rptr + 1875 sizeof (struct T_info_req); 1876 tim_send_ioctl_tpi_msg(q, mp, tp, 1877 iocbp); 1878 break; 1879 } 1880 1881 1882 /* 1883 * Can reply immediately. Just send back 1884 * T_CAPABILITY_ACK with CAP_bits1 set to 0. 1885 */ 1886 mp->b_cont = tcsr_mp = tpi_ack_alloc(mp->b_cont, 1887 sizeof (struct T_capability_ack), M_PCPROTO, 1888 T_CAPABILITY_ACK); 1889 1890 if (tcsr_mp == NULL) { 1891 tilog("timodwproc: allocb failed no " 1892 "recovery attempt\n", 0); 1893 miocnak(q, mp, 0, ENOMEM); 1894 break; 1895 } 1896 1897 tp->tim_flags &= ~(WAITIOCACK | TI_CAP_RECVD | 1898 WAIT_IOCINFOACK | CAP_WANTS_INFO); 1899 ((struct T_capability_ack *) 1900 tcsr_mp->b_rptr)->CAP_bits1 = 0; 1901 tim_ioctl_send_reply(q, mp, tcsr_mp); 1902 1903 /* 1904 * It could happen when timod is awaiting ack 1905 * for TI_GETPEERNAME/TI_GETMYNAME. 1906 */ 1907 if (tp->tim_iocsave != NULL) { 1908 freemsg(tp->tim_iocsave); 1909 tp->tim_iocsave = NULL; 1910 tp->tim_saved_prim = -1; 1911 } 1912 break; 1913 1914 default: 1915 cmn_err(CE_PANIC, 1916 "timodwproc: unknown tpi_capability value " 1917 "%d\n", tp->tim_provinfo->tpi_capability); 1918 break; 1919 } 1920 } 1921 break; 1922 1923 /* ONC_PLUS EXTRACT START */ 1924 case TI_GETMYNAME: 1925 1926 tilog("timodwproc: Got TI_GETMYNAME\n", 0); 1927 1928 if (tp->tim_provinfo->tpi_myname == PI_YES) { 1929 putnext(q, mp); 1930 break; 1931 } 1932 goto getname; 1933 1934 case TI_GETPEERNAME: 1935 1936 tilog("timodwproc: Got TI_GETPEERNAME\n", 0); 1937 1938 if (tp->tim_provinfo->tpi_peername == PI_YES) { 1939 putnext(q, mp); 1940 break; 1941 } 1942 getname: 1943 if ((tmp = copymsg(mp)) == NULL) { 1944 tim_recover(q, mp, msgsize(mp)); 1945 return (1); 1946 } 1947 /* 1948 * tim_iocsave may be non-NULL when timod is awaiting 1949 * ack for another TI_GETPEERNAME/TI_GETMYNAME. 1950 */ 1951 freemsg(tp->tim_iocsave); 1952 tp->tim_iocsave = mp; 1953 tp->tim_saved_prim = -1; 1954 putnext(q, tmp); 1955 break; 1956 } 1957 break; 1958 1959 case M_IOCDATA: 1960 1961 if (tp->tim_flags & NAMEPROC) { 1962 if (ti_doname(q, mp) != DONAME_CONT) { 1963 tp->tim_flags &= ~NAMEPROC; 1964 } 1965 } else 1966 putnext(q, mp); 1967 break; 1968 1969 case M_PROTO: 1970 case M_PCPROTO: 1971 if (MBLKL(mp) < sizeof (t_scalar_t)) { 1972 merror(q, mp, EPROTO); 1973 return (1); 1974 } 1975 1976 pptr = (union T_primitives *)mp->b_rptr; 1977 switch (pptr->type) { 1978 default: 1979 putnext(q, mp); 1980 break; 1981 1982 case T_EXDATA_REQ: 1983 case T_DATA_REQ: 1984 if (pptr->type == T_EXDATA_REQ) 1985 tilog("timodwproc: Got T_EXDATA_REQ\n", 0); 1986 1987 if (!bcanputnext(q, mp->b_band)) { 1988 (void) putbq(q, mp); 1989 return (1); 1990 } 1991 putnext(q, mp); 1992 break; 1993 /* ONC_PLUS EXTRACT END */ 1994 1995 case T_UNITDATA_REQ: 1996 if (tp->tim_flags & CLTS) { 1997 tmp = tim_filladdr(q, mp, B_TRUE); 1998 if (tmp == NULL) { 1999 return (1); 2000 } else { 2001 mp = tmp; 2002 } 2003 } 2004 if (audit_active) 2005 audit_sock(T_UNITDATA_REQ, q, mp, TIMOD_ID); 2006 if (!bcanputnext(q, mp->b_band)) { 2007 (void) putbq(q, mp); 2008 return (1); 2009 } 2010 putnext(q, mp); 2011 break; 2012 2013 /* ONC_PLUS EXTRACT START */ 2014 case T_CONN_REQ: { 2015 struct T_conn_req *reqp = (struct T_conn_req *) 2016 mp->b_rptr; 2017 void *p; 2018 2019 tilog("timodwproc: Got T_CONN_REQ\n", 0); 2020 2021 if (MBLKL(mp) < sizeof (struct T_conn_req)) { 2022 merror(q, mp, EPROTO); 2023 return (1); 2024 } 2025 2026 if (tp->tim_flags & DO_PEERNAME) { 2027 if (!MBLKIN(mp, reqp->DEST_offset, 2028 reqp->DEST_length)) { 2029 merror(q, mp, EPROTO); 2030 return (1); 2031 } 2032 ASSERT(reqp->DEST_length >= 0); 2033 mutex_enter(&tp->tim_mutex); 2034 if (reqp->DEST_length > tp->tim_peermaxlen) { 2035 p = kmem_alloc(reqp->DEST_length, 2036 KM_NOSLEEP); 2037 if (p == NULL) { 2038 mutex_exit(&tp->tim_mutex); 2039 tilog("timodwproc: kmem_alloc " 2040 "failed, attempting " 2041 "recovery\n", 0); 2042 tim_recover(q, mp, 2043 reqp->DEST_length); 2044 return (1); 2045 } 2046 if (tp->tim_peermaxlen) 2047 kmem_free(tp->tim_peername, 2048 tp->tim_peermaxlen); 2049 tp->tim_peername = p; 2050 tp->tim_peermaxlen = reqp->DEST_length; 2051 } 2052 tp->tim_peerlen = reqp->DEST_length; 2053 p = mp->b_rptr + reqp->DEST_offset; 2054 bcopy(p, tp->tim_peername, tp->tim_peerlen); 2055 mutex_exit(&tp->tim_mutex); 2056 } 2057 if (tp->tim_flags & COTS) 2058 tp->tim_flags |= CONNWAIT; 2059 /* ONC_PLUS EXTRACT END */ 2060 if (audit_active) 2061 audit_sock(T_CONN_REQ, q, mp, TIMOD_ID); 2062 /* ONC_PLUS EXTRACT START */ 2063 putnext(q, mp); 2064 break; 2065 } 2066 2067 case O_T_CONN_RES: 2068 case T_CONN_RES: { 2069 struct T_conn_res *resp; 2070 struct T_conn_ind *indp; 2071 mblk_t *pmp = NULL; 2072 mblk_t *nbp; 2073 2074 if (MBLKL(mp) < sizeof (struct T_conn_res) || 2075 (tp->tim_flags & WAITIOCACK)) { 2076 merror(q, mp, EPROTO); 2077 return (1); 2078 } 2079 2080 resp = (struct T_conn_res *)mp->b_rptr; 2081 for (tmp = tp->tim_consave; tmp != NULL; 2082 tmp = tmp->b_next) { 2083 indp = (struct T_conn_ind *)tmp->b_rptr; 2084 if (indp->SEQ_number == resp->SEQ_number) 2085 break; 2086 pmp = tmp; 2087 } 2088 if (tmp == NULL) 2089 goto cresout; 2090 2091 if ((nbp = dupb(mp)) == NULL && 2092 (nbp = copyb(mp)) == NULL) { 2093 tim_recover(q, mp, msgsize(mp)); 2094 return (1); 2095 } 2096 2097 if (pmp != NULL) 2098 pmp->b_next = tmp->b_next; 2099 else 2100 tp->tim_consave = tmp->b_next; 2101 tmp->b_next = NULL; 2102 2103 /* 2104 * Construct a list with: 2105 * nbp - copy of user's original request 2106 * tmp - the extracted T_conn_ind 2107 */ 2108 nbp->b_cont = tmp; 2109 /* 2110 * tim_iocsave may be non-NULL when timod is awaiting 2111 * ack for TI_GETPEERNAME/TI_GETMYNAME. 2112 */ 2113 freemsg(tp->tim_iocsave); 2114 tp->tim_iocsave = nbp; 2115 tp->tim_saved_prim = pptr->type; 2116 tp->tim_flags |= WAIT_CONNRESACK | WAITIOCACK; 2117 2118 cresout: 2119 putnext(q, mp); 2120 break; 2121 } 2122 2123 /* ONC_PLUS EXTRACT END */ 2124 case T_DISCON_REQ: { 2125 struct T_discon_req *disp; 2126 struct T_conn_ind *conp; 2127 mblk_t *pmp = NULL; 2128 2129 if (MBLKL(mp) < sizeof (struct T_discon_req)) { 2130 merror(q, mp, EPROTO); 2131 return (1); 2132 } 2133 2134 disp = (struct T_discon_req *)mp->b_rptr; 2135 tp->tim_flags &= ~(CONNWAIT|LOCORDREL|REMORDREL); 2136 tim_clear_peer(tp); 2137 2138 /* 2139 * If we are already connected, there won't 2140 * be any messages on tim_consave. 2141 */ 2142 for (tmp = tp->tim_consave; tmp; tmp = tmp->b_next) { 2143 conp = (struct T_conn_ind *)tmp->b_rptr; 2144 if (conp->SEQ_number == disp->SEQ_number) 2145 break; 2146 pmp = tmp; 2147 } 2148 if (tmp) { 2149 if (pmp) 2150 pmp->b_next = tmp->b_next; 2151 else 2152 tp->tim_consave = tmp->b_next; 2153 tmp->b_next = NULL; 2154 freemsg(tmp); 2155 } 2156 putnext(q, mp); 2157 break; 2158 } 2159 2160 case T_ORDREL_REQ: 2161 if (tp->tim_flags & REMORDREL) { 2162 tp->tim_flags &= ~(LOCORDREL|REMORDREL); 2163 tim_clear_peer(tp); 2164 } else { 2165 tp->tim_flags |= LOCORDREL; 2166 } 2167 putnext(q, mp); 2168 break; 2169 2170 case T_CAPABILITY_REQ: 2171 tilog("timodwproc: Got T_CAPABILITY_REQ\n", 0); 2172 /* 2173 * XXX: We may know at this point whether transport 2174 * provides T_CAPABILITY_REQ or not and we may utilise 2175 * this knowledge here. 2176 */ 2177 putnext(q, mp); 2178 break; 2179 /* ONC_PLUS EXTRACT START */ 2180 } 2181 break; 2182 case M_FLUSH: 2183 2184 tilog("timodwproc: Got M_FLUSH\n", 0); 2185 2186 if (*mp->b_rptr & FLUSHW) { 2187 if (*mp->b_rptr & FLUSHBAND) 2188 flushband(q, *(mp->b_rptr + 1), FLUSHDATA); 2189 else 2190 flushq(q, FLUSHDATA); 2191 } 2192 putnext(q, mp); 2193 break; 2194 } 2195 2196 return (0); 2197 } 2198 2199 static void 2200 tilog(char *str, t_scalar_t arg) 2201 { 2202 if (dotilog) { 2203 if (dotilog & 2) 2204 cmn_err(CE_CONT, str, arg); 2205 if (dotilog & 4) 2206 (void) strlog(TIMOD_ID, -1, 0, SL_TRACE | SL_ERROR, 2207 str, arg); 2208 else 2209 (void) strlog(TIMOD_ID, -1, 0, SL_TRACE, str, arg); 2210 } 2211 } 2212 2213 static void 2214 tilogp(char *str, uintptr_t arg) 2215 { 2216 if (dotilog) { 2217 if (dotilog & 2) 2218 cmn_err(CE_CONT, str, arg); 2219 if (dotilog & 4) 2220 (void) strlog(TIMOD_ID, -1, 0, SL_TRACE | SL_ERROR, 2221 str, arg); 2222 else 2223 (void) strlog(TIMOD_ID, -1, 0, SL_TRACE, str, arg); 2224 } 2225 } 2226 2227 2228 /* 2229 * Process the TI_GETNAME ioctl. If no name exists, return len = 0 2230 * in strbuf structures. The state transitions are determined by what 2231 * is hung of cq_private (cp_private) in the copyresp (copyreq) structure. 2232 * The high-level steps in the ioctl processing are as follows: 2233 * 2234 * 1) we recieve an transparent M_IOCTL with the arg in the second message 2235 * block of the message. 2236 * 2) we send up an M_COPYIN request for the strbuf structure pointed to 2237 * by arg. The block containing arg is hung off cq_private. 2238 * 3) we receive an M_IOCDATA response with cp->cp_private->b_cont == NULL. 2239 * This means that the strbuf structure is found in the message block 2240 * mp->b_cont. 2241 * 4) we send up an M_COPYOUT request with the strbuf message hung off 2242 * cq_private->b_cont. The address we are copying to is strbuf.buf. 2243 * we set strbuf.len to 0 to indicate that we should copy the strbuf 2244 * structure the next time. The message mp->b_cont contains the 2245 * address info. 2246 * 5) we receive an M_IOCDATA with cp_private->b_cont != NULL and 2247 * strbuf.len == 0. Restore strbuf.len to either tp->tim_mylen or 2248 * tp->tim_peerlen. 2249 * 6) we send up an M_COPYOUT request with a copy of the strbuf message 2250 * hung off mp->b_cont. In the strbuf structure in the message hung 2251 * off cq_private->b_cont, we set strbuf.len to 0 and strbuf.maxlen 2252 * to 0. This means that the next step is to ACK the ioctl. 2253 * 7) we receive an M_IOCDATA message with cp_private->b_cont != NULL and 2254 * strbuf.len == 0 and strbuf.maxlen == 0. Free up cp->private and 2255 * send an M_IOCACK upstream, and we are done. 2256 * 2257 */ 2258 static int 2259 ti_doname( 2260 queue_t *q, /* queue message arrived at */ 2261 mblk_t *mp) /* M_IOCTL or M_IOCDATA message only */ 2262 { 2263 struct iocblk *iocp; 2264 struct copyreq *cqp; 2265 STRUCT_HANDLE(strbuf, sb); 2266 struct copyresp *csp; 2267 int ret; 2268 mblk_t *bp; 2269 struct tim_tim *tp = q->q_ptr; 2270 boolean_t getpeer; 2271 2272 switch (mp->b_datap->db_type) { 2273 case M_IOCTL: 2274 iocp = (struct iocblk *)mp->b_rptr; 2275 if ((iocp->ioc_cmd != TI_GETMYNAME) && 2276 (iocp->ioc_cmd != TI_GETPEERNAME)) { 2277 tilog("ti_doname: bad M_IOCTL command\n", 0); 2278 miocnak(q, mp, 0, EINVAL); 2279 ret = DONAME_FAIL; 2280 break; 2281 } 2282 if ((iocp->ioc_count != TRANSPARENT)) { 2283 miocnak(q, mp, 0, EINVAL); 2284 ret = DONAME_FAIL; 2285 break; 2286 } 2287 2288 cqp = (struct copyreq *)mp->b_rptr; 2289 cqp->cq_private = mp->b_cont; 2290 cqp->cq_addr = (caddr_t)*(intptr_t *)mp->b_cont->b_rptr; 2291 mp->b_cont = NULL; 2292 cqp->cq_size = SIZEOF_STRUCT(strbuf, iocp->ioc_flag); 2293 cqp->cq_flag = 0; 2294 mp->b_datap->db_type = M_COPYIN; 2295 mp->b_wptr = mp->b_rptr + sizeof (struct copyreq); 2296 qreply(q, mp); 2297 ret = DONAME_CONT; 2298 break; 2299 2300 case M_IOCDATA: 2301 csp = (struct copyresp *)mp->b_rptr; 2302 iocp = (struct iocblk *)mp->b_rptr; 2303 cqp = (struct copyreq *)mp->b_rptr; 2304 if ((csp->cp_cmd != TI_GETMYNAME) && 2305 (csp->cp_cmd != TI_GETPEERNAME)) { 2306 cmn_err(CE_WARN, "ti_doname: bad M_IOCDATA command\n"); 2307 miocnak(q, mp, 0, EINVAL); 2308 ret = DONAME_FAIL; 2309 break; 2310 } 2311 if (csp->cp_rval) { /* error */ 2312 freemsg(csp->cp_private); 2313 freemsg(mp); 2314 ret = DONAME_FAIL; 2315 break; 2316 } 2317 ASSERT(csp->cp_private != NULL); 2318 getpeer = csp->cp_cmd == TI_GETPEERNAME; 2319 if (getpeer) 2320 mutex_enter(&tp->tim_mutex); 2321 if (csp->cp_private->b_cont == NULL) { /* got strbuf */ 2322 ASSERT(mp->b_cont); 2323 STRUCT_SET_HANDLE(sb, iocp->ioc_flag, 2324 (void *)mp->b_cont->b_rptr); 2325 if (getpeer) { 2326 if (tp->tim_peerlen == 0) { 2327 /* copy just strbuf */ 2328 STRUCT_FSET(sb, len, 0); 2329 } else if (tp->tim_peerlen > 2330 STRUCT_FGET(sb, maxlen)) { 2331 mutex_exit(&tp->tim_mutex); 2332 miocnak(q, mp, 0, ENAMETOOLONG); 2333 ret = DONAME_FAIL; 2334 break; 2335 } else { 2336 /* copy buffer */ 2337 STRUCT_FSET(sb, len, tp->tim_peerlen); 2338 } 2339 } else { 2340 if (tp->tim_mylen == 0) { 2341 /* copy just strbuf */ 2342 STRUCT_FSET(sb, len, 0); 2343 } else if (tp->tim_mylen > 2344 STRUCT_FGET(sb, maxlen)) { 2345 freemsg(csp->cp_private); 2346 miocnak(q, mp, 0, ENAMETOOLONG); 2347 ret = DONAME_FAIL; 2348 break; 2349 } else { 2350 /* copy buffer */ 2351 STRUCT_FSET(sb, len, tp->tim_mylen); 2352 } 2353 } 2354 csp->cp_private->b_cont = mp->b_cont; 2355 mp->b_cont = NULL; 2356 } 2357 STRUCT_SET_HANDLE(sb, iocp->ioc_flag, 2358 (void *)csp->cp_private->b_cont->b_rptr); 2359 if (STRUCT_FGET(sb, len) == 0) { 2360 /* 2361 * restore strbuf.len 2362 */ 2363 if (getpeer) 2364 STRUCT_FSET(sb, len, tp->tim_peerlen); 2365 else 2366 STRUCT_FSET(sb, len, tp->tim_mylen); 2367 2368 if (getpeer) 2369 mutex_exit(&tp->tim_mutex); 2370 if (STRUCT_FGET(sb, maxlen) == 0) { 2371 2372 /* 2373 * ack the ioctl 2374 */ 2375 freemsg(csp->cp_private); 2376 tim_ioctl_send_reply(q, mp, NULL); 2377 ret = DONAME_DONE; 2378 break; 2379 } 2380 2381 if ((bp = allocb(STRUCT_SIZE(sb), BPRI_MED)) == NULL) { 2382 2383 tilog( 2384 "ti_doname: allocb failed no recovery attempt\n", 0); 2385 2386 freemsg(csp->cp_private); 2387 miocnak(q, mp, 0, EAGAIN); 2388 ret = DONAME_FAIL; 2389 break; 2390 } 2391 bp->b_wptr += STRUCT_SIZE(sb); 2392 bcopy(STRUCT_BUF(sb), bp->b_rptr, STRUCT_SIZE(sb)); 2393 cqp->cq_addr = 2394 (caddr_t)*(intptr_t *)csp->cp_private->b_rptr; 2395 cqp->cq_size = STRUCT_SIZE(sb); 2396 cqp->cq_flag = 0; 2397 mp->b_datap->db_type = M_COPYOUT; 2398 mp->b_cont = bp; 2399 STRUCT_FSET(sb, len, 0); 2400 STRUCT_FSET(sb, maxlen, 0); /* ack next time around */ 2401 qreply(q, mp); 2402 ret = DONAME_CONT; 2403 break; 2404 } 2405 2406 /* 2407 * copy the address to the user 2408 */ 2409 if ((bp = allocb((size_t)STRUCT_FGET(sb, len), BPRI_MED)) 2410 == NULL) { 2411 if (getpeer) 2412 mutex_exit(&tp->tim_mutex); 2413 2414 tilog("ti_doname: allocb failed no recovery attempt\n", 2415 0); 2416 2417 freemsg(csp->cp_private); 2418 miocnak(q, mp, 0, EAGAIN); 2419 ret = DONAME_FAIL; 2420 break; 2421 } 2422 bp->b_wptr += STRUCT_FGET(sb, len); 2423 if (getpeer) { 2424 bcopy(tp->tim_peername, bp->b_rptr, 2425 STRUCT_FGET(sb, len)); 2426 mutex_exit(&tp->tim_mutex); 2427 } else { 2428 bcopy(tp->tim_myname, bp->b_rptr, STRUCT_FGET(sb, len)); 2429 } 2430 cqp->cq_addr = (caddr_t)STRUCT_FGETP(sb, buf); 2431 cqp->cq_size = STRUCT_FGET(sb, len); 2432 cqp->cq_flag = 0; 2433 mp->b_datap->db_type = M_COPYOUT; 2434 mp->b_cont = bp; 2435 STRUCT_FSET(sb, len, 0); /* copy the strbuf next time around */ 2436 qreply(q, mp); 2437 ret = DONAME_CONT; 2438 break; 2439 2440 default: 2441 tilog("ti_doname: freeing bad message type = %d\n", 2442 mp->b_datap->db_type); 2443 freemsg(mp); 2444 ret = DONAME_FAIL; 2445 break; 2446 } 2447 return (ret); 2448 } 2449 2450 /* ONC_PLUS EXTRACT END */ 2451 2452 /* 2453 * Fill in the address of a connectionless data packet if a connect 2454 * had been done on this endpoint. 2455 */ 2456 static mblk_t * 2457 tim_filladdr(queue_t *q, mblk_t *mp, boolean_t dorecover) 2458 { 2459 mblk_t *bp; 2460 struct tim_tim *tp; 2461 struct T_unitdata_req *up; 2462 struct T_unitdata_req *nup; 2463 size_t plen; 2464 2465 tp = (struct tim_tim *)q->q_ptr; 2466 if (mp->b_datap->db_type == M_DATA) { 2467 mutex_enter(&tp->tim_mutex); 2468 bp = allocb(sizeof (struct T_unitdata_req) + tp->tim_peerlen, 2469 BPRI_MED); 2470 if (bp != NULL) { 2471 bp->b_datap->db_type = M_PROTO; 2472 up = (struct T_unitdata_req *)bp->b_rptr; 2473 up->PRIM_type = T_UNITDATA_REQ; 2474 up->DEST_length = tp->tim_peerlen; 2475 bp->b_wptr += sizeof (struct T_unitdata_req); 2476 up->DEST_offset = sizeof (struct T_unitdata_req); 2477 up->OPT_length = 0; 2478 up->OPT_offset = 0; 2479 if (tp->tim_peerlen > 0) { 2480 bcopy(tp->tim_peername, bp->b_wptr, 2481 tp->tim_peerlen); 2482 bp->b_wptr += tp->tim_peerlen; 2483 } 2484 bp->b_cont = mp; 2485 } 2486 } else { 2487 ASSERT(mp->b_datap->db_type == M_PROTO); 2488 up = (struct T_unitdata_req *)mp->b_rptr; 2489 ASSERT(up->PRIM_type == T_UNITDATA_REQ); 2490 if (up->DEST_length != 0) 2491 return (mp); 2492 mutex_enter(&tp->tim_mutex); 2493 bp = allocb(sizeof (struct T_unitdata_req) + up->OPT_length + 2494 tp->tim_peerlen, BPRI_MED); 2495 if (bp != NULL) { 2496 bp->b_datap->db_type = M_PROTO; 2497 nup = (struct T_unitdata_req *)bp->b_rptr; 2498 nup->PRIM_type = T_UNITDATA_REQ; 2499 nup->DEST_length = plen = tp->tim_peerlen; 2500 bp->b_wptr += sizeof (struct T_unitdata_req); 2501 nup->DEST_offset = sizeof (struct T_unitdata_req); 2502 if (plen > 0) { 2503 bcopy(tp->tim_peername, bp->b_wptr, plen); 2504 bp->b_wptr += plen; 2505 } 2506 mutex_exit(&tp->tim_mutex); 2507 if (up->OPT_length == 0) { 2508 nup->OPT_length = 0; 2509 nup->OPT_offset = 0; 2510 } else { 2511 nup->OPT_length = up->OPT_length; 2512 nup->OPT_offset = 2513 sizeof (struct T_unitdata_req) + plen; 2514 bcopy((mp->b_wptr + up->OPT_offset), bp->b_wptr, 2515 up->OPT_length); 2516 bp->b_wptr += up->OPT_length; 2517 } 2518 bp->b_cont = mp->b_cont; 2519 mp->b_cont = NULL; 2520 freeb(mp); 2521 return (bp); 2522 } 2523 } 2524 ASSERT(MUTEX_HELD(&tp->tim_mutex)); 2525 if (bp == NULL && dorecover) { 2526 tim_recover(q, mp, 2527 sizeof (struct T_unitdata_req) + tp->tim_peerlen); 2528 } 2529 mutex_exit(&tp->tim_mutex); 2530 return (bp); 2531 } 2532 2533 static void 2534 tim_addlink(struct tim_tim *tp) 2535 { 2536 struct tim_tim **tpp; 2537 struct tim_tim *next; 2538 2539 tpp = &tim_hash[TIM_HASH(tp->tim_acceptor)]; 2540 rw_enter(&tim_list_rwlock, RW_WRITER); 2541 2542 if ((next = *tpp) != NULL) 2543 next->tim_ptpn = &tp->tim_next; 2544 tp->tim_next = next; 2545 tp->tim_ptpn = tpp; 2546 *tpp = tp; 2547 2548 tim_cnt++; 2549 2550 rw_exit(&tim_list_rwlock); 2551 } 2552 2553 static void 2554 tim_dellink(struct tim_tim *tp) 2555 { 2556 struct tim_tim *next; 2557 2558 rw_enter(&tim_list_rwlock, RW_WRITER); 2559 2560 if ((next = tp->tim_next) != NULL) 2561 next->tim_ptpn = tp->tim_ptpn; 2562 *(tp->tim_ptpn) = next; 2563 2564 tim_cnt--; 2565 2566 rw_exit(&tim_list_rwlock); 2567 } 2568 2569 static struct tim_tim * 2570 tim_findlink(t_uscalar_t id) 2571 { 2572 struct tim_tim *tp; 2573 2574 ASSERT(rw_lock_held(&tim_list_rwlock)); 2575 2576 for (tp = tim_hash[TIM_HASH(id)]; tp != NULL; tp = tp->tim_next) { 2577 if (tp->tim_acceptor == id) { 2578 break; 2579 } 2580 } 2581 return (tp); 2582 } 2583 2584 /* ONC_PLUS EXTRACT START */ 2585 static void 2586 tim_recover(queue_t *q, mblk_t *mp, t_scalar_t size) 2587 { 2588 struct tim_tim *tp; 2589 bufcall_id_t bid; 2590 timeout_id_t tid; 2591 2592 tp = (struct tim_tim *)q->q_ptr; 2593 2594 /* 2595 * Avoid re-enabling the queue. 2596 */ 2597 if (mp->b_datap->db_type == M_PCPROTO) 2598 mp->b_datap->db_type = M_PROTO; 2599 noenable(q); 2600 (void) putbq(q, mp); 2601 2602 /* 2603 * Make sure there is at most one outstanding request per queue. 2604 */ 2605 if (q->q_flag & QREADR) { 2606 if (tp->tim_rtimoutid || tp->tim_rbufcid) 2607 return; 2608 } else { 2609 if (tp->tim_wtimoutid || tp->tim_wbufcid) 2610 return; 2611 } 2612 if (!(bid = qbufcall(RD(q), (size_t)size, BPRI_MED, tim_buffer, q))) { 2613 tid = qtimeout(RD(q), tim_timer, q, TIMWAIT); 2614 if (q->q_flag & QREADR) 2615 tp->tim_rtimoutid = tid; 2616 else 2617 tp->tim_wtimoutid = tid; 2618 } else { 2619 if (q->q_flag & QREADR) 2620 tp->tim_rbufcid = bid; 2621 else 2622 tp->tim_wbufcid = bid; 2623 } 2624 } 2625 2626 /* 2627 * Timod is waiting on a downstream ioctl reply, come back soon 2628 * to reschedule the write side service routine, which will check 2629 * if the ioctl is done and another can proceed. 2630 */ 2631 static void 2632 tim_ioctl_retry(queue_t *q) 2633 { 2634 struct tim_tim *tp; 2635 2636 tp = (struct tim_tim *)q->q_ptr; 2637 2638 /* 2639 * Make sure there is at most one outstanding request per wqueue. 2640 */ 2641 if (tp->tim_wtimoutid || tp->tim_wbufcid) 2642 return; 2643 2644 tp->tim_wtimoutid = qtimeout(RD(q), tim_timer, q, TIMIOCWAIT); 2645 } 2646 2647 /* 2648 * Inspect the data on read queues starting from read queues passed as 2649 * paramter (timod read queue) and traverse until 2650 * q_next is NULL (stream head). Look for a TPI T_EXDATA_IND message 2651 * reutrn 1 if found, 0 if not found. 2652 */ 2653 static int 2654 ti_expind_on_rdqueues(queue_t *rq) 2655 { 2656 mblk_t *bp; 2657 queue_t *q; 2658 2659 q = rq; 2660 /* 2661 * We are going to walk q_next, so protect stream from plumbing 2662 * changes. 2663 */ 2664 claimstr(q); 2665 do { 2666 /* 2667 * Hold QLOCK while referencing data on queues 2668 */ 2669 mutex_enter(QLOCK(rq)); 2670 bp = rq->q_first; 2671 while (bp != NULL) { 2672 /* 2673 * Walk the messages on the queue looking 2674 * for a possible T_EXDATA_IND 2675 */ 2676 if ((bp->b_datap->db_type == M_PROTO) && 2677 ((bp->b_wptr - bp->b_rptr) >= 2678 sizeof (struct T_exdata_ind)) && 2679 (((struct T_exdata_ind *)bp->b_rptr)->PRIM_type 2680 == T_EXDATA_IND)) { 2681 /* bp is T_EXDATA_IND */ 2682 mutex_exit(QLOCK(rq)); 2683 releasestr(q); /* decrement sd_refcnt */ 2684 return (1); /* expdata is on a read queue */ 2685 } 2686 bp = bp->b_next; /* next message */ 2687 } 2688 mutex_exit(QLOCK(rq)); 2689 rq = rq->q_next; /* next upstream queue */ 2690 } while (rq != NULL); 2691 releasestr(q); 2692 return (0); /* no expdata on read queues */ 2693 } 2694 2695 /* ONC_PLUS EXTRACT END */ 2696 static void 2697 tim_tcap_timer(void *q_ptr) 2698 { 2699 queue_t *q = (queue_t *)q_ptr; 2700 struct tim_tim *tp = (struct tim_tim *)q->q_ptr; 2701 2702 ASSERT(tp != NULL && tp->tim_tcap_timoutid != 0); 2703 ASSERT((tp->tim_flags & TI_CAP_RECVD) != 0); 2704 2705 tp->tim_tcap_timoutid = 0; 2706 TILOG("tim_tcap_timer: fired\n", 0); 2707 tim_tcap_genreply(q, tp); 2708 } 2709 2710 /* 2711 * tim_tcap_genreply() is called either from timeout routine or when 2712 * T_ERROR_ACK is received. In both cases it means that underlying 2713 * transport doesn't provide T_CAPABILITY_REQ. 2714 */ 2715 static void 2716 tim_tcap_genreply(queue_t *q, struct tim_tim *tp) 2717 { 2718 mblk_t *mp = tp->tim_iocsave; 2719 struct iocblk *iocbp; 2720 2721 TILOG("timodrproc: tim_tcap_genreply\n", 0); 2722 2723 ASSERT(tp == (struct tim_tim *)q->q_ptr); 2724 ASSERT(mp != NULL); 2725 2726 iocbp = (struct iocblk *)mp->b_rptr; 2727 ASSERT(iocbp != NULL); 2728 ASSERT(MBLKL(mp) == sizeof (struct iocblk)); 2729 ASSERT(iocbp->ioc_cmd == TI_CAPABILITY); 2730 ASSERT(mp->b_cont == NULL); 2731 2732 /* Save this information permanently in the module */ 2733 PI_PROVLOCK(tp->tim_provinfo); 2734 if (tp->tim_provinfo->tpi_capability == PI_DONTKNOW) 2735 tp->tim_provinfo->tpi_capability = PI_NO; 2736 PI_PROVUNLOCK(tp->tim_provinfo); 2737 2738 if (tp->tim_tcap_timoutid != 0) { 2739 (void) quntimeout(q, tp->tim_tcap_timoutid); 2740 tp->tim_tcap_timoutid = 0; 2741 } 2742 2743 if ((tp->tim_flags & CAP_WANTS_INFO) != 0) { 2744 /* Send T_INFO_REQ down */ 2745 mblk_t *tirmp = tpi_ack_alloc(NULL, 2746 sizeof (struct T_info_req), M_PCPROTO, T_INFO_REQ); 2747 2748 if (tirmp != NULL) { 2749 /* Emulate TC1_INFO */ 2750 TILOG("emulate_tcap_ioc_req: sending T_INFO_REQ\n", 0); 2751 tp->tim_flags |= WAIT_IOCINFOACK; 2752 putnext(WR(q), tirmp); 2753 } else { 2754 tilog("emulate_tcap_req: allocb fail, " 2755 "no recovery attmpt\n", 0); 2756 tp->tim_iocsave = NULL; 2757 tp->tim_saved_prim = -1; 2758 tp->tim_flags &= ~(TI_CAP_RECVD | WAITIOCACK | 2759 CAP_WANTS_INFO | WAIT_IOCINFOACK); 2760 miocnak(q, mp, 0, ENOMEM); 2761 } 2762 } else { 2763 /* Reply immediately */ 2764 mblk_t *ackmp = tpi_ack_alloc(NULL, 2765 sizeof (struct T_capability_ack), M_PCPROTO, 2766 T_CAPABILITY_ACK); 2767 2768 mp->b_cont = ackmp; 2769 2770 if (ackmp != NULL) { 2771 ((struct T_capability_ack *) 2772 ackmp->b_rptr)->CAP_bits1 = 0; 2773 tim_ioctl_send_reply(q, mp, ackmp); 2774 tp->tim_iocsave = NULL; 2775 tp->tim_saved_prim = -1; 2776 tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 2777 TI_CAP_RECVD | CAP_WANTS_INFO); 2778 } else { 2779 tilog("timodwproc:allocb failed no " 2780 "recovery attempt\n", 0); 2781 tp->tim_iocsave = NULL; 2782 tp->tim_saved_prim = -1; 2783 tp->tim_flags &= ~(TI_CAP_RECVD | WAITIOCACK | 2784 CAP_WANTS_INFO | WAIT_IOCINFOACK); 2785 miocnak(q, mp, 0, ENOMEM); 2786 } 2787 } 2788 } 2789 2790 2791 static void 2792 tim_ioctl_send_reply(queue_t *q, mblk_t *ioc_mp, mblk_t *mp) 2793 { 2794 struct iocblk *iocbp; 2795 2796 ASSERT(q != NULL && ioc_mp != NULL); 2797 2798 ioc_mp->b_datap->db_type = M_IOCACK; 2799 if (mp != NULL) 2800 mp->b_datap->db_type = M_DATA; 2801 2802 if (ioc_mp->b_cont != mp) { 2803 /* It is safe to call freemsg for NULL pointers */ 2804 freemsg(ioc_mp->b_cont); 2805 ioc_mp->b_cont = mp; 2806 } 2807 iocbp = (struct iocblk *)ioc_mp->b_rptr; 2808 iocbp->ioc_error = 0; 2809 iocbp->ioc_rval = 0; 2810 /* 2811 * All ioctl's may return more data than was specified by 2812 * count arg. For TI_CAPABILITY count is treated as maximum data size. 2813 */ 2814 if (mp == NULL) 2815 iocbp->ioc_count = 0; 2816 else if (iocbp->ioc_cmd != TI_CAPABILITY) 2817 iocbp->ioc_count = msgsize(mp); 2818 else { 2819 iocbp->ioc_count = MIN(MBLKL(mp), iocbp->ioc_count); 2820 /* Truncate message if too large */ 2821 mp->b_wptr = mp->b_rptr + iocbp->ioc_count; 2822 } 2823 2824 TILOG("iosendreply: ioc_cmd = %d, ", iocbp->ioc_cmd); 2825 putnext(RD(q), ioc_mp); 2826 } 2827 2828 /* 2829 * Send M_IOCACK for errors. 2830 */ 2831 static void 2832 tim_send_ioc_error_ack(queue_t *q, struct tim_tim *tp, mblk_t *mp) 2833 { 2834 struct T_error_ack *tea = (struct T_error_ack *)mp->b_rptr; 2835 t_scalar_t error_prim; 2836 2837 mp->b_wptr = mp->b_rptr + sizeof (struct T_error_ack); 2838 ASSERT(mp->b_wptr <= mp->b_datap->db_lim); 2839 error_prim = tea->ERROR_prim; 2840 2841 ASSERT(tp->tim_iocsave != NULL); 2842 ASSERT(tp->tim_iocsave->b_cont != mp); 2843 2844 /* Always send this to the read side of the queue */ 2845 q = RD(q); 2846 2847 TILOG("tim_send_ioc_error_ack: prim = %d\n", tp->tim_saved_prim); 2848 2849 if (tp->tim_saved_prim != error_prim) { 2850 putnext(q, mp); 2851 } else if (error_prim == T_CAPABILITY_REQ) { 2852 TILOG("timodrproc: T_ERROR_ACK/T_CAPABILITY_REQ\n", 0); 2853 ASSERT(tp->tim_iocsave->b_cont == NULL); 2854 2855 tim_tcap_genreply(q, tp); 2856 freemsg(mp); 2857 } else { 2858 struct iocblk *iocbp = (struct iocblk *)tp->tim_iocsave->b_rptr; 2859 2860 TILOG("tim_send_ioc_error_ack: T_ERROR_ACK: prim %d\n", 2861 error_prim); 2862 ASSERT(tp->tim_iocsave->b_cont == NULL); 2863 2864 switch (error_prim) { 2865 default: 2866 TILOG("timodrproc: Unknown T_ERROR_ACK: tlierror %d\n", 2867 tea->TLI_error); 2868 2869 putnext(q, mp); 2870 break; 2871 2872 case T_INFO_REQ: 2873 case T_SVR4_OPTMGMT_REQ: 2874 case T_OPTMGMT_REQ: 2875 case O_T_BIND_REQ: 2876 case T_BIND_REQ: 2877 case T_UNBIND_REQ: 2878 case T_ADDR_REQ: 2879 case T_CAPABILITY_REQ: 2880 2881 TILOG("ioc_err_ack: T_ERROR_ACK: tlierror %x\n", 2882 tea->TLI_error); 2883 2884 /* get saved ioctl msg and set values */ 2885 iocbp->ioc_count = 0; 2886 iocbp->ioc_error = 0; 2887 iocbp->ioc_rval = tea->TLI_error; 2888 if (iocbp->ioc_rval == TSYSERR) 2889 iocbp->ioc_rval |= tea->UNIX_error << 8; 2890 tp->tim_iocsave->b_datap->db_type = M_IOCACK; 2891 freemsg(mp); 2892 putnext(q, tp->tim_iocsave); 2893 tp->tim_iocsave = NULL; 2894 tp->tim_saved_prim = -1; 2895 tp->tim_flags &= ~(WAITIOCACK | TI_CAP_RECVD | 2896 CAP_WANTS_INFO | WAIT_IOCINFOACK); 2897 break; 2898 } 2899 } 2900 } 2901 2902 /* 2903 * Send reply to a usual message or ioctl message upstream. 2904 * Should be called from the read side only. 2905 */ 2906 static void 2907 tim_send_reply(queue_t *q, mblk_t *mp, struct tim_tim *tp, t_scalar_t prim) 2908 { 2909 ASSERT(mp != NULL && q != NULL && tp != NULL); 2910 ASSERT(q == RD(q)); 2911 2912 /* Restore db_type - recover() might have changed it */ 2913 mp->b_datap->db_type = M_PCPROTO; 2914 2915 if (((tp->tim_flags & WAITIOCACK) == 0) || (tp->tim_saved_prim != prim)) 2916 putnext(q, mp); 2917 else { 2918 ASSERT(tp->tim_iocsave != NULL); 2919 tim_ioctl_send_reply(q, tp->tim_iocsave, mp); 2920 tp->tim_iocsave = NULL; 2921 tp->tim_saved_prim = -1; 2922 tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 2923 TI_CAP_RECVD | CAP_WANTS_INFO); 2924 } 2925 } 2926 2927 /* 2928 * Reply to TI_SYNC reequest without sending anything downstream. 2929 */ 2930 static void 2931 tim_answer_ti_sync(queue_t *q, mblk_t *mp, struct tim_tim *tp, 2932 mblk_t *ackmp, uint32_t tsr_flags) 2933 { 2934 struct ti_sync_ack *tsap; 2935 2936 ASSERT(q != NULL && q == WR(q) && ackmp != NULL); 2937 2938 tsap = (struct ti_sync_ack *)ackmp->b_rptr; 2939 bzero(tsap, sizeof (struct ti_sync_ack)); 2940 ackmp->b_wptr = ackmp->b_rptr + sizeof (struct ti_sync_ack); 2941 2942 if (tsr_flags == 0 || 2943 (tsr_flags & ~(TSRF_QLEN_REQ | TSRF_IS_EXP_IN_RCVBUF)) != 0) { 2944 /* 2945 * unsupported/bad flag setting 2946 * or no flag set. 2947 */ 2948 TILOG("timodwproc: unsupported/bad flag setting %x\n", 2949 tsr_flags); 2950 freemsg(ackmp); 2951 miocnak(q, mp, 0, EINVAL); 2952 return; 2953 } 2954 2955 if ((tsr_flags & TSRF_QLEN_REQ) != 0) 2956 tsap->tsa_qlen = tp->tim_backlog; 2957 2958 if ((tsr_flags & TSRF_IS_EXP_IN_RCVBUF) != 0 && 2959 ti_expind_on_rdqueues(RD(q))) { 2960 /* 2961 * Expedited data is queued on 2962 * the stream read side 2963 */ 2964 tsap->tsa_flags |= TSAF_EXP_QUEUED; 2965 } 2966 2967 tim_ioctl_send_reply(q, mp, ackmp); 2968 tp->tim_iocsave = NULL; 2969 tp->tim_saved_prim = -1; 2970 tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 2971 TI_CAP_RECVD | CAP_WANTS_INFO); 2972 } 2973 2974 /* 2975 * Send TPI message from IOCTL message, ssave original ioctl header and TPI 2976 * message type. Should be called from write side only. 2977 */ 2978 static void 2979 tim_send_ioctl_tpi_msg(queue_t *q, mblk_t *mp, struct tim_tim *tp, 2980 struct iocblk *iocb) 2981 { 2982 mblk_t *tmp; 2983 int ioc_cmd = iocb->ioc_cmd; 2984 2985 ASSERT(q != NULL && mp != NULL && tp != NULL); 2986 ASSERT(q == WR(q)); 2987 ASSERT(mp->b_cont != NULL); 2988 2989 tp->tim_iocsave = mp; 2990 tmp = mp->b_cont; 2991 2992 mp->b_cont = NULL; 2993 tp->tim_flags |= WAITIOCACK; 2994 tp->tim_saved_prim = ((union T_primitives *)tmp->b_rptr)->type; 2995 2996 /* 2997 * For TI_GETINFO, the attached message is a T_INFO_REQ 2998 * For TI_SYNC, we generate the T_INFO_REQ message above 2999 * For TI_CAPABILITY the attached message is either 3000 * T_CAPABILITY_REQ or T_INFO_REQ. 3001 * Among TPI request messages possible, 3002 * T_INFO_REQ/T_CAPABILITY_ACK messages are a M_PCPROTO, rest 3003 * are M_PROTO 3004 */ 3005 if (ioc_cmd == TI_GETINFO || ioc_cmd == TI_SYNC || 3006 ioc_cmd == TI_CAPABILITY) { 3007 tmp->b_datap->db_type = M_PCPROTO; 3008 } else { 3009 tmp->b_datap->db_type = M_PROTO; 3010 } 3011 3012 /* Verify credentials in STREAM */ 3013 ASSERT(iocb->ioc_cr == NULL || iocb->ioc_cr == DB_CRED(tmp)); 3014 3015 TILOG("timodwproc: sending down %d\n", tp->tim_saved_prim); 3016 putnext(q, tmp); 3017 } 3018 3019 static void 3020 tim_clear_peer(struct tim_tim *tp) 3021 { 3022 mutex_enter(&tp->tim_mutex); 3023 if (tp->tim_peercred != NULL) { 3024 crfree(tp->tim_peercred); 3025 tp->tim_peercred = NULL; 3026 } 3027 tp->tim_peerlen = 0; 3028 mutex_exit(&tp->tim_mutex); 3029 } 3030