10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 230Sstevel@tonic-gate /* 24*1261Sgeorges * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 250Sstevel@tonic-gate * Use is subject to license terms. 260Sstevel@tonic-gate */ 270Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 280Sstevel@tonic-gate /* All Rights Reserved */ 290Sstevel@tonic-gate 300Sstevel@tonic-gate 310Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 320Sstevel@tonic-gate 330Sstevel@tonic-gate /* 340Sstevel@tonic-gate * Transport Interface Library cooperating module - issue 2 350Sstevel@tonic-gate */ 360Sstevel@tonic-gate 370Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 380Sstevel@tonic-gate #include <sys/param.h> 390Sstevel@tonic-gate #include <sys/types.h> 400Sstevel@tonic-gate #include <sys/stream.h> 410Sstevel@tonic-gate #include <sys/stropts.h> 420Sstevel@tonic-gate #include <sys/strsubr.h> 430Sstevel@tonic-gate #define _SUN_TPI_VERSION 2 440Sstevel@tonic-gate #include <sys/tihdr.h> 450Sstevel@tonic-gate #include <sys/timod.h> 460Sstevel@tonic-gate #include <sys/suntpi.h> 470Sstevel@tonic-gate #include <sys/debug.h> 480Sstevel@tonic-gate #include <sys/strlog.h> 490Sstevel@tonic-gate #include <sys/errno.h> 500Sstevel@tonic-gate #include <sys/cred.h> 510Sstevel@tonic-gate #include <sys/cmn_err.h> 520Sstevel@tonic-gate #include <sys/kmem.h> 530Sstevel@tonic-gate #include <sys/sysmacros.h> 540Sstevel@tonic-gate #include <sys/ddi.h> 550Sstevel@tonic-gate #include <sys/sunddi.h> 560Sstevel@tonic-gate #include <sys/strsun.h> 570Sstevel@tonic-gate #include <c2/audit.h> 580Sstevel@tonic-gate 590Sstevel@tonic-gate /* 600Sstevel@tonic-gate * This is the loadable module wrapper. 610Sstevel@tonic-gate */ 620Sstevel@tonic-gate #include <sys/conf.h> 630Sstevel@tonic-gate #include <sys/modctl.h> 640Sstevel@tonic-gate 650Sstevel@tonic-gate static struct streamtab timinfo; 660Sstevel@tonic-gate 670Sstevel@tonic-gate static struct fmodsw fsw = { 680Sstevel@tonic-gate "timod", 690Sstevel@tonic-gate &timinfo, 700Sstevel@tonic-gate D_MTQPAIR | D_MP, 710Sstevel@tonic-gate }; 720Sstevel@tonic-gate 730Sstevel@tonic-gate /* 740Sstevel@tonic-gate * Module linkage information for the kernel. 750Sstevel@tonic-gate */ 760Sstevel@tonic-gate 770Sstevel@tonic-gate static struct modlstrmod modlstrmod = { 780Sstevel@tonic-gate &mod_strmodops, "transport interface str mod", &fsw 790Sstevel@tonic-gate }; 800Sstevel@tonic-gate 810Sstevel@tonic-gate static struct modlinkage modlinkage = { 820Sstevel@tonic-gate MODREV_1, &modlstrmod, NULL 830Sstevel@tonic-gate }; 840Sstevel@tonic-gate 850Sstevel@tonic-gate static krwlock_t tim_list_rwlock; 860Sstevel@tonic-gate 870Sstevel@tonic-gate /* 880Sstevel@tonic-gate * This module keeps track of capabilities of underlying transport. Information 890Sstevel@tonic-gate * is persistent through module invocations (open/close). Currently it remembers 900Sstevel@tonic-gate * whether underlying transport supports TI_GET{MY,PEER}NAME ioctls and 910Sstevel@tonic-gate * T_CAPABILITY_REQ message. This module either passes ioctl/messages to the 920Sstevel@tonic-gate * transport or emulates it when transport doesn't understand these 930Sstevel@tonic-gate * ioctl/messages. 940Sstevel@tonic-gate * 950Sstevel@tonic-gate * It is assumed that transport supports T_CAPABILITY_REQ when timod receives 960Sstevel@tonic-gate * T_CAPABILITY_ACK from the transport. There is no current standard describing 970Sstevel@tonic-gate * transport behaviour when it receives unknown message type, so following 980Sstevel@tonic-gate * reactions are expected and handled: 990Sstevel@tonic-gate * 1000Sstevel@tonic-gate * 1) Transport drops unknown T_CAPABILITY_REQ message type. In this case timod 1010Sstevel@tonic-gate * will wait for tcap_wait time and assume that transport doesn't provide 1020Sstevel@tonic-gate * this message type. T_CAPABILITY_REQ should never travel over the wire, so 1030Sstevel@tonic-gate * timeout value should only take into consideration internal processing time 1040Sstevel@tonic-gate * for the message. From user standpoint it may mean that an application will 1050Sstevel@tonic-gate * hang for TCAP_WAIT time in the kernel the first time this message is used 1060Sstevel@tonic-gate * with some particular transport (e.g. TCP/IP) during system uptime. 1070Sstevel@tonic-gate * 1080Sstevel@tonic-gate * 2) Transport responds with T_ERROR_ACK specifying T_CAPABILITY_REQ as 1090Sstevel@tonic-gate * original message type. In this case it is assumed that transport doesn't 1100Sstevel@tonic-gate * support it (which may not always be true - some transports return 1110Sstevel@tonic-gate * T_ERROR_ACK in other cases like lack of system memory). 1120Sstevel@tonic-gate * 1130Sstevel@tonic-gate * 3) Transport responds with M_ERROR, effectively shutting down the 1140Sstevel@tonic-gate * stream. Unfortunately there is no standard way to pass the reason of 1150Sstevel@tonic-gate * M_ERROR message back to the caller, so it is assumed that if M_ERROR was 1160Sstevel@tonic-gate * sent in response to T_CAPABILITY_REQ message, transport doesn't support 1170Sstevel@tonic-gate * it. 1180Sstevel@tonic-gate * 1190Sstevel@tonic-gate * It is possible under certain circumstances that timod will incorrectly assume 1200Sstevel@tonic-gate * that underlying transport doesn't provide T_CAPABILITY_REQ message type. In 1210Sstevel@tonic-gate * this "worst-case" scenario timod will emulate its functionality by itself and 1220Sstevel@tonic-gate * will provide only TC1_INFO capability. All other bits in CAP_bits1 field are 1230Sstevel@tonic-gate * cleaned. TC1_INFO is emulated by sending T_INFO_REQ down to transport 1240Sstevel@tonic-gate * provider. 1250Sstevel@tonic-gate */ 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate /* 1280Sstevel@tonic-gate * Notes about locking: 1290Sstevel@tonic-gate * 1300Sstevel@tonic-gate * tim_list_rwlock protects the list of tim_tim structures itself. When this 1310Sstevel@tonic-gate * lock is held, the list itself is stable, but the contents of the entries 1320Sstevel@tonic-gate * themselves might not be. 1330Sstevel@tonic-gate * 1340Sstevel@tonic-gate * The rest of the members are generally protected by D_MTQPAIR, which 1350Sstevel@tonic-gate * specifies a default exclusive inner perimeter. If you're looking at 1360Sstevel@tonic-gate * q->q_ptr, then it's stable. 1370Sstevel@tonic-gate * 1380Sstevel@tonic-gate * There's one exception to this rule: tim_peer{maxlen,len,name}. These members 1390Sstevel@tonic-gate * are touched without entering the associated STREAMS perimeter because we 1400Sstevel@tonic-gate * get the pointer via tim_findlink() rather than q_ptr. These are protected 1410Sstevel@tonic-gate * by tim_mutex instead. If you don't hold that lock, don't look at them. 1420Sstevel@tonic-gate * 1430Sstevel@tonic-gate * (It would be possible to separate out the 'set by T_CONN_RES' cases from the 1440Sstevel@tonic-gate * others, but there appears to be no reason to do so.) 1450Sstevel@tonic-gate */ 1460Sstevel@tonic-gate struct tim_tim { 1470Sstevel@tonic-gate uint32_t tim_flags; 1480Sstevel@tonic-gate t_uscalar_t tim_backlog; 1490Sstevel@tonic-gate mblk_t *tim_iocsave; 1500Sstevel@tonic-gate t_scalar_t tim_mymaxlen; 1510Sstevel@tonic-gate t_scalar_t tim_mylen; 1520Sstevel@tonic-gate caddr_t tim_myname; 1530Sstevel@tonic-gate t_scalar_t tim_peermaxlen; 1540Sstevel@tonic-gate t_scalar_t tim_peerlen; 1550Sstevel@tonic-gate caddr_t tim_peername; 1560Sstevel@tonic-gate cred_t *tim_peercred; 1570Sstevel@tonic-gate mblk_t *tim_consave; 1580Sstevel@tonic-gate bufcall_id_t tim_wbufcid; 1590Sstevel@tonic-gate bufcall_id_t tim_rbufcid; 1600Sstevel@tonic-gate timeout_id_t tim_wtimoutid; 1610Sstevel@tonic-gate timeout_id_t tim_rtimoutid; 1620Sstevel@tonic-gate /* Protected by the global tim_list_rwlock for all instances */ 1630Sstevel@tonic-gate struct tim_tim *tim_next; 1640Sstevel@tonic-gate struct tim_tim **tim_ptpn; 1650Sstevel@tonic-gate t_uscalar_t tim_acceptor; 1660Sstevel@tonic-gate t_scalar_t tim_saved_prim; /* Primitive from message */ 1670Sstevel@tonic-gate /* part of ioctl. */ 1680Sstevel@tonic-gate timeout_id_t tim_tcap_timoutid; /* For T_CAP_REQ timeout */ 1690Sstevel@tonic-gate tpi_provinfo_t *tim_provinfo; /* Transport description */ 1700Sstevel@tonic-gate kmutex_t tim_mutex; /* protect tim_peer* */ 1710Sstevel@tonic-gate pid_t tim_cpid; 1720Sstevel@tonic-gate }; 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate /* 1760Sstevel@tonic-gate * Local flags used with tim_flags field in instance structure of 1770Sstevel@tonic-gate * type 'struct _ti_user' declared above. 1780Sstevel@tonic-gate * Historical note: 1790Sstevel@tonic-gate * This namespace constants were previously declared in a 1800Sstevel@tonic-gate * a very messed up namespace in timod.h 1810Sstevel@tonic-gate * 1820Sstevel@tonic-gate * There may be 3 states for transport: 1830Sstevel@tonic-gate * 1840Sstevel@tonic-gate * 1) It provides T_CAPABILITY_REQ 1850Sstevel@tonic-gate * 2) It does not provide T_CAPABILITY_REQ 1860Sstevel@tonic-gate * 3) It is not known yet whether transport provides T_CAPABILITY_REQ or not. 1870Sstevel@tonic-gate * 1880Sstevel@tonic-gate * It is assumed that the underlying transport either provides 1890Sstevel@tonic-gate * T_CAPABILITY_REQ or not and this does not changes during the 1900Sstevel@tonic-gate * system lifetime. 1910Sstevel@tonic-gate * 1920Sstevel@tonic-gate */ 1930Sstevel@tonic-gate #define PEEK_RDQ_EXPIND 0x0001 /* look for expinds on stream rd queues */ 1940Sstevel@tonic-gate #define WAITIOCACK 0x0002 /* waiting for info for ioctl act */ 1950Sstevel@tonic-gate #define CLTS 0x0004 /* connectionless transport */ 1960Sstevel@tonic-gate #define COTS 0x0008 /* connection-oriented transport */ 1970Sstevel@tonic-gate #define CONNWAIT 0x0010 /* waiting for connect confirmation */ 1980Sstevel@tonic-gate #define LOCORDREL 0x0020 /* local end has orderly released */ 1990Sstevel@tonic-gate #define REMORDREL 0x0040 /* remote end had orderly released */ 2000Sstevel@tonic-gate #define NAMEPROC 0x0080 /* processing a NAME ioctl */ 2010Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 2020Sstevel@tonic-gate #define DO_MYNAME 0x0100 /* timod handles TI_GETMYNAME */ 2030Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 2040Sstevel@tonic-gate #define DO_PEERNAME 0x0200 /* timod handles TI_GETPEERNAME */ 2050Sstevel@tonic-gate #define TI_CAP_RECVD 0x0400 /* TI_CAPABILITY received */ 2060Sstevel@tonic-gate #define CAP_WANTS_INFO 0x0800 /* TI_CAPABILITY has TC1_INFO set */ 2070Sstevel@tonic-gate #define WAIT_IOCINFOACK 0x1000 /* T_INFO_REQ generated from ioctl */ 2080Sstevel@tonic-gate #define WAIT_CONNRESACK 0x2000 /* waiting for T_OK_ACK to T_CONN_RES */ 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate /* Debugging facilities */ 2120Sstevel@tonic-gate /* 2130Sstevel@tonic-gate * Logging needed for debugging timod should only appear in DEBUG kernel. 2140Sstevel@tonic-gate */ 2150Sstevel@tonic-gate #ifdef DEBUG 2160Sstevel@tonic-gate #define TILOG(msg, arg) tilog((msg), (arg)) 2170Sstevel@tonic-gate #define TILOGP(msg, arg) tilogp((msg), (arg)) 2180Sstevel@tonic-gate #else 2190Sstevel@tonic-gate #define TILOG(msg, arg) 2200Sstevel@tonic-gate #define TILOGP(msg, arg) 2210Sstevel@tonic-gate #endif 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate 2240Sstevel@tonic-gate /* 2250Sstevel@tonic-gate * Sleep timeout for T_CAPABILITY_REQ. This message never travels across 2260Sstevel@tonic-gate * network, so timeout value should be enough to cover all internal processing 2270Sstevel@tonic-gate * time. 2280Sstevel@tonic-gate */ 2290Sstevel@tonic-gate clock_t tim_tcap_wait = 2; 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate /* Sleep timeout in tim_recover() */ 2320Sstevel@tonic-gate #define TIMWAIT (1*hz) 233*1261Sgeorges /* Sleep timeout in tim_ioctl_retry() 0.2 seconds */ 234*1261Sgeorges #define TIMIOCWAIT (200*hz/1000) 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate /* 2370Sstevel@tonic-gate * Return values for ti_doname(). 2380Sstevel@tonic-gate */ 2390Sstevel@tonic-gate #define DONAME_FAIL 0 /* failing ioctl (done) */ 2400Sstevel@tonic-gate #define DONAME_DONE 1 /* done processing */ 2410Sstevel@tonic-gate #define DONAME_CONT 2 /* continue proceesing (not done yet) */ 2420Sstevel@tonic-gate 2430Sstevel@tonic-gate /* 2440Sstevel@tonic-gate * Function prototypes 2450Sstevel@tonic-gate */ 2460Sstevel@tonic-gate static int ti_doname(queue_t *, mblk_t *); 2470Sstevel@tonic-gate static int ti_expind_on_rdqueues(queue_t *); 2480Sstevel@tonic-gate static void tim_ioctl_send_reply(queue_t *, mblk_t *, mblk_t *); 2490Sstevel@tonic-gate static void tim_send_ioc_error_ack(queue_t *, struct tim_tim *, mblk_t *); 2500Sstevel@tonic-gate static void tim_tcap_timer(void *); 2510Sstevel@tonic-gate static void tim_tcap_genreply(queue_t *, struct tim_tim *); 2520Sstevel@tonic-gate static void tim_send_reply(queue_t *, mblk_t *, struct tim_tim *, t_scalar_t); 2530Sstevel@tonic-gate static void tim_answer_ti_sync(queue_t *, mblk_t *, struct tim_tim *, 2540Sstevel@tonic-gate mblk_t *, uint32_t); 2550Sstevel@tonic-gate static void tim_send_ioctl_tpi_msg(queue_t *, mblk_t *, struct tim_tim *, 2560Sstevel@tonic-gate struct iocblk *); 2570Sstevel@tonic-gate static void tim_clear_peer(struct tim_tim *); 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate int 2600Sstevel@tonic-gate _init(void) 2610Sstevel@tonic-gate { 2620Sstevel@tonic-gate int error; 2630Sstevel@tonic-gate 2640Sstevel@tonic-gate rw_init(&tim_list_rwlock, NULL, RW_DRIVER, NULL); 2650Sstevel@tonic-gate error = mod_install(&modlinkage); 2660Sstevel@tonic-gate if (error != 0) { 2670Sstevel@tonic-gate rw_destroy(&tim_list_rwlock); 2680Sstevel@tonic-gate return (error); 2690Sstevel@tonic-gate } 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate return (0); 2720Sstevel@tonic-gate } 2730Sstevel@tonic-gate 2740Sstevel@tonic-gate int 2750Sstevel@tonic-gate _fini(void) 2760Sstevel@tonic-gate { 2770Sstevel@tonic-gate int error; 2780Sstevel@tonic-gate 2790Sstevel@tonic-gate error = mod_remove(&modlinkage); 2800Sstevel@tonic-gate if (error != 0) 2810Sstevel@tonic-gate return (error); 2820Sstevel@tonic-gate rw_destroy(&tim_list_rwlock); 2830Sstevel@tonic-gate return (0); 2840Sstevel@tonic-gate } 2850Sstevel@tonic-gate 2860Sstevel@tonic-gate int 2870Sstevel@tonic-gate _info(struct modinfo *modinfop) 2880Sstevel@tonic-gate { 2890Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 2900Sstevel@tonic-gate } 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate 2930Sstevel@tonic-gate /* 2940Sstevel@tonic-gate * Hash list for all instances. Used to find tim_tim structure based on 2950Sstevel@tonic-gate * ACCEPTOR_id in T_CONN_RES. Protected by tim_list_rwlock. 2960Sstevel@tonic-gate */ 2970Sstevel@tonic-gate #define TIM_HASH_SIZE 256 2980Sstevel@tonic-gate #ifdef _ILP32 2990Sstevel@tonic-gate #define TIM_HASH(id) (((uintptr_t)(id) >> 8) % TIM_HASH_SIZE) 3000Sstevel@tonic-gate #else 3010Sstevel@tonic-gate #define TIM_HASH(id) ((uintptr_t)(id) % TIM_HASH_SIZE) 3020Sstevel@tonic-gate #endif /* _ILP32 */ 3030Sstevel@tonic-gate static struct tim_tim *tim_hash[TIM_HASH_SIZE]; 3040Sstevel@tonic-gate int tim_cnt = 0; 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate static void tilog(char *, t_scalar_t); 3070Sstevel@tonic-gate static void tilogp(char *, uintptr_t); 3080Sstevel@tonic-gate static mblk_t *tim_filladdr(queue_t *, mblk_t *, boolean_t); 3090Sstevel@tonic-gate static void tim_addlink(struct tim_tim *); 3100Sstevel@tonic-gate static void tim_dellink(struct tim_tim *); 3110Sstevel@tonic-gate static struct tim_tim *tim_findlink(t_uscalar_t); 3120Sstevel@tonic-gate static void tim_recover(queue_t *, mblk_t *, t_scalar_t); 313*1261Sgeorges static void tim_ioctl_retry(queue_t *); 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate int dotilog = 0; 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate #define TIMOD_ID 3 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 3200Sstevel@tonic-gate static int timodopen(queue_t *, dev_t *, int, int, cred_t *); 3210Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 3220Sstevel@tonic-gate static int timodclose(queue_t *, int, cred_t *); 3230Sstevel@tonic-gate static void timodwput(queue_t *, mblk_t *); 3240Sstevel@tonic-gate static void timodrput(queue_t *, mblk_t *); 3250Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 3260Sstevel@tonic-gate static void timodrsrv(queue_t *); 3270Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 3280Sstevel@tonic-gate static void timodwsrv(queue_t *); 3290Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 3300Sstevel@tonic-gate static int timodrproc(queue_t *, mblk_t *); 3310Sstevel@tonic-gate static int timodwproc(queue_t *, mblk_t *); 3320Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate /* stream data structure definitions */ 3350Sstevel@tonic-gate 3360Sstevel@tonic-gate static struct module_info timod_info = 3370Sstevel@tonic-gate {TIMOD_ID, "timod", 0, INFPSZ, 512, 128}; 3380Sstevel@tonic-gate static struct qinit timodrinit = { 3390Sstevel@tonic-gate (int (*)())timodrput, 3400Sstevel@tonic-gate (int (*)())timodrsrv, 3410Sstevel@tonic-gate timodopen, 3420Sstevel@tonic-gate timodclose, 3430Sstevel@tonic-gate nulldev, 3440Sstevel@tonic-gate &timod_info, 3450Sstevel@tonic-gate NULL 3460Sstevel@tonic-gate }; 3470Sstevel@tonic-gate static struct qinit timodwinit = { 3480Sstevel@tonic-gate (int (*)())timodwput, 3490Sstevel@tonic-gate (int (*)())timodwsrv, 3500Sstevel@tonic-gate timodopen, 3510Sstevel@tonic-gate timodclose, 3520Sstevel@tonic-gate nulldev, 3530Sstevel@tonic-gate &timod_info, 3540Sstevel@tonic-gate NULL 3550Sstevel@tonic-gate }; 3560Sstevel@tonic-gate static struct streamtab timinfo = { &timodrinit, &timodwinit, NULL, NULL }; 3570Sstevel@tonic-gate 3580Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 3590Sstevel@tonic-gate /* 3600Sstevel@tonic-gate * timodopen - open routine gets called when the module gets pushed 3610Sstevel@tonic-gate * onto the stream. 3620Sstevel@tonic-gate */ 3630Sstevel@tonic-gate /*ARGSUSED*/ 3640Sstevel@tonic-gate static int 3650Sstevel@tonic-gate timodopen( 3660Sstevel@tonic-gate queue_t *q, 3670Sstevel@tonic-gate dev_t *devp, 3680Sstevel@tonic-gate int flag, 3690Sstevel@tonic-gate int sflag, 3700Sstevel@tonic-gate cred_t *crp) 3710Sstevel@tonic-gate { 3720Sstevel@tonic-gate struct tim_tim *tp; 3730Sstevel@tonic-gate struct stroptions *sop; 3740Sstevel@tonic-gate mblk_t *bp; 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate ASSERT(q != NULL); 3770Sstevel@tonic-gate 3780Sstevel@tonic-gate if (q->q_ptr) { 3790Sstevel@tonic-gate return (0); 3800Sstevel@tonic-gate } 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate if ((bp = allocb(sizeof (struct stroptions), BPRI_MED)) == 0) 3830Sstevel@tonic-gate return (ENOMEM); 3840Sstevel@tonic-gate 3850Sstevel@tonic-gate tp = kmem_zalloc(sizeof (struct tim_tim), KM_SLEEP); 3860Sstevel@tonic-gate 3870Sstevel@tonic-gate tp->tim_cpid = -1; 3880Sstevel@tonic-gate tp->tim_saved_prim = -1; 3890Sstevel@tonic-gate 3900Sstevel@tonic-gate mutex_init(&tp->tim_mutex, NULL, MUTEX_DEFAULT, NULL); 3910Sstevel@tonic-gate 3920Sstevel@tonic-gate q->q_ptr = (caddr_t)tp; 3930Sstevel@tonic-gate WR(q)->q_ptr = (caddr_t)tp; 3940Sstevel@tonic-gate 3950Sstevel@tonic-gate tilogp("timodopen: Allocated for tp %lx\n", (uintptr_t)tp); 3960Sstevel@tonic-gate tilogp("timodopen: Allocated for q %lx\n", (uintptr_t)q); 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate /* Must be done before tpi_findprov and _ILP32 q_next walk below */ 3990Sstevel@tonic-gate qprocson(q); 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate tp->tim_provinfo = tpi_findprov(q); 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate /* 4040Sstevel@tonic-gate * Defer allocation of the buffers for the local address and 4050Sstevel@tonic-gate * the peer's address until we need them. 4060Sstevel@tonic-gate * Assume that timod has to handle getname until we here 4070Sstevel@tonic-gate * an iocack from the transport provider or we know that 4080Sstevel@tonic-gate * transport provider doesn't understand it. 4090Sstevel@tonic-gate */ 4100Sstevel@tonic-gate if (tp->tim_provinfo->tpi_myname != PI_YES) { 4110Sstevel@tonic-gate TILOG("timodopen: setting DO_MYNAME\n", 0); 4120Sstevel@tonic-gate tp->tim_flags |= DO_MYNAME; 4130Sstevel@tonic-gate } 4140Sstevel@tonic-gate 4150Sstevel@tonic-gate if (tp->tim_provinfo->tpi_peername != PI_YES) { 4160Sstevel@tonic-gate TILOG("timodopen: setting DO_PEERNAME\n", 0); 4170Sstevel@tonic-gate tp->tim_flags |= DO_PEERNAME; 4180Sstevel@tonic-gate } 4190Sstevel@tonic-gate 4200Sstevel@tonic-gate #ifdef _ILP32 4210Sstevel@tonic-gate { 4220Sstevel@tonic-gate queue_t *driverq; 4230Sstevel@tonic-gate 4240Sstevel@tonic-gate /* 4250Sstevel@tonic-gate * Find my driver's read queue (for T_CONN_RES handling) 4260Sstevel@tonic-gate */ 4270Sstevel@tonic-gate driverq = WR(q); 4280Sstevel@tonic-gate while (SAMESTR(driverq)) 4290Sstevel@tonic-gate driverq = driverq->q_next; 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate tp->tim_acceptor = (t_uscalar_t)RD(driverq); 4320Sstevel@tonic-gate } 4330Sstevel@tonic-gate #else 4340Sstevel@tonic-gate tp->tim_acceptor = (t_uscalar_t)getminor(*devp); 4350Sstevel@tonic-gate #endif /* _ILP32 */ 4360Sstevel@tonic-gate 4370Sstevel@tonic-gate /* 4380Sstevel@tonic-gate * Add this one to the list. 4390Sstevel@tonic-gate */ 4400Sstevel@tonic-gate tim_addlink(tp); 4410Sstevel@tonic-gate 4420Sstevel@tonic-gate /* 4430Sstevel@tonic-gate * Send M_SETOPTS to stream head to make sure M_PCPROTO messages 4440Sstevel@tonic-gate * are not flushed. This prevents application deadlocks. 4450Sstevel@tonic-gate */ 4460Sstevel@tonic-gate bp->b_datap->db_type = M_SETOPTS; 4470Sstevel@tonic-gate bp->b_wptr += sizeof (struct stroptions); 4480Sstevel@tonic-gate sop = (struct stroptions *)bp->b_rptr; 4490Sstevel@tonic-gate sop->so_flags = SO_READOPT; 4500Sstevel@tonic-gate sop->so_readopt = RFLUSHPCPROT; 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate putnext(q, bp); 4530Sstevel@tonic-gate 4540Sstevel@tonic-gate return (0); 4550Sstevel@tonic-gate } 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate static void 4580Sstevel@tonic-gate tim_timer(void *arg) 4590Sstevel@tonic-gate { 4600Sstevel@tonic-gate queue_t *q = arg; 4610Sstevel@tonic-gate struct tim_tim *tp = (struct tim_tim *)q->q_ptr; 4620Sstevel@tonic-gate 4630Sstevel@tonic-gate ASSERT(tp); 4640Sstevel@tonic-gate 4650Sstevel@tonic-gate if (q->q_flag & QREADR) { 4660Sstevel@tonic-gate ASSERT(tp->tim_rtimoutid); 4670Sstevel@tonic-gate tp->tim_rtimoutid = 0; 4680Sstevel@tonic-gate } else { 4690Sstevel@tonic-gate ASSERT(tp->tim_wtimoutid); 4700Sstevel@tonic-gate tp->tim_wtimoutid = 0; 4710Sstevel@tonic-gate } 4720Sstevel@tonic-gate enableok(q); 4730Sstevel@tonic-gate qenable(q); 4740Sstevel@tonic-gate } 4750Sstevel@tonic-gate 4760Sstevel@tonic-gate static void 4770Sstevel@tonic-gate tim_buffer(void *arg) 4780Sstevel@tonic-gate { 4790Sstevel@tonic-gate queue_t *q = arg; 4800Sstevel@tonic-gate struct tim_tim *tp = (struct tim_tim *)q->q_ptr; 4810Sstevel@tonic-gate 4820Sstevel@tonic-gate ASSERT(tp); 4830Sstevel@tonic-gate 4840Sstevel@tonic-gate if (q->q_flag & QREADR) { 4850Sstevel@tonic-gate ASSERT(tp->tim_rbufcid); 4860Sstevel@tonic-gate tp->tim_rbufcid = 0; 4870Sstevel@tonic-gate } else { 4880Sstevel@tonic-gate ASSERT(tp->tim_wbufcid); 4890Sstevel@tonic-gate tp->tim_wbufcid = 0; 4900Sstevel@tonic-gate } 4910Sstevel@tonic-gate enableok(q); 4920Sstevel@tonic-gate qenable(q); 4930Sstevel@tonic-gate } 4940Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 4950Sstevel@tonic-gate 4960Sstevel@tonic-gate /* 4970Sstevel@tonic-gate * timodclose - This routine gets called when the module gets popped 4980Sstevel@tonic-gate * off of the stream. 4990Sstevel@tonic-gate */ 5000Sstevel@tonic-gate /*ARGSUSED*/ 5010Sstevel@tonic-gate static int 5020Sstevel@tonic-gate timodclose( 5030Sstevel@tonic-gate queue_t *q, 5040Sstevel@tonic-gate int flag, 5050Sstevel@tonic-gate cred_t *crp) 5060Sstevel@tonic-gate { 5070Sstevel@tonic-gate struct tim_tim *tp; 5080Sstevel@tonic-gate mblk_t *mp; 5090Sstevel@tonic-gate mblk_t *nmp; 5100Sstevel@tonic-gate 5110Sstevel@tonic-gate ASSERT(q != NULL); 5120Sstevel@tonic-gate 5130Sstevel@tonic-gate tp = (struct tim_tim *)q->q_ptr; 5140Sstevel@tonic-gate q->q_ptr = NULL; 5150Sstevel@tonic-gate 5160Sstevel@tonic-gate ASSERT(tp != NULL); 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate tilogp("timodclose: Entered for tp %lx\n", (uintptr_t)tp); 5190Sstevel@tonic-gate tilogp("timodclose: Entered for q %lx\n", (uintptr_t)q); 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate qprocsoff(q); 5220Sstevel@tonic-gate tim_dellink(tp); 5230Sstevel@tonic-gate 5240Sstevel@tonic-gate /* 5250Sstevel@tonic-gate * Cancel any outstanding bufcall 5260Sstevel@tonic-gate * or timeout requests. 5270Sstevel@tonic-gate */ 5280Sstevel@tonic-gate if (tp->tim_wbufcid) { 5290Sstevel@tonic-gate qunbufcall(q, tp->tim_wbufcid); 5300Sstevel@tonic-gate tp->tim_wbufcid = 0; 5310Sstevel@tonic-gate } 5320Sstevel@tonic-gate if (tp->tim_rbufcid) { 5330Sstevel@tonic-gate qunbufcall(q, tp->tim_rbufcid); 5340Sstevel@tonic-gate tp->tim_rbufcid = 0; 5350Sstevel@tonic-gate } 5360Sstevel@tonic-gate if (tp->tim_wtimoutid) { 5370Sstevel@tonic-gate (void) quntimeout(q, tp->tim_wtimoutid); 5380Sstevel@tonic-gate tp->tim_wtimoutid = 0; 5390Sstevel@tonic-gate } 5400Sstevel@tonic-gate if (tp->tim_rtimoutid) { 5410Sstevel@tonic-gate (void) quntimeout(q, tp->tim_rtimoutid); 5420Sstevel@tonic-gate tp->tim_rtimoutid = 0; 5430Sstevel@tonic-gate } 5440Sstevel@tonic-gate 5450Sstevel@tonic-gate if (tp->tim_tcap_timoutid != 0) { 5460Sstevel@tonic-gate (void) quntimeout(q, tp->tim_tcap_timoutid); 5470Sstevel@tonic-gate tp->tim_tcap_timoutid = 0; 5480Sstevel@tonic-gate } 5490Sstevel@tonic-gate 5500Sstevel@tonic-gate if (tp->tim_iocsave != NULL) 5510Sstevel@tonic-gate freemsg(tp->tim_iocsave); 5520Sstevel@tonic-gate mp = tp->tim_consave; 5530Sstevel@tonic-gate while (mp) { 5540Sstevel@tonic-gate nmp = mp->b_next; 5550Sstevel@tonic-gate mp->b_next = NULL; 5560Sstevel@tonic-gate freemsg(mp); 5570Sstevel@tonic-gate mp = nmp; 5580Sstevel@tonic-gate } 5590Sstevel@tonic-gate ASSERT(tp->tim_mymaxlen >= 0); 5600Sstevel@tonic-gate if (tp->tim_mymaxlen != 0) 5610Sstevel@tonic-gate kmem_free(tp->tim_myname, (size_t)tp->tim_mymaxlen); 5620Sstevel@tonic-gate ASSERT(tp->tim_peermaxlen >= 0); 5630Sstevel@tonic-gate if (tp->tim_peermaxlen != 0) 5640Sstevel@tonic-gate kmem_free(tp->tim_peername, (size_t)tp->tim_peermaxlen); 5650Sstevel@tonic-gate 5660Sstevel@tonic-gate q->q_ptr = WR(q)->q_ptr = NULL; 5670Sstevel@tonic-gate 5680Sstevel@tonic-gate mutex_destroy(&tp->tim_mutex); 5690Sstevel@tonic-gate 5700Sstevel@tonic-gate if (tp->tim_peercred != NULL) 5710Sstevel@tonic-gate crfree(tp->tim_peercred); 5720Sstevel@tonic-gate 5730Sstevel@tonic-gate kmem_free(tp, sizeof (struct tim_tim)); 5740Sstevel@tonic-gate 5750Sstevel@tonic-gate return (0); 5760Sstevel@tonic-gate } 5770Sstevel@tonic-gate 5780Sstevel@tonic-gate /* 5790Sstevel@tonic-gate * timodrput - Module read put procedure. This is called from 5800Sstevel@tonic-gate * the module, driver, or stream head upstream/downstream. 5810Sstevel@tonic-gate * Handles M_FLUSH, M_DATA and some M_PROTO (T_DATA_IND, 5820Sstevel@tonic-gate * and T_UNITDATA_IND) messages. All others are queued to 5830Sstevel@tonic-gate * be handled by the service procedures. 5840Sstevel@tonic-gate */ 5850Sstevel@tonic-gate static void 5860Sstevel@tonic-gate timodrput(queue_t *q, mblk_t *mp) 5870Sstevel@tonic-gate { 5880Sstevel@tonic-gate union T_primitives *pptr; 5890Sstevel@tonic-gate 5900Sstevel@tonic-gate /* 5910Sstevel@tonic-gate * During flow control and other instances when messages 5920Sstevel@tonic-gate * are on queue, queue up a non high priority message 5930Sstevel@tonic-gate */ 5940Sstevel@tonic-gate if (q->q_first != 0 && mp->b_datap->db_type < QPCTL) { 5950Sstevel@tonic-gate (void) putq(q, mp); 5960Sstevel@tonic-gate return; 5970Sstevel@tonic-gate } 5980Sstevel@tonic-gate 5990Sstevel@tonic-gate /* 6000Sstevel@tonic-gate * Inline processing of data (to avoid additional procedure call). 6010Sstevel@tonic-gate * Rest is handled in timodrproc. 6020Sstevel@tonic-gate */ 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate switch (mp->b_datap->db_type) { 6050Sstevel@tonic-gate case M_DATA: 6060Sstevel@tonic-gate if (bcanputnext(q, mp->b_band)) 6070Sstevel@tonic-gate putnext(q, mp); 6080Sstevel@tonic-gate else 6090Sstevel@tonic-gate (void) putq(q, mp); 6100Sstevel@tonic-gate break; 6110Sstevel@tonic-gate case M_PROTO: 6120Sstevel@tonic-gate case M_PCPROTO: 6130Sstevel@tonic-gate if (MBLKL(mp) < sizeof (t_scalar_t)) { 6140Sstevel@tonic-gate if (mp->b_datap->db_type == M_PCPROTO || 6150Sstevel@tonic-gate bcanputnext(q, mp->b_band)) { 6160Sstevel@tonic-gate putnext(q, mp); 6170Sstevel@tonic-gate } else { 6180Sstevel@tonic-gate (void) putq(q, mp); 6190Sstevel@tonic-gate } 6200Sstevel@tonic-gate break; 6210Sstevel@tonic-gate } 6220Sstevel@tonic-gate pptr = (union T_primitives *)mp->b_rptr; 6230Sstevel@tonic-gate switch (pptr->type) { 6240Sstevel@tonic-gate case T_EXDATA_IND: 6250Sstevel@tonic-gate case T_DATA_IND: 6260Sstevel@tonic-gate case T_UNITDATA_IND: 6270Sstevel@tonic-gate if (bcanputnext(q, mp->b_band)) 6280Sstevel@tonic-gate putnext(q, mp); 6290Sstevel@tonic-gate else 6300Sstevel@tonic-gate (void) putq(q, mp); 6310Sstevel@tonic-gate break; 6320Sstevel@tonic-gate default: 6330Sstevel@tonic-gate (void) timodrproc(q, mp); 6340Sstevel@tonic-gate break; 6350Sstevel@tonic-gate } 6360Sstevel@tonic-gate break; 6370Sstevel@tonic-gate default: 6380Sstevel@tonic-gate (void) timodrproc(q, mp); 6390Sstevel@tonic-gate break; 6400Sstevel@tonic-gate } 6410Sstevel@tonic-gate } 6420Sstevel@tonic-gate 6430Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 6440Sstevel@tonic-gate /* 6450Sstevel@tonic-gate * timodrsrv - Module read queue service procedure. This is called when 6460Sstevel@tonic-gate * messages are placed on an empty queue, when high priority 6470Sstevel@tonic-gate * messages are placed on the queue, and when flow control 6480Sstevel@tonic-gate * restrictions subside. This code used to be included in a 6490Sstevel@tonic-gate * put procedure, but it was moved to a service procedure 6500Sstevel@tonic-gate * because several points were added where memory allocation 6510Sstevel@tonic-gate * could fail, and there is no reasonable recovery mechanism 6520Sstevel@tonic-gate * from the put procedure. 6530Sstevel@tonic-gate */ 6540Sstevel@tonic-gate /*ARGSUSED*/ 6550Sstevel@tonic-gate static void 6560Sstevel@tonic-gate timodrsrv(queue_t *q) 6570Sstevel@tonic-gate { 6580Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 6590Sstevel@tonic-gate mblk_t *mp; 6600Sstevel@tonic-gate struct tim_tim *tp; 6610Sstevel@tonic-gate 6620Sstevel@tonic-gate ASSERT(q != NULL); 6630Sstevel@tonic-gate 6640Sstevel@tonic-gate tp = (struct tim_tim *)q->q_ptr; 6650Sstevel@tonic-gate if (!tp) 6660Sstevel@tonic-gate return; 6670Sstevel@tonic-gate 6680Sstevel@tonic-gate while ((mp = getq(q)) != NULL) { 6690Sstevel@tonic-gate if (timodrproc(q, mp)) { 6700Sstevel@tonic-gate /* 6710Sstevel@tonic-gate * timodrproc did a putbq - stop processing 6720Sstevel@tonic-gate * messages. 6730Sstevel@tonic-gate */ 6740Sstevel@tonic-gate return; 6750Sstevel@tonic-gate } 6760Sstevel@tonic-gate } 6770Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 6780Sstevel@tonic-gate } 6790Sstevel@tonic-gate 6800Sstevel@tonic-gate /* 6810Sstevel@tonic-gate * Perform common processing when a T_CAPABILITY_ACK or T_INFO_ACK 6820Sstevel@tonic-gate * arrive. Set the queue properties and adjust the tim_flags according 6830Sstevel@tonic-gate * to the service type. 6840Sstevel@tonic-gate */ 6850Sstevel@tonic-gate static void 6860Sstevel@tonic-gate timodprocessinfo(queue_t *q, struct tim_tim *tp, struct T_info_ack *tia) 6870Sstevel@tonic-gate { 6880Sstevel@tonic-gate TILOG("timodprocessinfo: strqset(%d)\n", tia->TIDU_size); 6890Sstevel@tonic-gate (void) strqset(q, QMAXPSZ, 0, tia->TIDU_size); 6900Sstevel@tonic-gate (void) strqset(OTHERQ(q), QMAXPSZ, 0, tia->TIDU_size); 6910Sstevel@tonic-gate 6920Sstevel@tonic-gate if ((tia->SERV_type == T_COTS) || (tia->SERV_type == T_COTS_ORD)) 6930Sstevel@tonic-gate tp->tim_flags = (tp->tim_flags & ~CLTS) | COTS; 6940Sstevel@tonic-gate else if (tia->SERV_type == T_CLTS) 6950Sstevel@tonic-gate tp->tim_flags = (tp->tim_flags & ~COTS) | CLTS; 6960Sstevel@tonic-gate } 6970Sstevel@tonic-gate 6980Sstevel@tonic-gate static int 6990Sstevel@tonic-gate timodrproc(queue_t *q, mblk_t *mp) 7000Sstevel@tonic-gate { 7010Sstevel@tonic-gate union T_primitives *pptr; 7020Sstevel@tonic-gate struct tim_tim *tp; 7030Sstevel@tonic-gate struct iocblk *iocbp; 7040Sstevel@tonic-gate mblk_t *nbp; 7050Sstevel@tonic-gate size_t blen; 7060Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 7070Sstevel@tonic-gate 7080Sstevel@tonic-gate tp = (struct tim_tim *)q->q_ptr; 7090Sstevel@tonic-gate 7100Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 7110Sstevel@tonic-gate switch (mp->b_datap->db_type) { 7120Sstevel@tonic-gate default: 7130Sstevel@tonic-gate putnext(q, mp); 7140Sstevel@tonic-gate break; 7150Sstevel@tonic-gate 7160Sstevel@tonic-gate case M_ERROR: 7170Sstevel@tonic-gate TILOG("timodrproc: Got M_ERROR, flags = %x\n", tp->tim_flags); 7180Sstevel@tonic-gate /* 7190Sstevel@tonic-gate * There is no specified standard response for driver when it 7200Sstevel@tonic-gate * receives unknown message type and M_ERROR is one 7210Sstevel@tonic-gate * possibility. If we send T_CAPABILITY_REQ down and transport 7220Sstevel@tonic-gate * provider responds with M_ERROR we assume that it doesn't 7230Sstevel@tonic-gate * understand this message type. This assumption may be 7240Sstevel@tonic-gate * sometimes incorrect (transport may reply with M_ERROR for 7250Sstevel@tonic-gate * some other reason) but there is no way for us to distinguish 7260Sstevel@tonic-gate * between different cases. In the worst case timod and everyone 7270Sstevel@tonic-gate * else sharing global transport description with it may end up 7280Sstevel@tonic-gate * emulating T_CAPABILITY_REQ. 7290Sstevel@tonic-gate */ 7300Sstevel@tonic-gate 7310Sstevel@tonic-gate /* 7320Sstevel@tonic-gate * Check that we are waiting for T_CAPABILITY_ACK and 7330Sstevel@tonic-gate * T_CAPABILITY_REQ is not implemented by transport or emulated 7340Sstevel@tonic-gate * by timod. 7350Sstevel@tonic-gate */ 7360Sstevel@tonic-gate if ((tp->tim_provinfo->tpi_capability == PI_DONTKNOW) && 7370Sstevel@tonic-gate ((tp->tim_flags & TI_CAP_RECVD) != 0)) { 7380Sstevel@tonic-gate /* 7390Sstevel@tonic-gate * Good chances that this transport doesn't provide 7400Sstevel@tonic-gate * T_CAPABILITY_REQ. Mark this information permanently 7410Sstevel@tonic-gate * for the module + transport combination. 7420Sstevel@tonic-gate */ 7430Sstevel@tonic-gate PI_PROVLOCK(tp->tim_provinfo); 7440Sstevel@tonic-gate if (tp->tim_provinfo->tpi_capability == PI_DONTKNOW) 7450Sstevel@tonic-gate tp->tim_provinfo->tpi_capability = PI_NO; 7460Sstevel@tonic-gate PI_PROVUNLOCK(tp->tim_provinfo); 7470Sstevel@tonic-gate if (tp->tim_tcap_timoutid != 0) { 7480Sstevel@tonic-gate (void) quntimeout(q, tp->tim_tcap_timoutid); 7490Sstevel@tonic-gate tp->tim_tcap_timoutid = 0; 7500Sstevel@tonic-gate } 7510Sstevel@tonic-gate } 7520Sstevel@tonic-gate putnext(q, mp); 7530Sstevel@tonic-gate break; 7540Sstevel@tonic-gate case M_DATA: 7550Sstevel@tonic-gate if (!bcanputnext(q, mp->b_band)) { 7560Sstevel@tonic-gate (void) putbq(q, mp); 7570Sstevel@tonic-gate return (1); 7580Sstevel@tonic-gate } 7590Sstevel@tonic-gate putnext(q, mp); 7600Sstevel@tonic-gate break; 7610Sstevel@tonic-gate 7620Sstevel@tonic-gate case M_PROTO: 7630Sstevel@tonic-gate case M_PCPROTO: 7640Sstevel@tonic-gate blen = MBLKL(mp); 7650Sstevel@tonic-gate if (blen < sizeof (t_scalar_t)) { 7660Sstevel@tonic-gate /* 7670Sstevel@tonic-gate * Note: it's not actually possible to get 7680Sstevel@tonic-gate * here with db_type M_PCPROTO, because 7690Sstevel@tonic-gate * timodrput has already checked MBLKL, and 7700Sstevel@tonic-gate * thus the assertion below. If the length 7710Sstevel@tonic-gate * was too short, then the message would have 7720Sstevel@tonic-gate * already been putnext'd, and would thus 7730Sstevel@tonic-gate * never appear here. Just the same, the code 7740Sstevel@tonic-gate * below handles the impossible case since 7750Sstevel@tonic-gate * it's easy to do and saves future 7760Sstevel@tonic-gate * maintainers from unfortunate accidents. 7770Sstevel@tonic-gate */ 7780Sstevel@tonic-gate ASSERT(mp->b_datap->db_type == M_PROTO); 7790Sstevel@tonic-gate if (mp->b_datap->db_type == M_PROTO && 7800Sstevel@tonic-gate !bcanputnext(q, mp->b_band)) { 7810Sstevel@tonic-gate (void) putbq(q, mp); 7820Sstevel@tonic-gate return (1); 7830Sstevel@tonic-gate } 7840Sstevel@tonic-gate putnext(q, mp); 7850Sstevel@tonic-gate break; 7860Sstevel@tonic-gate } 7870Sstevel@tonic-gate 7880Sstevel@tonic-gate pptr = (union T_primitives *)mp->b_rptr; 7890Sstevel@tonic-gate switch (pptr->type) { 7900Sstevel@tonic-gate default: 7910Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 7920Sstevel@tonic-gate 7930Sstevel@tonic-gate #ifdef C2_AUDIT 7940Sstevel@tonic-gate if (audit_active) 7950Sstevel@tonic-gate audit_sock(T_UNITDATA_IND, q, mp, TIMOD_ID); 7960Sstevel@tonic-gate #endif 7970Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 7980Sstevel@tonic-gate putnext(q, mp); 7990Sstevel@tonic-gate break; 8000Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 8010Sstevel@tonic-gate 8020Sstevel@tonic-gate case T_ERROR_ACK: 8030Sstevel@tonic-gate /* Restore db_type - recover() might have changed it */ 8040Sstevel@tonic-gate mp->b_datap->db_type = M_PCPROTO; 8050Sstevel@tonic-gate if (blen < sizeof (struct T_error_ack)) { 8060Sstevel@tonic-gate putnext(q, mp); 8070Sstevel@tonic-gate break; 8080Sstevel@tonic-gate } 8090Sstevel@tonic-gate 8100Sstevel@tonic-gate tilog("timodrproc: Got T_ERROR_ACK, flags = %x\n", 8110Sstevel@tonic-gate tp->tim_flags); 8120Sstevel@tonic-gate 8130Sstevel@tonic-gate if ((tp->tim_flags & WAIT_CONNRESACK) && 8140Sstevel@tonic-gate tp->tim_saved_prim == pptr->error_ack.ERROR_prim) { 8150Sstevel@tonic-gate tp->tim_flags &= 8160Sstevel@tonic-gate ~(WAIT_CONNRESACK | WAITIOCACK); 8170Sstevel@tonic-gate freemsg(tp->tim_iocsave); 8180Sstevel@tonic-gate tp->tim_iocsave = NULL; 8190Sstevel@tonic-gate tp->tim_saved_prim = -1; 8200Sstevel@tonic-gate putnext(q, mp); 8210Sstevel@tonic-gate } else if (tp->tim_flags & WAITIOCACK) { 8220Sstevel@tonic-gate tim_send_ioc_error_ack(q, tp, mp); 8230Sstevel@tonic-gate } else { 8240Sstevel@tonic-gate putnext(q, mp); 8250Sstevel@tonic-gate } 8260Sstevel@tonic-gate break; 8270Sstevel@tonic-gate 8280Sstevel@tonic-gate case T_OK_ACK: 8290Sstevel@tonic-gate if (blen < sizeof (pptr->ok_ack)) { 8300Sstevel@tonic-gate mp->b_datap->db_type = M_PCPROTO; 8310Sstevel@tonic-gate putnext(q, mp); 8320Sstevel@tonic-gate break; 8330Sstevel@tonic-gate } 8340Sstevel@tonic-gate 8350Sstevel@tonic-gate tilog("timodrproc: Got T_OK_ACK\n", 0); 8360Sstevel@tonic-gate 8370Sstevel@tonic-gate if (pptr->ok_ack.CORRECT_prim == T_UNBIND_REQ) 8380Sstevel@tonic-gate tp->tim_mylen = 0; 8390Sstevel@tonic-gate 8400Sstevel@tonic-gate if ((tp->tim_flags & WAIT_CONNRESACK) && 8410Sstevel@tonic-gate tp->tim_saved_prim == pptr->ok_ack.CORRECT_prim) { 8420Sstevel@tonic-gate struct T_conn_res *resp; 8430Sstevel@tonic-gate struct T_conn_ind *indp; 8440Sstevel@tonic-gate struct tim_tim *ntp; 8450Sstevel@tonic-gate caddr_t ptr; 8460Sstevel@tonic-gate 8470Sstevel@tonic-gate rw_enter(&tim_list_rwlock, RW_READER); 8480Sstevel@tonic-gate resp = (struct T_conn_res *) 8490Sstevel@tonic-gate tp->tim_iocsave->b_rptr; 8500Sstevel@tonic-gate ntp = tim_findlink(resp->ACCEPTOR_id); 8510Sstevel@tonic-gate if (ntp == NULL) 8520Sstevel@tonic-gate goto cresackout; 8530Sstevel@tonic-gate 8540Sstevel@tonic-gate mutex_enter(&ntp->tim_mutex); 8550Sstevel@tonic-gate if (ntp->tim_peercred != NULL) 8560Sstevel@tonic-gate crfree(ntp->tim_peercred); 8570Sstevel@tonic-gate ntp->tim_peercred = 8580Sstevel@tonic-gate DB_CRED(tp->tim_iocsave->b_cont); 8590Sstevel@tonic-gate ntp->tim_cpid = 8600Sstevel@tonic-gate DB_CPID(tp->tim_iocsave->b_cont); 8610Sstevel@tonic-gate if (ntp->tim_peercred != NULL) 8620Sstevel@tonic-gate crhold(ntp->tim_peercred); 8630Sstevel@tonic-gate 8640Sstevel@tonic-gate if (!(ntp->tim_flags & DO_PEERNAME)) { 8650Sstevel@tonic-gate mutex_exit(&ntp->tim_mutex); 8660Sstevel@tonic-gate goto cresackout; 8670Sstevel@tonic-gate } 8680Sstevel@tonic-gate 8690Sstevel@tonic-gate indp = (struct T_conn_ind *) 8700Sstevel@tonic-gate tp->tim_iocsave->b_cont->b_rptr; 8710Sstevel@tonic-gate /* true as message is put on list */ 8720Sstevel@tonic-gate ASSERT(indp->SRC_length >= 0); 8730Sstevel@tonic-gate 8740Sstevel@tonic-gate if (indp->SRC_length > ntp->tim_peermaxlen) { 8750Sstevel@tonic-gate ptr = kmem_alloc(indp->SRC_length, 8760Sstevel@tonic-gate KM_NOSLEEP); 8770Sstevel@tonic-gate if (ptr == NULL) { 8780Sstevel@tonic-gate mutex_exit(&ntp->tim_mutex); 8790Sstevel@tonic-gate rw_exit(&tim_list_rwlock); 8800Sstevel@tonic-gate tilog("timodwproc: kmem_alloc " 8810Sstevel@tonic-gate "failed, attempting " 8820Sstevel@tonic-gate "recovery\n", 0); 8830Sstevel@tonic-gate tim_recover(q, mp, 8840Sstevel@tonic-gate indp->SRC_length); 8850Sstevel@tonic-gate return (1); 8860Sstevel@tonic-gate } 8870Sstevel@tonic-gate if (ntp->tim_peermaxlen > 0) 8880Sstevel@tonic-gate kmem_free(ntp->tim_peername, 8890Sstevel@tonic-gate ntp->tim_peermaxlen); 8900Sstevel@tonic-gate ntp->tim_peername = ptr; 8910Sstevel@tonic-gate ntp->tim_peermaxlen = indp->SRC_length; 8920Sstevel@tonic-gate } 8930Sstevel@tonic-gate ntp->tim_peerlen = indp->SRC_length; 8940Sstevel@tonic-gate ptr = (caddr_t)indp + indp->SRC_offset; 8950Sstevel@tonic-gate bcopy(ptr, ntp->tim_peername, ntp->tim_peerlen); 8960Sstevel@tonic-gate 8970Sstevel@tonic-gate mutex_exit(&ntp->tim_mutex); 8980Sstevel@tonic-gate 8990Sstevel@tonic-gate cresackout: 9000Sstevel@tonic-gate rw_exit(&tim_list_rwlock); 9010Sstevel@tonic-gate tp->tim_flags &= 9020Sstevel@tonic-gate ~(WAIT_CONNRESACK | WAITIOCACK); 9030Sstevel@tonic-gate freemsg(tp->tim_iocsave); 9040Sstevel@tonic-gate tp->tim_iocsave = NULL; 9050Sstevel@tonic-gate tp->tim_saved_prim = -1; 9060Sstevel@tonic-gate } 9070Sstevel@tonic-gate 9080Sstevel@tonic-gate tim_send_reply(q, mp, tp, pptr->ok_ack.CORRECT_prim); 9090Sstevel@tonic-gate break; 9100Sstevel@tonic-gate 9110Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 9120Sstevel@tonic-gate case T_BIND_ACK: { 9130Sstevel@tonic-gate struct T_bind_ack *ackp = 9140Sstevel@tonic-gate (struct T_bind_ack *)mp->b_rptr; 9150Sstevel@tonic-gate 9160Sstevel@tonic-gate /* Restore db_type - recover() might have changed it */ 9170Sstevel@tonic-gate mp->b_datap->db_type = M_PCPROTO; 9180Sstevel@tonic-gate if (blen < sizeof (*ackp)) { 9190Sstevel@tonic-gate putnext(q, mp); 9200Sstevel@tonic-gate break; 9210Sstevel@tonic-gate } 9220Sstevel@tonic-gate 9230Sstevel@tonic-gate /* save negotiated backlog */ 9240Sstevel@tonic-gate tp->tim_backlog = ackp->CONIND_number; 9250Sstevel@tonic-gate 9260Sstevel@tonic-gate if (((tp->tim_flags & WAITIOCACK) == 0) || 9270Sstevel@tonic-gate ((tp->tim_saved_prim != O_T_BIND_REQ) && 9280Sstevel@tonic-gate (tp->tim_saved_prim != T_BIND_REQ))) { 9290Sstevel@tonic-gate putnext(q, mp); 9300Sstevel@tonic-gate break; 9310Sstevel@tonic-gate } 9320Sstevel@tonic-gate ASSERT(tp->tim_iocsave != NULL); 9330Sstevel@tonic-gate 9340Sstevel@tonic-gate if (tp->tim_flags & DO_MYNAME) { 9350Sstevel@tonic-gate caddr_t p; 9360Sstevel@tonic-gate 9370Sstevel@tonic-gate if (ackp->ADDR_length < 0 || 9380Sstevel@tonic-gate mp->b_rptr + ackp->ADDR_offset + 9390Sstevel@tonic-gate ackp->ADDR_length > mp->b_wptr) { 9400Sstevel@tonic-gate putnext(q, mp); 9410Sstevel@tonic-gate break; 9420Sstevel@tonic-gate } 9430Sstevel@tonic-gate if (ackp->ADDR_length > tp->tim_mymaxlen) { 9440Sstevel@tonic-gate p = kmem_alloc(ackp->ADDR_length, 9450Sstevel@tonic-gate KM_NOSLEEP); 9460Sstevel@tonic-gate if (p == NULL) { 9470Sstevel@tonic-gate tilog("timodrproc: kmem_alloc " 9480Sstevel@tonic-gate "failed attempt recovery", 9490Sstevel@tonic-gate 0); 9500Sstevel@tonic-gate 9510Sstevel@tonic-gate tim_recover(q, mp, 9520Sstevel@tonic-gate ackp->ADDR_length); 9530Sstevel@tonic-gate return (1); 9540Sstevel@tonic-gate } 9550Sstevel@tonic-gate ASSERT(tp->tim_mymaxlen >= 0); 9560Sstevel@tonic-gate if (tp->tim_mymaxlen != NULL) { 9570Sstevel@tonic-gate kmem_free(tp->tim_myname, 9580Sstevel@tonic-gate tp->tim_mymaxlen); 9590Sstevel@tonic-gate } 9600Sstevel@tonic-gate tp->tim_myname = p; 9610Sstevel@tonic-gate tp->tim_mymaxlen = ackp->ADDR_length; 9620Sstevel@tonic-gate } 9630Sstevel@tonic-gate tp->tim_mylen = ackp->ADDR_length; 9640Sstevel@tonic-gate bcopy(mp->b_rptr + ackp->ADDR_offset, 9650Sstevel@tonic-gate tp->tim_myname, tp->tim_mylen); 9660Sstevel@tonic-gate } 9670Sstevel@tonic-gate tim_ioctl_send_reply(q, tp->tim_iocsave, mp); 9680Sstevel@tonic-gate tp->tim_iocsave = NULL; 9690Sstevel@tonic-gate tp->tim_saved_prim = -1; 9700Sstevel@tonic-gate tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 9710Sstevel@tonic-gate TI_CAP_RECVD | CAP_WANTS_INFO); 9720Sstevel@tonic-gate break; 9730Sstevel@tonic-gate } 9740Sstevel@tonic-gate 9750Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 9760Sstevel@tonic-gate case T_OPTMGMT_ACK: 9770Sstevel@tonic-gate 9780Sstevel@tonic-gate tilog("timodrproc: Got T_OPTMGMT_ACK\n", 0); 9790Sstevel@tonic-gate 9800Sstevel@tonic-gate /* Restore db_type - recover() might have change it */ 9810Sstevel@tonic-gate mp->b_datap->db_type = M_PCPROTO; 9820Sstevel@tonic-gate 9830Sstevel@tonic-gate if (((tp->tim_flags & WAITIOCACK) == 0) || 9840Sstevel@tonic-gate ((tp->tim_saved_prim != T_SVR4_OPTMGMT_REQ) && 9850Sstevel@tonic-gate (tp->tim_saved_prim != T_OPTMGMT_REQ))) { 9860Sstevel@tonic-gate putnext(q, mp); 9870Sstevel@tonic-gate } else { 9880Sstevel@tonic-gate ASSERT(tp->tim_iocsave != NULL); 9890Sstevel@tonic-gate tim_ioctl_send_reply(q, tp->tim_iocsave, mp); 9900Sstevel@tonic-gate tp->tim_iocsave = NULL; 9910Sstevel@tonic-gate tp->tim_saved_prim = -1; 9920Sstevel@tonic-gate tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 9930Sstevel@tonic-gate TI_CAP_RECVD | CAP_WANTS_INFO); 9940Sstevel@tonic-gate } 9950Sstevel@tonic-gate break; 9960Sstevel@tonic-gate 9970Sstevel@tonic-gate case T_INFO_ACK: { 9980Sstevel@tonic-gate struct T_info_ack *tia = (struct T_info_ack *)pptr; 9990Sstevel@tonic-gate 10000Sstevel@tonic-gate /* Restore db_type - recover() might have changed it */ 10010Sstevel@tonic-gate mp->b_datap->db_type = M_PCPROTO; 10020Sstevel@tonic-gate 10030Sstevel@tonic-gate if (blen < sizeof (*tia)) { 10040Sstevel@tonic-gate putnext(q, mp); 10050Sstevel@tonic-gate break; 10060Sstevel@tonic-gate } 10070Sstevel@tonic-gate 10080Sstevel@tonic-gate tilog("timodrproc: Got T_INFO_ACK, flags = %x\n", 10090Sstevel@tonic-gate tp->tim_flags); 10100Sstevel@tonic-gate 10110Sstevel@tonic-gate timodprocessinfo(q, tp, tia); 10120Sstevel@tonic-gate 10130Sstevel@tonic-gate TILOG("timodrproc: flags = %x\n", tp->tim_flags); 10140Sstevel@tonic-gate if ((tp->tim_flags & WAITIOCACK) != 0) { 10150Sstevel@tonic-gate size_t expected_ack_size; 10160Sstevel@tonic-gate ssize_t deficit; 10170Sstevel@tonic-gate int ioc_cmd; 10180Sstevel@tonic-gate struct T_capability_ack *tcap; 10190Sstevel@tonic-gate 10200Sstevel@tonic-gate /* 10210Sstevel@tonic-gate * The only case when T_INFO_ACK may be received back 10220Sstevel@tonic-gate * when we are waiting for ioctl to complete is when 10230Sstevel@tonic-gate * this ioctl sent T_INFO_REQ down. 10240Sstevel@tonic-gate */ 10250Sstevel@tonic-gate if (!(tp->tim_flags & WAIT_IOCINFOACK)) { 10260Sstevel@tonic-gate putnext(q, mp); 10270Sstevel@tonic-gate break; 10280Sstevel@tonic-gate } 10290Sstevel@tonic-gate ASSERT(tp->tim_iocsave != NULL); 10300Sstevel@tonic-gate 10310Sstevel@tonic-gate iocbp = (struct iocblk *)tp->tim_iocsave->b_rptr; 10320Sstevel@tonic-gate ioc_cmd = iocbp->ioc_cmd; 10330Sstevel@tonic-gate 10340Sstevel@tonic-gate /* 10350Sstevel@tonic-gate * Was it sent from TI_CAPABILITY emulation? 10360Sstevel@tonic-gate */ 10370Sstevel@tonic-gate if (ioc_cmd == TI_CAPABILITY) { 10380Sstevel@tonic-gate struct T_info_ack saved_info; 10390Sstevel@tonic-gate 10400Sstevel@tonic-gate /* 10410Sstevel@tonic-gate * Perform sanity checks. The only case when we 10420Sstevel@tonic-gate * send T_INFO_REQ from TI_CAPABILITY is when 10430Sstevel@tonic-gate * timod emulates T_CAPABILITY_REQ and CAP_bits1 10440Sstevel@tonic-gate * has TC1_INFO set. 10450Sstevel@tonic-gate */ 10460Sstevel@tonic-gate if ((tp->tim_flags & 10470Sstevel@tonic-gate (TI_CAP_RECVD | CAP_WANTS_INFO)) != 10480Sstevel@tonic-gate (TI_CAP_RECVD | CAP_WANTS_INFO)) { 10490Sstevel@tonic-gate putnext(q, mp); 10500Sstevel@tonic-gate break; 10510Sstevel@tonic-gate } 10520Sstevel@tonic-gate 10530Sstevel@tonic-gate TILOG("timodrproc: emulating TI_CAPABILITY/" 10540Sstevel@tonic-gate "info\n", 0); 10550Sstevel@tonic-gate 10560Sstevel@tonic-gate /* Save info & reuse mp for T_CAPABILITY_ACK */ 10570Sstevel@tonic-gate saved_info = *tia; 10580Sstevel@tonic-gate 10590Sstevel@tonic-gate mp = tpi_ack_alloc(mp, 10600Sstevel@tonic-gate sizeof (struct T_capability_ack), 10610Sstevel@tonic-gate M_PCPROTO, T_CAPABILITY_ACK); 10620Sstevel@tonic-gate 10630Sstevel@tonic-gate if (mp == NULL) { 10640Sstevel@tonic-gate tilog("timodrproc: realloc failed, " 10650Sstevel@tonic-gate "no recovery attempted\n", 0); 10660Sstevel@tonic-gate return (1); 10670Sstevel@tonic-gate } 10680Sstevel@tonic-gate 10690Sstevel@tonic-gate /* 10700Sstevel@tonic-gate * Copy T_INFO information into T_CAPABILITY_ACK 10710Sstevel@tonic-gate */ 10720Sstevel@tonic-gate tcap = (struct T_capability_ack *)mp->b_rptr; 10730Sstevel@tonic-gate tcap->CAP_bits1 = TC1_INFO; 10740Sstevel@tonic-gate tcap->INFO_ack = saved_info; 10750Sstevel@tonic-gate tp->tim_flags &= ~(WAITIOCACK | 10760Sstevel@tonic-gate WAIT_IOCINFOACK | TI_CAP_RECVD | 10770Sstevel@tonic-gate CAP_WANTS_INFO); 10780Sstevel@tonic-gate tim_ioctl_send_reply(q, tp->tim_iocsave, mp); 10790Sstevel@tonic-gate tp->tim_iocsave = NULL; 10800Sstevel@tonic-gate tp->tim_saved_prim = -1; 10810Sstevel@tonic-gate break; 10820Sstevel@tonic-gate } 10830Sstevel@tonic-gate 10840Sstevel@tonic-gate /* 10850Sstevel@tonic-gate * The code for TI_SYNC/TI_GETINFO is left here only for 10860Sstevel@tonic-gate * backward compatibility with staticaly linked old 10870Sstevel@tonic-gate * applications. New TLI/XTI code should use 10880Sstevel@tonic-gate * TI_CAPABILITY for getting transport info and should 10890Sstevel@tonic-gate * not use TI_GETINFO/TI_SYNC for this purpose. 10900Sstevel@tonic-gate */ 10910Sstevel@tonic-gate 10920Sstevel@tonic-gate /* 10930Sstevel@tonic-gate * make sure the message sent back is the size of 10940Sstevel@tonic-gate * the "expected ack" 10950Sstevel@tonic-gate * For TI_GETINFO, expected ack size is 10960Sstevel@tonic-gate * sizeof (T_info_ack) 10970Sstevel@tonic-gate * For TI_SYNC, expected ack size is 10980Sstevel@tonic-gate * sizeof (struct ti_sync_ack); 10990Sstevel@tonic-gate */ 11000Sstevel@tonic-gate if (ioc_cmd != TI_GETINFO && ioc_cmd != TI_SYNC) { 11010Sstevel@tonic-gate putnext(q, mp); 11020Sstevel@tonic-gate break; 11030Sstevel@tonic-gate } 11040Sstevel@tonic-gate 11050Sstevel@tonic-gate expected_ack_size = 11060Sstevel@tonic-gate sizeof (struct T_info_ack); /* TI_GETINFO */ 11070Sstevel@tonic-gate if (iocbp->ioc_cmd == TI_SYNC) { 11080Sstevel@tonic-gate expected_ack_size = 2 * sizeof (uint32_t) + 11090Sstevel@tonic-gate sizeof (struct ti_sync_ack); 11100Sstevel@tonic-gate } 11110Sstevel@tonic-gate deficit = expected_ack_size - blen; 11120Sstevel@tonic-gate 11130Sstevel@tonic-gate if (deficit != 0) { 11140Sstevel@tonic-gate if (mp->b_datap->db_lim - mp->b_wptr < 11150Sstevel@tonic-gate deficit) { 11160Sstevel@tonic-gate mblk_t *tmp = allocb(expected_ack_size, 11170Sstevel@tonic-gate BPRI_HI); 11180Sstevel@tonic-gate if (tmp == NULL) { 11190Sstevel@tonic-gate ASSERT((mp->b_datap->db_lim - 11200Sstevel@tonic-gate mp->b_datap->db_base) < 11210Sstevel@tonic-gate sizeof (struct T_error_ack)); 11220Sstevel@tonic-gate 11230Sstevel@tonic-gate tilog("timodrproc: allocb failed no " 11240Sstevel@tonic-gate "recovery attempt\n", 0); 11250Sstevel@tonic-gate 11260Sstevel@tonic-gate mp->b_rptr = mp->b_datap->db_base; 11270Sstevel@tonic-gate pptr = (union T_primitives *) 11280Sstevel@tonic-gate mp->b_rptr; 11290Sstevel@tonic-gate pptr->error_ack.ERROR_prim = T_INFO_ACK; 11300Sstevel@tonic-gate pptr->error_ack.TLI_error = TSYSERR; 11310Sstevel@tonic-gate pptr->error_ack.UNIX_error = EAGAIN; 11320Sstevel@tonic-gate pptr->error_ack.PRIM_type = T_ERROR_ACK; 11330Sstevel@tonic-gate mp->b_datap->db_type = M_PCPROTO; 11340Sstevel@tonic-gate tim_send_ioc_error_ack(q, tp, mp); 11350Sstevel@tonic-gate break; 11360Sstevel@tonic-gate } else { 11370Sstevel@tonic-gate bcopy(mp->b_rptr, tmp->b_rptr, blen); 11380Sstevel@tonic-gate tmp->b_wptr += blen; 11390Sstevel@tonic-gate pptr = (union T_primitives *) 11400Sstevel@tonic-gate tmp->b_rptr; 11410Sstevel@tonic-gate freemsg(mp); 11420Sstevel@tonic-gate mp = tmp; 11430Sstevel@tonic-gate } 11440Sstevel@tonic-gate } 11450Sstevel@tonic-gate } 11460Sstevel@tonic-gate /* 11470Sstevel@tonic-gate * We now have "mp" which has enough space for an 11480Sstevel@tonic-gate * appropriate ack and contains struct T_info_ack 11490Sstevel@tonic-gate * that the transport provider returned. We now 11500Sstevel@tonic-gate * stuff it with more stuff to fullfill 11510Sstevel@tonic-gate * TI_SYNC ioctl needs, as necessary 11520Sstevel@tonic-gate */ 11530Sstevel@tonic-gate if (iocbp->ioc_cmd == TI_SYNC) { 11540Sstevel@tonic-gate /* 11550Sstevel@tonic-gate * Assumes struct T_info_ack is first embedded 11560Sstevel@tonic-gate * type in struct ti_sync_ack so it is 11570Sstevel@tonic-gate * automatically there. 11580Sstevel@tonic-gate */ 11590Sstevel@tonic-gate struct ti_sync_ack *tsap = 11600Sstevel@tonic-gate (struct ti_sync_ack *)mp->b_rptr; 11610Sstevel@tonic-gate 11620Sstevel@tonic-gate /* 11630Sstevel@tonic-gate * tsap->tsa_qlen needs to be set only if 11640Sstevel@tonic-gate * TSRF_QLEN_REQ flag is set, but for 11650Sstevel@tonic-gate * compatibility with statically linked 11660Sstevel@tonic-gate * applications it is set here regardless of the 11670Sstevel@tonic-gate * flag since old XTI library expected it to be 11680Sstevel@tonic-gate * set. 11690Sstevel@tonic-gate */ 11700Sstevel@tonic-gate tsap->tsa_qlen = tp->tim_backlog; 11710Sstevel@tonic-gate tsap->tsa_flags = 0x0; /* intialize clear */ 11720Sstevel@tonic-gate if (tp->tim_flags & PEEK_RDQ_EXPIND) { 11730Sstevel@tonic-gate /* 11740Sstevel@tonic-gate * Request to peek for EXPIND in 11750Sstevel@tonic-gate * rcvbuf. 11760Sstevel@tonic-gate */ 11770Sstevel@tonic-gate if (ti_expind_on_rdqueues(q)) { 11780Sstevel@tonic-gate /* 11790Sstevel@tonic-gate * Expedited data is 11800Sstevel@tonic-gate * queued on the stream 11810Sstevel@tonic-gate * read side 11820Sstevel@tonic-gate */ 11830Sstevel@tonic-gate tsap->tsa_flags |= 11840Sstevel@tonic-gate TSAF_EXP_QUEUED; 11850Sstevel@tonic-gate } 11860Sstevel@tonic-gate tp->tim_flags &= 11870Sstevel@tonic-gate ~PEEK_RDQ_EXPIND; 11880Sstevel@tonic-gate } 11890Sstevel@tonic-gate mp->b_wptr += 2*sizeof (uint32_t); 11900Sstevel@tonic-gate } 11910Sstevel@tonic-gate tim_ioctl_send_reply(q, tp->tim_iocsave, mp); 11920Sstevel@tonic-gate tp->tim_iocsave = NULL; 11930Sstevel@tonic-gate tp->tim_saved_prim = -1; 11940Sstevel@tonic-gate tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 11950Sstevel@tonic-gate TI_CAP_RECVD | CAP_WANTS_INFO); 11960Sstevel@tonic-gate break; 11970Sstevel@tonic-gate } 11980Sstevel@tonic-gate } 11990Sstevel@tonic-gate 12000Sstevel@tonic-gate putnext(q, mp); 12010Sstevel@tonic-gate break; 12020Sstevel@tonic-gate 12030Sstevel@tonic-gate case T_ADDR_ACK: 12040Sstevel@tonic-gate tilog("timodrproc: Got T_ADDR_ACK\n", 0); 12050Sstevel@tonic-gate tim_send_reply(q, mp, tp, T_ADDR_REQ); 12060Sstevel@tonic-gate break; 12070Sstevel@tonic-gate 12080Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 12090Sstevel@tonic-gate case T_CONN_IND: { 12100Sstevel@tonic-gate struct T_conn_ind *tcip = 12110Sstevel@tonic-gate (struct T_conn_ind *)mp->b_rptr; 12120Sstevel@tonic-gate 12130Sstevel@tonic-gate tilog("timodrproc: Got T_CONN_IND\n", 0); 12140Sstevel@tonic-gate 12150Sstevel@tonic-gate if (blen >= sizeof (*tcip) && 12160Sstevel@tonic-gate MBLKIN(mp, tcip->SRC_offset, tcip->SRC_length)) { 12170Sstevel@tonic-gate if (((nbp = dupmsg(mp)) != NULL) || 12180Sstevel@tonic-gate ((nbp = copymsg(mp)) != NULL)) { 12190Sstevel@tonic-gate nbp->b_next = tp->tim_consave; 12200Sstevel@tonic-gate tp->tim_consave = nbp; 12210Sstevel@tonic-gate } else { 12220Sstevel@tonic-gate tim_recover(q, mp, 12230Sstevel@tonic-gate (t_scalar_t)sizeof (mblk_t)); 12240Sstevel@tonic-gate return (1); 12250Sstevel@tonic-gate } 12260Sstevel@tonic-gate } 12270Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 12280Sstevel@tonic-gate #ifdef C2_AUDIT 12290Sstevel@tonic-gate if (audit_active) 12300Sstevel@tonic-gate audit_sock(T_CONN_IND, q, mp, TIMOD_ID); 12310Sstevel@tonic-gate #endif 12320Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 12330Sstevel@tonic-gate putnext(q, mp); 12340Sstevel@tonic-gate break; 12350Sstevel@tonic-gate } 12360Sstevel@tonic-gate 12370Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 12380Sstevel@tonic-gate case T_CONN_CON: 12390Sstevel@tonic-gate mutex_enter(&tp->tim_mutex); 12400Sstevel@tonic-gate if (tp->tim_peercred != NULL) 12410Sstevel@tonic-gate crfree(tp->tim_peercred); 12420Sstevel@tonic-gate tp->tim_peercred = DB_CRED(mp); 12430Sstevel@tonic-gate if (tp->tim_peercred != NULL) 12440Sstevel@tonic-gate crhold(tp->tim_peercred); 12450Sstevel@tonic-gate tp->tim_cpid = DB_CPID(mp); 12460Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 12470Sstevel@tonic-gate 12480Sstevel@tonic-gate tilog("timodrproc: Got T_CONN_CON\n", 0); 12490Sstevel@tonic-gate 12500Sstevel@tonic-gate tp->tim_flags &= ~CONNWAIT; 12510Sstevel@tonic-gate putnext(q, mp); 12520Sstevel@tonic-gate break; 12530Sstevel@tonic-gate 12540Sstevel@tonic-gate case T_DISCON_IND: { 12550Sstevel@tonic-gate struct T_discon_ind *disp; 12560Sstevel@tonic-gate struct T_conn_ind *conp; 12570Sstevel@tonic-gate mblk_t *pbp = NULL; 12580Sstevel@tonic-gate 12590Sstevel@tonic-gate if (q->q_first != 0) 12600Sstevel@tonic-gate tilog("timodrput: T_DISCON_IND - flow control\n", 0); 12610Sstevel@tonic-gate 12620Sstevel@tonic-gate if (blen < sizeof (*disp)) { 12630Sstevel@tonic-gate putnext(q, mp); 12640Sstevel@tonic-gate break; 12650Sstevel@tonic-gate } 12660Sstevel@tonic-gate 12670Sstevel@tonic-gate disp = (struct T_discon_ind *)mp->b_rptr; 12680Sstevel@tonic-gate 12690Sstevel@tonic-gate tilog("timodrproc: Got T_DISCON_IND Reason: %d\n", 12700Sstevel@tonic-gate disp->DISCON_reason); 12710Sstevel@tonic-gate 12720Sstevel@tonic-gate tp->tim_flags &= ~(CONNWAIT|LOCORDREL|REMORDREL); 12730Sstevel@tonic-gate tim_clear_peer(tp); 12740Sstevel@tonic-gate for (nbp = tp->tim_consave; nbp; nbp = nbp->b_next) { 12750Sstevel@tonic-gate conp = (struct T_conn_ind *)nbp->b_rptr; 12760Sstevel@tonic-gate if (conp->SEQ_number == disp->SEQ_number) 12770Sstevel@tonic-gate break; 12780Sstevel@tonic-gate pbp = nbp; 12790Sstevel@tonic-gate } 12800Sstevel@tonic-gate if (nbp) { 12810Sstevel@tonic-gate if (pbp) 12820Sstevel@tonic-gate pbp->b_next = nbp->b_next; 12830Sstevel@tonic-gate else 12840Sstevel@tonic-gate tp->tim_consave = nbp->b_next; 12850Sstevel@tonic-gate nbp->b_next = NULL; 12860Sstevel@tonic-gate freemsg(nbp); 12870Sstevel@tonic-gate } 12880Sstevel@tonic-gate putnext(q, mp); 12890Sstevel@tonic-gate break; 12900Sstevel@tonic-gate } 12910Sstevel@tonic-gate 12920Sstevel@tonic-gate case T_ORDREL_IND: 12930Sstevel@tonic-gate 12940Sstevel@tonic-gate tilog("timodrproc: Got T_ORDREL_IND\n", 0); 12950Sstevel@tonic-gate 12960Sstevel@tonic-gate if (tp->tim_flags & LOCORDREL) { 12970Sstevel@tonic-gate tp->tim_flags &= ~(LOCORDREL|REMORDREL); 12980Sstevel@tonic-gate tim_clear_peer(tp); 12990Sstevel@tonic-gate } else { 13000Sstevel@tonic-gate tp->tim_flags |= REMORDREL; 13010Sstevel@tonic-gate } 13020Sstevel@tonic-gate putnext(q, mp); 13030Sstevel@tonic-gate break; 13040Sstevel@tonic-gate 13050Sstevel@tonic-gate case T_EXDATA_IND: 13060Sstevel@tonic-gate case T_DATA_IND: 13070Sstevel@tonic-gate case T_UNITDATA_IND: 13080Sstevel@tonic-gate if (pptr->type == T_EXDATA_IND) 13090Sstevel@tonic-gate tilog("timodrproc: Got T_EXDATA_IND\n", 0); 13100Sstevel@tonic-gate 13110Sstevel@tonic-gate if (!bcanputnext(q, mp->b_band)) { 13120Sstevel@tonic-gate (void) putbq(q, mp); 13130Sstevel@tonic-gate return (1); 13140Sstevel@tonic-gate } 13150Sstevel@tonic-gate putnext(q, mp); 13160Sstevel@tonic-gate break; 13170Sstevel@tonic-gate 13180Sstevel@tonic-gate case T_CAPABILITY_ACK: { 13190Sstevel@tonic-gate struct T_capability_ack *tca; 13200Sstevel@tonic-gate 13210Sstevel@tonic-gate if (blen < sizeof (*tca)) { 13220Sstevel@tonic-gate putnext(q, mp); 13230Sstevel@tonic-gate break; 13240Sstevel@tonic-gate } 13250Sstevel@tonic-gate 13260Sstevel@tonic-gate /* This transport supports T_CAPABILITY_REQ */ 13270Sstevel@tonic-gate tilog("timodrproc: Got T_CAPABILITY_ACK\n", 0); 13280Sstevel@tonic-gate 13290Sstevel@tonic-gate PI_PROVLOCK(tp->tim_provinfo); 13300Sstevel@tonic-gate if (tp->tim_provinfo->tpi_capability != PI_YES) 13310Sstevel@tonic-gate tp->tim_provinfo->tpi_capability = PI_YES; 13320Sstevel@tonic-gate PI_PROVUNLOCK(tp->tim_provinfo); 13330Sstevel@tonic-gate 13340Sstevel@tonic-gate /* Reset possible pending timeout */ 13350Sstevel@tonic-gate if (tp->tim_tcap_timoutid != 0) { 13360Sstevel@tonic-gate (void) quntimeout(q, tp->tim_tcap_timoutid); 13370Sstevel@tonic-gate tp->tim_tcap_timoutid = 0; 13380Sstevel@tonic-gate } 13390Sstevel@tonic-gate 13400Sstevel@tonic-gate tca = (struct T_capability_ack *)mp->b_rptr; 13410Sstevel@tonic-gate 13420Sstevel@tonic-gate if (tca->CAP_bits1 & TC1_INFO) 13430Sstevel@tonic-gate timodprocessinfo(q, tp, &tca->INFO_ack); 13440Sstevel@tonic-gate 13450Sstevel@tonic-gate tim_send_reply(q, mp, tp, T_CAPABILITY_REQ); 13460Sstevel@tonic-gate } 13470Sstevel@tonic-gate break; 13480Sstevel@tonic-gate } 13490Sstevel@tonic-gate break; 13500Sstevel@tonic-gate 13510Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 13520Sstevel@tonic-gate case M_FLUSH: 13530Sstevel@tonic-gate 13540Sstevel@tonic-gate tilog("timodrproc: Got M_FLUSH\n", 0); 13550Sstevel@tonic-gate 13560Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR) { 13570Sstevel@tonic-gate if (*mp->b_rptr & FLUSHBAND) 13580Sstevel@tonic-gate flushband(q, *(mp->b_rptr + 1), FLUSHDATA); 13590Sstevel@tonic-gate else 13600Sstevel@tonic-gate flushq(q, FLUSHDATA); 13610Sstevel@tonic-gate } 13620Sstevel@tonic-gate putnext(q, mp); 13630Sstevel@tonic-gate break; 13640Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 13650Sstevel@tonic-gate 13660Sstevel@tonic-gate case M_IOCACK: 13670Sstevel@tonic-gate iocbp = (struct iocblk *)mp->b_rptr; 13680Sstevel@tonic-gate 13690Sstevel@tonic-gate tilog("timodrproc: Got M_IOCACK\n", 0); 13700Sstevel@tonic-gate 13710Sstevel@tonic-gate if (iocbp->ioc_cmd == TI_GETMYNAME) { 13720Sstevel@tonic-gate 13730Sstevel@tonic-gate /* 13740Sstevel@tonic-gate * Transport provider supports this ioctl, 13750Sstevel@tonic-gate * so I don't have to. 13760Sstevel@tonic-gate */ 13770Sstevel@tonic-gate if ((tp->tim_flags & DO_MYNAME) != 0) { 13780Sstevel@tonic-gate tp->tim_flags &= ~DO_MYNAME; 13790Sstevel@tonic-gate PI_PROVLOCK(tp->tim_provinfo); 13800Sstevel@tonic-gate tp->tim_provinfo->tpi_myname = PI_YES; 13810Sstevel@tonic-gate PI_PROVUNLOCK(tp->tim_provinfo); 13820Sstevel@tonic-gate } 13830Sstevel@tonic-gate 13840Sstevel@tonic-gate ASSERT(tp->tim_mymaxlen >= 0); 13850Sstevel@tonic-gate if (tp->tim_mymaxlen != 0) { 13860Sstevel@tonic-gate kmem_free(tp->tim_myname, (size_t)tp->tim_mymaxlen); 13870Sstevel@tonic-gate tp->tim_myname = NULL; 13880Sstevel@tonic-gate tp->tim_mymaxlen = 0; 13890Sstevel@tonic-gate } 13900Sstevel@tonic-gate /* tim_iocsave may already be overwritten. */ 13910Sstevel@tonic-gate if (tp->tim_saved_prim == -1) { 13920Sstevel@tonic-gate freemsg(tp->tim_iocsave); 13930Sstevel@tonic-gate tp->tim_iocsave = NULL; 13940Sstevel@tonic-gate } 13950Sstevel@tonic-gate } else if (iocbp->ioc_cmd == TI_GETPEERNAME) { 13960Sstevel@tonic-gate boolean_t clearit; 13970Sstevel@tonic-gate 13980Sstevel@tonic-gate /* 13990Sstevel@tonic-gate * Transport provider supports this ioctl, 14000Sstevel@tonic-gate * so I don't have to. 14010Sstevel@tonic-gate */ 14020Sstevel@tonic-gate if ((tp->tim_flags & DO_PEERNAME) != 0) { 14030Sstevel@tonic-gate tp->tim_flags &= ~DO_PEERNAME; 14040Sstevel@tonic-gate PI_PROVLOCK(tp->tim_provinfo); 14050Sstevel@tonic-gate tp->tim_provinfo->tpi_peername = PI_YES; 14060Sstevel@tonic-gate PI_PROVUNLOCK(tp->tim_provinfo); 14070Sstevel@tonic-gate } 14080Sstevel@tonic-gate 14090Sstevel@tonic-gate mutex_enter(&tp->tim_mutex); 14100Sstevel@tonic-gate ASSERT(tp->tim_peermaxlen >= 0); 14110Sstevel@tonic-gate clearit = tp->tim_peermaxlen != 0; 14120Sstevel@tonic-gate if (clearit) { 14130Sstevel@tonic-gate kmem_free(tp->tim_peername, tp->tim_peermaxlen); 14140Sstevel@tonic-gate tp->tim_peername = NULL; 14150Sstevel@tonic-gate tp->tim_peermaxlen = 0; 14160Sstevel@tonic-gate tp->tim_peerlen = 0; 14170Sstevel@tonic-gate } 14180Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 14190Sstevel@tonic-gate if (clearit) { 14200Sstevel@tonic-gate mblk_t *bp; 14210Sstevel@tonic-gate 14220Sstevel@tonic-gate bp = tp->tim_consave; 14230Sstevel@tonic-gate while (bp != NULL) { 14240Sstevel@tonic-gate nbp = bp->b_next; 14250Sstevel@tonic-gate bp->b_next = NULL; 14260Sstevel@tonic-gate freemsg(bp); 14270Sstevel@tonic-gate bp = nbp; 14280Sstevel@tonic-gate } 14290Sstevel@tonic-gate tp->tim_consave = NULL; 14300Sstevel@tonic-gate } 14310Sstevel@tonic-gate /* tim_iocsave may already be overwritten. */ 14320Sstevel@tonic-gate if (tp->tim_saved_prim == -1) { 14330Sstevel@tonic-gate freemsg(tp->tim_iocsave); 14340Sstevel@tonic-gate tp->tim_iocsave = NULL; 14350Sstevel@tonic-gate } 14360Sstevel@tonic-gate } 14370Sstevel@tonic-gate putnext(q, mp); 14380Sstevel@tonic-gate break; 14390Sstevel@tonic-gate 14400Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 14410Sstevel@tonic-gate case M_IOCNAK: 14420Sstevel@tonic-gate 14430Sstevel@tonic-gate tilog("timodrproc: Got M_IOCNAK\n", 0); 14440Sstevel@tonic-gate 14450Sstevel@tonic-gate iocbp = (struct iocblk *)mp->b_rptr; 14460Sstevel@tonic-gate if (((iocbp->ioc_cmd == TI_GETMYNAME) || 14470Sstevel@tonic-gate (iocbp->ioc_cmd == TI_GETPEERNAME)) && 14480Sstevel@tonic-gate ((iocbp->ioc_error == EINVAL) || (iocbp->ioc_error == 0))) { 14490Sstevel@tonic-gate PI_PROVLOCK(tp->tim_provinfo); 14500Sstevel@tonic-gate if (iocbp->ioc_cmd == TI_GETMYNAME) { 14510Sstevel@tonic-gate if (tp->tim_provinfo->tpi_myname == PI_DONTKNOW) 14520Sstevel@tonic-gate tp->tim_provinfo->tpi_myname = PI_NO; 14530Sstevel@tonic-gate } else if (iocbp->ioc_cmd == TI_GETPEERNAME) { 14540Sstevel@tonic-gate if (tp->tim_provinfo->tpi_peername == PI_DONTKNOW) 14550Sstevel@tonic-gate tp->tim_provinfo->tpi_peername = PI_NO; 14560Sstevel@tonic-gate } 14570Sstevel@tonic-gate PI_PROVUNLOCK(tp->tim_provinfo); 14580Sstevel@tonic-gate /* tim_iocsave may already be overwritten. */ 14590Sstevel@tonic-gate if ((tp->tim_iocsave != NULL) && 14600Sstevel@tonic-gate (tp->tim_saved_prim == -1)) { 14610Sstevel@tonic-gate freemsg(mp); 14620Sstevel@tonic-gate mp = tp->tim_iocsave; 14630Sstevel@tonic-gate tp->tim_iocsave = NULL; 14640Sstevel@tonic-gate tp->tim_flags |= NAMEPROC; 14650Sstevel@tonic-gate if (ti_doname(WR(q), mp) != DONAME_CONT) { 14660Sstevel@tonic-gate tp->tim_flags &= ~NAMEPROC; 14670Sstevel@tonic-gate } 14680Sstevel@tonic-gate break; 14690Sstevel@tonic-gate } 14700Sstevel@tonic-gate } 14710Sstevel@tonic-gate putnext(q, mp); 14720Sstevel@tonic-gate break; 14730Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 14740Sstevel@tonic-gate } 14750Sstevel@tonic-gate 14760Sstevel@tonic-gate return (0); 14770Sstevel@tonic-gate } 14780Sstevel@tonic-gate 14790Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 14800Sstevel@tonic-gate /* 14810Sstevel@tonic-gate * timodwput - Module write put procedure. This is called from 14820Sstevel@tonic-gate * the module, driver, or stream head upstream/downstream. 14830Sstevel@tonic-gate * Handles M_FLUSH, M_DATA and some M_PROTO (T_DATA_REQ, 14840Sstevel@tonic-gate * and T_UNITDATA_REQ) messages. All others are queued to 14850Sstevel@tonic-gate * be handled by the service procedures. 14860Sstevel@tonic-gate */ 14870Sstevel@tonic-gate 14880Sstevel@tonic-gate static void 14890Sstevel@tonic-gate timodwput(queue_t *q, mblk_t *mp) 14900Sstevel@tonic-gate { 14910Sstevel@tonic-gate union T_primitives *pptr; 14920Sstevel@tonic-gate struct tim_tim *tp; 14930Sstevel@tonic-gate struct iocblk *iocbp; 14940Sstevel@tonic-gate 14950Sstevel@tonic-gate /* 14960Sstevel@tonic-gate * Enqueue normal-priority messages if our queue already 14970Sstevel@tonic-gate * holds some messages for deferred processing but don't 14980Sstevel@tonic-gate * enqueue those M_IOCTLs which will result in an 14990Sstevel@tonic-gate * M_PCPROTO (ie, high priority) message being created. 15000Sstevel@tonic-gate */ 15010Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 15020Sstevel@tonic-gate if (q->q_first != 0 && mp->b_datap->db_type < QPCTL) { 15030Sstevel@tonic-gate if (mp->b_datap->db_type == M_IOCTL) { 15040Sstevel@tonic-gate iocbp = (struct iocblk *)mp->b_rptr; 15050Sstevel@tonic-gate switch (iocbp->ioc_cmd) { 15060Sstevel@tonic-gate default: 15070Sstevel@tonic-gate (void) putq(q, mp); 15080Sstevel@tonic-gate return; 15090Sstevel@tonic-gate 15100Sstevel@tonic-gate case TI_GETINFO: 15110Sstevel@tonic-gate case TI_SYNC: 15120Sstevel@tonic-gate case TI_CAPABILITY: 15130Sstevel@tonic-gate break; 15140Sstevel@tonic-gate } 15150Sstevel@tonic-gate } else { 15160Sstevel@tonic-gate (void) putq(q, mp); 15170Sstevel@tonic-gate return; 15180Sstevel@tonic-gate } 15190Sstevel@tonic-gate } 15200Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 15210Sstevel@tonic-gate /* 15220Sstevel@tonic-gate * Inline processing of data (to avoid additional procedure call). 15230Sstevel@tonic-gate * Rest is handled in timodwproc. 15240Sstevel@tonic-gate */ 15250Sstevel@tonic-gate 15260Sstevel@tonic-gate switch (mp->b_datap->db_type) { 15270Sstevel@tonic-gate case M_DATA: 15280Sstevel@tonic-gate tp = (struct tim_tim *)q->q_ptr; 15290Sstevel@tonic-gate ASSERT(tp); 15300Sstevel@tonic-gate if (tp->tim_flags & CLTS) { 15310Sstevel@tonic-gate mblk_t *tmp; 15320Sstevel@tonic-gate 15330Sstevel@tonic-gate if ((tmp = tim_filladdr(q, mp, B_FALSE)) == NULL) { 15340Sstevel@tonic-gate (void) putq(q, mp); 15350Sstevel@tonic-gate break; 15360Sstevel@tonic-gate } else { 15370Sstevel@tonic-gate mp = tmp; 15380Sstevel@tonic-gate } 15390Sstevel@tonic-gate } 15400Sstevel@tonic-gate if (bcanputnext(q, mp->b_band)) 15410Sstevel@tonic-gate putnext(q, mp); 15420Sstevel@tonic-gate else 15430Sstevel@tonic-gate (void) putq(q, mp); 15440Sstevel@tonic-gate break; 15450Sstevel@tonic-gate case M_PROTO: 15460Sstevel@tonic-gate case M_PCPROTO: 15470Sstevel@tonic-gate pptr = (union T_primitives *)mp->b_rptr; 15480Sstevel@tonic-gate switch (pptr->type) { 15490Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 15500Sstevel@tonic-gate case T_UNITDATA_REQ: 15510Sstevel@tonic-gate tp = (struct tim_tim *)q->q_ptr; 15520Sstevel@tonic-gate ASSERT(tp); 15530Sstevel@tonic-gate if (tp->tim_flags & CLTS) { 15540Sstevel@tonic-gate mblk_t *tmp; 15550Sstevel@tonic-gate 15560Sstevel@tonic-gate tmp = tim_filladdr(q, mp, B_FALSE); 15570Sstevel@tonic-gate if (tmp == NULL) { 15580Sstevel@tonic-gate (void) putq(q, mp); 15590Sstevel@tonic-gate break; 15600Sstevel@tonic-gate } else { 15610Sstevel@tonic-gate mp = tmp; 15620Sstevel@tonic-gate } 15630Sstevel@tonic-gate } 15640Sstevel@tonic-gate if (bcanputnext(q, mp->b_band)) 15650Sstevel@tonic-gate putnext(q, mp); 15660Sstevel@tonic-gate else 15670Sstevel@tonic-gate (void) putq(q, mp); 15680Sstevel@tonic-gate break; 15690Sstevel@tonic-gate 15700Sstevel@tonic-gate case T_DATA_REQ: 15710Sstevel@tonic-gate case T_EXDATA_REQ: 15720Sstevel@tonic-gate if (bcanputnext(q, mp->b_band)) 15730Sstevel@tonic-gate putnext(q, mp); 15740Sstevel@tonic-gate else 15750Sstevel@tonic-gate (void) putq(q, mp); 15760Sstevel@tonic-gate break; 15770Sstevel@tonic-gate default: 15780Sstevel@tonic-gate (void) timodwproc(q, mp); 15790Sstevel@tonic-gate break; 15800Sstevel@tonic-gate } 15810Sstevel@tonic-gate break; 15820Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 15830Sstevel@tonic-gate default: 15840Sstevel@tonic-gate (void) timodwproc(q, mp); 15850Sstevel@tonic-gate break; 15860Sstevel@tonic-gate } 15870Sstevel@tonic-gate } 15880Sstevel@tonic-gate /* 15890Sstevel@tonic-gate * timodwsrv - Module write queue service procedure. 15900Sstevel@tonic-gate * This is called when messages are placed on an empty queue, 15910Sstevel@tonic-gate * when high priority messages are placed on the queue, and 15920Sstevel@tonic-gate * when flow control restrictions subside. This code used to 15930Sstevel@tonic-gate * be included in a put procedure, but it was moved to a 15940Sstevel@tonic-gate * service procedure because several points were added where 15950Sstevel@tonic-gate * memory allocation could fail, and there is no reasonable 15960Sstevel@tonic-gate * recovery mechanism from the put procedure. 15970Sstevel@tonic-gate */ 15980Sstevel@tonic-gate static void 15990Sstevel@tonic-gate timodwsrv(queue_t *q) 16000Sstevel@tonic-gate { 16010Sstevel@tonic-gate mblk_t *mp; 16020Sstevel@tonic-gate 16030Sstevel@tonic-gate ASSERT(q != NULL); 16040Sstevel@tonic-gate if (q->q_ptr == NULL) 16050Sstevel@tonic-gate return; 16060Sstevel@tonic-gate 16070Sstevel@tonic-gate while ((mp = getq(q)) != NULL) { 16080Sstevel@tonic-gate if (timodwproc(q, mp)) { 16090Sstevel@tonic-gate /* 16100Sstevel@tonic-gate * timodwproc did a putbq - stop processing 16110Sstevel@tonic-gate * messages. 16120Sstevel@tonic-gate */ 16130Sstevel@tonic-gate return; 16140Sstevel@tonic-gate } 16150Sstevel@tonic-gate } 16160Sstevel@tonic-gate } 16170Sstevel@tonic-gate 16180Sstevel@tonic-gate /* 16190Sstevel@tonic-gate * Common routine to process write side messages 16200Sstevel@tonic-gate */ 16210Sstevel@tonic-gate 16220Sstevel@tonic-gate static int 16230Sstevel@tonic-gate timodwproc(queue_t *q, mblk_t *mp) 16240Sstevel@tonic-gate { 16250Sstevel@tonic-gate union T_primitives *pptr; 16260Sstevel@tonic-gate struct tim_tim *tp; 16270Sstevel@tonic-gate mblk_t *tmp; 16280Sstevel@tonic-gate struct iocblk *iocbp; 16290Sstevel@tonic-gate int error; 16300Sstevel@tonic-gate 16310Sstevel@tonic-gate tp = (struct tim_tim *)q->q_ptr; 16320Sstevel@tonic-gate 16330Sstevel@tonic-gate switch (mp->b_datap->db_type) { 16340Sstevel@tonic-gate default: 16350Sstevel@tonic-gate putnext(q, mp); 16360Sstevel@tonic-gate break; 16370Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 16380Sstevel@tonic-gate 16390Sstevel@tonic-gate case M_DATA: 16400Sstevel@tonic-gate if (tp->tim_flags & CLTS) { 16410Sstevel@tonic-gate if ((tmp = tim_filladdr(q, mp, B_TRUE)) == NULL) { 16420Sstevel@tonic-gate return (1); 16430Sstevel@tonic-gate } else { 16440Sstevel@tonic-gate mp = tmp; 16450Sstevel@tonic-gate } 16460Sstevel@tonic-gate } 16470Sstevel@tonic-gate if (!bcanputnext(q, mp->b_band)) { 16480Sstevel@tonic-gate (void) putbq(q, mp); 16490Sstevel@tonic-gate return (1); 16500Sstevel@tonic-gate } 16510Sstevel@tonic-gate putnext(q, mp); 16520Sstevel@tonic-gate break; 16530Sstevel@tonic-gate 16540Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 16550Sstevel@tonic-gate case M_IOCTL: 16560Sstevel@tonic-gate 16570Sstevel@tonic-gate iocbp = (struct iocblk *)mp->b_rptr; 16580Sstevel@tonic-gate TILOG("timodwproc: Got M_IOCTL(%d)\n", iocbp->ioc_cmd); 16590Sstevel@tonic-gate 16600Sstevel@tonic-gate ASSERT(MBLKL(mp) == sizeof (struct iocblk)); 16610Sstevel@tonic-gate 16620Sstevel@tonic-gate /* 16630Sstevel@tonic-gate * TPI requires we await response to a previously sent message 1664*1261Sgeorges * before handling another, put it back on the head of queue. 1665*1261Sgeorges * Since putbq() may see QWANTR unset when called from the 1666*1261Sgeorges * service procedure, the queue must be explicitly scheduled 1667*1261Sgeorges * for service, as no backenable will occur for this case. 1668*1261Sgeorges * tim_ioctl_retry() sets a timer to handle the qenable. 16690Sstevel@tonic-gate */ 16700Sstevel@tonic-gate if (tp->tim_flags & WAITIOCACK) { 16710Sstevel@tonic-gate TILOG("timodwproc: putbq M_IOCTL(%d)\n", 16720Sstevel@tonic-gate iocbp->ioc_cmd); 16730Sstevel@tonic-gate (void) putbq(q, mp); 1674*1261Sgeorges /* Called from timodwsrv() and messages on queue */ 1675*1261Sgeorges if (!(q->q_flag & QWANTR)) 1676*1261Sgeorges tim_ioctl_retry(q); 16770Sstevel@tonic-gate return (1); 16780Sstevel@tonic-gate } 16790Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 16800Sstevel@tonic-gate 16810Sstevel@tonic-gate switch (iocbp->ioc_cmd) { 16820Sstevel@tonic-gate default: 16830Sstevel@tonic-gate putnext(q, mp); 16840Sstevel@tonic-gate break; 16850Sstevel@tonic-gate 16860Sstevel@tonic-gate case _I_GETPEERCRED: 16870Sstevel@tonic-gate if ((tp->tim_flags & COTS) == 0) { 16880Sstevel@tonic-gate miocnak(q, mp, 0, ENOTSUP); 16890Sstevel@tonic-gate } else { 16900Sstevel@tonic-gate mblk_t *cmp = mp->b_cont; 16910Sstevel@tonic-gate k_peercred_t *kp = NULL; 16920Sstevel@tonic-gate 16930Sstevel@tonic-gate mutex_enter(&tp->tim_mutex); 16940Sstevel@tonic-gate if (cmp != NULL && 16950Sstevel@tonic-gate iocbp->ioc_flag == IOC_NATIVE && 16960Sstevel@tonic-gate (tp->tim_flags & 16970Sstevel@tonic-gate (CONNWAIT|LOCORDREL|REMORDREL)) == 0 && 16980Sstevel@tonic-gate tp->tim_peercred != NULL && 16990Sstevel@tonic-gate DB_TYPE(cmp) == M_DATA && 17000Sstevel@tonic-gate MBLKL(cmp) == sizeof (k_peercred_t)) { 17010Sstevel@tonic-gate kp = (k_peercred_t *)cmp->b_rptr; 17020Sstevel@tonic-gate crhold(kp->pc_cr = tp->tim_peercred); 17030Sstevel@tonic-gate kp->pc_cpid = tp->tim_cpid; 17040Sstevel@tonic-gate } 17050Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 17060Sstevel@tonic-gate if (kp != NULL) 17070Sstevel@tonic-gate miocack(q, mp, sizeof (*kp), 0); 17080Sstevel@tonic-gate else 17090Sstevel@tonic-gate miocnak(q, mp, 0, ENOTCONN); 17100Sstevel@tonic-gate } 17110Sstevel@tonic-gate break; 17120Sstevel@tonic-gate case TI_BIND: 17130Sstevel@tonic-gate case TI_UNBIND: 17140Sstevel@tonic-gate case TI_OPTMGMT: 17150Sstevel@tonic-gate case TI_GETADDRS: 17160Sstevel@tonic-gate TILOG("timodwproc: TI_{BIND|UNBIND|OPTMGMT|GETADDRS}" 17170Sstevel@tonic-gate "\n", 0); 17180Sstevel@tonic-gate 17190Sstevel@tonic-gate /* 17200Sstevel@tonic-gate * We know that tim_send_ioctl_tpi_msg() is only 17210Sstevel@tonic-gate * going to examine the `type' field, so we only 17220Sstevel@tonic-gate * check that we can access that much data. 17230Sstevel@tonic-gate */ 17240Sstevel@tonic-gate error = miocpullup(mp, sizeof (t_scalar_t)); 17250Sstevel@tonic-gate if (error != 0) { 17260Sstevel@tonic-gate miocnak(q, mp, 0, error); 17270Sstevel@tonic-gate break; 17280Sstevel@tonic-gate } 17290Sstevel@tonic-gate tim_send_ioctl_tpi_msg(q, mp, tp, iocbp); 17300Sstevel@tonic-gate break; 17310Sstevel@tonic-gate 17320Sstevel@tonic-gate case TI_GETINFO: 17330Sstevel@tonic-gate TILOG("timodwproc: TI_GETINFO\n", 0); 17340Sstevel@tonic-gate error = miocpullup(mp, sizeof (struct T_info_req)); 17350Sstevel@tonic-gate if (error != 0) { 17360Sstevel@tonic-gate miocnak(q, mp, 0, error); 17370Sstevel@tonic-gate break; 17380Sstevel@tonic-gate } 17390Sstevel@tonic-gate tp->tim_flags |= WAIT_IOCINFOACK; 17400Sstevel@tonic-gate tim_send_ioctl_tpi_msg(q, mp, tp, iocbp); 17410Sstevel@tonic-gate break; 17420Sstevel@tonic-gate 17430Sstevel@tonic-gate case TI_SYNC: { 17440Sstevel@tonic-gate mblk_t *tsr_mp; 17450Sstevel@tonic-gate struct ti_sync_req *tsr; 17460Sstevel@tonic-gate uint32_t tsr_flags; 17470Sstevel@tonic-gate 17480Sstevel@tonic-gate error = miocpullup(mp, sizeof (struct ti_sync_req)); 17490Sstevel@tonic-gate if (error != 0) { 17500Sstevel@tonic-gate miocnak(q, mp, 0, error); 17510Sstevel@tonic-gate break; 17520Sstevel@tonic-gate } 17530Sstevel@tonic-gate 17540Sstevel@tonic-gate tsr_mp = mp->b_cont; 17550Sstevel@tonic-gate tsr = (struct ti_sync_req *)tsr_mp->b_rptr; 17560Sstevel@tonic-gate TILOG("timodwproc: TI_SYNC(%x)\n", tsr->tsr_flags); 17570Sstevel@tonic-gate 17580Sstevel@tonic-gate /* 17590Sstevel@tonic-gate * Save out the value of tsr_flags, in case we 17600Sstevel@tonic-gate * reallocb() tsr_mp (below). 17610Sstevel@tonic-gate */ 17620Sstevel@tonic-gate tsr_flags = tsr->tsr_flags; 17630Sstevel@tonic-gate if ((tsr_flags & TSRF_INFO_REQ) == 0) { 17640Sstevel@tonic-gate mblk_t *ack_mp = reallocb(tsr_mp, 17650Sstevel@tonic-gate sizeof (struct ti_sync_ack), 0); 17660Sstevel@tonic-gate 17670Sstevel@tonic-gate /* Can reply immediately. */ 17680Sstevel@tonic-gate mp->b_cont = NULL; 17690Sstevel@tonic-gate if (ack_mp == NULL) { 17700Sstevel@tonic-gate tilog("timodwproc: allocb failed no " 17710Sstevel@tonic-gate "recovery attempt\n", 0); 17720Sstevel@tonic-gate freemsg(tsr_mp); 17730Sstevel@tonic-gate miocnak(q, mp, 0, ENOMEM); 17740Sstevel@tonic-gate } else { 17750Sstevel@tonic-gate tim_answer_ti_sync(q, mp, tp, 17760Sstevel@tonic-gate ack_mp, tsr_flags); 17770Sstevel@tonic-gate } 17780Sstevel@tonic-gate break; 17790Sstevel@tonic-gate } 17800Sstevel@tonic-gate 17810Sstevel@tonic-gate /* 17820Sstevel@tonic-gate * This code is retained for compatibility with 17830Sstevel@tonic-gate * old statically linked applications. New code 17840Sstevel@tonic-gate * should use TI_CAPABILITY for all TPI 17850Sstevel@tonic-gate * information and should not use TSRF_INFO_REQ 17860Sstevel@tonic-gate * flag. 17870Sstevel@tonic-gate * 17880Sstevel@tonic-gate * defer processsing necessary to rput procedure 17890Sstevel@tonic-gate * as we need to get information from transport 17900Sstevel@tonic-gate * driver. Set flags that will tell the read 17910Sstevel@tonic-gate * side the work needed on this request. 17920Sstevel@tonic-gate */ 17930Sstevel@tonic-gate 17940Sstevel@tonic-gate if (tsr_flags & TSRF_IS_EXP_IN_RCVBUF) 17950Sstevel@tonic-gate tp->tim_flags |= PEEK_RDQ_EXPIND; 17960Sstevel@tonic-gate 17970Sstevel@tonic-gate /* 17980Sstevel@tonic-gate * Convert message to a T_INFO_REQ message; relies 17990Sstevel@tonic-gate * on sizeof (struct ti_sync_req) >= sizeof (struct 18000Sstevel@tonic-gate * T_info_req)). 18010Sstevel@tonic-gate */ 18020Sstevel@tonic-gate ASSERT(MBLKL(tsr_mp) >= sizeof (struct T_info_req)); 18030Sstevel@tonic-gate 18040Sstevel@tonic-gate ((struct T_info_req *)tsr_mp->b_rptr)->PRIM_type = 18050Sstevel@tonic-gate T_INFO_REQ; 18060Sstevel@tonic-gate tsr_mp->b_wptr = tsr_mp->b_rptr + 18070Sstevel@tonic-gate sizeof (struct T_info_req); 18080Sstevel@tonic-gate tp->tim_flags |= WAIT_IOCINFOACK; 18090Sstevel@tonic-gate tim_send_ioctl_tpi_msg(q, mp, tp, iocbp); 18100Sstevel@tonic-gate } 18110Sstevel@tonic-gate break; 18120Sstevel@tonic-gate 18130Sstevel@tonic-gate case TI_CAPABILITY: { 18140Sstevel@tonic-gate mblk_t *tcsr_mp; 18150Sstevel@tonic-gate struct T_capability_req *tcr; 18160Sstevel@tonic-gate 18170Sstevel@tonic-gate error = miocpullup(mp, sizeof (*tcr)); 18180Sstevel@tonic-gate if (error != 0) { 18190Sstevel@tonic-gate miocnak(q, mp, 0, error); 18200Sstevel@tonic-gate break; 18210Sstevel@tonic-gate } 18220Sstevel@tonic-gate 18230Sstevel@tonic-gate tcsr_mp = mp->b_cont; 18240Sstevel@tonic-gate tcr = (struct T_capability_req *)tcsr_mp->b_rptr; 18250Sstevel@tonic-gate TILOG("timodwproc: TI_CAPABILITY(CAP_bits1 = %x)\n", 18260Sstevel@tonic-gate tcr->CAP_bits1); 18270Sstevel@tonic-gate 18280Sstevel@tonic-gate if (tcr->PRIM_type != T_CAPABILITY_REQ) { 18290Sstevel@tonic-gate TILOG("timodwproc: invalid msg type %d\n", 18300Sstevel@tonic-gate tcr->PRIM_type); 18310Sstevel@tonic-gate miocnak(q, mp, 0, EPROTO); 18320Sstevel@tonic-gate break; 18330Sstevel@tonic-gate } 18340Sstevel@tonic-gate 18350Sstevel@tonic-gate switch (tp->tim_provinfo->tpi_capability) { 18360Sstevel@tonic-gate case PI_YES: 18370Sstevel@tonic-gate /* Just send T_CAPABILITY_REQ down */ 18380Sstevel@tonic-gate tim_send_ioctl_tpi_msg(q, mp, tp, iocbp); 18390Sstevel@tonic-gate break; 18400Sstevel@tonic-gate 18410Sstevel@tonic-gate case PI_DONTKNOW: 18420Sstevel@tonic-gate /* 18430Sstevel@tonic-gate * It is unknown yet whether transport provides 18440Sstevel@tonic-gate * T_CAPABILITY_REQ or not. Send message down 18450Sstevel@tonic-gate * and wait for reply. 18460Sstevel@tonic-gate */ 18470Sstevel@tonic-gate 18480Sstevel@tonic-gate ASSERT(tp->tim_tcap_timoutid == 0); 18490Sstevel@tonic-gate if ((tcr->CAP_bits1 & TC1_INFO) == 0) { 18500Sstevel@tonic-gate tp->tim_flags |= TI_CAP_RECVD; 18510Sstevel@tonic-gate } else { 18520Sstevel@tonic-gate tp->tim_flags |= (TI_CAP_RECVD | 18530Sstevel@tonic-gate CAP_WANTS_INFO); 18540Sstevel@tonic-gate } 18550Sstevel@tonic-gate 18560Sstevel@tonic-gate tp->tim_tcap_timoutid = qtimeout(q, 18570Sstevel@tonic-gate tim_tcap_timer, q, tim_tcap_wait * hz); 18580Sstevel@tonic-gate tim_send_ioctl_tpi_msg(q, mp, tp, iocbp); 18590Sstevel@tonic-gate break; 18600Sstevel@tonic-gate 18610Sstevel@tonic-gate case PI_NO: 18620Sstevel@tonic-gate /* 18630Sstevel@tonic-gate * Transport doesn't support T_CAPABILITY_REQ. 18640Sstevel@tonic-gate * Either reply immediately or send T_INFO_REQ 18650Sstevel@tonic-gate * if needed. 18660Sstevel@tonic-gate */ 18670Sstevel@tonic-gate if ((tcr->CAP_bits1 & TC1_INFO) != 0) { 18680Sstevel@tonic-gate tp->tim_flags |= (TI_CAP_RECVD | 18690Sstevel@tonic-gate CAP_WANTS_INFO | WAIT_IOCINFOACK); 18700Sstevel@tonic-gate TILOG("timodwproc: sending down " 18710Sstevel@tonic-gate "T_INFO_REQ, flags = %x\n", 18720Sstevel@tonic-gate tp->tim_flags); 18730Sstevel@tonic-gate 18740Sstevel@tonic-gate /* 18750Sstevel@tonic-gate * Generate T_INFO_REQ message and send 18760Sstevel@tonic-gate * it down 18770Sstevel@tonic-gate */ 18780Sstevel@tonic-gate ((struct T_info_req *)tcsr_mp->b_rptr)-> 18790Sstevel@tonic-gate PRIM_type = T_INFO_REQ; 18800Sstevel@tonic-gate tcsr_mp->b_wptr = tcsr_mp->b_rptr + 18810Sstevel@tonic-gate sizeof (struct T_info_req); 18820Sstevel@tonic-gate tim_send_ioctl_tpi_msg(q, mp, tp, 18830Sstevel@tonic-gate iocbp); 18840Sstevel@tonic-gate break; 18850Sstevel@tonic-gate } 18860Sstevel@tonic-gate 18870Sstevel@tonic-gate 18880Sstevel@tonic-gate /* 18890Sstevel@tonic-gate * Can reply immediately. Just send back 18900Sstevel@tonic-gate * T_CAPABILITY_ACK with CAP_bits1 set to 0. 18910Sstevel@tonic-gate */ 18920Sstevel@tonic-gate mp->b_cont = tcsr_mp = tpi_ack_alloc(mp->b_cont, 18930Sstevel@tonic-gate sizeof (struct T_capability_ack), M_PCPROTO, 18940Sstevel@tonic-gate T_CAPABILITY_ACK); 18950Sstevel@tonic-gate 18960Sstevel@tonic-gate if (tcsr_mp == NULL) { 18970Sstevel@tonic-gate tilog("timodwproc: allocb failed no " 18980Sstevel@tonic-gate "recovery attempt\n", 0); 18990Sstevel@tonic-gate miocnak(q, mp, 0, ENOMEM); 19000Sstevel@tonic-gate break; 19010Sstevel@tonic-gate } 19020Sstevel@tonic-gate 19030Sstevel@tonic-gate tp->tim_flags &= ~(WAITIOCACK | TI_CAP_RECVD | 19040Sstevel@tonic-gate WAIT_IOCINFOACK | CAP_WANTS_INFO); 19050Sstevel@tonic-gate ((struct T_capability_ack *) 19060Sstevel@tonic-gate tcsr_mp->b_rptr)->CAP_bits1 = 0; 19070Sstevel@tonic-gate tim_ioctl_send_reply(q, mp, tcsr_mp); 19080Sstevel@tonic-gate 19090Sstevel@tonic-gate /* 19100Sstevel@tonic-gate * It could happen when timod is awaiting ack 19110Sstevel@tonic-gate * for TI_GETPEERNAME/TI_GETMYNAME. 19120Sstevel@tonic-gate */ 19130Sstevel@tonic-gate if (tp->tim_iocsave != NULL) { 19140Sstevel@tonic-gate freemsg(tp->tim_iocsave); 19150Sstevel@tonic-gate tp->tim_iocsave = NULL; 19160Sstevel@tonic-gate tp->tim_saved_prim = -1; 19170Sstevel@tonic-gate } 19180Sstevel@tonic-gate break; 19190Sstevel@tonic-gate 19200Sstevel@tonic-gate default: 19210Sstevel@tonic-gate cmn_err(CE_PANIC, 19220Sstevel@tonic-gate "timodwproc: unknown tpi_capability value " 19230Sstevel@tonic-gate "%d\n", tp->tim_provinfo->tpi_capability); 19240Sstevel@tonic-gate break; 19250Sstevel@tonic-gate } 19260Sstevel@tonic-gate } 19270Sstevel@tonic-gate break; 19280Sstevel@tonic-gate 19290Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 19300Sstevel@tonic-gate case TI_GETMYNAME: 19310Sstevel@tonic-gate 19320Sstevel@tonic-gate tilog("timodwproc: Got TI_GETMYNAME\n", 0); 19330Sstevel@tonic-gate 19340Sstevel@tonic-gate if (tp->tim_provinfo->tpi_myname == PI_YES) { 19350Sstevel@tonic-gate putnext(q, mp); 19360Sstevel@tonic-gate break; 19370Sstevel@tonic-gate } 19380Sstevel@tonic-gate goto getname; 19390Sstevel@tonic-gate 19400Sstevel@tonic-gate case TI_GETPEERNAME: 19410Sstevel@tonic-gate 19420Sstevel@tonic-gate tilog("timodwproc: Got TI_GETPEERNAME\n", 0); 19430Sstevel@tonic-gate 19440Sstevel@tonic-gate if (tp->tim_provinfo->tpi_peername == PI_YES) { 19450Sstevel@tonic-gate putnext(q, mp); 19460Sstevel@tonic-gate break; 19470Sstevel@tonic-gate } 19480Sstevel@tonic-gate getname: 19490Sstevel@tonic-gate if ((tmp = copymsg(mp)) == NULL) { 19500Sstevel@tonic-gate tim_recover(q, mp, msgsize(mp)); 19510Sstevel@tonic-gate return (1); 19520Sstevel@tonic-gate } 19530Sstevel@tonic-gate /* 19540Sstevel@tonic-gate * tim_iocsave may be non-NULL when timod is awaiting 19550Sstevel@tonic-gate * ack for another TI_GETPEERNAME/TI_GETMYNAME. 19560Sstevel@tonic-gate */ 19570Sstevel@tonic-gate freemsg(tp->tim_iocsave); 19580Sstevel@tonic-gate tp->tim_iocsave = mp; 19590Sstevel@tonic-gate tp->tim_saved_prim = -1; 19600Sstevel@tonic-gate putnext(q, tmp); 19610Sstevel@tonic-gate break; 19620Sstevel@tonic-gate } 19630Sstevel@tonic-gate break; 19640Sstevel@tonic-gate 19650Sstevel@tonic-gate case M_IOCDATA: 19660Sstevel@tonic-gate 19670Sstevel@tonic-gate if (tp->tim_flags & NAMEPROC) { 19680Sstevel@tonic-gate if (ti_doname(q, mp) != DONAME_CONT) { 19690Sstevel@tonic-gate tp->tim_flags &= ~NAMEPROC; 19700Sstevel@tonic-gate } 19710Sstevel@tonic-gate } else 19720Sstevel@tonic-gate putnext(q, mp); 19730Sstevel@tonic-gate break; 19740Sstevel@tonic-gate 19750Sstevel@tonic-gate case M_PROTO: 19760Sstevel@tonic-gate case M_PCPROTO: 19770Sstevel@tonic-gate if (MBLKL(mp) < sizeof (t_scalar_t)) { 19780Sstevel@tonic-gate merror(q, mp, EPROTO); 19790Sstevel@tonic-gate return (1); 19800Sstevel@tonic-gate } 19810Sstevel@tonic-gate 19820Sstevel@tonic-gate pptr = (union T_primitives *)mp->b_rptr; 19830Sstevel@tonic-gate switch (pptr->type) { 19840Sstevel@tonic-gate default: 19850Sstevel@tonic-gate putnext(q, mp); 19860Sstevel@tonic-gate break; 19870Sstevel@tonic-gate 19880Sstevel@tonic-gate case T_EXDATA_REQ: 19890Sstevel@tonic-gate case T_DATA_REQ: 19900Sstevel@tonic-gate if (pptr->type == T_EXDATA_REQ) 19910Sstevel@tonic-gate tilog("timodwproc: Got T_EXDATA_REQ\n", 0); 19920Sstevel@tonic-gate 19930Sstevel@tonic-gate if (!bcanputnext(q, mp->b_band)) { 19940Sstevel@tonic-gate (void) putbq(q, mp); 19950Sstevel@tonic-gate return (1); 19960Sstevel@tonic-gate } 19970Sstevel@tonic-gate putnext(q, mp); 19980Sstevel@tonic-gate break; 19990Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 20000Sstevel@tonic-gate 20010Sstevel@tonic-gate case T_UNITDATA_REQ: 20020Sstevel@tonic-gate if (tp->tim_flags & CLTS) { 20030Sstevel@tonic-gate tmp = tim_filladdr(q, mp, B_TRUE); 20040Sstevel@tonic-gate if (tmp == NULL) { 20050Sstevel@tonic-gate return (1); 20060Sstevel@tonic-gate } else { 20070Sstevel@tonic-gate mp = tmp; 20080Sstevel@tonic-gate } 20090Sstevel@tonic-gate } 20100Sstevel@tonic-gate #ifdef C2_AUDIT 20110Sstevel@tonic-gate if (audit_active) 20120Sstevel@tonic-gate audit_sock(T_UNITDATA_REQ, q, mp, TIMOD_ID); 20130Sstevel@tonic-gate #endif 20140Sstevel@tonic-gate if (!bcanputnext(q, mp->b_band)) { 20150Sstevel@tonic-gate (void) putbq(q, mp); 20160Sstevel@tonic-gate return (1); 20170Sstevel@tonic-gate } 20180Sstevel@tonic-gate putnext(q, mp); 20190Sstevel@tonic-gate break; 20200Sstevel@tonic-gate 20210Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 20220Sstevel@tonic-gate case T_CONN_REQ: { 20230Sstevel@tonic-gate struct T_conn_req *reqp = (struct T_conn_req *) 20240Sstevel@tonic-gate mp->b_rptr; 20250Sstevel@tonic-gate void *p; 20260Sstevel@tonic-gate 20270Sstevel@tonic-gate tilog("timodwproc: Got T_CONN_REQ\n", 0); 20280Sstevel@tonic-gate 20290Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct T_conn_req)) { 20300Sstevel@tonic-gate merror(q, mp, EPROTO); 20310Sstevel@tonic-gate return (1); 20320Sstevel@tonic-gate } 20330Sstevel@tonic-gate 20340Sstevel@tonic-gate if (tp->tim_flags & DO_PEERNAME) { 20350Sstevel@tonic-gate if (!MBLKIN(mp, reqp->DEST_offset, 20360Sstevel@tonic-gate reqp->DEST_length)) { 20370Sstevel@tonic-gate merror(q, mp, EPROTO); 20380Sstevel@tonic-gate return (1); 20390Sstevel@tonic-gate } 20400Sstevel@tonic-gate ASSERT(reqp->DEST_length >= 0); 20410Sstevel@tonic-gate mutex_enter(&tp->tim_mutex); 20420Sstevel@tonic-gate if (reqp->DEST_length > tp->tim_peermaxlen) { 20430Sstevel@tonic-gate p = kmem_alloc(reqp->DEST_length, 20440Sstevel@tonic-gate KM_NOSLEEP); 20450Sstevel@tonic-gate if (p == NULL) { 20460Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 20470Sstevel@tonic-gate tilog("timodwproc: kmem_alloc " 20480Sstevel@tonic-gate "failed, attempting " 20490Sstevel@tonic-gate "recovery\n", 0); 20500Sstevel@tonic-gate tim_recover(q, mp, 20510Sstevel@tonic-gate reqp->DEST_length); 20520Sstevel@tonic-gate return (1); 20530Sstevel@tonic-gate } 20540Sstevel@tonic-gate if (tp->tim_peermaxlen) 20550Sstevel@tonic-gate kmem_free(tp->tim_peername, 20560Sstevel@tonic-gate tp->tim_peermaxlen); 20570Sstevel@tonic-gate tp->tim_peername = p; 20580Sstevel@tonic-gate tp->tim_peermaxlen = reqp->DEST_length; 20590Sstevel@tonic-gate } 20600Sstevel@tonic-gate tp->tim_peerlen = reqp->DEST_length; 20610Sstevel@tonic-gate p = mp->b_rptr + reqp->DEST_offset; 20620Sstevel@tonic-gate bcopy(p, tp->tim_peername, tp->tim_peerlen); 20630Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 20640Sstevel@tonic-gate } 20650Sstevel@tonic-gate if (tp->tim_flags & COTS) 20660Sstevel@tonic-gate tp->tim_flags |= CONNWAIT; 20670Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 20680Sstevel@tonic-gate #ifdef C2_AUDIT 20690Sstevel@tonic-gate if (audit_active) 20700Sstevel@tonic-gate audit_sock(T_CONN_REQ, q, mp, TIMOD_ID); 20710Sstevel@tonic-gate #endif 20720Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 20730Sstevel@tonic-gate putnext(q, mp); 20740Sstevel@tonic-gate break; 20750Sstevel@tonic-gate } 20760Sstevel@tonic-gate 20770Sstevel@tonic-gate case O_T_CONN_RES: 20780Sstevel@tonic-gate case T_CONN_RES: { 20790Sstevel@tonic-gate struct T_conn_res *resp; 20800Sstevel@tonic-gate struct T_conn_ind *indp; 20810Sstevel@tonic-gate mblk_t *pmp = NULL; 20820Sstevel@tonic-gate mblk_t *nbp; 20830Sstevel@tonic-gate 20840Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct T_conn_res) || 20850Sstevel@tonic-gate (tp->tim_flags & WAITIOCACK)) { 20860Sstevel@tonic-gate merror(q, mp, EPROTO); 20870Sstevel@tonic-gate return (1); 20880Sstevel@tonic-gate } 20890Sstevel@tonic-gate 20900Sstevel@tonic-gate resp = (struct T_conn_res *)mp->b_rptr; 20910Sstevel@tonic-gate for (tmp = tp->tim_consave; tmp != NULL; 20920Sstevel@tonic-gate tmp = tmp->b_next) { 20930Sstevel@tonic-gate indp = (struct T_conn_ind *)tmp->b_rptr; 20940Sstevel@tonic-gate if (indp->SEQ_number == resp->SEQ_number) 20950Sstevel@tonic-gate break; 20960Sstevel@tonic-gate pmp = tmp; 20970Sstevel@tonic-gate } 20980Sstevel@tonic-gate if (tmp == NULL) 20990Sstevel@tonic-gate goto cresout; 21000Sstevel@tonic-gate 21010Sstevel@tonic-gate if ((nbp = dupb(mp)) == NULL && 21020Sstevel@tonic-gate (nbp = copyb(mp)) == NULL) { 21030Sstevel@tonic-gate tim_recover(q, mp, msgsize(mp)); 21040Sstevel@tonic-gate return (1); 21050Sstevel@tonic-gate } 21060Sstevel@tonic-gate 21070Sstevel@tonic-gate if (pmp != NULL) 21080Sstevel@tonic-gate pmp->b_next = tmp->b_next; 21090Sstevel@tonic-gate else 21100Sstevel@tonic-gate tp->tim_consave = tmp->b_next; 21110Sstevel@tonic-gate tmp->b_next = NULL; 21120Sstevel@tonic-gate 21130Sstevel@tonic-gate /* 21140Sstevel@tonic-gate * Construct a list with: 21150Sstevel@tonic-gate * nbp - copy of user's original request 21160Sstevel@tonic-gate * tmp - the extracted T_conn_ind 21170Sstevel@tonic-gate */ 21180Sstevel@tonic-gate nbp->b_cont = tmp; 21190Sstevel@tonic-gate /* 21200Sstevel@tonic-gate * tim_iocsave may be non-NULL when timod is awaiting 21210Sstevel@tonic-gate * ack for TI_GETPEERNAME/TI_GETMYNAME. 21220Sstevel@tonic-gate */ 21230Sstevel@tonic-gate freemsg(tp->tim_iocsave); 21240Sstevel@tonic-gate tp->tim_iocsave = nbp; 21250Sstevel@tonic-gate tp->tim_saved_prim = pptr->type; 21260Sstevel@tonic-gate tp->tim_flags |= WAIT_CONNRESACK | WAITIOCACK; 21270Sstevel@tonic-gate 21280Sstevel@tonic-gate cresout: 21290Sstevel@tonic-gate putnext(q, mp); 21300Sstevel@tonic-gate break; 21310Sstevel@tonic-gate } 21320Sstevel@tonic-gate 21330Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 21340Sstevel@tonic-gate case T_DISCON_REQ: { 21350Sstevel@tonic-gate struct T_discon_req *disp; 21360Sstevel@tonic-gate struct T_conn_ind *conp; 21370Sstevel@tonic-gate mblk_t *pmp = NULL; 21380Sstevel@tonic-gate 21390Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct T_discon_req)) { 21400Sstevel@tonic-gate merror(q, mp, EPROTO); 21410Sstevel@tonic-gate return (1); 21420Sstevel@tonic-gate } 21430Sstevel@tonic-gate 21440Sstevel@tonic-gate disp = (struct T_discon_req *)mp->b_rptr; 21450Sstevel@tonic-gate tp->tim_flags &= ~(CONNWAIT|LOCORDREL|REMORDREL); 21460Sstevel@tonic-gate tim_clear_peer(tp); 21470Sstevel@tonic-gate 21480Sstevel@tonic-gate /* 21490Sstevel@tonic-gate * If we are already connected, there won't 21500Sstevel@tonic-gate * be any messages on tim_consave. 21510Sstevel@tonic-gate */ 21520Sstevel@tonic-gate for (tmp = tp->tim_consave; tmp; tmp = tmp->b_next) { 21530Sstevel@tonic-gate conp = (struct T_conn_ind *)tmp->b_rptr; 21540Sstevel@tonic-gate if (conp->SEQ_number == disp->SEQ_number) 21550Sstevel@tonic-gate break; 21560Sstevel@tonic-gate pmp = tmp; 21570Sstevel@tonic-gate } 21580Sstevel@tonic-gate if (tmp) { 21590Sstevel@tonic-gate if (pmp) 21600Sstevel@tonic-gate pmp->b_next = tmp->b_next; 21610Sstevel@tonic-gate else 21620Sstevel@tonic-gate tp->tim_consave = tmp->b_next; 21630Sstevel@tonic-gate tmp->b_next = NULL; 21640Sstevel@tonic-gate freemsg(tmp); 21650Sstevel@tonic-gate } 21660Sstevel@tonic-gate putnext(q, mp); 21670Sstevel@tonic-gate break; 21680Sstevel@tonic-gate } 21690Sstevel@tonic-gate 21700Sstevel@tonic-gate case T_ORDREL_REQ: 21710Sstevel@tonic-gate if (tp->tim_flags & REMORDREL) { 21720Sstevel@tonic-gate tp->tim_flags &= ~(LOCORDREL|REMORDREL); 21730Sstevel@tonic-gate tim_clear_peer(tp); 21740Sstevel@tonic-gate } else { 21750Sstevel@tonic-gate tp->tim_flags |= LOCORDREL; 21760Sstevel@tonic-gate } 21770Sstevel@tonic-gate putnext(q, mp); 21780Sstevel@tonic-gate break; 21790Sstevel@tonic-gate 21800Sstevel@tonic-gate case T_CAPABILITY_REQ: 21810Sstevel@tonic-gate tilog("timodwproc: Got T_CAPABILITY_REQ\n", 0); 21820Sstevel@tonic-gate /* 21830Sstevel@tonic-gate * XXX: We may know at this point whether transport 21840Sstevel@tonic-gate * provides T_CAPABILITY_REQ or not and we may utilise 21850Sstevel@tonic-gate * this knowledge here. 21860Sstevel@tonic-gate */ 21870Sstevel@tonic-gate putnext(q, mp); 21880Sstevel@tonic-gate break; 21890Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 21900Sstevel@tonic-gate } 21910Sstevel@tonic-gate break; 21920Sstevel@tonic-gate case M_FLUSH: 21930Sstevel@tonic-gate 21940Sstevel@tonic-gate tilog("timodwproc: Got M_FLUSH\n", 0); 21950Sstevel@tonic-gate 21960Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) { 21970Sstevel@tonic-gate if (*mp->b_rptr & FLUSHBAND) 21980Sstevel@tonic-gate flushband(q, *(mp->b_rptr + 1), FLUSHDATA); 21990Sstevel@tonic-gate else 22000Sstevel@tonic-gate flushq(q, FLUSHDATA); 22010Sstevel@tonic-gate } 22020Sstevel@tonic-gate putnext(q, mp); 22030Sstevel@tonic-gate break; 22040Sstevel@tonic-gate } 22050Sstevel@tonic-gate 22060Sstevel@tonic-gate return (0); 22070Sstevel@tonic-gate } 22080Sstevel@tonic-gate 22090Sstevel@tonic-gate static void 22100Sstevel@tonic-gate tilog(char *str, t_scalar_t arg) 22110Sstevel@tonic-gate { 22120Sstevel@tonic-gate if (dotilog) { 22130Sstevel@tonic-gate if (dotilog & 2) 22140Sstevel@tonic-gate cmn_err(CE_CONT, str, arg); 22150Sstevel@tonic-gate if (dotilog & 4) 22160Sstevel@tonic-gate (void) strlog(TIMOD_ID, -1, 0, SL_TRACE | SL_ERROR, 22170Sstevel@tonic-gate str, arg); 22180Sstevel@tonic-gate else 22190Sstevel@tonic-gate (void) strlog(TIMOD_ID, -1, 0, SL_TRACE, str, arg); 22200Sstevel@tonic-gate } 22210Sstevel@tonic-gate } 22220Sstevel@tonic-gate 22230Sstevel@tonic-gate static void 22240Sstevel@tonic-gate tilogp(char *str, uintptr_t arg) 22250Sstevel@tonic-gate { 22260Sstevel@tonic-gate if (dotilog) { 22270Sstevel@tonic-gate if (dotilog & 2) 22280Sstevel@tonic-gate cmn_err(CE_CONT, str, arg); 22290Sstevel@tonic-gate if (dotilog & 4) 22300Sstevel@tonic-gate (void) strlog(TIMOD_ID, -1, 0, SL_TRACE | SL_ERROR, 22310Sstevel@tonic-gate str, arg); 22320Sstevel@tonic-gate else 22330Sstevel@tonic-gate (void) strlog(TIMOD_ID, -1, 0, SL_TRACE, str, arg); 22340Sstevel@tonic-gate } 22350Sstevel@tonic-gate } 22360Sstevel@tonic-gate 22370Sstevel@tonic-gate 22380Sstevel@tonic-gate /* 22390Sstevel@tonic-gate * Process the TI_GETNAME ioctl. If no name exists, return len = 0 22400Sstevel@tonic-gate * in strbuf structures. The state transitions are determined by what 22410Sstevel@tonic-gate * is hung of cq_private (cp_private) in the copyresp (copyreq) structure. 22420Sstevel@tonic-gate * The high-level steps in the ioctl processing are as follows: 22430Sstevel@tonic-gate * 22440Sstevel@tonic-gate * 1) we recieve an transparent M_IOCTL with the arg in the second message 22450Sstevel@tonic-gate * block of the message. 22460Sstevel@tonic-gate * 2) we send up an M_COPYIN request for the strbuf structure pointed to 22470Sstevel@tonic-gate * by arg. The block containing arg is hung off cq_private. 22480Sstevel@tonic-gate * 3) we receive an M_IOCDATA response with cp->cp_private->b_cont == NULL. 22490Sstevel@tonic-gate * This means that the strbuf structure is found in the message block 22500Sstevel@tonic-gate * mp->b_cont. 22510Sstevel@tonic-gate * 4) we send up an M_COPYOUT request with the strbuf message hung off 22520Sstevel@tonic-gate * cq_private->b_cont. The address we are copying to is strbuf.buf. 22530Sstevel@tonic-gate * we set strbuf.len to 0 to indicate that we should copy the strbuf 22540Sstevel@tonic-gate * structure the next time. The message mp->b_cont contains the 22550Sstevel@tonic-gate * address info. 22560Sstevel@tonic-gate * 5) we receive an M_IOCDATA with cp_private->b_cont != NULL and 22570Sstevel@tonic-gate * strbuf.len == 0. Restore strbuf.len to either tp->tim_mylen or 22580Sstevel@tonic-gate * tp->tim_peerlen. 22590Sstevel@tonic-gate * 6) we send up an M_COPYOUT request with a copy of the strbuf message 22600Sstevel@tonic-gate * hung off mp->b_cont. In the strbuf structure in the message hung 22610Sstevel@tonic-gate * off cq_private->b_cont, we set strbuf.len to 0 and strbuf.maxlen 22620Sstevel@tonic-gate * to 0. This means that the next step is to ACK the ioctl. 22630Sstevel@tonic-gate * 7) we receive an M_IOCDATA message with cp_private->b_cont != NULL and 22640Sstevel@tonic-gate * strbuf.len == 0 and strbuf.maxlen == 0. Free up cp->private and 22650Sstevel@tonic-gate * send an M_IOCACK upstream, and we are done. 22660Sstevel@tonic-gate * 22670Sstevel@tonic-gate */ 22680Sstevel@tonic-gate static int 22690Sstevel@tonic-gate ti_doname( 22700Sstevel@tonic-gate queue_t *q, /* queue message arrived at */ 22710Sstevel@tonic-gate mblk_t *mp) /* M_IOCTL or M_IOCDATA message only */ 22720Sstevel@tonic-gate { 22730Sstevel@tonic-gate struct iocblk *iocp; 22740Sstevel@tonic-gate struct copyreq *cqp; 22750Sstevel@tonic-gate STRUCT_HANDLE(strbuf, sb); 22760Sstevel@tonic-gate struct copyresp *csp; 22770Sstevel@tonic-gate int ret; 22780Sstevel@tonic-gate mblk_t *bp; 22790Sstevel@tonic-gate struct tim_tim *tp = q->q_ptr; 22800Sstevel@tonic-gate boolean_t getpeer; 22810Sstevel@tonic-gate 22820Sstevel@tonic-gate switch (mp->b_datap->db_type) { 22830Sstevel@tonic-gate case M_IOCTL: 22840Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 22850Sstevel@tonic-gate if ((iocp->ioc_cmd != TI_GETMYNAME) && 22860Sstevel@tonic-gate (iocp->ioc_cmd != TI_GETPEERNAME)) { 22870Sstevel@tonic-gate tilog("ti_doname: bad M_IOCTL command\n", 0); 22880Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 22890Sstevel@tonic-gate ret = DONAME_FAIL; 22900Sstevel@tonic-gate break; 22910Sstevel@tonic-gate } 22920Sstevel@tonic-gate if ((iocp->ioc_count != TRANSPARENT)) { 22930Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 22940Sstevel@tonic-gate ret = DONAME_FAIL; 22950Sstevel@tonic-gate break; 22960Sstevel@tonic-gate } 22970Sstevel@tonic-gate 22980Sstevel@tonic-gate cqp = (struct copyreq *)mp->b_rptr; 22990Sstevel@tonic-gate cqp->cq_private = mp->b_cont; 23000Sstevel@tonic-gate cqp->cq_addr = (caddr_t)*(intptr_t *)mp->b_cont->b_rptr; 23010Sstevel@tonic-gate mp->b_cont = NULL; 23020Sstevel@tonic-gate cqp->cq_size = SIZEOF_STRUCT(strbuf, iocp->ioc_flag); 23030Sstevel@tonic-gate cqp->cq_flag = 0; 23040Sstevel@tonic-gate mp->b_datap->db_type = M_COPYIN; 23050Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (struct copyreq); 23060Sstevel@tonic-gate qreply(q, mp); 23070Sstevel@tonic-gate ret = DONAME_CONT; 23080Sstevel@tonic-gate break; 23090Sstevel@tonic-gate 23100Sstevel@tonic-gate case M_IOCDATA: 23110Sstevel@tonic-gate csp = (struct copyresp *)mp->b_rptr; 23120Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 23130Sstevel@tonic-gate cqp = (struct copyreq *)mp->b_rptr; 23140Sstevel@tonic-gate if ((csp->cp_cmd != TI_GETMYNAME) && 23150Sstevel@tonic-gate (csp->cp_cmd != TI_GETPEERNAME)) { 23160Sstevel@tonic-gate cmn_err(CE_WARN, "ti_doname: bad M_IOCDATA command\n"); 23170Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 23180Sstevel@tonic-gate ret = DONAME_FAIL; 23190Sstevel@tonic-gate break; 23200Sstevel@tonic-gate } 23210Sstevel@tonic-gate if (csp->cp_rval) { /* error */ 23220Sstevel@tonic-gate freemsg(csp->cp_private); 23230Sstevel@tonic-gate freemsg(mp); 23240Sstevel@tonic-gate ret = DONAME_FAIL; 23250Sstevel@tonic-gate break; 23260Sstevel@tonic-gate } 23270Sstevel@tonic-gate ASSERT(csp->cp_private != NULL); 23280Sstevel@tonic-gate getpeer = csp->cp_cmd == TI_GETPEERNAME; 23290Sstevel@tonic-gate if (getpeer) 23300Sstevel@tonic-gate mutex_enter(&tp->tim_mutex); 23310Sstevel@tonic-gate if (csp->cp_private->b_cont == NULL) { /* got strbuf */ 23320Sstevel@tonic-gate ASSERT(mp->b_cont); 23330Sstevel@tonic-gate STRUCT_SET_HANDLE(sb, iocp->ioc_flag, 23340Sstevel@tonic-gate (void *)mp->b_cont->b_rptr); 23350Sstevel@tonic-gate if (getpeer) { 23360Sstevel@tonic-gate if (tp->tim_peerlen == 0) { 23370Sstevel@tonic-gate /* copy just strbuf */ 23380Sstevel@tonic-gate STRUCT_FSET(sb, len, 0); 23390Sstevel@tonic-gate } else if (tp->tim_peerlen > 23400Sstevel@tonic-gate STRUCT_FGET(sb, maxlen)) { 23410Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 23420Sstevel@tonic-gate miocnak(q, mp, 0, ENAMETOOLONG); 23430Sstevel@tonic-gate ret = DONAME_FAIL; 23440Sstevel@tonic-gate break; 23450Sstevel@tonic-gate } else { 23460Sstevel@tonic-gate /* copy buffer */ 23470Sstevel@tonic-gate STRUCT_FSET(sb, len, tp->tim_peerlen); 23480Sstevel@tonic-gate } 23490Sstevel@tonic-gate } else { 23500Sstevel@tonic-gate if (tp->tim_mylen == 0) { 23510Sstevel@tonic-gate /* copy just strbuf */ 23520Sstevel@tonic-gate STRUCT_FSET(sb, len, 0); 23530Sstevel@tonic-gate } else if (tp->tim_mylen > 23540Sstevel@tonic-gate STRUCT_FGET(sb, maxlen)) { 23550Sstevel@tonic-gate freemsg(csp->cp_private); 23560Sstevel@tonic-gate miocnak(q, mp, 0, ENAMETOOLONG); 23570Sstevel@tonic-gate ret = DONAME_FAIL; 23580Sstevel@tonic-gate break; 23590Sstevel@tonic-gate } else { 23600Sstevel@tonic-gate /* copy buffer */ 23610Sstevel@tonic-gate STRUCT_FSET(sb, len, tp->tim_mylen); 23620Sstevel@tonic-gate } 23630Sstevel@tonic-gate } 23640Sstevel@tonic-gate csp->cp_private->b_cont = mp->b_cont; 23650Sstevel@tonic-gate mp->b_cont = NULL; 23660Sstevel@tonic-gate } 23670Sstevel@tonic-gate STRUCT_SET_HANDLE(sb, iocp->ioc_flag, 23680Sstevel@tonic-gate (void *)csp->cp_private->b_cont->b_rptr); 23690Sstevel@tonic-gate if (STRUCT_FGET(sb, len) == 0) { 23700Sstevel@tonic-gate /* 23710Sstevel@tonic-gate * restore strbuf.len 23720Sstevel@tonic-gate */ 23730Sstevel@tonic-gate if (getpeer) 23740Sstevel@tonic-gate STRUCT_FSET(sb, len, tp->tim_peerlen); 23750Sstevel@tonic-gate else 23760Sstevel@tonic-gate STRUCT_FSET(sb, len, tp->tim_mylen); 23770Sstevel@tonic-gate 23780Sstevel@tonic-gate if (getpeer) 23790Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 23800Sstevel@tonic-gate if (STRUCT_FGET(sb, maxlen) == 0) { 23810Sstevel@tonic-gate 23820Sstevel@tonic-gate /* 23830Sstevel@tonic-gate * ack the ioctl 23840Sstevel@tonic-gate */ 23850Sstevel@tonic-gate freemsg(csp->cp_private); 23860Sstevel@tonic-gate tim_ioctl_send_reply(q, mp, NULL); 23870Sstevel@tonic-gate ret = DONAME_DONE; 23880Sstevel@tonic-gate break; 23890Sstevel@tonic-gate } 23900Sstevel@tonic-gate 23910Sstevel@tonic-gate if ((bp = allocb(STRUCT_SIZE(sb), BPRI_MED)) == NULL) { 23920Sstevel@tonic-gate 23930Sstevel@tonic-gate tilog( 23940Sstevel@tonic-gate "ti_doname: allocb failed no recovery attempt\n", 0); 23950Sstevel@tonic-gate 23960Sstevel@tonic-gate freemsg(csp->cp_private); 23970Sstevel@tonic-gate miocnak(q, mp, 0, EAGAIN); 23980Sstevel@tonic-gate ret = DONAME_FAIL; 23990Sstevel@tonic-gate break; 24000Sstevel@tonic-gate } 24010Sstevel@tonic-gate bp->b_wptr += STRUCT_SIZE(sb); 24020Sstevel@tonic-gate bcopy(STRUCT_BUF(sb), bp->b_rptr, STRUCT_SIZE(sb)); 24030Sstevel@tonic-gate cqp->cq_addr = 24040Sstevel@tonic-gate (caddr_t)*(intptr_t *)csp->cp_private->b_rptr; 24050Sstevel@tonic-gate cqp->cq_size = STRUCT_SIZE(sb); 24060Sstevel@tonic-gate cqp->cq_flag = 0; 24070Sstevel@tonic-gate mp->b_datap->db_type = M_COPYOUT; 24080Sstevel@tonic-gate mp->b_cont = bp; 24090Sstevel@tonic-gate STRUCT_FSET(sb, len, 0); 24100Sstevel@tonic-gate STRUCT_FSET(sb, maxlen, 0); /* ack next time around */ 24110Sstevel@tonic-gate qreply(q, mp); 24120Sstevel@tonic-gate ret = DONAME_CONT; 24130Sstevel@tonic-gate break; 24140Sstevel@tonic-gate } 24150Sstevel@tonic-gate 24160Sstevel@tonic-gate /* 24170Sstevel@tonic-gate * copy the address to the user 24180Sstevel@tonic-gate */ 24190Sstevel@tonic-gate if ((bp = allocb((size_t)STRUCT_FGET(sb, len), BPRI_MED)) 24200Sstevel@tonic-gate == NULL) { 24210Sstevel@tonic-gate if (getpeer) 24220Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 24230Sstevel@tonic-gate 24240Sstevel@tonic-gate tilog("ti_doname: allocb failed no recovery attempt\n", 24250Sstevel@tonic-gate 0); 24260Sstevel@tonic-gate 24270Sstevel@tonic-gate freemsg(csp->cp_private); 24280Sstevel@tonic-gate miocnak(q, mp, 0, EAGAIN); 24290Sstevel@tonic-gate ret = DONAME_FAIL; 24300Sstevel@tonic-gate break; 24310Sstevel@tonic-gate } 24320Sstevel@tonic-gate bp->b_wptr += STRUCT_FGET(sb, len); 24330Sstevel@tonic-gate if (getpeer) { 24340Sstevel@tonic-gate bcopy(tp->tim_peername, bp->b_rptr, 24350Sstevel@tonic-gate STRUCT_FGET(sb, len)); 24360Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 24370Sstevel@tonic-gate } else { 24380Sstevel@tonic-gate bcopy(tp->tim_myname, bp->b_rptr, STRUCT_FGET(sb, len)); 24390Sstevel@tonic-gate } 24400Sstevel@tonic-gate cqp->cq_addr = (caddr_t)STRUCT_FGETP(sb, buf); 24410Sstevel@tonic-gate cqp->cq_size = STRUCT_FGET(sb, len); 24420Sstevel@tonic-gate cqp->cq_flag = 0; 24430Sstevel@tonic-gate mp->b_datap->db_type = M_COPYOUT; 24440Sstevel@tonic-gate mp->b_cont = bp; 24450Sstevel@tonic-gate STRUCT_FSET(sb, len, 0); /* copy the strbuf next time around */ 24460Sstevel@tonic-gate qreply(q, mp); 24470Sstevel@tonic-gate ret = DONAME_CONT; 24480Sstevel@tonic-gate break; 24490Sstevel@tonic-gate 24500Sstevel@tonic-gate default: 24510Sstevel@tonic-gate tilog("ti_doname: freeing bad message type = %d\n", 24520Sstevel@tonic-gate mp->b_datap->db_type); 24530Sstevel@tonic-gate freemsg(mp); 24540Sstevel@tonic-gate ret = DONAME_FAIL; 24550Sstevel@tonic-gate break; 24560Sstevel@tonic-gate } 24570Sstevel@tonic-gate return (ret); 24580Sstevel@tonic-gate } 24590Sstevel@tonic-gate 24600Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 24610Sstevel@tonic-gate 24620Sstevel@tonic-gate /* 24630Sstevel@tonic-gate * Fill in the address of a connectionless data packet if a connect 24640Sstevel@tonic-gate * had been done on this endpoint. 24650Sstevel@tonic-gate */ 24660Sstevel@tonic-gate static mblk_t * 24670Sstevel@tonic-gate tim_filladdr(queue_t *q, mblk_t *mp, boolean_t dorecover) 24680Sstevel@tonic-gate { 24690Sstevel@tonic-gate mblk_t *bp; 24700Sstevel@tonic-gate struct tim_tim *tp; 24710Sstevel@tonic-gate struct T_unitdata_req *up; 24720Sstevel@tonic-gate struct T_unitdata_req *nup; 24730Sstevel@tonic-gate size_t plen; 24740Sstevel@tonic-gate 24750Sstevel@tonic-gate tp = (struct tim_tim *)q->q_ptr; 24760Sstevel@tonic-gate if (mp->b_datap->db_type == M_DATA) { 24770Sstevel@tonic-gate mutex_enter(&tp->tim_mutex); 24780Sstevel@tonic-gate bp = allocb(sizeof (struct T_unitdata_req) + tp->tim_peerlen, 24790Sstevel@tonic-gate BPRI_MED); 24800Sstevel@tonic-gate if (bp != NULL) { 24810Sstevel@tonic-gate bp->b_datap->db_type = M_PROTO; 24820Sstevel@tonic-gate up = (struct T_unitdata_req *)bp->b_rptr; 24830Sstevel@tonic-gate up->PRIM_type = T_UNITDATA_REQ; 24840Sstevel@tonic-gate up->DEST_length = tp->tim_peerlen; 24850Sstevel@tonic-gate bp->b_wptr += sizeof (struct T_unitdata_req); 24860Sstevel@tonic-gate up->DEST_offset = sizeof (struct T_unitdata_req); 24870Sstevel@tonic-gate up->OPT_length = 0; 24880Sstevel@tonic-gate up->OPT_offset = 0; 24890Sstevel@tonic-gate if (tp->tim_peerlen > 0) { 24900Sstevel@tonic-gate bcopy(tp->tim_peername, bp->b_wptr, 24910Sstevel@tonic-gate tp->tim_peerlen); 24920Sstevel@tonic-gate bp->b_wptr += tp->tim_peerlen; 24930Sstevel@tonic-gate } 24940Sstevel@tonic-gate bp->b_cont = mp; 24950Sstevel@tonic-gate } 24960Sstevel@tonic-gate } else { 24970Sstevel@tonic-gate ASSERT(mp->b_datap->db_type == M_PROTO); 24980Sstevel@tonic-gate up = (struct T_unitdata_req *)mp->b_rptr; 24990Sstevel@tonic-gate ASSERT(up->PRIM_type == T_UNITDATA_REQ); 25000Sstevel@tonic-gate if (up->DEST_length != 0) 25010Sstevel@tonic-gate return (mp); 25020Sstevel@tonic-gate mutex_enter(&tp->tim_mutex); 25030Sstevel@tonic-gate bp = allocb(sizeof (struct T_unitdata_req) + up->OPT_length + 25040Sstevel@tonic-gate tp->tim_peerlen, BPRI_MED); 25050Sstevel@tonic-gate if (bp != NULL) { 25060Sstevel@tonic-gate bp->b_datap->db_type = M_PROTO; 25070Sstevel@tonic-gate nup = (struct T_unitdata_req *)bp->b_rptr; 25080Sstevel@tonic-gate nup->PRIM_type = T_UNITDATA_REQ; 25090Sstevel@tonic-gate nup->DEST_length = plen = tp->tim_peerlen; 25100Sstevel@tonic-gate bp->b_wptr += sizeof (struct T_unitdata_req); 25110Sstevel@tonic-gate nup->DEST_offset = sizeof (struct T_unitdata_req); 25120Sstevel@tonic-gate if (plen > 0) { 25130Sstevel@tonic-gate bcopy(tp->tim_peername, bp->b_wptr, plen); 25140Sstevel@tonic-gate bp->b_wptr += plen; 25150Sstevel@tonic-gate } 25160Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 25170Sstevel@tonic-gate if (up->OPT_length == 0) { 25180Sstevel@tonic-gate nup->OPT_length = 0; 25190Sstevel@tonic-gate nup->OPT_offset = 0; 25200Sstevel@tonic-gate } else { 25210Sstevel@tonic-gate nup->OPT_length = up->OPT_length; 25220Sstevel@tonic-gate nup->OPT_offset = 25230Sstevel@tonic-gate sizeof (struct T_unitdata_req) + plen; 25240Sstevel@tonic-gate bcopy((mp->b_wptr + up->OPT_offset), bp->b_wptr, 25250Sstevel@tonic-gate up->OPT_length); 25260Sstevel@tonic-gate bp->b_wptr += up->OPT_length; 25270Sstevel@tonic-gate } 25280Sstevel@tonic-gate bp->b_cont = mp->b_cont; 25290Sstevel@tonic-gate mp->b_cont = NULL; 25300Sstevel@tonic-gate freeb(mp); 25310Sstevel@tonic-gate return (bp); 25320Sstevel@tonic-gate } 25330Sstevel@tonic-gate } 25340Sstevel@tonic-gate ASSERT(MUTEX_HELD(&tp->tim_mutex)); 25350Sstevel@tonic-gate if (bp == NULL && dorecover) { 25360Sstevel@tonic-gate tim_recover(q, mp, 25370Sstevel@tonic-gate sizeof (struct T_unitdata_req) + tp->tim_peerlen); 25380Sstevel@tonic-gate } 25390Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 25400Sstevel@tonic-gate return (bp); 25410Sstevel@tonic-gate } 25420Sstevel@tonic-gate 25430Sstevel@tonic-gate static void 25440Sstevel@tonic-gate tim_addlink(struct tim_tim *tp) 25450Sstevel@tonic-gate { 25460Sstevel@tonic-gate struct tim_tim **tpp; 25470Sstevel@tonic-gate struct tim_tim *next; 25480Sstevel@tonic-gate 25490Sstevel@tonic-gate tpp = &tim_hash[TIM_HASH(tp->tim_acceptor)]; 25500Sstevel@tonic-gate rw_enter(&tim_list_rwlock, RW_WRITER); 25510Sstevel@tonic-gate 25520Sstevel@tonic-gate if ((next = *tpp) != NULL) 25530Sstevel@tonic-gate next->tim_ptpn = &tp->tim_next; 25540Sstevel@tonic-gate tp->tim_next = next; 25550Sstevel@tonic-gate tp->tim_ptpn = tpp; 25560Sstevel@tonic-gate *tpp = tp; 25570Sstevel@tonic-gate 25580Sstevel@tonic-gate tim_cnt++; 25590Sstevel@tonic-gate 25600Sstevel@tonic-gate rw_exit(&tim_list_rwlock); 25610Sstevel@tonic-gate } 25620Sstevel@tonic-gate 25630Sstevel@tonic-gate static void 25640Sstevel@tonic-gate tim_dellink(struct tim_tim *tp) 25650Sstevel@tonic-gate { 25660Sstevel@tonic-gate struct tim_tim *next; 25670Sstevel@tonic-gate 25680Sstevel@tonic-gate rw_enter(&tim_list_rwlock, RW_WRITER); 25690Sstevel@tonic-gate 25700Sstevel@tonic-gate if ((next = tp->tim_next) != NULL) 25710Sstevel@tonic-gate next->tim_ptpn = tp->tim_ptpn; 25720Sstevel@tonic-gate *(tp->tim_ptpn) = next; 25730Sstevel@tonic-gate 25740Sstevel@tonic-gate tim_cnt--; 25750Sstevel@tonic-gate 25760Sstevel@tonic-gate rw_exit(&tim_list_rwlock); 25770Sstevel@tonic-gate } 25780Sstevel@tonic-gate 25790Sstevel@tonic-gate static struct tim_tim * 25800Sstevel@tonic-gate tim_findlink(t_uscalar_t id) 25810Sstevel@tonic-gate { 25820Sstevel@tonic-gate struct tim_tim *tp; 25830Sstevel@tonic-gate 25840Sstevel@tonic-gate ASSERT(rw_lock_held(&tim_list_rwlock)); 25850Sstevel@tonic-gate 25860Sstevel@tonic-gate for (tp = tim_hash[TIM_HASH(id)]; tp != NULL; tp = tp->tim_next) { 25870Sstevel@tonic-gate if (tp->tim_acceptor == id) { 25880Sstevel@tonic-gate break; 25890Sstevel@tonic-gate } 25900Sstevel@tonic-gate } 25910Sstevel@tonic-gate return (tp); 25920Sstevel@tonic-gate } 25930Sstevel@tonic-gate 25940Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 25950Sstevel@tonic-gate static void 25960Sstevel@tonic-gate tim_recover(queue_t *q, mblk_t *mp, t_scalar_t size) 25970Sstevel@tonic-gate { 25980Sstevel@tonic-gate struct tim_tim *tp; 25990Sstevel@tonic-gate bufcall_id_t bid; 26000Sstevel@tonic-gate timeout_id_t tid; 26010Sstevel@tonic-gate 26020Sstevel@tonic-gate tp = (struct tim_tim *)q->q_ptr; 26030Sstevel@tonic-gate 26040Sstevel@tonic-gate /* 26050Sstevel@tonic-gate * Avoid re-enabling the queue. 26060Sstevel@tonic-gate */ 26070Sstevel@tonic-gate if (mp->b_datap->db_type == M_PCPROTO) 26080Sstevel@tonic-gate mp->b_datap->db_type = M_PROTO; 26090Sstevel@tonic-gate noenable(q); 26100Sstevel@tonic-gate (void) putbq(q, mp); 26110Sstevel@tonic-gate 26120Sstevel@tonic-gate /* 26130Sstevel@tonic-gate * Make sure there is at most one outstanding request per queue. 26140Sstevel@tonic-gate */ 26150Sstevel@tonic-gate if (q->q_flag & QREADR) { 26160Sstevel@tonic-gate if (tp->tim_rtimoutid || tp->tim_rbufcid) 26170Sstevel@tonic-gate return; 26180Sstevel@tonic-gate } else { 26190Sstevel@tonic-gate if (tp->tim_wtimoutid || tp->tim_wbufcid) 26200Sstevel@tonic-gate return; 26210Sstevel@tonic-gate } 26220Sstevel@tonic-gate if (!(bid = qbufcall(RD(q), (size_t)size, BPRI_MED, tim_buffer, q))) { 26230Sstevel@tonic-gate tid = qtimeout(RD(q), tim_timer, q, TIMWAIT); 26240Sstevel@tonic-gate if (q->q_flag & QREADR) 26250Sstevel@tonic-gate tp->tim_rtimoutid = tid; 26260Sstevel@tonic-gate else 26270Sstevel@tonic-gate tp->tim_wtimoutid = tid; 26280Sstevel@tonic-gate } else { 26290Sstevel@tonic-gate if (q->q_flag & QREADR) 26300Sstevel@tonic-gate tp->tim_rbufcid = bid; 26310Sstevel@tonic-gate else 26320Sstevel@tonic-gate tp->tim_wbufcid = bid; 26330Sstevel@tonic-gate } 26340Sstevel@tonic-gate } 26350Sstevel@tonic-gate 26360Sstevel@tonic-gate /* 2637*1261Sgeorges * Timod is waiting on a downstream ioctl reply, come back soon 2638*1261Sgeorges * to reschedule the write side service routine, which will check 2639*1261Sgeorges * if the ioctl is done and another can proceed. 2640*1261Sgeorges */ 2641*1261Sgeorges static void 2642*1261Sgeorges tim_ioctl_retry(queue_t *q) 2643*1261Sgeorges { 2644*1261Sgeorges struct tim_tim *tp; 2645*1261Sgeorges 2646*1261Sgeorges tp = (struct tim_tim *)q->q_ptr; 2647*1261Sgeorges 2648*1261Sgeorges /* 2649*1261Sgeorges * Make sure there is at most one outstanding request per wqueue. 2650*1261Sgeorges */ 2651*1261Sgeorges if (tp->tim_wtimoutid || tp->tim_wbufcid) 2652*1261Sgeorges return; 2653*1261Sgeorges 2654*1261Sgeorges tp->tim_wtimoutid = qtimeout(RD(q), tim_timer, q, TIMIOCWAIT); 2655*1261Sgeorges } 2656*1261Sgeorges 2657*1261Sgeorges /* 26580Sstevel@tonic-gate * Inspect the data on read queues starting from read queues passed as 26590Sstevel@tonic-gate * paramter (timod read queue) and traverse until 26600Sstevel@tonic-gate * q_next is NULL (stream head). Look for a TPI T_EXDATA_IND message 26610Sstevel@tonic-gate * reutrn 1 if found, 0 if not found. 26620Sstevel@tonic-gate */ 26630Sstevel@tonic-gate static int 26640Sstevel@tonic-gate ti_expind_on_rdqueues(queue_t *rq) 26650Sstevel@tonic-gate { 26660Sstevel@tonic-gate mblk_t *bp; 26670Sstevel@tonic-gate queue_t *q; 26680Sstevel@tonic-gate 26690Sstevel@tonic-gate q = rq; 26700Sstevel@tonic-gate /* 26710Sstevel@tonic-gate * We are going to walk q_next, so protect stream from plumbing 26720Sstevel@tonic-gate * changes. 26730Sstevel@tonic-gate */ 26740Sstevel@tonic-gate claimstr(q); 26750Sstevel@tonic-gate do { 26760Sstevel@tonic-gate /* 26770Sstevel@tonic-gate * Hold QLOCK while referencing data on queues 26780Sstevel@tonic-gate */ 26790Sstevel@tonic-gate mutex_enter(QLOCK(rq)); 26800Sstevel@tonic-gate bp = rq->q_first; 26810Sstevel@tonic-gate while (bp != NULL) { 26820Sstevel@tonic-gate /* 26830Sstevel@tonic-gate * Walk the messages on the queue looking 26840Sstevel@tonic-gate * for a possible T_EXDATA_IND 26850Sstevel@tonic-gate */ 26860Sstevel@tonic-gate if ((bp->b_datap->db_type == M_PROTO) && 26870Sstevel@tonic-gate ((bp->b_wptr - bp->b_rptr) >= 26880Sstevel@tonic-gate sizeof (struct T_exdata_ind)) && 26890Sstevel@tonic-gate (((struct T_exdata_ind *)bp->b_rptr)->PRIM_type 26900Sstevel@tonic-gate == T_EXDATA_IND)) { 26910Sstevel@tonic-gate /* bp is T_EXDATA_IND */ 26920Sstevel@tonic-gate mutex_exit(QLOCK(rq)); 26930Sstevel@tonic-gate releasestr(q); /* decrement sd_refcnt */ 26940Sstevel@tonic-gate return (1); /* expdata is on a read queue */ 26950Sstevel@tonic-gate } 26960Sstevel@tonic-gate bp = bp->b_next; /* next message */ 26970Sstevel@tonic-gate } 26980Sstevel@tonic-gate mutex_exit(QLOCK(rq)); 26990Sstevel@tonic-gate rq = rq->q_next; /* next upstream queue */ 27000Sstevel@tonic-gate } while (rq != NULL); 27010Sstevel@tonic-gate releasestr(q); 27020Sstevel@tonic-gate return (0); /* no expdata on read queues */ 27030Sstevel@tonic-gate } 27040Sstevel@tonic-gate 27050Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 27060Sstevel@tonic-gate static void 27070Sstevel@tonic-gate tim_tcap_timer(void *q_ptr) 27080Sstevel@tonic-gate { 27090Sstevel@tonic-gate queue_t *q = (queue_t *)q_ptr; 27100Sstevel@tonic-gate struct tim_tim *tp = (struct tim_tim *)q->q_ptr; 27110Sstevel@tonic-gate 27120Sstevel@tonic-gate ASSERT(tp != NULL && tp->tim_tcap_timoutid != 0); 27130Sstevel@tonic-gate ASSERT((tp->tim_flags & TI_CAP_RECVD) != 0); 27140Sstevel@tonic-gate 27150Sstevel@tonic-gate tp->tim_tcap_timoutid = 0; 27160Sstevel@tonic-gate TILOG("tim_tcap_timer: fired\n", 0); 27170Sstevel@tonic-gate tim_tcap_genreply(q, tp); 27180Sstevel@tonic-gate } 27190Sstevel@tonic-gate 27200Sstevel@tonic-gate /* 27210Sstevel@tonic-gate * tim_tcap_genreply() is called either from timeout routine or when 27220Sstevel@tonic-gate * T_ERROR_ACK is received. In both cases it means that underlying 27230Sstevel@tonic-gate * transport doesn't provide T_CAPABILITY_REQ. 27240Sstevel@tonic-gate */ 27250Sstevel@tonic-gate static void 27260Sstevel@tonic-gate tim_tcap_genreply(queue_t *q, struct tim_tim *tp) 27270Sstevel@tonic-gate { 27280Sstevel@tonic-gate mblk_t *mp = tp->tim_iocsave; 27290Sstevel@tonic-gate struct iocblk *iocbp; 27300Sstevel@tonic-gate 27310Sstevel@tonic-gate TILOG("timodrproc: tim_tcap_genreply\n", 0); 27320Sstevel@tonic-gate 27330Sstevel@tonic-gate ASSERT(tp == (struct tim_tim *)q->q_ptr); 27340Sstevel@tonic-gate ASSERT(mp != NULL); 27350Sstevel@tonic-gate 27360Sstevel@tonic-gate iocbp = (struct iocblk *)mp->b_rptr; 27370Sstevel@tonic-gate ASSERT(iocbp != NULL); 27380Sstevel@tonic-gate ASSERT(MBLKL(mp) == sizeof (struct iocblk)); 27390Sstevel@tonic-gate ASSERT(iocbp->ioc_cmd == TI_CAPABILITY); 27400Sstevel@tonic-gate ASSERT(mp->b_cont == NULL); 27410Sstevel@tonic-gate 27420Sstevel@tonic-gate /* Save this information permanently in the module */ 27430Sstevel@tonic-gate PI_PROVLOCK(tp->tim_provinfo); 27440Sstevel@tonic-gate if (tp->tim_provinfo->tpi_capability == PI_DONTKNOW) 27450Sstevel@tonic-gate tp->tim_provinfo->tpi_capability = PI_NO; 27460Sstevel@tonic-gate PI_PROVUNLOCK(tp->tim_provinfo); 27470Sstevel@tonic-gate 27480Sstevel@tonic-gate if (tp->tim_tcap_timoutid != 0) { 27490Sstevel@tonic-gate (void) quntimeout(q, tp->tim_tcap_timoutid); 27500Sstevel@tonic-gate tp->tim_tcap_timoutid = 0; 27510Sstevel@tonic-gate } 27520Sstevel@tonic-gate 27530Sstevel@tonic-gate if ((tp->tim_flags & CAP_WANTS_INFO) != 0) { 27540Sstevel@tonic-gate /* Send T_INFO_REQ down */ 27550Sstevel@tonic-gate mblk_t *tirmp = tpi_ack_alloc(NULL, 27560Sstevel@tonic-gate sizeof (struct T_info_req), M_PCPROTO, T_INFO_REQ); 27570Sstevel@tonic-gate 27580Sstevel@tonic-gate if (tirmp != NULL) { 27590Sstevel@tonic-gate /* Emulate TC1_INFO */ 27600Sstevel@tonic-gate TILOG("emulate_tcap_ioc_req: sending T_INFO_REQ\n", 0); 27610Sstevel@tonic-gate tp->tim_flags |= WAIT_IOCINFOACK; 27620Sstevel@tonic-gate putnext(WR(q), tirmp); 27630Sstevel@tonic-gate } else { 27640Sstevel@tonic-gate tilog("emulate_tcap_req: allocb fail, " 27650Sstevel@tonic-gate "no recovery attmpt\n", 0); 27660Sstevel@tonic-gate tp->tim_iocsave = NULL; 27670Sstevel@tonic-gate tp->tim_saved_prim = -1; 27680Sstevel@tonic-gate tp->tim_flags &= ~(TI_CAP_RECVD | WAITIOCACK | 27690Sstevel@tonic-gate CAP_WANTS_INFO | WAIT_IOCINFOACK); 27700Sstevel@tonic-gate miocnak(q, mp, 0, ENOMEM); 27710Sstevel@tonic-gate } 27720Sstevel@tonic-gate } else { 27730Sstevel@tonic-gate /* Reply immediately */ 27740Sstevel@tonic-gate mblk_t *ackmp = tpi_ack_alloc(NULL, 27750Sstevel@tonic-gate sizeof (struct T_capability_ack), M_PCPROTO, 27760Sstevel@tonic-gate T_CAPABILITY_ACK); 27770Sstevel@tonic-gate 27780Sstevel@tonic-gate mp->b_cont = ackmp; 27790Sstevel@tonic-gate 27800Sstevel@tonic-gate if (ackmp != NULL) { 27810Sstevel@tonic-gate ((struct T_capability_ack *) 27820Sstevel@tonic-gate ackmp->b_rptr)->CAP_bits1 = 0; 27830Sstevel@tonic-gate tim_ioctl_send_reply(q, mp, ackmp); 27840Sstevel@tonic-gate tp->tim_iocsave = NULL; 27850Sstevel@tonic-gate tp->tim_saved_prim = -1; 27860Sstevel@tonic-gate tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 27870Sstevel@tonic-gate TI_CAP_RECVD | CAP_WANTS_INFO); 27880Sstevel@tonic-gate } else { 27890Sstevel@tonic-gate tilog("timodwproc:allocb failed no " 27900Sstevel@tonic-gate "recovery attempt\n", 0); 27910Sstevel@tonic-gate tp->tim_iocsave = NULL; 27920Sstevel@tonic-gate tp->tim_saved_prim = -1; 27930Sstevel@tonic-gate tp->tim_flags &= ~(TI_CAP_RECVD | WAITIOCACK | 27940Sstevel@tonic-gate CAP_WANTS_INFO | WAIT_IOCINFOACK); 27950Sstevel@tonic-gate miocnak(q, mp, 0, ENOMEM); 27960Sstevel@tonic-gate } 27970Sstevel@tonic-gate } 27980Sstevel@tonic-gate } 27990Sstevel@tonic-gate 28000Sstevel@tonic-gate 28010Sstevel@tonic-gate static void 28020Sstevel@tonic-gate tim_ioctl_send_reply(queue_t *q, mblk_t *ioc_mp, mblk_t *mp) 28030Sstevel@tonic-gate { 28040Sstevel@tonic-gate struct iocblk *iocbp; 28050Sstevel@tonic-gate 28060Sstevel@tonic-gate ASSERT(q != NULL && ioc_mp != NULL); 28070Sstevel@tonic-gate 28080Sstevel@tonic-gate ioc_mp->b_datap->db_type = M_IOCACK; 28090Sstevel@tonic-gate if (mp != NULL) 28100Sstevel@tonic-gate mp->b_datap->db_type = M_DATA; 28110Sstevel@tonic-gate 28120Sstevel@tonic-gate if (ioc_mp->b_cont != mp) { 28130Sstevel@tonic-gate /* It is safe to call freemsg for NULL pointers */ 28140Sstevel@tonic-gate freemsg(ioc_mp->b_cont); 28150Sstevel@tonic-gate ioc_mp->b_cont = mp; 28160Sstevel@tonic-gate } 28170Sstevel@tonic-gate iocbp = (struct iocblk *)ioc_mp->b_rptr; 28180Sstevel@tonic-gate iocbp->ioc_error = 0; 28190Sstevel@tonic-gate iocbp->ioc_rval = 0; 28200Sstevel@tonic-gate /* 28210Sstevel@tonic-gate * All ioctl's may return more data than was specified by 28220Sstevel@tonic-gate * count arg. For TI_CAPABILITY count is treated as maximum data size. 28230Sstevel@tonic-gate */ 28240Sstevel@tonic-gate if (mp == NULL) 28250Sstevel@tonic-gate iocbp->ioc_count = 0; 28260Sstevel@tonic-gate else if (iocbp->ioc_cmd != TI_CAPABILITY) 28270Sstevel@tonic-gate iocbp->ioc_count = msgsize(mp); 28280Sstevel@tonic-gate else { 28290Sstevel@tonic-gate iocbp->ioc_count = MIN(MBLKL(mp), iocbp->ioc_count); 28300Sstevel@tonic-gate /* Truncate message if too large */ 28310Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + iocbp->ioc_count; 28320Sstevel@tonic-gate } 28330Sstevel@tonic-gate 28340Sstevel@tonic-gate TILOG("iosendreply: ioc_cmd = %d, ", iocbp->ioc_cmd); 28350Sstevel@tonic-gate putnext(RD(q), ioc_mp); 28360Sstevel@tonic-gate } 28370Sstevel@tonic-gate 28380Sstevel@tonic-gate /* 28390Sstevel@tonic-gate * Send M_IOCACK for errors. 28400Sstevel@tonic-gate */ 28410Sstevel@tonic-gate static void 28420Sstevel@tonic-gate tim_send_ioc_error_ack(queue_t *q, struct tim_tim *tp, mblk_t *mp) 28430Sstevel@tonic-gate { 28440Sstevel@tonic-gate struct T_error_ack *tea = (struct T_error_ack *)mp->b_rptr; 28450Sstevel@tonic-gate t_scalar_t error_prim; 28460Sstevel@tonic-gate 28470Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (struct T_error_ack); 28480Sstevel@tonic-gate ASSERT(mp->b_wptr <= mp->b_datap->db_lim); 28490Sstevel@tonic-gate error_prim = tea->ERROR_prim; 28500Sstevel@tonic-gate 28510Sstevel@tonic-gate ASSERT(tp->tim_iocsave != NULL); 28520Sstevel@tonic-gate ASSERT(tp->tim_iocsave->b_cont != mp); 28530Sstevel@tonic-gate 28540Sstevel@tonic-gate /* Always send this to the read side of the queue */ 28550Sstevel@tonic-gate q = RD(q); 28560Sstevel@tonic-gate 28570Sstevel@tonic-gate TILOG("tim_send_ioc_error_ack: prim = %d\n", tp->tim_saved_prim); 28580Sstevel@tonic-gate 28590Sstevel@tonic-gate if (tp->tim_saved_prim != error_prim) { 28600Sstevel@tonic-gate putnext(q, mp); 28610Sstevel@tonic-gate } else if (error_prim == T_CAPABILITY_REQ) { 28620Sstevel@tonic-gate TILOG("timodrproc: T_ERROR_ACK/T_CAPABILITY_REQ\n", 0); 28630Sstevel@tonic-gate ASSERT(tp->tim_iocsave->b_cont == NULL); 28640Sstevel@tonic-gate 28650Sstevel@tonic-gate tim_tcap_genreply(q, tp); 28660Sstevel@tonic-gate freemsg(mp); 28670Sstevel@tonic-gate } else { 28680Sstevel@tonic-gate struct iocblk *iocbp = (struct iocblk *)tp->tim_iocsave->b_rptr; 28690Sstevel@tonic-gate 28700Sstevel@tonic-gate TILOG("tim_send_ioc_error_ack: T_ERROR_ACK: prim %d\n", 28710Sstevel@tonic-gate error_prim); 28720Sstevel@tonic-gate ASSERT(tp->tim_iocsave->b_cont == NULL); 28730Sstevel@tonic-gate 28740Sstevel@tonic-gate switch (error_prim) { 28750Sstevel@tonic-gate default: 28760Sstevel@tonic-gate TILOG("timodrproc: Unknown T_ERROR_ACK: tlierror %d\n", 28770Sstevel@tonic-gate tea->TLI_error); 28780Sstevel@tonic-gate 28790Sstevel@tonic-gate putnext(q, mp); 28800Sstevel@tonic-gate break; 28810Sstevel@tonic-gate 28820Sstevel@tonic-gate case T_INFO_REQ: 28830Sstevel@tonic-gate case T_SVR4_OPTMGMT_REQ: 28840Sstevel@tonic-gate case T_OPTMGMT_REQ: 28850Sstevel@tonic-gate case O_T_BIND_REQ: 28860Sstevel@tonic-gate case T_BIND_REQ: 28870Sstevel@tonic-gate case T_UNBIND_REQ: 28880Sstevel@tonic-gate case T_ADDR_REQ: 28890Sstevel@tonic-gate case T_CAPABILITY_REQ: 28900Sstevel@tonic-gate 28910Sstevel@tonic-gate TILOG("ioc_err_ack: T_ERROR_ACK: tlierror %x\n", 28920Sstevel@tonic-gate tea->TLI_error); 28930Sstevel@tonic-gate 28940Sstevel@tonic-gate /* get saved ioctl msg and set values */ 28950Sstevel@tonic-gate iocbp->ioc_count = 0; 28960Sstevel@tonic-gate iocbp->ioc_error = 0; 28970Sstevel@tonic-gate iocbp->ioc_rval = tea->TLI_error; 28980Sstevel@tonic-gate if (iocbp->ioc_rval == TSYSERR) 28990Sstevel@tonic-gate iocbp->ioc_rval |= tea->UNIX_error << 8; 29000Sstevel@tonic-gate tp->tim_iocsave->b_datap->db_type = M_IOCACK; 29010Sstevel@tonic-gate freemsg(mp); 29020Sstevel@tonic-gate putnext(q, tp->tim_iocsave); 29030Sstevel@tonic-gate tp->tim_iocsave = NULL; 29040Sstevel@tonic-gate tp->tim_saved_prim = -1; 29050Sstevel@tonic-gate tp->tim_flags &= ~(WAITIOCACK | TI_CAP_RECVD | 29060Sstevel@tonic-gate CAP_WANTS_INFO | WAIT_IOCINFOACK); 29070Sstevel@tonic-gate break; 29080Sstevel@tonic-gate } 29090Sstevel@tonic-gate } 29100Sstevel@tonic-gate } 29110Sstevel@tonic-gate 29120Sstevel@tonic-gate /* 29130Sstevel@tonic-gate * Send reply to a usual message or ioctl message upstream. 29140Sstevel@tonic-gate * Should be called from the read side only. 29150Sstevel@tonic-gate */ 29160Sstevel@tonic-gate static void 29170Sstevel@tonic-gate tim_send_reply(queue_t *q, mblk_t *mp, struct tim_tim *tp, t_scalar_t prim) 29180Sstevel@tonic-gate { 29190Sstevel@tonic-gate ASSERT(mp != NULL && q != NULL && tp != NULL); 29200Sstevel@tonic-gate ASSERT(q == RD(q)); 29210Sstevel@tonic-gate 29220Sstevel@tonic-gate /* Restore db_type - recover() might have changed it */ 29230Sstevel@tonic-gate mp->b_datap->db_type = M_PCPROTO; 29240Sstevel@tonic-gate 29250Sstevel@tonic-gate if (((tp->tim_flags & WAITIOCACK) == 0) || (tp->tim_saved_prim != prim)) 29260Sstevel@tonic-gate putnext(q, mp); 29270Sstevel@tonic-gate else { 29280Sstevel@tonic-gate ASSERT(tp->tim_iocsave != NULL); 29290Sstevel@tonic-gate tim_ioctl_send_reply(q, tp->tim_iocsave, mp); 29300Sstevel@tonic-gate tp->tim_iocsave = NULL; 29310Sstevel@tonic-gate tp->tim_saved_prim = -1; 29320Sstevel@tonic-gate tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 29330Sstevel@tonic-gate TI_CAP_RECVD | CAP_WANTS_INFO); 29340Sstevel@tonic-gate } 29350Sstevel@tonic-gate } 29360Sstevel@tonic-gate 29370Sstevel@tonic-gate /* 29380Sstevel@tonic-gate * Reply to TI_SYNC reequest without sending anything downstream. 29390Sstevel@tonic-gate */ 29400Sstevel@tonic-gate static void 29410Sstevel@tonic-gate tim_answer_ti_sync(queue_t *q, mblk_t *mp, struct tim_tim *tp, 29420Sstevel@tonic-gate mblk_t *ackmp, uint32_t tsr_flags) 29430Sstevel@tonic-gate { 29440Sstevel@tonic-gate struct ti_sync_ack *tsap; 29450Sstevel@tonic-gate 29460Sstevel@tonic-gate ASSERT(q != NULL && q == WR(q) && ackmp != NULL); 29470Sstevel@tonic-gate 29480Sstevel@tonic-gate tsap = (struct ti_sync_ack *)ackmp->b_rptr; 29490Sstevel@tonic-gate bzero(tsap, sizeof (struct ti_sync_ack)); 29500Sstevel@tonic-gate ackmp->b_wptr = ackmp->b_rptr + sizeof (struct ti_sync_ack); 29510Sstevel@tonic-gate 29520Sstevel@tonic-gate if (tsr_flags == 0 || 29530Sstevel@tonic-gate (tsr_flags & ~(TSRF_QLEN_REQ | TSRF_IS_EXP_IN_RCVBUF)) != 0) { 29540Sstevel@tonic-gate /* 29550Sstevel@tonic-gate * unsupported/bad flag setting 29560Sstevel@tonic-gate * or no flag set. 29570Sstevel@tonic-gate */ 29580Sstevel@tonic-gate TILOG("timodwproc: unsupported/bad flag setting %x\n", 29590Sstevel@tonic-gate tsr_flags); 29600Sstevel@tonic-gate freemsg(ackmp); 29610Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 29620Sstevel@tonic-gate return; 29630Sstevel@tonic-gate } 29640Sstevel@tonic-gate 29650Sstevel@tonic-gate if ((tsr_flags & TSRF_QLEN_REQ) != 0) 29660Sstevel@tonic-gate tsap->tsa_qlen = tp->tim_backlog; 29670Sstevel@tonic-gate 29680Sstevel@tonic-gate if ((tsr_flags & TSRF_IS_EXP_IN_RCVBUF) != 0 && 29690Sstevel@tonic-gate ti_expind_on_rdqueues(RD(q))) { 29700Sstevel@tonic-gate /* 29710Sstevel@tonic-gate * Expedited data is queued on 29720Sstevel@tonic-gate * the stream read side 29730Sstevel@tonic-gate */ 29740Sstevel@tonic-gate tsap->tsa_flags |= TSAF_EXP_QUEUED; 29750Sstevel@tonic-gate } 29760Sstevel@tonic-gate 29770Sstevel@tonic-gate tim_ioctl_send_reply(q, mp, ackmp); 29780Sstevel@tonic-gate tp->tim_iocsave = NULL; 29790Sstevel@tonic-gate tp->tim_saved_prim = -1; 29800Sstevel@tonic-gate tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 29810Sstevel@tonic-gate TI_CAP_RECVD | CAP_WANTS_INFO); 29820Sstevel@tonic-gate } 29830Sstevel@tonic-gate 29840Sstevel@tonic-gate /* 29850Sstevel@tonic-gate * Send TPI message from IOCTL message, ssave original ioctl header and TPI 29860Sstevel@tonic-gate * message type. Should be called from write side only. 29870Sstevel@tonic-gate */ 29880Sstevel@tonic-gate static void 29890Sstevel@tonic-gate tim_send_ioctl_tpi_msg(queue_t *q, mblk_t *mp, struct tim_tim *tp, 29900Sstevel@tonic-gate struct iocblk *iocb) 29910Sstevel@tonic-gate { 29920Sstevel@tonic-gate mblk_t *tmp; 29930Sstevel@tonic-gate int ioc_cmd = iocb->ioc_cmd; 29940Sstevel@tonic-gate 29950Sstevel@tonic-gate ASSERT(q != NULL && mp != NULL && tp != NULL); 29960Sstevel@tonic-gate ASSERT(q == WR(q)); 29970Sstevel@tonic-gate ASSERT(mp->b_cont != NULL); 29980Sstevel@tonic-gate 29990Sstevel@tonic-gate tp->tim_iocsave = mp; 30000Sstevel@tonic-gate tmp = mp->b_cont; 30010Sstevel@tonic-gate 30020Sstevel@tonic-gate mp->b_cont = NULL; 30030Sstevel@tonic-gate tp->tim_flags |= WAITIOCACK; 30040Sstevel@tonic-gate tp->tim_saved_prim = ((union T_primitives *)tmp->b_rptr)->type; 30050Sstevel@tonic-gate 30060Sstevel@tonic-gate /* 30070Sstevel@tonic-gate * For TI_GETINFO, the attached message is a T_INFO_REQ 30080Sstevel@tonic-gate * For TI_SYNC, we generate the T_INFO_REQ message above 30090Sstevel@tonic-gate * For TI_CAPABILITY the attached message is either 30100Sstevel@tonic-gate * T_CAPABILITY_REQ or T_INFO_REQ. 30110Sstevel@tonic-gate * Among TPI request messages possible, 30120Sstevel@tonic-gate * T_INFO_REQ/T_CAPABILITY_ACK messages are a M_PCPROTO, rest 30130Sstevel@tonic-gate * are M_PROTO 30140Sstevel@tonic-gate */ 30150Sstevel@tonic-gate if (ioc_cmd == TI_GETINFO || ioc_cmd == TI_SYNC || 30160Sstevel@tonic-gate ioc_cmd == TI_CAPABILITY) { 30170Sstevel@tonic-gate tmp->b_datap->db_type = M_PCPROTO; 30180Sstevel@tonic-gate } else { 30190Sstevel@tonic-gate tmp->b_datap->db_type = M_PROTO; 30200Sstevel@tonic-gate } 30210Sstevel@tonic-gate 30220Sstevel@tonic-gate /* Verify credentials in STREAM */ 30230Sstevel@tonic-gate ASSERT(iocb->ioc_cr == NULL || iocb->ioc_cr == DB_CRED(tmp)); 30240Sstevel@tonic-gate 30250Sstevel@tonic-gate TILOG("timodwproc: sending down %d\n", tp->tim_saved_prim); 30260Sstevel@tonic-gate putnext(q, tmp); 30270Sstevel@tonic-gate } 30280Sstevel@tonic-gate 30290Sstevel@tonic-gate static void 30300Sstevel@tonic-gate tim_clear_peer(struct tim_tim *tp) 30310Sstevel@tonic-gate { 30320Sstevel@tonic-gate mutex_enter(&tp->tim_mutex); 30330Sstevel@tonic-gate if (tp->tim_peercred != NULL) { 30340Sstevel@tonic-gate crfree(tp->tim_peercred); 30350Sstevel@tonic-gate tp->tim_peercred = NULL; 30360Sstevel@tonic-gate } 30370Sstevel@tonic-gate tp->tim_peerlen = 0; 30380Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 30390Sstevel@tonic-gate } 3040