net.c revision 38ae88d332acd9f86a30d58158e306d795d98977
1/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5 * Copyright (c) 1996-2000 Wichert Akkerman <wichert@cistron.nl>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 *    derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 *	$Id$
31 */
32
33#include "defs.h"
34
35#include <sys/stat.h>
36#include <sys/socket.h>
37#include <sys/un.h>
38
39#if defined(HAVE_SIN6_SCOPE_ID_LINUX)
40#define in6_addr in6_addr_libc
41#define ipv6_mreq ipv6_mreq_libc
42#define sockaddr_in6 sockaddr_in6_libc
43#endif
44
45#include <netinet/in.h>
46#ifdef HAVE_NETINET_TCP_H
47#include <netinet/tcp.h>
48#endif
49#ifdef HAVE_NETINET_UDP_H
50#include <netinet/udp.h>
51#endif
52#include <arpa/inet.h>
53#include <net/if.h>
54#if defined(LINUX)
55#include <asm/types.h>
56#if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC__ + __GLIBC_MINOR__ >= 3)
57#  include <netipx/ipx.h>
58#else
59#  include <linux/ipx.h>
60#endif
61#endif /* LINUX */
62
63#if defined (__GLIBC__) && (((__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1)) || defined(HAVE_SIN6_SCOPE_ID_LINUX))
64#if defined(HAVE_LINUX_IN6_H)
65#if defined(HAVE_SIN6_SCOPE_ID_LINUX)
66#undef in6_addr
67#undef ipv6_mreq
68#undef sockaddr_in6
69#define in6_addr in6_addr_kernel
70#define ipv6_mreq ipv6_mreq_kernel
71#define sockaddr_in6 sockaddr_in6_kernel
72#endif
73#include <linux/in6.h>
74#if defined(HAVE_SIN6_SCOPE_ID_LINUX)
75#undef in6_addr
76#undef ipv6_mreq
77#undef sockaddr_in6
78#define in6_addr in6_addr_libc
79#define ipv6_mreq ipv6_mreq_libc
80#define sockaddr_in6 sockaddr_in6_kernel
81#endif
82#endif
83#endif
84
85#if defined(HAVE_SYS_UIO_H)
86#include <sys/uio.h>
87#endif
88
89#if defined(HAVE_LINUX_NETLINK_H)
90#include <linux/netlink.h>
91#endif
92
93#if defined(HAVE_LINUX_IF_PACKET_H)
94#include <linux/if_packet.h>
95#endif
96
97#if defined(HAVE_LINUX_ICMP_H)
98#include <linux/icmp.h>
99#endif
100
101#ifndef PF_UNSPEC
102#define PF_UNSPEC AF_UNSPEC
103#endif
104
105#if UNIXWARE >= 7
106#define HAVE_SENDMSG		1		/* HACK - *FIXME* */
107#endif
108
109#ifdef LINUX
110/* Under Linux these are enums so we can't test for them with ifdef. */
111#define IPPROTO_EGP IPPROTO_EGP
112#define IPPROTO_PUP IPPROTO_PUP
113#define IPPROTO_IDP IPPROTO_IDP
114#define IPPROTO_IGMP IPPROTO_IGMP
115#define IPPROTO_RAW IPPROTO_RAW
116#define IPPROTO_MAX IPPROTO_MAX
117#endif
118
119static struct xlat domains[] = {
120	{ PF_UNSPEC,	"PF_UNSPEC"	},
121	{ PF_UNIX,	"PF_UNIX"	},
122	{ PF_INET,	"PF_INET"	},
123#ifdef PF_NETLINK
124	{ PF_NETLINK,	"PF_NETLINK"	},
125#endif
126#ifdef PF_PACKET
127	{ PF_PACKET,	"PF_PACKET"	},
128#endif
129#ifdef PF_INET6
130	{ PF_INET6,	"PF_INET6"	},
131#endif
132#ifdef PF_ATMSVC
133	{ PF_ATMSVC,	"PF_INET6"	},
134#endif
135#ifdef PF_INET6
136	{ PF_INET6,	"PF_INET6"	},
137#endif
138#ifdef PF_LOCAL
139	{ PF_LOCAL,	"PS_LOCAL"	},
140#endif
141#ifdef PF_ISO
142	{ PF_ISO,	"PF_ISO"	},
143#endif
144#ifdef PF_AX25
145	{ PF_AX25,	"PF_AX25"	},
146#endif
147#ifdef PF_IPX
148	{ PF_IPX,	"PF_IPX"	},
149#endif
150#ifdef PF_APPLETALK
151	{ PF_APPLETALK,	"PF_APPLETALK"	},
152#endif
153#ifdef PF_NETROM
154	{ PF_NETROM,	"PF_NETROM"	},
155#endif
156#ifdef PF_BRIDGE
157	{ PF_BRIDGE,	"PF_BRIDGE"	},
158#endif
159#ifdef PF_AAL5
160	{ PF_AAL5,	"PF_AAL5"	},
161#endif
162#ifdef PF_X25
163	{ PF_X25,	"PF_X25"	},
164#endif
165#ifdef PF_ROSE
166	{ PF_ROSE,	"PF_ROSE"	},
167#endif
168#ifdef PF_DECNET
169	{ PF_DECNET,	"PF_DECNET"	},
170#endif
171#ifdef PF_NETBEUI
172	{ PF_NETBEUI,	"PF_NETBEUI"	},
173#endif
174#ifdef PF_IMPLINK
175	{ PF_IMPLINK,	"PF_IMPLINK"	},
176#endif
177	{ 0,		NULL		},
178};
179static struct xlat addrfams[] = {
180	{ AF_UNSPEC,	"AF_UNSPEC"	},
181	{ AF_UNIX,	"AF_UNIX"	},
182	{ AF_INET,	"AF_INET"	},
183#ifdef AF_INET6
184	{ AF_INET6,	"AF_INET6"	},
185#endif
186	{ AF_DECnet,	"AF_DECnet"	},
187#ifdef PF_ATMSVC
188	{ AF_ATMSVC,	"AF_ATMSVC"	},
189#endif
190#ifdef AF_PACKET
191	{ AF_PACKET,	"AF_PACKET"	},
192#endif
193#ifdef AF_NETLINK
194	{ AF_NETLINK,	"AF_NETLINK"	},
195#endif
196#ifdef AF_ISO
197	{ AF_ISO,	"AF_ISO"	},
198#endif
199#ifdef AF_IMPLINK
200	{ AF_IMPLINK,	"AF_IMPLINK"	},
201#endif
202	{ 0,		NULL		},
203};
204static struct xlat socktypes[] = {
205	{ SOCK_STREAM,	"SOCK_STREAM"	},
206	{ SOCK_DGRAM,	"SOCK_DGRAM"	},
207#ifdef SOCK_RAW
208	{ SOCK_RAW,	"SOCK_RAW"	},
209#endif
210#ifdef SOCK_SEQPACKET
211	{ SOCK_SEQPACKET,"SOCK_SEQPACKET"},
212#endif
213#ifdef SOCK_RDM
214	{ SOCK_RDM,	"SOCK_RDM"	},
215#endif
216#ifdef SOCK_PACKET
217	{ SOCK_PACKET,	"SOCK_PACKET"	},
218#endif
219	{ 0,		NULL		},
220};
221static struct xlat socketlayers[] = {
222#if defined(SOL_IP)
223	{ SOL_IP,	"SOL_IP"	},
224#endif
225#if defined(SOL_ICMP)
226	{ SOL_ICMP,	"SOL_ICMP"	},
227#endif
228#if defined(SOL_TCP)
229	{ SOL_TCP,	"SOL_TCP"	},
230#endif
231#if defined(SOL_UDP)
232	{ SOL_UDP,	"SOL_UDP"	},
233#endif
234#if defined(SOL_IPV6)
235	{ SOL_IPV6,	"SOL_IPV6"	},
236#endif
237#if defined(SOL_ICMPV6)
238	{ SOL_ICMPV6,	"SOL_ICMPV6"	},
239#endif
240#if defined(SOL_RAW)
241	{ SOL_RAW,	"SOL_RAW"	},
242#endif
243#if defined(SOL_IPX)
244	{ SOL_IPX,	"SOL_IPX"	},
245#endif
246#if defined(SOL_IPX)
247	{ SOL_IPX,	"SOL_IPX"	},
248#endif
249#if defined(SOL_AX25)
250	{ SOL_AX25,	"SOL_AX25"	},
251#endif
252#if defined(SOL_ATALK)
253	{ SOL_ATALK,	"SOL_ATALK"	},
254#endif
255#if defined(SOL_NETROM)
256	{ SOL_NETROM,	"SOL_NETROM"	},
257#endif
258#if defined(SOL_ROSE)
259	{ SOL_ROSE,	"SOL_ROSE"	},
260#endif
261#if defined(SOL_DECNET)
262	{ SOL_DECNET,	"SOL_DECNET"	},
263#endif
264#if defined(SOL_X25)
265	{ SOL_X25,	"SOL_X25"	},
266#endif
267#if defined(SOL_PACKET)
268	{ SOL_PACKET,	"SOL_PACKET"	},
269#endif
270#if defined(SOL_ATM)
271	{ SOL_ATM,	"SOL_ATM"	},
272#endif
273#if defined(SOL_AAL)
274	{ SOL_AAL,	"SOL_AAL"	},
275#endif
276#if defined(SOL_IRDA)
277	{ SOL_IRDA,	"SOL_IRDA"	},
278#endif
279	{ SOL_SOCKET,	"SOL_SOCKET"	},	/* Never used! */
280};
281/*** WARNING: DANGER WILL ROBINSON: NOTE "socketlayers" array above
282     falls into "protocols" array below!!!!   This is intended!!! ***/
283static struct xlat protocols[] = {
284	{ IPPROTO_IP,	"IPPROTO_IP"	},
285	{ IPPROTO_ICMP,	"IPPROTO_ICMP"	},
286	{ IPPROTO_TCP,	"IPPROTO_TCP"	},
287	{ IPPROTO_UDP,	"IPPROTO_UDP"	},
288#ifdef IPPROTO_GGP
289	{ IPPROTO_GGP,	"IPPROTO_GGP"	},
290#endif
291#ifdef IPPROTO_EGP
292	{ IPPROTO_EGP,	"IPPROTO_EGP"	},
293#endif
294#ifdef IPPROTO_PUP
295	{ IPPROTO_PUP,	"IPPROTO_PUP"	},
296#endif
297#ifdef IPPROTO_IDP
298	{ IPPROTO_IDP,	"IPPROTO_IDP"	},
299#endif
300#ifdef IPPROTO_IPV6
301	{ IPPROTO_IPV6,	"IPPROTO_IPV6"	},
302#endif
303#ifdef IPPROTO_ICMPV6
304	{ IPPROTO_ICMPV6,"IPPROTO_ICMPV6"},
305#endif
306#ifdef IPPROTO_IGMP
307	{ IPPROTO_IGMP,	"IPPROTO_IGMP"	},
308#endif
309#ifdef IPPROTO_HELLO
310	{ IPPROTO_HELLO,"IPPROTO_HELLO"	},
311#endif
312#ifdef IPPROTO_ND
313	{ IPPROTO_ND,	"IPPROTO_ND"	},
314#endif
315#ifdef IPPROTO_RAW
316	{ IPPROTO_RAW,	"IPPROTO_RAW"	},
317#endif
318#ifdef IPPROTO_MAX
319	{ IPPROTO_MAX,	"IPPROTO_MAX"	},
320#endif
321#ifdef IPPROTO_IPIP
322	{ IPPROTO_IPIP,	"IPPROTO_IPIP"	},
323#endif
324	{ 0,		NULL		},
325};
326static struct xlat msg_flags[] = {
327	{ MSG_OOB,	"MSG_OOB"	},
328#ifdef MSG_DONTROUTE
329	{ MSG_DONTROUTE,"MSG_DONTROUTE"	},
330#endif
331#ifdef MSG_PEEK
332	{ MSG_PEEK,	"MSG_PEEK"	},
333#endif
334#ifdef MSG_CTRUNC
335	{ MSG_CTRUNC,	"MSG_CTRUNC"	},
336#endif
337#ifdef MSG_PROXY
338	{ MSG_PROXY,	"MSG_PROXY"	},
339#endif
340#ifdef MSG_EOR
341	{ MSG_EOR,	"MSG_EOR"	},
342#endif
343#ifdef MSG_WAITALL
344	{ MSG_WAITALL,	"MSG_WAITALL"	},
345#endif
346#ifdef MSG_TRUNC
347	{ MSG_TRUNC,	"MSG_TRUNC"	},
348#endif
349#ifdef MSG_CTRUNC
350	{ MSG_CTRUNC,	"MSG_CTRUNC"	},
351#endif
352#ifdef MSG_ERRQUEUE
353	{ MSG_ERRQUEUE,	"MSG_ERRQUEUE"	},
354#endif
355#ifdef MSG_DONTWAIT
356	{ MSG_DONTWAIT,	"MSG_DONTWAIT"	},
357#endif
358#ifdef MSG_CONFIRM
359	{ MSG_CONFIRM,	"MSG_CONFIRM"	},
360#endif
361#ifdef MSG_PROBE
362	{ MSG_PROBE,	"MSG_PROBE"	},
363#endif
364	{ 0,		NULL		},
365};
366
367static struct xlat sockoptions[] = {
368#ifdef SO_PEERCRED
369	{ SO_PEERCRED,	"SO_PEERCRED"	},
370#endif
371#ifdef SO_PASSCRED
372	{ SO_PASSCRED,	"SO_PASSCRED"	},
373#endif
374#ifdef SO_DEBUG
375	{ SO_DEBUG,	"SO_DEBUG"	},
376#endif
377#ifdef SO_REUSEADDR
378	{ SO_REUSEADDR,	"SO_REUSEADDR"	},
379#endif
380#ifdef SO_KEEPALIVE
381	{ SO_KEEPALIVE,	"SO_KEEPALIVE"	},
382#endif
383#ifdef SO_DONTROUTE
384	{ SO_DONTROUTE,	"SO_DONTROUTE"	},
385#endif
386#ifdef SO_BROADCAST
387	{ SO_BROADCAST,	"SO_BROADCAST"	},
388#endif
389#ifdef SO_LINGER
390	{ SO_LINGER,	"SO_LINGER"	},
391#endif
392#ifdef SO_OOBINLINE
393	{ SO_OOBINLINE,	"SO_OOBINLINE"	},
394#endif
395#ifdef SO_TYPE
396	{ SO_TYPE,	"SO_TYPE"	},
397#endif
398#ifdef SO_ERROR
399	{ SO_ERROR,	"SO_ERROR"	},
400#endif
401#ifdef SO_SNDBUF
402	{ SO_SNDBUF,	"SO_SNDBUF"	},
403#endif
404#ifdef SO_RCVBUF
405	{ SO_RCVBUF,	"SO_RCVBUF"	},
406#endif
407#ifdef SO_NO_CHECK
408	{ SO_NO_CHECK,	"SO_NO_CHECK"	},
409#endif
410#ifdef SO_PRIORITY
411	{ SO_PRIORITY,	"SO_PRIORITY"	},
412#endif
413#ifdef SO_ACCEPTCONN
414	{ SO_ACCEPTCONN,"SO_ACCEPTCONN"	},
415#endif
416#ifdef SO_USELOOPBACK
417	{ SO_USELOOPBACK,"SO_USELOOPBACK"},
418#endif
419#ifdef SO_SNDLOWAT
420	{ SO_SNDLOWAT,	"SO_SNDLOWAT"	},
421#endif
422#ifdef SO_RCVLOWAT
423	{ SO_RCVLOWAT,	"SO_RCVLOWAT"	},
424#endif
425#ifdef SO_SNDTIMEO
426	{ SO_SNDTIMEO,	"SO_SNDTIMEO"	},
427#endif
428#ifdef SO_RCVTIMEO
429	{ SO_RCVTIMEO,	"SO_RCVTIMEO"	},
430#endif
431#ifdef SO_BSDCOMPAT
432	{ SO_BSDCOMPAT,	"SO_BSDCOMPAT"	},
433#endif
434#ifdef SO_REUSEPORT
435	{ SO_REUSEPORT,	"SO_REUSEPORT"	},
436#endif
437#ifdef SO_ORDREL
438	{ SO_ORDREL,	"SO_ORDREL"	},
439#endif
440#ifdef SO_IMASOCKET
441	{ SO_IMASOCKET,	"SO_IMASOCKET"	},
442#endif
443#ifdef SO_MGMT
444	{ SO_MGMT,	"SO_MGMT"	},
445#endif
446#ifdef SO_LISTENING
447	{ SO_LISTENING,	"SO_LISTENING"	},
448#endif
449#ifdef SO_RDWR
450	{ SO_RDWR,	"SO_RDWR"	},
451#endif
452#ifdef SO_SEMA
453	{ SO_SEMA,	"SO_SEMA"	},
454#endif
455#ifdef SO_PARALLELSVR
456	{ SO_PARALLELSVR,"SO_PARALLELSVR"},
457#endif
458#ifdef SO_PROTOTYPE
459	{ SO_PROTOTYPE,	"SO_PROTOTYPE"	},
460#endif
461#ifdef SO_ALLRAW
462	{ SO_ALLRAW,	"SO_ALLRAW"	},
463#endif
464#ifdef SO_ICS
465	{ SO_ICS,	"SO_ICS"	},
466#endif
467	{ 0,		NULL		},
468};
469
470#if !defined (SOL_IP) && defined (IPPROTO_IP)
471#define SOL_IP IPPROTO_IP
472#endif
473
474#ifdef SOL_IP
475static struct xlat sockipoptions[] = {
476#ifdef IP_TOS
477	{ IP_TOS,		"IP_TOS"		},
478#endif
479#ifdef IP_TTL
480	{ IP_TTL,		"IP_TTL"		},
481#endif
482#ifdef IP_HDRINCL
483	{ IP_HDRINCL,		"IP_HDRINCL"		},
484#endif
485#ifdef IP_OPTIONS
486	{ IP_OPTIONS,		"IP_OPTIONS"		},
487#endif
488#ifdef IP_ROUTER_ALERT
489	{ IP_ROUTER_ALERT,	"IP_ROUTER_ALERT"	},
490#endif
491#ifdef IP_RECVOPTIONS
492	{ IP_RECVOPTIONS,	"IP_RECVOPTIONS"	},
493#endif
494#ifdef IP_RECVOPTS
495	{ IP_RECVOPTS,		"IP_RECVOPTS"		},
496#endif
497#ifdef IP_RECVRETOPTS
498	{ IP_RECVRETOPTS,	"IP_RECVRETOPTS"	},
499#endif
500#ifdef IP_RECVDSTADDR
501	{ IP_RECVDSTADDR,	"IP_RECVDSTADDR"	},
502#endif
503#ifdef IP_RETOPTS
504	{ IP_RETOPTS,		"IP_RETOPTS"		},
505#endif
506#ifdef IP_PKTINFO
507	{ IP_PKTINFO,		"IP_PKTINFO"		},
508#endif
509#ifdef IP_PKTOPTIONS
510	{ IP_PKTOPTIONS,	"IP_PKTOPTIONS"		},
511#endif
512#ifdef IP_MTU_DISCOVER
513	{ IP_MTU_DISCOVER,	"IP_MTU_DISCOVER"	},
514#endif
515#ifdef IP_RECVERR
516	{ IP_RECVERR,		"IP_RECVERR"		},
517#endif
518#ifdef IP_RECVTTL
519	{ IP_RECVTTL,		"IP_RECRECVTTL"		},
520#endif
521#ifdef IP_RECVTOS
522	{ IP_RECVTOS,		"IP_RECRECVTOS"		},
523#endif
524#ifdef IP_MTU
525	{ IP_MTU,		"IP_MTU"		},
526#endif
527#ifdef IP_MULTICAST_IF
528	{ IP_MULTICAST_IF,	"IP_MULTICAST_IF"	},
529#endif
530#ifdef IP_MULTICAST_TTL
531	{ IP_MULTICAST_TTL,	"IP_MULTICAST_TTL"	},
532#endif
533#ifdef IP_MULTICAST_LOOP
534	{ IP_MULTICAST_LOOP,	"IP_MULTICAST_LOOP"	},
535#endif
536#ifdef IP_ADD_MEMBERSHIP
537	{ IP_ADD_MEMBERSHIP,	"IP_ADD_MEMBERSHIP"	},
538#endif
539#ifdef IP_DROP_MEMBERSHIP
540	{ IP_DROP_MEMBERSHIP,	"IP_DROP_MEMBERSHIP"	},
541#endif
542#ifdef IP_BROADCAST_IF
543	{ IP_BROADCAST_IF,	"IP_BROADCAST_IF"	},
544#endif
545#ifdef IP_RECVIFINDEX
546	{ IP_RECVIFINDEX,	"IP_RECVIFINDEX"	},
547#endif
548	{ 0,			NULL			},
549};
550#endif /* SOL_IP */
551
552#ifdef SOL_IPX
553static struct xlat sockipxoptions[] = {
554	{ IPX_TYPE,     "IPX_TYPE"      },
555	{ 0,            NULL            },
556};
557#endif /* SOL_IPX */
558
559#ifdef SOL_RAW
560static struct xlat sockrawoptions[] = {
561#if defined(ICMP_FILTER)
562	{ ICMP_FILTER,		"ICMP_FILTER"	},
563#endif
564	{ 0,			NULL		},
565};
566#endif /* SOL_RAW */
567
568#ifdef SOL_PACKET
569static struct xlat sockpacketoptions[] = {
570	{ PACKET_ADD_MEMBERSHIP,	"PACKET_ADD_MEMBERSHIP"	},
571	{ PACKET_DROP_MEMBERSHIP,	"PACKET_DROP_MEMBERSHIP"},
572#if defined(PACKET_RECV_OUTPUT)
573	{ PACKET_RECV_OUTPUT,		"PACKET_RECV_OUTPUT"	},
574#endif
575#if defined(PACKET_RX_RING)
576	{ PACKET_RX_RING,		"PACKET_RX_RING"	},
577#endif
578#if defined(PACKET_STATISTICS)
579	{ PACKET_STATISTICS,		"PACKET_STATISTICS"	},
580#endif
581	{ 0,				NULL			},
582};
583#endif /* SOL_PACKET */
584
585#if  !defined (SOL_TCP) && defined (IPPROTO_TCP)
586#define SOL_TCP IPPROTO_TCP
587#endif
588
589#ifdef SOL_TCP
590static struct xlat socktcpoptions[] = {
591	{ TCP_NODELAY,		"TCP_NODELAY"	},
592	{ TCP_MAXSEG,		"TCP_MAXSEG"	},
593#if defined(TCP_CORK)
594	{ TCP_CORK,		"TCP_CORK"	},
595#endif
596#if defined(TCP_KEEPIDLE)
597	{ TCP_KEEPIDLE,		"TCP_KEEPIDLE" },
598#endif
599#if defined(TCP_KEEPINTVL)
600	{ TCP_KEEPINTVL,	"TCP_KEEPINTVL" },
601#endif
602#if defined(TCP_KEEPCNT)
603	{ TCP_KEEPCNT,		"TCP_KEEPCNT" },
604#endif
605#if defined(TCP_NKEEP)
606	{ TCP_NKEEP,		"TCP_NKEEP"	},
607#endif
608#if defined(TCP_SYNCNT)
609	{ TCP_SYNCNT,		"TCP_SYNCNT" },
610#endif
611#if defined(TCP_LINGER2)
612	{ TCP_LINGER2,		"TCP_LINGER2" },
613#endif
614#if defined(TCP_DEFER_ACCEPT)
615	{ TCP_DEFER_ACCEPT,	"TCP_DEFER_ACCEPT" },
616#endif
617#if defined(TCP_WINDOW_CLAMP)
618	{ TCP_WINDOW_CLAMP,	"TCP_WINDOW_CLAMP" },
619#endif
620#if defined(TCP_INFO)
621	{ TCP_INFO,		"TCP_INFO" },
622#endif
623#if defined(TCP_QUICKACK)
624	{ TCP_QUICKACK,		"TCP_QUICKACK" },
625#endif
626	{ 0,			NULL		},
627};
628#endif /* SOL_TCP */
629
630#ifdef SOL_RAW
631static struct xlat icmpfilterflags[] = {
632#if defined(ICMP_ECHOREPLY)
633	{ (1<<ICMP_ECHOREPLY),		"ICMP_ECHOREPLY"	},
634#endif
635#if defined(ICMP_DEST_UNREACH)
636	{ (1<<ICMP_DEST_UNREACH),	"ICMP_DEST_UNREACH"	},
637#endif
638#if defined(ICMP_SOURCE_QUENCH)
639	{ (1<<ICMP_SOURCE_QUENCH),	"ICMP_SOURCE_QUENCH"	},
640#endif
641#if defined(ICMP_REDIRECT)
642	{ (1<<ICMP_REDIRECT),		"ICMP_REDIRECT"		},
643#endif
644#if defined(ICMP_ECHO)
645	{ (1<<ICMP_ECHO),		"ICMP_ECHO"		},
646#endif
647#if defined(ICMP_TIME_EXCEEDED)
648	{ (1<<ICMP_TIME_EXCEEDED),	"ICMP_TIME_EXCEEDED"	},
649#endif
650#if defined(ICMP_PARAMETERPROB)
651	{ (1<<ICMP_PARAMETERPROB),	"ICMP_PARAMETERPROB"	},
652#endif
653#if defined(ICMP_TIMESTAMP)
654	{ (1<<ICMP_TIMESTAMP),		"ICMP_TIMESTAMP"	},
655#endif
656#if defined(ICMP_TIMESTAMPREPLY)
657	{ (1<<ICMP_TIMESTAMPREPLY),	"ICMP_TIMESTAMPREPLY"	},
658#endif
659#if defined(ICMP_INFO_REQUEST)
660	{ (1<<ICMP_INFO_REQUEST),	"ICMP_INFO_REQUEST"	},
661#endif
662#if defined(ICMP_INFO_REPLY)
663	{ (1<<ICMP_INFO_REPLY),		"ICMP_INFO_REPLY"	},
664#endif
665#if defined(ICMP_ADDRESS)
666	{ (1<<ICMP_ADDRESS),		"ICMP_ADDRESS"		},
667#endif
668#if defined(ICMP_ADDRESSREPLY)
669	{ (1<<ICMP_ADDRESSREPLY),	"ICMP_ADDRESSREPLY"	},
670#endif
671	{ 0,				NULL			},
672};
673#endif /* SOL_RAW */
674
675#if defined(AF_PACKET) /* from e.g. linux/if_packet.h */
676static struct xlat af_packet_types[] = {
677#if defined(PACKET_HOST)
678	{ PACKET_HOST,			"PACKET_HOST"		},
679#endif
680#if defined(PACKET_BROADCAST)
681	{ PACKET_BROADCAST,		"PACKET_BROADCAST"	},
682#endif
683#if defined(PACKET_MULTICAST)
684	{ PACKET_MULTICAST,		"PACKET_MULTICAST"	},
685#endif
686#if defined(PACKET_OTHERHOST)
687	{ PACKET_OTHERHOST,		"PACKET_OTHERHOST"	},
688#endif
689#if defined(PACKET_OUTGOING)
690	{ PACKET_OUTGOING,		"PACKET_OUTGOING"	},
691#endif
692#if defined(PACKET_LOOPBACK)
693	{ PACKET_LOOPBACK,		"PACKET_LOOPBACK"	},
694#endif
695#if defined(PACKET_FASTROUTE)
696	{ PACKET_FASTROUTE,		"PACKET_FASTROUTE"	},
697#endif
698	{ 0,				NULL			},
699};
700#endif /* defined(AF_PACKET) */
701
702
703void
704printsock(tcp, addr, addrlen)
705struct tcb *tcp;
706long addr;
707int addrlen;
708{
709	union {
710		char pad[128];
711		struct sockaddr sa;
712		struct sockaddr_in sin;
713		struct sockaddr_un sau;
714#ifdef HAVE_INET_NTOP
715		struct sockaddr_in6 sa6;
716#endif
717#if defined(LINUX) && defined(AF_IPX)
718		struct sockaddr_ipx sipx;
719#endif
720#ifdef AF_PACKET
721		struct sockaddr_ll ll;
722#endif
723#ifdef AF_NETLINK
724		struct sockaddr_nl nl;
725#endif
726	} addrbuf;
727	char string_addr[100];
728
729	if (addr == 0) {
730		tprintf("NULL");
731		return;
732	}
733	if (!verbose(tcp)) {
734		tprintf("%#lx", addr);
735		return;
736	}
737	if ((addrlen<2) || (addrlen>sizeof(addrbuf)))
738		addrlen=sizeof(addrbuf);
739
740	if (umoven(tcp, addr, addrlen, (char*)&addrbuf) < 0) {
741		tprintf("{...}");
742		return;
743	}
744
745	tprintf("{sa_family=");
746	printxval(addrfams, addrbuf.sa.sa_family, "AF_???");
747	tprintf(", ");
748
749	switch (addrbuf.sa.sa_family) {
750	case AF_UNIX:
751		if (addrlen==2) {
752			tprintf("<nil>");
753		} else if (addrbuf.sau.sun_path[0]) {
754			tprintf("path=\"%-.*s\"", addrlen-2, addrbuf.sau.sun_path);
755		} else {
756			tprintf("path=@%-.*s", addrlen-3, addrbuf.sau.sun_path+1);
757		}
758		break;
759	case AF_INET:
760		tprintf("sin_port=htons(%u), sin_addr=inet_addr(\"%s\")",
761			ntohs(addrbuf.sin.sin_port), inet_ntoa(addrbuf.sin.sin_addr));
762		break;
763#ifdef HAVE_INET_NTOP
764	case AF_INET6:
765		inet_ntop(AF_INET6, &addrbuf.sa6.sin6_addr, string_addr, sizeof(string_addr));
766		tprintf("sin6_port=htons(%u), inet_pton(AF_INET6, \"%s\", &sin6_addr), sin6_flowinfo=%u",
767				ntohs(addrbuf.sa6.sin6_port), string_addr,
768				addrbuf.sa6.sin6_flowinfo);
769#ifdef HAVE_SIN6_SCOPE_ID
770		{
771#if defined(HAVE_IF_INDEXTONAME) && defined(IN6_IS_ADDR_LINKLOCAL) && defined(IN6_IS_ADDR_MC_LINKLOCAL)
772		    int numericscope = 0;
773		    if (IN6_IS_ADDR_LINKLOCAL (&addrbuf.sa6.sin6_addr)
774			    || IN6_IS_ADDR_MC_LINKLOCAL (&addrbuf.sa6.sin6_addr)) {
775			char scopebuf[IFNAMSIZ + 1];
776
777			if (if_indextoname (addrbuf.sa6.sin6_scope_id, scopebuf) == NULL)
778			    numericscope++;
779			else
780			    tprintf(", sin6_scope_id=if_nametoindex(\"%s\")", scopebuf);
781		    } else
782			numericscope++;
783
784		    if (numericscope)
785#endif
786			tprintf(", sin6_scope_id=%u", addrbuf.sa6.sin6_scope_id);
787		}
788#endif
789		    break;
790#endif
791#if defined(AF_IPX) && defined(linux)
792	case AF_IPX:
793		{
794			int i;
795			tprintf("sipx_port=htons(%u), ",
796					ntohs(addrbuf.sipx.sipx_port));
797			/* Yes, I know, this does not look too
798			 * strace-ish, but otherwise the IPX
799			 * addresses just look monstrous...
800			 * Anyways, feel free if you don't like
801			 * this way.. :)
802			 */
803			tprintf("%08lx:", (unsigned long)ntohl(addrbuf.sipx.sipx_network));
804			for (i = 0; i<IPX_NODE_LEN; i++)
805				tprintf("%02x", addrbuf.sipx.sipx_node[i]);
806			tprintf("/[%02x]", addrbuf.sipx.sipx_type);
807		}
808		break;
809#endif /* AF_IPX && linux */
810#ifdef AF_PACKET
811	case AF_PACKET:
812		{
813			int i;
814			tprintf("proto=%#04x, if%d, pkttype=",
815					ntohs(addrbuf.ll.sll_protocol),
816					addrbuf.ll.sll_ifindex);
817			printxval(af_packet_types, addrbuf.ll.sll_pkttype, "?");
818			tprintf(", addr(%d)={%d, ",
819					addrbuf.ll.sll_halen,
820					addrbuf.ll.sll_hatype);
821			for (i=0; i<addrbuf.ll.sll_halen; i++)
822				tprintf("%02x", addrbuf.ll.sll_addr[i]);
823		}
824		break;
825
826#endif /* AF_APACKET */
827#ifdef AF_NETLINLK
828	case AF_NETLINK:
829		tprintf("pid=%d, groups=%08x", addrbuf.nl.nl_pid, addrbuf.nl.nl_groups);
830		break;
831#endif /* AF_NETLINK */
832	/* AF_AX25 AF_APPLETALK AF_NETROM AF_BRIDGE AF_AAL5
833	AF_X25 AF_ROSE etc. still need to be done */
834
835	default:
836		tprintf("sa_data=");
837		printstr(tcp, (long) &((struct sockaddr *) addr)->sa_data,
838			sizeof addrbuf.sa.sa_data);
839		break;
840	}
841	tprintf("}");
842}
843
844#if HAVE_SENDMSG
845
846static void
847printmsghdr(tcp, addr)
848struct tcb *tcp;
849long addr;
850{
851	struct msghdr msg;
852
853	if (umove(tcp, addr, &msg) < 0) {
854		tprintf("%#lx", addr);
855		return;
856	}
857	tprintf("{msg_name(%d)=", msg.msg_namelen);
858	printsock(tcp, (long)msg.msg_name, msg.msg_namelen);
859
860	tprintf(", msg_iov(%lu)=", (unsigned long)msg.msg_iovlen);
861	tprint_iov(tcp, msg.msg_iovlen, (long) msg.msg_iov);
862
863#ifdef HAVE_MSG_CONTROL
864	tprintf(", msg_controllen=%lu", (unsigned long)msg.msg_controllen);
865	if (msg.msg_controllen)
866		tprintf(", msg_control=%#lx, ", (unsigned long) msg.msg_control);
867	tprintf(", msg_flags=");
868	if (printflags(msg_flags, msg.msg_flags)==0)
869		tprintf("0");
870#else /* !HAVE_MSG_CONTROL */
871	tprintf("msg_accrights=%#lx, msg_accrightslen=%u",
872		(unsigned long) msg.msg_accrights, msg.msg_accrightslen);
873#endif /* !HAVE_MSG_CONTROL */
874	tprintf("}");
875}
876
877#endif /* HAVE_SENDMSG */
878
879int
880sys_socket(tcp)
881struct tcb *tcp;
882{
883	if (entering(tcp)) {
884		printxval(domains, tcp->u_arg[0], "PF_???");
885		tprintf(", ");
886		printxval(socktypes, tcp->u_arg[1], "SOCK_???");
887		tprintf(", ");
888		switch (tcp->u_arg[0]) {
889		case PF_INET:
890			printxval(protocols, tcp->u_arg[2], "IPPROTO_???");
891			break;
892#ifdef PF_IPX
893		case PF_IPX:
894			/* BTW: I don't believe this.. */
895			tprintf("[");
896			printxval(domains, tcp->u_arg[2], "PF_???");
897			tprintf("]");
898			break;
899#endif /* PF_IPX */
900		default:
901			tprintf("%lu", tcp->u_arg[2]);
902			break;
903		}
904	}
905	return 0;
906}
907
908int
909sys_so_socket(tcp)
910struct tcb *tcp;
911{
912	if (entering(tcp)) {
913		/* not sure really what these args are... but this
914		 * is how truss prints it
915		 */
916		tprintf("%ld, %ld, %ld, ",
917		  tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]);
918		printpath(tcp, tcp->u_arg[3]);
919		tprintf(", %ld", tcp->u_arg[4]);
920	}
921	return 0;
922}
923
924int
925sys_so_socketpair(tcp)
926struct tcb *tcp;
927{
928	if (entering(tcp)) {
929	  	/* not sure what this arg is */
930		tprintf("0x%lx", tcp->u_arg[0]);
931	}
932	return 0;
933}
934
935int
936sys_bind(tcp)
937struct tcb *tcp;
938{
939	if (entering(tcp)) {
940		tprintf("%ld, ", tcp->u_arg[0]);
941		printsock(tcp, tcp->u_arg[1], tcp->u_arg[2]);
942		tprintf(", %lu", tcp->u_arg[2]);
943	}
944	return 0;
945}
946
947int
948sys_connect(tcp)
949struct tcb *tcp;
950{
951	return sys_bind(tcp);
952}
953
954int
955sys_listen(tcp)
956struct tcb *tcp;
957{
958	if (entering(tcp)) {
959		tprintf("%ld, %lu", tcp->u_arg[0], tcp->u_arg[1]);
960	}
961	return 0;
962}
963
964int
965sys_accept(tcp)
966struct tcb *tcp;
967{
968	if (entering(tcp)) {
969		tprintf("%ld, ", tcp->u_arg[0]);
970	} else if (!tcp->u_arg[2])
971		tprintf("%#lx, NULL", tcp->u_arg[1]);
972	else {
973		if (tcp->u_arg[1] == 0 || syserror(tcp)) {
974			tprintf("%#lx", tcp->u_arg[1]);
975		} else {
976			printsock(tcp, tcp->u_arg[1], tcp->u_arg[2]);
977		}
978		tprintf(", ");
979		printnum(tcp, tcp->u_arg[2], "%lu");
980	}
981	return 0;
982}
983
984int
985sys_send(tcp)
986struct tcb *tcp;
987{
988	if (entering(tcp)) {
989		tprintf("%ld, ", tcp->u_arg[0]);
990		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
991		tprintf(", %lu, ", tcp->u_arg[2]);
992		/* flags */
993		if (printflags(msg_flags, tcp->u_arg[3]) == 0)
994			tprintf("0");
995	}
996	return 0;
997}
998
999int
1000sys_sendto(tcp)
1001struct tcb *tcp;
1002{
1003	if (entering(tcp)) {
1004		tprintf("%ld, ", tcp->u_arg[0]);
1005		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1006		tprintf(", %lu, ", tcp->u_arg[2]);
1007		/* flags */
1008		if (printflags(msg_flags, tcp->u_arg[3]) == 0)
1009			tprintf("0");
1010		/* to address */
1011		tprintf(", ");
1012		printsock(tcp, tcp->u_arg[4], tcp->u_arg[5]);
1013		/* to length */
1014		tprintf(", %lu", tcp->u_arg[5]);
1015	}
1016	return 0;
1017}
1018
1019#ifdef HAVE_SENDMSG
1020
1021int
1022sys_sendmsg(tcp)
1023struct tcb *tcp;
1024{
1025	if (entering(tcp)) {
1026		tprintf("%ld, ", tcp->u_arg[0]);
1027		printmsghdr(tcp, tcp->u_arg[1]);
1028		/* flags */
1029		tprintf(", ");
1030		if (printflags(msg_flags, tcp->u_arg[2]) == 0)
1031			tprintf("0");
1032	}
1033	return 0;
1034}
1035
1036#endif /* HAVE_SENDMSG */
1037
1038int
1039sys_recv(tcp)
1040struct tcb *tcp;
1041{
1042	if (entering(tcp)) {
1043		tprintf("%ld, ", tcp->u_arg[0]);
1044	} else {
1045		if (syserror(tcp))
1046			tprintf("%#lx", tcp->u_arg[1]);
1047		else
1048			printstr(tcp, tcp->u_arg[1], tcp->u_rval);
1049
1050		tprintf(", %lu, ", tcp->u_arg[2]);
1051		if (printflags(msg_flags, tcp->u_arg[3]) == 0)
1052			tprintf("0");
1053	}
1054	return 0;
1055}
1056
1057int
1058sys_recvfrom(tcp)
1059struct tcb *tcp;
1060{
1061	int fromlen;
1062
1063	if (entering(tcp)) {
1064		tprintf("%ld, ", tcp->u_arg[0]);
1065	} else {
1066		if (syserror(tcp)) {
1067			tprintf("%#lx, %lu, %lu, %#lx, %#lx",
1068				tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3],
1069				tcp->u_arg[4], tcp->u_arg[5]);
1070			return 0;
1071		}
1072		/* buf */
1073		printstr(tcp, tcp->u_arg[1], tcp->u_rval);
1074		/* len */
1075		tprintf(", %lu, ", tcp->u_arg[2]);
1076		/* flags */
1077		if (printflags(msg_flags, tcp->u_arg[3]) == 0)
1078			tprintf("0");
1079		/* from address, len */
1080		if (!tcp->u_arg[4] || !tcp->u_arg[5]) {
1081			if (tcp->u_arg[4] == 0)
1082				tprintf(", NULL");
1083			else
1084				tprintf(", %#lx", tcp->u_arg[4]);
1085			if (tcp->u_arg[5] == 0)
1086				tprintf(", NULL");
1087			else
1088				tprintf(", %#lx", tcp->u_arg[5]);
1089			return 0;
1090		}
1091		if (umove(tcp, tcp->u_arg[5], &fromlen) < 0) {
1092			tprintf(", {...}, [?]");
1093			return 0;
1094		}
1095		tprintf(", ");
1096		printsock(tcp, tcp->u_arg[4], tcp->u_arg[5]);
1097		/* from length */
1098		tprintf(", [%u]", fromlen);
1099	}
1100	return 0;
1101}
1102
1103#ifdef HAVE_SENDMSG
1104
1105int
1106sys_recvmsg(tcp)
1107struct tcb *tcp;
1108{
1109	if (entering(tcp)) {
1110		tprintf("%ld, ", tcp->u_arg[0]);
1111	} else {
1112		if (syserror(tcp) || !verbose(tcp))
1113			tprintf("%#lx", tcp->u_arg[1]);
1114		else
1115			printmsghdr(tcp, tcp->u_arg[1]);
1116		/* flags */
1117		tprintf(", ");
1118		if (printflags(msg_flags, tcp->u_arg[2]) == 0)
1119			tprintf("0");
1120	}
1121	return 0;
1122}
1123
1124#endif /* HAVE_SENDMSG */
1125
1126int
1127sys_shutdown(tcp)
1128struct tcb *tcp;
1129{
1130	if (entering(tcp)) {
1131		tprintf("%ld, %ld", tcp->u_arg[0], tcp->u_arg[1]);
1132		switch (tcp->u_arg[1]) {
1133		case 0:
1134			tprintf("%s", " /* receive */");
1135			break;
1136		case 1:
1137			tprintf("%s", " /* send */");
1138			break;
1139		case 2:
1140			tprintf("%s", " /* send and receive */");
1141			break;
1142		}
1143	}
1144	return 0;
1145}
1146
1147int
1148sys_getsockname(tcp)
1149struct tcb *tcp;
1150{
1151	return sys_accept(tcp);
1152}
1153
1154int
1155sys_getpeername(tcp)
1156struct tcb *tcp;
1157{
1158	return sys_accept(tcp);
1159}
1160
1161int
1162sys_pipe(tcp)
1163struct tcb *tcp;
1164{
1165
1166#if defined(LINUX) && !defined(SPARC)
1167	int fds[2];
1168
1169	if (exiting(tcp)) {
1170		if (syserror(tcp)) {
1171			tprintf("%#lx", tcp->u_arg[0]);
1172			return 0;
1173		}
1174		if (umoven(tcp, tcp->u_arg[0], sizeof fds, (char *) fds) < 0)
1175			tprintf("[...]");
1176		else
1177			tprintf("[%u, %u]", fds[0], fds[1]);
1178	}
1179#elif defined(SPARC) || defined(SVR4) || defined(FREEBSD)
1180	if (exiting(tcp))
1181		tprintf("[%lu, %lu]", tcp->u_rval, getrval2(tcp));
1182#endif
1183	return 0;
1184}
1185
1186int
1187sys_socketpair(tcp)
1188struct tcb *tcp;
1189{
1190#ifdef LINUX
1191	int fds[2];
1192#endif
1193
1194	if (entering(tcp)) {
1195		printxval(domains, tcp->u_arg[0], "PF_???");
1196		tprintf(", ");
1197		printxval(socktypes, tcp->u_arg[1], "SOCK_???");
1198		tprintf(", ");
1199		switch (tcp->u_arg[0]) {
1200		case PF_INET:
1201			printxval(protocols, tcp->u_arg[2], "IPPROTO_???");
1202			break;
1203#ifdef PF_IPX
1204		case PF_IPX:
1205			/* BTW: I don't believe this.. */
1206			tprintf("[");
1207			printxval(domains, tcp->u_arg[2], "PF_???");
1208			tprintf("]");
1209			break;
1210#endif /* PF_IPX */
1211		default:
1212			tprintf("%lu", tcp->u_arg[2]);
1213			break;
1214		}
1215	} else {
1216		if (syserror(tcp)) {
1217			tprintf(", %#lx", tcp->u_arg[3]);
1218			return 0;
1219		}
1220#ifdef LINUX
1221		if (umoven(tcp, tcp->u_arg[3], sizeof fds, (char *) fds) < 0)
1222			tprintf(", [...]");
1223		else
1224			tprintf(", [%u, %u]", fds[0], fds[1]);
1225#endif /* LINUX */
1226#if defined(SUNOS4) || defined(SVR4) || defined(FREEBSD)
1227		tprintf(", [%lu, %lu]", tcp->u_rval, getrval2(tcp));
1228#endif /* SUNOS4 || SVR4 || FREEBSD */
1229	}
1230	return 0;
1231}
1232
1233int
1234sys_getsockopt(tcp)
1235struct tcb *tcp;
1236{
1237	if (entering(tcp)) {
1238		tprintf("%ld, ", tcp->u_arg[0]);
1239		printxval(socketlayers, tcp->u_arg[1], "SOL_???");
1240		tprintf (", ");
1241		switch (tcp->u_arg[1]) {
1242		case SOL_SOCKET:
1243			printxval(sockoptions, tcp->u_arg[2], "SO_???");
1244			break;
1245#ifdef SOL_IP
1246		case SOL_IP:
1247			printxval(sockipoptions, tcp->u_arg[2], "IP_???");
1248			break;
1249#endif
1250#ifdef SOL_IPX
1251		case SOL_IPX:
1252			printxval(sockipxoptions, tcp->u_arg[2], "IPX_???");
1253			break;
1254#endif
1255#ifdef SOL_PACKET
1256		case SOL_PACKET:
1257			printxval(sockpacketoptions, tcp->u_arg[2], "PACKET_???");
1258			break;
1259#endif
1260#ifdef SOL_TCP
1261		case SOL_TCP:
1262			printxval(socktcpoptions, tcp->u_arg[2], "TCP_???");
1263			break;
1264#endif
1265
1266		/* SOL_AX25 SOL_ROSE SOL_ATALK SOL_NETROM SOL_UDP SOL_DECNET SOL_X25
1267		 * etc. still need work */
1268		default:
1269			tprintf("%lu", tcp->u_arg[2]);
1270			break;
1271		}
1272	} else {
1273		long len;
1274		if (syserror(tcp) || umove (tcp, tcp->u_arg[4], &len) < 0) {
1275			tprintf(", %#lx, %#lx",
1276				tcp->u_arg[3], tcp->u_arg[4]);
1277			return 0;
1278		}
1279
1280		switch (tcp->u_arg[1]) {
1281		case SOL_SOCKET:
1282			switch (tcp->u_arg[2]) {
1283#ifdef SO_LINGER
1284			case SO_LINGER:
1285			        if (len == sizeof (struct linger)) {
1286					struct linger linger;
1287					if (umove (tcp,
1288						   tcp->u_arg[3],
1289						   &linger) < 0)
1290						break;
1291					tprintf(", {onoff=%d, linger=%d}, "
1292						"[%ld]",
1293						linger.l_onoff,
1294						linger.l_linger,
1295						len);
1296					return 0;
1297				}
1298				break;
1299#endif
1300			}
1301			break;
1302		}
1303
1304		tprintf (", ");
1305		if (len == sizeof (int)) {
1306			printnum(tcp, tcp->u_arg[3], "%ld");
1307		}
1308		else {
1309			printstr (tcp, tcp->u_arg[3], len);
1310		}
1311		tprintf(", [%ld]", len);
1312	}
1313	return 0;
1314}
1315
1316#if defined(ICMP_FILTER)
1317static void printicmpfilter(tcp, addr)
1318struct tcb *tcp;
1319long addr;
1320{
1321	struct icmp_filter	filter;
1322
1323	if (!addr) {
1324		tprintf("NULL");
1325		return;
1326	}
1327	if (syserror(tcp) || !verbose(tcp)) {
1328		tprintf("%#lx", addr);
1329		return;
1330	}
1331	if (umove(tcp, addr, &filter) < 0) {
1332		tprintf("{...}");
1333		return;
1334	}
1335
1336	tprintf("~(");
1337	if (printflags(icmpfilterflags, ~filter.data) == 0)
1338		tprintf("0");
1339	tprintf(")");
1340}
1341#endif /* ICMP_FILTER */
1342
1343static int
1344printsockopt (tcp, level, name, addr, len)
1345struct tcb *tcp;
1346int level;
1347int name;
1348long addr;
1349int len;
1350{
1351	printxval(socketlayers, level, "SOL_??");
1352	tprintf (", ");
1353	switch (level) {
1354	    case SOL_SOCKET:
1355		printxval(sockoptions, name, "SO_???");
1356		switch (name) {
1357#if defined(SO_LINGER)
1358		    case SO_LINGER:
1359			if (len == sizeof (struct linger)) {
1360				struct linger linger;
1361				if (umove (tcp, addr, &linger) < 0)
1362					break;
1363				tprintf(", {onoff=%d, linger=%d}",
1364					linger.l_onoff,
1365					linger.l_linger);
1366				return 0;
1367			}
1368			break;
1369#endif
1370		}
1371		break;
1372#ifdef SOL_IP
1373	    case SOL_IP:
1374		printxval(sockipoptions, name, "IP_???");
1375		break;
1376#endif
1377#ifdef SOL_IPX
1378	    case SOL_IPX:
1379		printxval(sockipxoptions, name, "IPX_???");
1380		break;
1381#endif
1382#ifdef SOL_PACKET
1383	    case SOL_PACKET:
1384		printxval(sockpacketoptions, name, "PACKET_???");
1385		/* TODO: decode packate_mreq for PACKET_*_MEMBERSHIP */
1386		break;
1387#endif
1388#ifdef SOL_TCP
1389	    case SOL_TCP:
1390		printxval(socktcpoptions, name, "TCP_???");
1391		break;
1392#endif
1393#ifdef SOL_RAW
1394	    case SOL_RAW:
1395		printxval(sockrawoptions, name, "RAW_???");
1396		switch (name) {
1397#if defined(ICMP_FILTER)
1398		    case ICMP_FILTER:
1399			tprintf(", ");
1400			printicmpfilter(tcp, addr);
1401			return 0;
1402#endif
1403		}
1404		break;
1405#endif
1406
1407		/* SOL_AX25 SOL_ATALK SOL_NETROM SOL_UDP SOL_DECNET SOL_X25
1408		 * etc. still need work  */
1409
1410	    default:
1411		tprintf("%u", name);
1412	}
1413
1414	/* default arg printing */
1415
1416	tprintf (", ");
1417
1418	if (len == sizeof (int)) {
1419		printnum(tcp, addr, "%ld");
1420	}
1421	else {
1422		printstr (tcp, addr, len);
1423	}
1424	return 0;
1425}
1426
1427
1428#ifdef HAVE_OPTHDR
1429
1430void
1431print_sock_optmgmt (tcp, addr, len)
1432struct tcb *tcp;
1433long addr;
1434int len;
1435{
1436	int c = 0;
1437	struct opthdr hdr;
1438
1439	while (len >= sizeof hdr) {
1440		if (umove(tcp, addr, &hdr) < 0) break;
1441		if (c++) {
1442			tprintf (", ");
1443		}
1444		else if (len > hdr.len + sizeof hdr) {
1445			tprintf ("[");
1446		}
1447		tprintf ("{");
1448		addr += sizeof hdr;
1449		len -= sizeof hdr;
1450		printsockopt (tcp, hdr.level, hdr.name, addr, hdr.len);
1451		addr += hdr.len;
1452		len -= hdr.len;
1453		tprintf ("}");
1454	}
1455	if (len > 0) {
1456		if (c++) tprintf (", ");
1457		printstr (tcp, addr, len);
1458	}
1459	if (c > 1) tprintf ("]");
1460}
1461
1462#endif
1463
1464int
1465sys_setsockopt(tcp)
1466struct tcb *tcp;
1467{
1468	if (entering(tcp)) {
1469		tprintf("%ld, ", tcp->u_arg[0]);
1470		printsockopt (tcp, tcp->u_arg[1], tcp->u_arg[2],
1471			      tcp->u_arg[3], tcp->u_arg[4]);
1472		tprintf(", %lu", tcp->u_arg[4]);
1473	}
1474	return 0;
1475}
1476
1477#if UNIXWARE >= 7
1478
1479static struct xlat sock_version[] = {
1480	{ __NETLIB_UW211_SVR4,	"UW211_SVR4" },
1481	{ __NETLIB_UW211_XPG4,	"UW211_XPG4" },
1482	{ __NETLIB_GEMINI_SVR4,	"GEMINI_SVR4" },
1483	{ __NETLIB_GEMINI_XPG4,	"GEMINI_XPG4" },
1484	{ __NETLIB_FP1_SVR4,	"FP1_SVR4" },
1485	{ __NETLIB_FP1_XPG4,	"FP1_XPG4" },
1486	{ 0,            NULL            },
1487};
1488
1489
1490int
1491netlib_call(tcp, func)
1492struct tcb *tcp;
1493int (*func) ();
1494{
1495	if (entering(tcp)) {
1496		int i;
1497		printxval (sock_version, tcp->u_arg[0], "__NETLIB_???");
1498		tprintf(", ");
1499		--tcp->u_nargs;
1500		for (i = 0; i < tcp->u_nargs; i++)
1501			tcp->u_arg[i] = tcp->u_arg[i + 1];
1502		return func (tcp);
1503
1504	}
1505
1506	return func (tcp);
1507}
1508
1509int
1510sys_xsocket(tcp)
1511struct tcb *tcp;
1512{
1513	return netlib_call (tcp, sys_socket);
1514}
1515
1516int
1517sys_xsocketpair(tcp)
1518struct tcb *tcp;
1519{
1520	return netlib_call (tcp, sys_socketpair);
1521}
1522
1523int
1524sys_xbind(tcp)
1525struct tcb *tcp;
1526{
1527	return netlib_call (tcp, sys_bind);
1528}
1529
1530int
1531sys_xconnect(tcp)
1532struct tcb *tcp;
1533{
1534	return netlib_call (tcp, sys_connect);
1535}
1536
1537int
1538sys_xlisten(tcp)
1539struct tcb *tcp;
1540{
1541	return netlib_call (tcp, sys_listen);
1542}
1543
1544int
1545sys_xaccept(tcp)
1546struct tcb *tcp;
1547{
1548	return netlib_call (tcp, sys_accept);
1549}
1550
1551int
1552sys_xsendmsg(tcp)
1553struct tcb *tcp;
1554{
1555	return netlib_call (tcp, sys_sendmsg);
1556}
1557
1558int
1559sys_xrecvmsg(tcp)
1560struct tcb *tcp;
1561{
1562	return netlib_call (tcp, sys_recvmsg);
1563}
1564
1565int
1566sys_xgetsockaddr(tcp)
1567struct tcb *tcp;
1568{
1569	if (entering(tcp)) {
1570		printxval (sock_version, tcp->u_arg[0], "__NETLIB_???");
1571		tprintf(", ");
1572		if (tcp->u_arg[1] == 0) {
1573			tprintf ("LOCALNAME, ");
1574		}
1575		else if (tcp->u_arg[1] == 1) {
1576			tprintf ("REMOTENAME, ");
1577		}
1578		else {
1579			tprintf ("%ld, ", tcp->u_arg [1]);
1580		}
1581		tprintf ("%ld, ", tcp->u_arg [2]);
1582	}
1583	else {
1584		if (tcp->u_arg[3] == 0 || syserror(tcp)) {
1585			tprintf("%#lx", tcp->u_arg[3]);
1586		} else {
1587			printsock(tcp, tcp->u_arg[3], tcp->u_arg[4]);
1588		}
1589		tprintf(", ");
1590		printnum(tcp, tcp->u_arg[4], "%lu");
1591	}
1592
1593	return 0;
1594
1595}
1596
1597#if 0
1598
1599int
1600sys_xsetsockaddr(tcp)
1601struct tcb *tcp;
1602{
1603	return netlib_call (tcp, sys_setsockaddr);
1604}
1605
1606#endif
1607
1608int
1609sys_xgetsockopt(tcp)
1610struct tcb *tcp;
1611{
1612	return netlib_call (tcp, sys_getsockopt);
1613}
1614
1615int
1616sys_xsetsockopt(tcp)
1617struct tcb *tcp;
1618{
1619	return netlib_call (tcp, sys_setsockopt);
1620}
1621
1622int
1623sys_xshutdown(tcp)
1624struct tcb *tcp;
1625{
1626	return netlib_call (tcp, sys_shutdown);
1627}
1628
1629#endif
1630