]> granicus.if.org Git - strace/blob - net.c
tests: check decoding of SO_PEERCRED socket option
[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, unsigned int len)
537 {
538         struct ucred uc;
539
540         if (len < sizeof(uc)) {
541                 if (len != sizeof(uc.pid)
542                     && len != offsetofend(struct ucred, uid)) {
543                         printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
544                         return;
545                 }
546         } else {
547                 len = sizeof(uc);
548         }
549
550         if (umoven(tcp, addr, len, &uc) < 0) {
551                 printaddr(addr);
552                 return;
553         }
554
555         PRINT_FIELD_D("{", uc, pid);
556         if (len > sizeof(uc.pid))
557                 PRINT_FIELD_UID(", ", uc, uid);
558         if (len == sizeof(uc))
559                 PRINT_FIELD_UID(", ", uc, gid);
560         tprints("}");
561 }
562 #endif /* SO_PEERCRED */
563
564 #ifdef PACKET_STATISTICS
565 static void
566 print_tpacket_stats(struct tcb *const tcp, const kernel_ulong_t addr,
567                     const int len)
568 {
569         struct tpacket_stats stats;
570
571         if (len != sizeof(stats) ||
572             umove(tcp, addr, &stats) < 0) {
573                 printaddr(addr);
574         } else {
575                 tprintf("{packets=%u, drops=%u}",
576                         stats.tp_packets,
577                         stats.tp_drops);
578         }
579 }
580 #endif /* PACKET_STATISTICS */
581
582 #include "xlat/icmpfilterflags.h"
583
584 static void
585 print_icmp_filter(struct tcb *const tcp, const kernel_ulong_t addr, int len)
586 {
587         struct icmp_filter filter = {};
588
589         if (len > (int) sizeof(filter))
590                 len = sizeof(filter);
591         else if (len <= 0) {
592                 printaddr(addr);
593                 return;
594         }
595
596         if (umoven_or_printaddr(tcp, addr, len, &filter))
597                 return;
598
599         tprints("~(");
600         printflags(icmpfilterflags, ~filter.data, "ICMP_???");
601         tprints(")");
602 }
603
604 static void
605 print_getsockopt(struct tcb *const tcp, const unsigned int level,
606                  const unsigned int name, const kernel_ulong_t addr,
607                  const int len)
608 {
609         if (addr && verbose(tcp))
610         switch (level) {
611         case SOL_SOCKET:
612                 switch (name) {
613                 case SO_LINGER:
614                         print_get_linger(tcp, addr, len);
615                         return;
616 #ifdef SO_PEERCRED
617                 case SO_PEERCRED:
618                         print_ucred(tcp, addr, len);
619                         return;
620 #endif
621 #ifdef SO_ATTACH_FILTER
622                 case SO_ATTACH_FILTER:
623                         if (len && (unsigned short) len == (unsigned int) len)
624                                 print_sock_fprog(tcp, addr, len);
625                         else
626                                 printaddr(addr);
627                         return;
628 #endif /* SO_ATTACH_FILTER */
629                 }
630                 break;
631
632         case SOL_PACKET:
633                 switch (name) {
634 #ifdef PACKET_STATISTICS
635                 case PACKET_STATISTICS:
636                         print_tpacket_stats(tcp, addr, len);
637                         return;
638 #endif
639                 }
640                 break;
641
642         case SOL_RAW:
643                 switch (name) {
644                 case ICMP_FILTER:
645                         print_icmp_filter(tcp, addr, len);
646                         return;
647                 }
648                 break;
649         }
650
651         /* default arg printing */
652
653         if (verbose(tcp)) {
654                 if (len == sizeof(int)) {
655                         printnum_int(tcp, addr, "%d");
656                 } else {
657                         printstrn(tcp, addr, len);
658                 }
659         } else {
660                 printaddr(addr);
661         }
662 }
663
664 SYS_FUNC(getsockopt)
665 {
666         int ulen, rlen;
667
668         if (entering(tcp)) {
669                 print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
670                                             tcp->u_arg[1], tcp->u_arg[2], true);
671
672                 if (verbose(tcp) && tcp->u_arg[4]
673                     && umove(tcp, tcp->u_arg[4], &ulen) == 0) {
674                         set_tcb_priv_ulong(tcp, ulen);
675                         return 0;
676                 } else {
677                         printaddr(tcp->u_arg[3]);
678                         tprints(", ");
679                         printaddr(tcp->u_arg[4]);
680                         return RVAL_DECODED;
681                 }
682         } else {
683                 ulen = get_tcb_priv_ulong(tcp);
684
685                 if (syserror(tcp) || umove(tcp, tcp->u_arg[4], &rlen) < 0) {
686                         printaddr(tcp->u_arg[3]);
687                         tprintf(", [%d]", ulen);
688                 } else {
689                         print_getsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
690                                          tcp->u_arg[3], rlen);
691                         if (ulen != rlen)
692                                 tprintf(", [%d->%d]", ulen, rlen);
693                         else
694                                 tprintf(", [%d]", rlen);
695                 }
696         }
697         return 0;
698 }
699
700 #ifdef IP_ADD_MEMBERSHIP
701 static void
702 print_mreq(struct tcb *const tcp, const kernel_ulong_t addr,
703            const unsigned int len)
704 {
705         struct ip_mreq mreq;
706
707         if (len < sizeof(mreq)) {
708                 printstrn(tcp, addr, len);
709                 return;
710         }
711         if (umove_or_printaddr(tcp, addr, &mreq))
712                 return;
713
714         tprintf("{imr_multiaddr=inet_addr(\"%s\")",
715                 inet_ntoa(mreq.imr_multiaddr));
716         tprintf(", imr_interface=inet_addr(\"%s\")}",
717                 inet_ntoa(mreq.imr_interface));
718 }
719 #endif /* IP_ADD_MEMBERSHIP */
720
721 #ifdef IPV6_ADD_MEMBERSHIP
722 static void
723 print_mreq6(struct tcb *const tcp, const kernel_ulong_t addr,
724             const unsigned int len)
725 {
726         struct ipv6_mreq mreq;
727
728         if (len < sizeof(mreq)) {
729                 printstrn(tcp, addr, len);
730                 return;
731         }
732         if (umove_or_printaddr(tcp, addr, &mreq))
733                 return;
734
735         tprints("{");
736         print_inet_addr(AF_INET6, &mreq.ipv6mr_multiaddr,
737                         sizeof(mreq.ipv6mr_multiaddr), "ipv6mr_multiaddr");
738
739         tprints(", ipv6mr_interface=");
740         print_ifindex(mreq.ipv6mr_interface);
741         tprints("}");
742 }
743 #endif /* IPV6_ADD_MEMBERSHIP */
744
745 #ifdef MCAST_JOIN_GROUP
746 static void
747 print_group_req(struct tcb *const tcp, const kernel_ulong_t addr, const int len)
748 {
749         struct group_req greq;
750
751         if (len != sizeof(greq) ||
752             umove(tcp, addr, &greq) < 0) {
753                 printaddr(addr);
754                 return;
755         }
756
757         tprintf("{gr_interface=%u, gr_group=", greq.gr_interface);
758         print_sockaddr(tcp, &greq.gr_group, sizeof(greq.gr_group));
759         tprints("}");
760
761 }
762 #endif /* MCAST_JOIN_GROUP */
763
764 #ifdef PACKET_RX_RING
765 static void
766 print_tpacket_req(struct tcb *const tcp, const kernel_ulong_t addr, const int len)
767 {
768         struct tpacket_req req;
769
770         if (len != sizeof(req) ||
771             umove(tcp, addr, &req) < 0) {
772                 printaddr(addr);
773         } else {
774                 tprintf("{block_size=%u, block_nr=%u, "
775                         "frame_size=%u, frame_nr=%u}",
776                         req.tp_block_size,
777                         req.tp_block_nr,
778                         req.tp_frame_size,
779                         req.tp_frame_nr);
780         }
781 }
782 #endif /* PACKET_RX_RING */
783
784 #ifdef PACKET_ADD_MEMBERSHIP
785 # include "xlat/packet_mreq_type.h"
786
787 static void
788 print_packet_mreq(struct tcb *const tcp, const kernel_ulong_t addr, const int len)
789 {
790         struct packet_mreq mreq;
791
792         if (len != sizeof(mreq) ||
793             umove(tcp, addr, &mreq) < 0) {
794                 printaddr(addr);
795         } else {
796                 unsigned int i;
797
798                 tprintf("{mr_ifindex=%u, mr_type=", mreq.mr_ifindex);
799                 printxval(packet_mreq_type, mreq.mr_type, "PACKET_MR_???");
800                 tprintf(", mr_alen=%u, mr_address=", mreq.mr_alen);
801                 if (mreq.mr_alen > ARRAY_SIZE(mreq.mr_address))
802                         mreq.mr_alen = ARRAY_SIZE(mreq.mr_address);
803                 for (i = 0; i < mreq.mr_alen; ++i)
804                         tprintf("%02x", mreq.mr_address[i]);
805                 tprints("}");
806         }
807 }
808 #endif /* PACKET_ADD_MEMBERSHIP */
809
810 static void
811 print_setsockopt(struct tcb *const tcp, const unsigned int level,
812                  const unsigned int name, const kernel_ulong_t addr,
813                  const int len)
814 {
815         if (addr && verbose(tcp))
816         switch (level) {
817         case SOL_SOCKET:
818                 switch (name) {
819                 case SO_LINGER:
820                         print_set_linger(tcp, addr, len);
821                         return;
822 #ifdef SO_ATTACH_FILTER
823                 case SO_ATTACH_FILTER:
824 # ifdef SO_ATTACH_REUSEPORT_CBPF
825                 case SO_ATTACH_REUSEPORT_CBPF:
826 # endif
827                         if ((unsigned int) len == get_sock_fprog_size())
828                                 decode_sock_fprog(tcp, addr);
829                         else
830                                 printaddr(addr);
831                         return;
832 #endif /* SO_ATTACH_FILTER */
833                 }
834                 break;
835
836         case SOL_IP:
837                 switch (name) {
838 #ifdef IP_ADD_MEMBERSHIP
839                 case IP_ADD_MEMBERSHIP:
840                 case IP_DROP_MEMBERSHIP:
841                         print_mreq(tcp, addr, len);
842                         return;
843 #endif /* IP_ADD_MEMBERSHIP */
844 #ifdef MCAST_JOIN_GROUP
845                 case MCAST_JOIN_GROUP:
846                 case MCAST_LEAVE_GROUP:
847                         print_group_req(tcp, addr, len);
848                         return;
849 #endif /* MCAST_JOIN_GROUP */
850                 }
851                 break;
852
853         case SOL_IPV6:
854                 switch (name) {
855 #ifdef IPV6_ADD_MEMBERSHIP
856                 case IPV6_ADD_MEMBERSHIP:
857                 case IPV6_DROP_MEMBERSHIP:
858 # ifdef IPV6_JOIN_ANYCAST
859                 case IPV6_JOIN_ANYCAST:
860 # endif
861 # ifdef IPV6_LEAVE_ANYCAST
862                 case IPV6_LEAVE_ANYCAST:
863 # endif
864                         print_mreq6(tcp, addr, len);
865                         return;
866 #endif /* IPV6_ADD_MEMBERSHIP */
867                 }
868                 break;
869
870         case SOL_PACKET:
871                 switch (name) {
872 #ifdef PACKET_RX_RING
873                 case PACKET_RX_RING:
874 # ifdef PACKET_TX_RING
875                 case PACKET_TX_RING:
876 # endif
877                         print_tpacket_req(tcp, addr, len);
878                         return;
879 #endif /* PACKET_RX_RING */
880 #ifdef PACKET_ADD_MEMBERSHIP
881                 case PACKET_ADD_MEMBERSHIP:
882                 case PACKET_DROP_MEMBERSHIP:
883                         print_packet_mreq(tcp, addr, len);
884                         return;
885 #endif /* PACKET_ADD_MEMBERSHIP */
886                 }
887                 break;
888
889         case SOL_RAW:
890                 switch (name) {
891                 case ICMP_FILTER:
892                         print_icmp_filter(tcp, addr, len);
893                         return;
894                 }
895                 break;
896         }
897
898         /* default arg printing */
899
900         if (verbose(tcp)) {
901                 if (len == sizeof(int)) {
902                         printnum_int(tcp, addr, "%d");
903                 } else {
904                         printstrn(tcp, addr, len);
905                 }
906         } else {
907                 printaddr(addr);
908         }
909 }
910
911 SYS_FUNC(setsockopt)
912 {
913         print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
914                                     tcp->u_arg[1], tcp->u_arg[2], false);
915         print_setsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
916                          tcp->u_arg[3], tcp->u_arg[4]);
917         tprintf(", %d", (int) tcp->u_arg[4]);
918
919         return RVAL_DECODED;
920 }