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