]> granicus.if.org Git - strace/blob - net.c
io.c: move sendfile parsers to a separate file
[strace] / net.c
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
31 #include "defs.h"
32 #include <sys/stat.h>
33 #include <sys/socket.h>
34 #include <sys/uio.h>
35 #include <sys/un.h>
36 #include <netinet/in.h>
37 #ifdef HAVE_NETINET_TCP_H
38 # include <netinet/tcp.h>
39 #endif
40 #ifdef HAVE_NETINET_UDP_H
41 # include <netinet/udp.h>
42 #endif
43 #ifdef HAVE_NETINET_SCTP_H
44 # include <netinet/sctp.h>
45 #endif
46 #include <arpa/inet.h>
47 #include <net/if.h>
48 #include <asm/types.h>
49 #if defined(__GLIBC__)
50 # include <netipx/ipx.h>
51 #else
52 # include <linux/ipx.h>
53 #endif
54
55 #if defined(HAVE_LINUX_NETLINK_H)
56 # include <linux/netlink.h>
57 #endif
58 #if defined(HAVE_LINUX_IF_PACKET_H)
59 # include <linux/if_packet.h>
60 #endif
61 #if defined(HAVE_LINUX_ICMP_H)
62 # include <linux/icmp.h>
63 #endif
64 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
65 # include <bluetooth/bluetooth.h>
66 # include <bluetooth/hci.h>
67 # include <bluetooth/l2cap.h>
68 # include <bluetooth/rfcomm.h>
69 # include <bluetooth/sco.h>
70 #endif
71 #ifndef PF_UNSPEC
72 # define PF_UNSPEC AF_UNSPEC
73 #endif
74
75 #include "xlat/domains.h"
76 #include "xlat/addrfams.h"
77 #include "xlat/socktypes.h"
78 #include "xlat/sock_type_flags.h"
79 #ifndef SOCK_TYPE_MASK
80 # define SOCK_TYPE_MASK 0xf
81 #endif
82
83 #include "xlat/socketlayers.h"
84
85 #include "xlat/inet_protocols.h"
86
87 #ifdef PF_NETLINK
88 # if !defined NETLINK_SOCK_DIAG && defined NETLINK_INET_DIAG
89 #  define NETLINK_SOCK_DIAG NETLINK_INET_DIAG
90 # endif
91 # include "xlat/netlink_protocols.h"
92 #endif
93
94 #if defined(HAVE_BLUETOOTH_BLUETOOTH_H)
95 # include "xlat/bt_protocols.h"
96 #endif
97
98 #include "xlat/msg_flags.h"
99
100 #if defined(AF_PACKET) /* from e.g. linux/if_packet.h */
101 # include "xlat/af_packet_types.h"
102 #endif
103
104 static void
105 print_ifindex(unsigned int ifindex)
106 {
107 #ifdef HAVE_IF_INDEXTONAME
108         char buf[IFNAMSIZ + 1];
109
110         if (if_indextoname(ifindex, buf)) {
111                 tprints("if_nametoindex(");
112                 print_quoted_string(buf, sizeof(buf), QUOTE_0_TERMINATED);
113                 tprints(")");
114                 return;
115         }
116 #endif
117         tprintf("%u", ifindex);
118 }
119
120 void
121 printsock(struct tcb *tcp, long addr, int addrlen)
122 {
123         union {
124                 char pad[128];
125                 struct sockaddr sa;
126                 struct sockaddr_in sin;
127                 struct sockaddr_un sau;
128 #ifdef HAVE_INET_NTOP
129                 struct sockaddr_in6 sa6;
130 #endif
131 #if defined(AF_IPX)
132                 struct sockaddr_ipx sipx;
133 #endif
134 #ifdef AF_PACKET
135                 struct sockaddr_ll ll;
136 #endif
137 #ifdef AF_NETLINK
138                 struct sockaddr_nl nl;
139 #endif
140 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
141                 struct sockaddr_hci hci;
142                 struct sockaddr_l2 l2;
143                 struct sockaddr_rc rc;
144                 struct sockaddr_sco sco;
145 #endif
146         } addrbuf;
147         char string_addr[100];
148
149         if (addrlen < 2) {
150                 printaddr(addr);
151                 return;
152         }
153
154         if (addrlen > (int) sizeof(addrbuf))
155                 addrlen = sizeof(addrbuf);
156
157         memset(&addrbuf, 0, sizeof(addrbuf));
158         if (umoven_or_printaddr(tcp, addr, addrlen, addrbuf.pad))
159                 return;
160         addrbuf.pad[sizeof(addrbuf.pad) - 1] = '\0';
161
162         tprints("{sa_family=");
163         printxval(addrfams, addrbuf.sa.sa_family, "AF_???");
164         tprints(", ");
165
166         switch (addrbuf.sa.sa_family) {
167         case AF_UNIX:
168                 if (addrlen == 2) {
169                         tprints("NULL");
170                 } else if (addrbuf.sau.sun_path[0]) {
171                         tprints("sun_path=");
172                         print_quoted_string(addrbuf.sau.sun_path,
173                                             sizeof(addrbuf.sau.sun_path) + 1,
174                                             QUOTE_0_TERMINATED);
175                 } else {
176                         tprints("sun_path=@");
177                         print_quoted_string(addrbuf.sau.sun_path + 1,
178                                             sizeof(addrbuf.sau.sun_path),
179                                             QUOTE_0_TERMINATED);
180                 }
181                 break;
182         case AF_INET:
183                 tprintf("sin_port=htons(%u), sin_addr=inet_addr(\"%s\")",
184                         ntohs(addrbuf.sin.sin_port), inet_ntoa(addrbuf.sin.sin_addr));
185                 break;
186 #ifdef HAVE_INET_NTOP
187         case AF_INET6:
188                 inet_ntop(AF_INET6, &addrbuf.sa6.sin6_addr, string_addr, sizeof(string_addr));
189                 tprintf("sin6_port=htons(%u), inet_pton(AF_INET6, \"%s\", &sin6_addr), sin6_flowinfo=%u",
190                                 ntohs(addrbuf.sa6.sin6_port), string_addr,
191                                 addrbuf.sa6.sin6_flowinfo);
192 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
193                 tprints(", sin6_scope_id=");
194 #if defined IN6_IS_ADDR_LINKLOCAL && defined IN6_IS_ADDR_MC_LINKLOCAL
195                 if (IN6_IS_ADDR_LINKLOCAL(&addrbuf.sa6.sin6_addr)
196                     || IN6_IS_ADDR_MC_LINKLOCAL(&addrbuf.sa6.sin6_addr))
197                         print_ifindex(addrbuf.sa6.sin6_scope_id);
198                 else
199 #endif
200                         tprintf("%u", addrbuf.sa6.sin6_scope_id);
201 #endif /* HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID */
202                 break;
203 #endif
204 #if defined(AF_IPX)
205         case AF_IPX:
206                 {
207                         int i;
208                         tprintf("sipx_port=htons(%u), ",
209                                         ntohs(addrbuf.sipx.sipx_port));
210                         /* Yes, I know, this does not look too
211                          * strace-ish, but otherwise the IPX
212                          * addresses just look monstrous...
213                          * Anyways, feel free if you don't like
214                          * this way.. :)
215                          */
216                         tprintf("%08lx:", (unsigned long)ntohl(addrbuf.sipx.sipx_network));
217                         for (i = 0; i < IPX_NODE_LEN; i++)
218                                 tprintf("%02x", addrbuf.sipx.sipx_node[i]);
219                         tprintf("/[%02x]", addrbuf.sipx.sipx_type);
220                 }
221                 break;
222 #endif /* AF_IPX */
223 #ifdef AF_PACKET
224         case AF_PACKET:
225                 {
226                         int i;
227                         tprintf("proto=%#04x, if%d, pkttype=",
228                                         ntohs(addrbuf.ll.sll_protocol),
229                                         addrbuf.ll.sll_ifindex);
230                         printxval(af_packet_types, addrbuf.ll.sll_pkttype, "PACKET_???");
231                         tprintf(", addr(%d)={%d, ",
232                                         addrbuf.ll.sll_halen,
233                                         addrbuf.ll.sll_hatype);
234                         for (i = 0; i < addrbuf.ll.sll_halen; i++)
235                                 tprintf("%02x", addrbuf.ll.sll_addr[i]);
236                 }
237                 break;
238
239 #endif /* AF_PACKET */
240 #ifdef AF_NETLINK
241         case AF_NETLINK:
242                 tprintf("pid=%d, groups=%08x", addrbuf.nl.nl_pid, addrbuf.nl.nl_groups);
243                 break;
244 #endif /* AF_NETLINK */
245 #if defined(AF_BLUETOOTH) && defined(HAVE_BLUETOOTH_BLUETOOTH_H)
246         case AF_BLUETOOTH:
247                 tprintf("{sco_bdaddr=%02X:%02X:%02X:%02X:%02X:%02X} or "
248                         "{rc_bdaddr=%02X:%02X:%02X:%02X:%02X:%02X, rc_channel=%d} or "
249                         "{l2_psm=htobs(%d), l2_bdaddr=%02X:%02X:%02X:%02X:%02X:%02X, l2_cid=htobs(%d)} or "
250                         "{hci_dev=htobs(%d)}",
251                         addrbuf.sco.sco_bdaddr.b[0], addrbuf.sco.sco_bdaddr.b[1],
252                         addrbuf.sco.sco_bdaddr.b[2], addrbuf.sco.sco_bdaddr.b[3],
253                         addrbuf.sco.sco_bdaddr.b[4], addrbuf.sco.sco_bdaddr.b[5],
254                         addrbuf.rc.rc_bdaddr.b[0], addrbuf.rc.rc_bdaddr.b[1],
255                         addrbuf.rc.rc_bdaddr.b[2], addrbuf.rc.rc_bdaddr.b[3],
256                         addrbuf.rc.rc_bdaddr.b[4], addrbuf.rc.rc_bdaddr.b[5],
257                         addrbuf.rc.rc_channel,
258                         btohs(addrbuf.l2.l2_psm), addrbuf.l2.l2_bdaddr.b[0],
259                         addrbuf.l2.l2_bdaddr.b[1], addrbuf.l2.l2_bdaddr.b[2],
260                         addrbuf.l2.l2_bdaddr.b[3], addrbuf.l2.l2_bdaddr.b[4],
261                         addrbuf.l2.l2_bdaddr.b[5], btohs(addrbuf.l2.l2_cid),
262                         btohs(addrbuf.hci.hci_dev));
263                 break;
264 #endif /* AF_BLUETOOTH && HAVE_BLUETOOTH_BLUETOOTH_H */
265         /* AF_AX25 AF_APPLETALK AF_NETROM AF_BRIDGE AF_AAL5
266         AF_X25 AF_ROSE etc. still need to be done */
267
268         default:
269                 tprints("sa_data=");
270                 print_quoted_string(addrbuf.sa.sa_data,
271                                     sizeof(addrbuf.sa.sa_data), 0);
272                 break;
273         }
274         tprints("}");
275 }
276
277 #ifdef HAVE_SENDMSG
278 # ifndef SCM_SECURITY
279 #  define SCM_SECURITY 0x03
280 # endif
281 # include "xlat/scmvals.h"
282
283 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
284 struct cmsghdr32 {
285         uint32_t cmsg_len;
286         int cmsg_level;
287         int cmsg_type;
288 };
289 #endif
290
291 typedef union {
292         char *ptr;
293         struct cmsghdr *cmsg;
294 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
295         struct cmsghdr32 *cmsg32;
296 #endif
297 } union_cmsghdr;
298
299 static bool
300 print_scm_rights(struct tcb *tcp, size_t cmsg_size, char *ptr, size_t cmsg_len)
301 {
302         if (cmsg_size + sizeof(int) > cmsg_len)
303                 return false;
304
305         int *fds = (int *) (ptr + cmsg_size);
306         bool seen = false;
307
308         tprints(", [");
309         while ((char *) fds < (ptr + cmsg_len)) {
310                 if (seen)
311                         tprints(", ");
312                 else
313                         seen = true;
314                 printfd(tcp, *fds++);
315         }
316         tprints("]}");
317         return true;
318 }
319
320 static bool
321 print_scm_creds(struct tcb *tcp, size_t cmsg_size, char *ptr, size_t cmsg_len)
322 {
323         if (cmsg_size + sizeof(struct ucred) > cmsg_len)
324                 return false;
325
326         const struct ucred *uc = (void *) (ptr + cmsg_size);
327
328         tprintf(", {pid=%u, uid=%u, gid=%u}}",
329                 (unsigned) uc->pid, (unsigned) uc->uid, (unsigned) uc->gid);
330         return true;
331 }
332
333 static bool
334 print_scm_security(struct tcb *tcp, size_t cmsg_size, char *ptr, size_t cmsg_len)
335 {
336         if (cmsg_size + sizeof(char) > cmsg_len)
337                 return false;
338
339         const char *label = (const char *) (ptr + cmsg_size);
340         const size_t label_len = cmsg_len - cmsg_size;
341
342         tprints(", ");
343         print_quoted_string(label, label_len, 0);
344         tprints("}");
345
346         return true;
347 }
348
349 static void
350 printcmsghdr(struct tcb *tcp, unsigned long addr, size_t len)
351 {
352         const size_t cmsg_size =
353 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
354                 (current_wordsize < sizeof(long)) ? sizeof(struct cmsghdr32) :
355 #endif
356                         sizeof(struct cmsghdr);
357
358         char *buf = len < cmsg_size ? NULL : malloc(len);
359         if (!buf || umoven(tcp, addr, len, buf) < 0) {
360                 tprints(", msg_control=");
361                 printaddr(addr);
362                 free(buf);
363                 return;
364         }
365
366         union_cmsghdr u = { .ptr = buf };
367
368         tprints(", [");
369         while (len >= cmsg_size) {
370                 size_t cmsg_len =
371 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
372                         (current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_len :
373 #endif
374                                 u.cmsg->cmsg_len;
375                 int cmsg_level =
376 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
377                         (current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_level :
378 #endif
379                                 u.cmsg->cmsg_level;
380                 int cmsg_type =
381 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
382                         (current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_type :
383 #endif
384                                 u.cmsg->cmsg_type;
385
386                 if (u.ptr != buf)
387                         tprints(", ");
388                 tprintf("{cmsg_len=%lu, cmsg_level=", (unsigned long) cmsg_len);
389                 printxval(socketlayers, cmsg_level, "SOL_???");
390                 tprints(", cmsg_type=");
391
392                 if (cmsg_len > len)
393                         cmsg_len = len;
394
395                 if (cmsg_level == SOL_SOCKET) {
396                         printxval(scmvals, cmsg_type, "SCM_???");
397                         switch (cmsg_type) {
398                         case SCM_RIGHTS:
399                                 if (print_scm_rights(tcp, cmsg_size, u.ptr, cmsg_len))
400                                         goto next_cmsg;
401                                 break;
402                         case SCM_CREDENTIALS:
403                                 if (print_scm_creds(tcp, cmsg_size, u.ptr, cmsg_len))
404                                         goto next_cmsg;
405                                 break;
406                         case SCM_SECURITY:
407                                 if (print_scm_security(tcp, cmsg_size, u.ptr, cmsg_len))
408                                         goto next_cmsg;
409                                 break;
410                         }
411                 } else {
412                         tprintf("%u", cmsg_type);
413                 }
414                 tprints(", ...}");
415 next_cmsg:
416                 if (cmsg_len < cmsg_size) {
417                         len -= cmsg_size;
418                         break;
419                 }
420                 cmsg_len = (cmsg_len + current_wordsize - 1) &
421                         (size_t) ~(current_wordsize - 1);
422                 if (cmsg_len >= len) {
423                         len = 0;
424                         break;
425                 }
426                 u.ptr += cmsg_len;
427                 len -= cmsg_len;
428         }
429         if (len)
430                 tprints(", ...");
431         tprints("]");
432         free(buf);
433 }
434
435 static void
436 do_msghdr(struct tcb *tcp, struct msghdr *msg, unsigned long data_size)
437 {
438         tprintf("{msg_name(%d)=", msg->msg_namelen);
439         printsock(tcp, (long)msg->msg_name, msg->msg_namelen);
440
441         tprintf(", msg_iov(%lu)=", (unsigned long)msg->msg_iovlen);
442         tprint_iov_upto(tcp, (unsigned long)msg->msg_iovlen,
443                    (unsigned long)msg->msg_iov, 1, data_size);
444
445 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
446         tprintf(", msg_controllen=%lu", (unsigned long)msg->msg_controllen);
447         if (msg->msg_controllen)
448                 printcmsghdr(tcp, (unsigned long) msg->msg_control,
449                              msg->msg_controllen);
450         tprints(", msg_flags=");
451         printflags(msg_flags, msg->msg_flags, "MSG_???");
452 #else /* !HAVE_STRUCT_MSGHDR_MSG_CONTROL */
453         tprintf("msg_accrights=%#lx, msg_accrightslen=%u",
454                 (unsigned long) msg->msg_accrights, msg->msg_accrightslen);
455 #endif /* !HAVE_STRUCT_MSGHDR_MSG_CONTROL */
456         tprints("}");
457 }
458
459 struct msghdr32 {
460         uint32_t /* void* */    msg_name;
461         uint32_t /* socklen_t */msg_namelen;
462         uint32_t /* iovec* */   msg_iov;
463         uint32_t /* size_t */   msg_iovlen;
464         uint32_t /* void* */    msg_control;
465         uint32_t /* size_t */   msg_controllen;
466         uint32_t /* int */      msg_flags;
467 };
468 struct mmsghdr32 {
469         struct msghdr32         msg_hdr;
470         uint32_t /* unsigned */ msg_len;
471 };
472
473 #ifndef HAVE_STRUCT_MMSGHDR
474 struct mmsghdr {
475         struct msghdr msg_hdr;
476         unsigned msg_len;
477 };
478 #endif
479
480 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
481 static void
482 copy_from_msghdr32(struct msghdr *to_msg, struct msghdr32 *from_msg32)
483 {
484         to_msg->msg_name       = (void*)(long)from_msg32->msg_name;
485         to_msg->msg_namelen    =              from_msg32->msg_namelen;
486         to_msg->msg_iov        = (void*)(long)from_msg32->msg_iov;
487         to_msg->msg_iovlen     =              from_msg32->msg_iovlen;
488         to_msg->msg_control    = (void*)(long)from_msg32->msg_control;
489         to_msg->msg_controllen =              from_msg32->msg_controllen;
490         to_msg->msg_flags      =              from_msg32->msg_flags;
491 }
492 #endif
493
494 static bool
495 extractmsghdr(struct tcb *tcp, long addr, struct msghdr *msg)
496 {
497 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
498         if (current_wordsize == 4) {
499                 struct msghdr32 msg32;
500
501                 if (umove(tcp, addr, &msg32) < 0)
502                         return false;
503                 copy_from_msghdr32(msg, &msg32);
504         } else
505 #endif
506         if (umove(tcp, addr, msg) < 0)
507                 return false;
508         return true;
509 }
510
511 static bool
512 extractmmsghdr(struct tcb *tcp, long addr, unsigned int idx, struct mmsghdr *mmsg)
513 {
514 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
515         if (current_wordsize == 4) {
516                 struct mmsghdr32 mmsg32;
517
518                 addr += sizeof(struct mmsghdr32) * idx;
519                 if (umove(tcp, addr, &mmsg32) < 0)
520                         return false;
521
522                 copy_from_msghdr32(&mmsg->msg_hdr, &mmsg32.msg_hdr);
523                 mmsg->msg_len = mmsg32.msg_len;
524         } else
525 #endif
526         {
527                 addr += sizeof(*mmsg) * idx;
528                 if (umove(tcp, addr, mmsg) < 0)
529                         return false;
530         }
531         return true;
532 }
533
534 static void
535 printmsghdr(struct tcb *tcp, long addr, unsigned long data_size)
536 {
537         struct msghdr msg;
538
539         if (verbose(tcp) && extractmsghdr(tcp, addr, &msg))
540                 do_msghdr(tcp, &msg, data_size);
541         else
542                 printaddr(addr);
543 }
544
545 void
546 dumpiov_in_msghdr(struct tcb *tcp, long addr)
547 {
548         struct msghdr msg;
549
550         if (extractmsghdr(tcp, addr, &msg))
551                 dumpiov(tcp, msg.msg_iovlen, (long)msg.msg_iov);
552 }
553
554 static void
555 printmmsghdr(struct tcb *tcp, long addr, unsigned int idx, unsigned long msg_len)
556 {
557         struct mmsghdr mmsg;
558
559         if (extractmmsghdr(tcp, addr, idx, &mmsg)) {
560                 tprints("{");
561                 do_msghdr(tcp, &mmsg.msg_hdr, msg_len ? msg_len : mmsg.msg_len);
562                 tprintf(", %u}", mmsg.msg_len);
563         }
564         else
565                 printaddr(addr);
566 }
567
568 static void
569 decode_mmsg(struct tcb *tcp, unsigned long msg_len)
570 {
571         /* mmsgvec */
572         if (syserror(tcp)) {
573                 printaddr(tcp->u_arg[1]);
574         } else {
575                 unsigned int len = tcp->u_rval;
576                 unsigned int i;
577
578                 tprints("{");
579                 for (i = 0; i < len; ++i) {
580                         if (i)
581                                 tprints(", ");
582                         printmmsghdr(tcp, tcp->u_arg[1], i, msg_len);
583                 }
584                 tprints("}");
585         }
586         /* vlen */
587         tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
588         /* flags */
589         printflags(msg_flags, tcp->u_arg[3], "MSG_???");
590 }
591
592 void
593 dumpiov_in_mmsghdr(struct tcb *tcp, long addr)
594 {
595         unsigned int len = tcp->u_rval;
596         unsigned int i;
597         struct mmsghdr mmsg;
598
599         for (i = 0; i < len; ++i) {
600                 if (extractmmsghdr(tcp, addr, i, &mmsg)) {
601                         tprintf(" = %lu buffers in vector %u\n",
602                                 (unsigned long)mmsg.msg_hdr.msg_iovlen, i);
603                         dumpiov(tcp, mmsg.msg_hdr.msg_iovlen,
604                                 (long)mmsg.msg_hdr.msg_iov);
605                 }
606         }
607 }
608 #endif /* HAVE_SENDMSG */
609
610 /*
611  * low bits of the socket type define real socket type,
612  * other bits are socket type flags.
613  */
614 static void
615 tprint_sock_type(int flags)
616 {
617         const char *str = xlookup(socktypes, flags & SOCK_TYPE_MASK);
618
619         if (str) {
620                 tprints(str);
621                 flags &= ~SOCK_TYPE_MASK;
622                 if (!flags)
623                         return;
624                 tprints("|");
625         }
626         printflags(sock_type_flags, flags, "SOCK_???");
627 }
628
629 SYS_FUNC(socket)
630 {
631         printxval(domains, tcp->u_arg[0], "PF_???");
632         tprints(", ");
633         tprint_sock_type(tcp->u_arg[1]);
634         tprints(", ");
635         switch (tcp->u_arg[0]) {
636         case PF_INET:
637 #ifdef PF_INET6
638         case PF_INET6:
639 #endif
640                 printxval(inet_protocols, tcp->u_arg[2], "IPPROTO_???");
641                 break;
642 #ifdef PF_IPX
643         case PF_IPX:
644                 /* BTW: I don't believe this.. */
645                 tprints("[");
646                 printxval(domains, tcp->u_arg[2], "PF_???");
647                 tprints("]");
648                 break;
649 #endif /* PF_IPX */
650 #ifdef PF_NETLINK
651         case PF_NETLINK:
652                 printxval(netlink_protocols, tcp->u_arg[2], "NETLINK_???");
653                 break;
654 #endif
655 #if defined(PF_BLUETOOTH) && defined(HAVE_BLUETOOTH_BLUETOOTH_H)
656         case PF_BLUETOOTH:
657                 printxval(bt_protocols, tcp->u_arg[2], "BTPROTO_???");
658                 break;
659 #endif
660         default:
661                 tprintf("%lu", tcp->u_arg[2]);
662                 break;
663         }
664
665         return RVAL_DECODED | RVAL_FD;
666 }
667
668 SYS_FUNC(bind)
669 {
670         printfd(tcp, tcp->u_arg[0]);
671         tprints(", ");
672         printsock(tcp, tcp->u_arg[1], tcp->u_arg[2]);
673         tprintf(", %lu", tcp->u_arg[2]);
674
675         return RVAL_DECODED;
676 }
677
678 SYS_FUNC(listen)
679 {
680         printfd(tcp, tcp->u_arg[0]);
681         tprints(", ");
682         tprintf("%lu", tcp->u_arg[1]);
683
684         return RVAL_DECODED;
685 }
686
687 static int
688 do_sockname(struct tcb *tcp, int flags_arg)
689 {
690         if (entering(tcp)) {
691                 printfd(tcp, tcp->u_arg[0]);
692                 tprints(", ");
693                 return 0;
694         }
695
696         int len;
697         if (!tcp->u_arg[2] || !verbose(tcp) || syserror(tcp) ||
698             umove(tcp, tcp->u_arg[2], &len) < 0) {
699                 printaddr(tcp->u_arg[1]);
700                 tprints(", ");
701                 printaddr(tcp->u_arg[2]);
702         } else {
703                 printsock(tcp, tcp->u_arg[1], len);
704                 tprintf(", [%d]", len);
705         }
706
707         if (flags_arg >= 0) {
708                 tprints(", ");
709                 printflags(sock_type_flags, tcp->u_arg[flags_arg],
710                            "SOCK_???");
711         }
712         return 0;
713 }
714
715 SYS_FUNC(accept)
716 {
717         do_sockname(tcp, -1);
718         return RVAL_FD;
719 }
720
721 SYS_FUNC(accept4)
722 {
723         do_sockname(tcp, 3);
724         return RVAL_FD;
725 }
726
727 SYS_FUNC(send)
728 {
729         printfd(tcp, tcp->u_arg[0]);
730         tprints(", ");
731         printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
732         tprintf(", %lu, ", tcp->u_arg[2]);
733         /* flags */
734         printflags(msg_flags, tcp->u_arg[3], "MSG_???");
735
736         return RVAL_DECODED;
737 }
738
739 SYS_FUNC(sendto)
740 {
741         printfd(tcp, tcp->u_arg[0]);
742         tprints(", ");
743         printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
744         tprintf(", %lu, ", tcp->u_arg[2]);
745         /* flags */
746         printflags(msg_flags, tcp->u_arg[3], "MSG_???");
747         /* to address */
748         tprints(", ");
749         printsock(tcp, tcp->u_arg[4], tcp->u_arg[5]);
750         /* to length */
751         tprintf(", %lu", tcp->u_arg[5]);
752
753         return RVAL_DECODED;
754 }
755
756 #ifdef HAVE_SENDMSG
757
758 SYS_FUNC(sendmsg)
759 {
760         printfd(tcp, tcp->u_arg[0]);
761         tprints(", ");
762         printmsghdr(tcp, tcp->u_arg[1], (unsigned long) -1L);
763         /* flags */
764         tprints(", ");
765         printflags(msg_flags, tcp->u_arg[2], "MSG_???");
766
767         return RVAL_DECODED;
768 }
769
770 SYS_FUNC(sendmmsg)
771 {
772         if (entering(tcp)) {
773                 /* sockfd */
774                 printfd(tcp, tcp->u_arg[0]);
775                 tprints(", ");
776                 if (!verbose(tcp)) {
777                         tprintf("%#lx, %u, ",
778                                 tcp->u_arg[1], (unsigned int) tcp->u_arg[2]);
779                         printflags(msg_flags, tcp->u_arg[3], "MSG_???");
780                 }
781         } else {
782                 if (verbose(tcp))
783                         decode_mmsg(tcp, (unsigned long) -1L);
784         }
785         return 0;
786 }
787
788 #endif /* HAVE_SENDMSG */
789
790 SYS_FUNC(recv)
791 {
792         if (entering(tcp)) {
793                 printfd(tcp, tcp->u_arg[0]);
794                 tprints(", ");
795         } else {
796                 if (syserror(tcp))
797                         printaddr(tcp->u_arg[1]);
798                 else
799                         printstr(tcp, tcp->u_arg[1], tcp->u_rval);
800
801                 tprintf(", %lu, ", tcp->u_arg[2]);
802                 printflags(msg_flags, tcp->u_arg[3], "MSG_???");
803         }
804         return 0;
805 }
806
807 SYS_FUNC(recvfrom)
808 {
809         int fromlen;
810
811         if (entering(tcp)) {
812                 printfd(tcp, tcp->u_arg[0]);
813                 tprints(", ");
814         } else {
815                 /* buf */
816                 if (syserror(tcp)) {
817                         printaddr(tcp->u_arg[1]);
818                 } else {
819                         printstr(tcp, tcp->u_arg[1], tcp->u_rval);
820                 }
821                 /* len */
822                 tprintf(", %lu, ", tcp->u_arg[2]);
823                 /* flags */
824                 printflags(msg_flags, tcp->u_arg[3], "MSG_???");
825                 tprints(", ");
826                 if (syserror(tcp) || !tcp->u_arg[4] || !tcp->u_arg[5] ||
827                     umove(tcp, tcp->u_arg[5], &fromlen) < 0) {
828                         /* from address, len */
829                         printaddr(tcp->u_arg[4]);
830                         tprints(", ");
831                         printaddr(tcp->u_arg[5]);
832                         return 0;
833                 }
834                 /* from address */
835                 printsock(tcp, tcp->u_arg[4], fromlen);
836                 /* from length */
837                 tprintf(", [%u]", fromlen);
838         }
839         return 0;
840 }
841
842 #ifdef HAVE_SENDMSG
843
844 SYS_FUNC(recvmsg)
845 {
846         if (entering(tcp)) {
847                 printfd(tcp, tcp->u_arg[0]);
848                 tprints(", ");
849         } else {
850                 if (syserror(tcp))
851                         printaddr(tcp->u_arg[1]);
852                 else
853                         printmsghdr(tcp, tcp->u_arg[1], tcp->u_rval);
854                 /* flags */
855                 tprints(", ");
856                 printflags(msg_flags, tcp->u_arg[2], "MSG_???");
857         }
858         return 0;
859 }
860
861 SYS_FUNC(recvmmsg)
862 {
863         /* +5 chars are for "left " prefix */
864         static char str[5 + TIMESPEC_TEXT_BUFSIZE];
865
866         if (entering(tcp)) {
867                 printfd(tcp, tcp->u_arg[0]);
868                 tprints(", ");
869                 if (verbose(tcp)) {
870                         sprint_timespec(str, tcp, tcp->u_arg[4]);
871                         /* Abusing tcp->auxstr as temp storage.
872                          * Will be used and freed on syscall exit.
873                          */
874                         tcp->auxstr = xstrdup(str);
875                 } else {
876                         tprintf("%#lx, %ld, ", tcp->u_arg[1], tcp->u_arg[2]);
877                         printflags(msg_flags, tcp->u_arg[3], "MSG_???");
878                         tprints(", ");
879                         print_timespec(tcp, tcp->u_arg[4]);
880                 }
881                 return 0;
882         } else {
883                 if (verbose(tcp)) {
884                         decode_mmsg(tcp, 0);
885                         /* timeout on entrance */
886                         tprintf(", %s", tcp->auxstr ? tcp->auxstr : "{...}");
887                         free((void *) tcp->auxstr);
888                         tcp->auxstr = NULL;
889                 }
890                 if (syserror(tcp))
891                         return 0;
892                 if (tcp->u_rval == 0) {
893                         tcp->auxstr = "Timeout";
894                         return RVAL_STR;
895                 }
896                 if (!verbose(tcp))
897                         return 0;
898                 /* timeout on exit */
899                 sprint_timespec(stpcpy(str, "left "), tcp, tcp->u_arg[4]);
900                 tcp->auxstr = str;
901                 return RVAL_STR;
902         }
903 }
904
905 #endif /* HAVE_SENDMSG */
906
907 #include "xlat/shutdown_modes.h"
908
909 SYS_FUNC(shutdown)
910 {
911         printfd(tcp, tcp->u_arg[0]);
912         tprints(", ");
913         printxval(shutdown_modes, tcp->u_arg[1], "SHUT_???");
914
915         return RVAL_DECODED;
916 }
917
918 SYS_FUNC(getsockname)
919 {
920         return do_sockname(tcp, -1);
921 }
922
923 static void
924 printpair_fd(struct tcb *tcp, const int i0, const int i1)
925 {
926         tprints("[");
927         printfd(tcp, i0);
928         tprints(", ");
929         printfd(tcp, i1);
930         tprints("]");
931 }
932
933 static void
934 decode_pair_fd(struct tcb *tcp, const long addr)
935 {
936         int pair[2];
937
938         if (umove_or_printaddr(tcp, addr, &pair))
939                 return;
940
941         printpair_fd(tcp, pair[0], pair[1]);
942 }
943
944 static int
945 do_pipe(struct tcb *tcp, int flags_arg)
946 {
947         if (exiting(tcp)) {
948                 if (syserror(tcp)) {
949                         printaddr(tcp->u_arg[0]);
950                 } else {
951 #ifdef HAVE_GETRVAL2
952                         if (flags_arg < 0) {
953                                 printpair_fd(tcp, tcp->u_rval, getrval2(tcp));
954                         } else
955 #endif
956                                 decode_pair_fd(tcp, tcp->u_arg[0]);
957                 }
958                 if (flags_arg >= 0) {
959                         tprints(", ");
960                         printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
961                 }
962         }
963         return 0;
964 }
965
966 SYS_FUNC(pipe)
967 {
968         return do_pipe(tcp, -1);
969 }
970
971 SYS_FUNC(pipe2)
972 {
973         return do_pipe(tcp, 1);
974 }
975
976 SYS_FUNC(socketpair)
977 {
978         if (entering(tcp)) {
979                 printxval(domains, tcp->u_arg[0], "PF_???");
980                 tprints(", ");
981                 tprint_sock_type(tcp->u_arg[1]);
982                 tprintf(", %lu", tcp->u_arg[2]);
983         } else {
984                 tprints(", ");
985                 decode_pair_fd(tcp, tcp->u_arg[3]);
986         }
987         return 0;
988 }
989
990 #include "xlat/sockoptions.h"
991 #include "xlat/sockipoptions.h"
992 #include "xlat/sockipv6options.h"
993 #include "xlat/sockipxoptions.h"
994 #include "xlat/sockrawoptions.h"
995 #include "xlat/sockpacketoptions.h"
996 #include "xlat/socksctpoptions.h"
997 #include "xlat/socktcpoptions.h"
998
999 static void
1000 print_sockopt_fd_level_name(struct tcb *tcp, int fd, int level, int name)
1001 {
1002         printfd(tcp, fd);
1003         tprints(", ");
1004         printxval(socketlayers, level, "SOL_??");
1005         tprints(", ");
1006
1007         switch (level) {
1008         case SOL_SOCKET:
1009                 printxval(sockoptions, name, "SO_???");
1010                 break;
1011         case SOL_IP:
1012                 printxval(sockipoptions, name, "IP_???");
1013                 break;
1014         case SOL_IPV6:
1015                 printxval(sockipv6options, name, "IPV6_???");
1016                 break;
1017         case SOL_IPX:
1018                 printxval(sockipxoptions, name, "IPX_???");
1019                 break;
1020         case SOL_PACKET:
1021                 printxval(sockpacketoptions, name, "PACKET_???");
1022                 break;
1023         case SOL_TCP:
1024                 printxval(socktcpoptions, name, "TCP_???");
1025                 break;
1026         case SOL_SCTP:
1027                 printxval(socksctpoptions, name, "SCTP_???");
1028                 break;
1029         case SOL_RAW:
1030                 printxval(sockrawoptions, name, "RAW_???");
1031                 break;
1032
1033                 /* Other SOL_* protocol levels still need work. */
1034
1035         default:
1036                 tprintf("%u", name);
1037         }
1038
1039         tprints(", ");
1040 }
1041
1042 #ifdef SO_LINGER
1043 static void
1044 print_linger(struct tcb *tcp, long addr, int len)
1045 {
1046         struct linger linger;
1047
1048         if (len != sizeof(linger) ||
1049             umove(tcp, addr, &linger) < 0) {
1050                 printaddr(addr);
1051                 return;
1052         }
1053
1054         tprintf("{onoff=%d, linger=%d}",
1055                 linger.l_onoff,
1056                 linger.l_linger);
1057 }
1058 #endif /* SO_LINGER */
1059
1060 #ifdef SO_PEERCRED
1061 static void
1062 print_ucred(struct tcb *tcp, long addr, int len)
1063 {
1064         struct ucred uc;
1065
1066         if (len != sizeof(uc) ||
1067             umove(tcp, addr, &uc) < 0) {
1068                 printaddr(addr);
1069         } else {
1070                 tprintf("{pid=%u, uid=%u, gid=%u}",
1071                         (unsigned) uc.pid,
1072                         (unsigned) uc.uid,
1073                         (unsigned) uc.gid);
1074         }
1075 }
1076 #endif /* SO_PEERCRED */
1077
1078 #ifdef PACKET_STATISTICS
1079 static void
1080 print_tpacket_stats(struct tcb *tcp, long addr, int len)
1081 {
1082         struct tpacket_stats stats;
1083
1084         if (len != sizeof(stats) ||
1085             umove(tcp, addr, &stats) < 0) {
1086                 printaddr(addr);
1087         } else {
1088                 tprintf("{packets=%u, drops=%u}",
1089                         stats.tp_packets,
1090                         stats.tp_drops);
1091         }
1092 }
1093 #endif /* PACKET_STATISTICS */
1094
1095 #ifdef ICMP_FILTER
1096 # include "xlat/icmpfilterflags.h"
1097
1098 static void
1099 print_icmp_filter(struct tcb *tcp, long addr, int len)
1100 {
1101         struct icmp_filter      filter;
1102
1103         if (len != sizeof(filter) ||
1104             umove(tcp, addr, &filter) < 0) {
1105                 printaddr(addr);
1106                 return;
1107         }
1108
1109         tprints("~(");
1110         printflags(icmpfilterflags, ~filter.data, "ICMP_???");
1111         tprints(")");
1112 }
1113 #endif /* ICMP_FILTER */
1114
1115 static void
1116 print_getsockopt(struct tcb *tcp, int level, int name, long addr, int len)
1117 {
1118         if (addr && verbose(tcp))
1119         switch (level) {
1120         case SOL_SOCKET:
1121                 switch (name) {
1122 #ifdef SO_LINGER
1123                 case SO_LINGER:
1124                         print_linger(tcp, addr, len);
1125                         goto done;
1126 #endif
1127 #ifdef SO_PEERCRED
1128                 case SO_PEERCRED:
1129                         print_ucred(tcp, addr, len);
1130                         goto done;
1131 #endif
1132                 }
1133                 break;
1134
1135         case SOL_PACKET:
1136                 switch (name) {
1137 #ifdef PACKET_STATISTICS
1138                 case PACKET_STATISTICS:
1139                         print_tpacket_stats(tcp, addr, len);
1140                         goto done;
1141 #endif
1142                 }
1143                 break;
1144
1145         case SOL_RAW:
1146                 switch (name) {
1147 #ifdef ICMP_FILTER
1148                 case ICMP_FILTER:
1149                         print_icmp_filter(tcp, addr, len);
1150                         goto done;
1151 #endif
1152                 }
1153                 break;
1154         }
1155
1156         /* default arg printing */
1157
1158         if (verbose(tcp)) {
1159                 if (len == sizeof(int)) {
1160                         printnum_int(tcp, addr, "%d");
1161                 } else {
1162                         printstr(tcp, addr, len);
1163                 }
1164         } else {
1165                 printaddr(addr);
1166         }
1167 done:
1168         tprintf(", [%d]", len);
1169 }
1170
1171 SYS_FUNC(getsockopt)
1172 {
1173         if (entering(tcp)) {
1174                 print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
1175                                             tcp->u_arg[1], tcp->u_arg[2]);
1176         } else {
1177                 int len;
1178
1179                 if (syserror(tcp) || umove(tcp, tcp->u_arg[4], &len) < 0) {
1180                         tprintf("%#lx, %#lx",
1181                                 tcp->u_arg[3], tcp->u_arg[4]);
1182                 } else {
1183                         print_getsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
1184                                          tcp->u_arg[3], len);
1185                 }
1186         }
1187         return 0;
1188 }
1189
1190 #ifdef IP_ADD_MEMBERSHIP
1191 static void
1192 print_mreq(struct tcb *tcp, long addr, unsigned int len)
1193 {
1194         struct ip_mreq mreq;
1195
1196         if (len < sizeof(mreq)) {
1197                 printstr(tcp, addr, len);
1198                 return;
1199         }
1200         if (umove_or_printaddr(tcp, addr, &mreq))
1201                 return;
1202
1203         tprints("{imr_multiaddr=inet_addr(");
1204         print_quoted_string(inet_ntoa(mreq.imr_multiaddr),
1205                             16, QUOTE_0_TERMINATED);
1206         tprints("), imr_interface=inet_addr(");
1207         print_quoted_string(inet_ntoa(mreq.imr_interface),
1208                             16, QUOTE_0_TERMINATED);
1209         tprints(")}");
1210 }
1211 #endif /* IP_ADD_MEMBERSHIP */
1212
1213 #ifdef IPV6_ADD_MEMBERSHIP
1214 static void
1215 print_mreq6(struct tcb *tcp, long addr, unsigned int len)
1216 {
1217         struct ipv6_mreq mreq;
1218
1219         if (len < sizeof(mreq))
1220                 goto fail;
1221
1222         if (umove_or_printaddr(tcp, addr, &mreq))
1223                 return;
1224
1225 #ifdef HAVE_INET_NTOP
1226         const struct in6_addr *in6 = &mreq.ipv6mr_multiaddr;
1227         char address[INET6_ADDRSTRLEN];
1228
1229         if (!inet_ntop(AF_INET6, in6, address, sizeof(address)))
1230                 goto fail;
1231
1232         tprints("{ipv6mr_multiaddr=inet_pton(");
1233         print_quoted_string(address, sizeof(address), QUOTE_0_TERMINATED);
1234         tprints("), ipv6mr_interface=");
1235         print_ifindex(mreq.ipv6mr_interface);
1236         tprints("}");
1237         return;
1238 #endif /* HAVE_INET_NTOP */
1239
1240 fail:
1241         printstr(tcp, addr, len);
1242 }
1243 #endif /* IPV6_ADD_MEMBERSHIP */
1244
1245 #ifdef MCAST_JOIN_GROUP
1246 static void
1247 print_group_req(struct tcb *tcp, long addr, int len)
1248 {
1249         struct group_req greq;
1250
1251         if (len != sizeof(greq) ||
1252             umove(tcp, addr, &greq) < 0) {
1253                 printaddr(addr);
1254                 return;
1255         }
1256
1257         union {
1258                 struct sockaddr *sa;
1259                 struct sockaddr_in *sin;
1260 #ifdef HAVE_INET_NTOP
1261                 struct sockaddr_in6 *sin6;
1262 #endif
1263         } a = { .sa = (struct sockaddr *) &greq.gr_group };
1264 #ifdef HAVE_INET_NTOP
1265         char str[INET6_ADDRSTRLEN];
1266 #endif
1267
1268         tprintf("{gr_interface=%u, gr_group={sa_family=", greq.gr_interface);
1269         printxval(addrfams, a.sa->sa_family, "AF_???");
1270
1271         switch (a.sa->sa_family) {
1272         case AF_INET:
1273                 tprintf(", sin_port=htons(%u), sin_addr=inet_addr(\"%s\")}}",
1274                         ntohs(a.sin->sin_port),
1275                         inet_ntoa(a.sin->sin_addr));
1276                 return;
1277 #ifdef HAVE_INET_NTOP
1278         case AF_INET6:
1279                 if (!inet_ntop(AF_INET6, &a.sin6->sin6_addr, str, sizeof(str)))
1280                         break;
1281                 tprintf(", sin6_port=htons(%u)"
1282                         ", inet_pton(AF_INET6, \"%s\", &sin6_addr)}}",
1283                         ntohs(a.sin6->sin6_port), str);
1284                 return;
1285 #endif /* HAVE_INET_NTOP */
1286         }
1287
1288         tprints(", sa_data=");
1289         print_quoted_string(a.sa->sa_data, sizeof(a.sa->sa_data), 0);
1290         tprintf("}}");
1291
1292 }
1293 #endif /* MCAST_JOIN_GROUP */
1294
1295 #ifdef PACKET_RX_RING
1296 static void
1297 print_tpacket_req(struct tcb *tcp, long addr, int len)
1298 {
1299         struct tpacket_req req;
1300
1301         if (len != sizeof(req) ||
1302             umove(tcp, addr, &req) < 0) {
1303                 printaddr(addr);
1304         } else {
1305                 tprintf("{block_size=%u, block_nr=%u, "
1306                         "frame_size=%u, frame_nr=%u}",
1307                         req.tp_block_size,
1308                         req.tp_block_nr,
1309                         req.tp_frame_size,
1310                         req.tp_frame_nr);
1311         }
1312 }
1313 #endif /* PACKET_RX_RING */
1314
1315 #ifdef PACKET_ADD_MEMBERSHIP
1316 # include "xlat/packet_mreq_type.h"
1317
1318 static void
1319 print_packet_mreq(struct tcb *tcp, long addr, int len)
1320 {
1321         struct packet_mreq mreq;
1322
1323         if (len != sizeof(mreq) ||
1324             umove(tcp, addr, &mreq) < 0) {
1325                 printaddr(addr);
1326         } else {
1327                 unsigned int i;
1328
1329                 tprintf("{mr_ifindex=%u, mr_type=", mreq.mr_ifindex);
1330                 printxval(packet_mreq_type, mreq.mr_type, "PACKET_MR_???");
1331                 tprintf(", mr_alen=%u, mr_address=", mreq.mr_alen);
1332                 if (mreq.mr_alen > ARRAY_SIZE(mreq.mr_address))
1333                         mreq.mr_alen = ARRAY_SIZE(mreq.mr_address);
1334                 for (i = 0; i < mreq.mr_alen; ++i)
1335                         tprintf("%02x", mreq.mr_address[i]);
1336                 tprints("}");
1337         }
1338 }
1339 #endif /* PACKET_ADD_MEMBERSHIP */
1340
1341 static void
1342 print_setsockopt(struct tcb *tcp, int level, int name, long addr, int len)
1343 {
1344         if (addr && verbose(tcp))
1345         switch (level) {
1346         case SOL_SOCKET:
1347                 switch (name) {
1348 #ifdef SO_LINGER
1349                 case SO_LINGER:
1350                         print_linger(tcp, addr, len);
1351                         goto done;
1352 #endif
1353                 }
1354                 break;
1355
1356         case SOL_IP:
1357                 switch (name) {
1358 #ifdef IP_ADD_MEMBERSHIP
1359                 case IP_ADD_MEMBERSHIP:
1360                 case IP_DROP_MEMBERSHIP:
1361                         print_mreq(tcp, addr, len);
1362                         goto done;
1363 #endif /* IP_ADD_MEMBERSHIP */
1364 #ifdef MCAST_JOIN_GROUP
1365                 case MCAST_JOIN_GROUP:
1366                 case MCAST_LEAVE_GROUP:
1367                         print_group_req(tcp, addr, len);
1368                         goto done;
1369 #endif /* MCAST_JOIN_GROUP */
1370                 }
1371                 break;
1372
1373         case SOL_IPV6:
1374                 switch (name) {
1375 #ifdef IPV6_ADD_MEMBERSHIP
1376                 case IPV6_ADD_MEMBERSHIP:
1377                 case IPV6_DROP_MEMBERSHIP:
1378 # ifdef IPV6_JOIN_ANYCAST
1379                 case IPV6_JOIN_ANYCAST:
1380 # endif
1381 # ifdef IPV6_LEAVE_ANYCAST
1382                 case IPV6_LEAVE_ANYCAST:
1383 # endif
1384                         print_mreq6(tcp, addr, len);
1385                         goto done;
1386 #endif /* IPV6_ADD_MEMBERSHIP */
1387                 }
1388                 break;
1389
1390         case SOL_PACKET:
1391                 switch (name) {
1392 #ifdef PACKET_RX_RING
1393                 case PACKET_RX_RING:
1394 # ifdef PACKET_TX_RING
1395                 case PACKET_TX_RING:
1396 # endif
1397                         print_tpacket_req(tcp, addr, len);
1398                         goto done;
1399 #endif /* PACKET_RX_RING */
1400 #ifdef PACKET_ADD_MEMBERSHIP
1401                 case PACKET_ADD_MEMBERSHIP:
1402                 case PACKET_DROP_MEMBERSHIP:
1403                         print_packet_mreq(tcp, addr, len);
1404                         goto done;
1405 #endif /* PACKET_ADD_MEMBERSHIP */
1406                 }
1407                 break;
1408
1409         case SOL_RAW:
1410                 switch (name) {
1411 #ifdef ICMP_FILTER
1412                 case ICMP_FILTER:
1413                         print_icmp_filter(tcp, addr, len);
1414                         goto done;
1415 #endif
1416                 }
1417                 break;
1418         }
1419
1420         /* default arg printing */
1421
1422         if (verbose(tcp)) {
1423                 if (len == sizeof(int)) {
1424                         printnum_int(tcp, addr, "%d");
1425                 } else {
1426                         printstr(tcp, addr, len);
1427                 }
1428         } else {
1429                 printaddr(addr);
1430         }
1431 done:
1432         tprintf(", %d", len);
1433 }
1434
1435 SYS_FUNC(setsockopt)
1436 {
1437         print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
1438                                     tcp->u_arg[1], tcp->u_arg[2]);
1439         print_setsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
1440                          tcp->u_arg[3], tcp->u_arg[4]);
1441
1442         return RVAL_DECODED;
1443 }