xref: /titanic_51/usr/src/lib/libnsl/nsl/t_look.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
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