stream.c revision 2843a4e1d2fca851be6e47e7ff2413b45903ac9a
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 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		if (!printflags(msgflags, tcp->u_arg[3]))
128			tprintf("0");
129	}
130	return 0;
131}
132
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			if (!printflags(msgflags, flags))
159				tprintf("0");
160			tprintf("]");
161		}
162		/* decode return value */
163		switch (tcp->u_rval) {
164		case MORECTL:
165			tcp->auxstr = "MORECTL";
166			break;
167		case MORECTL|MOREDATA:
168			tcp->auxstr = "MORECTL|MOREDATA";
169			break;
170		case MOREDATA:
171			tcp->auxstr = "MORECTL";
172			break;
173		default:
174			tcp->auxstr = NULL;
175			break;
176		}
177	}
178	return RVAL_HEX | RVAL_STR;
179}
180
181#if defined SYS_putpmsg || defined SYS_getpmsg
182static 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		if (!printflags(pmsgflags, tcp->u_arg[4]))
213			tprintf("0");
214	}
215	return 0;
216}
217#endif /* SYS_putpmsg */
218
219#ifdef SYS_getpmsg
220int
221sys_getpmsg(tcp)
222struct tcb *tcp;
223{
224	int i, flags;
225
226	if (entering(tcp)) {
227		/* fd */
228		tprintf("%lu, ", tcp->u_arg[0]);
229	} else {
230		if (syserror(tcp)) {
231			tprintf("%#lx, %#lx, %#lx, %#lx", tcp->u_arg[1],
232				tcp->u_arg[2], tcp->u_arg[3], tcp->u_arg[4]);
233			return 0;
234		}
235		/* control and data */
236		for (i = 1; i < 3; i++)
237			printstrbufarg(tcp, tcp->u_arg[i], 1);
238		/* pointer to band */
239		printnum(tcp, tcp->u_arg[3], "%d");
240		tprintf(", ");
241		/* pointer to flags */
242		if (tcp->u_arg[4] == 0)
243			tprintf("NULL");
244		else if (umove(tcp, tcp->u_arg[4], &flags) < 0)
245			tprintf("[?]");
246		else {
247			tprintf("[");
248			if (!printflags(pmsgflags, flags))
249				tprintf("0");
250			tprintf("]");
251		}
252		/* decode return value */
253		switch (tcp->u_rval) {
254		case MORECTL:
255			tcp->auxstr = "MORECTL";
256			break;
257		case MORECTL|MOREDATA:
258			tcp->auxstr = "MORECTL|MOREDATA";
259			break;
260		case MOREDATA:
261			tcp->auxstr = "MORECTL";
262			break;
263		default:
264			tcp->auxstr = NULL;
265			break;
266		}
267	}
268	return RVAL_HEX | RVAL_STR;
269}
270#endif /* SYS_getpmsg */
271
272#endif /* !FREEBSD */
273
274
275#ifdef HAVE_SYS_POLL_H
276
277static struct xlat pollflags[] = {
278#ifdef POLLIN
279	{ POLLIN,	"POLLIN"	},
280	{ POLLPRI,	"POLLPRI"	},
281	{ POLLOUT,	"POLLOUT"	},
282#ifdef POLLRDNORM
283	{ POLLRDNORM,	"POLLRDNORM"	},
284#endif
285#ifdef POLLWRNORM
286	{ POLLWRNORM,	"POLLWRNORM"	},
287#endif
288#ifdef POLLRDBAND
289	{ POLLRDBAND,	"POLLRDBAND"	},
290#endif
291#ifdef POLLWRBAND
292	{ POLLWRBAND,	"POLLWRBAND"	},
293#endif
294	{ POLLERR,	"POLLERR"	},
295	{ POLLHUP,	"POLLHUP"	},
296	{ POLLNVAL,	"POLLNVAL"	},
297#endif
298	{ 0,		NULL		},
299};
300
301int
302sys_poll(tcp)
303struct tcb *tcp;
304{
305	struct pollfd *pollp;
306
307	if (exiting(tcp)) {
308		int i;
309		int nfds = tcp->u_arg[1];
310
311		if (nfds <= 0) {
312			tprintf("%#lx, %d, %ld\n",
313				tcp->u_arg[0], nfds, tcp->u_arg[2]);
314			return 0;
315		}
316		pollp = (struct pollfd *) malloc(nfds * sizeof(*pollp));
317		if (pollp == NULL) {
318			fprintf(stderr, "sys_poll: no memory\n");
319			tprintf("%#lx, %d, %ld",
320				tcp->u_arg[0], nfds, tcp->u_arg[2]);
321			return 0;
322		}
323		if (umoven(tcp, tcp->u_arg[0],
324			   (nfds * sizeof(*pollp)), (char *) pollp) < 0) {
325			tprintf("%#lx", tcp->u_arg[0]);
326		}
327		else {
328			tprintf("[");
329			for (i = 0; i < nfds; i++) {
330				if (i)
331					tprintf(", ");
332				if (pollp[i].fd < 0) {
333					tprintf("{fd=%d}", pollp[i].fd);
334					continue;
335				}
336				tprintf("{fd=%d, events=", pollp[i].fd);
337				if (!printflags(pollflags, pollp[i].events))
338					tprintf("0");
339				if (!syserror(tcp) && pollp[i].revents) {
340					tprintf(", revents=");
341					if (!printflags(pollflags,
342							pollp[i].revents))
343						tprintf("0");
344				}
345				tprintf("}");
346			}
347			tprintf("]");
348		}
349		tprintf(", %d, ", nfds);
350#ifdef INFTIM
351		if (tcp->u_arg[2] == INFTIM)
352			tprintf("INFTIM");
353		else
354#endif
355			tprintf("%ld", tcp->u_arg[2]);
356		free(pollp);
357	}
358	return 0;
359}
360
361#else /* !HAVE_SYS_POLL_H */
362int
363sys_poll(tcp)
364struct tcb *tcp;
365{
366    	return 0;
367}
368#endif
369
370#if !defined(LINUX) && !defined(FREEBSD)
371
372static struct xlat stream_flush_options[] = {
373	{ FLUSHR,	"FLUSHR"	},
374	{ FLUSHW,	"FLUSHW"	},
375	{ FLUSHRW,	"FLUSHRW"	},
376#ifdef FLUSHBAND
377	{ FLUSHBAND,	"FLUSHBAND"	},
378#endif
379	{ 0,		NULL		},
380};
381
382static struct xlat stream_setsig_flags[] = {
383	{ S_INPUT,	"S_INPUT"	},
384	{ S_HIPRI,	"S_HIPRI"	},
385	{ S_OUTPUT,	"S_OUTPUT"	},
386	{ S_MSG,	"S_MSG"		},
387#ifdef S_ERROR
388	{ S_ERROR,	"S_ERROR"	},
389#endif
390#ifdef S_HANGUP
391	{ S_HANGUP,	"S_HANGUP"	},
392#endif
393#ifdef S_RDNORM
394	{ S_RDNORM,	"S_RDNORM"	},
395#endif
396#ifdef S_WRNORM
397	{ S_WRNORM,	"S_WRNORM"	},
398#endif
399#ifdef S_RDBAND
400	{ S_RDBAND,	"S_RDBAND"	},
401#endif
402#ifdef S_WRBAND
403	{ S_WRBAND,	"S_WRBAND"	},
404#endif
405#ifdef S_BANDURG
406	{ S_BANDURG,	"S_BANDURG"	},
407#endif
408	{ 0,		NULL		},
409};
410
411static struct xlat stream_read_options[] = {
412	{ RNORM,	"RNORM"		},
413	{ RMSGD,	"RMSGD"		},
414	{ RMSGN,	"RMSGN"		},
415	{ 0,		NULL		},
416};
417
418static struct xlat stream_read_flags[] = {
419#ifdef RPROTDAT
420	{ RPROTDAT,	"RPROTDAT"	},
421#endif
422#ifdef RPROTDIS
423	{ RPROTDIS,	"RPROTDIS"	},
424#endif
425#ifdef RPROTNORM
426	{ RPROTNORM,	"RPROTNORM"	},
427#endif
428	{ 0,		NULL		},
429};
430
431#ifndef RMODEMASK
432#define RMODEMASK (~0)
433#endif
434
435#ifdef I_SWROPT
436static struct xlat stream_write_flags[] = {
437	{ SNDZERO,	"SNDZERO"	},
438	{ SNDPIPE,	"SNDPIPE"	},
439	{ 0,		NULL		},
440};
441#endif /* I_SWROPT */
442
443#ifdef I_ATMARK
444static struct xlat stream_atmark_options[] = {
445	{ ANYMARK,	"ANYMARK"	},
446	{ LASTMARK,	"LASTMARK"	},
447	{ 0,		NULL		},
448};
449#endif /* I_ATMARK */
450
451#ifdef TI_BIND
452static struct xlat transport_user_options[] = {
453	{ T_CONN_REQ,	"T_CONN_REQ"	},
454	{ T_CONN_RES,	"T_CONN_RES"	},
455	{ T_DISCON_REQ,	"T_DISCON_REQ"	},
456	{ T_DATA_REQ,	"T_DATA_REQ"	},
457	{ T_EXDATA_REQ,	"T_EXDATA_REQ"	},
458	{ T_INFO_REQ,	"T_INFO_REQ"	},
459	{ T_BIND_REQ,	"T_BIND_REQ"	},
460	{ T_UNBIND_REQ,	"T_UNBIND_REQ"	},
461	{ T_UNITDATA_REQ,"T_UNITDATA_REQ"},
462	{ T_OPTMGMT_REQ,"T_OPTMGMT_REQ"	},
463	{ T_ORDREL_REQ,	"T_ORDREL_REQ"	},
464	{ 0,		NULL		},
465};
466
467static struct xlat transport_user_flags [] = {
468	{ 0,		"0"		},
469	{ T_MORE,	"T_MORE"	},
470	{ T_EXPEDITED,	"T_EXPEDITED"	},
471	{ T_NEGOTIATE,	"T_NEGOTIATE"	},
472	{ T_CHECK,	"T_CHECK"	},
473	{ T_DEFAULT,	"T_DEFAULT"	},
474	{ T_SUCCESS,	"T_SUCCESS"	},
475	{ T_FAILURE,	"T_FAILURE"	},
476	{ T_CURRENT,	"T_CURRENT"	},
477	{ T_PARTSUCCESS,"T_PARTSUCCESS"	},
478	{ T_READONLY,	"T_READONLY"	},
479	{ T_NOTSUPPORT,	"T_NOTSUPPORT"	},
480	{ 0,		NULL		},
481};
482
483
484#ifdef HAVE_STRUCT_T_OPTHDR
485
486static struct xlat xti_level [] = {
487	{ XTI_GENERIC,	"XTI_GENERIC"	},
488	{ 0,		NULL		},
489};
490
491static struct xlat xti_generic [] = {
492	{ XTI_DEBUG,	"XTI_DEBUG"	},
493	{ XTI_LINGER,	"XTI_LINGER"	},
494	{ XTI_RCVBUF,	"XTI_RCVBUF"	},
495	{ XTI_RCVLOWAT,	"XTI_RCVLOWAT"	},
496	{ XTI_SNDBUF,	"XTI_SNDBUF"	},
497	{ XTI_SNDLOWAT,	"XTI_SNDLOWAT"	},
498	{ 0,		NULL		},
499};
500
501
502
503void
504print_xti_optmgmt (tcp, addr, len)
505struct tcb *tcp;
506long addr;
507int len;
508{
509	int c = 0;
510	struct t_opthdr hdr;
511
512	while (len >= (int) sizeof hdr) {
513		if (umove(tcp, addr, &hdr) < 0) break;
514		if (c++) {
515			tprintf (", ");
516		}
517		else if (len > hdr.len + sizeof hdr) {
518			tprintf ("[");
519		}
520		tprintf ("{level=");
521		printxval (xti_level, hdr.level, "???");
522		tprintf (", name=");
523		switch (hdr.level) {
524		    case XTI_GENERIC:
525			printxval (xti_generic, hdr.name, "XTI_???");
526			break;
527		    default:
528			tprintf ("%ld", hdr.name);
529			break;
530		}
531		tprintf (", status=");
532		printxval (transport_user_flags,  hdr.status, "T_???");
533		addr += sizeof hdr;
534		len -= sizeof hdr;
535		if ((hdr.len -= sizeof hdr) > 0) {
536			if (hdr.len > len) break;
537			tprintf (", val=");
538			if (len == sizeof (int))
539				printnum (tcp, addr, "%d");
540			else
541				printstr (tcp, addr, hdr.len);
542			addr += hdr.len;
543			len -= hdr.len;
544		}
545		tprintf ("}");
546	}
547	if (len > 0) {
548		if (c++) tprintf (", ");
549		printstr (tcp, addr, len);
550	}
551	if (c > 1) tprintf ("]");
552}
553
554#endif
555
556
557static void
558print_optmgmt (tcp, addr, len)
559struct tcb *tcp;
560long addr;
561int len;
562{
563	/* We don't know how to tell if TLI (socket) or XTI
564	   optmgmt is being used yet, assume TLI. */
565#if defined (HAVE_STRUCT_OPTHDR)
566	print_sock_optmgmt (tcp, addr, len);
567#elif defined (HAVE_STRUCT_T_OPTHDR)
568	print_xti_optmgmt (tcp, addr, len);
569#else
570	printstr (tcp, addr, len);
571#endif
572}
573
574
575
576
577static struct xlat service_type [] = {
578	{ T_COTS,	"T_COTS"	},
579	{ T_COTS_ORD,	"T_COTS_ORD"	},
580	{ T_CLTS,	"T_CLTS"	},
581	{ 0,		NULL		},
582};
583
584static struct xlat ts_state [] = {
585	{ TS_UNBND,	"TS_UNBND"	},
586	{ TS_WACK_BREQ,	"TS_WACK_BREQ"	},
587	{ TS_WACK_UREQ,	"TS_WACK_UREQ"	},
588	{ TS_IDLE,	"TS_IDLE"	},
589	{ TS_WACK_OPTREQ,"TS_WACK_OPTREQ"},
590	{ TS_WACK_CREQ,	"TS_WACK_CREQ"	},
591	{ TS_WCON_CREQ,	"TS_WCON_CREQ"	},
592	{ TS_WRES_CIND,	"TS_WRES_CIND"	},
593	{ TS_WACK_CRES,	"TS_WACK_CRES"	},
594	{ TS_DATA_XFER,	"TS_DATA_XFER"	},
595	{ TS_WIND_ORDREL,"TS_WIND_ORDREL"},
596	{ TS_WREQ_ORDREL,"TS_WREQ_ORDREL"},
597	{ TS_WACK_DREQ6,"TS_WACK_DREQ6"	},
598	{ TS_WACK_DREQ7,"TS_WACK_DREQ7"	},
599	{ TS_WACK_DREQ9,"TS_WACK_DREQ9"	},
600	{ TS_WACK_DREQ10,"TS_WACK_DREQ10"},
601	{ TS_WACK_DREQ11,"TS_WACK_DREQ11"},
602	{ 0,		NULL		},
603};
604
605static struct xlat provider_flags [] = {
606	{ 0,		"0"		},
607	{ SENDZERO,	"SENDZERO"	},
608	{ EXPINLINE,	"EXPINLINE"	},
609	{ XPG4_1,	"XPG4_1"	},
610	{ 0,		NULL		},
611};
612
613
614static struct xlat tli_errors [] = {
615	{ TBADADDR,	"TBADADDR"	},
616	{ TBADOPT,	"TBADOPT"	},
617	{ TACCES,	"TACCES"	},
618	{ TBADF,	"TBADF"		},
619	{ TNOADDR,	"TNOADDR"	},
620	{ TOUTSTATE,	"TOUTSTATE"	},
621	{ TBADSEQ,	"TBADSEQ"	},
622	{ TSYSERR,	"TSYSERR"	},
623	{ TLOOK,	"TLOOK"		},
624	{ TBADDATA,	"TBADDATA"	},
625	{ TBUFOVFLW,	"TBUFOVFLW"	},
626	{ TFLOW,	"TFLOW"		},
627	{ TNODATA,	"TNODATA"	},
628	{ TNODIS,	"TNODIS"	},
629	{ TNOUDERR,	"TNOUDERR"	},
630	{ TBADFLAG,	"TBADFLAG"	},
631	{ TNOREL,	"TNOREL"	},
632	{ TNOTSUPPORT,	"TNOTSUPPORT"	},
633	{ TSTATECHNG,	"TSTATECHNG"	},
634	{ TNOSTRUCTYPE,	"TNOSTRUCTYPE"	},
635	{ TBADNAME,	"TBADNAME"	},
636	{ TBADQLEN,	"TBADQLEN"	},
637	{ TADDRBUSY,	"TADDRBUSY"	},
638	{ TINDOUT,	"TINDOUT"	},
639	{ TPROVMISMATCH,"TPROVMISMATCH"	},
640	{ TRESQLEN,	"TRESQLEN"	},
641	{ TRESADDR,	"TRESADDR"	},
642	{ TQFULL,	"TQFULL"	},
643	{ TPROTO,	"TPROTO"	},
644	{ 0,		NULL		},
645};
646
647
648static int
649print_transport_message (tcp, expect, addr, len)
650struct tcb *tcp;
651int expect;
652long addr;
653int len;
654{
655	union T_primitives m;
656	int c = 0;
657
658	if (len < sizeof m.type) goto dump;
659
660	if (umove (tcp, addr, &m.type) < 0) goto dump;
661
662#define GET(type, struct)	\
663	do {							\
664		if (len < sizeof m.struct) goto dump;		\
665		if (umove (tcp, addr, &m.struct) < 0) goto dump;\
666		tprintf ("{");					\
667		if (expect != type) {				\
668			++c;					\
669			tprintf (#type);			\
670		}						\
671	}							\
672	while (0)
673
674#define COMMA() \
675	do { if (c++) tprintf (", "); } while (0)
676
677
678#define STRUCT(struct, elem, print)					\
679	do {								\
680		COMMA ();						\
681		if (m.struct.elem##_length < 0 ||			\
682		    m.struct.elem##_offset < sizeof m.struct ||		\
683		    m.struct.elem##_offset + m.struct.elem##_length > len) \
684		{							\
685			tprintf (#elem "_length=%ld, " #elem "_offset=%ld",\
686				m.struct.elem##_length,			\
687				m.struct.elem##_offset);		\
688		}							\
689		else {							\
690			tprintf (#elem "=");				\
691			print (tcp,					\
692				 addr + m.struct.elem##_offset,		\
693				 m.struct.elem##_length);		\
694		}							\
695	}								\
696	while (0)
697
698#define ADDR(struct, elem) STRUCT (struct, elem, printstr)
699
700	switch (m.type) {
701#ifdef T_CONN_REQ
702	    case T_CONN_REQ:	/* connect request   */
703		GET (T_CONN_REQ, conn_req);
704		ADDR (conn_req, DEST);
705		ADDR (conn_req, OPT);
706		break;
707#endif
708#ifdef T_CONN_RES
709	    case T_CONN_RES:	/* connect response   */
710		GET (T_CONN_RES, conn_res);
711#ifdef HAVE_STRUCT_T_CONN_RES_QUEUE_PTR
712		COMMA ();
713		tprintf ("QUEUE=%p", m.conn_res.QUEUE_ptr);
714#elif defined HAVE_STRUCT_T_CONN_RES_ACCEPTOR_ID
715		COMMA ();
716		tprintf ("ACCEPTOR=%#lx", m.conn_res.ACCEPTOR_id);
717#endif
718		ADDR (conn_res, OPT);
719		COMMA ();
720		tprintf ("SEQ=%ld", m.conn_res.SEQ_number);
721		break;
722#endif
723#ifdef T_DISCON_REQ
724	    case T_DISCON_REQ:	/* disconnect request */
725		GET (T_DISCON_REQ, discon_req);
726		COMMA ();
727		tprintf ("SEQ=%ld", m.discon_req.SEQ_number);
728		break;
729#endif
730#ifdef T_DATA_REQ
731	    case T_DATA_REQ:	/* data request       */
732		GET (T_DATA_REQ, data_req);
733		COMMA ();
734		tprintf ("MORE=%ld", m.data_req.MORE_flag);
735		break;
736#endif
737#ifdef T_EXDATA_REQ
738	    case T_EXDATA_REQ:	/* expedited data req */
739		GET (T_EXDATA_REQ, exdata_req);
740		COMMA ();
741		tprintf ("MORE=%ld", m.exdata_req.MORE_flag);
742		break;
743#endif
744#ifdef T_INFO_REQ
745	    case T_INFO_REQ:	/* information req    */
746		GET (T_INFO_REQ, info_req);
747		break;
748#endif
749#ifdef T_BIND_REQ
750	    case T_BIND_REQ:	/* bind request       */
751#ifdef O_T_BIND_REQ
752	    case O_T_BIND_REQ:	/* Ugly xti/tli hack */
753#endif
754		GET (T_BIND_REQ, bind_req);
755		ADDR (bind_req, ADDR);
756		COMMA ();
757		tprintf ("CONIND=%ld", m.bind_req.CONIND_number);
758		break;
759#endif
760#ifdef T_UNBIND_REQ
761	    case T_UNBIND_REQ:	/* unbind request     */
762		GET (T_UNBIND_REQ, unbind_req);
763		break;
764#endif
765#ifdef T_UNITDATA_REQ
766	    case T_UNITDATA_REQ:	/* unitdata requset   */
767		GET (T_UNITDATA_REQ, unitdata_req);
768		ADDR (unitdata_req, DEST);
769		ADDR (unitdata_req, OPT);
770		break;
771#endif
772#ifdef T_OPTMGMT_REQ
773	    case T_OPTMGMT_REQ:	/* manage opt req     */
774		GET (T_OPTMGMT_REQ, optmgmt_req);
775		COMMA ();
776		tprintf ("MGMT=");
777		printflags (transport_user_flags, m.optmgmt_req.MGMT_flags);
778		STRUCT (optmgmt_req, OPT, print_optmgmt);
779		break;
780#endif
781#ifdef T_ORDREL_REQ
782	    case T_ORDREL_REQ:	/* orderly rel req    */
783		GET (T_ORDREL_REQ, ordrel_req);
784		break;
785#endif
786#ifdef T_CONN_IND
787	    case T_CONN_IND:	/* connect indication */
788		GET (T_CONN_IND, conn_ind);
789		ADDR (conn_ind, SRC);
790		ADDR (conn_ind, OPT);
791		tprintf (", SEQ=%ld", m.conn_ind.SEQ_number);
792		break;
793#endif
794#ifdef T_CONN_CON
795	    case T_CONN_CON:	/* connect corfirm    */
796		GET (T_CONN_CON, conn_con);
797		ADDR (conn_con, RES);
798		ADDR (conn_con, OPT);
799		break;
800#endif
801#ifdef T_DISCON_IND
802	    case T_DISCON_IND:	/* discon indication  */
803		GET (T_DISCON_IND, discon_ind);
804		COMMA ();
805		tprintf ("DISCON=%ld, SEQ=%ld",
806			 m.discon_ind.DISCON_reason, m.discon_ind.SEQ_number);
807		break;
808#endif
809#ifdef T_DATA_IND
810	    case T_DATA_IND:	/* data indication    */
811		GET (T_DATA_IND, data_ind);
812		COMMA ();
813		tprintf ("MORE=%ld", m.data_ind.MORE_flag);
814		break;
815#endif
816#ifdef T_EXDATA_IND
817	    case T_EXDATA_IND:	/* expedited data ind */
818		GET (T_EXDATA_IND, exdata_ind);
819		COMMA ();
820		tprintf ("MORE=%ld", m.exdata_ind.MORE_flag);
821		break;
822#endif
823#ifdef T_INFO_ACK
824	    case T_INFO_ACK:	/* info ack           */
825		GET (T_INFO_ACK, info_ack);
826		COMMA ();
827		tprintf ("TSDU=%ld, ETSDU=%ld, CDATA=%ld, DDATA=%ld, "
828			 "ADDR=%ld, OPT=%ld, TIDU=%ld, SERV=",
829			 m.info_ack.TSDU_size, m.info_ack.ETSDU_size,
830			 m.info_ack.CDATA_size, m.info_ack.DDATA_size,
831			 m.info_ack.ADDR_size, m.info_ack.OPT_size,
832			 m.info_ack.TIDU_size);
833		printxval (service_type, m.info_ack.SERV_type, "T_???");
834		tprintf (", CURRENT=");
835		printxval (ts_state, m.info_ack.CURRENT_state, "TS_???");
836		tprintf (", PROVIDER=");
837		printflags (provider_flags, m.info_ack.PROVIDER_flag);
838		break;
839#endif
840#ifdef T_BIND_ACK
841	    case T_BIND_ACK:	/* bind ack           */
842		GET (T_BIND_ACK, bind_ack);
843		ADDR (bind_ack, ADDR);
844		tprintf (", CONIND=%ld", m.bind_ack.CONIND_number);
845		break;
846#endif
847#ifdef T_ERROR_ACK
848	    case T_ERROR_ACK:	/* error ack          */
849		GET (T_ERROR_ACK, error_ack);
850		COMMA ();
851		tprintf ("ERROR=");
852		printxval (transport_user_options,
853			   m.error_ack.ERROR_prim, "TI_???");
854		tprintf (", TLI=");
855		printxval (tli_errors, m.error_ack.TLI_error, "T???");
856		tprintf ("UNIX=%s", strerror (m.error_ack.UNIX_error));
857		break;
858#endif
859#ifdef T_OK_ACK
860	    case T_OK_ACK:	/* ok ack             */
861		GET (T_OK_ACK, ok_ack);
862		COMMA ();
863		tprintf ("CORRECT=");
864		printxval (transport_user_options,
865			   m.ok_ack.CORRECT_prim, "TI_???");
866		break;
867#endif
868#ifdef T_UNITDATA_IND
869	    case T_UNITDATA_IND:	/* unitdata ind       */
870		GET (T_UNITDATA_IND, unitdata_ind);
871		ADDR (unitdata_ind, SRC);
872		ADDR (unitdata_ind, OPT);
873		break;
874#endif
875#ifdef T_UDERROR_IND
876	    case T_UDERROR_IND:	/* unitdata error ind */
877		GET (T_UDERROR_IND, uderror_ind);
878		ADDR (uderror_ind, DEST);
879		ADDR (uderror_ind, OPT);
880		tprintf (", ERROR=%ld", m.uderror_ind.ERROR_type);
881		break;
882#endif
883#ifdef T_OPTMGMT_ACK
884	    case T_OPTMGMT_ACK:	/* manage opt ack     */
885		GET (T_OPTMGMT_ACK, optmgmt_ack);
886		COMMA ();
887		tprintf ("MGMT=");
888		printflags (transport_user_flags, m.optmgmt_ack.MGMT_flags);
889		STRUCT (optmgmt_ack, OPT, print_optmgmt);
890		break;
891#endif
892#ifdef T_ORDREL_IND
893	case T_ORDREL_IND:	/* orderly rel ind    */
894		GET (T_ORDREL_IND, ordrel_ind);
895		break;
896#endif
897#ifdef T_ADDR_REQ
898	    case T_ADDR_REQ:	/* address req        */
899		GET (T_ADDR_REQ, addr_req);
900		break;
901#endif
902#ifdef T_ADDR_ACK
903	    case T_ADDR_ACK:	/* address response   */
904		GET (T_ADDR_ACK, addr_ack);
905		ADDR (addr_ack, LOCADDR);
906		ADDR (addr_ack, REMADDR);
907		break;
908#endif
909	    default:
910	    dump:
911		c = -1;
912		printstr(tcp, addr, len);
913		break;
914	}
915
916	if (c >= 0) tprintf ("}");
917
918#undef ADDR
919#undef COMMA
920#undef STRUCT
921
922	return 0;
923}
924
925
926#endif /* TI_BIND */
927
928
929static int
930internal_stream_ioctl(tcp, arg)
931struct tcb *tcp;
932int arg;
933{
934	struct strioctl si;
935	strict ioctlent *iop;
936	int in_and_out;
937	int timod = 0;
938#ifdef SI_GETUDATA
939	struct si_udata udata;
940#endif /* SI_GETUDATA */
941
942	if (!arg)
943		return 0;
944	if (umove(tcp, arg, &si) < 0) {
945		if (entering(tcp))
946			tprintf(", {...}");
947		return 1;
948	}
949	if (entering(tcp)) {
950		iop = ioctl_lookup(si.ic_cmd);
951		if (iop) {
952			tprintf(", {ic_cmd=%s", iop->symbol);
953			while ((iop = ioctl_next_match(iop)))
954				tprintf(" or %s", iop->symbol);
955		} else
956			tprintf(", {ic_cmd=%#x", si.ic_cmd);
957		if (si.ic_timout == INFTIM)
958			tprintf(", ic_timout=INFTIM, ");
959		else
960			tprintf(" ic_timout=%d, ", si.ic_timout);
961	}
962	in_and_out = 1;
963	switch (si.ic_cmd) {
964#ifdef SI_GETUDATA
965	case SI_GETUDATA:
966		in_and_out = 0;
967		break;
968#endif /* SI_GETUDATA */
969	}
970	if (in_and_out) {
971		if (entering(tcp))
972			tprintf("/* in */ ");
973		else
974			tprintf(", /* out */ ");
975	}
976	if (in_and_out || entering(tcp))
977		tprintf("ic_len=%d, ic_dp=", si.ic_len);
978	switch (si.ic_cmd) {
979#ifdef TI_BIND
980	case TI_BIND:
981		/* in T_BIND_REQ, out T_BIND_ACK */
982		++timod;
983		if (entering(tcp)) {
984			print_transport_message (tcp,
985						 T_BIND_REQ,
986						 si.ic_dp, si.ic_len);
987		}
988		else {
989			print_transport_message (tcp,
990						 T_BIND_ACK,
991						 si.ic_dp, si.ic_len);
992		}
993		break;
994#endif /* TI_BIND */
995#ifdef TI_UNBIND
996	case TI_UNBIND:
997		/* in T_UNBIND_REQ, out T_OK_ACK */
998		++timod;
999		if (entering(tcp)) {
1000			print_transport_message (tcp,
1001						 T_UNBIND_REQ,
1002						 si.ic_dp, si.ic_len);
1003		}
1004		else {
1005			print_transport_message (tcp,
1006						 T_OK_ACK,
1007						 si.ic_dp, si.ic_len);
1008		}
1009		break;
1010#endif /* TI_UNBIND */
1011#ifdef TI_GETINFO
1012	case TI_GETINFO:
1013		/* in T_INFO_REQ, out T_INFO_ACK */
1014		++timod;
1015		if (entering(tcp)) {
1016			print_transport_message (tcp,
1017						 T_INFO_REQ,
1018						 si.ic_dp, si.ic_len);
1019		}
1020		else {
1021			print_transport_message (tcp,
1022						 T_INFO_ACK,
1023						 si.ic_dp, si.ic_len);
1024		}
1025		break;
1026#endif /* TI_GETINFO */
1027#ifdef TI_OPTMGMT
1028	case TI_OPTMGMT:
1029		/* in T_OPTMGMT_REQ, out T_OPTMGMT_ACK */
1030		++timod;
1031		if (entering(tcp)) {
1032			print_transport_message (tcp,
1033						 T_OPTMGMT_REQ,
1034						 si.ic_dp, si.ic_len);
1035		}
1036		else {
1037			print_transport_message (tcp,
1038						 T_OPTMGMT_ACK,
1039						 si.ic_dp, si.ic_len);
1040		}
1041		break;
1042#endif /* TI_OPTMGMT */
1043#ifdef SI_GETUDATA
1044	case SI_GETUDATA:
1045		if (entering(tcp))
1046			break;
1047#if 0
1048		tprintf("struct si_udata ");
1049#endif
1050		if (umove(tcp, (int) si.ic_dp, &udata) < 0)
1051			tprintf("{...}");
1052		else {
1053			tprintf("{tidusize=%d, addrsize=%d, ",
1054				udata.tidusize, udata.addrsize);
1055			tprintf("optsize=%d, etsdusize=%d, ",
1056				udata.optsize, udata.etsdusize);
1057			tprintf("servtype=%d, so_state=%d, ",
1058				udata.servtype, udata.so_state);
1059			tprintf("so_options=%d", udata.so_options);
1060#if 0
1061			tprintf(", tsdusize=%d", udata.tsdusize);
1062#endif
1063			tprintf("}");
1064		}
1065		break;
1066#endif /* SI_GETUDATA */
1067	default:
1068		printstr(tcp, (long) si.ic_dp, si.ic_len);
1069		break;
1070	}
1071	if (exiting(tcp)) {
1072		tprintf("}");
1073		if (timod && tcp->u_rval) {
1074			tcp->auxstr = xlookup (tli_errors, tcp->u_rval);
1075			return RVAL_STR + 1;
1076		}
1077	}
1078
1079	return 1;
1080}
1081
1082int
1083stream_ioctl(tcp, code, arg)
1084struct tcb *tcp;
1085int code, arg;
1086{
1087#ifdef I_LIST
1088	int i;
1089#endif
1090	int val;
1091#ifdef I_FLUSHBAND
1092	struct bandinfo bi;
1093#endif
1094	struct strpeek sp;
1095	struct strfdinsert sfi;
1096	struct strrecvfd srf;
1097#ifdef I_LIST
1098	struct str_list sl;
1099#endif
1100
1101	/* I_STR is a special case because the data is read & written. */
1102	if (code == I_STR)
1103		return internal_stream_ioctl(tcp, arg);
1104	if (entering(tcp))
1105		return 0;
1106
1107	switch (code) {
1108	case I_PUSH:
1109	case I_LOOK:
1110	case I_FIND:
1111		/* arg is a string */
1112		tprintf(", ");
1113		printpath(tcp, arg);
1114		return 1;
1115	case I_POP:
1116		/* doesn't take an argument */
1117		return 1;
1118	case I_FLUSH:
1119		/* argument is an option */
1120		tprintf(", ");
1121		printxval(stream_flush_options, arg, "FLUSH???");
1122		return 1;
1123#ifdef I_FLUSHBAND
1124	case I_FLUSHBAND:
1125		/* argument is a pointer to a bandinfo struct */
1126		if (umove(tcp, arg, &bi) < 0)
1127			tprintf(", {...}");
1128		else {
1129			tprintf(", {bi_pri=%d, bi_flag=", bi.bi_pri);
1130			if (!printflags(stream_flush_options, bi.bi_flag))
1131				tprintf("0");
1132			tprintf("}");
1133		}
1134		return 1;
1135#endif /* I_FLUSHBAND */
1136	case I_SETSIG:
1137		/* argument is a set of flags */
1138		tprintf(", ");
1139		if (!printflags(stream_setsig_flags, arg))
1140			tprintf("0");
1141		return 1;
1142	case I_GETSIG:
1143		/* argument is a pointer to a set of flags */
1144		if (syserror(tcp))
1145			return 0;
1146		tprintf(", [");
1147		if (umove(tcp, arg, &val) < 0)
1148			tprintf("?");
1149		else if (!printflags(stream_setsig_flags, val))
1150			tprintf("0");
1151		tprintf("]");
1152		return 1;
1153	case I_PEEK:
1154		/* argument is a pointer to a strpeek structure */
1155		if (syserror(tcp) || !arg)
1156			return 0;
1157		if (umove(tcp, arg, &sp) < 0) {
1158			tprintf(", {...}");
1159			return 1;
1160		}
1161		tprintf(", {ctlbuf=");
1162		printstrbuf(tcp, &sp.ctlbuf, 1);
1163		tprintf(", databuf=");
1164		printstrbuf(tcp, &sp.databuf, 1);
1165		tprintf(", flags=");
1166		if (!printflags(msgflags, sp.flags))
1167			tprintf("0");
1168		tprintf("}");
1169		return 1;
1170	case I_SRDOPT:
1171		/* argument is an option with flags */
1172		tprintf(", ");
1173		printxval(stream_read_options, arg & RMODEMASK, "R???");
1174		addflags(stream_read_flags, arg & ~RMODEMASK);
1175		return 1;
1176	case I_GRDOPT:
1177		/* argument is an pointer to an option with flags */
1178		if (syserror(tcp))
1179			return 0;
1180		tprintf(", [");
1181		if (umove(tcp, arg, &val) < 0)
1182			tprintf("?");
1183		else {
1184			printxval(stream_read_options,
1185				  arg & RMODEMASK, "R???");
1186			addflags(stream_read_flags, arg & ~RMODEMASK);
1187		}
1188		tprintf("]");
1189		return 1;
1190	case I_NREAD:
1191#ifdef I_GETBAND
1192	case I_GETBAND:
1193#endif
1194#ifdef I_SETCLTIME
1195	case I_SETCLTIME:
1196#endif
1197#ifdef I_GETCLTIME
1198	case I_GETCLTIME:
1199#endif
1200		/* argument is a pointer to a decimal integer */
1201		if (syserror(tcp))
1202			return 0;
1203		tprintf(", ");
1204		printnum(tcp, arg, "%d");
1205		return 1;
1206	case I_FDINSERT:
1207		/* argument is a pointer to a strfdinsert structure */
1208		if (syserror(tcp) || !arg)
1209			return 0;
1210		if (umove(tcp, arg, &sfi) < 0) {
1211			tprintf(", {...}");
1212			return 1;
1213		}
1214		tprintf(", {ctlbuf=");
1215		printstrbuf(tcp, &sfi.ctlbuf, 1);
1216		tprintf(", databuf=");
1217		printstrbuf(tcp, &sfi.databuf, 1);
1218		tprintf(", flags=");
1219		if (!printflags(msgflags, sfi.flags))
1220			tprintf("0");
1221		tprintf(", filedes=%d, offset=%d}", sfi.fildes, sfi.offset);
1222		return 1;
1223#ifdef I_SWROPT
1224	case I_SWROPT:
1225		/* argument is a set of flags */
1226		tprintf(", ");
1227		if (!printflags(stream_write_flags, arg))
1228			tprintf("0");
1229		return 1;
1230#endif /* I_SWROPT */
1231#ifdef I_GWROPT
1232	case I_GWROPT:
1233		/* argument is an pointer to an option with flags */
1234		if (syserror(tcp))
1235			return 0;
1236		tprintf(", [");
1237		if (umove(tcp, arg, &val) < 0)
1238			tprintf("?");
1239		else if (!printflags(stream_write_flags, arg))
1240			tprintf("0");
1241		tprintf("]");
1242		return 1;
1243#endif /* I_GWROPT */
1244	case I_SENDFD:
1245#ifdef I_CKBAND
1246	case I_CKBAND:
1247#endif
1248#ifdef I_CANPUT
1249	case I_CANPUT:
1250#endif
1251	case I_LINK:
1252	case I_UNLINK:
1253	case I_PLINK:
1254	case I_PUNLINK:
1255		/* argument is a decimal integer */
1256		tprintf(", %d", arg);
1257		return 1;
1258	case I_RECVFD:
1259		/* argument is a pointer to a strrecvfd structure */
1260		if (syserror(tcp) || !arg)
1261			return 0;
1262		if (umove(tcp, arg, &srf) < 0) {
1263			tprintf(", {...}");
1264			return 1;
1265		}
1266		tprintf(", {fd=%d, uid=%lu, gid=%lu}", srf.fd,
1267			(unsigned long) srf.uid, (unsigned long) srf.gid);
1268		return 1;
1269#ifdef I_LIST
1270	case I_LIST:
1271		if (syserror(tcp))
1272			return 0;
1273		if (arg == 0) {
1274			tprintf(", NULL");
1275			return 1;
1276		}
1277		if (umove(tcp, arg, &sl) < 0) {
1278			tprintf(", {...}");
1279			return 1;
1280		}
1281		tprintf(", {sl_nmods=%d, sl_modlist=[", sl.sl_nmods);
1282		for (i = 0; i < tcp->u_rval; i++) {
1283			if (i)
1284				tprintf(", ");
1285			printpath(tcp, (int) sl.sl_modlist[i].l_name);
1286		}
1287		tprintf("]}");
1288		return 1;
1289#endif /* I_LIST */
1290#ifdef I_ATMARK
1291	case I_ATMARK:
1292		tprintf(", ");
1293		printxval(stream_atmark_options, arg, "???MARK");
1294		return 1;
1295#endif /* I_ATMARK */
1296	default:
1297		return 0;
1298	}
1299}
1300
1301#endif /* !LINUX && !FREEBSD */
1302
1303#endif /* HAVE_SYS_STREAM_H || LINUX || FREEBSD */
1304