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