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