xref: /illumos-gate/usr/src/lib/libnsl/dial/interface.c (revision 141040e8a310da49386b596573e5dde5580572ec)
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 /*
34  * interface( label )
35  *	provide alternate definitions for the I/O functions through global
36  *	interfaces.
37  */
38 #include "mt.h"
39 #include "uucp.h"
40 #include <unistd.h>
41 
42 #ifdef TLI
43 #include <tiuser.h>
44 #endif /*  TLI  */
45 
46 static void	sethup(int);
47 static int	restline(void);
48 static int	usetup(int, int *, int *);
49 static int	uteardown(int, int, int);
50 
51 static ssize_t	(*Read)() = read,
52 	(*Write)() = write;
53 static int	(*Ioctl)(int, int, ...) = ioctl,
54 	(*Setup)() = usetup;
55 
56 #ifdef TLI
57 static void tfaillog(int fd, const char *s);
58 static void show_tlook(int);
59 static ssize_t	tread(int, char *, unsigned);
60 static ssize_t	twrite(int, char *, unsigned);
61 static int tioctl(int, int, ...);
62 static int tsetup(int, int *, int *); /* TLI setup without streams module */
63 static int tssetup(int, int *, int *); /* TLI setup with streams module */
64 static int tteardown(int, int, int); /* TLI teardown, works with either setup */
65 #endif /*  TLI  */
66 
67 /*
68  *	The IN_label in Interface[] imply different caller routines:
69  *	e.g. tlicall().
70  *	If so, the names here and the names in callers.c must match.
71  */
72 static struct Interface {
73 	const	char	*IN_label;	/* interface name */
74 	ssize_t	(*IN_read)();		/* read function */
75 	ssize_t	(*IN_write)();		/* write function */
76 	int	(*IN_ioctl)(int, int, ...);
77 	int	(*IN_setup)();		/* setup function, called before */
78 					/* first i/o operation */
79 	int	(*IN_teardown)();	/* teardown function, called after */
80 					/* last i/o operation */
81 } Interface[] = {
82 			/* vanilla UNIX */
83 		{ "UNIX", read, write, ioctl, usetup, uteardown },
84 #ifdef TLI
85 			/* AT&T Transport Interface Library WITHOUT streams */
86 		{ "TLI", tread, twrite, tioctl, tsetup, tteardown },
87 #ifdef TLIS
88 			/* AT&T Transport Interface Library WITH streams */
89 		{ "TLIS", read, write, tioctl, tssetup, uteardown },
90 #endif /*  TLIS  */
91 #endif /*  TLI  */
92 		{ 0, 0, 0, 0, 0, 0 }
93 	};
94 
95 
96 static int
97 interface(const char *label)
98 {
99 	int	i;
100 
101 	for (i = 0;  Interface[i].IN_label;  ++i) {
102 		if (strcmp(Interface[i].IN_label, label) == 0) {
103 			Read = Interface[i].IN_read;
104 			Write = Interface[i].IN_write;
105 			Ioctl = Interface[i].IN_ioctl;
106 			Setup = Interface[i].IN_setup;
107 			DEBUG(5, "set interface %s\n", label);
108 			return (0);
109 		}
110 	}
111 	return (FAIL);
112 }
113 
114 /*
115  *	usetup - vanilla unix setup routine
116  */
117 static int
118 usetup(int role, int *fdreadp, int *fdwritep)
119 {
120 	if (role == SLAVE) {
121 		*fdreadp = 0;
122 		*fdwritep = 1;
123 		/* 2 has been re-opened to RMTDEBUG in main() */
124 	}
125 	return (SUCCESS);
126 }
127 
128 /*
129  *	uteardown - vanilla unix teardown routine
130  */
131 static int
132 uteardown(int role, int fdread, int fdwrite)
133 {
134 	char *ttyn;
135 
136 	if (role == SLAVE) {
137 		(void) restline();
138 		sethup(0);
139 	}
140 	if (fdread != -1) {
141 		ttyn = ttyname(fdread);
142 		if (ttyn != NULL)
143 			/* can fail, but who cares? */
144 			(void) chmod(ttyn, Dev_mode);
145 		(void) close(fdread);
146 		(void) close(fdwrite);
147 	}
148 	return (SUCCESS);
149 }
150 
151 #ifdef TLI
152 /*
153  *	tread - tli read routine
154  */
155 static ssize_t
156 tread(int fd, char *buf, unsigned nbytes)
157 {
158 	int		rcvflags;
159 
160 	return ((ssize_t)t_rcv(fd, buf, nbytes, &rcvflags));
161 }
162 
163 /*
164  *	twrite - tli write routine
165  */
166 #define	N_CHECK	100
167 static ssize_t
168 twrite(int fd, char *buf, unsigned nbytes)
169 {
170 	int			i, ret;
171 	static int		n_writ, got_info;
172 	static struct t_info	info;
173 
174 	if (got_info == 0) {
175 		if (t_getinfo(fd, &info) != 0) {
176 			tfaillog(fd, "twrite: t_getinfo\n");
177 			return (FAIL);
178 		}
179 		got_info = 1;
180 	}
181 
182 	/* on every N_CHECKth call, check that are still in DATAXFER state */
183 	if (++n_writ == N_CHECK) {
184 		n_writ = 0;
185 		if (t_getstate(fd) != T_DATAXFER)
186 			return (FAIL);
187 	}
188 
189 	if (info.tsdu <= 0 || nbytes <= info.tsdu)
190 		return ((ssize_t)t_snd(fd, buf, nbytes, NULL));
191 	/* if get here, then there is a limit on transmit size	*/
192 	/* (info.tsdu > 0) and buf exceeds it			*/
193 	i = ret = 0;
194 	while (nbytes >= info.tsdu) {
195 		if ((ret = t_snd(fd,  &buf[i], info.tsdu, NULL)) != info.tsdu)
196 			return ((ssize_t)(ret >= 0 ? (i + ret) : ret));
197 		i += info.tsdu;
198 		nbytes -= info.tsdu;
199 	}
200 	if (nbytes != 0) {
201 		if ((ret = t_snd(fd,  &buf[i], nbytes, NULL)) != nbytes)
202 			return ((ssize_t)(ret >= 0 ? (i + ret) : ret));
203 		i += nbytes;
204 	}
205 	return ((ssize_t)i);
206 }
207 
208 /*
209  *	tioctl - stub for tli ioctl routine
210  */
211 /* ARGSUSED */
212 static int
213 tioctl(int fd, int request, ...)
214 {
215 	return (SUCCESS);
216 }
217 
218 /*
219  *	tsetup - tli setup routine
220  *	note blatant assumption that *fdreadp == *fdwritep == 0
221  */
222 static int
223 tsetup(int role, int *fdreadp, int *fdwritep)
224 {
225 	if (role == SLAVE) {
226 		*fdreadp = 0;
227 		*fdwritep = 1;
228 		/* 2 has been re-opened to RMTDEBUG in main() */
229 		errno = t_errno = 0;
230 		if (t_sync(*fdreadp) == -1 || t_sync(*fdwritep) == -1) {
231 			tfaillog(*fdreadp, "tsetup: t_sync\n");
232 			return (FAIL);
233 		}
234 	}
235 	return (SUCCESS);
236 }
237 
238 /*
239  *	tteardown - tli shutdown routine
240  */
241 /* ARGSUSED */
242 static int
243 tteardown(int role, int fdread, int fdwrite)
244 {
245 	(void) t_unbind(fdread);
246 	(void) t_close(fdread);
247 	return (SUCCESS);
248 }
249 
250 #ifdef TLIS
251 /*
252  *	tssetup - tli, with streams module, setup routine
253  *	note blatant assumption that *fdreadp == *fdwritep
254  */
255 static int
256 tssetup(int role, int *fdreadp, int *fdwritep)
257 {
258 	if (role == SLAVE) {
259 		*fdreadp = 0;
260 		*fdwritep = 1;
261 		/* 2 has been re-opened to RMTDEBUG in main() */
262 		DEBUG(5, "tssetup: SLAVE mode: leaving ok\n%s", "");
263 		return (SUCCESS);
264 	}
265 
266 	DEBUG(4, "tssetup: MASTER mode: leaving ok\n%s", "");
267 	return (SUCCESS);
268 }
269 
270 /*
271  *	Report why a TLI call failed.
272  */
273 static void
274 tfaillog(int fd, const char *s)
275 {
276 	char	fmt[ BUFSIZ ];
277 
278 	if (0 < t_errno && t_errno < t_nerr) {
279 		(void) snprintf(fmt, sizeof (fmt), "%s: %%s\n", s);
280 		DEBUG(5, fmt, t_errlist[t_errno]);
281 		logent(s, t_errlist[t_errno]);
282 		if (t_errno == TSYSERR) {
283 			(void) strcpy(fmt, "tlicall: system error: %s\n");
284 			DEBUG(5, fmt, strerror(errno));
285 		} else if (t_errno == TLOOK) {
286 			show_tlook(fd);
287 		}
288 	} else {
289 		(void) snprintf(fmt, sizeof (fmt),
290 					"unknown tli error %d", t_errno);
291 		logent(s, fmt);
292 		(void) snprintf(fmt, sizeof (fmt),
293 					"%s: unknown tli error %d", s, t_errno);
294 		DEBUG(5, fmt, 0);
295 		(void) snprintf(fmt, sizeof (fmt), "%s: %%s\n", s);
296 		DEBUG(5, fmt, strerror(errno));
297 	}
298 }
299 
300 static void
301 show_tlook(int fd)
302 {
303 	int reason;
304 	const char *msg;
305 
306 /*
307  * Find out the current state of the interface.
308  */
309 	errno = t_errno = 0;
310 	switch (reason = t_getstate(fd)) {
311 	case T_UNBND:		msg = (const char *)"T_UNBIND";	break;
312 	case T_IDLE:		msg = (const char *)"T_IDLE";	break;
313 	case T_OUTCON:		msg = (const char *)"T_OUTCON";	break;
314 	case T_INCON:		msg = (const char *)"T_INCON";	break;
315 	case T_DATAXFER:	msg = (const char *)"T_DATAXFER"; break;
316 	case T_OUTREL:		msg = (const char *)"T_OUTREL";	break;
317 	case T_INREL:		msg = (const char *)"T_INREL";	break;
318 	default:		msg = NULL;		break;
319 	}
320 	if (msg == NULL)
321 		return;
322 	DEBUG(5, "state is %s", msg);
323 	switch (reason = t_look(fd)) {
324 	case -1:		msg = (const char *)""; break;
325 	case 0:			msg = (const char *)"NO ERROR"; break;
326 	case T_LISTEN:		msg = (const char *)"T_LISTEN"; break;
327 	case T_CONNECT:		msg = (const char *)"T_CONNECT"; break;
328 	case T_DATA:		msg = (const char *)"T_DATA";	 break;
329 	case T_EXDATA:		msg = (const char *)"T_EXDATA"; break;
330 	case T_DISCONNECT:	msg = (const char *)"T_DISCONNECT"; break;
331 	case T_ORDREL:		msg = (const char *)"T_ORDREL"; break;
332 	case T_ERROR:		msg = (const char *)"T_ERROR"; break;
333 	case T_UDERR:		msg = (const char *)"T_UDERR"; break;
334 	default:		msg = (const char *)"UNKNOWN ERROR"; break;
335 	}
336 	DEBUG(4, " reason is %s\n", msg);
337 
338 	if (reason == T_DISCONNECT) {
339 		struct t_discon	*dropped;
340 		if (((dropped =
341 			/* LINTED pointer cast */
342 			(struct t_discon *)t_alloc(fd, T_DIS, T_ALL)) == 0) ||
343 			(t_rcvdis(fd, dropped) == -1)) {
344 			if (dropped)
345 				(void) t_free((char *)dropped, T_DIS);
346 			return;
347 		}
348 		DEBUG(5, "disconnect reason #%d\n", dropped->reason);
349 		(void) t_free((char *)dropped, T_DIS);
350 	}
351 }
352 #endif /*  TLIS  */
353 #endif /*  TLI  */
354