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