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