stream.c revision b9fe011cdfb0a3014e68a6e82007b6c2703a340b
1/*
2 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
3 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 *	$Id$
29 */
30
31#include "defs.h"
32#include <sys/syscall.h>
33
34#ifdef HAVE_POLL_H
35#include <poll.h>
36#endif
37#ifdef HAVE_SYS_POLL_H
38#include <sys/poll.h>
39#endif
40#ifdef HAVE_STROPTS_H
41#include <stropts.h>
42#endif
43#ifdef HAVE_SYS_CONF_H
44#include <sys/conf.h>
45#endif
46#ifdef HAVE_SYS_STREAM_H
47#include <sys/stream.h>
48#endif
49#ifdef HAVE_SYS_TIHDR_H
50#include <sys/tihdr.h>
51#endif
52
53#if defined(HAVE_SYS_STREAM_H) || defined(LINUX) || defined(FREEBSD)
54
55#ifndef HAVE_STROPTS_H
56#define RS_HIPRI 1
57struct strbuf {
58        int     maxlen;                 /* no. of bytes in buffer */
59        int     len;                    /* no. of bytes returned */
60        char    *buf;                   /* pointer to data */
61};
62#define MORECTL 1
63#define MOREDATA 2
64#endif /* !HAVE_STROPTS_H */
65
66#ifdef HAVE_SYS_TIUSER_H
67#include <sys/tiuser.h>
68#include <sys/sockmod.h>
69#include <sys/timod.h>
70#endif /* HAVE_SYS_TIUSER_H */
71
72#ifndef FREEBSD
73static const struct xlat msgflags[] = {
74	{ RS_HIPRI,	"RS_HIPRI"	},
75	{ 0,		NULL		},
76};
77
78
79static void
80printstrbuf(tcp, sbp, getting)
81struct tcb *tcp;
82struct strbuf *sbp;
83int getting;
84{
85	if (sbp->maxlen == -1 && getting)
86		tprintf("{maxlen=-1}");
87	else {
88		tprintf("{");
89		if (getting)
90			tprintf("maxlen=%d, ", sbp->maxlen);
91		tprintf("len=%d, buf=", sbp->len);
92		printstr(tcp, (unsigned long) sbp->buf, sbp->len);
93		tprintf("}");
94	}
95}
96
97static void
98printstrbufarg(tcp, arg, getting)
99struct tcb *tcp;
100int arg;
101int getting;
102{
103	struct strbuf buf;
104
105	if (arg == 0)
106		tprintf("NULL");
107	else if (umove(tcp, arg, &buf) < 0)
108		tprintf("{...}");
109	else
110		printstrbuf(tcp, &buf, getting);
111	tprintf(", ");
112}
113
114int
115sys_putmsg(tcp)
116struct tcb *tcp;
117{
118	int i;
119
120	if (entering(tcp)) {
121		/* fd */
122		tprintf("%ld, ", tcp->u_arg[0]);
123		/* control and data */
124		for (i = 1; i < 3; i++)
125			printstrbufarg(tcp, tcp->u_arg[i], 0);
126		/* flags */
127		printflags(msgflags, tcp->u_arg[3], "RS_???");
128	}
129	return 0;
130}
131
132#if defined(SPARC) || defined(SPARC64) || defined(SUNOS4) || defined(SVR4)
133int
134sys_getmsg(tcp)
135struct tcb *tcp;
136{
137	int i, flags;
138
139	if (entering(tcp)) {
140		/* fd */
141		tprintf("%lu, ", tcp->u_arg[0]);
142	} else {
143		if (syserror(tcp)) {
144			tprintf("%#lx, %#lx, %#lx",
145				tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3]);
146			return 0;
147		}
148		/* control and data */
149		for (i = 1; i < 3; i++)
150			printstrbufarg(tcp, tcp->u_arg[i], 1);
151		/* pointer to flags */
152		if (tcp->u_arg[3] == 0)
153			tprintf("NULL");
154		else if (umove(tcp, tcp->u_arg[3], &flags) < 0)
155			tprintf("[?]");
156		else {
157			tprintf("[");
158			printflags(msgflags, flags, "RS_???");
159			tprintf("]");
160		}
161		/* decode return value */
162		switch (tcp->u_rval) {
163		case MORECTL:
164			tcp->auxstr = "MORECTL";
165			break;
166		case MORECTL|MOREDATA:
167			tcp->auxstr = "MORECTL|MOREDATA";
168			break;
169		case MOREDATA:
170			tcp->auxstr = "MORECTL";
171			break;
172		default:
173			tcp->auxstr = NULL;
174			break;
175		}
176	}
177	return RVAL_HEX | RVAL_STR;
178}
179#endif /* SPARC || SPARC64 || SUNOS4 || SVR4 */
180
181#if defined SYS_putpmsg || defined SYS_getpmsg
182static const struct xlat pmsgflags[] = {
183#ifdef MSG_HIPRI
184	{ MSG_HIPRI,	"MSG_HIPRI"	},
185#endif
186#ifdef MSG_AND
187	{ MSG_ANY,	"MSG_ANY"	},
188#endif
189#ifdef MSG_BAND
190	{ MSG_BAND,	"MSG_BAND"	},
191#endif
192	{ 0,		NULL		},
193};
194#endif
195
196#ifdef SYS_putpmsg
197int
198sys_putpmsg(tcp)
199struct tcb *tcp;
200{
201	int i;
202
203	if (entering(tcp)) {
204		/* fd */
205		tprintf("%ld, ", tcp->u_arg[0]);
206		/* control and data */
207		for (i = 1; i < 3; i++)
208			printstrbufarg(tcp, tcp->u_arg[i], 0);
209		/* band */
210		tprintf("%ld, ", tcp->u_arg[3]);
211		/* flags */
212		printflags(pmsgflags, tcp->u_arg[4], "MSG_???");
213	}
214	return 0;
215}
216#endif /* SYS_putpmsg */
217
218#ifdef SYS_getpmsg
219int
220sys_getpmsg(tcp)
221struct tcb *tcp;
222{
223	int i, flags;
224
225	if (entering(tcp)) {
226		/* fd */
227		tprintf("%lu, ", tcp->u_arg[0]);
228	} else {
229		if (syserror(tcp)) {
230			tprintf("%#lx, %#lx, %#lx, %#lx", tcp->u_arg[1],
231				tcp->u_arg[2], tcp->u_arg[3], tcp->u_arg[4]);
232			return 0;
233		}
234		/* control and data */
235		for (i = 1; i < 3; i++)
236			printstrbufarg(tcp, tcp->u_arg[i], 1);
237		/* pointer to band */
238		printnum(tcp, tcp->u_arg[3], "%d");
239		tprintf(", ");
240		/* pointer to flags */
241		if (tcp->u_arg[4] == 0)
242			tprintf("NULL");
243		else if (umove(tcp, tcp->u_arg[4], &flags) < 0)
244			tprintf("[?]");
245		else {
246			tprintf("[");
247			printflags(pmsgflags, flags, "MSG_???");
248			tprintf("]");
249		}
250		/* decode return value */
251		switch (tcp->u_rval) {
252		case MORECTL:
253			tcp->auxstr = "MORECTL";
254			break;
255		case MORECTL|MOREDATA:
256			tcp->auxstr = "MORECTL|MOREDATA";
257			break;
258		case MOREDATA:
259			tcp->auxstr = "MORECTL";
260			break;
261		default:
262			tcp->auxstr = NULL;
263			break;
264		}
265	}
266	return RVAL_HEX | RVAL_STR;
267}
268#endif /* SYS_getpmsg */
269
270#endif /* !FREEBSD */
271
272
273#ifdef HAVE_SYS_POLL_H
274
275static const struct xlat pollflags[] = {
276#ifdef POLLIN
277	{ POLLIN,	"POLLIN"	},
278	{ POLLPRI,	"POLLPRI"	},
279	{ POLLOUT,	"POLLOUT"	},
280#ifdef POLLRDNORM
281	{ POLLRDNORM,	"POLLRDNORM"	},
282#endif
283#ifdef POLLWRNORM
284	{ POLLWRNORM,	"POLLWRNORM"	},
285#endif
286#ifdef POLLRDBAND
287	{ POLLRDBAND,	"POLLRDBAND"	},
288#endif
289#ifdef POLLWRBAND
290	{ POLLWRBAND,	"POLLWRBAND"	},
291#endif
292	{ POLLERR,	"POLLERR"	},
293	{ POLLHUP,	"POLLHUP"	},
294	{ POLLNVAL,	"POLLNVAL"	},
295#endif
296	{ 0,		NULL		},
297};
298
299static int
300decode_poll(struct tcb *tcp)
301{
302	struct pollfd fds;
303	unsigned nfds;
304	unsigned long size, start, cur, end, abbrev_end;
305	int failed = 0;
306
307	if (entering(tcp))
308		return 0;
309
310	nfds = tcp->u_arg[1];
311	size = sizeof(fds) * nfds;
312	start = tcp->u_arg[0];
313	end = start + size;
314	if (nfds == 0 || size / sizeof(fds) != nfds || end < start) {
315		tprintf("%#lx, %d, ",
316			tcp->u_arg[0], nfds);
317		return 0;
318	}
319	if (abbrev(tcp)) {
320		abbrev_end = start + max_strlen * sizeof(fds);
321		if (abbrev_end < start)
322			abbrev_end = end;
323	} else {
324		abbrev_end = end;
325	}
326	tprintf("[");
327	for (cur = start; cur < end; cur += sizeof(fds)) {
328		if (cur > start)
329			tprintf(", ");
330		if (cur >= abbrev_end) {
331			tprintf("...");
332			break;
333		}
334		if (umoven(tcp, cur, sizeof fds, (char *) &fds) < 0) {
335			tprintf("?");
336			failed = 1;
337			break;
338		}
339		if (fds.fd < 0) {
340			tprintf("{fd=%d}", fds.fd);
341			continue;
342		}
343		tprintf("{fd=%d, events=", fds.fd);
344		printflags(pollflags, fds.events, "POLL???");
345		if (!syserror(tcp) && fds.revents) {
346			tprintf(", revents=");
347			printflags(pollflags, fds.revents, "POLL???");
348		}
349		tprintf("}");
350	}
351	tprintf("]");
352	if (failed)
353		tprintf(" %#lx", start);
354	tprintf(", %d, ", nfds);
355	return 0;
356}
357
358int
359sys_poll(struct tcb *tcp)
360{
361	int rc = decode_poll(tcp);
362	if (exiting(tcp)) {
363#ifdef INFTIM
364		if (tcp->u_arg[2] == INFTIM)
365			tprintf("INFTIM");
366		else
367#endif
368			tprintf("%ld", tcp->u_arg[2]);
369	}
370	return rc;
371}
372
373#ifdef LINUX
374int
375sys_ppoll(struct tcb *tcp)
376{
377	int rc = decode_poll(tcp);
378	if (exiting(tcp)) {
379		struct timespec ts;
380		if (umove(tcp, tcp->u_arg[2], &ts) == 0)
381			tprintf("{%lu, %lu}, ", ts.tv_sec, ts.tv_nsec);
382		else
383			tprintf("{...}, ");
384		print_sigset(tcp, tcp->u_arg[3], 0);
385		tprintf(", %lu", tcp->u_arg[4]);
386	}
387	return rc;
388}
389#endif
390
391#else /* !HAVE_SYS_POLL_H */
392int
393sys_poll(tcp)
394struct tcb *tcp;
395{
396    	return 0;
397}
398#endif
399
400#if !defined(LINUX) && !defined(FREEBSD)
401
402static const struct xlat stream_flush_options[] = {
403	{ FLUSHR,	"FLUSHR"	},
404	{ FLUSHW,	"FLUSHW"	},
405	{ FLUSHRW,	"FLUSHRW"	},
406#ifdef FLUSHBAND
407	{ FLUSHBAND,	"FLUSHBAND"	},
408#endif
409	{ 0,		NULL		},
410};
411
412static const struct xlat stream_setsig_flags[] = {
413	{ S_INPUT,	"S_INPUT"	},
414	{ S_HIPRI,	"S_HIPRI"	},
415	{ S_OUTPUT,	"S_OUTPUT"	},
416	{ S_MSG,	"S_MSG"		},
417#ifdef S_ERROR
418	{ S_ERROR,	"S_ERROR"	},
419#endif
420#ifdef S_HANGUP
421	{ S_HANGUP,	"S_HANGUP"	},
422#endif
423#ifdef S_RDNORM
424	{ S_RDNORM,	"S_RDNORM"	},
425#endif
426#ifdef S_WRNORM
427	{ S_WRNORM,	"S_WRNORM"	},
428#endif
429#ifdef S_RDBAND
430	{ S_RDBAND,	"S_RDBAND"	},
431#endif
432#ifdef S_WRBAND
433	{ S_WRBAND,	"S_WRBAND"	},
434#endif
435#ifdef S_BANDURG
436	{ S_BANDURG,	"S_BANDURG"	},
437#endif
438	{ 0,		NULL		},
439};
440
441static const struct xlat stream_read_options[] = {
442	{ RNORM,	"RNORM"		},
443	{ RMSGD,	"RMSGD"		},
444	{ RMSGN,	"RMSGN"		},
445	{ 0,		NULL		},
446};
447
448static const struct xlat stream_read_flags[] = {
449#ifdef RPROTDAT
450	{ RPROTDAT,	"RPROTDAT"	},
451#endif
452#ifdef RPROTDIS
453	{ RPROTDIS,	"RPROTDIS"	},
454#endif
455#ifdef RPROTNORM
456	{ RPROTNORM,	"RPROTNORM"	},
457#endif
458	{ 0,		NULL		},
459};
460
461#ifndef RMODEMASK
462#define RMODEMASK (~0)
463#endif
464
465#ifdef I_SWROPT
466static const struct xlat stream_write_flags[] = {
467	{ SNDZERO,	"SNDZERO"	},
468	{ SNDPIPE,	"SNDPIPE"	},
469	{ 0,		NULL		},
470};
471#endif /* I_SWROPT */
472
473#ifdef I_ATMARK
474static const struct xlat stream_atmark_options[] = {
475	{ ANYMARK,	"ANYMARK"	},
476	{ LASTMARK,	"LASTMARK"	},
477	{ 0,		NULL		},
478};
479#endif /* I_ATMARK */
480
481#ifdef TI_BIND
482static const struct xlat transport_user_options[] = {
483	{ T_CONN_REQ,	"T_CONN_REQ"	},
484	{ T_CONN_RES,	"T_CONN_RES"	},
485	{ T_DISCON_REQ,	"T_DISCON_REQ"	},
486	{ T_DATA_REQ,	"T_DATA_REQ"	},
487	{ T_EXDATA_REQ,	"T_EXDATA_REQ"	},
488	{ T_INFO_REQ,	"T_INFO_REQ"	},
489	{ T_BIND_REQ,	"T_BIND_REQ"	},
490	{ T_UNBIND_REQ,	"T_UNBIND_REQ"	},
491	{ T_UNITDATA_REQ,"T_UNITDATA_REQ"},
492	{ T_OPTMGMT_REQ,"T_OPTMGMT_REQ"	},
493	{ T_ORDREL_REQ,	"T_ORDREL_REQ"	},
494	{ 0,		NULL		},
495};
496
497static const struct xlat transport_user_flags [] = {
498	{ 0,		"0"		},
499	{ T_MORE,	"T_MORE"	},
500	{ T_EXPEDITED,	"T_EXPEDITED"	},
501	{ T_NEGOTIATE,	"T_NEGOTIATE"	},
502	{ T_CHECK,	"T_CHECK"	},
503	{ T_DEFAULT,	"T_DEFAULT"	},
504	{ T_SUCCESS,	"T_SUCCESS"	},
505	{ T_FAILURE,	"T_FAILURE"	},
506	{ T_CURRENT,	"T_CURRENT"	},
507	{ T_PARTSUCCESS,"T_PARTSUCCESS"	},
508	{ T_READONLY,	"T_READONLY"	},
509	{ T_NOTSUPPORT,	"T_NOTSUPPORT"	},
510	{ 0,		NULL		},
511};
512
513
514#ifdef HAVE_STRUCT_T_OPTHDR
515
516static const struct xlat xti_level [] = {
517	{ XTI_GENERIC,	"XTI_GENERIC"	},
518	{ 0,		NULL		},
519};
520
521static const struct xlat xti_generic [] = {
522	{ XTI_DEBUG,	"XTI_DEBUG"	},
523	{ XTI_LINGER,	"XTI_LINGER"	},
524	{ XTI_RCVBUF,	"XTI_RCVBUF"	},
525	{ XTI_RCVLOWAT,	"XTI_RCVLOWAT"	},
526	{ XTI_SNDBUF,	"XTI_SNDBUF"	},
527	{ XTI_SNDLOWAT,	"XTI_SNDLOWAT"	},
528	{ 0,		NULL		},
529};
530
531
532
533void
534print_xti_optmgmt (tcp, addr, len)
535struct tcb *tcp;
536long addr;
537int len;
538{
539	int c = 0;
540	struct t_opthdr hdr;
541
542	while (len >= (int) sizeof hdr) {
543		if (umove(tcp, addr, &hdr) < 0) break;
544		if (c++) {
545			tprintf (", ");
546		}
547		else if (len > hdr.len + sizeof hdr) {
548			tprintf ("[");
549		}
550		tprintf ("{level=");
551		printxval (xti_level, hdr.level, "???");
552		tprintf (", name=");
553		switch (hdr.level) {
554		    case XTI_GENERIC:
555			printxval (xti_generic, hdr.name, "XTI_???");
556			break;
557		    default:
558			tprintf ("%ld", hdr.name);
559			break;
560		}
561		tprintf (", status=");
562		printxval (transport_user_flags,  hdr.status, "T_???");
563		addr += sizeof hdr;
564		len -= sizeof hdr;
565		if ((hdr.len -= sizeof hdr) > 0) {
566			if (hdr.len > len) break;
567			tprintf (", val=");
568			if (len == sizeof (int))
569				printnum (tcp, addr, "%d");
570			else
571				printstr (tcp, addr, hdr.len);
572			addr += hdr.len;
573			len -= hdr.len;
574		}
575		tprintf ("}");
576	}
577	if (len > 0) {
578		if (c++) tprintf (", ");
579		printstr (tcp, addr, len);
580	}
581	if (c > 1) tprintf ("]");
582}
583
584#endif
585
586
587static void
588print_optmgmt (tcp, addr, len)
589struct tcb *tcp;
590long addr;
591int len;
592{
593	/* We don't know how to tell if TLI (socket) or XTI
594	   optmgmt is being used yet, assume TLI. */
595#if defined (HAVE_STRUCT_OPTHDR)
596	print_sock_optmgmt (tcp, addr, len);
597#elif defined (HAVE_STRUCT_T_OPTHDR)
598	print_xti_optmgmt (tcp, addr, len);
599#else
600	printstr (tcp, addr, len);
601#endif
602}
603
604
605
606
607static const struct xlat service_type [] = {
608	{ T_COTS,	"T_COTS"	},
609	{ T_COTS_ORD,	"T_COTS_ORD"	},
610	{ T_CLTS,	"T_CLTS"	},
611	{ 0,		NULL		},
612};
613
614static const struct xlat ts_state [] = {
615	{ TS_UNBND,	"TS_UNBND"	},
616	{ TS_WACK_BREQ,	"TS_WACK_BREQ"	},
617	{ TS_WACK_UREQ,	"TS_WACK_UREQ"	},
618	{ TS_IDLE,	"TS_IDLE"	},
619	{ TS_WACK_OPTREQ,"TS_WACK_OPTREQ"},
620	{ TS_WACK_CREQ,	"TS_WACK_CREQ"	},
621	{ TS_WCON_CREQ,	"TS_WCON_CREQ"	},
622	{ TS_WRES_CIND,	"TS_WRES_CIND"	},
623	{ TS_WACK_CRES,	"TS_WACK_CRES"	},
624	{ TS_DATA_XFER,	"TS_DATA_XFER"	},
625	{ TS_WIND_ORDREL,"TS_WIND_ORDREL"},
626	{ TS_WREQ_ORDREL,"TS_WREQ_ORDREL"},
627	{ TS_WACK_DREQ6,"TS_WACK_DREQ6"	},
628	{ TS_WACK_DREQ7,"TS_WACK_DREQ7"	},
629	{ TS_WACK_DREQ9,"TS_WACK_DREQ9"	},
630	{ TS_WACK_DREQ10,"TS_WACK_DREQ10"},
631	{ TS_WACK_DREQ11,"TS_WACK_DREQ11"},
632	{ 0,		NULL		},
633};
634
635static const struct xlat provider_flags [] = {
636	{ 0,		"0"		},
637	{ SENDZERO,	"SENDZERO"	},
638	{ EXPINLINE,	"EXPINLINE"	},
639	{ XPG4_1,	"XPG4_1"	},
640	{ 0,		NULL		},
641};
642
643
644static const struct xlat tli_errors [] = {
645	{ TBADADDR,	"TBADADDR"	},
646	{ TBADOPT,	"TBADOPT"	},
647	{ TACCES,	"TACCES"	},
648	{ TBADF,	"TBADF"		},
649	{ TNOADDR,	"TNOADDR"	},
650	{ TOUTSTATE,	"TOUTSTATE"	},
651	{ TBADSEQ,	"TBADSEQ"	},
652	{ TSYSERR,	"TSYSERR"	},
653	{ TLOOK,	"TLOOK"		},
654	{ TBADDATA,	"TBADDATA"	},
655	{ TBUFOVFLW,	"TBUFOVFLW"	},
656	{ TFLOW,	"TFLOW"		},
657	{ TNODATA,	"TNODATA"	},
658	{ TNODIS,	"TNODIS"	},
659	{ TNOUDERR,	"TNOUDERR"	},
660	{ TBADFLAG,	"TBADFLAG"	},
661	{ TNOREL,	"TNOREL"	},
662	{ TNOTSUPPORT,	"TNOTSUPPORT"	},
663	{ TSTATECHNG,	"TSTATECHNG"	},
664	{ TNOSTRUCTYPE,	"TNOSTRUCTYPE"	},
665	{ TBADNAME,	"TBADNAME"	},
666	{ TBADQLEN,	"TBADQLEN"	},
667	{ TADDRBUSY,	"TADDRBUSY"	},
668	{ TINDOUT,	"TINDOUT"	},
669	{ TPROVMISMATCH,"TPROVMISMATCH"	},
670	{ TRESQLEN,	"TRESQLEN"	},
671	{ TRESADDR,	"TRESADDR"	},
672	{ TQFULL,	"TQFULL"	},
673	{ TPROTO,	"TPROTO"	},
674	{ 0,		NULL		},
675};
676
677
678static int
679print_transport_message (tcp, expect, addr, len)
680struct tcb *tcp;
681int expect;
682long addr;
683int len;
684{
685	union T_primitives m;
686	int c = 0;
687
688	if (len < sizeof m.type) goto dump;
689
690	if (umove (tcp, addr, &m.type) < 0) goto dump;
691
692#define GET(type, struct)	\
693	do {							\
694		if (len < sizeof m.struct) goto dump;		\
695		if (umove (tcp, addr, &m.struct) < 0) goto dump;\
696		tprintf ("{");					\
697		if (expect != type) {				\
698			++c;					\
699			tprintf (#type);			\
700		}						\
701	}							\
702	while (0)
703
704#define COMMA() \
705	do { if (c++) tprintf (", "); } while (0)
706
707
708#define STRUCT(struct, elem, print)					\
709	do {								\
710		COMMA ();						\
711		if (m.struct.elem##_length < 0 ||			\
712		    m.struct.elem##_offset < sizeof m.struct ||		\
713		    m.struct.elem##_offset + m.struct.elem##_length > len) \
714		{							\
715			tprintf (#elem "_length=%ld, " #elem "_offset=%ld",\
716				m.struct.elem##_length,			\
717				m.struct.elem##_offset);		\
718		}							\
719		else {							\
720			tprintf (#elem "=");				\
721			print (tcp,					\
722				 addr + m.struct.elem##_offset,		\
723				 m.struct.elem##_length);		\
724		}							\
725	}								\
726	while (0)
727
728#define ADDR(struct, elem) STRUCT (struct, elem, printstr)
729
730	switch (m.type) {
731#ifdef T_CONN_REQ
732	    case T_CONN_REQ:	/* connect request   */
733		GET (T_CONN_REQ, conn_req);
734		ADDR (conn_req, DEST);
735		ADDR (conn_req, OPT);
736		break;
737#endif
738#ifdef T_CONN_RES
739	    case T_CONN_RES:	/* connect response   */
740		GET (T_CONN_RES, conn_res);
741#ifdef HAVE_STRUCT_T_CONN_RES_QUEUE_PTR
742		COMMA ();
743		tprintf ("QUEUE=%p", m.conn_res.QUEUE_ptr);
744#elif defined HAVE_STRUCT_T_CONN_RES_ACCEPTOR_ID
745		COMMA ();
746		tprintf ("ACCEPTOR=%#lx", m.conn_res.ACCEPTOR_id);
747#endif
748		ADDR (conn_res, OPT);
749		COMMA ();
750		tprintf ("SEQ=%ld", m.conn_res.SEQ_number);
751		break;
752#endif
753#ifdef T_DISCON_REQ
754	    case T_DISCON_REQ:	/* disconnect request */
755		GET (T_DISCON_REQ, discon_req);
756		COMMA ();
757		tprintf ("SEQ=%ld", m.discon_req.SEQ_number);
758		break;
759#endif
760#ifdef T_DATA_REQ
761	    case T_DATA_REQ:	/* data request       */
762		GET (T_DATA_REQ, data_req);
763		COMMA ();
764		tprintf ("MORE=%ld", m.data_req.MORE_flag);
765		break;
766#endif
767#ifdef T_EXDATA_REQ
768	    case T_EXDATA_REQ:	/* expedited data req */
769		GET (T_EXDATA_REQ, exdata_req);
770		COMMA ();
771		tprintf ("MORE=%ld", m.exdata_req.MORE_flag);
772		break;
773#endif
774#ifdef T_INFO_REQ
775	    case T_INFO_REQ:	/* information req    */
776		GET (T_INFO_REQ, info_req);
777		break;
778#endif
779#ifdef T_BIND_REQ
780	    case T_BIND_REQ:	/* bind request       */
781#ifdef O_T_BIND_REQ
782	    case O_T_BIND_REQ:	/* Ugly xti/tli hack */
783#endif
784		GET (T_BIND_REQ, bind_req);
785		ADDR (bind_req, ADDR);
786		COMMA ();
787		tprintf ("CONIND=%ld", m.bind_req.CONIND_number);
788		break;
789#endif
790#ifdef T_UNBIND_REQ
791	    case T_UNBIND_REQ:	/* unbind request     */
792		GET (T_UNBIND_REQ, unbind_req);
793		break;
794#endif
795#ifdef T_UNITDATA_REQ
796	    case T_UNITDATA_REQ:	/* unitdata requset   */
797		GET (T_UNITDATA_REQ, unitdata_req);
798		ADDR (unitdata_req, DEST);
799		ADDR (unitdata_req, OPT);
800		break;
801#endif
802#ifdef T_OPTMGMT_REQ
803	    case T_OPTMGMT_REQ:	/* manage opt req     */
804		GET (T_OPTMGMT_REQ, optmgmt_req);
805		COMMA ();
806		tprintf ("MGMT=");
807		printflags (transport_user_flags, m.optmgmt_req.MGMT_flags,
808			    "T_???");
809		STRUCT (optmgmt_req, OPT, print_optmgmt);
810		break;
811#endif
812#ifdef T_ORDREL_REQ
813	    case T_ORDREL_REQ:	/* orderly rel req    */
814		GET (T_ORDREL_REQ, ordrel_req);
815		break;
816#endif
817#ifdef T_CONN_IND
818	    case T_CONN_IND:	/* connect indication */
819		GET (T_CONN_IND, conn_ind);
820		ADDR (conn_ind, SRC);
821		ADDR (conn_ind, OPT);
822		tprintf (", SEQ=%ld", m.conn_ind.SEQ_number);
823		break;
824#endif
825#ifdef T_CONN_CON
826	    case T_CONN_CON:	/* connect corfirm    */
827		GET (T_CONN_CON, conn_con);
828		ADDR (conn_con, RES);
829		ADDR (conn_con, OPT);
830		break;
831#endif
832#ifdef T_DISCON_IND
833	    case T_DISCON_IND:	/* discon indication  */
834		GET (T_DISCON_IND, discon_ind);
835		COMMA ();
836		tprintf ("DISCON=%ld, SEQ=%ld",
837			 m.discon_ind.DISCON_reason, m.discon_ind.SEQ_number);
838		break;
839#endif
840#ifdef T_DATA_IND
841	    case T_DATA_IND:	/* data indication    */
842		GET (T_DATA_IND, data_ind);
843		COMMA ();
844		tprintf ("MORE=%ld", m.data_ind.MORE_flag);
845		break;
846#endif
847#ifdef T_EXDATA_IND
848	    case T_EXDATA_IND:	/* expedited data ind */
849		GET (T_EXDATA_IND, exdata_ind);
850		COMMA ();
851		tprintf ("MORE=%ld", m.exdata_ind.MORE_flag);
852		break;
853#endif
854#ifdef T_INFO_ACK
855	    case T_INFO_ACK:	/* info ack           */
856		GET (T_INFO_ACK, info_ack);
857		COMMA ();
858		tprintf ("TSDU=%ld, ETSDU=%ld, CDATA=%ld, DDATA=%ld, "
859			 "ADDR=%ld, OPT=%ld, TIDU=%ld, SERV=",
860			 m.info_ack.TSDU_size, m.info_ack.ETSDU_size,
861			 m.info_ack.CDATA_size, m.info_ack.DDATA_size,
862			 m.info_ack.ADDR_size, m.info_ack.OPT_size,
863			 m.info_ack.TIDU_size);
864		printxval (service_type, m.info_ack.SERV_type, "T_???");
865		tprintf (", CURRENT=");
866		printxval (ts_state, m.info_ack.CURRENT_state, "TS_???");
867		tprintf (", PROVIDER=");
868		printflags (provider_flags, m.info_ack.PROVIDER_flag, "???");
869		break;
870#endif
871#ifdef T_BIND_ACK
872	    case T_BIND_ACK:	/* bind ack           */
873		GET (T_BIND_ACK, bind_ack);
874		ADDR (bind_ack, ADDR);
875		tprintf (", CONIND=%ld", m.bind_ack.CONIND_number);
876		break;
877#endif
878#ifdef T_ERROR_ACK
879	    case T_ERROR_ACK:	/* error ack          */
880		GET (T_ERROR_ACK, error_ack);
881		COMMA ();
882		tprintf ("ERROR=");
883		printxval (transport_user_options,
884			   m.error_ack.ERROR_prim, "TI_???");
885		tprintf (", TLI=");
886		printxval (tli_errors, m.error_ack.TLI_error, "T???");
887		tprintf ("UNIX=%s", strerror (m.error_ack.UNIX_error));
888		break;
889#endif
890#ifdef T_OK_ACK
891	    case T_OK_ACK:	/* ok ack             */
892		GET (T_OK_ACK, ok_ack);
893		COMMA ();
894		tprintf ("CORRECT=");
895		printxval (transport_user_options,
896			   m.ok_ack.CORRECT_prim, "TI_???");
897		break;
898#endif
899#ifdef T_UNITDATA_IND
900	    case T_UNITDATA_IND:	/* unitdata ind       */
901		GET (T_UNITDATA_IND, unitdata_ind);
902		ADDR (unitdata_ind, SRC);
903		ADDR (unitdata_ind, OPT);
904		break;
905#endif
906#ifdef T_UDERROR_IND
907	    case T_UDERROR_IND:	/* unitdata error ind */
908		GET (T_UDERROR_IND, uderror_ind);
909		ADDR (uderror_ind, DEST);
910		ADDR (uderror_ind, OPT);
911		tprintf (", ERROR=%ld", m.uderror_ind.ERROR_type);
912		break;
913#endif
914#ifdef T_OPTMGMT_ACK
915	    case T_OPTMGMT_ACK:	/* manage opt ack     */
916		GET (T_OPTMGMT_ACK, optmgmt_ack);
917		COMMA ();
918		tprintf ("MGMT=");
919		printflags (transport_user_flags, m.optmgmt_ack.MGMT_flags,
920			    "T_???");
921		STRUCT (optmgmt_ack, OPT, print_optmgmt);
922		break;
923#endif
924#ifdef T_ORDREL_IND
925	case T_ORDREL_IND:	/* orderly rel ind    */
926		GET (T_ORDREL_IND, ordrel_ind);
927		break;
928#endif
929#ifdef T_ADDR_REQ
930	    case T_ADDR_REQ:	/* address req        */
931		GET (T_ADDR_REQ, addr_req);
932		break;
933#endif
934#ifdef T_ADDR_ACK
935	    case T_ADDR_ACK:	/* address response   */
936		GET (T_ADDR_ACK, addr_ack);
937		ADDR (addr_ack, LOCADDR);
938		ADDR (addr_ack, REMADDR);
939		break;
940#endif
941	    default:
942	    dump:
943		c = -1;
944		printstr(tcp, addr, len);
945		break;
946	}
947
948	if (c >= 0) tprintf ("}");
949
950#undef ADDR
951#undef COMMA
952#undef STRUCT
953
954	return 0;
955}
956
957
958#endif /* TI_BIND */
959
960
961static int
962internal_stream_ioctl(tcp, arg)
963struct tcb *tcp;
964int arg;
965{
966	struct strioctl si;
967	struct ioctlent *iop;
968	int in_and_out;
969	int timod = 0;
970#ifdef SI_GETUDATA
971	struct si_udata udata;
972#endif /* SI_GETUDATA */
973
974	if (!arg)
975		return 0;
976	if (umove(tcp, arg, &si) < 0) {
977		if (entering(tcp))
978			tprintf(", {...}");
979		return 1;
980	}
981	if (entering(tcp)) {
982		iop = ioctl_lookup(si.ic_cmd);
983		if (iop) {
984			tprintf(", {ic_cmd=%s", iop->symbol);
985			while ((iop = ioctl_next_match(iop)))
986				tprintf(" or %s", iop->symbol);
987		} else
988			tprintf(", {ic_cmd=%#x", si.ic_cmd);
989		if (si.ic_timout == INFTIM)
990			tprintf(", ic_timout=INFTIM, ");
991		else
992			tprintf(" ic_timout=%d, ", si.ic_timout);
993	}
994	in_and_out = 1;
995	switch (si.ic_cmd) {
996#ifdef SI_GETUDATA
997	case SI_GETUDATA:
998		in_and_out = 0;
999		break;
1000#endif /* SI_GETUDATA */
1001	}
1002	if (in_and_out) {
1003		if (entering(tcp))
1004			tprintf("/* in */ ");
1005		else
1006			tprintf(", /* out */ ");
1007	}
1008	if (in_and_out || entering(tcp))
1009		tprintf("ic_len=%d, ic_dp=", si.ic_len);
1010	switch (si.ic_cmd) {
1011#ifdef TI_BIND
1012	case TI_BIND:
1013		/* in T_BIND_REQ, out T_BIND_ACK */
1014		++timod;
1015		if (entering(tcp)) {
1016			print_transport_message (tcp,
1017						 T_BIND_REQ,
1018						 si.ic_dp, si.ic_len);
1019		}
1020		else {
1021			print_transport_message (tcp,
1022						 T_BIND_ACK,
1023						 si.ic_dp, si.ic_len);
1024		}
1025		break;
1026#endif /* TI_BIND */
1027#ifdef TI_UNBIND
1028	case TI_UNBIND:
1029		/* in T_UNBIND_REQ, out T_OK_ACK */
1030		++timod;
1031		if (entering(tcp)) {
1032			print_transport_message (tcp,
1033						 T_UNBIND_REQ,
1034						 si.ic_dp, si.ic_len);
1035		}
1036		else {
1037			print_transport_message (tcp,
1038						 T_OK_ACK,
1039						 si.ic_dp, si.ic_len);
1040		}
1041		break;
1042#endif /* TI_UNBIND */
1043#ifdef TI_GETINFO
1044	case TI_GETINFO:
1045		/* in T_INFO_REQ, out T_INFO_ACK */
1046		++timod;
1047		if (entering(tcp)) {
1048			print_transport_message (tcp,
1049						 T_INFO_REQ,
1050						 si.ic_dp, si.ic_len);
1051		}
1052		else {
1053			print_transport_message (tcp,
1054						 T_INFO_ACK,
1055						 si.ic_dp, si.ic_len);
1056		}
1057		break;
1058#endif /* TI_GETINFO */
1059#ifdef TI_OPTMGMT
1060	case TI_OPTMGMT:
1061		/* in T_OPTMGMT_REQ, out T_OPTMGMT_ACK */
1062		++timod;
1063		if (entering(tcp)) {
1064			print_transport_message (tcp,
1065						 T_OPTMGMT_REQ,
1066						 si.ic_dp, si.ic_len);
1067		}
1068		else {
1069			print_transport_message (tcp,
1070						 T_OPTMGMT_ACK,
1071						 si.ic_dp, si.ic_len);
1072		}
1073		break;
1074#endif /* TI_OPTMGMT */
1075#ifdef SI_GETUDATA
1076	case SI_GETUDATA:
1077		if (entering(tcp))
1078			break;
1079#if 0
1080		tprintf("struct si_udata ");
1081#endif
1082		if (umove(tcp, (int) si.ic_dp, &udata) < 0)
1083			tprintf("{...}");
1084		else {
1085			tprintf("{tidusize=%d, addrsize=%d, ",
1086				udata.tidusize, udata.addrsize);
1087			tprintf("optsize=%d, etsdusize=%d, ",
1088				udata.optsize, udata.etsdusize);
1089			tprintf("servtype=%d, so_state=%d, ",
1090				udata.servtype, udata.so_state);
1091			tprintf("so_options=%d", udata.so_options);
1092#if 0
1093			tprintf(", tsdusize=%d", udata.tsdusize);
1094#endif
1095			tprintf("}");
1096		}
1097		break;
1098#endif /* SI_GETUDATA */
1099	default:
1100		printstr(tcp, (long) si.ic_dp, si.ic_len);
1101		break;
1102	}
1103	if (exiting(tcp)) {
1104		tprintf("}");
1105		if (timod && tcp->u_rval) {
1106			tcp->auxstr = xlookup (tli_errors, tcp->u_rval);
1107			return RVAL_STR + 1;
1108		}
1109	}
1110
1111	return 1;
1112}
1113
1114int
1115stream_ioctl(tcp, code, arg)
1116struct tcb *tcp;
1117int code, arg;
1118{
1119#ifdef I_LIST
1120	int i;
1121#endif
1122	int val;
1123#ifdef I_FLUSHBAND
1124	struct bandinfo bi;
1125#endif
1126	struct strpeek sp;
1127	struct strfdinsert sfi;
1128	struct strrecvfd srf;
1129#ifdef I_LIST
1130	struct str_list sl;
1131#endif
1132
1133	/* I_STR is a special case because the data is read & written. */
1134	if (code == I_STR)
1135		return internal_stream_ioctl(tcp, arg);
1136	if (entering(tcp))
1137		return 0;
1138
1139	switch (code) {
1140	case I_PUSH:
1141	case I_LOOK:
1142	case I_FIND:
1143		/* arg is a string */
1144		tprintf(", ");
1145		printpath(tcp, arg);
1146		return 1;
1147	case I_POP:
1148		/* doesn't take an argument */
1149		return 1;
1150	case I_FLUSH:
1151		/* argument is an option */
1152		tprintf(", ");
1153		printxval(stream_flush_options, arg, "FLUSH???");
1154		return 1;
1155#ifdef I_FLUSHBAND
1156	case I_FLUSHBAND:
1157		/* argument is a pointer to a bandinfo struct */
1158		if (umove(tcp, arg, &bi) < 0)
1159			tprintf(", {...}");
1160		else {
1161			tprintf(", {bi_pri=%d, bi_flag=", bi.bi_pri);
1162			printflags(stream_flush_options, bi.bi_flag, "FLUSH???");
1163			tprintf("}");
1164		}
1165		return 1;
1166#endif /* I_FLUSHBAND */
1167	case I_SETSIG:
1168		/* argument is a set of flags */
1169		tprintf(", ");
1170		printflags(stream_setsig_flags, arg, "S_???");
1171		return 1;
1172	case I_GETSIG:
1173		/* argument is a pointer to a set of flags */
1174		if (syserror(tcp))
1175			return 0;
1176		tprintf(", [");
1177		if (umove(tcp, arg, &val) < 0)
1178			tprintf("?");
1179		else
1180			printflags(stream_setsig_flags, val, "S_???");
1181		tprintf("]");
1182		return 1;
1183	case I_PEEK:
1184		/* argument is a pointer to a strpeek structure */
1185		if (syserror(tcp) || !arg)
1186			return 0;
1187		if (umove(tcp, arg, &sp) < 0) {
1188			tprintf(", {...}");
1189			return 1;
1190		}
1191		tprintf(", {ctlbuf=");
1192		printstrbuf(tcp, &sp.ctlbuf, 1);
1193		tprintf(", databuf=");
1194		printstrbuf(tcp, &sp.databuf, 1);
1195		tprintf(", flags=");
1196		printflags(msgflags, sp.flags, "RS_???");
1197		tprintf("}");
1198		return 1;
1199	case I_SRDOPT:
1200		/* argument is an option with flags */
1201		tprintf(", ");
1202		printxval(stream_read_options, arg & RMODEMASK, "R???");
1203		addflags(stream_read_flags, arg & ~RMODEMASK);
1204		return 1;
1205	case I_GRDOPT:
1206		/* argument is an pointer to an option with flags */
1207		if (syserror(tcp))
1208			return 0;
1209		tprintf(", [");
1210		if (umove(tcp, arg, &val) < 0)
1211			tprintf("?");
1212		else {
1213			printxval(stream_read_options,
1214				  arg & RMODEMASK, "R???");
1215			addflags(stream_read_flags, arg & ~RMODEMASK);
1216		}
1217		tprintf("]");
1218		return 1;
1219	case I_NREAD:
1220#ifdef I_GETBAND
1221	case I_GETBAND:
1222#endif
1223#ifdef I_SETCLTIME
1224	case I_SETCLTIME:
1225#endif
1226#ifdef I_GETCLTIME
1227	case I_GETCLTIME:
1228#endif
1229		/* argument is a pointer to a decimal integer */
1230		if (syserror(tcp))
1231			return 0;
1232		tprintf(", ");
1233		printnum(tcp, arg, "%d");
1234		return 1;
1235	case I_FDINSERT:
1236		/* argument is a pointer to a strfdinsert structure */
1237		if (syserror(tcp) || !arg)
1238			return 0;
1239		if (umove(tcp, arg, &sfi) < 0) {
1240			tprintf(", {...}");
1241			return 1;
1242		}
1243		tprintf(", {ctlbuf=");
1244		printstrbuf(tcp, &sfi.ctlbuf, 1);
1245		tprintf(", databuf=");
1246		printstrbuf(tcp, &sfi.databuf, 1);
1247		tprintf(", flags=");
1248		printflags(msgflags, sfi.flags, "RS_???");
1249		tprintf(", filedes=%d, offset=%d}", sfi.fildes, sfi.offset);
1250		return 1;
1251#ifdef I_SWROPT
1252	case I_SWROPT:
1253		/* argument is a set of flags */
1254		tprintf(", ");
1255		printflags(stream_write_flags, arg, "SND???");
1256		return 1;
1257#endif /* I_SWROPT */
1258#ifdef I_GWROPT
1259	case I_GWROPT:
1260		/* argument is an pointer to an option with flags */
1261		if (syserror(tcp))
1262			return 0;
1263		tprintf(", [");
1264		if (umove(tcp, arg, &val) < 0)
1265			tprintf("?");
1266		else
1267			printflags(stream_write_flags, arg, "SND???");
1268		tprintf("]");
1269		return 1;
1270#endif /* I_GWROPT */
1271	case I_SENDFD:
1272#ifdef I_CKBAND
1273	case I_CKBAND:
1274#endif
1275#ifdef I_CANPUT
1276	case I_CANPUT:
1277#endif
1278	case I_LINK:
1279	case I_UNLINK:
1280	case I_PLINK:
1281	case I_PUNLINK:
1282		/* argument is a decimal integer */
1283		tprintf(", %d", arg);
1284		return 1;
1285	case I_RECVFD:
1286		/* argument is a pointer to a strrecvfd structure */
1287		if (syserror(tcp) || !arg)
1288			return 0;
1289		if (umove(tcp, arg, &srf) < 0) {
1290			tprintf(", {...}");
1291			return 1;
1292		}
1293		tprintf(", {fd=%d, uid=%lu, gid=%lu}", srf.fd,
1294			(unsigned long) srf.uid, (unsigned long) srf.gid);
1295		return 1;
1296#ifdef I_LIST
1297	case I_LIST:
1298		if (syserror(tcp))
1299			return 0;
1300		if (arg == 0) {
1301			tprintf(", NULL");
1302			return 1;
1303		}
1304		if (umove(tcp, arg, &sl) < 0) {
1305			tprintf(", {...}");
1306			return 1;
1307		}
1308		tprintf(", {sl_nmods=%d, sl_modlist=[", sl.sl_nmods);
1309		for (i = 0; i < tcp->u_rval; i++) {
1310			if (i)
1311				tprintf(", ");
1312			printpath(tcp, (int) sl.sl_modlist[i].l_name);
1313		}
1314		tprintf("]}");
1315		return 1;
1316#endif /* I_LIST */
1317#ifdef I_ATMARK
1318	case I_ATMARK:
1319		tprintf(", ");
1320		printxval(stream_atmark_options, arg, "???MARK");
1321		return 1;
1322#endif /* I_ATMARK */
1323	default:
1324		return 0;
1325	}
1326}
1327
1328#endif /* !LINUX && !FREEBSD */
1329
1330#endif /* HAVE_SYS_STREAM_H || LINUX || FREEBSD */
1331