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