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  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. The name of the author may not be used to endorse or promote products
     17  *    derived from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "defs.h"
     32 #include <sys/stat.h>
     33 #include <sys/socket.h>
     34 #include <sys/uio.h>
     35 #include <sys/un.h>
     36 #include <netinet/in.h>
     37 #ifdef HAVE_NETINET_TCP_H
     38 # include <netinet/tcp.h>
     39 #endif
     40 #ifdef HAVE_NETINET_UDP_H
     41 # include <netinet/udp.h>
     42 #endif
     43 #ifdef HAVE_NETINET_SCTP_H
     44 # include <netinet/sctp.h>
     45 #endif
     46 #include <arpa/inet.h>
     47 #include <net/if.h>
     48 #include <asm/types.h>
     49 #if defined(__GLIBC__)
     50 # include <netipx/ipx.h>
     51 #else
     52 # include <linux/ipx.h>
     53 #endif
     54 
     55 #if defined(HAVE_LINUX_NETLINK_H)
     56 # include <linux/netlink.h>
     57 #endif
     58 #if defined(HAVE_LINUX_IF_PACKET_H)
     59 # include <linux/if_packet.h>
     60 #endif
     61 #if defined(HAVE_LINUX_ICMP_H)
     62 # include <linux/icmp.h>
     63 #endif
     64 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
     65 # include <bluetooth/bluetooth.h>
     66 # include <bluetooth/hci.h>
     67 # include <bluetooth/l2cap.h>
     68 # include <bluetooth/rfcomm.h>
     69 # include <bluetooth/sco.h>
     70 #endif
     71 #ifndef PF_UNSPEC
     72 # define PF_UNSPEC AF_UNSPEC
     73 #endif
     74 
     75 #include "xlat/domains.h"
     76 #include "xlat/addrfams.h"
     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 #ifndef SOL_IP
     84 # define SOL_IP 0
     85 #endif
     86 #ifndef SOL_TCP
     87 # define SOL_TCP 6
     88 #endif
     89 #ifndef SOL_UDP
     90 # define SOL_UDP 17
     91 #endif
     92 #ifndef SOL_IPV6
     93 # define SOL_IPV6 41
     94 #endif
     95 #ifndef SOL_ICMPV6
     96 # define SOL_ICMPV6 58
     97 #endif
     98 #ifndef SOL_SCTP
     99 # define SOL_SCTP 132
    100 #endif
    101 #ifndef SOL_UDPLITE
    102 # define SOL_UDPLITE 136
    103 #endif
    104 #ifndef SOL_RAW
    105 # define SOL_RAW 255
    106 #endif
    107 #ifndef SOL_IPX
    108 # define SOL_IPX 256
    109 #endif
    110 #ifndef SOL_AX25
    111 # define SOL_AX25 257
    112 #endif
    113 #ifndef SOL_ATALK
    114 # define SOL_ATALK 258
    115 #endif
    116 #ifndef SOL_NETROM
    117 # define SOL_NETROM 259
    118 #endif
    119 #ifndef SOL_ROSE
    120 # define SOL_ROSE 260
    121 #endif
    122 #ifndef SOL_DECNET
    123 # define SOL_DECNET 261
    124 #endif
    125 #ifndef SOL_X25
    126 # define SOL_X25 262
    127 #endif
    128 #ifndef SOL_PACKET
    129 # define SOL_PACKET 263
    130 #endif
    131 #ifndef SOL_ATM
    132 # define SOL_ATM 264
    133 #endif
    134 #ifndef SOL_AAL
    135 # define SOL_AAL 265
    136 #endif
    137 #ifndef SOL_IRDA
    138 # define SOL_IRDA 266
    139 #endif
    140 #ifndef SOL_NETBEUI
    141 # define SOL_NETBEUI 267
    142 #endif
    143 #ifndef SOL_LLC
    144 # define SOL_LLC 268
    145 #endif
    146 #ifndef SOL_DCCP
    147 # define SOL_DCCP 269
    148 #endif
    149 #ifndef SOL_NETLINK
    150 # define SOL_NETLINK 270
    151 #endif
    152 #ifndef SOL_TIPC
    153 # define SOL_TIPC 271
    154 #endif
    155 #ifndef SOL_RXRPC
    156 # define SOL_RXRPC 272
    157 #endif
    158 #ifndef SOL_PPPOL2TP
    159 # define SOL_PPPOL2TP 273
    160 #endif
    161 #ifndef SOL_BLUETOOTH
    162 # define SOL_BLUETOOTH 274
    163 #endif
    164 #ifndef SOL_PNPIPE
    165 # define SOL_PNPIPE 275
    166 #endif
    167 #ifndef SOL_RDS
    168 # define SOL_RDS 276
    169 #endif
    170 #ifndef SOL_IUCV
    171 # define SOL_IUCV 277
    172 #endif
    173 #ifndef SOL_CAIF
    174 # define SOL_CAIF 278
    175 #endif
    176 #ifndef SOL_ALG
    177 # define SOL_ALG 279
    178 #endif
    179 #ifndef SOL_NFC
    180 # define SOL_NFC 280
    181 #endif
    182 #include "xlat/socketlayers.h"
    183 
    184 #include "xlat/inet_protocols.h"
    185 
    186 #ifdef PF_NETLINK
    187 # if !defined NETLINK_SOCK_DIAG && defined NETLINK_INET_DIAG
    188 #  define NETLINK_SOCK_DIAG NETLINK_INET_DIAG
    189 # endif
    190 # include "xlat/netlink_protocols.h"
    191 #endif
    192 
    193 #if defined(HAVE_BLUETOOTH_BLUETOOTH_H)
    194 # include "xlat/bt_protocols.h"
    195 #endif
    196 
    197 #include "xlat/msg_flags.h"
    198 
    199 #if defined(AF_PACKET) /* from e.g. linux/if_packet.h */
    200 # include "xlat/af_packet_types.h"
    201 #endif
    202 
    203 void
    204 printsock(struct tcb *tcp, long addr, int addrlen)
    205 {
    206 	union {
    207 		char pad[128];
    208 		struct sockaddr sa;
    209 		struct sockaddr_in sin;
    210 		struct sockaddr_un sau;
    211 #ifdef HAVE_INET_NTOP
    212 		struct sockaddr_in6 sa6;
    213 #endif
    214 #if defined(AF_IPX)
    215 		struct sockaddr_ipx sipx;
    216 #endif
    217 #ifdef AF_PACKET
    218 		struct sockaddr_ll ll;
    219 #endif
    220 #ifdef AF_NETLINK
    221 		struct sockaddr_nl nl;
    222 #endif
    223 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
    224 		struct sockaddr_hci hci;
    225 		struct sockaddr_l2 l2;
    226 		struct sockaddr_rc rc;
    227 		struct sockaddr_sco sco;
    228 #endif
    229 	} addrbuf;
    230 	char string_addr[100];
    231 
    232 	if (addr == 0) {
    233 		tprints("NULL");
    234 		return;
    235 	}
    236 	if (!verbose(tcp)) {
    237 		tprintf("%#lx", addr);
    238 		return;
    239 	}
    240 
    241 	if (addrlen < 2 || addrlen > (int) sizeof(addrbuf))
    242 		addrlen = sizeof(addrbuf);
    243 
    244 	memset(&addrbuf, 0, sizeof(addrbuf));
    245 	if (umoven(tcp, addr, addrlen, addrbuf.pad) < 0) {
    246 		tprints("{...}");
    247 		return;
    248 	}
    249 	addrbuf.pad[sizeof(addrbuf.pad) - 1] = '\0';
    250 
    251 	tprints("{sa_family=");
    252 	printxval(addrfams, addrbuf.sa.sa_family, "AF_???");
    253 	tprints(", ");
    254 
    255 	switch (addrbuf.sa.sa_family) {
    256 	case AF_UNIX:
    257 		if (addrlen == 2) {
    258 			tprints("NULL");
    259 		} else if (addrbuf.sau.sun_path[0]) {
    260 			tprints("sun_path=");
    261 			print_quoted_string(addrbuf.sau.sun_path,
    262 					    sizeof(addrbuf.sau.sun_path) + 1,
    263 					    QUOTE_0_TERMINATED);
    264 		} else {
    265 			tprints("sun_path=@");
    266 			print_quoted_string(addrbuf.sau.sun_path + 1,
    267 					    sizeof(addrbuf.sau.sun_path),
    268 					    QUOTE_0_TERMINATED);
    269 		}
    270 		break;
    271 	case AF_INET:
    272 		tprintf("sin_port=htons(%u), sin_addr=inet_addr(\"%s\")",
    273 			ntohs(addrbuf.sin.sin_port), inet_ntoa(addrbuf.sin.sin_addr));
    274 		break;
    275 #ifdef HAVE_INET_NTOP
    276 	case AF_INET6:
    277 		inet_ntop(AF_INET6, &addrbuf.sa6.sin6_addr, string_addr, sizeof(string_addr));
    278 		tprintf("sin6_port=htons(%u), inet_pton(AF_INET6, \"%s\", &sin6_addr), sin6_flowinfo=%u",
    279 				ntohs(addrbuf.sa6.sin6_port), string_addr,
    280 				addrbuf.sa6.sin6_flowinfo);
    281 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
    282 		{
    283 #if defined(HAVE_IF_INDEXTONAME) && defined(IN6_IS_ADDR_LINKLOCAL) && defined(IN6_IS_ADDR_MC_LINKLOCAL)
    284 			int numericscope = 0;
    285 			if (IN6_IS_ADDR_LINKLOCAL(&addrbuf.sa6.sin6_addr)
    286 			    || IN6_IS_ADDR_MC_LINKLOCAL(&addrbuf.sa6.sin6_addr)) {
    287 				char scopebuf[IFNAMSIZ + 1];
    288 
    289 				if (if_indextoname(addrbuf.sa6.sin6_scope_id, scopebuf) == NULL)
    290 					numericscope++;
    291 				else {
    292 					tprints(", sin6_scope_id=if_nametoindex(");
    293 					print_quoted_string(scopebuf,
    294 							    sizeof(scopebuf),
    295 							    QUOTE_0_TERMINATED);
    296 					tprints(")");
    297 				}
    298 			} else
    299 				numericscope++;
    300 
    301 			if (numericscope)
    302 #endif
    303 				tprintf(", sin6_scope_id=%u", addrbuf.sa6.sin6_scope_id);
    304 		}
    305 #endif
    306 		break;
    307 #endif
    308 #if defined(AF_IPX)
    309 	case AF_IPX:
    310 		{
    311 			int i;
    312 			tprintf("sipx_port=htons(%u), ",
    313 					ntohs(addrbuf.sipx.sipx_port));
    314 			/* Yes, I know, this does not look too
    315 			 * strace-ish, but otherwise the IPX
    316 			 * addresses just look monstrous...
    317 			 * Anyways, feel free if you don't like
    318 			 * this way.. :)
    319 			 */
    320 			tprintf("%08lx:", (unsigned long)ntohl(addrbuf.sipx.sipx_network));
    321 			for (i = 0; i < IPX_NODE_LEN; i++)
    322 				tprintf("%02x", addrbuf.sipx.sipx_node[i]);
    323 			tprintf("/[%02x]", addrbuf.sipx.sipx_type);
    324 		}
    325 		break;
    326 #endif /* AF_IPX */
    327 #ifdef AF_PACKET
    328 	case AF_PACKET:
    329 		{
    330 			int i;
    331 			tprintf("proto=%#04x, if%d, pkttype=",
    332 					ntohs(addrbuf.ll.sll_protocol),
    333 					addrbuf.ll.sll_ifindex);
    334 			printxval(af_packet_types, addrbuf.ll.sll_pkttype, "PACKET_???");
    335 			tprintf(", addr(%d)={%d, ",
    336 					addrbuf.ll.sll_halen,
    337 					addrbuf.ll.sll_hatype);
    338 			for (i = 0; i < addrbuf.ll.sll_halen; i++)
    339 				tprintf("%02x", addrbuf.ll.sll_addr[i]);
    340 		}
    341 		break;
    342 
    343 #endif /* AF_PACKET */
    344 #ifdef AF_NETLINK
    345 	case AF_NETLINK:
    346 		tprintf("pid=%d, groups=%08x", addrbuf.nl.nl_pid, addrbuf.nl.nl_groups);
    347 		break;
    348 #endif /* AF_NETLINK */
    349 #if defined(AF_BLUETOOTH) && defined(HAVE_BLUETOOTH_BLUETOOTH_H)
    350 	case AF_BLUETOOTH:
    351 		tprintf("{sco_bdaddr=%02X:%02X:%02X:%02X:%02X:%02X} or "
    352 			"{rc_bdaddr=%02X:%02X:%02X:%02X:%02X:%02X, rc_channel=%d} or "
    353 			"{l2_psm=htobs(%d), l2_bdaddr=%02X:%02X:%02X:%02X:%02X:%02X, l2_cid=htobs(%d)} or "
    354 			"{hci_dev=htobs(%d)}",
    355 			addrbuf.sco.sco_bdaddr.b[0], addrbuf.sco.sco_bdaddr.b[1],
    356 			addrbuf.sco.sco_bdaddr.b[2], addrbuf.sco.sco_bdaddr.b[3],
    357 			addrbuf.sco.sco_bdaddr.b[4], addrbuf.sco.sco_bdaddr.b[5],
    358 			addrbuf.rc.rc_bdaddr.b[0], addrbuf.rc.rc_bdaddr.b[1],
    359 			addrbuf.rc.rc_bdaddr.b[2], addrbuf.rc.rc_bdaddr.b[3],
    360 			addrbuf.rc.rc_bdaddr.b[4], addrbuf.rc.rc_bdaddr.b[5],
    361 			addrbuf.rc.rc_channel,
    362 			btohs(addrbuf.l2.l2_psm), addrbuf.l2.l2_bdaddr.b[0],
    363 			addrbuf.l2.l2_bdaddr.b[1], addrbuf.l2.l2_bdaddr.b[2],
    364 			addrbuf.l2.l2_bdaddr.b[3], addrbuf.l2.l2_bdaddr.b[4],
    365 			addrbuf.l2.l2_bdaddr.b[5], btohs(addrbuf.l2.l2_cid),
    366 			btohs(addrbuf.hci.hci_dev));
    367 		break;
    368 #endif /* AF_BLUETOOTH && HAVE_BLUETOOTH_BLUETOOTH_H */
    369 	/* AF_AX25 AF_APPLETALK AF_NETROM AF_BRIDGE AF_AAL5
    370 	AF_X25 AF_ROSE etc. still need to be done */
    371 
    372 	default:
    373 		tprints("sa_data=");
    374 		print_quoted_string(addrbuf.sa.sa_data,
    375 				    sizeof(addrbuf.sa.sa_data), 0);
    376 		break;
    377 	}
    378 	tprints("}");
    379 }
    380 
    381 #if HAVE_SENDMSG
    382 # ifndef SCM_SECURITY
    383 #  define SCM_SECURITY 0x03
    384 # endif
    385 # include "xlat/scmvals.h"
    386 
    387 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
    388 struct cmsghdr32 {
    389 	uint32_t cmsg_len;
    390 	int cmsg_level;
    391 	int cmsg_type;
    392 };
    393 #endif
    394 
    395 typedef union {
    396 	char *ptr;
    397 	struct cmsghdr *cmsg;
    398 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
    399 	struct cmsghdr32 *cmsg32;
    400 #endif
    401 } union_cmsghdr;
    402 
    403 static bool
    404 print_scm_rights(struct tcb *tcp, size_t cmsg_size, char *ptr, size_t cmsg_len)
    405 {
    406 	if (cmsg_size + sizeof(int) > cmsg_len)
    407 		return false;
    408 
    409 	int *fds = (int *) (ptr + cmsg_size);
    410 	bool seen = false;
    411 
    412 	tprints(", [");
    413 	while ((char *) fds < (ptr + cmsg_len)) {
    414 		if (seen)
    415 			tprints(", ");
    416 		else
    417 			seen = true;
    418 		printfd(tcp, *fds++);
    419 	}
    420 	tprints("]}");
    421 	return true;
    422 }
    423 
    424 static bool
    425 print_scm_creds(struct tcb *tcp, size_t cmsg_size, char *ptr, size_t cmsg_len)
    426 {
    427 	if (cmsg_size + sizeof(struct ucred) > cmsg_len)
    428 		return false;
    429 
    430 	const struct ucred *uc = (void *) (ptr + cmsg_size);
    431 
    432 	tprintf(", {pid=%u, uid=%u, gid=%u}}",
    433 		(unsigned) uc->pid, (unsigned) uc->uid, (unsigned) uc->gid);
    434 	return true;
    435 }
    436 
    437 static bool
    438 print_scm_security(struct tcb *tcp, size_t cmsg_size, char *ptr, size_t cmsg_len)
    439 {
    440 	if (cmsg_size + sizeof(char) > cmsg_len)
    441 		return false;
    442 
    443 	const char *label = (const char *) (ptr + cmsg_size);
    444 	const size_t label_len = cmsg_len - cmsg_size;
    445 
    446 	tprints(", ");
    447 	print_quoted_string(label, label_len, 0);
    448 	tprints("}");
    449 
    450 	return true;
    451 }
    452 
    453 static void
    454 printcmsghdr(struct tcb *tcp, unsigned long addr, size_t len)
    455 {
    456 	const size_t cmsg_size =
    457 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
    458 		(current_wordsize < sizeof(long)) ? sizeof(struct cmsghdr32) :
    459 #endif
    460 			sizeof(struct cmsghdr);
    461 
    462 	char *buf = len < cmsg_size ? NULL : malloc(len);
    463 	if (!buf || umoven(tcp, addr, len, buf) < 0) {
    464 		tprintf(", msg_control=%#lx", addr);
    465 		free(buf);
    466 		return;
    467 	}
    468 
    469 	union_cmsghdr u = { .ptr = buf };
    470 
    471 	tprints(", [");
    472 	while (len >= cmsg_size) {
    473 		size_t cmsg_len =
    474 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
    475 			(current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_len :
    476 #endif
    477 				u.cmsg->cmsg_len;
    478 		int cmsg_level =
    479 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
    480 			(current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_level :
    481 #endif
    482 				u.cmsg->cmsg_level;
    483 		int cmsg_type =
    484 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
    485 			(current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_type :
    486 #endif
    487 				u.cmsg->cmsg_type;
    488 
    489 		if (u.ptr != buf)
    490 			tprints(", ");
    491 		tprintf("{cmsg_len=%lu, cmsg_level=", (unsigned long) cmsg_len);
    492 		printxval(socketlayers, cmsg_level, "SOL_???");
    493 		tprints(", cmsg_type=");
    494 
    495 		if (cmsg_len > len)
    496 			cmsg_len = len;
    497 
    498 		if (cmsg_level == SOL_SOCKET) {
    499 			printxval(scmvals, cmsg_type, "SCM_???");
    500 			switch (cmsg_type) {
    501 			case SCM_RIGHTS:
    502 				if (print_scm_rights(tcp, cmsg_size, u.ptr, cmsg_len))
    503 					goto next_cmsg;
    504 				break;
    505 			case SCM_CREDENTIALS:
    506 				if (print_scm_creds(tcp, cmsg_size, u.ptr, cmsg_len))
    507 					goto next_cmsg;
    508 				break;
    509 			case SCM_SECURITY:
    510 				if (print_scm_security(tcp, cmsg_size, u.ptr, cmsg_len))
    511 					goto next_cmsg;
    512 				break;
    513 			}
    514 		} else {
    515 			tprintf("%u", cmsg_type);
    516 		}
    517 		tprints(", ...}");
    518 next_cmsg:
    519 		if (cmsg_len < cmsg_size) {
    520 			len -= cmsg_size;
    521 			break;
    522 		}
    523 		cmsg_len = (cmsg_len + current_wordsize - 1) &
    524 			(size_t) ~(current_wordsize - 1);
    525 		if (cmsg_len >= len) {
    526 			len = 0;
    527 			break;
    528 		}
    529 		u.ptr += cmsg_len;
    530 		len -= cmsg_len;
    531 	}
    532 	if (len)
    533 		tprints(", ...");
    534 	tprints("]");
    535 	free(buf);
    536 }
    537 
    538 static void
    539 do_msghdr(struct tcb *tcp, struct msghdr *msg, unsigned long data_size)
    540 {
    541 	tprintf("{msg_name(%d)=", msg->msg_namelen);
    542 	printsock(tcp, (long)msg->msg_name, msg->msg_namelen);
    543 
    544 	tprintf(", msg_iov(%lu)=", (unsigned long)msg->msg_iovlen);
    545 	tprint_iov_upto(tcp, (unsigned long)msg->msg_iovlen,
    546 		   (unsigned long)msg->msg_iov, 1, data_size);
    547 
    548 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
    549 	tprintf(", msg_controllen=%lu", (unsigned long)msg->msg_controllen);
    550 	if (msg->msg_controllen)
    551 		printcmsghdr(tcp, (unsigned long) msg->msg_control,
    552 			     msg->msg_controllen);
    553 	tprints(", msg_flags=");
    554 	printflags(msg_flags, msg->msg_flags, "MSG_???");
    555 #else /* !HAVE_STRUCT_MSGHDR_MSG_CONTROL */
    556 	tprintf("msg_accrights=%#lx, msg_accrightslen=%u",
    557 		(unsigned long) msg->msg_accrights, msg->msg_accrightslen);
    558 #endif /* !HAVE_STRUCT_MSGHDR_MSG_CONTROL */
    559 	tprints("}");
    560 }
    561 
    562 struct msghdr32 {
    563 	uint32_t /* void* */    msg_name;
    564 	uint32_t /* socklen_t */msg_namelen;
    565 	uint32_t /* iovec* */   msg_iov;
    566 	uint32_t /* size_t */   msg_iovlen;
    567 	uint32_t /* void* */    msg_control;
    568 	uint32_t /* size_t */   msg_controllen;
    569 	uint32_t /* int */      msg_flags;
    570 };
    571 struct mmsghdr32 {
    572 	struct msghdr32         msg_hdr;
    573 	uint32_t /* unsigned */ msg_len;
    574 };
    575 
    576 #ifndef HAVE_STRUCT_MMSGHDR
    577 struct mmsghdr {
    578 	struct msghdr msg_hdr;
    579 	unsigned msg_len;
    580 };
    581 #endif
    582 
    583 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
    584 static void
    585 copy_from_msghdr32(struct msghdr *to_msg, struct msghdr32 *from_msg32)
    586 {
    587 	to_msg->msg_name       = (void*)(long)from_msg32->msg_name;
    588 	to_msg->msg_namelen    =              from_msg32->msg_namelen;
    589 	to_msg->msg_iov        = (void*)(long)from_msg32->msg_iov;
    590 	to_msg->msg_iovlen     =              from_msg32->msg_iovlen;
    591 	to_msg->msg_control    = (void*)(long)from_msg32->msg_control;
    592 	to_msg->msg_controllen =              from_msg32->msg_controllen;
    593 	to_msg->msg_flags      =              from_msg32->msg_flags;
    594 }
    595 #endif
    596 
    597 static bool
    598 extractmsghdr(struct tcb *tcp, long addr, struct msghdr *msg)
    599 {
    600 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
    601 	if (current_wordsize == 4) {
    602 		struct msghdr32 msg32;
    603 
    604 		if (umove(tcp, addr, &msg32) < 0)
    605 			return false;
    606 		copy_from_msghdr32(msg, &msg32);
    607 	} else
    608 #endif
    609 	if (umove(tcp, addr, msg) < 0)
    610 		return false;
    611 	return true;
    612 }
    613 
    614 static bool
    615 extractmmsghdr(struct tcb *tcp, long addr, unsigned int idx, struct mmsghdr *mmsg)
    616 {
    617 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
    618 	if (current_wordsize == 4) {
    619 		struct mmsghdr32 mmsg32;
    620 
    621 		addr += sizeof(struct mmsghdr32) * idx;
    622 		if (umove(tcp, addr, &mmsg32) < 0)
    623 			return false;
    624 
    625 		copy_from_msghdr32(&mmsg->msg_hdr, &mmsg32.msg_hdr);
    626 		mmsg->msg_len = mmsg32.msg_len;
    627 	} else
    628 #endif
    629 	{
    630 		addr += sizeof(*mmsg) * idx;
    631 		if (umove(tcp, addr, mmsg) < 0)
    632 			return false;
    633 	}
    634 	return true;
    635 }
    636 
    637 static void
    638 printmsghdr(struct tcb *tcp, long addr, unsigned long data_size)
    639 {
    640 	struct msghdr msg;
    641 
    642 	if (verbose(tcp) && extractmsghdr(tcp, addr, &msg))
    643 		do_msghdr(tcp, &msg, data_size);
    644 	else
    645 		tprintf("%#lx", addr);
    646 }
    647 
    648 void
    649 dumpiov_in_msghdr(struct tcb *tcp, long addr)
    650 {
    651 	struct msghdr msg;
    652 
    653 	if (extractmsghdr(tcp, addr, &msg))
    654 		dumpiov(tcp, msg.msg_iovlen, (long)msg.msg_iov);
    655 }
    656 
    657 static void
    658 printmmsghdr(struct tcb *tcp, long addr, unsigned int idx, unsigned long msg_len)
    659 {
    660 	struct mmsghdr mmsg;
    661 
    662 	if (extractmmsghdr(tcp, addr, idx, &mmsg)) {
    663 		tprints("{");
    664 		do_msghdr(tcp, &mmsg.msg_hdr, msg_len ? msg_len : mmsg.msg_len);
    665 		tprintf(", %u}", mmsg.msg_len);
    666 	}
    667 	else
    668 		tprintf("%#lx", addr);
    669 }
    670 
    671 static void
    672 decode_mmsg(struct tcb *tcp, unsigned long msg_len)
    673 {
    674 	/* mmsgvec */
    675 	if (syserror(tcp)) {
    676 		tprintf("%#lx", tcp->u_arg[1]);
    677 	} else {
    678 		unsigned int len = tcp->u_rval;
    679 		unsigned int i;
    680 
    681 		tprints("{");
    682 		for (i = 0; i < len; ++i) {
    683 			if (i)
    684 				tprints(", ");
    685 			printmmsghdr(tcp, tcp->u_arg[1], i, msg_len);
    686 		}
    687 		tprints("}");
    688 	}
    689 	/* vlen */
    690 	tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
    691 	/* flags */
    692 	printflags(msg_flags, tcp->u_arg[3], "MSG_???");
    693 }
    694 
    695 void
    696 dumpiov_in_mmsghdr(struct tcb *tcp, long addr)
    697 {
    698 	unsigned int len = tcp->u_rval;
    699 	unsigned int i;
    700 	struct mmsghdr mmsg;
    701 
    702 	for (i = 0; i < len; ++i) {
    703 		if (extractmmsghdr(tcp, addr, i, &mmsg)) {
    704 			tprintf(" = %lu buffers in vector %u\n",
    705 				(unsigned long)mmsg.msg_hdr.msg_iovlen, i);
    706 			dumpiov(tcp, mmsg.msg_hdr.msg_iovlen,
    707 				(long)mmsg.msg_hdr.msg_iov);
    708 		}
    709 	}
    710 }
    711 #endif /* HAVE_SENDMSG */
    712 
    713 /*
    714  * low bits of the socket type define real socket type,
    715  * other bits are socket type flags.
    716  */
    717 static void
    718 tprint_sock_type(int flags)
    719 {
    720 	const char *str = xlookup(socktypes, flags & SOCK_TYPE_MASK);
    721 
    722 	if (str) {
    723 		tprints(str);
    724 		flags &= ~SOCK_TYPE_MASK;
    725 		if (!flags)
    726 			return;
    727 		tprints("|");
    728 	}
    729 	printflags(sock_type_flags, flags, "SOCK_???");
    730 }
    731 
    732 SYS_FUNC(socket)
    733 {
    734 	if (entering(tcp)) {
    735 		printxval(domains, tcp->u_arg[0], "PF_???");
    736 		tprints(", ");
    737 		tprint_sock_type(tcp->u_arg[1]);
    738 		tprints(", ");
    739 		switch (tcp->u_arg[0]) {
    740 		case PF_INET:
    741 #ifdef PF_INET6
    742 		case PF_INET6:
    743 #endif
    744 			printxval(inet_protocols, tcp->u_arg[2], "IPPROTO_???");
    745 			break;
    746 #ifdef PF_IPX
    747 		case PF_IPX:
    748 			/* BTW: I don't believe this.. */
    749 			tprints("[");
    750 			printxval(domains, tcp->u_arg[2], "PF_???");
    751 			tprints("]");
    752 			break;
    753 #endif /* PF_IPX */
    754 #ifdef PF_NETLINK
    755 		case PF_NETLINK:
    756 			printxval(netlink_protocols, tcp->u_arg[2], "NETLINK_???");
    757 			break;
    758 #endif
    759 #if defined(PF_BLUETOOTH) && defined(HAVE_BLUETOOTH_BLUETOOTH_H)
    760 		case PF_BLUETOOTH:
    761 			printxval(bt_protocols, tcp->u_arg[2], "BTPROTO_???");
    762 			break;
    763 #endif
    764 		default:
    765 			tprintf("%lu", tcp->u_arg[2]);
    766 			break;
    767 		}
    768 	}
    769 	return 0;
    770 }
    771 
    772 SYS_FUNC(bind)
    773 {
    774 	if (entering(tcp)) {
    775 		printfd(tcp, tcp->u_arg[0]);
    776 		tprints(", ");
    777 		printsock(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    778 		tprintf(", %lu", tcp->u_arg[2]);
    779 	}
    780 	return 0;
    781 }
    782 
    783 SYS_FUNC(connect)
    784 {
    785 	return sys_bind(tcp);
    786 }
    787 
    788 SYS_FUNC(listen)
    789 {
    790 	if (entering(tcp)) {
    791 		printfd(tcp, tcp->u_arg[0]);
    792 		tprints(", ");
    793 		tprintf("%lu", tcp->u_arg[1]);
    794 	}
    795 	return 0;
    796 }
    797 
    798 static int
    799 do_sockname(struct tcb *tcp, int flags_arg)
    800 {
    801 	if (entering(tcp)) {
    802 		printfd(tcp, tcp->u_arg[0]);
    803 		tprints(", ");
    804 		return 0;
    805 	}
    806 	if (!tcp->u_arg[2])
    807 		tprintf("%#lx, NULL", tcp->u_arg[1]);
    808 	else {
    809 		int len;
    810 		if (tcp->u_arg[1] == 0 || syserror(tcp)
    811 		    || umove(tcp, tcp->u_arg[2], &len) < 0) {
    812 			tprintf("%#lx", tcp->u_arg[1]);
    813 		} else {
    814 			printsock(tcp, tcp->u_arg[1], len);
    815 		}
    816 		tprints(", ");
    817 		printnum_int(tcp, tcp->u_arg[2], "%u");
    818 	}
    819 	if (flags_arg >= 0) {
    820 		tprints(", ");
    821 		printflags(sock_type_flags, tcp->u_arg[flags_arg],
    822 			   "SOCK_???");
    823 	}
    824 	return 0;
    825 }
    826 
    827 SYS_FUNC(accept)
    828 {
    829 	do_sockname(tcp, -1);
    830 	return RVAL_FD;
    831 }
    832 
    833 SYS_FUNC(accept4)
    834 {
    835 	do_sockname(tcp, 3);
    836 	return RVAL_FD;
    837 }
    838 
    839 SYS_FUNC(send)
    840 {
    841 	if (entering(tcp)) {
    842 		printfd(tcp, tcp->u_arg[0]);
    843 		tprints(", ");
    844 		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    845 		tprintf(", %lu, ", tcp->u_arg[2]);
    846 		/* flags */
    847 		printflags(msg_flags, tcp->u_arg[3], "MSG_???");
    848 	}
    849 	return 0;
    850 }
    851 
    852 SYS_FUNC(sendto)
    853 {
    854 	if (entering(tcp)) {
    855 		printfd(tcp, tcp->u_arg[0]);
    856 		tprints(", ");
    857 		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
    858 		tprintf(", %lu, ", tcp->u_arg[2]);
    859 		/* flags */
    860 		printflags(msg_flags, tcp->u_arg[3], "MSG_???");
    861 		/* to address */
    862 		tprints(", ");
    863 		printsock(tcp, tcp->u_arg[4], tcp->u_arg[5]);
    864 		/* to length */
    865 		tprintf(", %lu", tcp->u_arg[5]);
    866 	}
    867 	return 0;
    868 }
    869 
    870 #ifdef HAVE_SENDMSG
    871 
    872 SYS_FUNC(sendmsg)
    873 {
    874 	if (entering(tcp)) {
    875 		printfd(tcp, tcp->u_arg[0]);
    876 		tprints(", ");
    877 		printmsghdr(tcp, tcp->u_arg[1], (unsigned long) -1L);
    878 		/* flags */
    879 		tprints(", ");
    880 		printflags(msg_flags, tcp->u_arg[2], "MSG_???");
    881 	}
    882 	return 0;
    883 }
    884 
    885 SYS_FUNC(sendmmsg)
    886 {
    887 	if (entering(tcp)) {
    888 		/* sockfd */
    889 		printfd(tcp, tcp->u_arg[0]);
    890 		tprints(", ");
    891 		if (!verbose(tcp)) {
    892 			tprintf("%#lx, %u, ",
    893 				tcp->u_arg[1], (unsigned int) tcp->u_arg[2]);
    894 			printflags(msg_flags, tcp->u_arg[3], "MSG_???");
    895 		}
    896 	} else {
    897 		if (verbose(tcp))
    898 			decode_mmsg(tcp, (unsigned long) -1L);
    899 	}
    900 	return 0;
    901 }
    902 
    903 #endif /* HAVE_SENDMSG */
    904 
    905 SYS_FUNC(recv)
    906 {
    907 	if (entering(tcp)) {
    908 		printfd(tcp, tcp->u_arg[0]);
    909 		tprints(", ");
    910 	} else {
    911 		if (syserror(tcp))
    912 			tprintf("%#lx", tcp->u_arg[1]);
    913 		else
    914 			printstr(tcp, tcp->u_arg[1], tcp->u_rval);
    915 
    916 		tprintf(", %lu, ", tcp->u_arg[2]);
    917 		printflags(msg_flags, tcp->u_arg[3], "MSG_???");
    918 	}
    919 	return 0;
    920 }
    921 
    922 SYS_FUNC(recvfrom)
    923 {
    924 	int fromlen;
    925 
    926 	if (entering(tcp)) {
    927 		printfd(tcp, tcp->u_arg[0]);
    928 		tprints(", ");
    929 	} else {
    930 		if (syserror(tcp)) {
    931 			tprintf("%#lx, %lu, %lu, %#lx, %#lx",
    932 				tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3],
    933 				tcp->u_arg[4], tcp->u_arg[5]);
    934 			return 0;
    935 		}
    936 		/* buf */
    937 		printstr(tcp, tcp->u_arg[1], tcp->u_rval);
    938 		/* len */
    939 		tprintf(", %lu, ", tcp->u_arg[2]);
    940 		/* flags */
    941 		printflags(msg_flags, tcp->u_arg[3], "MSG_???");
    942 		/* from address, len */
    943 		if (!tcp->u_arg[4] || !tcp->u_arg[5]) {
    944 			if (tcp->u_arg[4] == 0)
    945 				tprints(", NULL");
    946 			else
    947 				tprintf(", %#lx", tcp->u_arg[4]);
    948 			if (tcp->u_arg[5] == 0)
    949 				tprints(", NULL");
    950 			else
    951 				tprintf(", %#lx", tcp->u_arg[5]);
    952 			return 0;
    953 		}
    954 		if (umove(tcp, tcp->u_arg[5], &fromlen) < 0) {
    955 			tprints(", {...}, [?]");
    956 			return 0;
    957 		}
    958 		tprints(", ");
    959 		printsock(tcp, tcp->u_arg[4], tcp->u_arg[5]);
    960 		/* from length */
    961 		tprintf(", [%u]", fromlen);
    962 	}
    963 	return 0;
    964 }
    965 
    966 #ifdef HAVE_SENDMSG
    967 
    968 SYS_FUNC(recvmsg)
    969 {
    970 	if (entering(tcp)) {
    971 		printfd(tcp, tcp->u_arg[0]);
    972 		tprints(", ");
    973 	} else {
    974 		if (syserror(tcp))
    975 			tprintf("%#lx", tcp->u_arg[1]);
    976 		else
    977 			printmsghdr(tcp, tcp->u_arg[1], tcp->u_rval);
    978 		/* flags */
    979 		tprints(", ");
    980 		printflags(msg_flags, tcp->u_arg[2], "MSG_???");
    981 	}
    982 	return 0;
    983 }
    984 
    985 SYS_FUNC(recvmmsg)
    986 {
    987 	/* +5 chars are for "left " prefix */
    988 	static char str[5 + TIMESPEC_TEXT_BUFSIZE];
    989 
    990 	if (entering(tcp)) {
    991 		printfd(tcp, tcp->u_arg[0]);
    992 		tprints(", ");
    993 		if (verbose(tcp)) {
    994 			sprint_timespec(str, tcp, tcp->u_arg[4]);
    995 			/* Abusing tcp->auxstr as temp storage.
    996 			 * Will be used and freed on syscall exit.
    997 			 */
    998 			tcp->auxstr = strdup(str);
    999 		} else {
   1000 			tprintf("%#lx, %ld, ", tcp->u_arg[1], tcp->u_arg[2]);
   1001 			printflags(msg_flags, tcp->u_arg[3], "MSG_???");
   1002 			tprints(", ");
   1003 			print_timespec(tcp, tcp->u_arg[4]);
   1004 		}
   1005 		return 0;
   1006 	} else {
   1007 		if (verbose(tcp)) {
   1008 			decode_mmsg(tcp, 0);
   1009 			/* timeout on entrance */
   1010 			tprintf(", %s", tcp->auxstr ? tcp->auxstr : "{...}");
   1011 			free((void *) tcp->auxstr);
   1012 			tcp->auxstr = NULL;
   1013 		}
   1014 		if (syserror(tcp))
   1015 			return 0;
   1016 		if (tcp->u_rval == 0) {
   1017 			tcp->auxstr = "Timeout";
   1018 			return RVAL_STR;
   1019 		}
   1020 		if (!verbose(tcp))
   1021 			return 0;
   1022 		/* timeout on exit */
   1023 		sprint_timespec(stpcpy(str, "left "), tcp, tcp->u_arg[4]);
   1024 		tcp->auxstr = str;
   1025 		return RVAL_STR;
   1026 	}
   1027 }
   1028 
   1029 #endif /* HAVE_SENDMSG */
   1030 
   1031 #include "xlat/shutdown_modes.h"
   1032 
   1033 SYS_FUNC(shutdown)
   1034 {
   1035 	if (entering(tcp)) {
   1036 		printfd(tcp, tcp->u_arg[0]);
   1037 		tprints(", ");
   1038 		printxval(shutdown_modes, tcp->u_arg[1], "SHUT_???");
   1039 	}
   1040 	return 0;
   1041 }
   1042 
   1043 SYS_FUNC(getsockname)
   1044 {
   1045 	return do_sockname(tcp, -1);
   1046 }
   1047 
   1048 static int
   1049 do_pipe(struct tcb *tcp, int flags_arg)
   1050 {
   1051 	if (exiting(tcp)) {
   1052 		if (syserror(tcp)) {
   1053 			tprintf("%#lx", tcp->u_arg[0]);
   1054 		} else {
   1055 #ifdef HAVE_GETRVAL2
   1056 			if (flags_arg < 0) {
   1057 				tprintf("[%lu, %lu]", tcp->u_rval, getrval2(tcp));
   1058 			} else
   1059 #endif
   1060 			{
   1061 				int fds[2];
   1062 
   1063 				if (umove(tcp, tcp->u_arg[0], &fds) < 0)
   1064 					tprintf("%#lx", tcp->u_arg[0]);
   1065 				else
   1066 					tprintf("[%u, %u]", fds[0], fds[1]);
   1067 			}
   1068 		}
   1069 		if (flags_arg >= 0) {
   1070 			tprints(", ");
   1071 			printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
   1072 		}
   1073 	}
   1074 	return 0;
   1075 }
   1076 
   1077 SYS_FUNC(pipe)
   1078 {
   1079 	return do_pipe(tcp, -1);
   1080 }
   1081 
   1082 SYS_FUNC(pipe2)
   1083 {
   1084 	return do_pipe(tcp, 1);
   1085 }
   1086 
   1087 SYS_FUNC(socketpair)
   1088 {
   1089 	int fds[2];
   1090 
   1091 	if (entering(tcp)) {
   1092 		printxval(domains, tcp->u_arg[0], "PF_???");
   1093 		tprints(", ");
   1094 		tprint_sock_type(tcp->u_arg[1]);
   1095 		tprintf(", %lu", tcp->u_arg[2]);
   1096 	} else {
   1097 		if (syserror(tcp)) {
   1098 			tprintf(", %#lx", tcp->u_arg[3]);
   1099 			return 0;
   1100 		}
   1101 		if (umoven(tcp, tcp->u_arg[3], sizeof fds, fds) < 0)
   1102 			tprints(", [...]");
   1103 		else
   1104 			tprintf(", [%u, %u]", fds[0], fds[1]);
   1105 	}
   1106 	return 0;
   1107 }
   1108 
   1109 #include "xlat/sockoptions.h"
   1110 #include "xlat/sockipoptions.h"
   1111 #include "xlat/sockipv6options.h"
   1112 #include "xlat/sockipxoptions.h"
   1113 #include "xlat/sockrawoptions.h"
   1114 #include "xlat/sockpacketoptions.h"
   1115 #include "xlat/socksctpoptions.h"
   1116 #include "xlat/socktcpoptions.h"
   1117 
   1118 static void
   1119 print_sockopt_fd_level_name(struct tcb *tcp, int fd, int level, int name)
   1120 {
   1121 	printfd(tcp, fd);
   1122 	tprints(", ");
   1123 	printxval(socketlayers, level, "SOL_??");
   1124 	tprints(", ");
   1125 
   1126 	switch (level) {
   1127 	case SOL_SOCKET:
   1128 		printxval(sockoptions, name, "SO_???");
   1129 		break;
   1130 	case SOL_IP:
   1131 		printxval(sockipoptions, name, "IP_???");
   1132 		break;
   1133 	case SOL_IPV6:
   1134 		printxval(sockipv6options, name, "IPV6_???");
   1135 		break;
   1136 	case SOL_IPX:
   1137 		printxval(sockipxoptions, name, "IPX_???");
   1138 		break;
   1139 	case SOL_PACKET:
   1140 		printxval(sockpacketoptions, name, "PACKET_???");
   1141 		break;
   1142 	case SOL_TCP:
   1143 		printxval(socktcpoptions, name, "TCP_???");
   1144 		break;
   1145 	case SOL_SCTP:
   1146 		printxval(socksctpoptions, name, "SCTP_???");
   1147 		break;
   1148 	case SOL_RAW:
   1149 		printxval(sockrawoptions, name, "RAW_???");
   1150 		break;
   1151 
   1152 		/* Other SOL_* protocol levels still need work. */
   1153 
   1154 	default:
   1155 		tprintf("%u", name);
   1156 	}
   1157 
   1158 	tprints(", ");
   1159 }
   1160 
   1161 #ifdef SO_LINGER
   1162 static void
   1163 print_linger(struct tcb *tcp, long addr, int len)
   1164 {
   1165 	struct linger linger;
   1166 
   1167 	if (len != sizeof(linger) ||
   1168 	    umove(tcp, addr, &linger) < 0) {
   1169 		tprintf("%#lx", addr);
   1170 		return;
   1171 	}
   1172 
   1173 	tprintf("{onoff=%d, linger=%d}",
   1174 		linger.l_onoff,
   1175 		linger.l_linger);
   1176 }
   1177 #endif /* SO_LINGER */
   1178 
   1179 #ifdef SO_PEERCRED
   1180 static void
   1181 print_ucred(struct tcb *tcp, long addr, int len)
   1182 {
   1183 	struct ucred uc;
   1184 
   1185 	if (len != sizeof(uc) ||
   1186 	    umove(tcp, addr, &uc) < 0) {
   1187 		tprintf("%#lx", addr);
   1188 	} else {
   1189 		tprintf("{pid=%u, uid=%u, gid=%u}",
   1190 			(unsigned) uc.pid,
   1191 			(unsigned) uc.uid,
   1192 			(unsigned) uc.gid);
   1193 	}
   1194 }
   1195 #endif /* SO_PEERCRED */
   1196 
   1197 #ifdef PACKET_STATISTICS
   1198 static void
   1199 print_tpacket_stats(struct tcb *tcp, long addr, int len)
   1200 {
   1201 	struct tpacket_stats stats;
   1202 
   1203 	if (len != sizeof(stats) ||
   1204 	    umove(tcp, addr, &stats) < 0) {
   1205 		tprintf("%#lx", addr);
   1206 	} else {
   1207 		tprintf("{packets=%u, drops=%u}",
   1208 			stats.tp_packets,
   1209 			stats.tp_drops);
   1210 	}
   1211 }
   1212 #endif /* PACKET_STATISTICS */
   1213 
   1214 #ifdef ICMP_FILTER
   1215 # include "xlat/icmpfilterflags.h"
   1216 
   1217 static void
   1218 print_icmp_filter(struct tcb *tcp, long addr, int len)
   1219 {
   1220 	struct icmp_filter	filter;
   1221 
   1222 	if (len != sizeof(filter) ||
   1223 	    umove(tcp, addr, &filter) < 0) {
   1224 		tprintf("%#lx", addr);
   1225 		return;
   1226 	}
   1227 
   1228 	tprints("~(");
   1229 	printflags(icmpfilterflags, ~filter.data, "ICMP_???");
   1230 	tprints(")");
   1231 }
   1232 #endif /* ICMP_FILTER */
   1233 
   1234 static void
   1235 print_getsockopt(struct tcb *tcp, int level, int name, long addr, int len)
   1236 {
   1237 	if (addr && verbose(tcp))
   1238 	switch (level) {
   1239 	case SOL_SOCKET:
   1240 		switch (name) {
   1241 #ifdef SO_LINGER
   1242 		case SO_LINGER:
   1243 			print_linger(tcp, addr, len);
   1244 			goto done;
   1245 #endif
   1246 #ifdef SO_PEERCRED
   1247 		case SO_PEERCRED:
   1248 			print_ucred(tcp, addr, len);
   1249 			goto done;
   1250 #endif
   1251 		}
   1252 		break;
   1253 
   1254 	case SOL_PACKET:
   1255 		switch (name) {
   1256 #ifdef PACKET_STATISTICS
   1257 		case PACKET_STATISTICS:
   1258 			print_tpacket_stats(tcp, addr, len);
   1259 			goto done;
   1260 #endif
   1261 		}
   1262 		break;
   1263 
   1264 	case SOL_RAW:
   1265 		switch (name) {
   1266 #ifdef ICMP_FILTER
   1267 		case ICMP_FILTER:
   1268 			print_icmp_filter(tcp, addr, len);
   1269 			goto done;
   1270 #endif
   1271 		}
   1272 		break;
   1273 	}
   1274 
   1275 	/* default arg printing */
   1276 
   1277 	if (verbose(tcp)) {
   1278 		if (len == sizeof(int)) {
   1279 			printnum_int(tcp, addr, "%d");
   1280 		} else {
   1281 			printstr(tcp, addr, len);
   1282 		}
   1283 	} else {
   1284 		tprintf("%#lx", addr);
   1285 	}
   1286 done:
   1287 	tprintf(", [%d]", len);
   1288 }
   1289 
   1290 SYS_FUNC(getsockopt)
   1291 {
   1292 	if (entering(tcp)) {
   1293 		print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
   1294 					    tcp->u_arg[1], tcp->u_arg[2]);
   1295 	} else {
   1296 		int len;
   1297 
   1298 		if (syserror(tcp) || umove(tcp, tcp->u_arg[4], &len) < 0) {
   1299 			tprintf("%#lx, %#lx",
   1300 				tcp->u_arg[3], tcp->u_arg[4]);
   1301 		} else {
   1302 			print_getsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
   1303 					 tcp->u_arg[3], len);
   1304 		}
   1305 	}
   1306 	return 0;
   1307 }
   1308 
   1309 #ifdef MCAST_JOIN_GROUP
   1310 static void
   1311 print_group_req(struct tcb *tcp, long addr, int len)
   1312 {
   1313 	struct group_req greq;
   1314 
   1315 	if (len != sizeof(greq) ||
   1316 	    umove(tcp, addr, &greq) < 0) {
   1317 		tprintf("%#lx", addr);
   1318 		return;
   1319 	}
   1320 
   1321 	union {
   1322 		struct sockaddr *sa;
   1323 		struct sockaddr_in *sin;
   1324 #ifdef HAVE_INET_NTOP
   1325 		struct sockaddr_in6 *sin6;
   1326 #endif
   1327 	} a = { .sa = (struct sockaddr *) &greq.gr_group };
   1328 #ifdef HAVE_INET_NTOP
   1329 	char str[INET6_ADDRSTRLEN];
   1330 #endif
   1331 
   1332 	tprintf("{gr_interface=%u, gr_group={sa_family=", greq.gr_interface);
   1333 	printxval(addrfams, a.sa->sa_family, "AF_???");
   1334 
   1335 	switch (a.sa->sa_family) {
   1336 	case AF_INET:
   1337 		tprintf(", sin_port=htons(%u), sin_addr=inet_addr(\"%s\")}}",
   1338 			ntohs(a.sin->sin_port),
   1339 			inet_ntoa(a.sin->sin_addr));
   1340 		return;
   1341 #ifdef HAVE_INET_NTOP
   1342 	case AF_INET6:
   1343 		if (!inet_ntop(AF_INET6, &a.sin6->sin6_addr, str, sizeof(str)))
   1344 			break;
   1345 		tprintf(", sin6_port=htons(%u)"
   1346 			", inet_pton(AF_INET6, \"%s\", &sin6_addr)}}",
   1347 			ntohs(a.sin6->sin6_port), str);
   1348 		return;
   1349 #endif /* HAVE_INET_NTOP */
   1350 	}
   1351 
   1352 	tprints(", sa_data=");
   1353 	print_quoted_string(a.sa->sa_data, sizeof(a.sa->sa_data), 0);
   1354 	tprintf("}}");
   1355 
   1356 }
   1357 #endif /* MCAST_JOIN_GROUP */
   1358 
   1359 #ifdef PACKET_RX_RING
   1360 static void
   1361 print_tpacket_req(struct tcb *tcp, long addr, int len)
   1362 {
   1363 	struct tpacket_req req;
   1364 
   1365 	if (len != sizeof(req) ||
   1366 	    umove(tcp, addr, &req) < 0) {
   1367 		tprintf("%#lx", addr);
   1368 	} else {
   1369 		tprintf("{block_size=%u, block_nr=%u, "
   1370 			"frame_size=%u, frame_nr=%u}",
   1371 			req.tp_block_size,
   1372 			req.tp_block_nr,
   1373 			req.tp_frame_size,
   1374 			req.tp_frame_nr);
   1375 	}
   1376 }
   1377 #endif /* PACKET_RX_RING */
   1378 
   1379 #ifdef PACKET_ADD_MEMBERSHIP
   1380 # include "xlat/packet_mreq_type.h"
   1381 
   1382 static void
   1383 print_packet_mreq(struct tcb *tcp, long addr, int len)
   1384 {
   1385 	struct packet_mreq mreq;
   1386 
   1387 	if (len != sizeof(mreq) ||
   1388 	    umove(tcp, addr, &mreq) < 0) {
   1389 		tprintf("%#lx", addr);
   1390 	} else {
   1391 		unsigned int i;
   1392 
   1393 		tprintf("{mr_ifindex=%u, mr_type=", mreq.mr_ifindex);
   1394 		printxval(packet_mreq_type, mreq.mr_type, "PACKET_MR_???");
   1395 		tprintf(", mr_alen=%u, mr_address=", mreq.mr_alen);
   1396 		if (mreq.mr_alen > ARRAY_SIZE(mreq.mr_address))
   1397 			mreq.mr_alen = ARRAY_SIZE(mreq.mr_address);
   1398 		for (i = 0; i < mreq.mr_alen; ++i)
   1399 			tprintf("%02x", mreq.mr_address[i]);
   1400 		tprints("}");
   1401 	}
   1402 }
   1403 #endif /* PACKET_ADD_MEMBERSHIP */
   1404 
   1405 static void
   1406 print_setsockopt(struct tcb *tcp, int level, int name, long addr, int len)
   1407 {
   1408 	if (addr && verbose(tcp))
   1409 	switch (level) {
   1410 	case SOL_SOCKET:
   1411 		switch (name) {
   1412 #ifdef SO_LINGER
   1413 		case SO_LINGER:
   1414 			print_linger(tcp, addr, len);
   1415 			goto done;
   1416 #endif
   1417 		}
   1418 		break;
   1419 
   1420 	case SOL_IP:
   1421 		switch (name) {
   1422 #ifdef MCAST_JOIN_GROUP
   1423 		case MCAST_JOIN_GROUP:
   1424 		case MCAST_LEAVE_GROUP:
   1425 			print_group_req(tcp, addr, len);
   1426 			goto done;
   1427 #endif /* MCAST_JOIN_GROUP */
   1428 		}
   1429 		break;
   1430 
   1431 	case SOL_PACKET:
   1432 		switch (name) {
   1433 #ifdef PACKET_RX_RING
   1434 		case PACKET_RX_RING:
   1435 # ifdef PACKET_TX_RING
   1436 		case PACKET_TX_RING:
   1437 # endif
   1438 			print_tpacket_req(tcp, addr, len);
   1439 			goto done;
   1440 #endif /* PACKET_RX_RING */
   1441 #ifdef PACKET_ADD_MEMBERSHIP
   1442 		case PACKET_ADD_MEMBERSHIP:
   1443 		case PACKET_DROP_MEMBERSHIP:
   1444 			print_packet_mreq(tcp, addr, len);
   1445 			goto done;
   1446 #endif /* PACKET_ADD_MEMBERSHIP */
   1447 		}
   1448 		break;
   1449 
   1450 	case SOL_RAW:
   1451 		switch (name) {
   1452 #ifdef ICMP_FILTER
   1453 		case ICMP_FILTER:
   1454 			print_icmp_filter(tcp, addr, len);
   1455 			goto done;
   1456 #endif
   1457 		}
   1458 		break;
   1459 	}
   1460 
   1461 	/* default arg printing */
   1462 
   1463 	if (verbose(tcp)) {
   1464 		if (len == sizeof(int)) {
   1465 			printnum_int(tcp, addr, "%d");
   1466 		} else {
   1467 			printstr(tcp, addr, len);
   1468 		}
   1469 	} else {
   1470 		tprintf("%#lx", addr);
   1471 	}
   1472 done:
   1473 	tprintf(", %d", len);
   1474 }
   1475 
   1476 SYS_FUNC(setsockopt)
   1477 {
   1478 	if (entering(tcp)) {
   1479 		print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
   1480 					    tcp->u_arg[1], tcp->u_arg[2]);
   1481 		print_setsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
   1482 				 tcp->u_arg[3], tcp->u_arg[4]);
   1483 	}
   1484 	return 0;
   1485 }
   1486