]> granicus.if.org Git - strace/blob - net.c
mem: decode hugetlb page size in mmap flags
[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  * Copyright (c) 1999-2017 The strace developers.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "defs.h"
33 #include "print_fields.h"
34
35 #include <sys/stat.h>
36 #include <sys/socket.h>
37 #include <sys/uio.h>
38 #include <sys/un.h>
39 #include <netinet/in.h>
40 #ifdef HAVE_NETINET_TCP_H
41 # include <netinet/tcp.h>
42 #endif
43 #ifdef HAVE_NETINET_UDP_H
44 # include <netinet/udp.h>
45 #endif
46 #ifdef HAVE_NETINET_SCTP_H
47 # include <netinet/sctp.h>
48 #endif
49 #include <arpa/inet.h>
50 #include <net/if.h>
51 #include <asm/types.h>
52 #ifdef HAVE_NETIPX_IPX_H
53 # include <netipx/ipx.h>
54 #else
55 # include <linux/ipx.h>
56 #endif
57
58 #if defined(HAVE_LINUX_IP_VS_H)
59 # include <linux/ip_vs.h>
60 #endif
61 #include "netlink.h"
62 #if defined(HAVE_LINUX_NETFILTER_ARP_ARP_TABLES_H)
63 # include <linux/netfilter_arp/arp_tables.h>
64 #endif
65 #if defined(HAVE_LINUX_NETFILTER_BRIDGE_EBTABLES_H)
66 # include <linux/netfilter_bridge/ebtables.h>
67 #endif
68 #if defined(HAVE_LINUX_NETFILTER_IPV4_IP_TABLES_H)
69 # include <linux/netfilter_ipv4/ip_tables.h>
70 #endif
71 #if defined(HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H)
72 # include <linux/netfilter_ipv6/ip6_tables.h>
73 #endif
74 #include <linux/if_packet.h>
75 #include <linux/icmp.h>
76
77 #include "xlat/socktypes.h"
78 #include "xlat/sock_type_flags.h"
79 #ifndef SOCK_TYPE_MASK
80 # define SOCK_TYPE_MASK 0xf
81 #endif
82
83 #include "xlat/socketlayers.h"
84
85 #include "xlat/inet_protocols.h"
86
87 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
88 # include <bluetooth/bluetooth.h>
89 # include "xlat/bt_protocols.h"
90 #endif
91
92 static void
93 decode_sockbuf(struct tcb *const tcp, const int fd, const kernel_ulong_t addr,
94                const kernel_ulong_t addrlen)
95 {
96
97         switch (verbose(tcp) ? getfdproto(tcp, fd) : SOCK_PROTO_UNKNOWN) {
98         case SOCK_PROTO_NETLINK:
99                 decode_netlink(tcp, fd, addr, addrlen);
100                 break;
101         default:
102                 printstrn(tcp, addr, addrlen);
103         }
104 }
105
106 /*
107  * low bits of the socket type define real socket type,
108  * other bits are socket type flags.
109  */
110 static void
111 tprint_sock_type(unsigned int flags)
112 {
113         const char *str = xlookup(socktypes, flags & SOCK_TYPE_MASK);
114
115         if (str) {
116                 tprints(str);
117                 flags &= ~SOCK_TYPE_MASK;
118                 if (!flags)
119                         return;
120                 tprints("|");
121         }
122         printflags(sock_type_flags, flags, "SOCK_???");
123 }
124
125 SYS_FUNC(socket)
126 {
127         printxval(addrfams, tcp->u_arg[0], "AF_???");
128         tprints(", ");
129         tprint_sock_type(tcp->u_arg[1]);
130         tprints(", ");
131         switch (tcp->u_arg[0]) {
132         case AF_INET:
133         case AF_INET6:
134                 printxval(inet_protocols, tcp->u_arg[2], "IPPROTO_???");
135                 break;
136
137         case AF_NETLINK:
138                 printxval(netlink_protocols, tcp->u_arg[2], "NETLINK_???");
139                 break;
140
141 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
142         case AF_BLUETOOTH:
143                 printxval(bt_protocols, tcp->u_arg[2], "BTPROTO_???");
144                 break;
145 #endif
146
147         default:
148                 tprintf("%" PRI_klu, tcp->u_arg[2]);
149                 break;
150         }
151
152         return RVAL_DECODED | RVAL_FD;
153 }
154
155 static bool
156 fetch_socklen(struct tcb *const tcp, int *const plen,
157               const kernel_ulong_t sockaddr, const kernel_ulong_t socklen)
158 {
159         return verbose(tcp) && sockaddr && socklen
160                && umove(tcp, socklen, plen) == 0;
161 }
162
163 static int
164 decode_sockname(struct tcb *tcp)
165 {
166         int ulen, rlen;
167
168         if (entering(tcp)) {
169                 printfd(tcp, tcp->u_arg[0]);
170                 tprints(", ");
171                 if (fetch_socklen(tcp, &ulen, tcp->u_arg[1], tcp->u_arg[2])) {
172                         set_tcb_priv_ulong(tcp, ulen);
173                         return 0;
174                 } else {
175                         printaddr(tcp->u_arg[1]);
176                         tprints(", ");
177                         printaddr(tcp->u_arg[2]);
178                         return RVAL_DECODED;
179                 }
180         }
181
182         ulen = get_tcb_priv_ulong(tcp);
183
184         if (syserror(tcp) || umove(tcp, tcp->u_arg[2], &rlen) < 0) {
185                 printaddr(tcp->u_arg[1]);
186                 tprintf(", [%d]", ulen);
187         } else {
188                 decode_sockaddr(tcp, tcp->u_arg[1], ulen > rlen ? rlen : ulen);
189                 if (ulen != rlen)
190                         tprintf(", [%d->%d]", ulen, rlen);
191                 else
192                         tprintf(", [%d]", rlen);
193         }
194
195         return RVAL_DECODED;
196 }
197
198 SYS_FUNC(accept)
199 {
200         return decode_sockname(tcp) | RVAL_FD;
201 }
202
203 SYS_FUNC(accept4)
204 {
205         int rc = decode_sockname(tcp);
206
207         if (rc & RVAL_DECODED) {
208                 tprints(", ");
209                 printflags(sock_type_flags, tcp->u_arg[3], "SOCK_???");
210         }
211
212         return rc | RVAL_FD;
213 }
214
215 SYS_FUNC(send)
216 {
217         printfd(tcp, tcp->u_arg[0]);
218         tprints(", ");
219         decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]);
220         tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
221         /* flags */
222         printflags(msg_flags, tcp->u_arg[3], "MSG_???");
223
224         return RVAL_DECODED;
225 }
226
227 SYS_FUNC(sendto)
228 {
229         printfd(tcp, tcp->u_arg[0]);
230         tprints(", ");
231         decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]);
232         tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
233         /* flags */
234         printflags(msg_flags, tcp->u_arg[3], "MSG_???");
235         /* to address */
236         const int addrlen = tcp->u_arg[5];
237         tprints(", ");
238         decode_sockaddr(tcp, tcp->u_arg[4], addrlen);
239         /* to length */
240         tprintf(", %d", addrlen);
241
242         return RVAL_DECODED;
243 }
244
245 SYS_FUNC(recv)
246 {
247         if (entering(tcp)) {
248                 printfd(tcp, tcp->u_arg[0]);
249                 tprints(", ");
250         } else {
251                 if (syserror(tcp)) {
252                         printaddr(tcp->u_arg[1]);
253                 } else {
254                         decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1],
255                                      tcp->u_rval);
256                 }
257
258                 tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
259                 printflags(msg_flags, tcp->u_arg[3], "MSG_???");
260         }
261         return 0;
262 }
263
264 SYS_FUNC(recvfrom)
265 {
266         int ulen, rlen;
267
268         if (entering(tcp)) {
269                 printfd(tcp, tcp->u_arg[0]);
270                 tprints(", ");
271                 if (fetch_socklen(tcp, &ulen, tcp->u_arg[4], tcp->u_arg[5])) {
272                         set_tcb_priv_ulong(tcp, ulen);
273                 }
274         } else {
275                 /* buf */
276                 if (syserror(tcp)) {
277                         printaddr(tcp->u_arg[1]);
278                 } else {
279                         decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1],
280                                      tcp->u_rval);
281                 }
282                 /* size */
283                 tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
284                 /* flags */
285                 printflags(msg_flags, tcp->u_arg[3], "MSG_???");
286                 tprints(", ");
287
288                 ulen = get_tcb_priv_ulong(tcp);
289
290                 if (!fetch_socklen(tcp, &rlen, tcp->u_arg[4], tcp->u_arg[5])) {
291                         /* from address */
292                         printaddr(tcp->u_arg[4]);
293                         tprints(", ");
294                         /* from length */
295                         printaddr(tcp->u_arg[5]);
296                         return 0;
297                 }
298                 if (syserror(tcp)) {
299                         /* from address */
300                         printaddr(tcp->u_arg[4]);
301                         /* from length */
302                         tprintf(", [%d]", ulen);
303                         return 0;
304                 }
305                 /* from address */
306                 decode_sockaddr(tcp, tcp->u_arg[4], ulen > rlen ? rlen : ulen);
307                 /* from length */
308                 if (ulen != rlen)
309                         tprintf(", [%d->%d]", ulen, rlen);
310                 else
311                         tprintf(", [%d]", rlen);
312         }
313         return 0;
314 }
315
316 SYS_FUNC(getsockname)
317 {
318         return decode_sockname(tcp);
319 }
320
321 static void
322 printpair_fd(struct tcb *tcp, const int i0, const int i1)
323 {
324         tprints("[");
325         printfd(tcp, i0);
326         tprints(", ");
327         printfd(tcp, i1);
328         tprints("]");
329 }
330
331 static void
332 decode_pair_fd(struct tcb *const tcp, const kernel_ulong_t addr)
333 {
334         int pair[2];
335
336         if (umove_or_printaddr(tcp, addr, &pair))
337                 return;
338
339         printpair_fd(tcp, pair[0], pair[1]);
340 }
341
342 static int
343 do_pipe(struct tcb *tcp, int flags_arg)
344 {
345         if (exiting(tcp)) {
346                 decode_pair_fd(tcp, tcp->u_arg[0]);
347                 if (flags_arg >= 0) {
348                         tprints(", ");
349                         printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
350                 }
351         }
352         return 0;
353 }
354
355 SYS_FUNC(pipe)
356 {
357 #ifdef HAVE_GETRVAL2
358         if (exiting(tcp) && !syserror(tcp))
359                 printpair_fd(tcp, tcp->u_rval, getrval2(tcp));
360         return 0;
361 #else
362         return do_pipe(tcp, -1);
363 #endif
364 }
365
366 SYS_FUNC(pipe2)
367 {
368         return do_pipe(tcp, 1);
369 }
370
371 SYS_FUNC(socketpair)
372 {
373         if (entering(tcp)) {
374                 printxval(addrfams, tcp->u_arg[0], "AF_???");
375                 tprints(", ");
376                 tprint_sock_type(tcp->u_arg[1]);
377                 tprintf(", %" PRI_klu, tcp->u_arg[2]);
378         } else {
379                 tprints(", ");
380                 decode_pair_fd(tcp, tcp->u_arg[3]);
381         }
382         return 0;
383 }
384
385 #include "xlat/sockoptions.h"
386 #include "xlat/sockipoptions.h"
387 #include "xlat/getsockipoptions.h"
388 #include "xlat/setsockipoptions.h"
389 #include "xlat/sockipv6options.h"
390 #include "xlat/getsockipv6options.h"
391 #include "xlat/setsockipv6options.h"
392 #include "xlat/sockipxoptions.h"
393 #include "xlat/socknetlinkoptions.h"
394 #include "xlat/sockpacketoptions.h"
395 #include "xlat/sockrawoptions.h"
396 #include "xlat/socksctpoptions.h"
397 #include "xlat/socktcpoptions.h"
398
399 static void
400 print_sockopt_fd_level_name(struct tcb *tcp, int fd, unsigned int level,
401                             unsigned int name, bool is_getsockopt)
402 {
403         printfd(tcp, fd);
404         tprints(", ");
405         printxval(socketlayers, level, "SOL_??");
406         tprints(", ");
407
408         switch (level) {
409         case SOL_SOCKET:
410                 printxval(sockoptions, name, "SO_???");
411                 break;
412         case SOL_IP:
413                 printxvals(name, "IP_???", sockipoptions,
414                         is_getsockopt ? getsockipoptions : setsockipoptions, NULL);
415                 break;
416         case SOL_IPV6:
417                 printxvals(name, "IPV6_???", sockipv6options,
418                         is_getsockopt ? getsockipv6options : setsockipv6options, NULL);
419                 break;
420         case SOL_IPX:
421                 printxval(sockipxoptions, name, "IPX_???");
422                 break;
423         case SOL_PACKET:
424                 printxval(sockpacketoptions, name, "PACKET_???");
425                 break;
426         case SOL_TCP:
427                 printxval(socktcpoptions, name, "TCP_???");
428                 break;
429         case SOL_SCTP:
430                 printxval(socksctpoptions, name, "SCTP_???");
431                 break;
432         case SOL_RAW:
433                 printxval(sockrawoptions, name, "RAW_???");
434                 break;
435         case SOL_NETLINK:
436                 printxval(socknetlinkoptions, name, "NETLINK_???");
437                 break;
438
439                 /* Other SOL_* protocol levels still need work. */
440
441         default:
442                 tprintf("%u", name);
443         }
444
445         tprints(", ");
446 }
447
448 static void
449 print_set_linger(struct tcb *const tcp, const kernel_ulong_t addr,
450                  const int len)
451 {
452         struct linger linger;
453
454         if (len < (int) sizeof(linger)) {
455                 printaddr(addr);
456         } else if (!umove_or_printaddr(tcp, addr, &linger)) {
457                 PRINT_FIELD_D("{", linger, l_onoff);
458                 PRINT_FIELD_D(", ", linger, l_linger);
459                 tprints("}");
460         }
461 }
462
463 static void
464 print_get_linger(struct tcb *const tcp, const kernel_ulong_t addr,
465                  unsigned int len)
466 {
467         struct linger linger;
468
469         if (len < sizeof(linger)) {
470                 if (len != sizeof(linger.l_onoff)) {
471                         printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
472                         return;
473                 }
474         } else {
475                 len = sizeof(linger);
476         }
477
478         if (umoven(tcp, addr, len, &linger) < 0) {
479                 printaddr(addr);
480                 return;
481         }
482
483         PRINT_FIELD_D("{", linger, l_onoff);
484         if (len == sizeof(linger))
485                 PRINT_FIELD_D(", ", linger, l_linger);
486         tprints("}");
487 }
488
489 #ifdef SO_PEERCRED
490 static void
491 print_ucred(struct tcb *const tcp, const kernel_ulong_t addr, unsigned int len)
492 {
493         struct ucred uc;
494
495         if (len < sizeof(uc)) {
496                 if (len != sizeof(uc.pid)
497                     && len != offsetofend(struct ucred, uid)) {
498                         printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
499                         return;
500                 }
501         } else {
502                 len = sizeof(uc);
503         }
504
505         if (umoven(tcp, addr, len, &uc) < 0) {
506                 printaddr(addr);
507                 return;
508         }
509
510         PRINT_FIELD_D("{", uc, pid);
511         if (len > sizeof(uc.pid))
512                 PRINT_FIELD_UID(", ", uc, uid);
513         if (len == sizeof(uc))
514                 PRINT_FIELD_UID(", ", uc, gid);
515         tprints("}");
516 }
517 #endif /* SO_PEERCRED */
518
519 #ifdef PACKET_STATISTICS
520 static void
521 print_tpacket_stats(struct tcb *const tcp, const kernel_ulong_t addr,
522                     const int len)
523 {
524         struct tpacket_stats stats;
525
526         if (len != sizeof(stats) ||
527             umove(tcp, addr, &stats) < 0) {
528                 printaddr(addr);
529         } else {
530                 PRINT_FIELD_U("{", stats, tp_packets);
531                 PRINT_FIELD_U("{", stats, tp_drops);
532                 tprints("}");
533         }
534 }
535 #endif /* PACKET_STATISTICS */
536
537 #include "xlat/icmpfilterflags.h"
538
539 static void
540 print_icmp_filter(struct tcb *const tcp, const kernel_ulong_t addr, int len)
541 {
542         struct icmp_filter filter = {};
543
544         if (len > (int) sizeof(filter))
545                 len = sizeof(filter);
546         else if (len <= 0) {
547                 printaddr(addr);
548                 return;
549         }
550
551         if (umoven_or_printaddr(tcp, addr, len, &filter))
552                 return;
553
554         tprints("~(");
555         printflags(icmpfilterflags, ~filter.data, "ICMP_???");
556         tprints(")");
557 }
558
559 static bool
560 print_uint32(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
561 {
562         tprintf("%u", *(uint32_t *) elem_buf);
563
564         return true;
565 }
566
567 static void
568 print_getsockopt(struct tcb *const tcp, const unsigned int level,
569                  const unsigned int name, const kernel_ulong_t addr,
570                  const int ulen, const int rlen)
571 {
572         if (addr && verbose(tcp))
573         switch (level) {
574         case SOL_SOCKET:
575                 switch (name) {
576                 case SO_LINGER:
577                         print_get_linger(tcp, addr, rlen);
578                         return;
579 #ifdef SO_PEERCRED
580                 case SO_PEERCRED:
581                         print_ucred(tcp, addr, rlen);
582                         return;
583 #endif
584 #ifdef SO_ATTACH_FILTER
585                 case SO_ATTACH_FILTER:
586                         if (rlen && (unsigned short) rlen == (unsigned int) rlen)
587                                 print_sock_fprog(tcp, addr, rlen);
588                         else
589                                 printaddr(addr);
590                         return;
591 #endif /* SO_ATTACH_FILTER */
592                 }
593                 break;
594
595         case SOL_PACKET:
596                 switch (name) {
597 #ifdef PACKET_STATISTICS
598                 case PACKET_STATISTICS:
599                         print_tpacket_stats(tcp, addr, rlen);
600                         return;
601 #endif
602                 }
603                 break;
604
605         case SOL_RAW:
606                 switch (name) {
607                 case ICMP_FILTER:
608                         print_icmp_filter(tcp, addr, rlen);
609                         return;
610                 }
611                 break;
612
613         case SOL_NETLINK:
614                 if (ulen < 0 || rlen < 0) {
615                         /*
616                          * As the kernel neither accepts nor returns a negative
617                          * length, in case of successful getsockopt syscall
618                          * invocation these negative values must have come
619                          * from userspace.
620                          */
621                         printaddr(addr);
622                         return;
623                 }
624                 switch (name) {
625                 case NETLINK_LIST_MEMBERSHIPS: {
626                         uint32_t buf;
627                         print_array(tcp, addr, MIN(ulen, rlen) / sizeof(buf),
628                                     &buf, sizeof(buf),
629                                     umoven_or_printaddr, print_uint32, 0);
630                         break;
631                         }
632                 default:
633                         printnum_int(tcp, addr, "%d");
634                         break;
635                 }
636                 return;
637         }
638
639         /* default arg printing */
640
641         if (verbose(tcp)) {
642                 if (rlen == sizeof(int)) {
643                         printnum_int(tcp, addr, "%d");
644                 } else {
645                         printstrn(tcp, addr, rlen);
646                 }
647         } else {
648                 printaddr(addr);
649         }
650 }
651
652 SYS_FUNC(getsockopt)
653 {
654         int ulen, rlen;
655
656         if (entering(tcp)) {
657                 print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
658                                             tcp->u_arg[1], tcp->u_arg[2], true);
659
660                 if (verbose(tcp) && tcp->u_arg[4]
661                     && umove(tcp, tcp->u_arg[4], &ulen) == 0) {
662                         set_tcb_priv_ulong(tcp, ulen);
663                         return 0;
664                 } else {
665                         printaddr(tcp->u_arg[3]);
666                         tprints(", ");
667                         printaddr(tcp->u_arg[4]);
668                         return RVAL_DECODED;
669                 }
670         } else {
671                 ulen = get_tcb_priv_ulong(tcp);
672
673                 if (syserror(tcp) || umove(tcp, tcp->u_arg[4], &rlen) < 0) {
674                         printaddr(tcp->u_arg[3]);
675                         tprintf(", [%d]", ulen);
676                 } else {
677                         print_getsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
678                                          tcp->u_arg[3], ulen, rlen);
679                         if (ulen != rlen)
680                                 tprintf(", [%d->%d]", ulen, rlen);
681                         else
682                                 tprintf(", [%d]", rlen);
683                 }
684         }
685         return 0;
686 }
687
688 #ifdef IP_ADD_MEMBERSHIP
689 static void
690 print_mreq(struct tcb *const tcp, const kernel_ulong_t addr,
691            const int len)
692 {
693         struct ip_mreq mreq;
694
695         if (len < (int) sizeof(mreq)) {
696                 printaddr(addr);
697         } else if (!umove_or_printaddr(tcp, addr, &mreq)) {
698                 PRINT_FIELD_INET4_ADDR("{", mreq, imr_multiaddr);
699                 PRINT_FIELD_INET4_ADDR(", ", mreq, imr_interface);
700                 tprints("}");
701         }
702 }
703 #endif /* IP_ADD_MEMBERSHIP */
704
705 #ifdef IPV6_ADD_MEMBERSHIP
706 static void
707 print_mreq6(struct tcb *const tcp, const kernel_ulong_t addr,
708             const int len)
709 {
710         struct ipv6_mreq mreq;
711
712         if (len < (int) sizeof(mreq)) {
713                 printaddr(addr);
714         } else if (!umove_or_printaddr(tcp, addr, &mreq)) {
715                 PRINT_FIELD_INET_ADDR("{", mreq, ipv6mr_multiaddr, AF_INET6);
716                 PRINT_FIELD_IFINDEX(", ", mreq, ipv6mr_interface);
717                 tprints("}");
718         }
719 }
720 #endif /* IPV6_ADD_MEMBERSHIP */
721
722 #ifdef PACKET_RX_RING
723 static void
724 print_tpacket_req(struct tcb *const tcp, const kernel_ulong_t addr, const int len)
725 {
726         struct tpacket_req req;
727
728         if (len != sizeof(req) ||
729             umove(tcp, addr, &req) < 0) {
730                 printaddr(addr);
731         } else {
732                 PRINT_FIELD_U("{", req, tp_block_size);
733                 PRINT_FIELD_U(", ", req, tp_block_nr);
734                 PRINT_FIELD_U(", ", req, tp_frame_size);
735                 PRINT_FIELD_U(", ", req, tp_frame_nr);
736                 tprints("}");
737         }
738 }
739 #endif /* PACKET_RX_RING */
740
741 #ifdef PACKET_ADD_MEMBERSHIP
742 # include "xlat/packet_mreq_type.h"
743
744 static void
745 print_packet_mreq(struct tcb *const tcp, const kernel_ulong_t addr, const int len)
746 {
747         struct packet_mreq mreq;
748
749         if (len != sizeof(mreq) ||
750             umove(tcp, addr, &mreq) < 0) {
751                 printaddr(addr);
752         } else {
753                 unsigned int i;
754
755                 PRINT_FIELD_IFINDEX("{", mreq, mr_ifindex);
756                 PRINT_FIELD_XVAL(", ", mreq, mr_type, packet_mreq_type,
757                                  "PACKET_MR_???");
758                 PRINT_FIELD_U(", ", mreq, mr_alen);
759                 tprints(", mr_address=");
760                 if (mreq.mr_alen > ARRAY_SIZE(mreq.mr_address))
761                         mreq.mr_alen = ARRAY_SIZE(mreq.mr_address);
762                 for (i = 0; i < mreq.mr_alen; ++i)
763                         tprintf("%02x", mreq.mr_address[i]);
764                 tprints("}");
765         }
766 }
767 #endif /* PACKET_ADD_MEMBERSHIP */
768
769 static void
770 print_setsockopt(struct tcb *const tcp, const unsigned int level,
771                  const unsigned int name, const kernel_ulong_t addr,
772                  const int len)
773 {
774         if (addr && verbose(tcp))
775         switch (level) {
776         case SOL_SOCKET:
777                 switch (name) {
778                 case SO_LINGER:
779                         print_set_linger(tcp, addr, len);
780                         return;
781 #ifdef SO_ATTACH_FILTER
782                 case SO_ATTACH_FILTER:
783 # ifdef SO_ATTACH_REUSEPORT_CBPF
784                 case SO_ATTACH_REUSEPORT_CBPF:
785 # endif
786                         if ((unsigned int) len == get_sock_fprog_size())
787                                 decode_sock_fprog(tcp, addr);
788                         else
789                                 printaddr(addr);
790                         return;
791 #endif /* SO_ATTACH_FILTER */
792                 }
793                 break;
794
795         case SOL_IP:
796                 switch (name) {
797 #ifdef IP_ADD_MEMBERSHIP
798                 case IP_ADD_MEMBERSHIP:
799                 case IP_DROP_MEMBERSHIP:
800                         print_mreq(tcp, addr, len);
801                         return;
802 #endif /* IP_ADD_MEMBERSHIP */
803 #ifdef MCAST_JOIN_GROUP
804                 case MCAST_JOIN_GROUP:
805                 case MCAST_LEAVE_GROUP:
806                         print_group_req(tcp, addr, len);
807                         return;
808 #endif /* MCAST_JOIN_GROUP */
809                 }
810                 break;
811
812         case SOL_IPV6:
813                 switch (name) {
814 #ifdef IPV6_ADD_MEMBERSHIP
815                 case IPV6_ADD_MEMBERSHIP:
816                 case IPV6_DROP_MEMBERSHIP:
817 # ifdef IPV6_JOIN_ANYCAST
818                 case IPV6_JOIN_ANYCAST:
819 # endif
820 # ifdef IPV6_LEAVE_ANYCAST
821                 case IPV6_LEAVE_ANYCAST:
822 # endif
823                         print_mreq6(tcp, addr, len);
824                         return;
825 #endif /* IPV6_ADD_MEMBERSHIP */
826 #ifdef MCAST_JOIN_GROUP
827                 case MCAST_JOIN_GROUP:
828                 case MCAST_LEAVE_GROUP:
829                         print_group_req(tcp, addr, len);
830                         return;
831 #endif /* MCAST_JOIN_GROUP */
832                 }
833                 break;
834
835         case SOL_PACKET:
836                 switch (name) {
837 #ifdef PACKET_RX_RING
838                 case PACKET_RX_RING:
839 # ifdef PACKET_TX_RING
840                 case PACKET_TX_RING:
841 # endif
842                         print_tpacket_req(tcp, addr, len);
843                         return;
844 #endif /* PACKET_RX_RING */
845 #ifdef PACKET_ADD_MEMBERSHIP
846                 case PACKET_ADD_MEMBERSHIP:
847                 case PACKET_DROP_MEMBERSHIP:
848                         print_packet_mreq(tcp, addr, len);
849                         return;
850 #endif /* PACKET_ADD_MEMBERSHIP */
851                 }
852                 break;
853
854         case SOL_RAW:
855                 switch (name) {
856                 case ICMP_FILTER:
857                         print_icmp_filter(tcp, addr, len);
858                         return;
859                 }
860                 break;
861
862         case SOL_NETLINK:
863                 if (len < (int) sizeof(int))
864                         printaddr(addr);
865                 else
866                         printnum_int(tcp, addr, "%d");
867                 return;
868         }
869
870         /* default arg printing */
871
872         if (verbose(tcp)) {
873                 if (len == sizeof(int)) {
874                         printnum_int(tcp, addr, "%d");
875                 } else {
876                         printstrn(tcp, addr, len);
877                 }
878         } else {
879                 printaddr(addr);
880         }
881 }
882
883 SYS_FUNC(setsockopt)
884 {
885         print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
886                                     tcp->u_arg[1], tcp->u_arg[2], false);
887         print_setsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
888                          tcp->u_arg[3], tcp->u_arg[4]);
889         tprintf(", %d", (int) tcp->u_arg[4]);
890
891         return RVAL_DECODED;
892 }