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 }