]> granicus.if.org Git - strace/blob - net.c
tests: add variants of IPC tests with different xlat verbosity levels
[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-2018 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 #ifndef AF_BLUETOOTH
88 # define AF_BLUETOOTH 31
89 #endif
90 #include "xlat/bt_protocols.h"
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                 print_xlat_ex(flags & SOCK_TYPE_MASK, str, XLAT_STYLE_DEFAULT);
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         case AF_BLUETOOTH:
142                 printxval_index(bt_protocols, tcp->u_arg[2], "BTPROTO_???");
143                 break;
144
145         default:
146                 tprintf("%" PRI_klu, tcp->u_arg[2]);
147                 break;
148         }
149
150         return RVAL_DECODED | RVAL_FD;
151 }
152
153 static bool
154 fetch_socklen(struct tcb *const tcp, int *const plen,
155               const kernel_ulong_t sockaddr, const kernel_ulong_t socklen)
156 {
157         return verbose(tcp) && sockaddr && socklen
158                && umove(tcp, socklen, plen) == 0;
159 }
160
161 static int
162 decode_sockname(struct tcb *tcp)
163 {
164         int ulen, rlen;
165
166         if (entering(tcp)) {
167                 printfd(tcp, tcp->u_arg[0]);
168                 tprints(", ");
169                 if (fetch_socklen(tcp, &ulen, tcp->u_arg[1], tcp->u_arg[2])) {
170                         set_tcb_priv_ulong(tcp, ulen);
171                         return 0;
172                 } else {
173                         printaddr(tcp->u_arg[1]);
174                         tprints(", ");
175                         printaddr(tcp->u_arg[2]);
176                         return RVAL_DECODED;
177                 }
178         }
179
180         ulen = get_tcb_priv_ulong(tcp);
181
182         if (syserror(tcp) || umove(tcp, tcp->u_arg[2], &rlen) < 0) {
183                 printaddr(tcp->u_arg[1]);
184                 tprintf(", [%d]", ulen);
185         } else {
186                 decode_sockaddr(tcp, tcp->u_arg[1], ulen > rlen ? rlen : ulen);
187                 if (ulen != rlen)
188                         tprintf(", [%d->%d]", ulen, rlen);
189                 else
190                         tprintf(", [%d]", rlen);
191         }
192
193         return RVAL_DECODED;
194 }
195
196 SYS_FUNC(accept)
197 {
198         return decode_sockname(tcp) | RVAL_FD;
199 }
200
201 SYS_FUNC(accept4)
202 {
203         int rc = decode_sockname(tcp);
204
205         if (rc & RVAL_DECODED) {
206                 tprints(", ");
207                 printflags(sock_type_flags, tcp->u_arg[3], "SOCK_???");
208         }
209
210         return rc | RVAL_FD;
211 }
212
213 SYS_FUNC(send)
214 {
215         printfd(tcp, tcp->u_arg[0]);
216         tprints(", ");
217         decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]);
218         tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
219         /* flags */
220         printflags(msg_flags, tcp->u_arg[3], "MSG_???");
221
222         return RVAL_DECODED;
223 }
224
225 SYS_FUNC(sendto)
226 {
227         printfd(tcp, tcp->u_arg[0]);
228         tprints(", ");
229         decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]);
230         tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
231         /* flags */
232         printflags(msg_flags, tcp->u_arg[3], "MSG_???");
233         /* to address */
234         const int addrlen = tcp->u_arg[5];
235         tprints(", ");
236         decode_sockaddr(tcp, tcp->u_arg[4], addrlen);
237         /* to length */
238         tprintf(", %d", addrlen);
239
240         return RVAL_DECODED;
241 }
242
243 SYS_FUNC(recv)
244 {
245         if (entering(tcp)) {
246                 printfd(tcp, tcp->u_arg[0]);
247                 tprints(", ");
248         } else {
249                 if (syserror(tcp)) {
250                         printaddr(tcp->u_arg[1]);
251                 } else {
252                         decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1],
253                                      tcp->u_rval);
254                 }
255
256                 tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
257                 printflags(msg_flags, tcp->u_arg[3], "MSG_???");
258         }
259         return 0;
260 }
261
262 SYS_FUNC(recvfrom)
263 {
264         int ulen, rlen;
265
266         if (entering(tcp)) {
267                 printfd(tcp, tcp->u_arg[0]);
268                 tprints(", ");
269                 if (fetch_socklen(tcp, &ulen, tcp->u_arg[4], tcp->u_arg[5])) {
270                         set_tcb_priv_ulong(tcp, ulen);
271                 }
272         } else {
273                 /* buf */
274                 if (syserror(tcp)) {
275                         printaddr(tcp->u_arg[1]);
276                 } else {
277                         decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1],
278                                      tcp->u_rval);
279                 }
280                 /* size */
281                 tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
282                 /* flags */
283                 printflags(msg_flags, tcp->u_arg[3], "MSG_???");
284                 tprints(", ");
285
286                 ulen = get_tcb_priv_ulong(tcp);
287
288                 if (!fetch_socklen(tcp, &rlen, tcp->u_arg[4], tcp->u_arg[5])) {
289                         /* from address */
290                         printaddr(tcp->u_arg[4]);
291                         tprints(", ");
292                         /* from length */
293                         printaddr(tcp->u_arg[5]);
294                         return 0;
295                 }
296                 if (syserror(tcp)) {
297                         /* from address */
298                         printaddr(tcp->u_arg[4]);
299                         /* from length */
300                         tprintf(", [%d]", ulen);
301                         return 0;
302                 }
303                 /* from address */
304                 decode_sockaddr(tcp, tcp->u_arg[4], ulen > rlen ? rlen : ulen);
305                 /* from length */
306                 if (ulen != rlen)
307                         tprintf(", [%d->%d]", ulen, rlen);
308                 else
309                         tprintf(", [%d]", rlen);
310         }
311         return 0;
312 }
313
314 SYS_FUNC(getsockname)
315 {
316         return decode_sockname(tcp);
317 }
318
319 static void
320 printpair_fd(struct tcb *tcp, const int i0, const int i1)
321 {
322         tprints("[");
323         printfd(tcp, i0);
324         tprints(", ");
325         printfd(tcp, i1);
326         tprints("]");
327 }
328
329 static void
330 decode_pair_fd(struct tcb *const tcp, const kernel_ulong_t addr)
331 {
332         int pair[2];
333
334         if (umove_or_printaddr(tcp, addr, &pair))
335                 return;
336
337         printpair_fd(tcp, pair[0], pair[1]);
338 }
339
340 static int
341 do_pipe(struct tcb *tcp, int flags_arg)
342 {
343         if (exiting(tcp)) {
344                 decode_pair_fd(tcp, tcp->u_arg[0]);
345                 if (flags_arg >= 0) {
346                         tprints(", ");
347                         printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
348                 }
349         }
350         return 0;
351 }
352
353 SYS_FUNC(pipe)
354 {
355 #if HAVE_ARCH_GETRVAL2
356         if (exiting(tcp) && !syserror(tcp))
357                 printpair_fd(tcp, tcp->u_rval, getrval2(tcp));
358         return 0;
359 #else
360         return do_pipe(tcp, -1);
361 #endif
362 }
363
364 SYS_FUNC(pipe2)
365 {
366         return do_pipe(tcp, 1);
367 }
368
369 SYS_FUNC(socketpair)
370 {
371         if (entering(tcp)) {
372                 printxval(addrfams, tcp->u_arg[0], "AF_???");
373                 tprints(", ");
374                 tprint_sock_type(tcp->u_arg[1]);
375                 tprintf(", %" PRI_klu, tcp->u_arg[2]);
376         } else {
377                 tprints(", ");
378                 decode_pair_fd(tcp, tcp->u_arg[3]);
379         }
380         return 0;
381 }
382
383 #include "xlat/sockoptions.h"
384 #include "xlat/sockipoptions.h"
385 #include "xlat/getsockipoptions.h"
386 #include "xlat/setsockipoptions.h"
387 #include "xlat/sockipv6options.h"
388 #include "xlat/getsockipv6options.h"
389 #include "xlat/setsockipv6options.h"
390 #include "xlat/sockipxoptions.h"
391 #include "xlat/socknetlinkoptions.h"
392 #include "xlat/sockpacketoptions.h"
393 #include "xlat/sockrawoptions.h"
394 #include "xlat/socksctpoptions.h"
395 #include "xlat/socktcpoptions.h"
396
397 static void
398 print_sockopt_fd_level_name(struct tcb *tcp, int fd, unsigned int level,
399                             unsigned int name, bool is_getsockopt)
400 {
401         printfd(tcp, fd);
402         tprints(", ");
403         printxval_search(socketlayers, level, "SOL_??");
404         tprints(", ");
405
406         switch (level) {
407         case SOL_SOCKET:
408                 printxval(sockoptions, name, "SO_???");
409                 break;
410         case SOL_IP:
411                 printxvals(name, "IP_???", sockipoptions,
412                         is_getsockopt ? getsockipoptions : setsockipoptions, NULL);
413                 break;
414         case SOL_IPV6:
415                 printxvals(name, "IPV6_???", sockipv6options,
416                         is_getsockopt ? getsockipv6options : setsockipv6options, NULL);
417                 break;
418         case SOL_IPX:
419                 printxval(sockipxoptions, name, "IPX_???");
420                 break;
421         case SOL_PACKET:
422                 printxval(sockpacketoptions, name, "PACKET_???");
423                 break;
424         case SOL_TCP:
425                 printxval(socktcpoptions, name, "TCP_???");
426                 break;
427         case SOL_SCTP:
428                 printxval(socksctpoptions, name, "SCTP_???");
429                 break;
430         case SOL_RAW:
431                 printxval(sockrawoptions, name, "RAW_???");
432                 break;
433         case SOL_NETLINK:
434                 printxval(socknetlinkoptions, name, "NETLINK_???");
435                 break;
436
437                 /* Other SOL_* protocol levels still need work. */
438
439         default:
440                 tprintf("%u", name);
441         }
442
443         tprints(", ");
444 }
445
446 static void
447 print_set_linger(struct tcb *const tcp, const kernel_ulong_t addr,
448                  const int len)
449 {
450         struct linger linger;
451
452         if (len < (int) sizeof(linger)) {
453                 printaddr(addr);
454         } else if (!umove_or_printaddr(tcp, addr, &linger)) {
455                 PRINT_FIELD_D("{", linger, l_onoff);
456                 PRINT_FIELD_D(", ", linger, l_linger);
457                 tprints("}");
458         }
459 }
460
461 static void
462 print_get_linger(struct tcb *const tcp, const kernel_ulong_t addr,
463                  unsigned int len)
464 {
465         struct linger linger;
466
467         if (len < sizeof(linger)) {
468                 if (len != sizeof(linger.l_onoff)) {
469                         printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
470                         return;
471                 }
472         } else {
473                 len = sizeof(linger);
474         }
475
476         if (umoven(tcp, addr, len, &linger) < 0) {
477                 printaddr(addr);
478                 return;
479         }
480
481         PRINT_FIELD_D("{", linger, l_onoff);
482         if (len == sizeof(linger))
483                 PRINT_FIELD_D(", ", linger, l_linger);
484         tprints("}");
485 }
486
487 #ifdef SO_PEERCRED
488 static void
489 print_ucred(struct tcb *const tcp, const kernel_ulong_t addr, unsigned int len)
490 {
491         struct ucred uc;
492
493         if (len < sizeof(uc)) {
494                 if (len != sizeof(uc.pid)
495                     && len != offsetofend(struct ucred, uid)) {
496                         printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
497                         return;
498                 }
499         } else {
500                 len = sizeof(uc);
501         }
502
503         if (umoven(tcp, addr, len, &uc) < 0) {
504                 printaddr(addr);
505                 return;
506         }
507
508         PRINT_FIELD_D("{", uc, pid);
509         if (len > sizeof(uc.pid))
510                 PRINT_FIELD_UID(", ", uc, uid);
511         if (len == sizeof(uc))
512                 PRINT_FIELD_UID(", ", uc, gid);
513         tprints("}");
514 }
515 #endif /* SO_PEERCRED */
516
517 #ifdef PACKET_STATISTICS
518 static void
519 print_tpacket_stats(struct tcb *const tcp, const kernel_ulong_t addr,
520                     const int len)
521 {
522         struct tpacket_stats stats;
523
524         if (len != sizeof(stats) ||
525             umove(tcp, addr, &stats) < 0) {
526                 printaddr(addr);
527         } else {
528                 PRINT_FIELD_U("{", stats, tp_packets);
529                 PRINT_FIELD_U("{", stats, tp_drops);
530                 tprints("}");
531         }
532 }
533 #endif /* PACKET_STATISTICS */
534
535 #include "xlat/icmpfilterflags.h"
536
537 static void
538 print_icmp_filter(struct tcb *const tcp, const kernel_ulong_t addr, int len)
539 {
540         struct icmp_filter filter = {};
541
542         if (len > (int) sizeof(filter))
543                 len = sizeof(filter);
544         else if (len <= 0) {
545                 printaddr(addr);
546                 return;
547         }
548
549         if (umoven_or_printaddr(tcp, addr, len, &filter))
550                 return;
551
552         tprints("~(");
553         printflags(icmpfilterflags, ~filter.data, "ICMP_???");
554         tprints(")");
555 }
556
557 static bool
558 print_uint32(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
559 {
560         tprintf("%u", *(uint32_t *) elem_buf);
561
562         return true;
563 }
564
565 static void
566 print_getsockopt(struct tcb *const tcp, const unsigned int level,
567                  const unsigned int name, const kernel_ulong_t addr,
568                  const int ulen, const int rlen)
569 {
570         if (addr && verbose(tcp))
571         switch (level) {
572         case SOL_SOCKET:
573                 switch (name) {
574                 case SO_LINGER:
575                         print_get_linger(tcp, addr, rlen);
576                         return;
577 #ifdef SO_PEERCRED
578                 case SO_PEERCRED:
579                         print_ucred(tcp, addr, rlen);
580                         return;
581 #endif
582 #ifdef SO_ATTACH_FILTER
583                 case SO_ATTACH_FILTER:
584                         if (rlen && (unsigned short) rlen == (unsigned int) rlen)
585                                 print_sock_fprog(tcp, addr, rlen);
586                         else
587                                 printaddr(addr);
588                         return;
589 #endif /* SO_ATTACH_FILTER */
590                 }
591                 break;
592
593         case SOL_PACKET:
594                 switch (name) {
595 #ifdef PACKET_STATISTICS
596                 case PACKET_STATISTICS:
597                         print_tpacket_stats(tcp, addr, rlen);
598                         return;
599 #endif
600                 }
601                 break;
602
603         case SOL_RAW:
604                 switch (name) {
605                 case ICMP_FILTER:
606                         print_icmp_filter(tcp, addr, rlen);
607                         return;
608                 }
609                 break;
610
611         case SOL_NETLINK:
612                 if (ulen < 0 || rlen < 0) {
613                         /*
614                          * As the kernel neither accepts nor returns a negative
615                          * length, in case of successful getsockopt syscall
616                          * invocation these negative values must have come
617                          * from userspace.
618                          */
619                         printaddr(addr);
620                         return;
621                 }
622                 switch (name) {
623                 case NETLINK_LIST_MEMBERSHIPS: {
624                         uint32_t buf;
625                         print_array(tcp, addr, MIN(ulen, rlen) / sizeof(buf),
626                                     &buf, sizeof(buf),
627                                     umoven_or_printaddr, print_uint32, 0);
628                         break;
629                         }
630                 default:
631                         printnum_int(tcp, addr, "%d");
632                         break;
633                 }
634                 return;
635         }
636
637         /* default arg printing */
638
639         if (verbose(tcp)) {
640                 if (rlen == sizeof(int)) {
641                         printnum_int(tcp, addr, "%d");
642                 } else {
643                         printstrn(tcp, addr, rlen);
644                 }
645         } else {
646                 printaddr(addr);
647         }
648 }
649
650 SYS_FUNC(getsockopt)
651 {
652         int ulen, rlen;
653
654         if (entering(tcp)) {
655                 print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
656                                             tcp->u_arg[1], tcp->u_arg[2], true);
657
658                 if (verbose(tcp) && tcp->u_arg[4]
659                     && umove(tcp, tcp->u_arg[4], &ulen) == 0) {
660                         set_tcb_priv_ulong(tcp, ulen);
661                         return 0;
662                 } else {
663                         printaddr(tcp->u_arg[3]);
664                         tprints(", ");
665                         printaddr(tcp->u_arg[4]);
666                         return RVAL_DECODED;
667                 }
668         } else {
669                 ulen = get_tcb_priv_ulong(tcp);
670
671                 if (syserror(tcp) || umove(tcp, tcp->u_arg[4], &rlen) < 0) {
672                         printaddr(tcp->u_arg[3]);
673                         tprintf(", [%d]", ulen);
674                 } else {
675                         print_getsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
676                                          tcp->u_arg[3], ulen, rlen);
677                         if (ulen != rlen)
678                                 tprintf(", [%d->%d]", ulen, rlen);
679                         else
680                                 tprintf(", [%d]", rlen);
681                 }
682         }
683         return 0;
684 }
685
686 #ifdef IP_ADD_MEMBERSHIP
687 static void
688 print_mreq(struct tcb *const tcp, const kernel_ulong_t addr,
689            const int len)
690 {
691         struct ip_mreq mreq;
692
693         if (len < (int) sizeof(mreq)) {
694                 printaddr(addr);
695         } else if (!umove_or_printaddr(tcp, addr, &mreq)) {
696                 PRINT_FIELD_INET4_ADDR("{", mreq, imr_multiaddr);
697                 PRINT_FIELD_INET4_ADDR(", ", mreq, imr_interface);
698                 tprints("}");
699         }
700 }
701 #endif /* IP_ADD_MEMBERSHIP */
702
703 #ifdef IPV6_ADD_MEMBERSHIP
704 static void
705 print_mreq6(struct tcb *const tcp, const kernel_ulong_t addr,
706             const int len)
707 {
708         struct ipv6_mreq mreq;
709
710         if (len < (int) sizeof(mreq)) {
711                 printaddr(addr);
712         } else if (!umove_or_printaddr(tcp, addr, &mreq)) {
713                 PRINT_FIELD_INET_ADDR("{", mreq, ipv6mr_multiaddr, AF_INET6);
714                 PRINT_FIELD_IFINDEX(", ", mreq, ipv6mr_interface);
715                 tprints("}");
716         }
717 }
718 #endif /* IPV6_ADD_MEMBERSHIP */
719
720 #ifdef PACKET_RX_RING
721 static void
722 print_tpacket_req(struct tcb *const tcp, const kernel_ulong_t addr, const int len)
723 {
724         struct tpacket_req req;
725
726         if (len != sizeof(req) ||
727             umove(tcp, addr, &req) < 0) {
728                 printaddr(addr);
729         } else {
730                 PRINT_FIELD_U("{", req, tp_block_size);
731                 PRINT_FIELD_U(", ", req, tp_block_nr);
732                 PRINT_FIELD_U(", ", req, tp_frame_size);
733                 PRINT_FIELD_U(", ", req, tp_frame_nr);
734                 tprints("}");
735         }
736 }
737 #endif /* PACKET_RX_RING */
738
739 #ifdef PACKET_ADD_MEMBERSHIP
740 # include "xlat/packet_mreq_type.h"
741
742 static void
743 print_packet_mreq(struct tcb *const tcp, const kernel_ulong_t addr, const int len)
744 {
745         struct packet_mreq mreq;
746
747         if (len != sizeof(mreq) ||
748             umove(tcp, addr, &mreq) < 0) {
749                 printaddr(addr);
750         } else {
751                 unsigned int i;
752
753                 PRINT_FIELD_IFINDEX("{", mreq, mr_ifindex);
754                 PRINT_FIELD_XVAL(", ", mreq, mr_type, packet_mreq_type,
755                                  "PACKET_MR_???");
756                 PRINT_FIELD_U(", ", mreq, mr_alen);
757                 tprints(", mr_address=");
758                 if (mreq.mr_alen > ARRAY_SIZE(mreq.mr_address))
759                         mreq.mr_alen = ARRAY_SIZE(mreq.mr_address);
760                 for (i = 0; i < mreq.mr_alen; ++i)
761                         tprintf("%02x", mreq.mr_address[i]);
762                 tprints("}");
763         }
764 }
765 #endif /* PACKET_ADD_MEMBERSHIP */
766
767 static void
768 print_setsockopt(struct tcb *const tcp, const unsigned int level,
769                  const unsigned int name, const kernel_ulong_t addr,
770                  const int len)
771 {
772         if (addr && verbose(tcp))
773         switch (level) {
774         case SOL_SOCKET:
775                 switch (name) {
776                 case SO_LINGER:
777                         print_set_linger(tcp, addr, len);
778                         return;
779 #ifdef SO_ATTACH_FILTER
780                 case SO_ATTACH_FILTER:
781 # ifdef SO_ATTACH_REUSEPORT_CBPF
782                 case SO_ATTACH_REUSEPORT_CBPF:
783 # endif
784                         if ((unsigned int) len == get_sock_fprog_size())
785                                 decode_sock_fprog(tcp, addr);
786                         else
787                                 printaddr(addr);
788                         return;
789 #endif /* SO_ATTACH_FILTER */
790                 }
791                 break;
792
793         case SOL_IP:
794                 switch (name) {
795 #ifdef IP_ADD_MEMBERSHIP
796                 case IP_ADD_MEMBERSHIP:
797                 case IP_DROP_MEMBERSHIP:
798                         print_mreq(tcp, addr, len);
799                         return;
800 #endif /* IP_ADD_MEMBERSHIP */
801 #ifdef MCAST_JOIN_GROUP
802                 case MCAST_JOIN_GROUP:
803                 case MCAST_LEAVE_GROUP:
804                         print_group_req(tcp, addr, len);
805                         return;
806 #endif /* MCAST_JOIN_GROUP */
807                 }
808                 break;
809
810         case SOL_IPV6:
811                 switch (name) {
812 #ifdef IPV6_ADD_MEMBERSHIP
813                 case IPV6_ADD_MEMBERSHIP:
814                 case IPV6_DROP_MEMBERSHIP:
815 # ifdef IPV6_JOIN_ANYCAST
816                 case IPV6_JOIN_ANYCAST:
817 # endif
818 # ifdef IPV6_LEAVE_ANYCAST
819                 case IPV6_LEAVE_ANYCAST:
820 # endif
821                         print_mreq6(tcp, addr, len);
822                         return;
823 #endif /* IPV6_ADD_MEMBERSHIP */
824 #ifdef MCAST_JOIN_GROUP
825                 case MCAST_JOIN_GROUP:
826                 case MCAST_LEAVE_GROUP:
827                         print_group_req(tcp, addr, len);
828                         return;
829 #endif /* MCAST_JOIN_GROUP */
830                 }
831                 break;
832
833         case SOL_PACKET:
834                 switch (name) {
835 #ifdef PACKET_RX_RING
836                 case PACKET_RX_RING:
837 # ifdef PACKET_TX_RING
838                 case PACKET_TX_RING:
839 # endif
840                         print_tpacket_req(tcp, addr, len);
841                         return;
842 #endif /* PACKET_RX_RING */
843 #ifdef PACKET_ADD_MEMBERSHIP
844                 case PACKET_ADD_MEMBERSHIP:
845                 case PACKET_DROP_MEMBERSHIP:
846                         print_packet_mreq(tcp, addr, len);
847                         return;
848 #endif /* PACKET_ADD_MEMBERSHIP */
849                 }
850                 break;
851
852         case SOL_RAW:
853                 switch (name) {
854                 case ICMP_FILTER:
855                         print_icmp_filter(tcp, addr, len);
856                         return;
857                 }
858                 break;
859
860         case SOL_NETLINK:
861                 if (len < (int) sizeof(int))
862                         printaddr(addr);
863                 else
864                         printnum_int(tcp, addr, "%d");
865                 return;
866         }
867
868         /* default arg printing */
869
870         if (verbose(tcp)) {
871                 if (len == sizeof(int)) {
872                         printnum_int(tcp, addr, "%d");
873                 } else {
874                         printstrn(tcp, addr, len);
875                 }
876         } else {
877                 printaddr(addr);
878         }
879 }
880
881 SYS_FUNC(setsockopt)
882 {
883         print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
884                                     tcp->u_arg[1], tcp->u_arg[2], false);
885         print_setsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
886                          tcp->u_arg[3], tcp->u_arg[4]);
887         tprintf(", %d", (int) tcp->u_arg[4]);
888
889         return RVAL_DECODED;
890 }