Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk (at) cs.few.eur.nl>
      3  * Copyright (c) 1993 Branko Lankester <branko (at) hacktic.nl>
      4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com>
      5  * Copyright (c) 1996-2000 Wichert Akkerman <wichert (at) 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 #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 #if HAVE_ARCH_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/socknetlinkoptions.h"
    394 #include "xlat/sockpacketoptions.h"
    395 #include "xlat/sockrawoptions.h"
    396 #include "xlat/socksctpoptions.h"
    397 #include "xlat/socktcpoptions.h"
    398 
    399 static void
    400 print_sockopt_fd_level_name(struct tcb *tcp, int fd, unsigned int level,
    401 			    unsigned int name, bool is_getsockopt)
    402 {
    403 	printfd(tcp, fd);
    404 	tprints(", ");
    405 	printxval(socketlayers, level, "SOL_??");
    406 	tprints(", ");
    407 
    408 	switch (level) {
    409 	case SOL_SOCKET:
    410 		printxval(sockoptions, name, "SO_???");
    411 		break;
    412 	case SOL_IP:
    413 		printxvals(name, "IP_???", sockipoptions,
    414 			is_getsockopt ? getsockipoptions : setsockipoptions, NULL);
    415 		break;
    416 	case SOL_IPV6:
    417 		printxvals(name, "IPV6_???", sockipv6options,
    418 			is_getsockopt ? getsockipv6options : setsockipv6options, NULL);
    419 		break;
    420 	case SOL_IPX:
    421 		printxval(sockipxoptions, name, "IPX_???");
    422 		break;
    423 	case SOL_PACKET:
    424 		printxval(sockpacketoptions, name, "PACKET_???");
    425 		break;
    426 	case SOL_TCP:
    427 		printxval(socktcpoptions, name, "TCP_???");
    428 		break;
    429 	case SOL_SCTP:
    430 		printxval(socksctpoptions, name, "SCTP_???");
    431 		break;
    432 	case SOL_RAW:
    433 		printxval(sockrawoptions, name, "RAW_???");
    434 		break;
    435 	case SOL_NETLINK:
    436 		printxval(socknetlinkoptions, name, "NETLINK_???");
    437 		break;
    438 
    439 		/* Other SOL_* protocol levels still need work. */
    440 
    441 	default:
    442 		tprintf("%u", name);
    443 	}
    444 
    445 	tprints(", ");
    446 }
    447 
    448 static void
    449 print_set_linger(struct tcb *const tcp, const kernel_ulong_t addr,
    450 		 const int len)
    451 {
    452 	struct linger linger;
    453 
    454 	if (len < (int) sizeof(linger)) {
    455 		printaddr(addr);
    456 	} else if (!umove_or_printaddr(tcp, addr, &linger)) {
    457 		PRINT_FIELD_D("{", linger, l_onoff);
    458 		PRINT_FIELD_D(", ", linger, l_linger);
    459 		tprints("}");
    460 	}
    461 }
    462 
    463 static void
    464 print_get_linger(struct tcb *const tcp, const kernel_ulong_t addr,
    465 		 unsigned int len)
    466 {
    467 	struct linger linger;
    468 
    469 	if (len < sizeof(linger)) {
    470 		if (len != sizeof(linger.l_onoff)) {
    471 			printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
    472 			return;
    473 		}
    474 	} else {
    475 		len = sizeof(linger);
    476 	}
    477 
    478 	if (umoven(tcp, addr, len, &linger) < 0) {
    479 		printaddr(addr);
    480 		return;
    481 	}
    482 
    483 	PRINT_FIELD_D("{", linger, l_onoff);
    484 	if (len == sizeof(linger))
    485 		PRINT_FIELD_D(", ", linger, l_linger);
    486 	tprints("}");
    487 }
    488 
    489 #ifdef SO_PEERCRED
    490 static void
    491 print_ucred(struct tcb *const tcp, const kernel_ulong_t addr, unsigned int len)
    492 {
    493 	struct ucred uc;
    494 
    495 	if (len < sizeof(uc)) {
    496 		if (len != sizeof(uc.pid)
    497 		    && len != offsetofend(struct ucred, uid)) {
    498 			printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
    499 			return;
    500 		}
    501 	} else {
    502 		len = sizeof(uc);
    503 	}
    504 
    505 	if (umoven(tcp, addr, len, &uc) < 0) {
    506 		printaddr(addr);
    507 		return;
    508 	}
    509 
    510 	PRINT_FIELD_D("{", uc, pid);
    511 	if (len > sizeof(uc.pid))
    512 		PRINT_FIELD_UID(", ", uc, uid);
    513 	if (len == sizeof(uc))
    514 		PRINT_FIELD_UID(", ", uc, gid);
    515 	tprints("}");
    516 }
    517 #endif /* SO_PEERCRED */
    518 
    519 #ifdef PACKET_STATISTICS
    520 static void
    521 print_tpacket_stats(struct tcb *const tcp, const kernel_ulong_t addr,
    522 		    const int len)
    523 {
    524 	struct tpacket_stats stats;
    525 
    526 	if (len != sizeof(stats) ||
    527 	    umove(tcp, addr, &stats) < 0) {
    528 		printaddr(addr);
    529 	} else {
    530 		PRINT_FIELD_U("{", stats, tp_packets);
    531 		PRINT_FIELD_U("{", stats, tp_drops);
    532 		tprints("}");
    533 	}
    534 }
    535 #endif /* PACKET_STATISTICS */
    536 
    537 #include "xlat/icmpfilterflags.h"
    538 
    539 static void
    540 print_icmp_filter(struct tcb *const tcp, const kernel_ulong_t addr, int len)
    541 {
    542 	struct icmp_filter filter = {};
    543 
    544 	if (len > (int) sizeof(filter))
    545 		len = sizeof(filter);
    546 	else if (len <= 0) {
    547 		printaddr(addr);
    548 		return;
    549 	}
    550 
    551 	if (umoven_or_printaddr(tcp, addr, len, &filter))
    552 		return;
    553 
    554 	tprints("~(");
    555 	printflags(icmpfilterflags, ~filter.data, "ICMP_???");
    556 	tprints(")");
    557 }
    558 
    559 static bool
    560 print_uint32(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
    561 {
    562 	tprintf("%u", *(uint32_t *) elem_buf);
    563 
    564 	return true;
    565 }
    566 
    567 static void
    568 print_getsockopt(struct tcb *const tcp, const unsigned int level,
    569 		 const unsigned int name, const kernel_ulong_t addr,
    570 		 const int ulen, const int rlen)
    571 {
    572 	if (addr && verbose(tcp))
    573 	switch (level) {
    574 	case SOL_SOCKET:
    575 		switch (name) {
    576 		case SO_LINGER:
    577 			print_get_linger(tcp, addr, rlen);
    578 			return;
    579 #ifdef SO_PEERCRED
    580 		case SO_PEERCRED:
    581 			print_ucred(tcp, addr, rlen);
    582 			return;
    583 #endif
    584 #ifdef SO_ATTACH_FILTER
    585 		case SO_ATTACH_FILTER:
    586 			if (rlen && (unsigned short) rlen == (unsigned int) rlen)
    587 				print_sock_fprog(tcp, addr, rlen);
    588 			else
    589 				printaddr(addr);
    590 			return;
    591 #endif /* SO_ATTACH_FILTER */
    592 		}
    593 		break;
    594 
    595 	case SOL_PACKET:
    596 		switch (name) {
    597 #ifdef PACKET_STATISTICS
    598 		case PACKET_STATISTICS:
    599 			print_tpacket_stats(tcp, addr, rlen);
    600 			return;
    601 #endif
    602 		}
    603 		break;
    604 
    605 	case SOL_RAW:
    606 		switch (name) {
    607 		case ICMP_FILTER:
    608 			print_icmp_filter(tcp, addr, rlen);
    609 			return;
    610 		}
    611 		break;
    612 
    613 	case SOL_NETLINK:
    614 		if (ulen < 0 || rlen < 0) {
    615 			/*
    616 			 * As the kernel neither accepts nor returns a negative
    617 			 * length, in case of successful getsockopt syscall
    618 			 * invocation these negative values must have come
    619 			 * from userspace.
    620 			 */
    621 			printaddr(addr);
    622 			return;
    623 		}
    624 		switch (name) {
    625 		case NETLINK_LIST_MEMBERSHIPS: {
    626 			uint32_t buf;
    627 			print_array(tcp, addr, MIN(ulen, rlen) / sizeof(buf),
    628 				    &buf, sizeof(buf),
    629 				    umoven_or_printaddr, print_uint32, 0);
    630 			break;
    631 			}
    632 		default:
    633 			printnum_int(tcp, addr, "%d");
    634 			break;
    635 		}
    636 		return;
    637 	}
    638 
    639 	/* default arg printing */
    640 
    641 	if (verbose(tcp)) {
    642 		if (rlen == sizeof(int)) {
    643 			printnum_int(tcp, addr, "%d");
    644 		} else {
    645 			printstrn(tcp, addr, rlen);
    646 		}
    647 	} else {
    648 		printaddr(addr);
    649 	}
    650 }
    651 
    652 SYS_FUNC(getsockopt)
    653 {
    654 	int ulen, rlen;
    655 
    656 	if (entering(tcp)) {
    657 		print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
    658 					    tcp->u_arg[1], tcp->u_arg[2], true);
    659 
    660 		if (verbose(tcp) && tcp->u_arg[4]
    661 		    && umove(tcp, tcp->u_arg[4], &ulen) == 0) {
    662 			set_tcb_priv_ulong(tcp, ulen);
    663 			return 0;
    664 		} else {
    665 			printaddr(tcp->u_arg[3]);
    666 			tprints(", ");
    667 			printaddr(tcp->u_arg[4]);
    668 			return RVAL_DECODED;
    669 		}
    670 	} else {
    671 		ulen = get_tcb_priv_ulong(tcp);
    672 
    673 		if (syserror(tcp) || umove(tcp, tcp->u_arg[4], &rlen) < 0) {
    674 			printaddr(tcp->u_arg[3]);
    675 			tprintf(", [%d]", ulen);
    676 		} else {
    677 			print_getsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
    678 					 tcp->u_arg[3], ulen, rlen);
    679 			if (ulen != rlen)
    680 				tprintf(", [%d->%d]", ulen, rlen);
    681 			else
    682 				tprintf(", [%d]", rlen);
    683 		}
    684 	}
    685 	return 0;
    686 }
    687 
    688 #ifdef IP_ADD_MEMBERSHIP
    689 static void
    690 print_mreq(struct tcb *const tcp, const kernel_ulong_t addr,
    691 	   const int len)
    692 {
    693 	struct ip_mreq mreq;
    694 
    695 	if (len < (int) sizeof(mreq)) {
    696 		printaddr(addr);
    697 	} else if (!umove_or_printaddr(tcp, addr, &mreq)) {
    698 		PRINT_FIELD_INET4_ADDR("{", mreq, imr_multiaddr);
    699 		PRINT_FIELD_INET4_ADDR(", ", mreq, imr_interface);
    700 		tprints("}");
    701 	}
    702 }
    703 #endif /* IP_ADD_MEMBERSHIP */
    704 
    705 #ifdef IPV6_ADD_MEMBERSHIP
    706 static void
    707 print_mreq6(struct tcb *const tcp, const kernel_ulong_t addr,
    708 	    const int len)
    709 {
    710 	struct ipv6_mreq mreq;
    711 
    712 	if (len < (int) sizeof(mreq)) {
    713 		printaddr(addr);
    714 	} else if (!umove_or_printaddr(tcp, addr, &mreq)) {
    715 		PRINT_FIELD_INET_ADDR("{", mreq, ipv6mr_multiaddr, AF_INET6);
    716 		PRINT_FIELD_IFINDEX(", ", mreq, ipv6mr_interface);
    717 		tprints("}");
    718 	}
    719 }
    720 #endif /* IPV6_ADD_MEMBERSHIP */
    721 
    722 #ifdef PACKET_RX_RING
    723 static void
    724 print_tpacket_req(struct tcb *const tcp, const kernel_ulong_t addr, const int len)
    725 {
    726 	struct tpacket_req req;
    727 
    728 	if (len != sizeof(req) ||
    729 	    umove(tcp, addr, &req) < 0) {
    730 		printaddr(addr);
    731 	} else {
    732 		PRINT_FIELD_U("{", req, tp_block_size);
    733 		PRINT_FIELD_U(", ", req, tp_block_nr);
    734 		PRINT_FIELD_U(", ", req, tp_frame_size);
    735 		PRINT_FIELD_U(", ", req, tp_frame_nr);
    736 		tprints("}");
    737 	}
    738 }
    739 #endif /* PACKET_RX_RING */
    740 
    741 #ifdef PACKET_ADD_MEMBERSHIP
    742 # include "xlat/packet_mreq_type.h"
    743 
    744 static void
    745 print_packet_mreq(struct tcb *const tcp, const kernel_ulong_t addr, const int len)
    746 {
    747 	struct packet_mreq mreq;
    748 
    749 	if (len != sizeof(mreq) ||
    750 	    umove(tcp, addr, &mreq) < 0) {
    751 		printaddr(addr);
    752 	} else {
    753 		unsigned int i;
    754 
    755 		PRINT_FIELD_IFINDEX("{", mreq, mr_ifindex);
    756 		PRINT_FIELD_XVAL(", ", mreq, mr_type, packet_mreq_type,
    757 				 "PACKET_MR_???");
    758 		PRINT_FIELD_U(", ", mreq, mr_alen);
    759 		tprints(", mr_address=");
    760 		if (mreq.mr_alen > ARRAY_SIZE(mreq.mr_address))
    761 			mreq.mr_alen = ARRAY_SIZE(mreq.mr_address);
    762 		for (i = 0; i < mreq.mr_alen; ++i)
    763 			tprintf("%02x", mreq.mr_address[i]);
    764 		tprints("}");
    765 	}
    766 }
    767 #endif /* PACKET_ADD_MEMBERSHIP */
    768 
    769 static void
    770 print_setsockopt(struct tcb *const tcp, const unsigned int level,
    771 		 const unsigned int name, const kernel_ulong_t addr,
    772 		 const int len)
    773 {
    774 	if (addr && verbose(tcp))
    775 	switch (level) {
    776 	case SOL_SOCKET:
    777 		switch (name) {
    778 		case SO_LINGER:
    779 			print_set_linger(tcp, addr, len);
    780 			return;
    781 #ifdef SO_ATTACH_FILTER
    782 		case SO_ATTACH_FILTER:
    783 # ifdef SO_ATTACH_REUSEPORT_CBPF
    784 		case SO_ATTACH_REUSEPORT_CBPF:
    785 # endif
    786 			if ((unsigned int) len == get_sock_fprog_size())
    787 				decode_sock_fprog(tcp, addr);
    788 			else
    789 				printaddr(addr);
    790 			return;
    791 #endif /* SO_ATTACH_FILTER */
    792 		}
    793 		break;
    794 
    795 	case SOL_IP:
    796 		switch (name) {
    797 #ifdef IP_ADD_MEMBERSHIP
    798 		case IP_ADD_MEMBERSHIP:
    799 		case IP_DROP_MEMBERSHIP:
    800 			print_mreq(tcp, addr, len);
    801 			return;
    802 #endif /* IP_ADD_MEMBERSHIP */
    803 #ifdef MCAST_JOIN_GROUP
    804 		case MCAST_JOIN_GROUP:
    805 		case MCAST_LEAVE_GROUP:
    806 			print_group_req(tcp, addr, len);
    807 			return;
    808 #endif /* MCAST_JOIN_GROUP */
    809 		}
    810 		break;
    811 
    812 	case SOL_IPV6:
    813 		switch (name) {
    814 #ifdef IPV6_ADD_MEMBERSHIP
    815 		case IPV6_ADD_MEMBERSHIP:
    816 		case IPV6_DROP_MEMBERSHIP:
    817 # ifdef IPV6_JOIN_ANYCAST
    818 		case IPV6_JOIN_ANYCAST:
    819 # endif
    820 # ifdef IPV6_LEAVE_ANYCAST
    821 		case IPV6_LEAVE_ANYCAST:
    822 # endif
    823 			print_mreq6(tcp, addr, len);
    824 			return;
    825 #endif /* IPV6_ADD_MEMBERSHIP */
    826 #ifdef MCAST_JOIN_GROUP
    827 		case MCAST_JOIN_GROUP:
    828 		case MCAST_LEAVE_GROUP:
    829 			print_group_req(tcp, addr, len);
    830 			return;
    831 #endif /* MCAST_JOIN_GROUP */
    832 		}
    833 		break;
    834 
    835 	case SOL_PACKET:
    836 		switch (name) {
    837 #ifdef PACKET_RX_RING
    838 		case PACKET_RX_RING:
    839 # ifdef PACKET_TX_RING
    840 		case PACKET_TX_RING:
    841 # endif
    842 			print_tpacket_req(tcp, addr, len);
    843 			return;
    844 #endif /* PACKET_RX_RING */
    845 #ifdef PACKET_ADD_MEMBERSHIP
    846 		case PACKET_ADD_MEMBERSHIP:
    847 		case PACKET_DROP_MEMBERSHIP:
    848 			print_packet_mreq(tcp, addr, len);
    849 			return;
    850 #endif /* PACKET_ADD_MEMBERSHIP */
    851 		}
    852 		break;
    853 
    854 	case SOL_RAW:
    855 		switch (name) {
    856 		case ICMP_FILTER:
    857 			print_icmp_filter(tcp, addr, len);
    858 			return;
    859 		}
    860 		break;
    861 
    862 	case SOL_NETLINK:
    863 		if (len < (int) sizeof(int))
    864 			printaddr(addr);
    865 		else
    866 			printnum_int(tcp, addr, "%d");
    867 		return;
    868 	}
    869 
    870 	/* default arg printing */
    871 
    872 	if (verbose(tcp)) {
    873 		if (len == sizeof(int)) {
    874 			printnum_int(tcp, addr, "%d");
    875 		} else {
    876 			printstrn(tcp, addr, len);
    877 		}
    878 	} else {
    879 		printaddr(addr);
    880 	}
    881 }
    882 
    883 SYS_FUNC(setsockopt)
    884 {
    885 	print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
    886 				    tcp->u_arg[1], tcp->u_arg[2], false);
    887 	print_setsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
    888 			 tcp->u_arg[3], tcp->u_arg[4]);
    889 	tprintf(", %d", (int) tcp->u_arg[4]);
    890 
    891 	return RVAL_DECODED;
    892 }
    893