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