1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 24 /* All Rights Reserved */ 25 26 /* 27 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 #include "mt.h" 34 #include <errno.h> 35 #include <unistd.h> 36 #include <sys/stream.h> 37 #include <stropts.h> 38 #define _SUN_TPI_VERSION 2 39 #include <sys/tihdr.h> 40 #include <sys/timod.h> 41 #include <xti.h> 42 #include <assert.h> 43 #include "tx.h" 44 45 int 46 _tx_look(int fd, int api_semantics) 47 { 48 int state; 49 int sv_errno; 50 int do_expinline_peek; /* unusual XTI specific processing */ 51 struct _ti_user *tiptr; 52 53 if ((tiptr = _t_checkfd(fd, 0, api_semantics)) == NULL) 54 return (-1); 55 sig_mutex_lock(&tiptr->ti_lock); 56 57 if (_T_IS_XTI(api_semantics)) 58 do_expinline_peek = 1; 59 else 60 do_expinline_peek = 0; 61 state = _t_look_locked(fd, tiptr, do_expinline_peek, api_semantics); 62 63 sv_errno = errno; 64 65 sig_mutex_unlock(&tiptr->ti_lock); 66 errno = sv_errno; 67 return (state); 68 } 69 70 /* 71 * _t_look_locked() assumes tiptr->ti_lock lock is already held and signals 72 * already blocked in MT case. 73 * Intended for use by other TLI routines only. 74 */ 75 int 76 _t_look_locked( 77 int fd, 78 struct _ti_user *tiptr, 79 int do_expinline_peek, 80 int api_semantics 81 ) 82 { 83 struct strpeek strpeek; 84 int retval; 85 union T_primitives *pptr; 86 t_scalar_t type; 87 t_scalar_t ctltype; 88 89 assert(MUTEX_HELD(&tiptr->ti_lock)); 90 91 #ifdef notyet 92 if (_T_IS_XTI(api_semantics)) { 93 /* 94 * XTI requires the strange T_GODATA and T_GOEXDATA 95 * events which are almost brain-damaged but thankfully 96 * not tested. Anyone feeling the need for those should 97 * consider the need for using non-blocking endpoint. 98 * Probably introduced at the behest of some weird-os 99 * vendor which did not understand the non-blocking endpoint 100 * option. 101 * We choose not to implment these mis-features. 102 * Here is the plan-of-action (POA)if we are ever forced 103 * to implement these. 104 * - When returning TFLOW set state to indicate if it was 105 * a normal or expedited data send attempt. 106 * - In routines that set TFLOW, clear the above set state 107 * on each entry/reentry 108 * - In this routine, if that state flag is set, 109 * do a I_CANPUT on appropriate band to to see if it 110 * is writeable. If that indicates that the band is 111 * writeable, return T_GODATA or T_GOEXDATA event. 112 * 113 * Actions are also influenced by whether T_EXDATA_REQ stays 114 * band 1 or goes to band 0 if EXPINLINE is set 115 * 116 * We will also need to sort out if "write side" events 117 * (such as T_GODATA/T_GOEXDATA) take precedence over 118 * all other events (all read side) or not. 119 */ 120 } 121 #endif /* notyet */ 122 123 strpeek.ctlbuf.maxlen = (int)sizeof (ctltype); 124 strpeek.ctlbuf.len = 0; 125 strpeek.ctlbuf.buf = (char *)&ctltype; 126 strpeek.databuf.maxlen = 0; 127 strpeek.databuf.len = 0; 128 strpeek.databuf.buf = NULL; 129 strpeek.flags = 0; 130 131 do { 132 retval = ioctl(fd, I_PEEK, &strpeek); 133 } while (retval < 0 && errno == EINTR); 134 135 if (retval < 0) { 136 if (_T_IS_TLI(api_semantics)) { 137 /* 138 * This return of T_ERROR event is ancient 139 * SVR3 TLI semantics and not documented for 140 * current SVR4 TLI interface. 141 * Fixing this will impact some apps 142 * (e.g. nfsd,lockd) in ON consolidation 143 * so they need to be fixed first before TLI 144 * can be fixed. 145 * XXX Should we never fix this because it might 146 * break apps in field ? 147 */ 148 return (T_ERROR); 149 } 150 /* 151 * XTI semantics (also identical to documented, 152 * but not implemented TLI semantics). 153 */ 154 t_errno = TSYSERR; 155 return (-1); 156 } 157 158 /* 159 * if something there and cntl part also there 160 */ 161 if ((tiptr->ti_lookcnt > 0) || 162 ((retval > 0) && (strpeek.ctlbuf.len >= (int)sizeof (t_scalar_t)))) { 163 /* LINTED pointer cast */ 164 pptr = (union T_primitives *)strpeek.ctlbuf.buf; 165 if (tiptr->ti_lookcnt > 0) { 166 /* LINTED pointer cast */ 167 type = *((t_scalar_t *)tiptr->ti_lookbufs.tl_lookcbuf); 168 /* 169 * If message on stream head is a T_DISCON_IND, that 170 * has priority over a T_ORDREL_IND in the look 171 * buffer. 172 * (This assumes that T_ORDREL_IND can only be in the 173 * first look buffer in the list) 174 */ 175 if ((type == T_ORDREL_IND) && retval && 176 (pptr->type == T_DISCON_IND)) { 177 type = pptr->type; 178 /* 179 * Blow away T_ORDREL_IND 180 */ 181 _t_free_looklist_head(tiptr); 182 } 183 } else 184 type = pptr->type; 185 186 switch (type) { 187 188 case T_CONN_IND: 189 return (T_LISTEN); 190 191 case T_CONN_CON: 192 return (T_CONNECT); 193 194 case T_DISCON_IND: 195 return (T_DISCONNECT); 196 197 case T_DATA_IND: { 198 int event = T_DATA; 199 int retval, exp_on_q; 200 201 if (do_expinline_peek && 202 (tiptr->ti_prov_flag & EXPINLINE)) { 203 assert(_T_IS_XTI(api_semantics)); 204 retval = _t_expinline_queued(fd, &exp_on_q); 205 if (retval < 0) { 206 t_errno = TSYSERR; 207 return (-1); 208 } 209 if (exp_on_q) 210 event = T_EXDATA; 211 } 212 return (event); 213 } 214 215 case T_UNITDATA_IND: 216 return (T_DATA); 217 218 case T_EXDATA_IND: 219 return (T_EXDATA); 220 221 case T_UDERROR_IND: 222 return (T_UDERR); 223 224 case T_ORDREL_IND: 225 return (T_ORDREL); 226 227 default: 228 t_errno = TSYSERR; 229 errno = EPROTO; 230 return (-1); 231 } 232 } 233 234 /* 235 * if something there put no control part 236 * it must be data on the stream head. 237 */ 238 if ((retval > 0) && (strpeek.ctlbuf.len <= 0)) { 239 int event = T_DATA; 240 int retval, exp_on_q; 241 242 if (do_expinline_peek && 243 (tiptr->ti_prov_flag & EXPINLINE)) { 244 assert(_T_IS_XTI(api_semantics)); 245 retval = _t_expinline_queued(fd, &exp_on_q); 246 if (retval < 0) 247 return (-1); 248 if (exp_on_q) 249 event = T_EXDATA; 250 } 251 return (event); 252 } 253 254 /* 255 * if msg there and control 256 * part not large enough to determine type? 257 * it must be illegal TLI message 258 */ 259 if ((retval > 0) && (strpeek.ctlbuf.len > 0)) { 260 t_errno = TSYSERR; 261 errno = EPROTO; 262 return (-1); 263 } 264 return (0); 265 } 266