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