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