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