]> granicus.if.org Git - strace/blob - net.c
net: print SO_GET_FILTER in getsockopt
[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-2018 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 #define XLAT_MACROS_ONLY
88 # include "xlat/addrfams.h"
89 #undef XLAT_MACROS_ONLY
90 #include "xlat/irda_protocols.h"
91 #include "xlat/can_protocols.h"
92 #include "xlat/bt_protocols.h"
93 #include "xlat/isdn_protocols.h"
94 #include "xlat/phonet_protocols.h"
95 #include "xlat/caif_protocols.h"
96 #include "xlat/nfc_protocols.h"
97 #include "xlat/kcm_protocols.h"
98 #include "xlat/smc_protocols.h"
99
100 static void
101 decode_sockbuf(struct tcb *const tcp, const int fd, const kernel_ulong_t addr,
102                const kernel_ulong_t addrlen)
103 {
104
105         switch (verbose(tcp) ? getfdproto(tcp, fd) : SOCK_PROTO_UNKNOWN) {
106         case SOCK_PROTO_NETLINK:
107                 decode_netlink(tcp, fd, addr, addrlen);
108                 break;
109         default:
110                 printstrn(tcp, addr, addrlen);
111         }
112 }
113
114 /*
115  * low bits of the socket type define real socket type,
116  * other bits are socket type flags.
117  */
118 static void
119 tprint_sock_type(unsigned int flags)
120 {
121         const char *str = xlookup(socktypes, flags & SOCK_TYPE_MASK);
122
123         if (str) {
124                 print_xlat_ex(flags & SOCK_TYPE_MASK, str, XLAT_STYLE_DEFAULT);
125                 flags &= ~SOCK_TYPE_MASK;
126                 if (!flags)
127                         return;
128                 tprints("|");
129         }
130         printflags(sock_type_flags, flags, "SOCK_???");
131 }
132
133 SYS_FUNC(socket)
134 {
135         printxval(addrfams, tcp->u_arg[0], "AF_???");
136         tprints(", ");
137         tprint_sock_type(tcp->u_arg[1]);
138         tprints(", ");
139         switch (tcp->u_arg[0]) {
140         case AF_INET:
141         case AF_INET6:
142                 printxval(inet_protocols, tcp->u_arg[2], "IPPROTO_???");
143                 break;
144
145         case AF_NETLINK:
146                 printxval(netlink_protocols, tcp->u_arg[2], "NETLINK_???");
147                 break;
148
149         case AF_IRDA:
150                 printxval_index(can_protocols, tcp->u_arg[2], "IRDAPROTO_???");
151                 break;
152
153         case AF_CAN:
154                 printxval_index(can_protocols, tcp->u_arg[2], "CAN_???");
155                 break;
156
157         case AF_BLUETOOTH:
158                 printxval_index(bt_protocols, tcp->u_arg[2], "BTPROTO_???");
159                 break;
160
161         case AF_RXRPC:
162                 printxval(addrfams, tcp->u_arg[2], "AF_???");
163                 break;
164
165         case AF_ISDN:
166                 printxval(isdn_protocols, tcp->u_arg[2], "ISDN_P_???");
167                 break;
168
169         case AF_PHONET:
170                 printxval_index(phonet_protocols, tcp->u_arg[2], "PN_PROTO_???");
171                 break;
172
173         case AF_CAIF:
174                 printxval_index(caif_protocols, tcp->u_arg[2], "CAIFPROTO_???");
175                 break;
176
177         case AF_NFC:
178                 printxval_index(nfc_protocols, tcp->u_arg[2],
179                                 "NFC_SOCKPROTO_???");
180                 break;
181
182         case AF_KCM:
183                 printxval_index(kcm_protocols, tcp->u_arg[2], "KCMPROTO_???");
184                 break;
185
186         case AF_SMC:
187                 printxval_index(smc_protocols, tcp->u_arg[2], "SMCPROTO_???");
188                 break;
189
190         default:
191                 tprintf("%" PRI_klu, tcp->u_arg[2]);
192                 break;
193         }
194
195         return RVAL_DECODED | RVAL_FD;
196 }
197
198 static bool
199 fetch_socklen(struct tcb *const tcp, int *const plen,
200               const kernel_ulong_t sockaddr, const kernel_ulong_t socklen)
201 {
202         return verbose(tcp) && sockaddr && socklen
203                && umove(tcp, socklen, plen) == 0;
204 }
205
206 static int
207 decode_sockname(struct tcb *tcp)
208 {
209         int ulen, rlen;
210
211         if (entering(tcp)) {
212                 printfd(tcp, tcp->u_arg[0]);
213                 tprints(", ");
214                 if (fetch_socklen(tcp, &ulen, tcp->u_arg[1], tcp->u_arg[2])) {
215                         set_tcb_priv_ulong(tcp, ulen);
216                         return 0;
217                 } else {
218                         printaddr(tcp->u_arg[1]);
219                         tprints(", ");
220                         printaddr(tcp->u_arg[2]);
221                         return RVAL_DECODED;
222                 }
223         }
224
225         ulen = get_tcb_priv_ulong(tcp);
226
227         if (syserror(tcp) || umove(tcp, tcp->u_arg[2], &rlen) < 0) {
228                 printaddr(tcp->u_arg[1]);
229                 tprintf(", [%d]", ulen);
230         } else {
231                 decode_sockaddr(tcp, tcp->u_arg[1], ulen > rlen ? rlen : ulen);
232                 if (ulen != rlen)
233                         tprintf(", [%d->%d]", ulen, rlen);
234                 else
235                         tprintf(", [%d]", rlen);
236         }
237
238         return RVAL_DECODED;
239 }
240
241 SYS_FUNC(accept)
242 {
243         return decode_sockname(tcp) | RVAL_FD;
244 }
245
246 SYS_FUNC(accept4)
247 {
248         int rc = decode_sockname(tcp);
249
250         if (rc & RVAL_DECODED) {
251                 tprints(", ");
252                 printflags(sock_type_flags, tcp->u_arg[3], "SOCK_???");
253         }
254
255         return rc | RVAL_FD;
256 }
257
258 SYS_FUNC(send)
259 {
260         printfd(tcp, tcp->u_arg[0]);
261         tprints(", ");
262         decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]);
263         tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
264         /* flags */
265         printflags(msg_flags, tcp->u_arg[3], "MSG_???");
266
267         return RVAL_DECODED;
268 }
269
270 SYS_FUNC(sendto)
271 {
272         printfd(tcp, tcp->u_arg[0]);
273         tprints(", ");
274         decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]);
275         tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
276         /* flags */
277         printflags(msg_flags, tcp->u_arg[3], "MSG_???");
278         /* to address */
279         const int addrlen = tcp->u_arg[5];
280         tprints(", ");
281         decode_sockaddr(tcp, tcp->u_arg[4], addrlen);
282         /* to length */
283         tprintf(", %d", addrlen);
284
285         return RVAL_DECODED;
286 }
287
288 SYS_FUNC(recv)
289 {
290         if (entering(tcp)) {
291                 printfd(tcp, tcp->u_arg[0]);
292                 tprints(", ");
293         } else {
294                 if (syserror(tcp)) {
295                         printaddr(tcp->u_arg[1]);
296                 } else {
297                         decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1],
298                                      tcp->u_rval);
299                 }
300
301                 tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
302                 printflags(msg_flags, tcp->u_arg[3], "MSG_???");
303         }
304         return 0;
305 }
306
307 SYS_FUNC(recvfrom)
308 {
309         int ulen, rlen;
310
311         if (entering(tcp)) {
312                 printfd(tcp, tcp->u_arg[0]);
313                 tprints(", ");
314                 if (fetch_socklen(tcp, &ulen, tcp->u_arg[4], tcp->u_arg[5])) {
315                         set_tcb_priv_ulong(tcp, ulen);
316                 }
317         } else {
318                 /* buf */
319                 if (syserror(tcp)) {
320                         printaddr(tcp->u_arg[1]);
321                 } else {
322                         decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1],
323                                      tcp->u_rval);
324                 }
325                 /* size */
326                 tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
327                 /* flags */
328                 printflags(msg_flags, tcp->u_arg[3], "MSG_???");
329                 tprints(", ");
330
331                 ulen = get_tcb_priv_ulong(tcp);
332
333                 if (!fetch_socklen(tcp, &rlen, tcp->u_arg[4], tcp->u_arg[5])) {
334                         /* from address */
335                         printaddr(tcp->u_arg[4]);
336                         tprints(", ");
337                         /* from length */
338                         printaddr(tcp->u_arg[5]);
339                         return 0;
340                 }
341                 if (syserror(tcp)) {
342                         /* from address */
343                         printaddr(tcp->u_arg[4]);
344                         /* from length */
345                         tprintf(", [%d]", ulen);
346                         return 0;
347                 }
348                 /* from address */
349                 decode_sockaddr(tcp, tcp->u_arg[4], ulen > rlen ? rlen : ulen);
350                 /* from length */
351                 if (ulen != rlen)
352                         tprintf(", [%d->%d]", ulen, rlen);
353                 else
354                         tprintf(", [%d]", rlen);
355         }
356         return 0;
357 }
358
359 SYS_FUNC(getsockname)
360 {
361         return decode_sockname(tcp);
362 }
363
364 static void
365 printpair_fd(struct tcb *tcp, const int i0, const int i1)
366 {
367         tprints("[");
368         printfd(tcp, i0);
369         tprints(", ");
370         printfd(tcp, i1);
371         tprints("]");
372 }
373
374 static void
375 decode_pair_fd(struct tcb *const tcp, const kernel_ulong_t addr)
376 {
377         int pair[2];
378
379         if (umove_or_printaddr(tcp, addr, &pair))
380                 return;
381
382         printpair_fd(tcp, pair[0], pair[1]);
383 }
384
385 static int
386 do_pipe(struct tcb *tcp, int flags_arg)
387 {
388         if (exiting(tcp)) {
389                 decode_pair_fd(tcp, tcp->u_arg[0]);
390                 if (flags_arg >= 0) {
391                         tprints(", ");
392                         printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
393                 }
394         }
395         return 0;
396 }
397
398 SYS_FUNC(pipe)
399 {
400 #if HAVE_ARCH_GETRVAL2
401         if (exiting(tcp) && !syserror(tcp))
402                 printpair_fd(tcp, tcp->u_rval, getrval2(tcp));
403         return 0;
404 #else
405         return do_pipe(tcp, -1);
406 #endif
407 }
408
409 SYS_FUNC(pipe2)
410 {
411         return do_pipe(tcp, 1);
412 }
413
414 SYS_FUNC(socketpair)
415 {
416         if (entering(tcp)) {
417                 printxval(addrfams, tcp->u_arg[0], "AF_???");
418                 tprints(", ");
419                 tprint_sock_type(tcp->u_arg[1]);
420                 tprintf(", %" PRI_klu, tcp->u_arg[2]);
421         } else {
422                 tprints(", ");
423                 decode_pair_fd(tcp, tcp->u_arg[3]);
424         }
425         return 0;
426 }
427
428 #include "xlat/sock_options.h"
429 #include "xlat/getsock_options.h"
430 #include "xlat/setsock_options.h"
431 #include "xlat/sock_ip_options.h"
432 #include "xlat/getsock_ip_options.h"
433 #include "xlat/setsock_ip_options.h"
434 #include "xlat/sock_ipv6_options.h"
435 #include "xlat/getsock_ipv6_options.h"
436 #include "xlat/setsock_ipv6_options.h"
437 #include "xlat/sock_ipx_options.h"
438 #include "xlat/sock_netlink_options.h"
439 #include "xlat/sock_packet_options.h"
440 #include "xlat/sock_raw_options.h"
441 #include "xlat/sock_sctp_options.h"
442 #include "xlat/sock_tcp_options.h"
443 #include "xlat/sock_udp_options.h"
444 #include "xlat/sock_irda_options.h"
445 #include "xlat/sock_llc_options.h"
446 #include "xlat/sock_dccp_options.h"
447 #include "xlat/sock_tipc_options.h"
448 #include "xlat/sock_rxrpc_options.h"
449 #include "xlat/sock_pppol2tp_options.h"
450 #include "xlat/sock_bluetooth_options.h"
451 #include "xlat/sock_pnp_options.h"
452 #include "xlat/sock_rds_options.h"
453 #include "xlat/sock_iucv_options.h"
454 #include "xlat/sock_caif_options.h"
455 #include "xlat/sock_alg_options.h"
456 #include "xlat/sock_nfcllcp_options.h"
457 #include "xlat/sock_kcm_options.h"
458 #include "xlat/sock_tls_options.h"
459
460 static void
461 print_sockopt_fd_level_name(struct tcb *tcp, int fd, unsigned int level,
462                             unsigned int name, bool is_getsockopt)
463 {
464         printfd(tcp, fd);
465         tprints(", ");
466         printxval_search(socketlayers, level, "SOL_??");
467         tprints(", ");
468
469         switch (level) {
470         case SOL_SOCKET:
471                 printxvals(name, "SO_???", sock_options,
472                            is_getsockopt ? getsock_options :
473                                            setsock_options, NULL);
474                 break;
475         case SOL_IP:
476                 printxvals(name, "IP_???", sock_ip_options,
477                            is_getsockopt ? getsock_ip_options :
478                                            setsock_ip_options, NULL);
479                 break;
480         case SOL_IPV6:
481                 printxvals(name, "IPV6_???", sock_ipv6_options,
482                            is_getsockopt ? getsock_ipv6_options :
483                                            setsock_ipv6_options, NULL);
484                 break;
485         case SOL_IPX:
486                 printxval(sock_ipx_options, name, "IPX_???");
487                 break;
488         case SOL_PACKET:
489                 printxval(sock_packet_options, name, "PACKET_???");
490                 break;
491         case SOL_TCP:
492                 printxval(sock_tcp_options, name, "TCP_???");
493                 break;
494         case SOL_SCTP:
495                 printxval(sock_sctp_options, name, "SCTP_???");
496                 break;
497         case SOL_RAW:
498                 printxval(sock_raw_options, name, "RAW_???");
499                 break;
500         case SOL_NETLINK:
501                 printxval(sock_netlink_options, name, "NETLINK_???");
502                 break;
503         case SOL_UDP:
504                 printxval(sock_udp_options, name, "UDP_???");
505                 break;
506         case SOL_IRDA:
507                 printxval_index(sock_irda_options, name, "IRLMP_???");
508                 break;
509         case SOL_LLC:
510                 printxval_index(sock_llc_options, name, "LLC_OPT_???");
511                 break;
512         case SOL_DCCP:
513                 printxval_search(sock_dccp_options, name, "DCCP_SOCKOPT_???");
514                 break;
515         case SOL_TIPC:
516                 printxval_search(sock_tipc_options, name, "TIPC_???");
517                 break;
518         case SOL_RXRPC:
519                 printxval_index(sock_rxrpc_options, name, "RXRPC_???");
520                 break;
521         case SOL_PPPOL2TP:
522                 printxval_index(sock_pppol2tp_options, name, "PPPOL2TP_SO_???");
523                 break;
524         case SOL_BLUETOOTH:
525                 printxval_search(sock_bluetooth_options, name, "BT_???");
526                 break;
527         case SOL_PNPIPE:
528                 printxval(sock_pnp_options, name, "PNPIPE_???");
529                 break;
530         case SOL_RDS:
531                 printxval(sock_rds_options, name, "RDS_???");
532                 break;
533         case SOL_IUCV:
534                 printxval(sock_iucv_options, name, "SO_???");
535                 break;
536         case SOL_CAIF:
537                 printxval(sock_caif_options, name, "CAIFSO_???");
538                 break;
539         case SOL_ALG:
540                 printxval_index(sock_alg_options, name, "ALG_???");
541                 break;
542         case SOL_NFC:
543                 printxval_index(sock_nfcllcp_options, name, "NFC_LLCP_???");
544                 break;
545         case SOL_KCM:
546                 printxval(sock_kcm_options, name, "KCM_???");
547                 break;
548         case SOL_TLS:
549                 printxval(sock_tls_options, name, "TLS_???");
550                 break;
551
552                 /* Other SOL_* protocol levels still need work. */
553
554         default:
555                 tprintf("%u", name);
556         }
557
558         tprints(", ");
559 }
560
561 static void
562 print_set_linger(struct tcb *const tcp, const kernel_ulong_t addr,
563                  const int len)
564 {
565         struct linger linger;
566
567         if (len < (int) sizeof(linger)) {
568                 printaddr(addr);
569         } else if (!umove_or_printaddr(tcp, addr, &linger)) {
570                 PRINT_FIELD_D("{", linger, l_onoff);
571                 PRINT_FIELD_D(", ", linger, l_linger);
572                 tprints("}");
573         }
574 }
575
576 static void
577 print_get_linger(struct tcb *const tcp, const kernel_ulong_t addr,
578                  unsigned int len)
579 {
580         struct linger linger;
581
582         if (len < sizeof(linger)) {
583                 if (len != sizeof(linger.l_onoff)) {
584                         printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
585                         return;
586                 }
587         } else {
588                 len = sizeof(linger);
589         }
590
591         if (umoven(tcp, addr, len, &linger) < 0) {
592                 printaddr(addr);
593                 return;
594         }
595
596         PRINT_FIELD_D("{", linger, l_onoff);
597         if (len == sizeof(linger))
598                 PRINT_FIELD_D(", ", linger, l_linger);
599         tprints("}");
600 }
601
602 #ifdef SO_PEERCRED
603 static void
604 print_ucred(struct tcb *const tcp, const kernel_ulong_t addr, unsigned int len)
605 {
606         struct ucred uc;
607
608         if (len < sizeof(uc)) {
609                 if (len != sizeof(uc.pid)
610                     && len != offsetofend(struct ucred, uid)) {
611                         printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
612                         return;
613                 }
614         } else {
615                 len = sizeof(uc);
616         }
617
618         if (umoven(tcp, addr, len, &uc) < 0) {
619                 printaddr(addr);
620                 return;
621         }
622
623         PRINT_FIELD_D("{", uc, pid);
624         if (len > sizeof(uc.pid))
625                 PRINT_FIELD_UID(", ", uc, uid);
626         if (len == sizeof(uc))
627                 PRINT_FIELD_UID(", ", uc, gid);
628         tprints("}");
629 }
630 #endif /* SO_PEERCRED */
631
632 #ifdef PACKET_STATISTICS
633 static void
634 print_tpacket_stats(struct tcb *const tcp, const kernel_ulong_t addr,
635                     const int len)
636 {
637         struct tpacket_stats stats;
638
639         if (len != sizeof(stats) ||
640             umove(tcp, addr, &stats) < 0) {
641                 printaddr(addr);
642         } else {
643                 PRINT_FIELD_U("{", stats, tp_packets);
644                 PRINT_FIELD_U("{", stats, tp_drops);
645                 tprints("}");
646         }
647 }
648 #endif /* PACKET_STATISTICS */
649
650 #include "xlat/icmpfilterflags.h"
651
652 static void
653 print_icmp_filter(struct tcb *const tcp, const kernel_ulong_t addr, int len)
654 {
655         struct icmp_filter filter = {};
656
657         if (len > (int) sizeof(filter))
658                 len = sizeof(filter);
659         else if (len <= 0) {
660                 printaddr(addr);
661                 return;
662         }
663
664         if (umoven_or_printaddr(tcp, addr, len, &filter))
665                 return;
666
667         tprints("~(");
668         printflags(icmpfilterflags, ~filter.data, "ICMP_???");
669         tprints(")");
670 }
671
672 static bool
673 print_uint32(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
674 {
675         tprintf("%u", *(uint32_t *) elem_buf);
676
677         return true;
678 }
679
680 static void
681 print_getsockopt(struct tcb *const tcp, const unsigned int level,
682                  const unsigned int name, const kernel_ulong_t addr,
683                  const int ulen, const int rlen)
684 {
685         if (addr && verbose(tcp))
686         switch (level) {
687         case SOL_SOCKET:
688                 switch (name) {
689                 case SO_LINGER:
690                         print_get_linger(tcp, addr, rlen);
691                         return;
692 #ifdef SO_PEERCRED
693                 case SO_PEERCRED:
694                         print_ucred(tcp, addr, rlen);
695                         return;
696 #endif
697 #ifdef SO_ATTACH_FILTER
698                 case SO_ATTACH_FILTER:
699                         if (rlen && (unsigned short) rlen == (unsigned int) rlen)
700                                 print_sock_fprog(tcp, addr, rlen);
701                         else
702                                 printaddr(addr);
703                         return;
704 #endif /* SO_ATTACH_FILTER */
705                 }
706                 break;
707
708         case SOL_PACKET:
709                 switch (name) {
710 #ifdef PACKET_STATISTICS
711                 case PACKET_STATISTICS:
712                         print_tpacket_stats(tcp, addr, rlen);
713                         return;
714 #endif
715                 }
716                 break;
717
718         case SOL_RAW:
719                 switch (name) {
720                 case ICMP_FILTER:
721                         print_icmp_filter(tcp, addr, rlen);
722                         return;
723                 }
724                 break;
725
726         case SOL_NETLINK:
727                 if (ulen < 0 || rlen < 0) {
728                         /*
729                          * As the kernel neither accepts nor returns a negative
730                          * length, in case of successful getsockopt syscall
731                          * invocation these negative values must have come
732                          * from userspace.
733                          */
734                         printaddr(addr);
735                         return;
736                 }
737                 switch (name) {
738                 case NETLINK_LIST_MEMBERSHIPS: {
739                         uint32_t buf;
740                         print_array(tcp, addr, MIN(ulen, rlen) / sizeof(buf),
741                                     &buf, sizeof(buf),
742                                     umoven_or_printaddr, print_uint32, 0);
743                         break;
744                         }
745                 default:
746                         printnum_int(tcp, addr, "%d");
747                         break;
748                 }
749                 return;
750         }
751
752         /* default arg printing */
753
754         if (verbose(tcp)) {
755                 if (rlen == sizeof(int)) {
756                         printnum_int(tcp, addr, "%d");
757                 } else {
758                         printstrn(tcp, addr, rlen);
759                 }
760         } else {
761                 printaddr(addr);
762         }
763 }
764
765 SYS_FUNC(getsockopt)
766 {
767         int ulen, rlen;
768
769         if (entering(tcp)) {
770                 print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
771                                             tcp->u_arg[1], tcp->u_arg[2], true);
772
773                 if (verbose(tcp) && tcp->u_arg[4]
774                     && umove(tcp, tcp->u_arg[4], &ulen) == 0) {
775                         set_tcb_priv_ulong(tcp, ulen);
776                         return 0;
777                 } else {
778                         printaddr(tcp->u_arg[3]);
779                         tprints(", ");
780                         printaddr(tcp->u_arg[4]);
781                         return RVAL_DECODED;
782                 }
783         } else {
784                 ulen = get_tcb_priv_ulong(tcp);
785
786                 if (syserror(tcp) || umove(tcp, tcp->u_arg[4], &rlen) < 0) {
787                         printaddr(tcp->u_arg[3]);
788                         tprintf(", [%d]", ulen);
789                 } else {
790                         print_getsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
791                                          tcp->u_arg[3], ulen, rlen);
792                         if (ulen != rlen)
793                                 tprintf(", [%d->%d]", ulen, rlen);
794                         else
795                                 tprintf(", [%d]", rlen);
796                 }
797         }
798         return 0;
799 }
800
801 #ifdef IP_ADD_MEMBERSHIP
802 static void
803 print_mreq(struct tcb *const tcp, const kernel_ulong_t addr,
804            const int len)
805 {
806         struct ip_mreq mreq;
807
808         if (len < (int) sizeof(mreq)) {
809                 printaddr(addr);
810         } else if (!umove_or_printaddr(tcp, addr, &mreq)) {
811                 PRINT_FIELD_INET4_ADDR("{", mreq, imr_multiaddr);
812                 PRINT_FIELD_INET4_ADDR(", ", mreq, imr_interface);
813                 tprints("}");
814         }
815 }
816 #endif /* IP_ADD_MEMBERSHIP */
817
818 #ifdef IPV6_ADD_MEMBERSHIP
819 static void
820 print_mreq6(struct tcb *const tcp, const kernel_ulong_t addr,
821             const int len)
822 {
823         struct ipv6_mreq mreq;
824
825         if (len < (int) sizeof(mreq)) {
826                 printaddr(addr);
827         } else if (!umove_or_printaddr(tcp, addr, &mreq)) {
828                 PRINT_FIELD_INET_ADDR("{", mreq, ipv6mr_multiaddr, AF_INET6);
829                 PRINT_FIELD_IFINDEX(", ", mreq, ipv6mr_interface);
830                 tprints("}");
831         }
832 }
833 #endif /* IPV6_ADD_MEMBERSHIP */
834
835 #ifdef PACKET_RX_RING
836 static void
837 print_tpacket_req(struct tcb *const tcp, const kernel_ulong_t addr, const int len)
838 {
839         struct tpacket_req req;
840
841         if (len != sizeof(req) ||
842             umove(tcp, addr, &req) < 0) {
843                 printaddr(addr);
844         } else {
845                 PRINT_FIELD_U("{", req, tp_block_size);
846                 PRINT_FIELD_U(", ", req, tp_block_nr);
847                 PRINT_FIELD_U(", ", req, tp_frame_size);
848                 PRINT_FIELD_U(", ", req, tp_frame_nr);
849                 tprints("}");
850         }
851 }
852 #endif /* PACKET_RX_RING */
853
854 #ifdef PACKET_ADD_MEMBERSHIP
855 # include "xlat/packet_mreq_type.h"
856
857 static void
858 print_packet_mreq(struct tcb *const tcp, const kernel_ulong_t addr, const int len)
859 {
860         struct packet_mreq mreq;
861
862         if (len != sizeof(mreq) ||
863             umove(tcp, addr, &mreq) < 0) {
864                 printaddr(addr);
865         } else {
866                 unsigned int i;
867
868                 PRINT_FIELD_IFINDEX("{", mreq, mr_ifindex);
869                 PRINT_FIELD_XVAL(", ", mreq, mr_type, packet_mreq_type,
870                                  "PACKET_MR_???");
871                 PRINT_FIELD_U(", ", mreq, mr_alen);
872                 tprints(", mr_address=");
873                 if (mreq.mr_alen > ARRAY_SIZE(mreq.mr_address))
874                         mreq.mr_alen = ARRAY_SIZE(mreq.mr_address);
875                 for (i = 0; i < mreq.mr_alen; ++i)
876                         tprintf("%02x", mreq.mr_address[i]);
877                 tprints("}");
878         }
879 }
880 #endif /* PACKET_ADD_MEMBERSHIP */
881
882 static void
883 print_setsockopt(struct tcb *const tcp, const unsigned int level,
884                  const unsigned int name, const kernel_ulong_t addr,
885                  const int len)
886 {
887         if (addr && verbose(tcp))
888         switch (level) {
889         case SOL_SOCKET:
890                 switch (name) {
891                 case SO_LINGER:
892                         print_set_linger(tcp, addr, len);
893                         return;
894 #ifdef SO_ATTACH_FILTER
895                 case SO_ATTACH_FILTER:
896 # ifdef SO_ATTACH_REUSEPORT_CBPF
897                 case SO_ATTACH_REUSEPORT_CBPF:
898 # endif
899                         if ((unsigned int) len == get_sock_fprog_size())
900                                 decode_sock_fprog(tcp, addr);
901                         else
902                                 printaddr(addr);
903                         return;
904 #endif /* SO_ATTACH_FILTER */
905                 }
906                 break;
907
908         case SOL_IP:
909                 switch (name) {
910 #ifdef IP_ADD_MEMBERSHIP
911                 case IP_ADD_MEMBERSHIP:
912                 case IP_DROP_MEMBERSHIP:
913                         print_mreq(tcp, addr, len);
914                         return;
915 #endif /* IP_ADD_MEMBERSHIP */
916 #ifdef MCAST_JOIN_GROUP
917                 case MCAST_JOIN_GROUP:
918                 case MCAST_LEAVE_GROUP:
919                         print_group_req(tcp, addr, len);
920                         return;
921 #endif /* MCAST_JOIN_GROUP */
922                 }
923                 break;
924
925         case SOL_IPV6:
926                 switch (name) {
927 #ifdef IPV6_ADD_MEMBERSHIP
928                 case IPV6_ADD_MEMBERSHIP:
929                 case IPV6_DROP_MEMBERSHIP:
930 # ifdef IPV6_JOIN_ANYCAST
931                 case IPV6_JOIN_ANYCAST:
932 # endif
933 # ifdef IPV6_LEAVE_ANYCAST
934                 case IPV6_LEAVE_ANYCAST:
935 # endif
936                         print_mreq6(tcp, addr, len);
937                         return;
938 #endif /* IPV6_ADD_MEMBERSHIP */
939 #ifdef MCAST_JOIN_GROUP
940                 case MCAST_JOIN_GROUP:
941                 case MCAST_LEAVE_GROUP:
942                         print_group_req(tcp, addr, len);
943                         return;
944 #endif /* MCAST_JOIN_GROUP */
945                 }
946                 break;
947
948         case SOL_PACKET:
949                 switch (name) {
950 #ifdef PACKET_RX_RING
951                 case PACKET_RX_RING:
952 # ifdef PACKET_TX_RING
953                 case PACKET_TX_RING:
954 # endif
955                         print_tpacket_req(tcp, addr, len);
956                         return;
957 #endif /* PACKET_RX_RING */
958 #ifdef PACKET_ADD_MEMBERSHIP
959                 case PACKET_ADD_MEMBERSHIP:
960                 case PACKET_DROP_MEMBERSHIP:
961                         print_packet_mreq(tcp, addr, len);
962                         return;
963 #endif /* PACKET_ADD_MEMBERSHIP */
964                 }
965                 break;
966
967         case SOL_RAW:
968                 switch (name) {
969                 case ICMP_FILTER:
970                         print_icmp_filter(tcp, addr, len);
971                         return;
972                 }
973                 break;
974
975         case SOL_NETLINK:
976                 if (len < (int) sizeof(int))
977                         printaddr(addr);
978                 else
979                         printnum_int(tcp, addr, "%d");
980                 return;
981         }
982
983         /* default arg printing */
984
985         if (verbose(tcp)) {
986                 if (len == sizeof(int)) {
987                         printnum_int(tcp, addr, "%d");
988                 } else {
989                         printstrn(tcp, addr, len);
990                 }
991         } else {
992                 printaddr(addr);
993         }
994 }
995
996 SYS_FUNC(setsockopt)
997 {
998         print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
999                                     tcp->u_arg[1], tcp->u_arg[2], false);
1000         print_setsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
1001                          tcp->u_arg[3], tcp->u_arg[4]);
1002         tprintf(", %d", (int) tcp->u_arg[4]);
1003
1004         return RVAL_DECODED;
1005 }