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 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * Copyright 1993-2003 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 <rpc/trace.h> 35 #include <errno.h> 36 #include <unistd.h> 37 #include <sys/stream.h> 38 #include <stropts.h> 39 #define _SUN_TPI_VERSION 2 40 #include <sys/tihdr.h> 41 #include <sys/timod.h> 42 #include <xti.h> 43 #include <assert.h> 44 #include "tx.h" 45 46 int 47 _tx_look(int fd, int api_semantics) 48 { 49 int state; 50 int sv_errno; 51 int do_expinline_peek; /* unusual XTI specific processing */ 52 struct _ti_user *tiptr; 53 54 trace2(TR_t_look, 0, fd); 55 if ((tiptr = _t_checkfd(fd, 0, api_semantics)) == NULL) { 56 sv_errno = errno; 57 trace2(TR__t_look, 1, fd); 58 errno = sv_errno; 59 return (-1); 60 } 61 sig_mutex_lock(&tiptr->ti_lock); 62 63 if (_T_IS_XTI(api_semantics)) 64 do_expinline_peek = 1; 65 else 66 do_expinline_peek = 0; 67 state = _t_look_locked(fd, tiptr, do_expinline_peek, api_semantics); 68 69 sv_errno = errno; 70 71 sig_mutex_unlock(&tiptr->ti_lock); 72 trace2(TR_t_look, 1, fd); 73 errno = sv_errno; 74 return (state); 75 } 76 77 /* 78 * _t_look_locked() assumes tiptr->ti_lock lock is already held and signals 79 * already blocked in MT case. 80 * Intended for use by other TLI routines only. 81 */ 82 int 83 _t_look_locked( 84 int fd, 85 struct _ti_user *tiptr, 86 int do_expinline_peek, 87 int api_semantics 88 ) 89 { 90 struct strpeek strpeek; 91 int retval, sv_errno; 92 union T_primitives *pptr; 93 t_scalar_t type; 94 t_scalar_t ctltype; 95 96 trace2(TR__t_look_locked, 0, fd); 97 98 assert(MUTEX_HELD(&tiptr->ti_lock)); 99 100 #ifdef notyet 101 if (_T_IS_XTI(api_semantics)) { 102 /* 103 * XTI requires the strange T_GODATA and T_GOEXDATA 104 * events which are almost brain-damaged but thankfully 105 * not tested. Anyone feeling the need for those should 106 * consider the need for using non-blocking endpoint. 107 * Probably introduced at the behest of some weird-os 108 * vendor which did not understand the non-blocking endpoint 109 * option. 110 * We choose not to implment these mis-features. 111 * Here is the plan-of-action (POA)if we are ever forced 112 * to implement these. 113 * - When returning TFLOW set state to indicate if it was 114 * a normal or expedited data send attempt. 115 * - In routines that set TFLOW, clear the above set state 116 * on each entry/reentry 117 * - In this routine, if that state flag is set, 118 * do a I_CANPUT on appropriate band to to see if it 119 * is writeable. If that indicates that the band is 120 * writeable, return T_GODATA or T_GOEXDATA event. 121 * 122 * Actions are also influenced by whether T_EXDATA_REQ stays 123 * band 1 or goes to band 0 if EXPINLINE is set 124 * 125 * We will also need to sort out if "write side" events 126 * (such as T_GODATA/T_GOEXDATA) take precedence over 127 * all other events (all read side) or not. 128 */ 129 } 130 #endif /* notyet */ 131 132 strpeek.ctlbuf.maxlen = (int)sizeof (ctltype); 133 strpeek.ctlbuf.len = 0; 134 strpeek.ctlbuf.buf = (char *)&ctltype; 135 strpeek.databuf.maxlen = 0; 136 strpeek.databuf.len = 0; 137 strpeek.databuf.buf = NULL; 138 strpeek.flags = 0; 139 140 do { 141 retval = _ioctl(fd, I_PEEK, &strpeek); 142 } while (retval < 0 && errno == EINTR); 143 144 if (retval < 0) { 145 sv_errno = errno; 146 trace2(TR__t_look_locked, 1, fd); 147 errno = sv_errno; 148 if (_T_IS_TLI(api_semantics)) { 149 /* 150 * This return of T_ERROR event is ancient 151 * SVR3 TLI semantics and not documented for 152 * current SVR4 TLI interface. 153 * Fixing this will impact some apps 154 * (e.g. nfsd,lockd) in ON consolidation 155 * so they need to be fixed first before TLI 156 * can be fixed. 157 * XXX Should we never fix this because it might 158 * break apps in field ? 159 */ 160 return (T_ERROR); 161 } else { 162 /* 163 * XTI semantics (also identical to documented, 164 * but not implemented TLI semantics). 165 */ 166 t_errno = TSYSERR; 167 return (-1); 168 } 169 } 170 171 /* 172 * if something there and cntl part also there 173 */ 174 if ((tiptr->ti_lookcnt > 0) || 175 ((retval > 0) && (strpeek.ctlbuf.len >= (int)sizeof (t_scalar_t)))) { 176 pptr = (union T_primitives *)strpeek.ctlbuf.buf; 177 if (tiptr->ti_lookcnt > 0) { 178 type = *((t_scalar_t *)tiptr->ti_lookbufs.tl_lookcbuf); 179 /* 180 * If message on stream head is a T_DISCON_IND, that 181 * has priority over a T_ORDREL_IND in the look 182 * buffer. 183 * (This assumes that T_ORDREL_IND can only be in the 184 * first look buffer in the list) 185 */ 186 if ((type == T_ORDREL_IND) && retval && 187 (pptr->type == T_DISCON_IND)) { 188 type = pptr->type; 189 /* 190 * Blow away T_ORDREL_IND 191 */ 192 _t_free_looklist_head(tiptr); 193 } 194 } else 195 type = pptr->type; 196 197 switch (type) { 198 199 case T_CONN_IND: 200 trace2(TR__t_look_locked, 1, fd); 201 return (T_LISTEN); 202 203 case T_CONN_CON: 204 trace2(TR__t_look_locked, 1, fd); 205 return (T_CONNECT); 206 207 case T_DISCON_IND: 208 trace2(TR__t_look_locked, 1, fd); 209 return (T_DISCONNECT); 210 211 case T_DATA_IND: { 212 int event = T_DATA; 213 int retval, exp_on_q; 214 215 if (do_expinline_peek && 216 (tiptr->ti_prov_flag & EXPINLINE)) { 217 assert(_T_IS_XTI(api_semantics)); 218 retval = _t_expinline_queued(fd, &exp_on_q); 219 if (retval < 0) { 220 t_errno = TSYSERR; 221 sv_errno = errno; 222 trace2(TR__t_look_locked, 1, fd); 223 errno = sv_errno; 224 return (-1); 225 } 226 if (exp_on_q) 227 event = T_EXDATA; 228 } 229 trace2(TR__t_look_locked, 1, fd); 230 return (event); 231 } 232 233 case T_UNITDATA_IND: 234 trace2(TR__t_look_locked, 1, fd); 235 return (T_DATA); 236 237 case T_EXDATA_IND: 238 trace2(TR__t_look_locked, 1, fd); 239 return (T_EXDATA); 240 241 case T_UDERROR_IND: 242 trace2(TR__t_look_locked, 1, fd); 243 return (T_UDERR); 244 245 case T_ORDREL_IND: 246 trace2(TR__t_look_locked, 1, fd); 247 return (T_ORDREL); 248 249 default: 250 t_errno = TSYSERR; 251 trace2(TR__t_look_locked, 1, fd); 252 errno = EPROTO; 253 return (-1); 254 } 255 } 256 257 /* 258 * if something there put no control part 259 * it must be data on the stream head. 260 */ 261 if ((retval > 0) && (strpeek.ctlbuf.len <= 0)) { 262 int event = T_DATA; 263 int retval, exp_on_q; 264 265 if (do_expinline_peek && 266 (tiptr->ti_prov_flag & EXPINLINE)) { 267 assert(_T_IS_XTI(api_semantics)); 268 retval = _t_expinline_queued(fd, &exp_on_q); 269 if (retval < 0) { 270 sv_errno = errno; 271 trace2(TR__t_look_locked, 1, fd); 272 errno = sv_errno; 273 return (-1); 274 } 275 if (exp_on_q) 276 event = T_EXDATA; 277 } 278 trace2(TR__t_look_locked, 1, fd); 279 return (event); 280 } 281 282 /* 283 * if msg there and control 284 * part not large enough to determine type? 285 * it must be illegal TLI message 286 */ 287 if ((retval > 0) && (strpeek.ctlbuf.len > 0)) { 288 t_errno = TSYSERR; 289 trace2(TR__t_look_locked, 1, fd); 290 errno = EPROTO; 291 return (-1); 292 } 293 trace2(TR__t_look_locked, 1, fd); 294 return (0); 295 } 296