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