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