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
_tx_look(int fd,int api_semantics)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
_t_look_locked(int fd,struct _ti_user * tiptr,int do_expinline_peek,int api_semantics)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 }
252