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