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