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