17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 237c478bd9Sstevel@tonic-gate /* 24*2cbe889aSgeorges * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 287c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate /* 347c478bd9Sstevel@tonic-gate * Transport Interface Library cooperating module - issue 2 357c478bd9Sstevel@tonic-gate */ 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 387c478bd9Sstevel@tonic-gate #include <sys/param.h> 397c478bd9Sstevel@tonic-gate #include <sys/types.h> 407c478bd9Sstevel@tonic-gate #include <sys/stream.h> 417c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 427c478bd9Sstevel@tonic-gate #include <sys/strsubr.h> 437c478bd9Sstevel@tonic-gate #define _SUN_TPI_VERSION 2 447c478bd9Sstevel@tonic-gate #include <sys/tihdr.h> 457c478bd9Sstevel@tonic-gate #include <sys/timod.h> 467c478bd9Sstevel@tonic-gate #include <sys/suntpi.h> 477c478bd9Sstevel@tonic-gate #include <sys/debug.h> 487c478bd9Sstevel@tonic-gate #include <sys/strlog.h> 497c478bd9Sstevel@tonic-gate #include <sys/errno.h> 507c478bd9Sstevel@tonic-gate #include <sys/cred.h> 517c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 527c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 537c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 547c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 557c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 567c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 577c478bd9Sstevel@tonic-gate #include <c2/audit.h> 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate /* 607c478bd9Sstevel@tonic-gate * This is the loadable module wrapper. 617c478bd9Sstevel@tonic-gate */ 627c478bd9Sstevel@tonic-gate #include <sys/conf.h> 637c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate static struct streamtab timinfo; 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate static struct fmodsw fsw = { 687c478bd9Sstevel@tonic-gate "timod", 697c478bd9Sstevel@tonic-gate &timinfo, 707c478bd9Sstevel@tonic-gate D_MTQPAIR | D_MP, 717c478bd9Sstevel@tonic-gate }; 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate /* 747c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 757c478bd9Sstevel@tonic-gate */ 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate static struct modlstrmod modlstrmod = { 787c478bd9Sstevel@tonic-gate &mod_strmodops, "transport interface str mod", &fsw 797c478bd9Sstevel@tonic-gate }; 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 827c478bd9Sstevel@tonic-gate MODREV_1, &modlstrmod, NULL 837c478bd9Sstevel@tonic-gate }; 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate static krwlock_t tim_list_rwlock; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate /* 887c478bd9Sstevel@tonic-gate * This module keeps track of capabilities of underlying transport. Information 897c478bd9Sstevel@tonic-gate * is persistent through module invocations (open/close). Currently it remembers 907c478bd9Sstevel@tonic-gate * whether underlying transport supports TI_GET{MY,PEER}NAME ioctls and 917c478bd9Sstevel@tonic-gate * T_CAPABILITY_REQ message. This module either passes ioctl/messages to the 927c478bd9Sstevel@tonic-gate * transport or emulates it when transport doesn't understand these 937c478bd9Sstevel@tonic-gate * ioctl/messages. 947c478bd9Sstevel@tonic-gate * 957c478bd9Sstevel@tonic-gate * It is assumed that transport supports T_CAPABILITY_REQ when timod receives 967c478bd9Sstevel@tonic-gate * T_CAPABILITY_ACK from the transport. There is no current standard describing 977c478bd9Sstevel@tonic-gate * transport behaviour when it receives unknown message type, so following 987c478bd9Sstevel@tonic-gate * reactions are expected and handled: 997c478bd9Sstevel@tonic-gate * 1007c478bd9Sstevel@tonic-gate * 1) Transport drops unknown T_CAPABILITY_REQ message type. In this case timod 1017c478bd9Sstevel@tonic-gate * will wait for tcap_wait time and assume that transport doesn't provide 1027c478bd9Sstevel@tonic-gate * this message type. T_CAPABILITY_REQ should never travel over the wire, so 1037c478bd9Sstevel@tonic-gate * timeout value should only take into consideration internal processing time 1047c478bd9Sstevel@tonic-gate * for the message. From user standpoint it may mean that an application will 1057c478bd9Sstevel@tonic-gate * hang for TCAP_WAIT time in the kernel the first time this message is used 1067c478bd9Sstevel@tonic-gate * with some particular transport (e.g. TCP/IP) during system uptime. 1077c478bd9Sstevel@tonic-gate * 1087c478bd9Sstevel@tonic-gate * 2) Transport responds with T_ERROR_ACK specifying T_CAPABILITY_REQ as 1097c478bd9Sstevel@tonic-gate * original message type. In this case it is assumed that transport doesn't 1107c478bd9Sstevel@tonic-gate * support it (which may not always be true - some transports return 1117c478bd9Sstevel@tonic-gate * T_ERROR_ACK in other cases like lack of system memory). 1127c478bd9Sstevel@tonic-gate * 1137c478bd9Sstevel@tonic-gate * 3) Transport responds with M_ERROR, effectively shutting down the 1147c478bd9Sstevel@tonic-gate * stream. Unfortunately there is no standard way to pass the reason of 1157c478bd9Sstevel@tonic-gate * M_ERROR message back to the caller, so it is assumed that if M_ERROR was 1167c478bd9Sstevel@tonic-gate * sent in response to T_CAPABILITY_REQ message, transport doesn't support 1177c478bd9Sstevel@tonic-gate * it. 1187c478bd9Sstevel@tonic-gate * 1197c478bd9Sstevel@tonic-gate * It is possible under certain circumstances that timod will incorrectly assume 1207c478bd9Sstevel@tonic-gate * that underlying transport doesn't provide T_CAPABILITY_REQ message type. In 1217c478bd9Sstevel@tonic-gate * this "worst-case" scenario timod will emulate its functionality by itself and 1227c478bd9Sstevel@tonic-gate * will provide only TC1_INFO capability. All other bits in CAP_bits1 field are 1237c478bd9Sstevel@tonic-gate * cleaned. TC1_INFO is emulated by sending T_INFO_REQ down to transport 1247c478bd9Sstevel@tonic-gate * provider. 1257c478bd9Sstevel@tonic-gate */ 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate /* 1287c478bd9Sstevel@tonic-gate * Notes about locking: 1297c478bd9Sstevel@tonic-gate * 1307c478bd9Sstevel@tonic-gate * tim_list_rwlock protects the list of tim_tim structures itself. When this 1317c478bd9Sstevel@tonic-gate * lock is held, the list itself is stable, but the contents of the entries 1327c478bd9Sstevel@tonic-gate * themselves might not be. 1337c478bd9Sstevel@tonic-gate * 1347c478bd9Sstevel@tonic-gate * The rest of the members are generally protected by D_MTQPAIR, which 1357c478bd9Sstevel@tonic-gate * specifies a default exclusive inner perimeter. If you're looking at 1367c478bd9Sstevel@tonic-gate * q->q_ptr, then it's stable. 1377c478bd9Sstevel@tonic-gate * 1387c478bd9Sstevel@tonic-gate * There's one exception to this rule: tim_peer{maxlen,len,name}. These members 1397c478bd9Sstevel@tonic-gate * are touched without entering the associated STREAMS perimeter because we 1407c478bd9Sstevel@tonic-gate * get the pointer via tim_findlink() rather than q_ptr. These are protected 1417c478bd9Sstevel@tonic-gate * by tim_mutex instead. If you don't hold that lock, don't look at them. 1427c478bd9Sstevel@tonic-gate * 1437c478bd9Sstevel@tonic-gate * (It would be possible to separate out the 'set by T_CONN_RES' cases from the 1447c478bd9Sstevel@tonic-gate * others, but there appears to be no reason to do so.) 1457c478bd9Sstevel@tonic-gate */ 1467c478bd9Sstevel@tonic-gate struct tim_tim { 1477c478bd9Sstevel@tonic-gate uint32_t tim_flags; 1487c478bd9Sstevel@tonic-gate t_uscalar_t tim_backlog; 1497c478bd9Sstevel@tonic-gate mblk_t *tim_iocsave; 1507c478bd9Sstevel@tonic-gate t_scalar_t tim_mymaxlen; 1517c478bd9Sstevel@tonic-gate t_scalar_t tim_mylen; 1527c478bd9Sstevel@tonic-gate caddr_t tim_myname; 1537c478bd9Sstevel@tonic-gate t_scalar_t tim_peermaxlen; 1547c478bd9Sstevel@tonic-gate t_scalar_t tim_peerlen; 1557c478bd9Sstevel@tonic-gate caddr_t tim_peername; 1567c478bd9Sstevel@tonic-gate cred_t *tim_peercred; 1577c478bd9Sstevel@tonic-gate mblk_t *tim_consave; 1587c478bd9Sstevel@tonic-gate bufcall_id_t tim_wbufcid; 1597c478bd9Sstevel@tonic-gate bufcall_id_t tim_rbufcid; 1607c478bd9Sstevel@tonic-gate timeout_id_t tim_wtimoutid; 1617c478bd9Sstevel@tonic-gate timeout_id_t tim_rtimoutid; 1627c478bd9Sstevel@tonic-gate /* Protected by the global tim_list_rwlock for all instances */ 1637c478bd9Sstevel@tonic-gate struct tim_tim *tim_next; 1647c478bd9Sstevel@tonic-gate struct tim_tim **tim_ptpn; 1657c478bd9Sstevel@tonic-gate t_uscalar_t tim_acceptor; 1667c478bd9Sstevel@tonic-gate t_scalar_t tim_saved_prim; /* Primitive from message */ 1677c478bd9Sstevel@tonic-gate /* part of ioctl. */ 1687c478bd9Sstevel@tonic-gate timeout_id_t tim_tcap_timoutid; /* For T_CAP_REQ timeout */ 1697c478bd9Sstevel@tonic-gate tpi_provinfo_t *tim_provinfo; /* Transport description */ 1707c478bd9Sstevel@tonic-gate kmutex_t tim_mutex; /* protect tim_peer* */ 1717c478bd9Sstevel@tonic-gate pid_t tim_cpid; 1727c478bd9Sstevel@tonic-gate }; 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate /* 1767c478bd9Sstevel@tonic-gate * Local flags used with tim_flags field in instance structure of 1777c478bd9Sstevel@tonic-gate * type 'struct _ti_user' declared above. 1787c478bd9Sstevel@tonic-gate * Historical note: 1797c478bd9Sstevel@tonic-gate * This namespace constants were previously declared in a 1807c478bd9Sstevel@tonic-gate * a very messed up namespace in timod.h 1817c478bd9Sstevel@tonic-gate * 1827c478bd9Sstevel@tonic-gate * There may be 3 states for transport: 1837c478bd9Sstevel@tonic-gate * 1847c478bd9Sstevel@tonic-gate * 1) It provides T_CAPABILITY_REQ 1857c478bd9Sstevel@tonic-gate * 2) It does not provide T_CAPABILITY_REQ 1867c478bd9Sstevel@tonic-gate * 3) It is not known yet whether transport provides T_CAPABILITY_REQ or not. 1877c478bd9Sstevel@tonic-gate * 1887c478bd9Sstevel@tonic-gate * It is assumed that the underlying transport either provides 1897c478bd9Sstevel@tonic-gate * T_CAPABILITY_REQ or not and this does not changes during the 1907c478bd9Sstevel@tonic-gate * system lifetime. 1917c478bd9Sstevel@tonic-gate * 1927c478bd9Sstevel@tonic-gate */ 1937c478bd9Sstevel@tonic-gate #define PEEK_RDQ_EXPIND 0x0001 /* look for expinds on stream rd queues */ 1947c478bd9Sstevel@tonic-gate #define WAITIOCACK 0x0002 /* waiting for info for ioctl act */ 1957c478bd9Sstevel@tonic-gate #define CLTS 0x0004 /* connectionless transport */ 1967c478bd9Sstevel@tonic-gate #define COTS 0x0008 /* connection-oriented transport */ 1977c478bd9Sstevel@tonic-gate #define CONNWAIT 0x0010 /* waiting for connect confirmation */ 1987c478bd9Sstevel@tonic-gate #define LOCORDREL 0x0020 /* local end has orderly released */ 1997c478bd9Sstevel@tonic-gate #define REMORDREL 0x0040 /* remote end had orderly released */ 2007c478bd9Sstevel@tonic-gate #define NAMEPROC 0x0080 /* processing a NAME ioctl */ 2017c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 2027c478bd9Sstevel@tonic-gate #define DO_MYNAME 0x0100 /* timod handles TI_GETMYNAME */ 2037c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 2047c478bd9Sstevel@tonic-gate #define DO_PEERNAME 0x0200 /* timod handles TI_GETPEERNAME */ 2057c478bd9Sstevel@tonic-gate #define TI_CAP_RECVD 0x0400 /* TI_CAPABILITY received */ 2067c478bd9Sstevel@tonic-gate #define CAP_WANTS_INFO 0x0800 /* TI_CAPABILITY has TC1_INFO set */ 2077c478bd9Sstevel@tonic-gate #define WAIT_IOCINFOACK 0x1000 /* T_INFO_REQ generated from ioctl */ 2087c478bd9Sstevel@tonic-gate #define WAIT_CONNRESACK 0x2000 /* waiting for T_OK_ACK to T_CONN_RES */ 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate /* Debugging facilities */ 2127c478bd9Sstevel@tonic-gate /* 2137c478bd9Sstevel@tonic-gate * Logging needed for debugging timod should only appear in DEBUG kernel. 2147c478bd9Sstevel@tonic-gate */ 2157c478bd9Sstevel@tonic-gate #ifdef DEBUG 2167c478bd9Sstevel@tonic-gate #define TILOG(msg, arg) tilog((msg), (arg)) 2177c478bd9Sstevel@tonic-gate #define TILOGP(msg, arg) tilogp((msg), (arg)) 2187c478bd9Sstevel@tonic-gate #else 2197c478bd9Sstevel@tonic-gate #define TILOG(msg, arg) 2207c478bd9Sstevel@tonic-gate #define TILOGP(msg, arg) 2217c478bd9Sstevel@tonic-gate #endif 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate /* 2257c478bd9Sstevel@tonic-gate * Sleep timeout for T_CAPABILITY_REQ. This message never travels across 2267c478bd9Sstevel@tonic-gate * network, so timeout value should be enough to cover all internal processing 2277c478bd9Sstevel@tonic-gate * time. 2287c478bd9Sstevel@tonic-gate */ 2297c478bd9Sstevel@tonic-gate clock_t tim_tcap_wait = 2; 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate /* Sleep timeout in tim_recover() */ 2327c478bd9Sstevel@tonic-gate #define TIMWAIT (1*hz) 233*2cbe889aSgeorges /* Sleep timeout in tim_ioctl_retry() 0.2 seconds */ 234*2cbe889aSgeorges #define TIMIOCWAIT (200*hz/1000) 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate /* 2377c478bd9Sstevel@tonic-gate * Return values for ti_doname(). 2387c478bd9Sstevel@tonic-gate */ 2397c478bd9Sstevel@tonic-gate #define DONAME_FAIL 0 /* failing ioctl (done) */ 2407c478bd9Sstevel@tonic-gate #define DONAME_DONE 1 /* done processing */ 2417c478bd9Sstevel@tonic-gate #define DONAME_CONT 2 /* continue proceesing (not done yet) */ 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate /* 2447c478bd9Sstevel@tonic-gate * Function prototypes 2457c478bd9Sstevel@tonic-gate */ 2467c478bd9Sstevel@tonic-gate static int ti_doname(queue_t *, mblk_t *); 2477c478bd9Sstevel@tonic-gate static int ti_expind_on_rdqueues(queue_t *); 2487c478bd9Sstevel@tonic-gate static void tim_ioctl_send_reply(queue_t *, mblk_t *, mblk_t *); 2497c478bd9Sstevel@tonic-gate static void tim_send_ioc_error_ack(queue_t *, struct tim_tim *, mblk_t *); 2507c478bd9Sstevel@tonic-gate static void tim_tcap_timer(void *); 2517c478bd9Sstevel@tonic-gate static void tim_tcap_genreply(queue_t *, struct tim_tim *); 2527c478bd9Sstevel@tonic-gate static void tim_send_reply(queue_t *, mblk_t *, struct tim_tim *, t_scalar_t); 2537c478bd9Sstevel@tonic-gate static void tim_answer_ti_sync(queue_t *, mblk_t *, struct tim_tim *, 2547c478bd9Sstevel@tonic-gate mblk_t *, uint32_t); 2557c478bd9Sstevel@tonic-gate static void tim_send_ioctl_tpi_msg(queue_t *, mblk_t *, struct tim_tim *, 2567c478bd9Sstevel@tonic-gate struct iocblk *); 2577c478bd9Sstevel@tonic-gate static void tim_clear_peer(struct tim_tim *); 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate int 2607c478bd9Sstevel@tonic-gate _init(void) 2617c478bd9Sstevel@tonic-gate { 2627c478bd9Sstevel@tonic-gate int error; 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate rw_init(&tim_list_rwlock, NULL, RW_DRIVER, NULL); 2657c478bd9Sstevel@tonic-gate error = mod_install(&modlinkage); 2667c478bd9Sstevel@tonic-gate if (error != 0) { 2677c478bd9Sstevel@tonic-gate rw_destroy(&tim_list_rwlock); 2687c478bd9Sstevel@tonic-gate return (error); 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate return (0); 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate int 2757c478bd9Sstevel@tonic-gate _fini(void) 2767c478bd9Sstevel@tonic-gate { 2777c478bd9Sstevel@tonic-gate int error; 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate error = mod_remove(&modlinkage); 2807c478bd9Sstevel@tonic-gate if (error != 0) 2817c478bd9Sstevel@tonic-gate return (error); 2827c478bd9Sstevel@tonic-gate rw_destroy(&tim_list_rwlock); 2837c478bd9Sstevel@tonic-gate return (0); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate int 2877c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 2887c478bd9Sstevel@tonic-gate { 2897c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate /* 2947c478bd9Sstevel@tonic-gate * Hash list for all instances. Used to find tim_tim structure based on 2957c478bd9Sstevel@tonic-gate * ACCEPTOR_id in T_CONN_RES. Protected by tim_list_rwlock. 2967c478bd9Sstevel@tonic-gate */ 2977c478bd9Sstevel@tonic-gate #define TIM_HASH_SIZE 256 2987c478bd9Sstevel@tonic-gate #ifdef _ILP32 2997c478bd9Sstevel@tonic-gate #define TIM_HASH(id) (((uintptr_t)(id) >> 8) % TIM_HASH_SIZE) 3007c478bd9Sstevel@tonic-gate #else 3017c478bd9Sstevel@tonic-gate #define TIM_HASH(id) ((uintptr_t)(id) % TIM_HASH_SIZE) 3027c478bd9Sstevel@tonic-gate #endif /* _ILP32 */ 3037c478bd9Sstevel@tonic-gate static struct tim_tim *tim_hash[TIM_HASH_SIZE]; 3047c478bd9Sstevel@tonic-gate int tim_cnt = 0; 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate static void tilog(char *, t_scalar_t); 3077c478bd9Sstevel@tonic-gate static void tilogp(char *, uintptr_t); 3087c478bd9Sstevel@tonic-gate static mblk_t *tim_filladdr(queue_t *, mblk_t *, boolean_t); 3097c478bd9Sstevel@tonic-gate static void tim_addlink(struct tim_tim *); 3107c478bd9Sstevel@tonic-gate static void tim_dellink(struct tim_tim *); 3117c478bd9Sstevel@tonic-gate static struct tim_tim *tim_findlink(t_uscalar_t); 3127c478bd9Sstevel@tonic-gate static void tim_recover(queue_t *, mblk_t *, t_scalar_t); 313*2cbe889aSgeorges static void tim_ioctl_retry(queue_t *); 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate int dotilog = 0; 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate #define TIMOD_ID 3 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 3207c478bd9Sstevel@tonic-gate static int timodopen(queue_t *, dev_t *, int, int, cred_t *); 3217c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 3227c478bd9Sstevel@tonic-gate static int timodclose(queue_t *, int, cred_t *); 3237c478bd9Sstevel@tonic-gate static void timodwput(queue_t *, mblk_t *); 3247c478bd9Sstevel@tonic-gate static void timodrput(queue_t *, mblk_t *); 3257c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 3267c478bd9Sstevel@tonic-gate static void timodrsrv(queue_t *); 3277c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 3287c478bd9Sstevel@tonic-gate static void timodwsrv(queue_t *); 3297c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 3307c478bd9Sstevel@tonic-gate static int timodrproc(queue_t *, mblk_t *); 3317c478bd9Sstevel@tonic-gate static int timodwproc(queue_t *, mblk_t *); 3327c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate /* stream data structure definitions */ 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate static struct module_info timod_info = 3377c478bd9Sstevel@tonic-gate {TIMOD_ID, "timod", 0, INFPSZ, 512, 128}; 3387c478bd9Sstevel@tonic-gate static struct qinit timodrinit = { 3397c478bd9Sstevel@tonic-gate (int (*)())timodrput, 3407c478bd9Sstevel@tonic-gate (int (*)())timodrsrv, 3417c478bd9Sstevel@tonic-gate timodopen, 3427c478bd9Sstevel@tonic-gate timodclose, 3437c478bd9Sstevel@tonic-gate nulldev, 3447c478bd9Sstevel@tonic-gate &timod_info, 3457c478bd9Sstevel@tonic-gate NULL 3467c478bd9Sstevel@tonic-gate }; 3477c478bd9Sstevel@tonic-gate static struct qinit timodwinit = { 3487c478bd9Sstevel@tonic-gate (int (*)())timodwput, 3497c478bd9Sstevel@tonic-gate (int (*)())timodwsrv, 3507c478bd9Sstevel@tonic-gate timodopen, 3517c478bd9Sstevel@tonic-gate timodclose, 3527c478bd9Sstevel@tonic-gate nulldev, 3537c478bd9Sstevel@tonic-gate &timod_info, 3547c478bd9Sstevel@tonic-gate NULL 3557c478bd9Sstevel@tonic-gate }; 3567c478bd9Sstevel@tonic-gate static struct streamtab timinfo = { &timodrinit, &timodwinit, NULL, NULL }; 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 3597c478bd9Sstevel@tonic-gate /* 3607c478bd9Sstevel@tonic-gate * timodopen - open routine gets called when the module gets pushed 3617c478bd9Sstevel@tonic-gate * onto the stream. 3627c478bd9Sstevel@tonic-gate */ 3637c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3647c478bd9Sstevel@tonic-gate static int 3657c478bd9Sstevel@tonic-gate timodopen( 3667c478bd9Sstevel@tonic-gate queue_t *q, 3677c478bd9Sstevel@tonic-gate dev_t *devp, 3687c478bd9Sstevel@tonic-gate int flag, 3697c478bd9Sstevel@tonic-gate int sflag, 3707c478bd9Sstevel@tonic-gate cred_t *crp) 3717c478bd9Sstevel@tonic-gate { 3727c478bd9Sstevel@tonic-gate struct tim_tim *tp; 3737c478bd9Sstevel@tonic-gate struct stroptions *sop; 3747c478bd9Sstevel@tonic-gate mblk_t *bp; 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate ASSERT(q != NULL); 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate if (q->q_ptr) { 3797c478bd9Sstevel@tonic-gate return (0); 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate if ((bp = allocb(sizeof (struct stroptions), BPRI_MED)) == 0) 3837c478bd9Sstevel@tonic-gate return (ENOMEM); 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate tp = kmem_zalloc(sizeof (struct tim_tim), KM_SLEEP); 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate tp->tim_cpid = -1; 3887c478bd9Sstevel@tonic-gate tp->tim_saved_prim = -1; 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate mutex_init(&tp->tim_mutex, NULL, MUTEX_DEFAULT, NULL); 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate q->q_ptr = (caddr_t)tp; 3937c478bd9Sstevel@tonic-gate WR(q)->q_ptr = (caddr_t)tp; 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate tilogp("timodopen: Allocated for tp %lx\n", (uintptr_t)tp); 3967c478bd9Sstevel@tonic-gate tilogp("timodopen: Allocated for q %lx\n", (uintptr_t)q); 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate /* Must be done before tpi_findprov and _ILP32 q_next walk below */ 3997c478bd9Sstevel@tonic-gate qprocson(q); 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate tp->tim_provinfo = tpi_findprov(q); 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate /* 4047c478bd9Sstevel@tonic-gate * Defer allocation of the buffers for the local address and 4057c478bd9Sstevel@tonic-gate * the peer's address until we need them. 4067c478bd9Sstevel@tonic-gate * Assume that timod has to handle getname until we here 4077c478bd9Sstevel@tonic-gate * an iocack from the transport provider or we know that 4087c478bd9Sstevel@tonic-gate * transport provider doesn't understand it. 4097c478bd9Sstevel@tonic-gate */ 4107c478bd9Sstevel@tonic-gate if (tp->tim_provinfo->tpi_myname != PI_YES) { 4117c478bd9Sstevel@tonic-gate TILOG("timodopen: setting DO_MYNAME\n", 0); 4127c478bd9Sstevel@tonic-gate tp->tim_flags |= DO_MYNAME; 4137c478bd9Sstevel@tonic-gate } 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate if (tp->tim_provinfo->tpi_peername != PI_YES) { 4167c478bd9Sstevel@tonic-gate TILOG("timodopen: setting DO_PEERNAME\n", 0); 4177c478bd9Sstevel@tonic-gate tp->tim_flags |= DO_PEERNAME; 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate #ifdef _ILP32 4217c478bd9Sstevel@tonic-gate { 4227c478bd9Sstevel@tonic-gate queue_t *driverq; 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate /* 4257c478bd9Sstevel@tonic-gate * Find my driver's read queue (for T_CONN_RES handling) 4267c478bd9Sstevel@tonic-gate */ 4277c478bd9Sstevel@tonic-gate driverq = WR(q); 4287c478bd9Sstevel@tonic-gate while (SAMESTR(driverq)) 4297c478bd9Sstevel@tonic-gate driverq = driverq->q_next; 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate tp->tim_acceptor = (t_uscalar_t)RD(driverq); 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate #else 4347c478bd9Sstevel@tonic-gate tp->tim_acceptor = (t_uscalar_t)getminor(*devp); 4357c478bd9Sstevel@tonic-gate #endif /* _ILP32 */ 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate /* 4387c478bd9Sstevel@tonic-gate * Add this one to the list. 4397c478bd9Sstevel@tonic-gate */ 4407c478bd9Sstevel@tonic-gate tim_addlink(tp); 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate /* 4437c478bd9Sstevel@tonic-gate * Send M_SETOPTS to stream head to make sure M_PCPROTO messages 4447c478bd9Sstevel@tonic-gate * are not flushed. This prevents application deadlocks. 4457c478bd9Sstevel@tonic-gate */ 4467c478bd9Sstevel@tonic-gate bp->b_datap->db_type = M_SETOPTS; 4477c478bd9Sstevel@tonic-gate bp->b_wptr += sizeof (struct stroptions); 4487c478bd9Sstevel@tonic-gate sop = (struct stroptions *)bp->b_rptr; 4497c478bd9Sstevel@tonic-gate sop->so_flags = SO_READOPT; 4507c478bd9Sstevel@tonic-gate sop->so_readopt = RFLUSHPCPROT; 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate putnext(q, bp); 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate return (0); 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate static void 4587c478bd9Sstevel@tonic-gate tim_timer(void *arg) 4597c478bd9Sstevel@tonic-gate { 4607c478bd9Sstevel@tonic-gate queue_t *q = arg; 4617c478bd9Sstevel@tonic-gate struct tim_tim *tp = (struct tim_tim *)q->q_ptr; 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate ASSERT(tp); 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate if (q->q_flag & QREADR) { 4667c478bd9Sstevel@tonic-gate ASSERT(tp->tim_rtimoutid); 4677c478bd9Sstevel@tonic-gate tp->tim_rtimoutid = 0; 4687c478bd9Sstevel@tonic-gate } else { 4697c478bd9Sstevel@tonic-gate ASSERT(tp->tim_wtimoutid); 4707c478bd9Sstevel@tonic-gate tp->tim_wtimoutid = 0; 4717c478bd9Sstevel@tonic-gate } 4727c478bd9Sstevel@tonic-gate enableok(q); 4737c478bd9Sstevel@tonic-gate qenable(q); 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate static void 4777c478bd9Sstevel@tonic-gate tim_buffer(void *arg) 4787c478bd9Sstevel@tonic-gate { 4797c478bd9Sstevel@tonic-gate queue_t *q = arg; 4807c478bd9Sstevel@tonic-gate struct tim_tim *tp = (struct tim_tim *)q->q_ptr; 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate ASSERT(tp); 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate if (q->q_flag & QREADR) { 4857c478bd9Sstevel@tonic-gate ASSERT(tp->tim_rbufcid); 4867c478bd9Sstevel@tonic-gate tp->tim_rbufcid = 0; 4877c478bd9Sstevel@tonic-gate } else { 4887c478bd9Sstevel@tonic-gate ASSERT(tp->tim_wbufcid); 4897c478bd9Sstevel@tonic-gate tp->tim_wbufcid = 0; 4907c478bd9Sstevel@tonic-gate } 4917c478bd9Sstevel@tonic-gate enableok(q); 4927c478bd9Sstevel@tonic-gate qenable(q); 4937c478bd9Sstevel@tonic-gate } 4947c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate /* 4977c478bd9Sstevel@tonic-gate * timodclose - This routine gets called when the module gets popped 4987c478bd9Sstevel@tonic-gate * off of the stream. 4997c478bd9Sstevel@tonic-gate */ 5007c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 5017c478bd9Sstevel@tonic-gate static int 5027c478bd9Sstevel@tonic-gate timodclose( 5037c478bd9Sstevel@tonic-gate queue_t *q, 5047c478bd9Sstevel@tonic-gate int flag, 5057c478bd9Sstevel@tonic-gate cred_t *crp) 5067c478bd9Sstevel@tonic-gate { 5077c478bd9Sstevel@tonic-gate struct tim_tim *tp; 5087c478bd9Sstevel@tonic-gate mblk_t *mp; 5097c478bd9Sstevel@tonic-gate mblk_t *nmp; 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate ASSERT(q != NULL); 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate tp = (struct tim_tim *)q->q_ptr; 5147c478bd9Sstevel@tonic-gate q->q_ptr = NULL; 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate ASSERT(tp != NULL); 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate tilogp("timodclose: Entered for tp %lx\n", (uintptr_t)tp); 5197c478bd9Sstevel@tonic-gate tilogp("timodclose: Entered for q %lx\n", (uintptr_t)q); 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate qprocsoff(q); 5227c478bd9Sstevel@tonic-gate tim_dellink(tp); 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate /* 5257c478bd9Sstevel@tonic-gate * Cancel any outstanding bufcall 5267c478bd9Sstevel@tonic-gate * or timeout requests. 5277c478bd9Sstevel@tonic-gate */ 5287c478bd9Sstevel@tonic-gate if (tp->tim_wbufcid) { 5297c478bd9Sstevel@tonic-gate qunbufcall(q, tp->tim_wbufcid); 5307c478bd9Sstevel@tonic-gate tp->tim_wbufcid = 0; 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate if (tp->tim_rbufcid) { 5337c478bd9Sstevel@tonic-gate qunbufcall(q, tp->tim_rbufcid); 5347c478bd9Sstevel@tonic-gate tp->tim_rbufcid = 0; 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate if (tp->tim_wtimoutid) { 5377c478bd9Sstevel@tonic-gate (void) quntimeout(q, tp->tim_wtimoutid); 5387c478bd9Sstevel@tonic-gate tp->tim_wtimoutid = 0; 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate if (tp->tim_rtimoutid) { 5417c478bd9Sstevel@tonic-gate (void) quntimeout(q, tp->tim_rtimoutid); 5427c478bd9Sstevel@tonic-gate tp->tim_rtimoutid = 0; 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate if (tp->tim_tcap_timoutid != 0) { 5467c478bd9Sstevel@tonic-gate (void) quntimeout(q, tp->tim_tcap_timoutid); 5477c478bd9Sstevel@tonic-gate tp->tim_tcap_timoutid = 0; 5487c478bd9Sstevel@tonic-gate } 5497c478bd9Sstevel@tonic-gate 5507c478bd9Sstevel@tonic-gate if (tp->tim_iocsave != NULL) 5517c478bd9Sstevel@tonic-gate freemsg(tp->tim_iocsave); 5527c478bd9Sstevel@tonic-gate mp = tp->tim_consave; 5537c478bd9Sstevel@tonic-gate while (mp) { 5547c478bd9Sstevel@tonic-gate nmp = mp->b_next; 5557c478bd9Sstevel@tonic-gate mp->b_next = NULL; 5567c478bd9Sstevel@tonic-gate freemsg(mp); 5577c478bd9Sstevel@tonic-gate mp = nmp; 5587c478bd9Sstevel@tonic-gate } 5597c478bd9Sstevel@tonic-gate ASSERT(tp->tim_mymaxlen >= 0); 5607c478bd9Sstevel@tonic-gate if (tp->tim_mymaxlen != 0) 5617c478bd9Sstevel@tonic-gate kmem_free(tp->tim_myname, (size_t)tp->tim_mymaxlen); 5627c478bd9Sstevel@tonic-gate ASSERT(tp->tim_peermaxlen >= 0); 5637c478bd9Sstevel@tonic-gate if (tp->tim_peermaxlen != 0) 5647c478bd9Sstevel@tonic-gate kmem_free(tp->tim_peername, (size_t)tp->tim_peermaxlen); 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate q->q_ptr = WR(q)->q_ptr = NULL; 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate mutex_destroy(&tp->tim_mutex); 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate if (tp->tim_peercred != NULL) 5717c478bd9Sstevel@tonic-gate crfree(tp->tim_peercred); 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate kmem_free(tp, sizeof (struct tim_tim)); 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate return (0); 5767c478bd9Sstevel@tonic-gate } 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate /* 5797c478bd9Sstevel@tonic-gate * timodrput - Module read put procedure. This is called from 5807c478bd9Sstevel@tonic-gate * the module, driver, or stream head upstream/downstream. 5817c478bd9Sstevel@tonic-gate * Handles M_FLUSH, M_DATA and some M_PROTO (T_DATA_IND, 5827c478bd9Sstevel@tonic-gate * and T_UNITDATA_IND) messages. All others are queued to 5837c478bd9Sstevel@tonic-gate * be handled by the service procedures. 5847c478bd9Sstevel@tonic-gate */ 5857c478bd9Sstevel@tonic-gate static void 5867c478bd9Sstevel@tonic-gate timodrput(queue_t *q, mblk_t *mp) 5877c478bd9Sstevel@tonic-gate { 5887c478bd9Sstevel@tonic-gate union T_primitives *pptr; 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate /* 5917c478bd9Sstevel@tonic-gate * During flow control and other instances when messages 5927c478bd9Sstevel@tonic-gate * are on queue, queue up a non high priority message 5937c478bd9Sstevel@tonic-gate */ 5947c478bd9Sstevel@tonic-gate if (q->q_first != 0 && mp->b_datap->db_type < QPCTL) { 5957c478bd9Sstevel@tonic-gate (void) putq(q, mp); 5967c478bd9Sstevel@tonic-gate return; 5977c478bd9Sstevel@tonic-gate } 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate /* 6007c478bd9Sstevel@tonic-gate * Inline processing of data (to avoid additional procedure call). 6017c478bd9Sstevel@tonic-gate * Rest is handled in timodrproc. 6027c478bd9Sstevel@tonic-gate */ 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 6057c478bd9Sstevel@tonic-gate case M_DATA: 6067c478bd9Sstevel@tonic-gate if (bcanputnext(q, mp->b_band)) 6077c478bd9Sstevel@tonic-gate putnext(q, mp); 6087c478bd9Sstevel@tonic-gate else 6097c478bd9Sstevel@tonic-gate (void) putq(q, mp); 6107c478bd9Sstevel@tonic-gate break; 6117c478bd9Sstevel@tonic-gate case M_PROTO: 6127c478bd9Sstevel@tonic-gate case M_PCPROTO: 6137c478bd9Sstevel@tonic-gate if (MBLKL(mp) < sizeof (t_scalar_t)) { 6147c478bd9Sstevel@tonic-gate if (mp->b_datap->db_type == M_PCPROTO || 6157c478bd9Sstevel@tonic-gate bcanputnext(q, mp->b_band)) { 6167c478bd9Sstevel@tonic-gate putnext(q, mp); 6177c478bd9Sstevel@tonic-gate } else { 6187c478bd9Sstevel@tonic-gate (void) putq(q, mp); 6197c478bd9Sstevel@tonic-gate } 6207c478bd9Sstevel@tonic-gate break; 6217c478bd9Sstevel@tonic-gate } 6227c478bd9Sstevel@tonic-gate pptr = (union T_primitives *)mp->b_rptr; 6237c478bd9Sstevel@tonic-gate switch (pptr->type) { 6247c478bd9Sstevel@tonic-gate case T_EXDATA_IND: 6257c478bd9Sstevel@tonic-gate case T_DATA_IND: 6267c478bd9Sstevel@tonic-gate case T_UNITDATA_IND: 6277c478bd9Sstevel@tonic-gate if (bcanputnext(q, mp->b_band)) 6287c478bd9Sstevel@tonic-gate putnext(q, mp); 6297c478bd9Sstevel@tonic-gate else 6307c478bd9Sstevel@tonic-gate (void) putq(q, mp); 6317c478bd9Sstevel@tonic-gate break; 6327c478bd9Sstevel@tonic-gate default: 6337c478bd9Sstevel@tonic-gate (void) timodrproc(q, mp); 6347c478bd9Sstevel@tonic-gate break; 6357c478bd9Sstevel@tonic-gate } 6367c478bd9Sstevel@tonic-gate break; 6377c478bd9Sstevel@tonic-gate default: 6387c478bd9Sstevel@tonic-gate (void) timodrproc(q, mp); 6397c478bd9Sstevel@tonic-gate break; 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate } 6427c478bd9Sstevel@tonic-gate 6437c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 6447c478bd9Sstevel@tonic-gate /* 6457c478bd9Sstevel@tonic-gate * timodrsrv - Module read queue service procedure. This is called when 6467c478bd9Sstevel@tonic-gate * messages are placed on an empty queue, when high priority 6477c478bd9Sstevel@tonic-gate * messages are placed on the queue, and when flow control 6487c478bd9Sstevel@tonic-gate * restrictions subside. This code used to be included in a 6497c478bd9Sstevel@tonic-gate * put procedure, but it was moved to a service procedure 6507c478bd9Sstevel@tonic-gate * because several points were added where memory allocation 6517c478bd9Sstevel@tonic-gate * could fail, and there is no reasonable recovery mechanism 6527c478bd9Sstevel@tonic-gate * from the put procedure. 6537c478bd9Sstevel@tonic-gate */ 6547c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 6557c478bd9Sstevel@tonic-gate static void 6567c478bd9Sstevel@tonic-gate timodrsrv(queue_t *q) 6577c478bd9Sstevel@tonic-gate { 6587c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 6597c478bd9Sstevel@tonic-gate mblk_t *mp; 6607c478bd9Sstevel@tonic-gate struct tim_tim *tp; 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate ASSERT(q != NULL); 6637c478bd9Sstevel@tonic-gate 6647c478bd9Sstevel@tonic-gate tp = (struct tim_tim *)q->q_ptr; 6657c478bd9Sstevel@tonic-gate if (!tp) 6667c478bd9Sstevel@tonic-gate return; 6677c478bd9Sstevel@tonic-gate 6687c478bd9Sstevel@tonic-gate while ((mp = getq(q)) != NULL) { 6697c478bd9Sstevel@tonic-gate if (timodrproc(q, mp)) { 6707c478bd9Sstevel@tonic-gate /* 6717c478bd9Sstevel@tonic-gate * timodrproc did a putbq - stop processing 6727c478bd9Sstevel@tonic-gate * messages. 6737c478bd9Sstevel@tonic-gate */ 6747c478bd9Sstevel@tonic-gate return; 6757c478bd9Sstevel@tonic-gate } 6767c478bd9Sstevel@tonic-gate } 6777c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 6787c478bd9Sstevel@tonic-gate } 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate /* 6817c478bd9Sstevel@tonic-gate * Perform common processing when a T_CAPABILITY_ACK or T_INFO_ACK 6827c478bd9Sstevel@tonic-gate * arrive. Set the queue properties and adjust the tim_flags according 6837c478bd9Sstevel@tonic-gate * to the service type. 6847c478bd9Sstevel@tonic-gate */ 6857c478bd9Sstevel@tonic-gate static void 6867c478bd9Sstevel@tonic-gate timodprocessinfo(queue_t *q, struct tim_tim *tp, struct T_info_ack *tia) 6877c478bd9Sstevel@tonic-gate { 6887c478bd9Sstevel@tonic-gate TILOG("timodprocessinfo: strqset(%d)\n", tia->TIDU_size); 6897c478bd9Sstevel@tonic-gate (void) strqset(q, QMAXPSZ, 0, tia->TIDU_size); 6907c478bd9Sstevel@tonic-gate (void) strqset(OTHERQ(q), QMAXPSZ, 0, tia->TIDU_size); 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate if ((tia->SERV_type == T_COTS) || (tia->SERV_type == T_COTS_ORD)) 6937c478bd9Sstevel@tonic-gate tp->tim_flags = (tp->tim_flags & ~CLTS) | COTS; 6947c478bd9Sstevel@tonic-gate else if (tia->SERV_type == T_CLTS) 6957c478bd9Sstevel@tonic-gate tp->tim_flags = (tp->tim_flags & ~COTS) | CLTS; 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate static int 6997c478bd9Sstevel@tonic-gate timodrproc(queue_t *q, mblk_t *mp) 7007c478bd9Sstevel@tonic-gate { 7017c478bd9Sstevel@tonic-gate union T_primitives *pptr; 7027c478bd9Sstevel@tonic-gate struct tim_tim *tp; 7037c478bd9Sstevel@tonic-gate struct iocblk *iocbp; 7047c478bd9Sstevel@tonic-gate mblk_t *nbp; 7057c478bd9Sstevel@tonic-gate size_t blen; 7067c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate tp = (struct tim_tim *)q->q_ptr; 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 7117c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 7127c478bd9Sstevel@tonic-gate default: 7137c478bd9Sstevel@tonic-gate putnext(q, mp); 7147c478bd9Sstevel@tonic-gate break; 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate case M_ERROR: 7177c478bd9Sstevel@tonic-gate TILOG("timodrproc: Got M_ERROR, flags = %x\n", tp->tim_flags); 7187c478bd9Sstevel@tonic-gate /* 7197c478bd9Sstevel@tonic-gate * There is no specified standard response for driver when it 7207c478bd9Sstevel@tonic-gate * receives unknown message type and M_ERROR is one 7217c478bd9Sstevel@tonic-gate * possibility. If we send T_CAPABILITY_REQ down and transport 7227c478bd9Sstevel@tonic-gate * provider responds with M_ERROR we assume that it doesn't 7237c478bd9Sstevel@tonic-gate * understand this message type. This assumption may be 7247c478bd9Sstevel@tonic-gate * sometimes incorrect (transport may reply with M_ERROR for 7257c478bd9Sstevel@tonic-gate * some other reason) but there is no way for us to distinguish 7267c478bd9Sstevel@tonic-gate * between different cases. In the worst case timod and everyone 7277c478bd9Sstevel@tonic-gate * else sharing global transport description with it may end up 7287c478bd9Sstevel@tonic-gate * emulating T_CAPABILITY_REQ. 7297c478bd9Sstevel@tonic-gate */ 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate /* 7327c478bd9Sstevel@tonic-gate * Check that we are waiting for T_CAPABILITY_ACK and 7337c478bd9Sstevel@tonic-gate * T_CAPABILITY_REQ is not implemented by transport or emulated 7347c478bd9Sstevel@tonic-gate * by timod. 7357c478bd9Sstevel@tonic-gate */ 7367c478bd9Sstevel@tonic-gate if ((tp->tim_provinfo->tpi_capability == PI_DONTKNOW) && 7377c478bd9Sstevel@tonic-gate ((tp->tim_flags & TI_CAP_RECVD) != 0)) { 7387c478bd9Sstevel@tonic-gate /* 7397c478bd9Sstevel@tonic-gate * Good chances that this transport doesn't provide 7407c478bd9Sstevel@tonic-gate * T_CAPABILITY_REQ. Mark this information permanently 7417c478bd9Sstevel@tonic-gate * for the module + transport combination. 7427c478bd9Sstevel@tonic-gate */ 7437c478bd9Sstevel@tonic-gate PI_PROVLOCK(tp->tim_provinfo); 7447c478bd9Sstevel@tonic-gate if (tp->tim_provinfo->tpi_capability == PI_DONTKNOW) 7457c478bd9Sstevel@tonic-gate tp->tim_provinfo->tpi_capability = PI_NO; 7467c478bd9Sstevel@tonic-gate PI_PROVUNLOCK(tp->tim_provinfo); 7477c478bd9Sstevel@tonic-gate if (tp->tim_tcap_timoutid != 0) { 7487c478bd9Sstevel@tonic-gate (void) quntimeout(q, tp->tim_tcap_timoutid); 7497c478bd9Sstevel@tonic-gate tp->tim_tcap_timoutid = 0; 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate } 7527c478bd9Sstevel@tonic-gate putnext(q, mp); 7537c478bd9Sstevel@tonic-gate break; 7547c478bd9Sstevel@tonic-gate case M_DATA: 7557c478bd9Sstevel@tonic-gate if (!bcanputnext(q, mp->b_band)) { 7567c478bd9Sstevel@tonic-gate (void) putbq(q, mp); 7577c478bd9Sstevel@tonic-gate return (1); 7587c478bd9Sstevel@tonic-gate } 7597c478bd9Sstevel@tonic-gate putnext(q, mp); 7607c478bd9Sstevel@tonic-gate break; 7617c478bd9Sstevel@tonic-gate 7627c478bd9Sstevel@tonic-gate case M_PROTO: 7637c478bd9Sstevel@tonic-gate case M_PCPROTO: 7647c478bd9Sstevel@tonic-gate blen = MBLKL(mp); 7657c478bd9Sstevel@tonic-gate if (blen < sizeof (t_scalar_t)) { 7667c478bd9Sstevel@tonic-gate /* 7677c478bd9Sstevel@tonic-gate * Note: it's not actually possible to get 7687c478bd9Sstevel@tonic-gate * here with db_type M_PCPROTO, because 7697c478bd9Sstevel@tonic-gate * timodrput has already checked MBLKL, and 7707c478bd9Sstevel@tonic-gate * thus the assertion below. If the length 7717c478bd9Sstevel@tonic-gate * was too short, then the message would have 7727c478bd9Sstevel@tonic-gate * already been putnext'd, and would thus 7737c478bd9Sstevel@tonic-gate * never appear here. Just the same, the code 7747c478bd9Sstevel@tonic-gate * below handles the impossible case since 7757c478bd9Sstevel@tonic-gate * it's easy to do and saves future 7767c478bd9Sstevel@tonic-gate * maintainers from unfortunate accidents. 7777c478bd9Sstevel@tonic-gate */ 7787c478bd9Sstevel@tonic-gate ASSERT(mp->b_datap->db_type == M_PROTO); 7797c478bd9Sstevel@tonic-gate if (mp->b_datap->db_type == M_PROTO && 7807c478bd9Sstevel@tonic-gate !bcanputnext(q, mp->b_band)) { 7817c478bd9Sstevel@tonic-gate (void) putbq(q, mp); 7827c478bd9Sstevel@tonic-gate return (1); 7837c478bd9Sstevel@tonic-gate } 7847c478bd9Sstevel@tonic-gate putnext(q, mp); 7857c478bd9Sstevel@tonic-gate break; 7867c478bd9Sstevel@tonic-gate } 7877c478bd9Sstevel@tonic-gate 7887c478bd9Sstevel@tonic-gate pptr = (union T_primitives *)mp->b_rptr; 7897c478bd9Sstevel@tonic-gate switch (pptr->type) { 7907c478bd9Sstevel@tonic-gate default: 7917c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate #ifdef C2_AUDIT 7947c478bd9Sstevel@tonic-gate if (audit_active) 7957c478bd9Sstevel@tonic-gate audit_sock(T_UNITDATA_IND, q, mp, TIMOD_ID); 7967c478bd9Sstevel@tonic-gate #endif 7977c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 7987c478bd9Sstevel@tonic-gate putnext(q, mp); 7997c478bd9Sstevel@tonic-gate break; 8007c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 8017c478bd9Sstevel@tonic-gate 8027c478bd9Sstevel@tonic-gate case T_ERROR_ACK: 8037c478bd9Sstevel@tonic-gate /* Restore db_type - recover() might have changed it */ 8047c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PCPROTO; 8057c478bd9Sstevel@tonic-gate if (blen < sizeof (struct T_error_ack)) { 8067c478bd9Sstevel@tonic-gate putnext(q, mp); 8077c478bd9Sstevel@tonic-gate break; 8087c478bd9Sstevel@tonic-gate } 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate tilog("timodrproc: Got T_ERROR_ACK, flags = %x\n", 8117c478bd9Sstevel@tonic-gate tp->tim_flags); 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate if ((tp->tim_flags & WAIT_CONNRESACK) && 8147c478bd9Sstevel@tonic-gate tp->tim_saved_prim == pptr->error_ack.ERROR_prim) { 8157c478bd9Sstevel@tonic-gate tp->tim_flags &= 8167c478bd9Sstevel@tonic-gate ~(WAIT_CONNRESACK | WAITIOCACK); 8177c478bd9Sstevel@tonic-gate freemsg(tp->tim_iocsave); 8187c478bd9Sstevel@tonic-gate tp->tim_iocsave = NULL; 8197c478bd9Sstevel@tonic-gate tp->tim_saved_prim = -1; 8207c478bd9Sstevel@tonic-gate putnext(q, mp); 8217c478bd9Sstevel@tonic-gate } else if (tp->tim_flags & WAITIOCACK) { 8227c478bd9Sstevel@tonic-gate tim_send_ioc_error_ack(q, tp, mp); 8237c478bd9Sstevel@tonic-gate } else { 8247c478bd9Sstevel@tonic-gate putnext(q, mp); 8257c478bd9Sstevel@tonic-gate } 8267c478bd9Sstevel@tonic-gate break; 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate case T_OK_ACK: 8297c478bd9Sstevel@tonic-gate if (blen < sizeof (pptr->ok_ack)) { 8307c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PCPROTO; 8317c478bd9Sstevel@tonic-gate putnext(q, mp); 8327c478bd9Sstevel@tonic-gate break; 8337c478bd9Sstevel@tonic-gate } 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate tilog("timodrproc: Got T_OK_ACK\n", 0); 8367c478bd9Sstevel@tonic-gate 8377c478bd9Sstevel@tonic-gate if (pptr->ok_ack.CORRECT_prim == T_UNBIND_REQ) 8387c478bd9Sstevel@tonic-gate tp->tim_mylen = 0; 8397c478bd9Sstevel@tonic-gate 8407c478bd9Sstevel@tonic-gate if ((tp->tim_flags & WAIT_CONNRESACK) && 8417c478bd9Sstevel@tonic-gate tp->tim_saved_prim == pptr->ok_ack.CORRECT_prim) { 8427c478bd9Sstevel@tonic-gate struct T_conn_res *resp; 8437c478bd9Sstevel@tonic-gate struct T_conn_ind *indp; 8447c478bd9Sstevel@tonic-gate struct tim_tim *ntp; 8457c478bd9Sstevel@tonic-gate caddr_t ptr; 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate rw_enter(&tim_list_rwlock, RW_READER); 8487c478bd9Sstevel@tonic-gate resp = (struct T_conn_res *) 8497c478bd9Sstevel@tonic-gate tp->tim_iocsave->b_rptr; 8507c478bd9Sstevel@tonic-gate ntp = tim_findlink(resp->ACCEPTOR_id); 8517c478bd9Sstevel@tonic-gate if (ntp == NULL) 8527c478bd9Sstevel@tonic-gate goto cresackout; 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate mutex_enter(&ntp->tim_mutex); 8557c478bd9Sstevel@tonic-gate if (ntp->tim_peercred != NULL) 8567c478bd9Sstevel@tonic-gate crfree(ntp->tim_peercred); 8577c478bd9Sstevel@tonic-gate ntp->tim_peercred = 8587c478bd9Sstevel@tonic-gate DB_CRED(tp->tim_iocsave->b_cont); 8597c478bd9Sstevel@tonic-gate ntp->tim_cpid = 8607c478bd9Sstevel@tonic-gate DB_CPID(tp->tim_iocsave->b_cont); 8617c478bd9Sstevel@tonic-gate if (ntp->tim_peercred != NULL) 8627c478bd9Sstevel@tonic-gate crhold(ntp->tim_peercred); 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate if (!(ntp->tim_flags & DO_PEERNAME)) { 8657c478bd9Sstevel@tonic-gate mutex_exit(&ntp->tim_mutex); 8667c478bd9Sstevel@tonic-gate goto cresackout; 8677c478bd9Sstevel@tonic-gate } 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate indp = (struct T_conn_ind *) 8707c478bd9Sstevel@tonic-gate tp->tim_iocsave->b_cont->b_rptr; 8717c478bd9Sstevel@tonic-gate /* true as message is put on list */ 8727c478bd9Sstevel@tonic-gate ASSERT(indp->SRC_length >= 0); 8737c478bd9Sstevel@tonic-gate 8747c478bd9Sstevel@tonic-gate if (indp->SRC_length > ntp->tim_peermaxlen) { 8757c478bd9Sstevel@tonic-gate ptr = kmem_alloc(indp->SRC_length, 8767c478bd9Sstevel@tonic-gate KM_NOSLEEP); 8777c478bd9Sstevel@tonic-gate if (ptr == NULL) { 8787c478bd9Sstevel@tonic-gate mutex_exit(&ntp->tim_mutex); 8797c478bd9Sstevel@tonic-gate rw_exit(&tim_list_rwlock); 8807c478bd9Sstevel@tonic-gate tilog("timodwproc: kmem_alloc " 8817c478bd9Sstevel@tonic-gate "failed, attempting " 8827c478bd9Sstevel@tonic-gate "recovery\n", 0); 8837c478bd9Sstevel@tonic-gate tim_recover(q, mp, 8847c478bd9Sstevel@tonic-gate indp->SRC_length); 8857c478bd9Sstevel@tonic-gate return (1); 8867c478bd9Sstevel@tonic-gate } 8877c478bd9Sstevel@tonic-gate if (ntp->tim_peermaxlen > 0) 8887c478bd9Sstevel@tonic-gate kmem_free(ntp->tim_peername, 8897c478bd9Sstevel@tonic-gate ntp->tim_peermaxlen); 8907c478bd9Sstevel@tonic-gate ntp->tim_peername = ptr; 8917c478bd9Sstevel@tonic-gate ntp->tim_peermaxlen = indp->SRC_length; 8927c478bd9Sstevel@tonic-gate } 8937c478bd9Sstevel@tonic-gate ntp->tim_peerlen = indp->SRC_length; 8947c478bd9Sstevel@tonic-gate ptr = (caddr_t)indp + indp->SRC_offset; 8957c478bd9Sstevel@tonic-gate bcopy(ptr, ntp->tim_peername, ntp->tim_peerlen); 8967c478bd9Sstevel@tonic-gate 8977c478bd9Sstevel@tonic-gate mutex_exit(&ntp->tim_mutex); 8987c478bd9Sstevel@tonic-gate 8997c478bd9Sstevel@tonic-gate cresackout: 9007c478bd9Sstevel@tonic-gate rw_exit(&tim_list_rwlock); 9017c478bd9Sstevel@tonic-gate tp->tim_flags &= 9027c478bd9Sstevel@tonic-gate ~(WAIT_CONNRESACK | WAITIOCACK); 9037c478bd9Sstevel@tonic-gate freemsg(tp->tim_iocsave); 9047c478bd9Sstevel@tonic-gate tp->tim_iocsave = NULL; 9057c478bd9Sstevel@tonic-gate tp->tim_saved_prim = -1; 9067c478bd9Sstevel@tonic-gate } 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate tim_send_reply(q, mp, tp, pptr->ok_ack.CORRECT_prim); 9097c478bd9Sstevel@tonic-gate break; 9107c478bd9Sstevel@tonic-gate 9117c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 9127c478bd9Sstevel@tonic-gate case T_BIND_ACK: { 9137c478bd9Sstevel@tonic-gate struct T_bind_ack *ackp = 9147c478bd9Sstevel@tonic-gate (struct T_bind_ack *)mp->b_rptr; 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate /* Restore db_type - recover() might have changed it */ 9177c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PCPROTO; 9187c478bd9Sstevel@tonic-gate if (blen < sizeof (*ackp)) { 9197c478bd9Sstevel@tonic-gate putnext(q, mp); 9207c478bd9Sstevel@tonic-gate break; 9217c478bd9Sstevel@tonic-gate } 9227c478bd9Sstevel@tonic-gate 9237c478bd9Sstevel@tonic-gate /* save negotiated backlog */ 9247c478bd9Sstevel@tonic-gate tp->tim_backlog = ackp->CONIND_number; 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate if (((tp->tim_flags & WAITIOCACK) == 0) || 9277c478bd9Sstevel@tonic-gate ((tp->tim_saved_prim != O_T_BIND_REQ) && 9287c478bd9Sstevel@tonic-gate (tp->tim_saved_prim != T_BIND_REQ))) { 9297c478bd9Sstevel@tonic-gate putnext(q, mp); 9307c478bd9Sstevel@tonic-gate break; 9317c478bd9Sstevel@tonic-gate } 9327c478bd9Sstevel@tonic-gate ASSERT(tp->tim_iocsave != NULL); 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate if (tp->tim_flags & DO_MYNAME) { 9357c478bd9Sstevel@tonic-gate caddr_t p; 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate if (ackp->ADDR_length < 0 || 9387c478bd9Sstevel@tonic-gate mp->b_rptr + ackp->ADDR_offset + 9397c478bd9Sstevel@tonic-gate ackp->ADDR_length > mp->b_wptr) { 9407c478bd9Sstevel@tonic-gate putnext(q, mp); 9417c478bd9Sstevel@tonic-gate break; 9427c478bd9Sstevel@tonic-gate } 9437c478bd9Sstevel@tonic-gate if (ackp->ADDR_length > tp->tim_mymaxlen) { 9447c478bd9Sstevel@tonic-gate p = kmem_alloc(ackp->ADDR_length, 9457c478bd9Sstevel@tonic-gate KM_NOSLEEP); 9467c478bd9Sstevel@tonic-gate if (p == NULL) { 9477c478bd9Sstevel@tonic-gate tilog("timodrproc: kmem_alloc " 9487c478bd9Sstevel@tonic-gate "failed attempt recovery", 9497c478bd9Sstevel@tonic-gate 0); 9507c478bd9Sstevel@tonic-gate 9517c478bd9Sstevel@tonic-gate tim_recover(q, mp, 9527c478bd9Sstevel@tonic-gate ackp->ADDR_length); 9537c478bd9Sstevel@tonic-gate return (1); 9547c478bd9Sstevel@tonic-gate } 9557c478bd9Sstevel@tonic-gate ASSERT(tp->tim_mymaxlen >= 0); 9567c478bd9Sstevel@tonic-gate if (tp->tim_mymaxlen != NULL) { 9577c478bd9Sstevel@tonic-gate kmem_free(tp->tim_myname, 9587c478bd9Sstevel@tonic-gate tp->tim_mymaxlen); 9597c478bd9Sstevel@tonic-gate } 9607c478bd9Sstevel@tonic-gate tp->tim_myname = p; 9617c478bd9Sstevel@tonic-gate tp->tim_mymaxlen = ackp->ADDR_length; 9627c478bd9Sstevel@tonic-gate } 9637c478bd9Sstevel@tonic-gate tp->tim_mylen = ackp->ADDR_length; 9647c478bd9Sstevel@tonic-gate bcopy(mp->b_rptr + ackp->ADDR_offset, 9657c478bd9Sstevel@tonic-gate tp->tim_myname, tp->tim_mylen); 9667c478bd9Sstevel@tonic-gate } 9677c478bd9Sstevel@tonic-gate tim_ioctl_send_reply(q, tp->tim_iocsave, mp); 9687c478bd9Sstevel@tonic-gate tp->tim_iocsave = NULL; 9697c478bd9Sstevel@tonic-gate tp->tim_saved_prim = -1; 9707c478bd9Sstevel@tonic-gate tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 9717c478bd9Sstevel@tonic-gate TI_CAP_RECVD | CAP_WANTS_INFO); 9727c478bd9Sstevel@tonic-gate break; 9737c478bd9Sstevel@tonic-gate } 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 9767c478bd9Sstevel@tonic-gate case T_OPTMGMT_ACK: 9777c478bd9Sstevel@tonic-gate 9787c478bd9Sstevel@tonic-gate tilog("timodrproc: Got T_OPTMGMT_ACK\n", 0); 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate /* Restore db_type - recover() might have change it */ 9817c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PCPROTO; 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate if (((tp->tim_flags & WAITIOCACK) == 0) || 9847c478bd9Sstevel@tonic-gate ((tp->tim_saved_prim != T_SVR4_OPTMGMT_REQ) && 9857c478bd9Sstevel@tonic-gate (tp->tim_saved_prim != T_OPTMGMT_REQ))) { 9867c478bd9Sstevel@tonic-gate putnext(q, mp); 9877c478bd9Sstevel@tonic-gate } else { 9887c478bd9Sstevel@tonic-gate ASSERT(tp->tim_iocsave != NULL); 9897c478bd9Sstevel@tonic-gate tim_ioctl_send_reply(q, tp->tim_iocsave, mp); 9907c478bd9Sstevel@tonic-gate tp->tim_iocsave = NULL; 9917c478bd9Sstevel@tonic-gate tp->tim_saved_prim = -1; 9927c478bd9Sstevel@tonic-gate tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 9937c478bd9Sstevel@tonic-gate TI_CAP_RECVD | CAP_WANTS_INFO); 9947c478bd9Sstevel@tonic-gate } 9957c478bd9Sstevel@tonic-gate break; 9967c478bd9Sstevel@tonic-gate 9977c478bd9Sstevel@tonic-gate case T_INFO_ACK: { 9987c478bd9Sstevel@tonic-gate struct T_info_ack *tia = (struct T_info_ack *)pptr; 9997c478bd9Sstevel@tonic-gate 10007c478bd9Sstevel@tonic-gate /* Restore db_type - recover() might have changed it */ 10017c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PCPROTO; 10027c478bd9Sstevel@tonic-gate 10037c478bd9Sstevel@tonic-gate if (blen < sizeof (*tia)) { 10047c478bd9Sstevel@tonic-gate putnext(q, mp); 10057c478bd9Sstevel@tonic-gate break; 10067c478bd9Sstevel@tonic-gate } 10077c478bd9Sstevel@tonic-gate 10087c478bd9Sstevel@tonic-gate tilog("timodrproc: Got T_INFO_ACK, flags = %x\n", 10097c478bd9Sstevel@tonic-gate tp->tim_flags); 10107c478bd9Sstevel@tonic-gate 10117c478bd9Sstevel@tonic-gate timodprocessinfo(q, tp, tia); 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate TILOG("timodrproc: flags = %x\n", tp->tim_flags); 10147c478bd9Sstevel@tonic-gate if ((tp->tim_flags & WAITIOCACK) != 0) { 10157c478bd9Sstevel@tonic-gate size_t expected_ack_size; 10167c478bd9Sstevel@tonic-gate ssize_t deficit; 10177c478bd9Sstevel@tonic-gate int ioc_cmd; 10187c478bd9Sstevel@tonic-gate struct T_capability_ack *tcap; 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate /* 10217c478bd9Sstevel@tonic-gate * The only case when T_INFO_ACK may be received back 10227c478bd9Sstevel@tonic-gate * when we are waiting for ioctl to complete is when 10237c478bd9Sstevel@tonic-gate * this ioctl sent T_INFO_REQ down. 10247c478bd9Sstevel@tonic-gate */ 10257c478bd9Sstevel@tonic-gate if (!(tp->tim_flags & WAIT_IOCINFOACK)) { 10267c478bd9Sstevel@tonic-gate putnext(q, mp); 10277c478bd9Sstevel@tonic-gate break; 10287c478bd9Sstevel@tonic-gate } 10297c478bd9Sstevel@tonic-gate ASSERT(tp->tim_iocsave != NULL); 10307c478bd9Sstevel@tonic-gate 10317c478bd9Sstevel@tonic-gate iocbp = (struct iocblk *)tp->tim_iocsave->b_rptr; 10327c478bd9Sstevel@tonic-gate ioc_cmd = iocbp->ioc_cmd; 10337c478bd9Sstevel@tonic-gate 10347c478bd9Sstevel@tonic-gate /* 10357c478bd9Sstevel@tonic-gate * Was it sent from TI_CAPABILITY emulation? 10367c478bd9Sstevel@tonic-gate */ 10377c478bd9Sstevel@tonic-gate if (ioc_cmd == TI_CAPABILITY) { 10387c478bd9Sstevel@tonic-gate struct T_info_ack saved_info; 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate /* 10417c478bd9Sstevel@tonic-gate * Perform sanity checks. The only case when we 10427c478bd9Sstevel@tonic-gate * send T_INFO_REQ from TI_CAPABILITY is when 10437c478bd9Sstevel@tonic-gate * timod emulates T_CAPABILITY_REQ and CAP_bits1 10447c478bd9Sstevel@tonic-gate * has TC1_INFO set. 10457c478bd9Sstevel@tonic-gate */ 10467c478bd9Sstevel@tonic-gate if ((tp->tim_flags & 10477c478bd9Sstevel@tonic-gate (TI_CAP_RECVD | CAP_WANTS_INFO)) != 10487c478bd9Sstevel@tonic-gate (TI_CAP_RECVD | CAP_WANTS_INFO)) { 10497c478bd9Sstevel@tonic-gate putnext(q, mp); 10507c478bd9Sstevel@tonic-gate break; 10517c478bd9Sstevel@tonic-gate } 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate TILOG("timodrproc: emulating TI_CAPABILITY/" 10547c478bd9Sstevel@tonic-gate "info\n", 0); 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate /* Save info & reuse mp for T_CAPABILITY_ACK */ 10577c478bd9Sstevel@tonic-gate saved_info = *tia; 10587c478bd9Sstevel@tonic-gate 10597c478bd9Sstevel@tonic-gate mp = tpi_ack_alloc(mp, 10607c478bd9Sstevel@tonic-gate sizeof (struct T_capability_ack), 10617c478bd9Sstevel@tonic-gate M_PCPROTO, T_CAPABILITY_ACK); 10627c478bd9Sstevel@tonic-gate 10637c478bd9Sstevel@tonic-gate if (mp == NULL) { 10647c478bd9Sstevel@tonic-gate tilog("timodrproc: realloc failed, " 10657c478bd9Sstevel@tonic-gate "no recovery attempted\n", 0); 10667c478bd9Sstevel@tonic-gate return (1); 10677c478bd9Sstevel@tonic-gate } 10687c478bd9Sstevel@tonic-gate 10697c478bd9Sstevel@tonic-gate /* 10707c478bd9Sstevel@tonic-gate * Copy T_INFO information into T_CAPABILITY_ACK 10717c478bd9Sstevel@tonic-gate */ 10727c478bd9Sstevel@tonic-gate tcap = (struct T_capability_ack *)mp->b_rptr; 10737c478bd9Sstevel@tonic-gate tcap->CAP_bits1 = TC1_INFO; 10747c478bd9Sstevel@tonic-gate tcap->INFO_ack = saved_info; 10757c478bd9Sstevel@tonic-gate tp->tim_flags &= ~(WAITIOCACK | 10767c478bd9Sstevel@tonic-gate WAIT_IOCINFOACK | TI_CAP_RECVD | 10777c478bd9Sstevel@tonic-gate CAP_WANTS_INFO); 10787c478bd9Sstevel@tonic-gate tim_ioctl_send_reply(q, tp->tim_iocsave, mp); 10797c478bd9Sstevel@tonic-gate tp->tim_iocsave = NULL; 10807c478bd9Sstevel@tonic-gate tp->tim_saved_prim = -1; 10817c478bd9Sstevel@tonic-gate break; 10827c478bd9Sstevel@tonic-gate } 10837c478bd9Sstevel@tonic-gate 10847c478bd9Sstevel@tonic-gate /* 10857c478bd9Sstevel@tonic-gate * The code for TI_SYNC/TI_GETINFO is left here only for 10867c478bd9Sstevel@tonic-gate * backward compatibility with staticaly linked old 10877c478bd9Sstevel@tonic-gate * applications. New TLI/XTI code should use 10887c478bd9Sstevel@tonic-gate * TI_CAPABILITY for getting transport info and should 10897c478bd9Sstevel@tonic-gate * not use TI_GETINFO/TI_SYNC for this purpose. 10907c478bd9Sstevel@tonic-gate */ 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate /* 10937c478bd9Sstevel@tonic-gate * make sure the message sent back is the size of 10947c478bd9Sstevel@tonic-gate * the "expected ack" 10957c478bd9Sstevel@tonic-gate * For TI_GETINFO, expected ack size is 10967c478bd9Sstevel@tonic-gate * sizeof (T_info_ack) 10977c478bd9Sstevel@tonic-gate * For TI_SYNC, expected ack size is 10987c478bd9Sstevel@tonic-gate * sizeof (struct ti_sync_ack); 10997c478bd9Sstevel@tonic-gate */ 11007c478bd9Sstevel@tonic-gate if (ioc_cmd != TI_GETINFO && ioc_cmd != TI_SYNC) { 11017c478bd9Sstevel@tonic-gate putnext(q, mp); 11027c478bd9Sstevel@tonic-gate break; 11037c478bd9Sstevel@tonic-gate } 11047c478bd9Sstevel@tonic-gate 11057c478bd9Sstevel@tonic-gate expected_ack_size = 11067c478bd9Sstevel@tonic-gate sizeof (struct T_info_ack); /* TI_GETINFO */ 11077c478bd9Sstevel@tonic-gate if (iocbp->ioc_cmd == TI_SYNC) { 11087c478bd9Sstevel@tonic-gate expected_ack_size = 2 * sizeof (uint32_t) + 11097c478bd9Sstevel@tonic-gate sizeof (struct ti_sync_ack); 11107c478bd9Sstevel@tonic-gate } 11117c478bd9Sstevel@tonic-gate deficit = expected_ack_size - blen; 11127c478bd9Sstevel@tonic-gate 11137c478bd9Sstevel@tonic-gate if (deficit != 0) { 11147c478bd9Sstevel@tonic-gate if (mp->b_datap->db_lim - mp->b_wptr < 11157c478bd9Sstevel@tonic-gate deficit) { 11167c478bd9Sstevel@tonic-gate mblk_t *tmp = allocb(expected_ack_size, 11177c478bd9Sstevel@tonic-gate BPRI_HI); 11187c478bd9Sstevel@tonic-gate if (tmp == NULL) { 11197c478bd9Sstevel@tonic-gate ASSERT((mp->b_datap->db_lim - 11207c478bd9Sstevel@tonic-gate mp->b_datap->db_base) < 11217c478bd9Sstevel@tonic-gate sizeof (struct T_error_ack)); 11227c478bd9Sstevel@tonic-gate 11237c478bd9Sstevel@tonic-gate tilog("timodrproc: allocb failed no " 11247c478bd9Sstevel@tonic-gate "recovery attempt\n", 0); 11257c478bd9Sstevel@tonic-gate 11267c478bd9Sstevel@tonic-gate mp->b_rptr = mp->b_datap->db_base; 11277c478bd9Sstevel@tonic-gate pptr = (union T_primitives *) 11287c478bd9Sstevel@tonic-gate mp->b_rptr; 11297c478bd9Sstevel@tonic-gate pptr->error_ack.ERROR_prim = T_INFO_ACK; 11307c478bd9Sstevel@tonic-gate pptr->error_ack.TLI_error = TSYSERR; 11317c478bd9Sstevel@tonic-gate pptr->error_ack.UNIX_error = EAGAIN; 11327c478bd9Sstevel@tonic-gate pptr->error_ack.PRIM_type = T_ERROR_ACK; 11337c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PCPROTO; 11347c478bd9Sstevel@tonic-gate tim_send_ioc_error_ack(q, tp, mp); 11357c478bd9Sstevel@tonic-gate break; 11367c478bd9Sstevel@tonic-gate } else { 11377c478bd9Sstevel@tonic-gate bcopy(mp->b_rptr, tmp->b_rptr, blen); 11387c478bd9Sstevel@tonic-gate tmp->b_wptr += blen; 11397c478bd9Sstevel@tonic-gate pptr = (union T_primitives *) 11407c478bd9Sstevel@tonic-gate tmp->b_rptr; 11417c478bd9Sstevel@tonic-gate freemsg(mp); 11427c478bd9Sstevel@tonic-gate mp = tmp; 11437c478bd9Sstevel@tonic-gate } 11447c478bd9Sstevel@tonic-gate } 11457c478bd9Sstevel@tonic-gate } 11467c478bd9Sstevel@tonic-gate /* 11477c478bd9Sstevel@tonic-gate * We now have "mp" which has enough space for an 11487c478bd9Sstevel@tonic-gate * appropriate ack and contains struct T_info_ack 11497c478bd9Sstevel@tonic-gate * that the transport provider returned. We now 11507c478bd9Sstevel@tonic-gate * stuff it with more stuff to fullfill 11517c478bd9Sstevel@tonic-gate * TI_SYNC ioctl needs, as necessary 11527c478bd9Sstevel@tonic-gate */ 11537c478bd9Sstevel@tonic-gate if (iocbp->ioc_cmd == TI_SYNC) { 11547c478bd9Sstevel@tonic-gate /* 11557c478bd9Sstevel@tonic-gate * Assumes struct T_info_ack is first embedded 11567c478bd9Sstevel@tonic-gate * type in struct ti_sync_ack so it is 11577c478bd9Sstevel@tonic-gate * automatically there. 11587c478bd9Sstevel@tonic-gate */ 11597c478bd9Sstevel@tonic-gate struct ti_sync_ack *tsap = 11607c478bd9Sstevel@tonic-gate (struct ti_sync_ack *)mp->b_rptr; 11617c478bd9Sstevel@tonic-gate 11627c478bd9Sstevel@tonic-gate /* 11637c478bd9Sstevel@tonic-gate * tsap->tsa_qlen needs to be set only if 11647c478bd9Sstevel@tonic-gate * TSRF_QLEN_REQ flag is set, but for 11657c478bd9Sstevel@tonic-gate * compatibility with statically linked 11667c478bd9Sstevel@tonic-gate * applications it is set here regardless of the 11677c478bd9Sstevel@tonic-gate * flag since old XTI library expected it to be 11687c478bd9Sstevel@tonic-gate * set. 11697c478bd9Sstevel@tonic-gate */ 11707c478bd9Sstevel@tonic-gate tsap->tsa_qlen = tp->tim_backlog; 11717c478bd9Sstevel@tonic-gate tsap->tsa_flags = 0x0; /* intialize clear */ 11727c478bd9Sstevel@tonic-gate if (tp->tim_flags & PEEK_RDQ_EXPIND) { 11737c478bd9Sstevel@tonic-gate /* 11747c478bd9Sstevel@tonic-gate * Request to peek for EXPIND in 11757c478bd9Sstevel@tonic-gate * rcvbuf. 11767c478bd9Sstevel@tonic-gate */ 11777c478bd9Sstevel@tonic-gate if (ti_expind_on_rdqueues(q)) { 11787c478bd9Sstevel@tonic-gate /* 11797c478bd9Sstevel@tonic-gate * Expedited data is 11807c478bd9Sstevel@tonic-gate * queued on the stream 11817c478bd9Sstevel@tonic-gate * read side 11827c478bd9Sstevel@tonic-gate */ 11837c478bd9Sstevel@tonic-gate tsap->tsa_flags |= 11847c478bd9Sstevel@tonic-gate TSAF_EXP_QUEUED; 11857c478bd9Sstevel@tonic-gate } 11867c478bd9Sstevel@tonic-gate tp->tim_flags &= 11877c478bd9Sstevel@tonic-gate ~PEEK_RDQ_EXPIND; 11887c478bd9Sstevel@tonic-gate } 11897c478bd9Sstevel@tonic-gate mp->b_wptr += 2*sizeof (uint32_t); 11907c478bd9Sstevel@tonic-gate } 11917c478bd9Sstevel@tonic-gate tim_ioctl_send_reply(q, tp->tim_iocsave, mp); 11927c478bd9Sstevel@tonic-gate tp->tim_iocsave = NULL; 11937c478bd9Sstevel@tonic-gate tp->tim_saved_prim = -1; 11947c478bd9Sstevel@tonic-gate tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 11957c478bd9Sstevel@tonic-gate TI_CAP_RECVD | CAP_WANTS_INFO); 11967c478bd9Sstevel@tonic-gate break; 11977c478bd9Sstevel@tonic-gate } 11987c478bd9Sstevel@tonic-gate } 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate putnext(q, mp); 12017c478bd9Sstevel@tonic-gate break; 12027c478bd9Sstevel@tonic-gate 12037c478bd9Sstevel@tonic-gate case T_ADDR_ACK: 12047c478bd9Sstevel@tonic-gate tilog("timodrproc: Got T_ADDR_ACK\n", 0); 12057c478bd9Sstevel@tonic-gate tim_send_reply(q, mp, tp, T_ADDR_REQ); 12067c478bd9Sstevel@tonic-gate break; 12077c478bd9Sstevel@tonic-gate 12087c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 12097c478bd9Sstevel@tonic-gate case T_CONN_IND: { 12107c478bd9Sstevel@tonic-gate struct T_conn_ind *tcip = 12117c478bd9Sstevel@tonic-gate (struct T_conn_ind *)mp->b_rptr; 12127c478bd9Sstevel@tonic-gate 12137c478bd9Sstevel@tonic-gate tilog("timodrproc: Got T_CONN_IND\n", 0); 12147c478bd9Sstevel@tonic-gate 12157c478bd9Sstevel@tonic-gate if (blen >= sizeof (*tcip) && 12167c478bd9Sstevel@tonic-gate MBLKIN(mp, tcip->SRC_offset, tcip->SRC_length)) { 12177c478bd9Sstevel@tonic-gate if (((nbp = dupmsg(mp)) != NULL) || 12187c478bd9Sstevel@tonic-gate ((nbp = copymsg(mp)) != NULL)) { 12197c478bd9Sstevel@tonic-gate nbp->b_next = tp->tim_consave; 12207c478bd9Sstevel@tonic-gate tp->tim_consave = nbp; 12217c478bd9Sstevel@tonic-gate } else { 12227c478bd9Sstevel@tonic-gate tim_recover(q, mp, 12237c478bd9Sstevel@tonic-gate (t_scalar_t)sizeof (mblk_t)); 12247c478bd9Sstevel@tonic-gate return (1); 12257c478bd9Sstevel@tonic-gate } 12267c478bd9Sstevel@tonic-gate } 12277c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 12287c478bd9Sstevel@tonic-gate #ifdef C2_AUDIT 12297c478bd9Sstevel@tonic-gate if (audit_active) 12307c478bd9Sstevel@tonic-gate audit_sock(T_CONN_IND, q, mp, TIMOD_ID); 12317c478bd9Sstevel@tonic-gate #endif 12327c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 12337c478bd9Sstevel@tonic-gate putnext(q, mp); 12347c478bd9Sstevel@tonic-gate break; 12357c478bd9Sstevel@tonic-gate } 12367c478bd9Sstevel@tonic-gate 12377c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 12387c478bd9Sstevel@tonic-gate case T_CONN_CON: 12397c478bd9Sstevel@tonic-gate mutex_enter(&tp->tim_mutex); 12407c478bd9Sstevel@tonic-gate if (tp->tim_peercred != NULL) 12417c478bd9Sstevel@tonic-gate crfree(tp->tim_peercred); 12427c478bd9Sstevel@tonic-gate tp->tim_peercred = DB_CRED(mp); 12437c478bd9Sstevel@tonic-gate if (tp->tim_peercred != NULL) 12447c478bd9Sstevel@tonic-gate crhold(tp->tim_peercred); 12457c478bd9Sstevel@tonic-gate tp->tim_cpid = DB_CPID(mp); 12467c478bd9Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 12477c478bd9Sstevel@tonic-gate 12487c478bd9Sstevel@tonic-gate tilog("timodrproc: Got T_CONN_CON\n", 0); 12497c478bd9Sstevel@tonic-gate 12507c478bd9Sstevel@tonic-gate tp->tim_flags &= ~CONNWAIT; 12517c478bd9Sstevel@tonic-gate putnext(q, mp); 12527c478bd9Sstevel@tonic-gate break; 12537c478bd9Sstevel@tonic-gate 12547c478bd9Sstevel@tonic-gate case T_DISCON_IND: { 12557c478bd9Sstevel@tonic-gate struct T_discon_ind *disp; 12567c478bd9Sstevel@tonic-gate struct T_conn_ind *conp; 12577c478bd9Sstevel@tonic-gate mblk_t *pbp = NULL; 12587c478bd9Sstevel@tonic-gate 12597c478bd9Sstevel@tonic-gate if (q->q_first != 0) 12607c478bd9Sstevel@tonic-gate tilog("timodrput: T_DISCON_IND - flow control\n", 0); 12617c478bd9Sstevel@tonic-gate 12627c478bd9Sstevel@tonic-gate if (blen < sizeof (*disp)) { 12637c478bd9Sstevel@tonic-gate putnext(q, mp); 12647c478bd9Sstevel@tonic-gate break; 12657c478bd9Sstevel@tonic-gate } 12667c478bd9Sstevel@tonic-gate 12677c478bd9Sstevel@tonic-gate disp = (struct T_discon_ind *)mp->b_rptr; 12687c478bd9Sstevel@tonic-gate 12697c478bd9Sstevel@tonic-gate tilog("timodrproc: Got T_DISCON_IND Reason: %d\n", 12707c478bd9Sstevel@tonic-gate disp->DISCON_reason); 12717c478bd9Sstevel@tonic-gate 12727c478bd9Sstevel@tonic-gate tp->tim_flags &= ~(CONNWAIT|LOCORDREL|REMORDREL); 12737c478bd9Sstevel@tonic-gate tim_clear_peer(tp); 12747c478bd9Sstevel@tonic-gate for (nbp = tp->tim_consave; nbp; nbp = nbp->b_next) { 12757c478bd9Sstevel@tonic-gate conp = (struct T_conn_ind *)nbp->b_rptr; 12767c478bd9Sstevel@tonic-gate if (conp->SEQ_number == disp->SEQ_number) 12777c478bd9Sstevel@tonic-gate break; 12787c478bd9Sstevel@tonic-gate pbp = nbp; 12797c478bd9Sstevel@tonic-gate } 12807c478bd9Sstevel@tonic-gate if (nbp) { 12817c478bd9Sstevel@tonic-gate if (pbp) 12827c478bd9Sstevel@tonic-gate pbp->b_next = nbp->b_next; 12837c478bd9Sstevel@tonic-gate else 12847c478bd9Sstevel@tonic-gate tp->tim_consave = nbp->b_next; 12857c478bd9Sstevel@tonic-gate nbp->b_next = NULL; 12867c478bd9Sstevel@tonic-gate freemsg(nbp); 12877c478bd9Sstevel@tonic-gate } 12887c478bd9Sstevel@tonic-gate putnext(q, mp); 12897c478bd9Sstevel@tonic-gate break; 12907c478bd9Sstevel@tonic-gate } 12917c478bd9Sstevel@tonic-gate 12927c478bd9Sstevel@tonic-gate case T_ORDREL_IND: 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate tilog("timodrproc: Got T_ORDREL_IND\n", 0); 12957c478bd9Sstevel@tonic-gate 12967c478bd9Sstevel@tonic-gate if (tp->tim_flags & LOCORDREL) { 12977c478bd9Sstevel@tonic-gate tp->tim_flags &= ~(LOCORDREL|REMORDREL); 12987c478bd9Sstevel@tonic-gate tim_clear_peer(tp); 12997c478bd9Sstevel@tonic-gate } else { 13007c478bd9Sstevel@tonic-gate tp->tim_flags |= REMORDREL; 13017c478bd9Sstevel@tonic-gate } 13027c478bd9Sstevel@tonic-gate putnext(q, mp); 13037c478bd9Sstevel@tonic-gate break; 13047c478bd9Sstevel@tonic-gate 13057c478bd9Sstevel@tonic-gate case T_EXDATA_IND: 13067c478bd9Sstevel@tonic-gate case T_DATA_IND: 13077c478bd9Sstevel@tonic-gate case T_UNITDATA_IND: 13087c478bd9Sstevel@tonic-gate if (pptr->type == T_EXDATA_IND) 13097c478bd9Sstevel@tonic-gate tilog("timodrproc: Got T_EXDATA_IND\n", 0); 13107c478bd9Sstevel@tonic-gate 13117c478bd9Sstevel@tonic-gate if (!bcanputnext(q, mp->b_band)) { 13127c478bd9Sstevel@tonic-gate (void) putbq(q, mp); 13137c478bd9Sstevel@tonic-gate return (1); 13147c478bd9Sstevel@tonic-gate } 13157c478bd9Sstevel@tonic-gate putnext(q, mp); 13167c478bd9Sstevel@tonic-gate break; 13177c478bd9Sstevel@tonic-gate 13187c478bd9Sstevel@tonic-gate case T_CAPABILITY_ACK: { 13197c478bd9Sstevel@tonic-gate struct T_capability_ack *tca; 13207c478bd9Sstevel@tonic-gate 13217c478bd9Sstevel@tonic-gate if (blen < sizeof (*tca)) { 13227c478bd9Sstevel@tonic-gate putnext(q, mp); 13237c478bd9Sstevel@tonic-gate break; 13247c478bd9Sstevel@tonic-gate } 13257c478bd9Sstevel@tonic-gate 13267c478bd9Sstevel@tonic-gate /* This transport supports T_CAPABILITY_REQ */ 13277c478bd9Sstevel@tonic-gate tilog("timodrproc: Got T_CAPABILITY_ACK\n", 0); 13287c478bd9Sstevel@tonic-gate 13297c478bd9Sstevel@tonic-gate PI_PROVLOCK(tp->tim_provinfo); 13307c478bd9Sstevel@tonic-gate if (tp->tim_provinfo->tpi_capability != PI_YES) 13317c478bd9Sstevel@tonic-gate tp->tim_provinfo->tpi_capability = PI_YES; 13327c478bd9Sstevel@tonic-gate PI_PROVUNLOCK(tp->tim_provinfo); 13337c478bd9Sstevel@tonic-gate 13347c478bd9Sstevel@tonic-gate /* Reset possible pending timeout */ 13357c478bd9Sstevel@tonic-gate if (tp->tim_tcap_timoutid != 0) { 13367c478bd9Sstevel@tonic-gate (void) quntimeout(q, tp->tim_tcap_timoutid); 13377c478bd9Sstevel@tonic-gate tp->tim_tcap_timoutid = 0; 13387c478bd9Sstevel@tonic-gate } 13397c478bd9Sstevel@tonic-gate 13407c478bd9Sstevel@tonic-gate tca = (struct T_capability_ack *)mp->b_rptr; 13417c478bd9Sstevel@tonic-gate 13427c478bd9Sstevel@tonic-gate if (tca->CAP_bits1 & TC1_INFO) 13437c478bd9Sstevel@tonic-gate timodprocessinfo(q, tp, &tca->INFO_ack); 13447c478bd9Sstevel@tonic-gate 13457c478bd9Sstevel@tonic-gate tim_send_reply(q, mp, tp, T_CAPABILITY_REQ); 13467c478bd9Sstevel@tonic-gate } 13477c478bd9Sstevel@tonic-gate break; 13487c478bd9Sstevel@tonic-gate } 13497c478bd9Sstevel@tonic-gate break; 13507c478bd9Sstevel@tonic-gate 13517c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 13527c478bd9Sstevel@tonic-gate case M_FLUSH: 13537c478bd9Sstevel@tonic-gate 13547c478bd9Sstevel@tonic-gate tilog("timodrproc: Got M_FLUSH\n", 0); 13557c478bd9Sstevel@tonic-gate 13567c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR) { 13577c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHBAND) 13587c478bd9Sstevel@tonic-gate flushband(q, *(mp->b_rptr + 1), FLUSHDATA); 13597c478bd9Sstevel@tonic-gate else 13607c478bd9Sstevel@tonic-gate flushq(q, FLUSHDATA); 13617c478bd9Sstevel@tonic-gate } 13627c478bd9Sstevel@tonic-gate putnext(q, mp); 13637c478bd9Sstevel@tonic-gate break; 13647c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 13657c478bd9Sstevel@tonic-gate 13667c478bd9Sstevel@tonic-gate case M_IOCACK: 13677c478bd9Sstevel@tonic-gate iocbp = (struct iocblk *)mp->b_rptr; 13687c478bd9Sstevel@tonic-gate 13697c478bd9Sstevel@tonic-gate tilog("timodrproc: Got M_IOCACK\n", 0); 13707c478bd9Sstevel@tonic-gate 13717c478bd9Sstevel@tonic-gate if (iocbp->ioc_cmd == TI_GETMYNAME) { 13727c478bd9Sstevel@tonic-gate 13737c478bd9Sstevel@tonic-gate /* 13747c478bd9Sstevel@tonic-gate * Transport provider supports this ioctl, 13757c478bd9Sstevel@tonic-gate * so I don't have to. 13767c478bd9Sstevel@tonic-gate */ 13777c478bd9Sstevel@tonic-gate if ((tp->tim_flags & DO_MYNAME) != 0) { 13787c478bd9Sstevel@tonic-gate tp->tim_flags &= ~DO_MYNAME; 13797c478bd9Sstevel@tonic-gate PI_PROVLOCK(tp->tim_provinfo); 13807c478bd9Sstevel@tonic-gate tp->tim_provinfo->tpi_myname = PI_YES; 13817c478bd9Sstevel@tonic-gate PI_PROVUNLOCK(tp->tim_provinfo); 13827c478bd9Sstevel@tonic-gate } 13837c478bd9Sstevel@tonic-gate 13847c478bd9Sstevel@tonic-gate ASSERT(tp->tim_mymaxlen >= 0); 13857c478bd9Sstevel@tonic-gate if (tp->tim_mymaxlen != 0) { 13867c478bd9Sstevel@tonic-gate kmem_free(tp->tim_myname, (size_t)tp->tim_mymaxlen); 13877c478bd9Sstevel@tonic-gate tp->tim_myname = NULL; 13887c478bd9Sstevel@tonic-gate tp->tim_mymaxlen = 0; 13897c478bd9Sstevel@tonic-gate } 13907c478bd9Sstevel@tonic-gate /* tim_iocsave may already be overwritten. */ 13917c478bd9Sstevel@tonic-gate if (tp->tim_saved_prim == -1) { 13927c478bd9Sstevel@tonic-gate freemsg(tp->tim_iocsave); 13937c478bd9Sstevel@tonic-gate tp->tim_iocsave = NULL; 13947c478bd9Sstevel@tonic-gate } 13957c478bd9Sstevel@tonic-gate } else if (iocbp->ioc_cmd == TI_GETPEERNAME) { 13967c478bd9Sstevel@tonic-gate boolean_t clearit; 13977c478bd9Sstevel@tonic-gate 13987c478bd9Sstevel@tonic-gate /* 13997c478bd9Sstevel@tonic-gate * Transport provider supports this ioctl, 14007c478bd9Sstevel@tonic-gate * so I don't have to. 14017c478bd9Sstevel@tonic-gate */ 14027c478bd9Sstevel@tonic-gate if ((tp->tim_flags & DO_PEERNAME) != 0) { 14037c478bd9Sstevel@tonic-gate tp->tim_flags &= ~DO_PEERNAME; 14047c478bd9Sstevel@tonic-gate PI_PROVLOCK(tp->tim_provinfo); 14057c478bd9Sstevel@tonic-gate tp->tim_provinfo->tpi_peername = PI_YES; 14067c478bd9Sstevel@tonic-gate PI_PROVUNLOCK(tp->tim_provinfo); 14077c478bd9Sstevel@tonic-gate } 14087c478bd9Sstevel@tonic-gate 14097c478bd9Sstevel@tonic-gate mutex_enter(&tp->tim_mutex); 14107c478bd9Sstevel@tonic-gate ASSERT(tp->tim_peermaxlen >= 0); 14117c478bd9Sstevel@tonic-gate clearit = tp->tim_peermaxlen != 0; 14127c478bd9Sstevel@tonic-gate if (clearit) { 14137c478bd9Sstevel@tonic-gate kmem_free(tp->tim_peername, tp->tim_peermaxlen); 14147c478bd9Sstevel@tonic-gate tp->tim_peername = NULL; 14157c478bd9Sstevel@tonic-gate tp->tim_peermaxlen = 0; 14167c478bd9Sstevel@tonic-gate tp->tim_peerlen = 0; 14177c478bd9Sstevel@tonic-gate } 14187c478bd9Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 14197c478bd9Sstevel@tonic-gate if (clearit) { 14207c478bd9Sstevel@tonic-gate mblk_t *bp; 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate bp = tp->tim_consave; 14237c478bd9Sstevel@tonic-gate while (bp != NULL) { 14247c478bd9Sstevel@tonic-gate nbp = bp->b_next; 14257c478bd9Sstevel@tonic-gate bp->b_next = NULL; 14267c478bd9Sstevel@tonic-gate freemsg(bp); 14277c478bd9Sstevel@tonic-gate bp = nbp; 14287c478bd9Sstevel@tonic-gate } 14297c478bd9Sstevel@tonic-gate tp->tim_consave = NULL; 14307c478bd9Sstevel@tonic-gate } 14317c478bd9Sstevel@tonic-gate /* tim_iocsave may already be overwritten. */ 14327c478bd9Sstevel@tonic-gate if (tp->tim_saved_prim == -1) { 14337c478bd9Sstevel@tonic-gate freemsg(tp->tim_iocsave); 14347c478bd9Sstevel@tonic-gate tp->tim_iocsave = NULL; 14357c478bd9Sstevel@tonic-gate } 14367c478bd9Sstevel@tonic-gate } 14377c478bd9Sstevel@tonic-gate putnext(q, mp); 14387c478bd9Sstevel@tonic-gate break; 14397c478bd9Sstevel@tonic-gate 14407c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 14417c478bd9Sstevel@tonic-gate case M_IOCNAK: 14427c478bd9Sstevel@tonic-gate 14437c478bd9Sstevel@tonic-gate tilog("timodrproc: Got M_IOCNAK\n", 0); 14447c478bd9Sstevel@tonic-gate 14457c478bd9Sstevel@tonic-gate iocbp = (struct iocblk *)mp->b_rptr; 14467c478bd9Sstevel@tonic-gate if (((iocbp->ioc_cmd == TI_GETMYNAME) || 14477c478bd9Sstevel@tonic-gate (iocbp->ioc_cmd == TI_GETPEERNAME)) && 14487c478bd9Sstevel@tonic-gate ((iocbp->ioc_error == EINVAL) || (iocbp->ioc_error == 0))) { 14497c478bd9Sstevel@tonic-gate PI_PROVLOCK(tp->tim_provinfo); 14507c478bd9Sstevel@tonic-gate if (iocbp->ioc_cmd == TI_GETMYNAME) { 14517c478bd9Sstevel@tonic-gate if (tp->tim_provinfo->tpi_myname == PI_DONTKNOW) 14527c478bd9Sstevel@tonic-gate tp->tim_provinfo->tpi_myname = PI_NO; 14537c478bd9Sstevel@tonic-gate } else if (iocbp->ioc_cmd == TI_GETPEERNAME) { 14547c478bd9Sstevel@tonic-gate if (tp->tim_provinfo->tpi_peername == PI_DONTKNOW) 14557c478bd9Sstevel@tonic-gate tp->tim_provinfo->tpi_peername = PI_NO; 14567c478bd9Sstevel@tonic-gate } 14577c478bd9Sstevel@tonic-gate PI_PROVUNLOCK(tp->tim_provinfo); 14587c478bd9Sstevel@tonic-gate /* tim_iocsave may already be overwritten. */ 14597c478bd9Sstevel@tonic-gate if ((tp->tim_iocsave != NULL) && 14607c478bd9Sstevel@tonic-gate (tp->tim_saved_prim == -1)) { 14617c478bd9Sstevel@tonic-gate freemsg(mp); 14627c478bd9Sstevel@tonic-gate mp = tp->tim_iocsave; 14637c478bd9Sstevel@tonic-gate tp->tim_iocsave = NULL; 14647c478bd9Sstevel@tonic-gate tp->tim_flags |= NAMEPROC; 14657c478bd9Sstevel@tonic-gate if (ti_doname(WR(q), mp) != DONAME_CONT) { 14667c478bd9Sstevel@tonic-gate tp->tim_flags &= ~NAMEPROC; 14677c478bd9Sstevel@tonic-gate } 14687c478bd9Sstevel@tonic-gate break; 14697c478bd9Sstevel@tonic-gate } 14707c478bd9Sstevel@tonic-gate } 14717c478bd9Sstevel@tonic-gate putnext(q, mp); 14727c478bd9Sstevel@tonic-gate break; 14737c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 14747c478bd9Sstevel@tonic-gate } 14757c478bd9Sstevel@tonic-gate 14767c478bd9Sstevel@tonic-gate return (0); 14777c478bd9Sstevel@tonic-gate } 14787c478bd9Sstevel@tonic-gate 14797c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 14807c478bd9Sstevel@tonic-gate /* 14817c478bd9Sstevel@tonic-gate * timodwput - Module write put procedure. This is called from 14827c478bd9Sstevel@tonic-gate * the module, driver, or stream head upstream/downstream. 14837c478bd9Sstevel@tonic-gate * Handles M_FLUSH, M_DATA and some M_PROTO (T_DATA_REQ, 14847c478bd9Sstevel@tonic-gate * and T_UNITDATA_REQ) messages. All others are queued to 14857c478bd9Sstevel@tonic-gate * be handled by the service procedures. 14867c478bd9Sstevel@tonic-gate */ 14877c478bd9Sstevel@tonic-gate 14887c478bd9Sstevel@tonic-gate static void 14897c478bd9Sstevel@tonic-gate timodwput(queue_t *q, mblk_t *mp) 14907c478bd9Sstevel@tonic-gate { 14917c478bd9Sstevel@tonic-gate union T_primitives *pptr; 14927c478bd9Sstevel@tonic-gate struct tim_tim *tp; 14937c478bd9Sstevel@tonic-gate struct iocblk *iocbp; 14947c478bd9Sstevel@tonic-gate 14957c478bd9Sstevel@tonic-gate /* 14967c478bd9Sstevel@tonic-gate * Enqueue normal-priority messages if our queue already 14977c478bd9Sstevel@tonic-gate * holds some messages for deferred processing but don't 14987c478bd9Sstevel@tonic-gate * enqueue those M_IOCTLs which will result in an 14997c478bd9Sstevel@tonic-gate * M_PCPROTO (ie, high priority) message being created. 15007c478bd9Sstevel@tonic-gate */ 15017c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 15027c478bd9Sstevel@tonic-gate if (q->q_first != 0 && mp->b_datap->db_type < QPCTL) { 15037c478bd9Sstevel@tonic-gate if (mp->b_datap->db_type == M_IOCTL) { 15047c478bd9Sstevel@tonic-gate iocbp = (struct iocblk *)mp->b_rptr; 15057c478bd9Sstevel@tonic-gate switch (iocbp->ioc_cmd) { 15067c478bd9Sstevel@tonic-gate default: 15077c478bd9Sstevel@tonic-gate (void) putq(q, mp); 15087c478bd9Sstevel@tonic-gate return; 15097c478bd9Sstevel@tonic-gate 15107c478bd9Sstevel@tonic-gate case TI_GETINFO: 15117c478bd9Sstevel@tonic-gate case TI_SYNC: 15127c478bd9Sstevel@tonic-gate case TI_CAPABILITY: 15137c478bd9Sstevel@tonic-gate break; 15147c478bd9Sstevel@tonic-gate } 15157c478bd9Sstevel@tonic-gate } else { 15167c478bd9Sstevel@tonic-gate (void) putq(q, mp); 15177c478bd9Sstevel@tonic-gate return; 15187c478bd9Sstevel@tonic-gate } 15197c478bd9Sstevel@tonic-gate } 15207c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 15217c478bd9Sstevel@tonic-gate /* 15227c478bd9Sstevel@tonic-gate * Inline processing of data (to avoid additional procedure call). 15237c478bd9Sstevel@tonic-gate * Rest is handled in timodwproc. 15247c478bd9Sstevel@tonic-gate */ 15257c478bd9Sstevel@tonic-gate 15267c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 15277c478bd9Sstevel@tonic-gate case M_DATA: 15287c478bd9Sstevel@tonic-gate tp = (struct tim_tim *)q->q_ptr; 15297c478bd9Sstevel@tonic-gate ASSERT(tp); 15307c478bd9Sstevel@tonic-gate if (tp->tim_flags & CLTS) { 15317c478bd9Sstevel@tonic-gate mblk_t *tmp; 15327c478bd9Sstevel@tonic-gate 15337c478bd9Sstevel@tonic-gate if ((tmp = tim_filladdr(q, mp, B_FALSE)) == NULL) { 15347c478bd9Sstevel@tonic-gate (void) putq(q, mp); 15357c478bd9Sstevel@tonic-gate break; 15367c478bd9Sstevel@tonic-gate } else { 15377c478bd9Sstevel@tonic-gate mp = tmp; 15387c478bd9Sstevel@tonic-gate } 15397c478bd9Sstevel@tonic-gate } 15407c478bd9Sstevel@tonic-gate if (bcanputnext(q, mp->b_band)) 15417c478bd9Sstevel@tonic-gate putnext(q, mp); 15427c478bd9Sstevel@tonic-gate else 15437c478bd9Sstevel@tonic-gate (void) putq(q, mp); 15447c478bd9Sstevel@tonic-gate break; 15457c478bd9Sstevel@tonic-gate case M_PROTO: 15467c478bd9Sstevel@tonic-gate case M_PCPROTO: 15477c478bd9Sstevel@tonic-gate pptr = (union T_primitives *)mp->b_rptr; 15487c478bd9Sstevel@tonic-gate switch (pptr->type) { 15497c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 15507c478bd9Sstevel@tonic-gate case T_UNITDATA_REQ: 15517c478bd9Sstevel@tonic-gate tp = (struct tim_tim *)q->q_ptr; 15527c478bd9Sstevel@tonic-gate ASSERT(tp); 15537c478bd9Sstevel@tonic-gate if (tp->tim_flags & CLTS) { 15547c478bd9Sstevel@tonic-gate mblk_t *tmp; 15557c478bd9Sstevel@tonic-gate 15567c478bd9Sstevel@tonic-gate tmp = tim_filladdr(q, mp, B_FALSE); 15577c478bd9Sstevel@tonic-gate if (tmp == NULL) { 15587c478bd9Sstevel@tonic-gate (void) putq(q, mp); 15597c478bd9Sstevel@tonic-gate break; 15607c478bd9Sstevel@tonic-gate } else { 15617c478bd9Sstevel@tonic-gate mp = tmp; 15627c478bd9Sstevel@tonic-gate } 15637c478bd9Sstevel@tonic-gate } 15647c478bd9Sstevel@tonic-gate if (bcanputnext(q, mp->b_band)) 15657c478bd9Sstevel@tonic-gate putnext(q, mp); 15667c478bd9Sstevel@tonic-gate else 15677c478bd9Sstevel@tonic-gate (void) putq(q, mp); 15687c478bd9Sstevel@tonic-gate break; 15697c478bd9Sstevel@tonic-gate 15707c478bd9Sstevel@tonic-gate case T_DATA_REQ: 15717c478bd9Sstevel@tonic-gate case T_EXDATA_REQ: 15727c478bd9Sstevel@tonic-gate if (bcanputnext(q, mp->b_band)) 15737c478bd9Sstevel@tonic-gate putnext(q, mp); 15747c478bd9Sstevel@tonic-gate else 15757c478bd9Sstevel@tonic-gate (void) putq(q, mp); 15767c478bd9Sstevel@tonic-gate break; 15777c478bd9Sstevel@tonic-gate default: 15787c478bd9Sstevel@tonic-gate (void) timodwproc(q, mp); 15797c478bd9Sstevel@tonic-gate break; 15807c478bd9Sstevel@tonic-gate } 15817c478bd9Sstevel@tonic-gate break; 15827c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 15837c478bd9Sstevel@tonic-gate default: 15847c478bd9Sstevel@tonic-gate (void) timodwproc(q, mp); 15857c478bd9Sstevel@tonic-gate break; 15867c478bd9Sstevel@tonic-gate } 15877c478bd9Sstevel@tonic-gate } 15887c478bd9Sstevel@tonic-gate /* 15897c478bd9Sstevel@tonic-gate * timodwsrv - Module write queue service procedure. 15907c478bd9Sstevel@tonic-gate * This is called when messages are placed on an empty queue, 15917c478bd9Sstevel@tonic-gate * when high priority messages are placed on the queue, and 15927c478bd9Sstevel@tonic-gate * when flow control restrictions subside. This code used to 15937c478bd9Sstevel@tonic-gate * be included in a put procedure, but it was moved to a 15947c478bd9Sstevel@tonic-gate * service procedure because several points were added where 15957c478bd9Sstevel@tonic-gate * memory allocation could fail, and there is no reasonable 15967c478bd9Sstevel@tonic-gate * recovery mechanism from the put procedure. 15977c478bd9Sstevel@tonic-gate */ 15987c478bd9Sstevel@tonic-gate static void 15997c478bd9Sstevel@tonic-gate timodwsrv(queue_t *q) 16007c478bd9Sstevel@tonic-gate { 16017c478bd9Sstevel@tonic-gate mblk_t *mp; 16027c478bd9Sstevel@tonic-gate 16037c478bd9Sstevel@tonic-gate ASSERT(q != NULL); 16047c478bd9Sstevel@tonic-gate if (q->q_ptr == NULL) 16057c478bd9Sstevel@tonic-gate return; 16067c478bd9Sstevel@tonic-gate 16077c478bd9Sstevel@tonic-gate while ((mp = getq(q)) != NULL) { 16087c478bd9Sstevel@tonic-gate if (timodwproc(q, mp)) { 16097c478bd9Sstevel@tonic-gate /* 16107c478bd9Sstevel@tonic-gate * timodwproc did a putbq - stop processing 16117c478bd9Sstevel@tonic-gate * messages. 16127c478bd9Sstevel@tonic-gate */ 16137c478bd9Sstevel@tonic-gate return; 16147c478bd9Sstevel@tonic-gate } 16157c478bd9Sstevel@tonic-gate } 16167c478bd9Sstevel@tonic-gate } 16177c478bd9Sstevel@tonic-gate 16187c478bd9Sstevel@tonic-gate /* 16197c478bd9Sstevel@tonic-gate * Common routine to process write side messages 16207c478bd9Sstevel@tonic-gate */ 16217c478bd9Sstevel@tonic-gate 16227c478bd9Sstevel@tonic-gate static int 16237c478bd9Sstevel@tonic-gate timodwproc(queue_t *q, mblk_t *mp) 16247c478bd9Sstevel@tonic-gate { 16257c478bd9Sstevel@tonic-gate union T_primitives *pptr; 16267c478bd9Sstevel@tonic-gate struct tim_tim *tp; 16277c478bd9Sstevel@tonic-gate mblk_t *tmp; 16287c478bd9Sstevel@tonic-gate struct iocblk *iocbp; 16297c478bd9Sstevel@tonic-gate int error; 16307c478bd9Sstevel@tonic-gate 16317c478bd9Sstevel@tonic-gate tp = (struct tim_tim *)q->q_ptr; 16327c478bd9Sstevel@tonic-gate 16337c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 16347c478bd9Sstevel@tonic-gate default: 16357c478bd9Sstevel@tonic-gate putnext(q, mp); 16367c478bd9Sstevel@tonic-gate break; 16377c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 16387c478bd9Sstevel@tonic-gate 16397c478bd9Sstevel@tonic-gate case M_DATA: 16407c478bd9Sstevel@tonic-gate if (tp->tim_flags & CLTS) { 16417c478bd9Sstevel@tonic-gate if ((tmp = tim_filladdr(q, mp, B_TRUE)) == NULL) { 16427c478bd9Sstevel@tonic-gate return (1); 16437c478bd9Sstevel@tonic-gate } else { 16447c478bd9Sstevel@tonic-gate mp = tmp; 16457c478bd9Sstevel@tonic-gate } 16467c478bd9Sstevel@tonic-gate } 16477c478bd9Sstevel@tonic-gate if (!bcanputnext(q, mp->b_band)) { 16487c478bd9Sstevel@tonic-gate (void) putbq(q, mp); 16497c478bd9Sstevel@tonic-gate return (1); 16507c478bd9Sstevel@tonic-gate } 16517c478bd9Sstevel@tonic-gate putnext(q, mp); 16527c478bd9Sstevel@tonic-gate break; 16537c478bd9Sstevel@tonic-gate 16547c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 16557c478bd9Sstevel@tonic-gate case M_IOCTL: 16567c478bd9Sstevel@tonic-gate 16577c478bd9Sstevel@tonic-gate iocbp = (struct iocblk *)mp->b_rptr; 16587c478bd9Sstevel@tonic-gate TILOG("timodwproc: Got M_IOCTL(%d)\n", iocbp->ioc_cmd); 16597c478bd9Sstevel@tonic-gate 16607c478bd9Sstevel@tonic-gate ASSERT(MBLKL(mp) == sizeof (struct iocblk)); 16617c478bd9Sstevel@tonic-gate 16627c478bd9Sstevel@tonic-gate /* 16637c478bd9Sstevel@tonic-gate * TPI requires we await response to a previously sent message 1664*2cbe889aSgeorges * before handling another, put it back on the head of queue. 1665*2cbe889aSgeorges * Since putbq() may see QWANTR unset when called from the 1666*2cbe889aSgeorges * service procedure, the queue must be explicitly scheduled 1667*2cbe889aSgeorges * for service, as no backenable will occur for this case. 1668*2cbe889aSgeorges * tim_ioctl_retry() sets a timer to handle the qenable. 16697c478bd9Sstevel@tonic-gate */ 16707c478bd9Sstevel@tonic-gate if (tp->tim_flags & WAITIOCACK) { 16717c478bd9Sstevel@tonic-gate TILOG("timodwproc: putbq M_IOCTL(%d)\n", 16727c478bd9Sstevel@tonic-gate iocbp->ioc_cmd); 16737c478bd9Sstevel@tonic-gate (void) putbq(q, mp); 1674*2cbe889aSgeorges /* Called from timodwsrv() and messages on queue */ 1675*2cbe889aSgeorges if (!(q->q_flag & QWANTR)) 1676*2cbe889aSgeorges tim_ioctl_retry(q); 16777c478bd9Sstevel@tonic-gate return (1); 16787c478bd9Sstevel@tonic-gate } 16797c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 16807c478bd9Sstevel@tonic-gate 16817c478bd9Sstevel@tonic-gate switch (iocbp->ioc_cmd) { 16827c478bd9Sstevel@tonic-gate default: 16837c478bd9Sstevel@tonic-gate putnext(q, mp); 16847c478bd9Sstevel@tonic-gate break; 16857c478bd9Sstevel@tonic-gate 16867c478bd9Sstevel@tonic-gate case _I_GETPEERCRED: 16877c478bd9Sstevel@tonic-gate if ((tp->tim_flags & COTS) == 0) { 16887c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, ENOTSUP); 16897c478bd9Sstevel@tonic-gate } else { 16907c478bd9Sstevel@tonic-gate mblk_t *cmp = mp->b_cont; 16917c478bd9Sstevel@tonic-gate k_peercred_t *kp = NULL; 16927c478bd9Sstevel@tonic-gate 16937c478bd9Sstevel@tonic-gate mutex_enter(&tp->tim_mutex); 16947c478bd9Sstevel@tonic-gate if (cmp != NULL && 16957c478bd9Sstevel@tonic-gate iocbp->ioc_flag == IOC_NATIVE && 16967c478bd9Sstevel@tonic-gate (tp->tim_flags & 16977c478bd9Sstevel@tonic-gate (CONNWAIT|LOCORDREL|REMORDREL)) == 0 && 16987c478bd9Sstevel@tonic-gate tp->tim_peercred != NULL && 16997c478bd9Sstevel@tonic-gate DB_TYPE(cmp) == M_DATA && 17007c478bd9Sstevel@tonic-gate MBLKL(cmp) == sizeof (k_peercred_t)) { 17017c478bd9Sstevel@tonic-gate kp = (k_peercred_t *)cmp->b_rptr; 17027c478bd9Sstevel@tonic-gate crhold(kp->pc_cr = tp->tim_peercred); 17037c478bd9Sstevel@tonic-gate kp->pc_cpid = tp->tim_cpid; 17047c478bd9Sstevel@tonic-gate } 17057c478bd9Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 17067c478bd9Sstevel@tonic-gate if (kp != NULL) 17077c478bd9Sstevel@tonic-gate miocack(q, mp, sizeof (*kp), 0); 17087c478bd9Sstevel@tonic-gate else 17097c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, ENOTCONN); 17107c478bd9Sstevel@tonic-gate } 17117c478bd9Sstevel@tonic-gate break; 17127c478bd9Sstevel@tonic-gate case TI_BIND: 17137c478bd9Sstevel@tonic-gate case TI_UNBIND: 17147c478bd9Sstevel@tonic-gate case TI_OPTMGMT: 17157c478bd9Sstevel@tonic-gate case TI_GETADDRS: 17167c478bd9Sstevel@tonic-gate TILOG("timodwproc: TI_{BIND|UNBIND|OPTMGMT|GETADDRS}" 17177c478bd9Sstevel@tonic-gate "\n", 0); 17187c478bd9Sstevel@tonic-gate 17197c478bd9Sstevel@tonic-gate /* 17207c478bd9Sstevel@tonic-gate * We know that tim_send_ioctl_tpi_msg() is only 17217c478bd9Sstevel@tonic-gate * going to examine the `type' field, so we only 17227c478bd9Sstevel@tonic-gate * check that we can access that much data. 17237c478bd9Sstevel@tonic-gate */ 17247c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (t_scalar_t)); 17257c478bd9Sstevel@tonic-gate if (error != 0) { 17267c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error); 17277c478bd9Sstevel@tonic-gate break; 17287c478bd9Sstevel@tonic-gate } 17297c478bd9Sstevel@tonic-gate tim_send_ioctl_tpi_msg(q, mp, tp, iocbp); 17307c478bd9Sstevel@tonic-gate break; 17317c478bd9Sstevel@tonic-gate 17327c478bd9Sstevel@tonic-gate case TI_GETINFO: 17337c478bd9Sstevel@tonic-gate TILOG("timodwproc: TI_GETINFO\n", 0); 17347c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (struct T_info_req)); 17357c478bd9Sstevel@tonic-gate if (error != 0) { 17367c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error); 17377c478bd9Sstevel@tonic-gate break; 17387c478bd9Sstevel@tonic-gate } 17397c478bd9Sstevel@tonic-gate tp->tim_flags |= WAIT_IOCINFOACK; 17407c478bd9Sstevel@tonic-gate tim_send_ioctl_tpi_msg(q, mp, tp, iocbp); 17417c478bd9Sstevel@tonic-gate break; 17427c478bd9Sstevel@tonic-gate 17437c478bd9Sstevel@tonic-gate case TI_SYNC: { 17447c478bd9Sstevel@tonic-gate mblk_t *tsr_mp; 17457c478bd9Sstevel@tonic-gate struct ti_sync_req *tsr; 17467c478bd9Sstevel@tonic-gate uint32_t tsr_flags; 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (struct ti_sync_req)); 17497c478bd9Sstevel@tonic-gate if (error != 0) { 17507c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error); 17517c478bd9Sstevel@tonic-gate break; 17527c478bd9Sstevel@tonic-gate } 17537c478bd9Sstevel@tonic-gate 17547c478bd9Sstevel@tonic-gate tsr_mp = mp->b_cont; 17557c478bd9Sstevel@tonic-gate tsr = (struct ti_sync_req *)tsr_mp->b_rptr; 17567c478bd9Sstevel@tonic-gate TILOG("timodwproc: TI_SYNC(%x)\n", tsr->tsr_flags); 17577c478bd9Sstevel@tonic-gate 17587c478bd9Sstevel@tonic-gate /* 17597c478bd9Sstevel@tonic-gate * Save out the value of tsr_flags, in case we 17607c478bd9Sstevel@tonic-gate * reallocb() tsr_mp (below). 17617c478bd9Sstevel@tonic-gate */ 17627c478bd9Sstevel@tonic-gate tsr_flags = tsr->tsr_flags; 17637c478bd9Sstevel@tonic-gate if ((tsr_flags & TSRF_INFO_REQ) == 0) { 17647c478bd9Sstevel@tonic-gate mblk_t *ack_mp = reallocb(tsr_mp, 17657c478bd9Sstevel@tonic-gate sizeof (struct ti_sync_ack), 0); 17667c478bd9Sstevel@tonic-gate 17677c478bd9Sstevel@tonic-gate /* Can reply immediately. */ 17687c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 17697c478bd9Sstevel@tonic-gate if (ack_mp == NULL) { 17707c478bd9Sstevel@tonic-gate tilog("timodwproc: allocb failed no " 17717c478bd9Sstevel@tonic-gate "recovery attempt\n", 0); 17727c478bd9Sstevel@tonic-gate freemsg(tsr_mp); 17737c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, ENOMEM); 17747c478bd9Sstevel@tonic-gate } else { 17757c478bd9Sstevel@tonic-gate tim_answer_ti_sync(q, mp, tp, 17767c478bd9Sstevel@tonic-gate ack_mp, tsr_flags); 17777c478bd9Sstevel@tonic-gate } 17787c478bd9Sstevel@tonic-gate break; 17797c478bd9Sstevel@tonic-gate } 17807c478bd9Sstevel@tonic-gate 17817c478bd9Sstevel@tonic-gate /* 17827c478bd9Sstevel@tonic-gate * This code is retained for compatibility with 17837c478bd9Sstevel@tonic-gate * old statically linked applications. New code 17847c478bd9Sstevel@tonic-gate * should use TI_CAPABILITY for all TPI 17857c478bd9Sstevel@tonic-gate * information and should not use TSRF_INFO_REQ 17867c478bd9Sstevel@tonic-gate * flag. 17877c478bd9Sstevel@tonic-gate * 17887c478bd9Sstevel@tonic-gate * defer processsing necessary to rput procedure 17897c478bd9Sstevel@tonic-gate * as we need to get information from transport 17907c478bd9Sstevel@tonic-gate * driver. Set flags that will tell the read 17917c478bd9Sstevel@tonic-gate * side the work needed on this request. 17927c478bd9Sstevel@tonic-gate */ 17937c478bd9Sstevel@tonic-gate 17947c478bd9Sstevel@tonic-gate if (tsr_flags & TSRF_IS_EXP_IN_RCVBUF) 17957c478bd9Sstevel@tonic-gate tp->tim_flags |= PEEK_RDQ_EXPIND; 17967c478bd9Sstevel@tonic-gate 17977c478bd9Sstevel@tonic-gate /* 17987c478bd9Sstevel@tonic-gate * Convert message to a T_INFO_REQ message; relies 17997c478bd9Sstevel@tonic-gate * on sizeof (struct ti_sync_req) >= sizeof (struct 18007c478bd9Sstevel@tonic-gate * T_info_req)). 18017c478bd9Sstevel@tonic-gate */ 18027c478bd9Sstevel@tonic-gate ASSERT(MBLKL(tsr_mp) >= sizeof (struct T_info_req)); 18037c478bd9Sstevel@tonic-gate 18047c478bd9Sstevel@tonic-gate ((struct T_info_req *)tsr_mp->b_rptr)->PRIM_type = 18057c478bd9Sstevel@tonic-gate T_INFO_REQ; 18067c478bd9Sstevel@tonic-gate tsr_mp->b_wptr = tsr_mp->b_rptr + 18077c478bd9Sstevel@tonic-gate sizeof (struct T_info_req); 18087c478bd9Sstevel@tonic-gate tp->tim_flags |= WAIT_IOCINFOACK; 18097c478bd9Sstevel@tonic-gate tim_send_ioctl_tpi_msg(q, mp, tp, iocbp); 18107c478bd9Sstevel@tonic-gate } 18117c478bd9Sstevel@tonic-gate break; 18127c478bd9Sstevel@tonic-gate 18137c478bd9Sstevel@tonic-gate case TI_CAPABILITY: { 18147c478bd9Sstevel@tonic-gate mblk_t *tcsr_mp; 18157c478bd9Sstevel@tonic-gate struct T_capability_req *tcr; 18167c478bd9Sstevel@tonic-gate 18177c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (*tcr)); 18187c478bd9Sstevel@tonic-gate if (error != 0) { 18197c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error); 18207c478bd9Sstevel@tonic-gate break; 18217c478bd9Sstevel@tonic-gate } 18227c478bd9Sstevel@tonic-gate 18237c478bd9Sstevel@tonic-gate tcsr_mp = mp->b_cont; 18247c478bd9Sstevel@tonic-gate tcr = (struct T_capability_req *)tcsr_mp->b_rptr; 18257c478bd9Sstevel@tonic-gate TILOG("timodwproc: TI_CAPABILITY(CAP_bits1 = %x)\n", 18267c478bd9Sstevel@tonic-gate tcr->CAP_bits1); 18277c478bd9Sstevel@tonic-gate 18287c478bd9Sstevel@tonic-gate if (tcr->PRIM_type != T_CAPABILITY_REQ) { 18297c478bd9Sstevel@tonic-gate TILOG("timodwproc: invalid msg type %d\n", 18307c478bd9Sstevel@tonic-gate tcr->PRIM_type); 18317c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EPROTO); 18327c478bd9Sstevel@tonic-gate break; 18337c478bd9Sstevel@tonic-gate } 18347c478bd9Sstevel@tonic-gate 18357c478bd9Sstevel@tonic-gate switch (tp->tim_provinfo->tpi_capability) { 18367c478bd9Sstevel@tonic-gate case PI_YES: 18377c478bd9Sstevel@tonic-gate /* Just send T_CAPABILITY_REQ down */ 18387c478bd9Sstevel@tonic-gate tim_send_ioctl_tpi_msg(q, mp, tp, iocbp); 18397c478bd9Sstevel@tonic-gate break; 18407c478bd9Sstevel@tonic-gate 18417c478bd9Sstevel@tonic-gate case PI_DONTKNOW: 18427c478bd9Sstevel@tonic-gate /* 18437c478bd9Sstevel@tonic-gate * It is unknown yet whether transport provides 18447c478bd9Sstevel@tonic-gate * T_CAPABILITY_REQ or not. Send message down 18457c478bd9Sstevel@tonic-gate * and wait for reply. 18467c478bd9Sstevel@tonic-gate */ 18477c478bd9Sstevel@tonic-gate 18487c478bd9Sstevel@tonic-gate ASSERT(tp->tim_tcap_timoutid == 0); 18497c478bd9Sstevel@tonic-gate if ((tcr->CAP_bits1 & TC1_INFO) == 0) { 18507c478bd9Sstevel@tonic-gate tp->tim_flags |= TI_CAP_RECVD; 18517c478bd9Sstevel@tonic-gate } else { 18527c478bd9Sstevel@tonic-gate tp->tim_flags |= (TI_CAP_RECVD | 18537c478bd9Sstevel@tonic-gate CAP_WANTS_INFO); 18547c478bd9Sstevel@tonic-gate } 18557c478bd9Sstevel@tonic-gate 18567c478bd9Sstevel@tonic-gate tp->tim_tcap_timoutid = qtimeout(q, 18577c478bd9Sstevel@tonic-gate tim_tcap_timer, q, tim_tcap_wait * hz); 18587c478bd9Sstevel@tonic-gate tim_send_ioctl_tpi_msg(q, mp, tp, iocbp); 18597c478bd9Sstevel@tonic-gate break; 18607c478bd9Sstevel@tonic-gate 18617c478bd9Sstevel@tonic-gate case PI_NO: 18627c478bd9Sstevel@tonic-gate /* 18637c478bd9Sstevel@tonic-gate * Transport doesn't support T_CAPABILITY_REQ. 18647c478bd9Sstevel@tonic-gate * Either reply immediately or send T_INFO_REQ 18657c478bd9Sstevel@tonic-gate * if needed. 18667c478bd9Sstevel@tonic-gate */ 18677c478bd9Sstevel@tonic-gate if ((tcr->CAP_bits1 & TC1_INFO) != 0) { 18687c478bd9Sstevel@tonic-gate tp->tim_flags |= (TI_CAP_RECVD | 18697c478bd9Sstevel@tonic-gate CAP_WANTS_INFO | WAIT_IOCINFOACK); 18707c478bd9Sstevel@tonic-gate TILOG("timodwproc: sending down " 18717c478bd9Sstevel@tonic-gate "T_INFO_REQ, flags = %x\n", 18727c478bd9Sstevel@tonic-gate tp->tim_flags); 18737c478bd9Sstevel@tonic-gate 18747c478bd9Sstevel@tonic-gate /* 18757c478bd9Sstevel@tonic-gate * Generate T_INFO_REQ message and send 18767c478bd9Sstevel@tonic-gate * it down 18777c478bd9Sstevel@tonic-gate */ 18787c478bd9Sstevel@tonic-gate ((struct T_info_req *)tcsr_mp->b_rptr)-> 18797c478bd9Sstevel@tonic-gate PRIM_type = T_INFO_REQ; 18807c478bd9Sstevel@tonic-gate tcsr_mp->b_wptr = tcsr_mp->b_rptr + 18817c478bd9Sstevel@tonic-gate sizeof (struct T_info_req); 18827c478bd9Sstevel@tonic-gate tim_send_ioctl_tpi_msg(q, mp, tp, 18837c478bd9Sstevel@tonic-gate iocbp); 18847c478bd9Sstevel@tonic-gate break; 18857c478bd9Sstevel@tonic-gate } 18867c478bd9Sstevel@tonic-gate 18877c478bd9Sstevel@tonic-gate 18887c478bd9Sstevel@tonic-gate /* 18897c478bd9Sstevel@tonic-gate * Can reply immediately. Just send back 18907c478bd9Sstevel@tonic-gate * T_CAPABILITY_ACK with CAP_bits1 set to 0. 18917c478bd9Sstevel@tonic-gate */ 18927c478bd9Sstevel@tonic-gate mp->b_cont = tcsr_mp = tpi_ack_alloc(mp->b_cont, 18937c478bd9Sstevel@tonic-gate sizeof (struct T_capability_ack), M_PCPROTO, 18947c478bd9Sstevel@tonic-gate T_CAPABILITY_ACK); 18957c478bd9Sstevel@tonic-gate 18967c478bd9Sstevel@tonic-gate if (tcsr_mp == NULL) { 18977c478bd9Sstevel@tonic-gate tilog("timodwproc: allocb failed no " 18987c478bd9Sstevel@tonic-gate "recovery attempt\n", 0); 18997c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, ENOMEM); 19007c478bd9Sstevel@tonic-gate break; 19017c478bd9Sstevel@tonic-gate } 19027c478bd9Sstevel@tonic-gate 19037c478bd9Sstevel@tonic-gate tp->tim_flags &= ~(WAITIOCACK | TI_CAP_RECVD | 19047c478bd9Sstevel@tonic-gate WAIT_IOCINFOACK | CAP_WANTS_INFO); 19057c478bd9Sstevel@tonic-gate ((struct T_capability_ack *) 19067c478bd9Sstevel@tonic-gate tcsr_mp->b_rptr)->CAP_bits1 = 0; 19077c478bd9Sstevel@tonic-gate tim_ioctl_send_reply(q, mp, tcsr_mp); 19087c478bd9Sstevel@tonic-gate 19097c478bd9Sstevel@tonic-gate /* 19107c478bd9Sstevel@tonic-gate * It could happen when timod is awaiting ack 19117c478bd9Sstevel@tonic-gate * for TI_GETPEERNAME/TI_GETMYNAME. 19127c478bd9Sstevel@tonic-gate */ 19137c478bd9Sstevel@tonic-gate if (tp->tim_iocsave != NULL) { 19147c478bd9Sstevel@tonic-gate freemsg(tp->tim_iocsave); 19157c478bd9Sstevel@tonic-gate tp->tim_iocsave = NULL; 19167c478bd9Sstevel@tonic-gate tp->tim_saved_prim = -1; 19177c478bd9Sstevel@tonic-gate } 19187c478bd9Sstevel@tonic-gate break; 19197c478bd9Sstevel@tonic-gate 19207c478bd9Sstevel@tonic-gate default: 19217c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, 19227c478bd9Sstevel@tonic-gate "timodwproc: unknown tpi_capability value " 19237c478bd9Sstevel@tonic-gate "%d\n", tp->tim_provinfo->tpi_capability); 19247c478bd9Sstevel@tonic-gate break; 19257c478bd9Sstevel@tonic-gate } 19267c478bd9Sstevel@tonic-gate } 19277c478bd9Sstevel@tonic-gate break; 19287c478bd9Sstevel@tonic-gate 19297c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 19307c478bd9Sstevel@tonic-gate case TI_GETMYNAME: 19317c478bd9Sstevel@tonic-gate 19327c478bd9Sstevel@tonic-gate tilog("timodwproc: Got TI_GETMYNAME\n", 0); 19337c478bd9Sstevel@tonic-gate 19347c478bd9Sstevel@tonic-gate if (tp->tim_provinfo->tpi_myname == PI_YES) { 19357c478bd9Sstevel@tonic-gate putnext(q, mp); 19367c478bd9Sstevel@tonic-gate break; 19377c478bd9Sstevel@tonic-gate } 19387c478bd9Sstevel@tonic-gate goto getname; 19397c478bd9Sstevel@tonic-gate 19407c478bd9Sstevel@tonic-gate case TI_GETPEERNAME: 19417c478bd9Sstevel@tonic-gate 19427c478bd9Sstevel@tonic-gate tilog("timodwproc: Got TI_GETPEERNAME\n", 0); 19437c478bd9Sstevel@tonic-gate 19447c478bd9Sstevel@tonic-gate if (tp->tim_provinfo->tpi_peername == PI_YES) { 19457c478bd9Sstevel@tonic-gate putnext(q, mp); 19467c478bd9Sstevel@tonic-gate break; 19477c478bd9Sstevel@tonic-gate } 19487c478bd9Sstevel@tonic-gate getname: 19497c478bd9Sstevel@tonic-gate if ((tmp = copymsg(mp)) == NULL) { 19507c478bd9Sstevel@tonic-gate tim_recover(q, mp, msgsize(mp)); 19517c478bd9Sstevel@tonic-gate return (1); 19527c478bd9Sstevel@tonic-gate } 19537c478bd9Sstevel@tonic-gate /* 19547c478bd9Sstevel@tonic-gate * tim_iocsave may be non-NULL when timod is awaiting 19557c478bd9Sstevel@tonic-gate * ack for another TI_GETPEERNAME/TI_GETMYNAME. 19567c478bd9Sstevel@tonic-gate */ 19577c478bd9Sstevel@tonic-gate freemsg(tp->tim_iocsave); 19587c478bd9Sstevel@tonic-gate tp->tim_iocsave = mp; 19597c478bd9Sstevel@tonic-gate tp->tim_saved_prim = -1; 19607c478bd9Sstevel@tonic-gate putnext(q, tmp); 19617c478bd9Sstevel@tonic-gate break; 19627c478bd9Sstevel@tonic-gate } 19637c478bd9Sstevel@tonic-gate break; 19647c478bd9Sstevel@tonic-gate 19657c478bd9Sstevel@tonic-gate case M_IOCDATA: 19667c478bd9Sstevel@tonic-gate 19677c478bd9Sstevel@tonic-gate if (tp->tim_flags & NAMEPROC) { 19687c478bd9Sstevel@tonic-gate if (ti_doname(q, mp) != DONAME_CONT) { 19697c478bd9Sstevel@tonic-gate tp->tim_flags &= ~NAMEPROC; 19707c478bd9Sstevel@tonic-gate } 19717c478bd9Sstevel@tonic-gate } else 19727c478bd9Sstevel@tonic-gate putnext(q, mp); 19737c478bd9Sstevel@tonic-gate break; 19747c478bd9Sstevel@tonic-gate 19757c478bd9Sstevel@tonic-gate case M_PROTO: 19767c478bd9Sstevel@tonic-gate case M_PCPROTO: 19777c478bd9Sstevel@tonic-gate if (MBLKL(mp) < sizeof (t_scalar_t)) { 19787c478bd9Sstevel@tonic-gate merror(q, mp, EPROTO); 19797c478bd9Sstevel@tonic-gate return (1); 19807c478bd9Sstevel@tonic-gate } 19817c478bd9Sstevel@tonic-gate 19827c478bd9Sstevel@tonic-gate pptr = (union T_primitives *)mp->b_rptr; 19837c478bd9Sstevel@tonic-gate switch (pptr->type) { 19847c478bd9Sstevel@tonic-gate default: 19857c478bd9Sstevel@tonic-gate putnext(q, mp); 19867c478bd9Sstevel@tonic-gate break; 19877c478bd9Sstevel@tonic-gate 19887c478bd9Sstevel@tonic-gate case T_EXDATA_REQ: 19897c478bd9Sstevel@tonic-gate case T_DATA_REQ: 19907c478bd9Sstevel@tonic-gate if (pptr->type == T_EXDATA_REQ) 19917c478bd9Sstevel@tonic-gate tilog("timodwproc: Got T_EXDATA_REQ\n", 0); 19927c478bd9Sstevel@tonic-gate 19937c478bd9Sstevel@tonic-gate if (!bcanputnext(q, mp->b_band)) { 19947c478bd9Sstevel@tonic-gate (void) putbq(q, mp); 19957c478bd9Sstevel@tonic-gate return (1); 19967c478bd9Sstevel@tonic-gate } 19977c478bd9Sstevel@tonic-gate putnext(q, mp); 19987c478bd9Sstevel@tonic-gate break; 19997c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 20007c478bd9Sstevel@tonic-gate 20017c478bd9Sstevel@tonic-gate case T_UNITDATA_REQ: 20027c478bd9Sstevel@tonic-gate if (tp->tim_flags & CLTS) { 20037c478bd9Sstevel@tonic-gate tmp = tim_filladdr(q, mp, B_TRUE); 20047c478bd9Sstevel@tonic-gate if (tmp == NULL) { 20057c478bd9Sstevel@tonic-gate return (1); 20067c478bd9Sstevel@tonic-gate } else { 20077c478bd9Sstevel@tonic-gate mp = tmp; 20087c478bd9Sstevel@tonic-gate } 20097c478bd9Sstevel@tonic-gate } 20107c478bd9Sstevel@tonic-gate #ifdef C2_AUDIT 20117c478bd9Sstevel@tonic-gate if (audit_active) 20127c478bd9Sstevel@tonic-gate audit_sock(T_UNITDATA_REQ, q, mp, TIMOD_ID); 20137c478bd9Sstevel@tonic-gate #endif 20147c478bd9Sstevel@tonic-gate if (!bcanputnext(q, mp->b_band)) { 20157c478bd9Sstevel@tonic-gate (void) putbq(q, mp); 20167c478bd9Sstevel@tonic-gate return (1); 20177c478bd9Sstevel@tonic-gate } 20187c478bd9Sstevel@tonic-gate putnext(q, mp); 20197c478bd9Sstevel@tonic-gate break; 20207c478bd9Sstevel@tonic-gate 20217c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 20227c478bd9Sstevel@tonic-gate case T_CONN_REQ: { 20237c478bd9Sstevel@tonic-gate struct T_conn_req *reqp = (struct T_conn_req *) 20247c478bd9Sstevel@tonic-gate mp->b_rptr; 20257c478bd9Sstevel@tonic-gate void *p; 20267c478bd9Sstevel@tonic-gate 20277c478bd9Sstevel@tonic-gate tilog("timodwproc: Got T_CONN_REQ\n", 0); 20287c478bd9Sstevel@tonic-gate 20297c478bd9Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct T_conn_req)) { 20307c478bd9Sstevel@tonic-gate merror(q, mp, EPROTO); 20317c478bd9Sstevel@tonic-gate return (1); 20327c478bd9Sstevel@tonic-gate } 20337c478bd9Sstevel@tonic-gate 20347c478bd9Sstevel@tonic-gate if (tp->tim_flags & DO_PEERNAME) { 20357c478bd9Sstevel@tonic-gate if (!MBLKIN(mp, reqp->DEST_offset, 20367c478bd9Sstevel@tonic-gate reqp->DEST_length)) { 20377c478bd9Sstevel@tonic-gate merror(q, mp, EPROTO); 20387c478bd9Sstevel@tonic-gate return (1); 20397c478bd9Sstevel@tonic-gate } 20407c478bd9Sstevel@tonic-gate ASSERT(reqp->DEST_length >= 0); 20417c478bd9Sstevel@tonic-gate mutex_enter(&tp->tim_mutex); 20427c478bd9Sstevel@tonic-gate if (reqp->DEST_length > tp->tim_peermaxlen) { 20437c478bd9Sstevel@tonic-gate p = kmem_alloc(reqp->DEST_length, 20447c478bd9Sstevel@tonic-gate KM_NOSLEEP); 20457c478bd9Sstevel@tonic-gate if (p == NULL) { 20467c478bd9Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 20477c478bd9Sstevel@tonic-gate tilog("timodwproc: kmem_alloc " 20487c478bd9Sstevel@tonic-gate "failed, attempting " 20497c478bd9Sstevel@tonic-gate "recovery\n", 0); 20507c478bd9Sstevel@tonic-gate tim_recover(q, mp, 20517c478bd9Sstevel@tonic-gate reqp->DEST_length); 20527c478bd9Sstevel@tonic-gate return (1); 20537c478bd9Sstevel@tonic-gate } 20547c478bd9Sstevel@tonic-gate if (tp->tim_peermaxlen) 20557c478bd9Sstevel@tonic-gate kmem_free(tp->tim_peername, 20567c478bd9Sstevel@tonic-gate tp->tim_peermaxlen); 20577c478bd9Sstevel@tonic-gate tp->tim_peername = p; 20587c478bd9Sstevel@tonic-gate tp->tim_peermaxlen = reqp->DEST_length; 20597c478bd9Sstevel@tonic-gate } 20607c478bd9Sstevel@tonic-gate tp->tim_peerlen = reqp->DEST_length; 20617c478bd9Sstevel@tonic-gate p = mp->b_rptr + reqp->DEST_offset; 20627c478bd9Sstevel@tonic-gate bcopy(p, tp->tim_peername, tp->tim_peerlen); 20637c478bd9Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 20647c478bd9Sstevel@tonic-gate } 20657c478bd9Sstevel@tonic-gate if (tp->tim_flags & COTS) 20667c478bd9Sstevel@tonic-gate tp->tim_flags |= CONNWAIT; 20677c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 20687c478bd9Sstevel@tonic-gate #ifdef C2_AUDIT 20697c478bd9Sstevel@tonic-gate if (audit_active) 20707c478bd9Sstevel@tonic-gate audit_sock(T_CONN_REQ, q, mp, TIMOD_ID); 20717c478bd9Sstevel@tonic-gate #endif 20727c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 20737c478bd9Sstevel@tonic-gate putnext(q, mp); 20747c478bd9Sstevel@tonic-gate break; 20757c478bd9Sstevel@tonic-gate } 20767c478bd9Sstevel@tonic-gate 20777c478bd9Sstevel@tonic-gate case O_T_CONN_RES: 20787c478bd9Sstevel@tonic-gate case T_CONN_RES: { 20797c478bd9Sstevel@tonic-gate struct T_conn_res *resp; 20807c478bd9Sstevel@tonic-gate struct T_conn_ind *indp; 20817c478bd9Sstevel@tonic-gate mblk_t *pmp = NULL; 20827c478bd9Sstevel@tonic-gate mblk_t *nbp; 20837c478bd9Sstevel@tonic-gate 20847c478bd9Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct T_conn_res) || 20857c478bd9Sstevel@tonic-gate (tp->tim_flags & WAITIOCACK)) { 20867c478bd9Sstevel@tonic-gate merror(q, mp, EPROTO); 20877c478bd9Sstevel@tonic-gate return (1); 20887c478bd9Sstevel@tonic-gate } 20897c478bd9Sstevel@tonic-gate 20907c478bd9Sstevel@tonic-gate resp = (struct T_conn_res *)mp->b_rptr; 20917c478bd9Sstevel@tonic-gate for (tmp = tp->tim_consave; tmp != NULL; 20927c478bd9Sstevel@tonic-gate tmp = tmp->b_next) { 20937c478bd9Sstevel@tonic-gate indp = (struct T_conn_ind *)tmp->b_rptr; 20947c478bd9Sstevel@tonic-gate if (indp->SEQ_number == resp->SEQ_number) 20957c478bd9Sstevel@tonic-gate break; 20967c478bd9Sstevel@tonic-gate pmp = tmp; 20977c478bd9Sstevel@tonic-gate } 20987c478bd9Sstevel@tonic-gate if (tmp == NULL) 20997c478bd9Sstevel@tonic-gate goto cresout; 21007c478bd9Sstevel@tonic-gate 21017c478bd9Sstevel@tonic-gate if ((nbp = dupb(mp)) == NULL && 21027c478bd9Sstevel@tonic-gate (nbp = copyb(mp)) == NULL) { 21037c478bd9Sstevel@tonic-gate tim_recover(q, mp, msgsize(mp)); 21047c478bd9Sstevel@tonic-gate return (1); 21057c478bd9Sstevel@tonic-gate } 21067c478bd9Sstevel@tonic-gate 21077c478bd9Sstevel@tonic-gate if (pmp != NULL) 21087c478bd9Sstevel@tonic-gate pmp->b_next = tmp->b_next; 21097c478bd9Sstevel@tonic-gate else 21107c478bd9Sstevel@tonic-gate tp->tim_consave = tmp->b_next; 21117c478bd9Sstevel@tonic-gate tmp->b_next = NULL; 21127c478bd9Sstevel@tonic-gate 21137c478bd9Sstevel@tonic-gate /* 21147c478bd9Sstevel@tonic-gate * Construct a list with: 21157c478bd9Sstevel@tonic-gate * nbp - copy of user's original request 21167c478bd9Sstevel@tonic-gate * tmp - the extracted T_conn_ind 21177c478bd9Sstevel@tonic-gate */ 21187c478bd9Sstevel@tonic-gate nbp->b_cont = tmp; 21197c478bd9Sstevel@tonic-gate /* 21207c478bd9Sstevel@tonic-gate * tim_iocsave may be non-NULL when timod is awaiting 21217c478bd9Sstevel@tonic-gate * ack for TI_GETPEERNAME/TI_GETMYNAME. 21227c478bd9Sstevel@tonic-gate */ 21237c478bd9Sstevel@tonic-gate freemsg(tp->tim_iocsave); 21247c478bd9Sstevel@tonic-gate tp->tim_iocsave = nbp; 21257c478bd9Sstevel@tonic-gate tp->tim_saved_prim = pptr->type; 21267c478bd9Sstevel@tonic-gate tp->tim_flags |= WAIT_CONNRESACK | WAITIOCACK; 21277c478bd9Sstevel@tonic-gate 21287c478bd9Sstevel@tonic-gate cresout: 21297c478bd9Sstevel@tonic-gate putnext(q, mp); 21307c478bd9Sstevel@tonic-gate break; 21317c478bd9Sstevel@tonic-gate } 21327c478bd9Sstevel@tonic-gate 21337c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 21347c478bd9Sstevel@tonic-gate case T_DISCON_REQ: { 21357c478bd9Sstevel@tonic-gate struct T_discon_req *disp; 21367c478bd9Sstevel@tonic-gate struct T_conn_ind *conp; 21377c478bd9Sstevel@tonic-gate mblk_t *pmp = NULL; 21387c478bd9Sstevel@tonic-gate 21397c478bd9Sstevel@tonic-gate if (MBLKL(mp) < sizeof (struct T_discon_req)) { 21407c478bd9Sstevel@tonic-gate merror(q, mp, EPROTO); 21417c478bd9Sstevel@tonic-gate return (1); 21427c478bd9Sstevel@tonic-gate } 21437c478bd9Sstevel@tonic-gate 21447c478bd9Sstevel@tonic-gate disp = (struct T_discon_req *)mp->b_rptr; 21457c478bd9Sstevel@tonic-gate tp->tim_flags &= ~(CONNWAIT|LOCORDREL|REMORDREL); 21467c478bd9Sstevel@tonic-gate tim_clear_peer(tp); 21477c478bd9Sstevel@tonic-gate 21487c478bd9Sstevel@tonic-gate /* 21497c478bd9Sstevel@tonic-gate * If we are already connected, there won't 21507c478bd9Sstevel@tonic-gate * be any messages on tim_consave. 21517c478bd9Sstevel@tonic-gate */ 21527c478bd9Sstevel@tonic-gate for (tmp = tp->tim_consave; tmp; tmp = tmp->b_next) { 21537c478bd9Sstevel@tonic-gate conp = (struct T_conn_ind *)tmp->b_rptr; 21547c478bd9Sstevel@tonic-gate if (conp->SEQ_number == disp->SEQ_number) 21557c478bd9Sstevel@tonic-gate break; 21567c478bd9Sstevel@tonic-gate pmp = tmp; 21577c478bd9Sstevel@tonic-gate } 21587c478bd9Sstevel@tonic-gate if (tmp) { 21597c478bd9Sstevel@tonic-gate if (pmp) 21607c478bd9Sstevel@tonic-gate pmp->b_next = tmp->b_next; 21617c478bd9Sstevel@tonic-gate else 21627c478bd9Sstevel@tonic-gate tp->tim_consave = tmp->b_next; 21637c478bd9Sstevel@tonic-gate tmp->b_next = NULL; 21647c478bd9Sstevel@tonic-gate freemsg(tmp); 21657c478bd9Sstevel@tonic-gate } 21667c478bd9Sstevel@tonic-gate putnext(q, mp); 21677c478bd9Sstevel@tonic-gate break; 21687c478bd9Sstevel@tonic-gate } 21697c478bd9Sstevel@tonic-gate 21707c478bd9Sstevel@tonic-gate case T_ORDREL_REQ: 21717c478bd9Sstevel@tonic-gate if (tp->tim_flags & REMORDREL) { 21727c478bd9Sstevel@tonic-gate tp->tim_flags &= ~(LOCORDREL|REMORDREL); 21737c478bd9Sstevel@tonic-gate tim_clear_peer(tp); 21747c478bd9Sstevel@tonic-gate } else { 21757c478bd9Sstevel@tonic-gate tp->tim_flags |= LOCORDREL; 21767c478bd9Sstevel@tonic-gate } 21777c478bd9Sstevel@tonic-gate putnext(q, mp); 21787c478bd9Sstevel@tonic-gate break; 21797c478bd9Sstevel@tonic-gate 21807c478bd9Sstevel@tonic-gate case T_CAPABILITY_REQ: 21817c478bd9Sstevel@tonic-gate tilog("timodwproc: Got T_CAPABILITY_REQ\n", 0); 21827c478bd9Sstevel@tonic-gate /* 21837c478bd9Sstevel@tonic-gate * XXX: We may know at this point whether transport 21847c478bd9Sstevel@tonic-gate * provides T_CAPABILITY_REQ or not and we may utilise 21857c478bd9Sstevel@tonic-gate * this knowledge here. 21867c478bd9Sstevel@tonic-gate */ 21877c478bd9Sstevel@tonic-gate putnext(q, mp); 21887c478bd9Sstevel@tonic-gate break; 21897c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 21907c478bd9Sstevel@tonic-gate } 21917c478bd9Sstevel@tonic-gate break; 21927c478bd9Sstevel@tonic-gate case M_FLUSH: 21937c478bd9Sstevel@tonic-gate 21947c478bd9Sstevel@tonic-gate tilog("timodwproc: Got M_FLUSH\n", 0); 21957c478bd9Sstevel@tonic-gate 21967c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) { 21977c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHBAND) 21987c478bd9Sstevel@tonic-gate flushband(q, *(mp->b_rptr + 1), FLUSHDATA); 21997c478bd9Sstevel@tonic-gate else 22007c478bd9Sstevel@tonic-gate flushq(q, FLUSHDATA); 22017c478bd9Sstevel@tonic-gate } 22027c478bd9Sstevel@tonic-gate putnext(q, mp); 22037c478bd9Sstevel@tonic-gate break; 22047c478bd9Sstevel@tonic-gate } 22057c478bd9Sstevel@tonic-gate 22067c478bd9Sstevel@tonic-gate return (0); 22077c478bd9Sstevel@tonic-gate } 22087c478bd9Sstevel@tonic-gate 22097c478bd9Sstevel@tonic-gate static void 22107c478bd9Sstevel@tonic-gate tilog(char *str, t_scalar_t arg) 22117c478bd9Sstevel@tonic-gate { 22127c478bd9Sstevel@tonic-gate if (dotilog) { 22137c478bd9Sstevel@tonic-gate if (dotilog & 2) 22147c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, str, arg); 22157c478bd9Sstevel@tonic-gate if (dotilog & 4) 22167c478bd9Sstevel@tonic-gate (void) strlog(TIMOD_ID, -1, 0, SL_TRACE | SL_ERROR, 22177c478bd9Sstevel@tonic-gate str, arg); 22187c478bd9Sstevel@tonic-gate else 22197c478bd9Sstevel@tonic-gate (void) strlog(TIMOD_ID, -1, 0, SL_TRACE, str, arg); 22207c478bd9Sstevel@tonic-gate } 22217c478bd9Sstevel@tonic-gate } 22227c478bd9Sstevel@tonic-gate 22237c478bd9Sstevel@tonic-gate static void 22247c478bd9Sstevel@tonic-gate tilogp(char *str, uintptr_t arg) 22257c478bd9Sstevel@tonic-gate { 22267c478bd9Sstevel@tonic-gate if (dotilog) { 22277c478bd9Sstevel@tonic-gate if (dotilog & 2) 22287c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, str, arg); 22297c478bd9Sstevel@tonic-gate if (dotilog & 4) 22307c478bd9Sstevel@tonic-gate (void) strlog(TIMOD_ID, -1, 0, SL_TRACE | SL_ERROR, 22317c478bd9Sstevel@tonic-gate str, arg); 22327c478bd9Sstevel@tonic-gate else 22337c478bd9Sstevel@tonic-gate (void) strlog(TIMOD_ID, -1, 0, SL_TRACE, str, arg); 22347c478bd9Sstevel@tonic-gate } 22357c478bd9Sstevel@tonic-gate } 22367c478bd9Sstevel@tonic-gate 22377c478bd9Sstevel@tonic-gate 22387c478bd9Sstevel@tonic-gate /* 22397c478bd9Sstevel@tonic-gate * Process the TI_GETNAME ioctl. If no name exists, return len = 0 22407c478bd9Sstevel@tonic-gate * in strbuf structures. The state transitions are determined by what 22417c478bd9Sstevel@tonic-gate * is hung of cq_private (cp_private) in the copyresp (copyreq) structure. 22427c478bd9Sstevel@tonic-gate * The high-level steps in the ioctl processing are as follows: 22437c478bd9Sstevel@tonic-gate * 22447c478bd9Sstevel@tonic-gate * 1) we recieve an transparent M_IOCTL with the arg in the second message 22457c478bd9Sstevel@tonic-gate * block of the message. 22467c478bd9Sstevel@tonic-gate * 2) we send up an M_COPYIN request for the strbuf structure pointed to 22477c478bd9Sstevel@tonic-gate * by arg. The block containing arg is hung off cq_private. 22487c478bd9Sstevel@tonic-gate * 3) we receive an M_IOCDATA response with cp->cp_private->b_cont == NULL. 22497c478bd9Sstevel@tonic-gate * This means that the strbuf structure is found in the message block 22507c478bd9Sstevel@tonic-gate * mp->b_cont. 22517c478bd9Sstevel@tonic-gate * 4) we send up an M_COPYOUT request with the strbuf message hung off 22527c478bd9Sstevel@tonic-gate * cq_private->b_cont. The address we are copying to is strbuf.buf. 22537c478bd9Sstevel@tonic-gate * we set strbuf.len to 0 to indicate that we should copy the strbuf 22547c478bd9Sstevel@tonic-gate * structure the next time. The message mp->b_cont contains the 22557c478bd9Sstevel@tonic-gate * address info. 22567c478bd9Sstevel@tonic-gate * 5) we receive an M_IOCDATA with cp_private->b_cont != NULL and 22577c478bd9Sstevel@tonic-gate * strbuf.len == 0. Restore strbuf.len to either tp->tim_mylen or 22587c478bd9Sstevel@tonic-gate * tp->tim_peerlen. 22597c478bd9Sstevel@tonic-gate * 6) we send up an M_COPYOUT request with a copy of the strbuf message 22607c478bd9Sstevel@tonic-gate * hung off mp->b_cont. In the strbuf structure in the message hung 22617c478bd9Sstevel@tonic-gate * off cq_private->b_cont, we set strbuf.len to 0 and strbuf.maxlen 22627c478bd9Sstevel@tonic-gate * to 0. This means that the next step is to ACK the ioctl. 22637c478bd9Sstevel@tonic-gate * 7) we receive an M_IOCDATA message with cp_private->b_cont != NULL and 22647c478bd9Sstevel@tonic-gate * strbuf.len == 0 and strbuf.maxlen == 0. Free up cp->private and 22657c478bd9Sstevel@tonic-gate * send an M_IOCACK upstream, and we are done. 22667c478bd9Sstevel@tonic-gate * 22677c478bd9Sstevel@tonic-gate */ 22687c478bd9Sstevel@tonic-gate static int 22697c478bd9Sstevel@tonic-gate ti_doname( 22707c478bd9Sstevel@tonic-gate queue_t *q, /* queue message arrived at */ 22717c478bd9Sstevel@tonic-gate mblk_t *mp) /* M_IOCTL or M_IOCDATA message only */ 22727c478bd9Sstevel@tonic-gate { 22737c478bd9Sstevel@tonic-gate struct iocblk *iocp; 22747c478bd9Sstevel@tonic-gate struct copyreq *cqp; 22757c478bd9Sstevel@tonic-gate STRUCT_HANDLE(strbuf, sb); 22767c478bd9Sstevel@tonic-gate struct copyresp *csp; 22777c478bd9Sstevel@tonic-gate int ret; 22787c478bd9Sstevel@tonic-gate mblk_t *bp; 22797c478bd9Sstevel@tonic-gate struct tim_tim *tp = q->q_ptr; 22807c478bd9Sstevel@tonic-gate boolean_t getpeer; 22817c478bd9Sstevel@tonic-gate 22827c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 22837c478bd9Sstevel@tonic-gate case M_IOCTL: 22847c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 22857c478bd9Sstevel@tonic-gate if ((iocp->ioc_cmd != TI_GETMYNAME) && 22867c478bd9Sstevel@tonic-gate (iocp->ioc_cmd != TI_GETPEERNAME)) { 22877c478bd9Sstevel@tonic-gate tilog("ti_doname: bad M_IOCTL command\n", 0); 22887c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 22897c478bd9Sstevel@tonic-gate ret = DONAME_FAIL; 22907c478bd9Sstevel@tonic-gate break; 22917c478bd9Sstevel@tonic-gate } 22927c478bd9Sstevel@tonic-gate if ((iocp->ioc_count != TRANSPARENT)) { 22937c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 22947c478bd9Sstevel@tonic-gate ret = DONAME_FAIL; 22957c478bd9Sstevel@tonic-gate break; 22967c478bd9Sstevel@tonic-gate } 22977c478bd9Sstevel@tonic-gate 22987c478bd9Sstevel@tonic-gate cqp = (struct copyreq *)mp->b_rptr; 22997c478bd9Sstevel@tonic-gate cqp->cq_private = mp->b_cont; 23007c478bd9Sstevel@tonic-gate cqp->cq_addr = (caddr_t)*(intptr_t *)mp->b_cont->b_rptr; 23017c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 23027c478bd9Sstevel@tonic-gate cqp->cq_size = SIZEOF_STRUCT(strbuf, iocp->ioc_flag); 23037c478bd9Sstevel@tonic-gate cqp->cq_flag = 0; 23047c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_COPYIN; 23057c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (struct copyreq); 23067c478bd9Sstevel@tonic-gate qreply(q, mp); 23077c478bd9Sstevel@tonic-gate ret = DONAME_CONT; 23087c478bd9Sstevel@tonic-gate break; 23097c478bd9Sstevel@tonic-gate 23107c478bd9Sstevel@tonic-gate case M_IOCDATA: 23117c478bd9Sstevel@tonic-gate csp = (struct copyresp *)mp->b_rptr; 23127c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr; 23137c478bd9Sstevel@tonic-gate cqp = (struct copyreq *)mp->b_rptr; 23147c478bd9Sstevel@tonic-gate if ((csp->cp_cmd != TI_GETMYNAME) && 23157c478bd9Sstevel@tonic-gate (csp->cp_cmd != TI_GETPEERNAME)) { 23167c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "ti_doname: bad M_IOCDATA command\n"); 23177c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 23187c478bd9Sstevel@tonic-gate ret = DONAME_FAIL; 23197c478bd9Sstevel@tonic-gate break; 23207c478bd9Sstevel@tonic-gate } 23217c478bd9Sstevel@tonic-gate if (csp->cp_rval) { /* error */ 23227c478bd9Sstevel@tonic-gate freemsg(csp->cp_private); 23237c478bd9Sstevel@tonic-gate freemsg(mp); 23247c478bd9Sstevel@tonic-gate ret = DONAME_FAIL; 23257c478bd9Sstevel@tonic-gate break; 23267c478bd9Sstevel@tonic-gate } 23277c478bd9Sstevel@tonic-gate ASSERT(csp->cp_private != NULL); 23287c478bd9Sstevel@tonic-gate getpeer = csp->cp_cmd == TI_GETPEERNAME; 23297c478bd9Sstevel@tonic-gate if (getpeer) 23307c478bd9Sstevel@tonic-gate mutex_enter(&tp->tim_mutex); 23317c478bd9Sstevel@tonic-gate if (csp->cp_private->b_cont == NULL) { /* got strbuf */ 23327c478bd9Sstevel@tonic-gate ASSERT(mp->b_cont); 23337c478bd9Sstevel@tonic-gate STRUCT_SET_HANDLE(sb, iocp->ioc_flag, 23347c478bd9Sstevel@tonic-gate (void *)mp->b_cont->b_rptr); 23357c478bd9Sstevel@tonic-gate if (getpeer) { 23367c478bd9Sstevel@tonic-gate if (tp->tim_peerlen == 0) { 23377c478bd9Sstevel@tonic-gate /* copy just strbuf */ 23387c478bd9Sstevel@tonic-gate STRUCT_FSET(sb, len, 0); 23397c478bd9Sstevel@tonic-gate } else if (tp->tim_peerlen > 23407c478bd9Sstevel@tonic-gate STRUCT_FGET(sb, maxlen)) { 23417c478bd9Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 23427c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, ENAMETOOLONG); 23437c478bd9Sstevel@tonic-gate ret = DONAME_FAIL; 23447c478bd9Sstevel@tonic-gate break; 23457c478bd9Sstevel@tonic-gate } else { 23467c478bd9Sstevel@tonic-gate /* copy buffer */ 23477c478bd9Sstevel@tonic-gate STRUCT_FSET(sb, len, tp->tim_peerlen); 23487c478bd9Sstevel@tonic-gate } 23497c478bd9Sstevel@tonic-gate } else { 23507c478bd9Sstevel@tonic-gate if (tp->tim_mylen == 0) { 23517c478bd9Sstevel@tonic-gate /* copy just strbuf */ 23527c478bd9Sstevel@tonic-gate STRUCT_FSET(sb, len, 0); 23537c478bd9Sstevel@tonic-gate } else if (tp->tim_mylen > 23547c478bd9Sstevel@tonic-gate STRUCT_FGET(sb, maxlen)) { 23557c478bd9Sstevel@tonic-gate freemsg(csp->cp_private); 23567c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, ENAMETOOLONG); 23577c478bd9Sstevel@tonic-gate ret = DONAME_FAIL; 23587c478bd9Sstevel@tonic-gate break; 23597c478bd9Sstevel@tonic-gate } else { 23607c478bd9Sstevel@tonic-gate /* copy buffer */ 23617c478bd9Sstevel@tonic-gate STRUCT_FSET(sb, len, tp->tim_mylen); 23627c478bd9Sstevel@tonic-gate } 23637c478bd9Sstevel@tonic-gate } 23647c478bd9Sstevel@tonic-gate csp->cp_private->b_cont = mp->b_cont; 23657c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 23667c478bd9Sstevel@tonic-gate } 23677c478bd9Sstevel@tonic-gate STRUCT_SET_HANDLE(sb, iocp->ioc_flag, 23687c478bd9Sstevel@tonic-gate (void *)csp->cp_private->b_cont->b_rptr); 23697c478bd9Sstevel@tonic-gate if (STRUCT_FGET(sb, len) == 0) { 23707c478bd9Sstevel@tonic-gate /* 23717c478bd9Sstevel@tonic-gate * restore strbuf.len 23727c478bd9Sstevel@tonic-gate */ 23737c478bd9Sstevel@tonic-gate if (getpeer) 23747c478bd9Sstevel@tonic-gate STRUCT_FSET(sb, len, tp->tim_peerlen); 23757c478bd9Sstevel@tonic-gate else 23767c478bd9Sstevel@tonic-gate STRUCT_FSET(sb, len, tp->tim_mylen); 23777c478bd9Sstevel@tonic-gate 23787c478bd9Sstevel@tonic-gate if (getpeer) 23797c478bd9Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 23807c478bd9Sstevel@tonic-gate if (STRUCT_FGET(sb, maxlen) == 0) { 23817c478bd9Sstevel@tonic-gate 23827c478bd9Sstevel@tonic-gate /* 23837c478bd9Sstevel@tonic-gate * ack the ioctl 23847c478bd9Sstevel@tonic-gate */ 23857c478bd9Sstevel@tonic-gate freemsg(csp->cp_private); 23867c478bd9Sstevel@tonic-gate tim_ioctl_send_reply(q, mp, NULL); 23877c478bd9Sstevel@tonic-gate ret = DONAME_DONE; 23887c478bd9Sstevel@tonic-gate break; 23897c478bd9Sstevel@tonic-gate } 23907c478bd9Sstevel@tonic-gate 23917c478bd9Sstevel@tonic-gate if ((bp = allocb(STRUCT_SIZE(sb), BPRI_MED)) == NULL) { 23927c478bd9Sstevel@tonic-gate 23937c478bd9Sstevel@tonic-gate tilog( 23947c478bd9Sstevel@tonic-gate "ti_doname: allocb failed no recovery attempt\n", 0); 23957c478bd9Sstevel@tonic-gate 23967c478bd9Sstevel@tonic-gate freemsg(csp->cp_private); 23977c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EAGAIN); 23987c478bd9Sstevel@tonic-gate ret = DONAME_FAIL; 23997c478bd9Sstevel@tonic-gate break; 24007c478bd9Sstevel@tonic-gate } 24017c478bd9Sstevel@tonic-gate bp->b_wptr += STRUCT_SIZE(sb); 24027c478bd9Sstevel@tonic-gate bcopy(STRUCT_BUF(sb), bp->b_rptr, STRUCT_SIZE(sb)); 24037c478bd9Sstevel@tonic-gate cqp->cq_addr = 24047c478bd9Sstevel@tonic-gate (caddr_t)*(intptr_t *)csp->cp_private->b_rptr; 24057c478bd9Sstevel@tonic-gate cqp->cq_size = STRUCT_SIZE(sb); 24067c478bd9Sstevel@tonic-gate cqp->cq_flag = 0; 24077c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_COPYOUT; 24087c478bd9Sstevel@tonic-gate mp->b_cont = bp; 24097c478bd9Sstevel@tonic-gate STRUCT_FSET(sb, len, 0); 24107c478bd9Sstevel@tonic-gate STRUCT_FSET(sb, maxlen, 0); /* ack next time around */ 24117c478bd9Sstevel@tonic-gate qreply(q, mp); 24127c478bd9Sstevel@tonic-gate ret = DONAME_CONT; 24137c478bd9Sstevel@tonic-gate break; 24147c478bd9Sstevel@tonic-gate } 24157c478bd9Sstevel@tonic-gate 24167c478bd9Sstevel@tonic-gate /* 24177c478bd9Sstevel@tonic-gate * copy the address to the user 24187c478bd9Sstevel@tonic-gate */ 24197c478bd9Sstevel@tonic-gate if ((bp = allocb((size_t)STRUCT_FGET(sb, len), BPRI_MED)) 24207c478bd9Sstevel@tonic-gate == NULL) { 24217c478bd9Sstevel@tonic-gate if (getpeer) 24227c478bd9Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 24237c478bd9Sstevel@tonic-gate 24247c478bd9Sstevel@tonic-gate tilog("ti_doname: allocb failed no recovery attempt\n", 24257c478bd9Sstevel@tonic-gate 0); 24267c478bd9Sstevel@tonic-gate 24277c478bd9Sstevel@tonic-gate freemsg(csp->cp_private); 24287c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EAGAIN); 24297c478bd9Sstevel@tonic-gate ret = DONAME_FAIL; 24307c478bd9Sstevel@tonic-gate break; 24317c478bd9Sstevel@tonic-gate } 24327c478bd9Sstevel@tonic-gate bp->b_wptr += STRUCT_FGET(sb, len); 24337c478bd9Sstevel@tonic-gate if (getpeer) { 24347c478bd9Sstevel@tonic-gate bcopy(tp->tim_peername, bp->b_rptr, 24357c478bd9Sstevel@tonic-gate STRUCT_FGET(sb, len)); 24367c478bd9Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 24377c478bd9Sstevel@tonic-gate } else { 24387c478bd9Sstevel@tonic-gate bcopy(tp->tim_myname, bp->b_rptr, STRUCT_FGET(sb, len)); 24397c478bd9Sstevel@tonic-gate } 24407c478bd9Sstevel@tonic-gate cqp->cq_addr = (caddr_t)STRUCT_FGETP(sb, buf); 24417c478bd9Sstevel@tonic-gate cqp->cq_size = STRUCT_FGET(sb, len); 24427c478bd9Sstevel@tonic-gate cqp->cq_flag = 0; 24437c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_COPYOUT; 24447c478bd9Sstevel@tonic-gate mp->b_cont = bp; 24457c478bd9Sstevel@tonic-gate STRUCT_FSET(sb, len, 0); /* copy the strbuf next time around */ 24467c478bd9Sstevel@tonic-gate qreply(q, mp); 24477c478bd9Sstevel@tonic-gate ret = DONAME_CONT; 24487c478bd9Sstevel@tonic-gate break; 24497c478bd9Sstevel@tonic-gate 24507c478bd9Sstevel@tonic-gate default: 24517c478bd9Sstevel@tonic-gate tilog("ti_doname: freeing bad message type = %d\n", 24527c478bd9Sstevel@tonic-gate mp->b_datap->db_type); 24537c478bd9Sstevel@tonic-gate freemsg(mp); 24547c478bd9Sstevel@tonic-gate ret = DONAME_FAIL; 24557c478bd9Sstevel@tonic-gate break; 24567c478bd9Sstevel@tonic-gate } 24577c478bd9Sstevel@tonic-gate return (ret); 24587c478bd9Sstevel@tonic-gate } 24597c478bd9Sstevel@tonic-gate 24607c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 24617c478bd9Sstevel@tonic-gate 24627c478bd9Sstevel@tonic-gate /* 24637c478bd9Sstevel@tonic-gate * Fill in the address of a connectionless data packet if a connect 24647c478bd9Sstevel@tonic-gate * had been done on this endpoint. 24657c478bd9Sstevel@tonic-gate */ 24667c478bd9Sstevel@tonic-gate static mblk_t * 24677c478bd9Sstevel@tonic-gate tim_filladdr(queue_t *q, mblk_t *mp, boolean_t dorecover) 24687c478bd9Sstevel@tonic-gate { 24697c478bd9Sstevel@tonic-gate mblk_t *bp; 24707c478bd9Sstevel@tonic-gate struct tim_tim *tp; 24717c478bd9Sstevel@tonic-gate struct T_unitdata_req *up; 24727c478bd9Sstevel@tonic-gate struct T_unitdata_req *nup; 24737c478bd9Sstevel@tonic-gate size_t plen; 24747c478bd9Sstevel@tonic-gate 24757c478bd9Sstevel@tonic-gate tp = (struct tim_tim *)q->q_ptr; 24767c478bd9Sstevel@tonic-gate if (mp->b_datap->db_type == M_DATA) { 24777c478bd9Sstevel@tonic-gate mutex_enter(&tp->tim_mutex); 24787c478bd9Sstevel@tonic-gate bp = allocb(sizeof (struct T_unitdata_req) + tp->tim_peerlen, 24797c478bd9Sstevel@tonic-gate BPRI_MED); 24807c478bd9Sstevel@tonic-gate if (bp != NULL) { 24817c478bd9Sstevel@tonic-gate bp->b_datap->db_type = M_PROTO; 24827c478bd9Sstevel@tonic-gate up = (struct T_unitdata_req *)bp->b_rptr; 24837c478bd9Sstevel@tonic-gate up->PRIM_type = T_UNITDATA_REQ; 24847c478bd9Sstevel@tonic-gate up->DEST_length = tp->tim_peerlen; 24857c478bd9Sstevel@tonic-gate bp->b_wptr += sizeof (struct T_unitdata_req); 24867c478bd9Sstevel@tonic-gate up->DEST_offset = sizeof (struct T_unitdata_req); 24877c478bd9Sstevel@tonic-gate up->OPT_length = 0; 24887c478bd9Sstevel@tonic-gate up->OPT_offset = 0; 24897c478bd9Sstevel@tonic-gate if (tp->tim_peerlen > 0) { 24907c478bd9Sstevel@tonic-gate bcopy(tp->tim_peername, bp->b_wptr, 24917c478bd9Sstevel@tonic-gate tp->tim_peerlen); 24927c478bd9Sstevel@tonic-gate bp->b_wptr += tp->tim_peerlen; 24937c478bd9Sstevel@tonic-gate } 24947c478bd9Sstevel@tonic-gate bp->b_cont = mp; 24957c478bd9Sstevel@tonic-gate } 24967c478bd9Sstevel@tonic-gate } else { 24977c478bd9Sstevel@tonic-gate ASSERT(mp->b_datap->db_type == M_PROTO); 24987c478bd9Sstevel@tonic-gate up = (struct T_unitdata_req *)mp->b_rptr; 24997c478bd9Sstevel@tonic-gate ASSERT(up->PRIM_type == T_UNITDATA_REQ); 25007c478bd9Sstevel@tonic-gate if (up->DEST_length != 0) 25017c478bd9Sstevel@tonic-gate return (mp); 25027c478bd9Sstevel@tonic-gate mutex_enter(&tp->tim_mutex); 25037c478bd9Sstevel@tonic-gate bp = allocb(sizeof (struct T_unitdata_req) + up->OPT_length + 25047c478bd9Sstevel@tonic-gate tp->tim_peerlen, BPRI_MED); 25057c478bd9Sstevel@tonic-gate if (bp != NULL) { 25067c478bd9Sstevel@tonic-gate bp->b_datap->db_type = M_PROTO; 25077c478bd9Sstevel@tonic-gate nup = (struct T_unitdata_req *)bp->b_rptr; 25087c478bd9Sstevel@tonic-gate nup->PRIM_type = T_UNITDATA_REQ; 25097c478bd9Sstevel@tonic-gate nup->DEST_length = plen = tp->tim_peerlen; 25107c478bd9Sstevel@tonic-gate bp->b_wptr += sizeof (struct T_unitdata_req); 25117c478bd9Sstevel@tonic-gate nup->DEST_offset = sizeof (struct T_unitdata_req); 25127c478bd9Sstevel@tonic-gate if (plen > 0) { 25137c478bd9Sstevel@tonic-gate bcopy(tp->tim_peername, bp->b_wptr, plen); 25147c478bd9Sstevel@tonic-gate bp->b_wptr += plen; 25157c478bd9Sstevel@tonic-gate } 25167c478bd9Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 25177c478bd9Sstevel@tonic-gate if (up->OPT_length == 0) { 25187c478bd9Sstevel@tonic-gate nup->OPT_length = 0; 25197c478bd9Sstevel@tonic-gate nup->OPT_offset = 0; 25207c478bd9Sstevel@tonic-gate } else { 25217c478bd9Sstevel@tonic-gate nup->OPT_length = up->OPT_length; 25227c478bd9Sstevel@tonic-gate nup->OPT_offset = 25237c478bd9Sstevel@tonic-gate sizeof (struct T_unitdata_req) + plen; 25247c478bd9Sstevel@tonic-gate bcopy((mp->b_wptr + up->OPT_offset), bp->b_wptr, 25257c478bd9Sstevel@tonic-gate up->OPT_length); 25267c478bd9Sstevel@tonic-gate bp->b_wptr += up->OPT_length; 25277c478bd9Sstevel@tonic-gate } 25287c478bd9Sstevel@tonic-gate bp->b_cont = mp->b_cont; 25297c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 25307c478bd9Sstevel@tonic-gate freeb(mp); 25317c478bd9Sstevel@tonic-gate return (bp); 25327c478bd9Sstevel@tonic-gate } 25337c478bd9Sstevel@tonic-gate } 25347c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&tp->tim_mutex)); 25357c478bd9Sstevel@tonic-gate if (bp == NULL && dorecover) { 25367c478bd9Sstevel@tonic-gate tim_recover(q, mp, 25377c478bd9Sstevel@tonic-gate sizeof (struct T_unitdata_req) + tp->tim_peerlen); 25387c478bd9Sstevel@tonic-gate } 25397c478bd9Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 25407c478bd9Sstevel@tonic-gate return (bp); 25417c478bd9Sstevel@tonic-gate } 25427c478bd9Sstevel@tonic-gate 25437c478bd9Sstevel@tonic-gate static void 25447c478bd9Sstevel@tonic-gate tim_addlink(struct tim_tim *tp) 25457c478bd9Sstevel@tonic-gate { 25467c478bd9Sstevel@tonic-gate struct tim_tim **tpp; 25477c478bd9Sstevel@tonic-gate struct tim_tim *next; 25487c478bd9Sstevel@tonic-gate 25497c478bd9Sstevel@tonic-gate tpp = &tim_hash[TIM_HASH(tp->tim_acceptor)]; 25507c478bd9Sstevel@tonic-gate rw_enter(&tim_list_rwlock, RW_WRITER); 25517c478bd9Sstevel@tonic-gate 25527c478bd9Sstevel@tonic-gate if ((next = *tpp) != NULL) 25537c478bd9Sstevel@tonic-gate next->tim_ptpn = &tp->tim_next; 25547c478bd9Sstevel@tonic-gate tp->tim_next = next; 25557c478bd9Sstevel@tonic-gate tp->tim_ptpn = tpp; 25567c478bd9Sstevel@tonic-gate *tpp = tp; 25577c478bd9Sstevel@tonic-gate 25587c478bd9Sstevel@tonic-gate tim_cnt++; 25597c478bd9Sstevel@tonic-gate 25607c478bd9Sstevel@tonic-gate rw_exit(&tim_list_rwlock); 25617c478bd9Sstevel@tonic-gate } 25627c478bd9Sstevel@tonic-gate 25637c478bd9Sstevel@tonic-gate static void 25647c478bd9Sstevel@tonic-gate tim_dellink(struct tim_tim *tp) 25657c478bd9Sstevel@tonic-gate { 25667c478bd9Sstevel@tonic-gate struct tim_tim *next; 25677c478bd9Sstevel@tonic-gate 25687c478bd9Sstevel@tonic-gate rw_enter(&tim_list_rwlock, RW_WRITER); 25697c478bd9Sstevel@tonic-gate 25707c478bd9Sstevel@tonic-gate if ((next = tp->tim_next) != NULL) 25717c478bd9Sstevel@tonic-gate next->tim_ptpn = tp->tim_ptpn; 25727c478bd9Sstevel@tonic-gate *(tp->tim_ptpn) = next; 25737c478bd9Sstevel@tonic-gate 25747c478bd9Sstevel@tonic-gate tim_cnt--; 25757c478bd9Sstevel@tonic-gate 25767c478bd9Sstevel@tonic-gate rw_exit(&tim_list_rwlock); 25777c478bd9Sstevel@tonic-gate } 25787c478bd9Sstevel@tonic-gate 25797c478bd9Sstevel@tonic-gate static struct tim_tim * 25807c478bd9Sstevel@tonic-gate tim_findlink(t_uscalar_t id) 25817c478bd9Sstevel@tonic-gate { 25827c478bd9Sstevel@tonic-gate struct tim_tim *tp; 25837c478bd9Sstevel@tonic-gate 25847c478bd9Sstevel@tonic-gate ASSERT(rw_lock_held(&tim_list_rwlock)); 25857c478bd9Sstevel@tonic-gate 25867c478bd9Sstevel@tonic-gate for (tp = tim_hash[TIM_HASH(id)]; tp != NULL; tp = tp->tim_next) { 25877c478bd9Sstevel@tonic-gate if (tp->tim_acceptor == id) { 25887c478bd9Sstevel@tonic-gate break; 25897c478bd9Sstevel@tonic-gate } 25907c478bd9Sstevel@tonic-gate } 25917c478bd9Sstevel@tonic-gate return (tp); 25927c478bd9Sstevel@tonic-gate } 25937c478bd9Sstevel@tonic-gate 25947c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 25957c478bd9Sstevel@tonic-gate static void 25967c478bd9Sstevel@tonic-gate tim_recover(queue_t *q, mblk_t *mp, t_scalar_t size) 25977c478bd9Sstevel@tonic-gate { 25987c478bd9Sstevel@tonic-gate struct tim_tim *tp; 25997c478bd9Sstevel@tonic-gate bufcall_id_t bid; 26007c478bd9Sstevel@tonic-gate timeout_id_t tid; 26017c478bd9Sstevel@tonic-gate 26027c478bd9Sstevel@tonic-gate tp = (struct tim_tim *)q->q_ptr; 26037c478bd9Sstevel@tonic-gate 26047c478bd9Sstevel@tonic-gate /* 26057c478bd9Sstevel@tonic-gate * Avoid re-enabling the queue. 26067c478bd9Sstevel@tonic-gate */ 26077c478bd9Sstevel@tonic-gate if (mp->b_datap->db_type == M_PCPROTO) 26087c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PROTO; 26097c478bd9Sstevel@tonic-gate noenable(q); 26107c478bd9Sstevel@tonic-gate (void) putbq(q, mp); 26117c478bd9Sstevel@tonic-gate 26127c478bd9Sstevel@tonic-gate /* 26137c478bd9Sstevel@tonic-gate * Make sure there is at most one outstanding request per queue. 26147c478bd9Sstevel@tonic-gate */ 26157c478bd9Sstevel@tonic-gate if (q->q_flag & QREADR) { 26167c478bd9Sstevel@tonic-gate if (tp->tim_rtimoutid || tp->tim_rbufcid) 26177c478bd9Sstevel@tonic-gate return; 26187c478bd9Sstevel@tonic-gate } else { 26197c478bd9Sstevel@tonic-gate if (tp->tim_wtimoutid || tp->tim_wbufcid) 26207c478bd9Sstevel@tonic-gate return; 26217c478bd9Sstevel@tonic-gate } 26227c478bd9Sstevel@tonic-gate if (!(bid = qbufcall(RD(q), (size_t)size, BPRI_MED, tim_buffer, q))) { 26237c478bd9Sstevel@tonic-gate tid = qtimeout(RD(q), tim_timer, q, TIMWAIT); 26247c478bd9Sstevel@tonic-gate if (q->q_flag & QREADR) 26257c478bd9Sstevel@tonic-gate tp->tim_rtimoutid = tid; 26267c478bd9Sstevel@tonic-gate else 26277c478bd9Sstevel@tonic-gate tp->tim_wtimoutid = tid; 26287c478bd9Sstevel@tonic-gate } else { 26297c478bd9Sstevel@tonic-gate if (q->q_flag & QREADR) 26307c478bd9Sstevel@tonic-gate tp->tim_rbufcid = bid; 26317c478bd9Sstevel@tonic-gate else 26327c478bd9Sstevel@tonic-gate tp->tim_wbufcid = bid; 26337c478bd9Sstevel@tonic-gate } 26347c478bd9Sstevel@tonic-gate } 26357c478bd9Sstevel@tonic-gate 26367c478bd9Sstevel@tonic-gate /* 2637*2cbe889aSgeorges * Timod is waiting on a downstream ioctl reply, come back soon 2638*2cbe889aSgeorges * to reschedule the write side service routine, which will check 2639*2cbe889aSgeorges * if the ioctl is done and another can proceed. 2640*2cbe889aSgeorges */ 2641*2cbe889aSgeorges static void 2642*2cbe889aSgeorges tim_ioctl_retry(queue_t *q) 2643*2cbe889aSgeorges { 2644*2cbe889aSgeorges struct tim_tim *tp; 2645*2cbe889aSgeorges 2646*2cbe889aSgeorges tp = (struct tim_tim *)q->q_ptr; 2647*2cbe889aSgeorges 2648*2cbe889aSgeorges /* 2649*2cbe889aSgeorges * Make sure there is at most one outstanding request per wqueue. 2650*2cbe889aSgeorges */ 2651*2cbe889aSgeorges if (tp->tim_wtimoutid || tp->tim_wbufcid) 2652*2cbe889aSgeorges return; 2653*2cbe889aSgeorges 2654*2cbe889aSgeorges tp->tim_wtimoutid = qtimeout(RD(q), tim_timer, q, TIMIOCWAIT); 2655*2cbe889aSgeorges } 2656*2cbe889aSgeorges 2657*2cbe889aSgeorges /* 26587c478bd9Sstevel@tonic-gate * Inspect the data on read queues starting from read queues passed as 26597c478bd9Sstevel@tonic-gate * paramter (timod read queue) and traverse until 26607c478bd9Sstevel@tonic-gate * q_next is NULL (stream head). Look for a TPI T_EXDATA_IND message 26617c478bd9Sstevel@tonic-gate * reutrn 1 if found, 0 if not found. 26627c478bd9Sstevel@tonic-gate */ 26637c478bd9Sstevel@tonic-gate static int 26647c478bd9Sstevel@tonic-gate ti_expind_on_rdqueues(queue_t *rq) 26657c478bd9Sstevel@tonic-gate { 26667c478bd9Sstevel@tonic-gate mblk_t *bp; 26677c478bd9Sstevel@tonic-gate queue_t *q; 26687c478bd9Sstevel@tonic-gate 26697c478bd9Sstevel@tonic-gate q = rq; 26707c478bd9Sstevel@tonic-gate /* 26717c478bd9Sstevel@tonic-gate * We are going to walk q_next, so protect stream from plumbing 26727c478bd9Sstevel@tonic-gate * changes. 26737c478bd9Sstevel@tonic-gate */ 26747c478bd9Sstevel@tonic-gate claimstr(q); 26757c478bd9Sstevel@tonic-gate do { 26767c478bd9Sstevel@tonic-gate /* 26777c478bd9Sstevel@tonic-gate * Hold QLOCK while referencing data on queues 26787c478bd9Sstevel@tonic-gate */ 26797c478bd9Sstevel@tonic-gate mutex_enter(QLOCK(rq)); 26807c478bd9Sstevel@tonic-gate bp = rq->q_first; 26817c478bd9Sstevel@tonic-gate while (bp != NULL) { 26827c478bd9Sstevel@tonic-gate /* 26837c478bd9Sstevel@tonic-gate * Walk the messages on the queue looking 26847c478bd9Sstevel@tonic-gate * for a possible T_EXDATA_IND 26857c478bd9Sstevel@tonic-gate */ 26867c478bd9Sstevel@tonic-gate if ((bp->b_datap->db_type == M_PROTO) && 26877c478bd9Sstevel@tonic-gate ((bp->b_wptr - bp->b_rptr) >= 26887c478bd9Sstevel@tonic-gate sizeof (struct T_exdata_ind)) && 26897c478bd9Sstevel@tonic-gate (((struct T_exdata_ind *)bp->b_rptr)->PRIM_type 26907c478bd9Sstevel@tonic-gate == T_EXDATA_IND)) { 26917c478bd9Sstevel@tonic-gate /* bp is T_EXDATA_IND */ 26927c478bd9Sstevel@tonic-gate mutex_exit(QLOCK(rq)); 26937c478bd9Sstevel@tonic-gate releasestr(q); /* decrement sd_refcnt */ 26947c478bd9Sstevel@tonic-gate return (1); /* expdata is on a read queue */ 26957c478bd9Sstevel@tonic-gate } 26967c478bd9Sstevel@tonic-gate bp = bp->b_next; /* next message */ 26977c478bd9Sstevel@tonic-gate } 26987c478bd9Sstevel@tonic-gate mutex_exit(QLOCK(rq)); 26997c478bd9Sstevel@tonic-gate rq = rq->q_next; /* next upstream queue */ 27007c478bd9Sstevel@tonic-gate } while (rq != NULL); 27017c478bd9Sstevel@tonic-gate releasestr(q); 27027c478bd9Sstevel@tonic-gate return (0); /* no expdata on read queues */ 27037c478bd9Sstevel@tonic-gate } 27047c478bd9Sstevel@tonic-gate 27057c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 27067c478bd9Sstevel@tonic-gate static void 27077c478bd9Sstevel@tonic-gate tim_tcap_timer(void *q_ptr) 27087c478bd9Sstevel@tonic-gate { 27097c478bd9Sstevel@tonic-gate queue_t *q = (queue_t *)q_ptr; 27107c478bd9Sstevel@tonic-gate struct tim_tim *tp = (struct tim_tim *)q->q_ptr; 27117c478bd9Sstevel@tonic-gate 27127c478bd9Sstevel@tonic-gate ASSERT(tp != NULL && tp->tim_tcap_timoutid != 0); 27137c478bd9Sstevel@tonic-gate ASSERT((tp->tim_flags & TI_CAP_RECVD) != 0); 27147c478bd9Sstevel@tonic-gate 27157c478bd9Sstevel@tonic-gate tp->tim_tcap_timoutid = 0; 27167c478bd9Sstevel@tonic-gate TILOG("tim_tcap_timer: fired\n", 0); 27177c478bd9Sstevel@tonic-gate tim_tcap_genreply(q, tp); 27187c478bd9Sstevel@tonic-gate } 27197c478bd9Sstevel@tonic-gate 27207c478bd9Sstevel@tonic-gate /* 27217c478bd9Sstevel@tonic-gate * tim_tcap_genreply() is called either from timeout routine or when 27227c478bd9Sstevel@tonic-gate * T_ERROR_ACK is received. In both cases it means that underlying 27237c478bd9Sstevel@tonic-gate * transport doesn't provide T_CAPABILITY_REQ. 27247c478bd9Sstevel@tonic-gate */ 27257c478bd9Sstevel@tonic-gate static void 27267c478bd9Sstevel@tonic-gate tim_tcap_genreply(queue_t *q, struct tim_tim *tp) 27277c478bd9Sstevel@tonic-gate { 27287c478bd9Sstevel@tonic-gate mblk_t *mp = tp->tim_iocsave; 27297c478bd9Sstevel@tonic-gate struct iocblk *iocbp; 27307c478bd9Sstevel@tonic-gate 27317c478bd9Sstevel@tonic-gate TILOG("timodrproc: tim_tcap_genreply\n", 0); 27327c478bd9Sstevel@tonic-gate 27337c478bd9Sstevel@tonic-gate ASSERT(tp == (struct tim_tim *)q->q_ptr); 27347c478bd9Sstevel@tonic-gate ASSERT(mp != NULL); 27357c478bd9Sstevel@tonic-gate 27367c478bd9Sstevel@tonic-gate iocbp = (struct iocblk *)mp->b_rptr; 27377c478bd9Sstevel@tonic-gate ASSERT(iocbp != NULL); 27387c478bd9Sstevel@tonic-gate ASSERT(MBLKL(mp) == sizeof (struct iocblk)); 27397c478bd9Sstevel@tonic-gate ASSERT(iocbp->ioc_cmd == TI_CAPABILITY); 27407c478bd9Sstevel@tonic-gate ASSERT(mp->b_cont == NULL); 27417c478bd9Sstevel@tonic-gate 27427c478bd9Sstevel@tonic-gate /* Save this information permanently in the module */ 27437c478bd9Sstevel@tonic-gate PI_PROVLOCK(tp->tim_provinfo); 27447c478bd9Sstevel@tonic-gate if (tp->tim_provinfo->tpi_capability == PI_DONTKNOW) 27457c478bd9Sstevel@tonic-gate tp->tim_provinfo->tpi_capability = PI_NO; 27467c478bd9Sstevel@tonic-gate PI_PROVUNLOCK(tp->tim_provinfo); 27477c478bd9Sstevel@tonic-gate 27487c478bd9Sstevel@tonic-gate if (tp->tim_tcap_timoutid != 0) { 27497c478bd9Sstevel@tonic-gate (void) quntimeout(q, tp->tim_tcap_timoutid); 27507c478bd9Sstevel@tonic-gate tp->tim_tcap_timoutid = 0; 27517c478bd9Sstevel@tonic-gate } 27527c478bd9Sstevel@tonic-gate 27537c478bd9Sstevel@tonic-gate if ((tp->tim_flags & CAP_WANTS_INFO) != 0) { 27547c478bd9Sstevel@tonic-gate /* Send T_INFO_REQ down */ 27557c478bd9Sstevel@tonic-gate mblk_t *tirmp = tpi_ack_alloc(NULL, 27567c478bd9Sstevel@tonic-gate sizeof (struct T_info_req), M_PCPROTO, T_INFO_REQ); 27577c478bd9Sstevel@tonic-gate 27587c478bd9Sstevel@tonic-gate if (tirmp != NULL) { 27597c478bd9Sstevel@tonic-gate /* Emulate TC1_INFO */ 27607c478bd9Sstevel@tonic-gate TILOG("emulate_tcap_ioc_req: sending T_INFO_REQ\n", 0); 27617c478bd9Sstevel@tonic-gate tp->tim_flags |= WAIT_IOCINFOACK; 27627c478bd9Sstevel@tonic-gate putnext(WR(q), tirmp); 27637c478bd9Sstevel@tonic-gate } else { 27647c478bd9Sstevel@tonic-gate tilog("emulate_tcap_req: allocb fail, " 27657c478bd9Sstevel@tonic-gate "no recovery attmpt\n", 0); 27667c478bd9Sstevel@tonic-gate tp->tim_iocsave = NULL; 27677c478bd9Sstevel@tonic-gate tp->tim_saved_prim = -1; 27687c478bd9Sstevel@tonic-gate tp->tim_flags &= ~(TI_CAP_RECVD | WAITIOCACK | 27697c478bd9Sstevel@tonic-gate CAP_WANTS_INFO | WAIT_IOCINFOACK); 27707c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, ENOMEM); 27717c478bd9Sstevel@tonic-gate } 27727c478bd9Sstevel@tonic-gate } else { 27737c478bd9Sstevel@tonic-gate /* Reply immediately */ 27747c478bd9Sstevel@tonic-gate mblk_t *ackmp = tpi_ack_alloc(NULL, 27757c478bd9Sstevel@tonic-gate sizeof (struct T_capability_ack), M_PCPROTO, 27767c478bd9Sstevel@tonic-gate T_CAPABILITY_ACK); 27777c478bd9Sstevel@tonic-gate 27787c478bd9Sstevel@tonic-gate mp->b_cont = ackmp; 27797c478bd9Sstevel@tonic-gate 27807c478bd9Sstevel@tonic-gate if (ackmp != NULL) { 27817c478bd9Sstevel@tonic-gate ((struct T_capability_ack *) 27827c478bd9Sstevel@tonic-gate ackmp->b_rptr)->CAP_bits1 = 0; 27837c478bd9Sstevel@tonic-gate tim_ioctl_send_reply(q, mp, ackmp); 27847c478bd9Sstevel@tonic-gate tp->tim_iocsave = NULL; 27857c478bd9Sstevel@tonic-gate tp->tim_saved_prim = -1; 27867c478bd9Sstevel@tonic-gate tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 27877c478bd9Sstevel@tonic-gate TI_CAP_RECVD | CAP_WANTS_INFO); 27887c478bd9Sstevel@tonic-gate } else { 27897c478bd9Sstevel@tonic-gate tilog("timodwproc:allocb failed no " 27907c478bd9Sstevel@tonic-gate "recovery attempt\n", 0); 27917c478bd9Sstevel@tonic-gate tp->tim_iocsave = NULL; 27927c478bd9Sstevel@tonic-gate tp->tim_saved_prim = -1; 27937c478bd9Sstevel@tonic-gate tp->tim_flags &= ~(TI_CAP_RECVD | WAITIOCACK | 27947c478bd9Sstevel@tonic-gate CAP_WANTS_INFO | WAIT_IOCINFOACK); 27957c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, ENOMEM); 27967c478bd9Sstevel@tonic-gate } 27977c478bd9Sstevel@tonic-gate } 27987c478bd9Sstevel@tonic-gate } 27997c478bd9Sstevel@tonic-gate 28007c478bd9Sstevel@tonic-gate 28017c478bd9Sstevel@tonic-gate static void 28027c478bd9Sstevel@tonic-gate tim_ioctl_send_reply(queue_t *q, mblk_t *ioc_mp, mblk_t *mp) 28037c478bd9Sstevel@tonic-gate { 28047c478bd9Sstevel@tonic-gate struct iocblk *iocbp; 28057c478bd9Sstevel@tonic-gate 28067c478bd9Sstevel@tonic-gate ASSERT(q != NULL && ioc_mp != NULL); 28077c478bd9Sstevel@tonic-gate 28087c478bd9Sstevel@tonic-gate ioc_mp->b_datap->db_type = M_IOCACK; 28097c478bd9Sstevel@tonic-gate if (mp != NULL) 28107c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_DATA; 28117c478bd9Sstevel@tonic-gate 28127c478bd9Sstevel@tonic-gate if (ioc_mp->b_cont != mp) { 28137c478bd9Sstevel@tonic-gate /* It is safe to call freemsg for NULL pointers */ 28147c478bd9Sstevel@tonic-gate freemsg(ioc_mp->b_cont); 28157c478bd9Sstevel@tonic-gate ioc_mp->b_cont = mp; 28167c478bd9Sstevel@tonic-gate } 28177c478bd9Sstevel@tonic-gate iocbp = (struct iocblk *)ioc_mp->b_rptr; 28187c478bd9Sstevel@tonic-gate iocbp->ioc_error = 0; 28197c478bd9Sstevel@tonic-gate iocbp->ioc_rval = 0; 28207c478bd9Sstevel@tonic-gate /* 28217c478bd9Sstevel@tonic-gate * All ioctl's may return more data than was specified by 28227c478bd9Sstevel@tonic-gate * count arg. For TI_CAPABILITY count is treated as maximum data size. 28237c478bd9Sstevel@tonic-gate */ 28247c478bd9Sstevel@tonic-gate if (mp == NULL) 28257c478bd9Sstevel@tonic-gate iocbp->ioc_count = 0; 28267c478bd9Sstevel@tonic-gate else if (iocbp->ioc_cmd != TI_CAPABILITY) 28277c478bd9Sstevel@tonic-gate iocbp->ioc_count = msgsize(mp); 28287c478bd9Sstevel@tonic-gate else { 28297c478bd9Sstevel@tonic-gate iocbp->ioc_count = MIN(MBLKL(mp), iocbp->ioc_count); 28307c478bd9Sstevel@tonic-gate /* Truncate message if too large */ 28317c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + iocbp->ioc_count; 28327c478bd9Sstevel@tonic-gate } 28337c478bd9Sstevel@tonic-gate 28347c478bd9Sstevel@tonic-gate TILOG("iosendreply: ioc_cmd = %d, ", iocbp->ioc_cmd); 28357c478bd9Sstevel@tonic-gate putnext(RD(q), ioc_mp); 28367c478bd9Sstevel@tonic-gate } 28377c478bd9Sstevel@tonic-gate 28387c478bd9Sstevel@tonic-gate /* 28397c478bd9Sstevel@tonic-gate * Send M_IOCACK for errors. 28407c478bd9Sstevel@tonic-gate */ 28417c478bd9Sstevel@tonic-gate static void 28427c478bd9Sstevel@tonic-gate tim_send_ioc_error_ack(queue_t *q, struct tim_tim *tp, mblk_t *mp) 28437c478bd9Sstevel@tonic-gate { 28447c478bd9Sstevel@tonic-gate struct T_error_ack *tea = (struct T_error_ack *)mp->b_rptr; 28457c478bd9Sstevel@tonic-gate t_scalar_t error_prim; 28467c478bd9Sstevel@tonic-gate 28477c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (struct T_error_ack); 28487c478bd9Sstevel@tonic-gate ASSERT(mp->b_wptr <= mp->b_datap->db_lim); 28497c478bd9Sstevel@tonic-gate error_prim = tea->ERROR_prim; 28507c478bd9Sstevel@tonic-gate 28517c478bd9Sstevel@tonic-gate ASSERT(tp->tim_iocsave != NULL); 28527c478bd9Sstevel@tonic-gate ASSERT(tp->tim_iocsave->b_cont != mp); 28537c478bd9Sstevel@tonic-gate 28547c478bd9Sstevel@tonic-gate /* Always send this to the read side of the queue */ 28557c478bd9Sstevel@tonic-gate q = RD(q); 28567c478bd9Sstevel@tonic-gate 28577c478bd9Sstevel@tonic-gate TILOG("tim_send_ioc_error_ack: prim = %d\n", tp->tim_saved_prim); 28587c478bd9Sstevel@tonic-gate 28597c478bd9Sstevel@tonic-gate if (tp->tim_saved_prim != error_prim) { 28607c478bd9Sstevel@tonic-gate putnext(q, mp); 28617c478bd9Sstevel@tonic-gate } else if (error_prim == T_CAPABILITY_REQ) { 28627c478bd9Sstevel@tonic-gate TILOG("timodrproc: T_ERROR_ACK/T_CAPABILITY_REQ\n", 0); 28637c478bd9Sstevel@tonic-gate ASSERT(tp->tim_iocsave->b_cont == NULL); 28647c478bd9Sstevel@tonic-gate 28657c478bd9Sstevel@tonic-gate tim_tcap_genreply(q, tp); 28667c478bd9Sstevel@tonic-gate freemsg(mp); 28677c478bd9Sstevel@tonic-gate } else { 28687c478bd9Sstevel@tonic-gate struct iocblk *iocbp = (struct iocblk *)tp->tim_iocsave->b_rptr; 28697c478bd9Sstevel@tonic-gate 28707c478bd9Sstevel@tonic-gate TILOG("tim_send_ioc_error_ack: T_ERROR_ACK: prim %d\n", 28717c478bd9Sstevel@tonic-gate error_prim); 28727c478bd9Sstevel@tonic-gate ASSERT(tp->tim_iocsave->b_cont == NULL); 28737c478bd9Sstevel@tonic-gate 28747c478bd9Sstevel@tonic-gate switch (error_prim) { 28757c478bd9Sstevel@tonic-gate default: 28767c478bd9Sstevel@tonic-gate TILOG("timodrproc: Unknown T_ERROR_ACK: tlierror %d\n", 28777c478bd9Sstevel@tonic-gate tea->TLI_error); 28787c478bd9Sstevel@tonic-gate 28797c478bd9Sstevel@tonic-gate putnext(q, mp); 28807c478bd9Sstevel@tonic-gate break; 28817c478bd9Sstevel@tonic-gate 28827c478bd9Sstevel@tonic-gate case T_INFO_REQ: 28837c478bd9Sstevel@tonic-gate case T_SVR4_OPTMGMT_REQ: 28847c478bd9Sstevel@tonic-gate case T_OPTMGMT_REQ: 28857c478bd9Sstevel@tonic-gate case O_T_BIND_REQ: 28867c478bd9Sstevel@tonic-gate case T_BIND_REQ: 28877c478bd9Sstevel@tonic-gate case T_UNBIND_REQ: 28887c478bd9Sstevel@tonic-gate case T_ADDR_REQ: 28897c478bd9Sstevel@tonic-gate case T_CAPABILITY_REQ: 28907c478bd9Sstevel@tonic-gate 28917c478bd9Sstevel@tonic-gate TILOG("ioc_err_ack: T_ERROR_ACK: tlierror %x\n", 28927c478bd9Sstevel@tonic-gate tea->TLI_error); 28937c478bd9Sstevel@tonic-gate 28947c478bd9Sstevel@tonic-gate /* get saved ioctl msg and set values */ 28957c478bd9Sstevel@tonic-gate iocbp->ioc_count = 0; 28967c478bd9Sstevel@tonic-gate iocbp->ioc_error = 0; 28977c478bd9Sstevel@tonic-gate iocbp->ioc_rval = tea->TLI_error; 28987c478bd9Sstevel@tonic-gate if (iocbp->ioc_rval == TSYSERR) 28997c478bd9Sstevel@tonic-gate iocbp->ioc_rval |= tea->UNIX_error << 8; 29007c478bd9Sstevel@tonic-gate tp->tim_iocsave->b_datap->db_type = M_IOCACK; 29017c478bd9Sstevel@tonic-gate freemsg(mp); 29027c478bd9Sstevel@tonic-gate putnext(q, tp->tim_iocsave); 29037c478bd9Sstevel@tonic-gate tp->tim_iocsave = NULL; 29047c478bd9Sstevel@tonic-gate tp->tim_saved_prim = -1; 29057c478bd9Sstevel@tonic-gate tp->tim_flags &= ~(WAITIOCACK | TI_CAP_RECVD | 29067c478bd9Sstevel@tonic-gate CAP_WANTS_INFO | WAIT_IOCINFOACK); 29077c478bd9Sstevel@tonic-gate break; 29087c478bd9Sstevel@tonic-gate } 29097c478bd9Sstevel@tonic-gate } 29107c478bd9Sstevel@tonic-gate } 29117c478bd9Sstevel@tonic-gate 29127c478bd9Sstevel@tonic-gate /* 29137c478bd9Sstevel@tonic-gate * Send reply to a usual message or ioctl message upstream. 29147c478bd9Sstevel@tonic-gate * Should be called from the read side only. 29157c478bd9Sstevel@tonic-gate */ 29167c478bd9Sstevel@tonic-gate static void 29177c478bd9Sstevel@tonic-gate tim_send_reply(queue_t *q, mblk_t *mp, struct tim_tim *tp, t_scalar_t prim) 29187c478bd9Sstevel@tonic-gate { 29197c478bd9Sstevel@tonic-gate ASSERT(mp != NULL && q != NULL && tp != NULL); 29207c478bd9Sstevel@tonic-gate ASSERT(q == RD(q)); 29217c478bd9Sstevel@tonic-gate 29227c478bd9Sstevel@tonic-gate /* Restore db_type - recover() might have changed it */ 29237c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_PCPROTO; 29247c478bd9Sstevel@tonic-gate 29257c478bd9Sstevel@tonic-gate if (((tp->tim_flags & WAITIOCACK) == 0) || (tp->tim_saved_prim != prim)) 29267c478bd9Sstevel@tonic-gate putnext(q, mp); 29277c478bd9Sstevel@tonic-gate else { 29287c478bd9Sstevel@tonic-gate ASSERT(tp->tim_iocsave != NULL); 29297c478bd9Sstevel@tonic-gate tim_ioctl_send_reply(q, tp->tim_iocsave, mp); 29307c478bd9Sstevel@tonic-gate tp->tim_iocsave = NULL; 29317c478bd9Sstevel@tonic-gate tp->tim_saved_prim = -1; 29327c478bd9Sstevel@tonic-gate tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 29337c478bd9Sstevel@tonic-gate TI_CAP_RECVD | CAP_WANTS_INFO); 29347c478bd9Sstevel@tonic-gate } 29357c478bd9Sstevel@tonic-gate } 29367c478bd9Sstevel@tonic-gate 29377c478bd9Sstevel@tonic-gate /* 29387c478bd9Sstevel@tonic-gate * Reply to TI_SYNC reequest without sending anything downstream. 29397c478bd9Sstevel@tonic-gate */ 29407c478bd9Sstevel@tonic-gate static void 29417c478bd9Sstevel@tonic-gate tim_answer_ti_sync(queue_t *q, mblk_t *mp, struct tim_tim *tp, 29427c478bd9Sstevel@tonic-gate mblk_t *ackmp, uint32_t tsr_flags) 29437c478bd9Sstevel@tonic-gate { 29447c478bd9Sstevel@tonic-gate struct ti_sync_ack *tsap; 29457c478bd9Sstevel@tonic-gate 29467c478bd9Sstevel@tonic-gate ASSERT(q != NULL && q == WR(q) && ackmp != NULL); 29477c478bd9Sstevel@tonic-gate 29487c478bd9Sstevel@tonic-gate tsap = (struct ti_sync_ack *)ackmp->b_rptr; 29497c478bd9Sstevel@tonic-gate bzero(tsap, sizeof (struct ti_sync_ack)); 29507c478bd9Sstevel@tonic-gate ackmp->b_wptr = ackmp->b_rptr + sizeof (struct ti_sync_ack); 29517c478bd9Sstevel@tonic-gate 29527c478bd9Sstevel@tonic-gate if (tsr_flags == 0 || 29537c478bd9Sstevel@tonic-gate (tsr_flags & ~(TSRF_QLEN_REQ | TSRF_IS_EXP_IN_RCVBUF)) != 0) { 29547c478bd9Sstevel@tonic-gate /* 29557c478bd9Sstevel@tonic-gate * unsupported/bad flag setting 29567c478bd9Sstevel@tonic-gate * or no flag set. 29577c478bd9Sstevel@tonic-gate */ 29587c478bd9Sstevel@tonic-gate TILOG("timodwproc: unsupported/bad flag setting %x\n", 29597c478bd9Sstevel@tonic-gate tsr_flags); 29607c478bd9Sstevel@tonic-gate freemsg(ackmp); 29617c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 29627c478bd9Sstevel@tonic-gate return; 29637c478bd9Sstevel@tonic-gate } 29647c478bd9Sstevel@tonic-gate 29657c478bd9Sstevel@tonic-gate if ((tsr_flags & TSRF_QLEN_REQ) != 0) 29667c478bd9Sstevel@tonic-gate tsap->tsa_qlen = tp->tim_backlog; 29677c478bd9Sstevel@tonic-gate 29687c478bd9Sstevel@tonic-gate if ((tsr_flags & TSRF_IS_EXP_IN_RCVBUF) != 0 && 29697c478bd9Sstevel@tonic-gate ti_expind_on_rdqueues(RD(q))) { 29707c478bd9Sstevel@tonic-gate /* 29717c478bd9Sstevel@tonic-gate * Expedited data is queued on 29727c478bd9Sstevel@tonic-gate * the stream read side 29737c478bd9Sstevel@tonic-gate */ 29747c478bd9Sstevel@tonic-gate tsap->tsa_flags |= TSAF_EXP_QUEUED; 29757c478bd9Sstevel@tonic-gate } 29767c478bd9Sstevel@tonic-gate 29777c478bd9Sstevel@tonic-gate tim_ioctl_send_reply(q, mp, ackmp); 29787c478bd9Sstevel@tonic-gate tp->tim_iocsave = NULL; 29797c478bd9Sstevel@tonic-gate tp->tim_saved_prim = -1; 29807c478bd9Sstevel@tonic-gate tp->tim_flags &= ~(WAITIOCACK | WAIT_IOCINFOACK | 29817c478bd9Sstevel@tonic-gate TI_CAP_RECVD | CAP_WANTS_INFO); 29827c478bd9Sstevel@tonic-gate } 29837c478bd9Sstevel@tonic-gate 29847c478bd9Sstevel@tonic-gate /* 29857c478bd9Sstevel@tonic-gate * Send TPI message from IOCTL message, ssave original ioctl header and TPI 29867c478bd9Sstevel@tonic-gate * message type. Should be called from write side only. 29877c478bd9Sstevel@tonic-gate */ 29887c478bd9Sstevel@tonic-gate static void 29897c478bd9Sstevel@tonic-gate tim_send_ioctl_tpi_msg(queue_t *q, mblk_t *mp, struct tim_tim *tp, 29907c478bd9Sstevel@tonic-gate struct iocblk *iocb) 29917c478bd9Sstevel@tonic-gate { 29927c478bd9Sstevel@tonic-gate mblk_t *tmp; 29937c478bd9Sstevel@tonic-gate int ioc_cmd = iocb->ioc_cmd; 29947c478bd9Sstevel@tonic-gate 29957c478bd9Sstevel@tonic-gate ASSERT(q != NULL && mp != NULL && tp != NULL); 29967c478bd9Sstevel@tonic-gate ASSERT(q == WR(q)); 29977c478bd9Sstevel@tonic-gate ASSERT(mp->b_cont != NULL); 29987c478bd9Sstevel@tonic-gate 29997c478bd9Sstevel@tonic-gate tp->tim_iocsave = mp; 30007c478bd9Sstevel@tonic-gate tmp = mp->b_cont; 30017c478bd9Sstevel@tonic-gate 30027c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 30037c478bd9Sstevel@tonic-gate tp->tim_flags |= WAITIOCACK; 30047c478bd9Sstevel@tonic-gate tp->tim_saved_prim = ((union T_primitives *)tmp->b_rptr)->type; 30057c478bd9Sstevel@tonic-gate 30067c478bd9Sstevel@tonic-gate /* 30077c478bd9Sstevel@tonic-gate * For TI_GETINFO, the attached message is a T_INFO_REQ 30087c478bd9Sstevel@tonic-gate * For TI_SYNC, we generate the T_INFO_REQ message above 30097c478bd9Sstevel@tonic-gate * For TI_CAPABILITY the attached message is either 30107c478bd9Sstevel@tonic-gate * T_CAPABILITY_REQ or T_INFO_REQ. 30117c478bd9Sstevel@tonic-gate * Among TPI request messages possible, 30127c478bd9Sstevel@tonic-gate * T_INFO_REQ/T_CAPABILITY_ACK messages are a M_PCPROTO, rest 30137c478bd9Sstevel@tonic-gate * are M_PROTO 30147c478bd9Sstevel@tonic-gate */ 30157c478bd9Sstevel@tonic-gate if (ioc_cmd == TI_GETINFO || ioc_cmd == TI_SYNC || 30167c478bd9Sstevel@tonic-gate ioc_cmd == TI_CAPABILITY) { 30177c478bd9Sstevel@tonic-gate tmp->b_datap->db_type = M_PCPROTO; 30187c478bd9Sstevel@tonic-gate } else { 30197c478bd9Sstevel@tonic-gate tmp->b_datap->db_type = M_PROTO; 30207c478bd9Sstevel@tonic-gate } 30217c478bd9Sstevel@tonic-gate 30227c478bd9Sstevel@tonic-gate /* Verify credentials in STREAM */ 30237c478bd9Sstevel@tonic-gate ASSERT(iocb->ioc_cr == NULL || iocb->ioc_cr == DB_CRED(tmp)); 30247c478bd9Sstevel@tonic-gate 30257c478bd9Sstevel@tonic-gate TILOG("timodwproc: sending down %d\n", tp->tim_saved_prim); 30267c478bd9Sstevel@tonic-gate putnext(q, tmp); 30277c478bd9Sstevel@tonic-gate } 30287c478bd9Sstevel@tonic-gate 30297c478bd9Sstevel@tonic-gate static void 30307c478bd9Sstevel@tonic-gate tim_clear_peer(struct tim_tim *tp) 30317c478bd9Sstevel@tonic-gate { 30327c478bd9Sstevel@tonic-gate mutex_enter(&tp->tim_mutex); 30337c478bd9Sstevel@tonic-gate if (tp->tim_peercred != NULL) { 30347c478bd9Sstevel@tonic-gate crfree(tp->tim_peercred); 30357c478bd9Sstevel@tonic-gate tp->tim_peercred = NULL; 30367c478bd9Sstevel@tonic-gate } 30377c478bd9Sstevel@tonic-gate tp->tim_peerlen = 0; 30387c478bd9Sstevel@tonic-gate mutex_exit(&tp->tim_mutex); 30397c478bd9Sstevel@tonic-gate } 3040