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