net.c revision 45ae937cedd8ddb477ead0a04158c79b214d5422
1/* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com> 5 * Copyright (c) 1996-2000 Wichert Akkerman <wichert@cistron.nl> 6 * 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#ifdef HAVE_NETIPX_IPX_H 50# include <netipx/ipx.h> 51#else 52# include <linux/ipx.h> 53#endif 54 55#if defined(HAVE_LINUX_IP_VS_H) 56# include <linux/ip_vs.h> 57#endif 58#include <linux/netlink.h> 59#if defined(HAVE_LINUX_NETFILTER_ARP_ARP_TABLES_H) 60# include <linux/netfilter_arp/arp_tables.h> 61#endif 62#if defined(HAVE_LINUX_NETFILTER_BRIDGE_EBTABLES_H) 63# include <linux/netfilter_bridge/ebtables.h> 64#endif 65#if defined(HAVE_LINUX_NETFILTER_IPV4_IP_TABLES_H) 66# include <linux/netfilter_ipv4/ip_tables.h> 67#endif 68#if defined(HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H) 69# include <linux/netfilter_ipv6/ip6_tables.h> 70#endif 71#include <linux/if_packet.h> 72#include <linux/icmp.h> 73#ifdef HAVE_BLUETOOTH_BLUETOOTH_H 74# include <bluetooth/bluetooth.h> 75# include <bluetooth/hci.h> 76# include <bluetooth/l2cap.h> 77# include <bluetooth/rfcomm.h> 78# include <bluetooth/sco.h> 79#endif 80 81#include "xlat/addrfams.h" 82#include "xlat/socktypes.h" 83#include "xlat/sock_type_flags.h" 84#ifndef SOCK_TYPE_MASK 85# define SOCK_TYPE_MASK 0xf 86#endif 87 88#include "xlat/socketlayers.h" 89 90#include "xlat/inet_protocols.h" 91 92#if !defined NETLINK_SOCK_DIAG && defined NETLINK_INET_DIAG 93# define NETLINK_SOCK_DIAG NETLINK_INET_DIAG 94#endif 95#include "xlat/netlink_protocols.h" 96 97#if defined(HAVE_BLUETOOTH_BLUETOOTH_H) 98# include "xlat/bt_protocols.h" 99# include "xlat/hci_channels.h" 100#endif 101 102#include "xlat/msg_flags.h" 103 104#define SIZEOF_SA_FAMILY sizeof(((struct sockaddr *) 0)->sa_family) 105 106static void 107print_sockaddr_data_un(const void *const buf, const int addrlen) 108{ 109 const struct sockaddr_un *const sa_un = buf; 110 const int un_len = addrlen > (int) sizeof(*sa_un) 111 ? (int) sizeof(*sa_un) : addrlen; 112 const int path_len = un_len - SIZEOF_SA_FAMILY; 113 114 tprints("sun_path="); 115 if (sa_un->sun_path[0]) { 116 print_quoted_string(sa_un->sun_path, path_len + 1, 117 QUOTE_0_TERMINATED); 118 } else { 119 tprints("@"); 120 print_quoted_string(sa_un->sun_path + 1, path_len - 1, 0); 121 } 122} 123 124static void 125print_sockaddr_data_in(const void *const buf, const int addrlen) 126{ 127 const struct sockaddr_in *const sa_in = buf; 128 129 tprintf("sin_port=htons(%u), sin_addr=inet_addr(\"%s\")", 130 ntohs(sa_in->sin_port), inet_ntoa(sa_in->sin_addr)); 131} 132 133void 134print_ifindex(unsigned int ifindex) 135{ 136#ifdef HAVE_IF_INDEXTONAME 137 char buf[IFNAMSIZ + 1]; 138 139 if (if_indextoname(ifindex, buf)) { 140 tprints("if_nametoindex("); 141 print_quoted_string(buf, sizeof(buf), QUOTE_0_TERMINATED); 142 tprints(")"); 143 return; 144 } 145#endif 146 tprintf("%u", ifindex); 147} 148 149#define SIN6_MIN_LEN offsetof(struct sockaddr_in6, sin6_scope_id) 150 151static void 152print_sockaddr_data_in6(const void *const buf, const int addrlen) 153{ 154 const struct sockaddr_in6 *const sa_in6 = buf; 155 156 char string_addr[100]; 157 inet_ntop(AF_INET6, &sa_in6->sin6_addr, 158 string_addr, sizeof(string_addr)); 159 tprintf("sin6_port=htons(%u), inet_pton(AF_INET6" 160 ", \"%s\", &sin6_addr), sin6_flowinfo=htonl(%u)", 161 ntohs(sa_in6->sin6_port), string_addr, 162 ntohl(sa_in6->sin6_flowinfo)); 163 164 if (addrlen <= (int) SIN6_MIN_LEN) 165 return; 166 167 tprints(", sin6_scope_id="); 168#if defined IN6_IS_ADDR_LINKLOCAL && defined IN6_IS_ADDR_MC_LINKLOCAL 169 if (IN6_IS_ADDR_LINKLOCAL(&sa_in6->sin6_addr) 170 || IN6_IS_ADDR_MC_LINKLOCAL(&sa_in6->sin6_addr)) 171 print_ifindex(sa_in6->sin6_scope_id); 172 else 173#endif 174 tprintf("%u", sa_in6->sin6_scope_id); 175} 176 177static void 178print_sockaddr_data_ipx(const void *const buf, const int addrlen) 179{ 180 const struct sockaddr_ipx *const sa_ipx = buf; 181 unsigned int i; 182 183 tprintf("sipx_port=htons(%u)" 184 ", sipx_network=htonl(%#08x)" 185 ", sipx_node=[", 186 ntohs(sa_ipx->sipx_port), 187 ntohl(sa_ipx->sipx_network)); 188 for (i = 0; i < IPX_NODE_LEN; ++i) { 189 tprintf("%s%#02x", i ? ", " : "", 190 sa_ipx->sipx_node[i]); 191 } 192 tprintf("], sipx_type=%#02x", sa_ipx->sipx_type); 193} 194 195static void 196print_sockaddr_data_nl(const void *const buf, const int addrlen) 197{ 198 const struct sockaddr_nl *const sa_nl = buf; 199 200 tprintf("nl_pid=%d, nl_groups=%#08x", 201 sa_nl->nl_pid, sa_nl->nl_groups); 202} 203 204static void 205print_sockaddr_data_raw(const void *const buf, const int addrlen) 206{ 207 const char *const data = buf + SIZEOF_SA_FAMILY; 208 const int datalen = addrlen - SIZEOF_SA_FAMILY; 209 210 tprints("sa_data="); 211 print_quoted_string(data, datalen, 0); 212} 213 214#ifdef HAVE_BLUETOOTH_BLUETOOTH_H 215static void 216print_sockaddr_data_bt(const void *const buf, const int addrlen) 217{ 218 switch (addrlen) { 219 case sizeof(struct sockaddr_hci): { 220 const struct sockaddr_hci *const hci = buf; 221 tprintf("hci_dev=htobs(%hu), hci_channel=", 222 btohs(hci->hci_dev)); 223 printxval(hci_channels, hci->hci_channel, 224 "HCI_CHANNEL_???"); 225 break; 226 } 227 case sizeof(struct sockaddr_sco): { 228 const struct sockaddr_sco *const sco = buf; 229 tprintf("sco_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x", 230 sco->sco_bdaddr.b[0], sco->sco_bdaddr.b[1], 231 sco->sco_bdaddr.b[2], sco->sco_bdaddr.b[3], 232 sco->sco_bdaddr.b[4], sco->sco_bdaddr.b[5]); 233 break; 234 } 235 case sizeof(struct sockaddr_rc): { 236 const struct sockaddr_rc *const rc = buf; 237 tprintf("rc_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" 238 ", rc_channel=%u", 239 rc->rc_bdaddr.b[0], rc->rc_bdaddr.b[1], 240 rc->rc_bdaddr.b[2], rc->rc_bdaddr.b[3], 241 rc->rc_bdaddr.b[4], rc->rc_bdaddr.b[5], 242 rc->rc_channel); 243 break; 244 } 245 case sizeof(struct sockaddr_l2): { 246 const struct sockaddr_l2 *const l2 = buf; 247 tprintf("l2_psm=htobs(%hu)" 248 ", l2_bdaddr=%02x:%02x:%02x:%02x:%02x:%02x" 249 ", l2_cid=htobs(%hu), l2_bdaddr_type=%u", 250 btohs(l2->l2_psm), 251 l2->l2_bdaddr.b[0], l2->l2_bdaddr.b[1], 252 l2->l2_bdaddr.b[2], l2->l2_bdaddr.b[3], 253 l2->l2_bdaddr.b[4], l2->l2_bdaddr.b[5], 254 btohs(l2->l2_cid), l2->l2_bdaddr_type); 255 break; 256 } 257 default: 258 print_sockaddr_data_raw(buf, addrlen); 259 break; 260 } 261} 262#endif /* HAVE_BLUETOOTH_BLUETOOTH_H */ 263 264typedef void (* const sockaddr_printer)(const void *const, const int); 265 266static const struct { 267 const sockaddr_printer printer; 268 const int min_len; 269} sa_printers[] = { 270 [AF_UNIX] = { print_sockaddr_data_un, SIZEOF_SA_FAMILY + 1 }, 271 [AF_INET] = { print_sockaddr_data_in, sizeof(struct sockaddr_in) }, 272 [AF_IPX] = { print_sockaddr_data_ipx, sizeof(struct sockaddr_ipx) }, 273 [AF_INET6] = { print_sockaddr_data_in6, SIN6_MIN_LEN }, 274 [AF_NETLINK] = { print_sockaddr_data_nl, SIZEOF_SA_FAMILY + 1 }, 275 [AF_PACKET] = { print_sockaddr_data_ll, sizeof(struct sockaddr_ll) }, 276#ifdef HAVE_BLUETOOTH_BLUETOOTH_H 277 [AF_BLUETOOTH] = { print_sockaddr_data_bt, SIZEOF_SA_FAMILY + 1 }, 278#endif 279}; 280 281void 282print_sockaddr(struct tcb *tcp, const void *const buf, const int addrlen) 283{ 284 const struct sockaddr *const sa = buf; 285 286 tprints("{sa_family="); 287 printxval(addrfams, sa->sa_family, "AF_???"); 288 289 if (addrlen > (int) SIZEOF_SA_FAMILY) { 290 tprints(", "); 291 292 if (sa->sa_family < ARRAY_SIZE(sa_printers) 293 && sa_printers[sa->sa_family].printer 294 && addrlen >= sa_printers[sa->sa_family].min_len) { 295 sa_printers[sa->sa_family].printer(buf, addrlen); 296 } else { 297 print_sockaddr_data_raw(buf, addrlen); 298 } 299 } 300 301 tprints("}"); 302} 303 304int 305printsock(struct tcb *tcp, long addr, int addrlen) 306{ 307 if (addrlen < 2) { 308 printaddr(addr); 309 return -1; 310 } 311 312 union { 313 struct sockaddr sa; 314 struct sockaddr_storage storage; 315 char pad[sizeof(struct sockaddr_storage) + 1]; 316 } addrbuf; 317 318 if ((unsigned) addrlen > sizeof(addrbuf.storage)) 319 addrlen = sizeof(addrbuf.storage); 320 321 if (umoven_or_printaddr(tcp, addr, addrlen, addrbuf.pad)) 322 return -1; 323 324 memset(&addrbuf.pad[addrlen], 0, sizeof(addrbuf.pad) - addrlen); 325 326 print_sockaddr(tcp, &addrbuf, addrlen); 327 328 return addrbuf.sa.sa_family; 329} 330 331#include "xlat/scmvals.h" 332#include "xlat/ip_cmsg_types.h" 333 334#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 335struct cmsghdr32 { 336 uint32_t cmsg_len; 337 int cmsg_level; 338 int cmsg_type; 339}; 340#endif 341 342typedef union { 343 char *ptr; 344 struct cmsghdr *cmsg; 345#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 346 struct cmsghdr32 *cmsg32; 347#endif 348} union_cmsghdr; 349 350static void 351print_scm_rights(struct tcb *tcp, const void *cmsg_data, 352 const size_t data_len) 353{ 354 const int *fds = cmsg_data; 355 const char *end = (const char *) cmsg_data + data_len; 356 bool seen = false; 357 358 if (sizeof(*fds) > data_len) 359 return; 360 361 tprints(", ["); 362 while ((const char *) fds < end) { 363 if (seen) 364 tprints(", "); 365 else 366 seen = true; 367 printfd(tcp, *fds++); 368 } 369 tprints("]"); 370} 371 372static void 373print_scm_creds(struct tcb *tcp, const void *cmsg_data, 374 const size_t data_len) 375{ 376 const struct ucred *uc = cmsg_data; 377 378 if (sizeof(*uc) > data_len) 379 return; 380 381 tprintf(", {pid=%u, uid=%u, gid=%u}", 382 (unsigned) uc->pid, (unsigned) uc->uid, (unsigned) uc->gid); 383} 384 385static void 386print_scm_security(struct tcb *tcp, const void *cmsg_data, 387 const size_t data_len) 388{ 389 if (!data_len) 390 return; 391 392 tprints(", "); 393 print_quoted_string(cmsg_data, data_len, 0); 394} 395 396static void 397print_cmsg_ip_pktinfo(struct tcb *tcp, const void *cmsg_data, 398 const size_t data_len) 399{ 400 const struct in_pktinfo *info = cmsg_data; 401 402 if (sizeof(*info) > data_len) 403 return; 404 405 tprints(", {ipi_ifindex="); 406 print_ifindex(info->ipi_ifindex); 407 tprintf(", ipi_spec_dst=inet_addr(\"%s\"), ipi_addr=inet_addr(\"%s\")}", 408 inet_ntoa(info->ipi_spec_dst), inet_ntoa(info->ipi_addr)); 409} 410 411static void 412print_cmsg_ip_ttl(struct tcb *tcp, const void *cmsg_data, 413 const size_t data_len) 414{ 415 const unsigned int *ttl = cmsg_data; 416 417 if (sizeof(*ttl) > data_len) 418 return; 419 420 tprintf(", {ttl=%u}", *ttl); 421} 422 423static void 424print_cmsg_ip_tos(struct tcb *tcp, const void *cmsg_data, 425 const size_t data_len) 426{ 427 const uint8_t *tos = cmsg_data; 428 429 if (sizeof(*tos) > data_len) 430 return; 431 432 tprintf(", {tos=%x}", *tos); 433} 434 435static void 436print_cmsg_ip_checksum(struct tcb *tcp, const void *cmsg_data, 437 const size_t data_len) 438{ 439 const uint32_t *csum = cmsg_data; 440 441 if (sizeof(*csum) > data_len) 442 return; 443 444 tprintf(", {csum=%u}", *csum); 445} 446 447static void 448print_cmsg_ip_opts(struct tcb *tcp, const void *cmsg_data, 449 const size_t data_len) 450{ 451 const unsigned char *opts = cmsg_data; 452 size_t i; 453 454 if (!data_len) 455 return; 456 457 tprints(", {opts=0x"); 458 for (i = 0; i < data_len; ++i) 459 tprintf("%02x", opts[i]); 460 tprints("}"); 461} 462 463static void 464print_cmsg_ip_recverr(struct tcb *tcp, const void *cmsg_data, 465 const size_t data_len) 466{ 467 const struct { 468 uint32_t ee_errno; 469 uint8_t ee_origin; 470 uint8_t ee_type; 471 uint8_t ee_code; 472 uint8_t ee_pad; 473 uint32_t ee_info; 474 uint32_t ee_data; 475 struct sockaddr_in offender; 476 } *err = cmsg_data; 477 478 if (sizeof(*err) > data_len) 479 return; 480 481 tprintf(", {ee_errno=%u, ee_origin=%u, ee_type=%u, ee_code=%u" 482 ", ee_info=%u, ee_data=%u, offender=", 483 err->ee_errno, err->ee_origin, err->ee_type, 484 err->ee_code, err->ee_info, err->ee_data); 485 print_sockaddr(tcp, &err->offender, sizeof(err->offender)); 486 tprints("}"); 487} 488 489static void 490print_cmsg_ip_origdstaddr(struct tcb *tcp, const void *cmsg_data, 491 const size_t data_len) 492{ 493 if (sizeof(struct sockaddr_in) > data_len) 494 return; 495 496 tprints(", "); 497 print_sockaddr(tcp, cmsg_data, data_len); 498} 499 500static void 501print_cmsg_type_data(struct tcb *tcp, const int cmsg_level, const int cmsg_type, 502 const void *cmsg_data, const size_t data_len) 503{ 504 switch (cmsg_level) { 505 case SOL_SOCKET: 506 printxval(scmvals, cmsg_type, "SCM_???"); 507 switch (cmsg_type) { 508 case SCM_RIGHTS: 509 print_scm_rights(tcp, cmsg_data, data_len); 510 break; 511 case SCM_CREDENTIALS: 512 print_scm_creds(tcp, cmsg_data, data_len); 513 break; 514 case SCM_SECURITY: 515 print_scm_security(tcp, cmsg_data, data_len); 516 break; 517 } 518 break; 519 case SOL_IP: 520 printxval(ip_cmsg_types, cmsg_type, "IP_???"); 521 switch (cmsg_type) { 522 case IP_PKTINFO: 523 print_cmsg_ip_pktinfo(tcp, cmsg_data, data_len); 524 break; 525 case IP_TTL: 526 print_cmsg_ip_ttl(tcp, cmsg_data, data_len); 527 break; 528 case IP_TOS: 529 print_cmsg_ip_tos(tcp, cmsg_data, data_len); 530 break; 531 case IP_RECVOPTS: 532 case IP_RETOPTS: 533 print_cmsg_ip_opts(tcp, cmsg_data, data_len); 534 break; 535 case IP_RECVERR: 536 print_cmsg_ip_recverr(tcp, cmsg_data, data_len); 537 break; 538 case IP_ORIGDSTADDR: 539 print_cmsg_ip_origdstaddr(tcp, cmsg_data, data_len); 540 break; 541 case IP_CHECKSUM: 542 print_cmsg_ip_checksum(tcp, cmsg_data, data_len); 543 break; 544 case SCM_SECURITY: 545 print_scm_security(tcp, cmsg_data, data_len); 546 break; 547 } 548 break; 549 default: 550 tprintf("%u", cmsg_type); 551 } 552} 553 554static void 555printcmsghdr(struct tcb *tcp, unsigned long addr, size_t len) 556{ 557 const size_t cmsg_size = 558#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 559 (current_wordsize < sizeof(long)) ? sizeof(struct cmsghdr32) : 560#endif 561 sizeof(struct cmsghdr); 562 563 char *buf = len < cmsg_size ? NULL : malloc(len); 564 if (!buf || umoven(tcp, addr, len, buf) < 0) { 565 tprints(", msg_control="); 566 printaddr(addr); 567 free(buf); 568 return; 569 } 570 571 union_cmsghdr u = { .ptr = buf }; 572 573 tprints(", ["); 574 while (len >= cmsg_size) { 575 size_t cmsg_len = 576#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 577 (current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_len : 578#endif 579 u.cmsg->cmsg_len; 580 int cmsg_level = 581#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 582 (current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_level : 583#endif 584 u.cmsg->cmsg_level; 585 int cmsg_type = 586#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 587 (current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_type : 588#endif 589 u.cmsg->cmsg_type; 590 591 if (u.ptr != buf) 592 tprints(", "); 593 tprintf("{cmsg_len=%lu, cmsg_level=", (unsigned long) cmsg_len); 594 printxval(socketlayers, cmsg_level, "SOL_???"); 595 tprints(", cmsg_type="); 596 597 if (cmsg_len > len) 598 cmsg_len = len; 599 600 print_cmsg_type_data(tcp, cmsg_level, cmsg_type, 601 (const void *) (u.ptr + cmsg_size), 602 cmsg_len > cmsg_size ? cmsg_len - cmsg_size: 0); 603 tprints("}"); 604 605 if (cmsg_len < cmsg_size) { 606 len -= cmsg_size; 607 break; 608 } 609 cmsg_len = (cmsg_len + current_wordsize - 1) & 610 (size_t) ~(current_wordsize - 1); 611 if (cmsg_len >= len) { 612 len = 0; 613 break; 614 } 615 u.ptr += cmsg_len; 616 len -= cmsg_len; 617 } 618 if (len) 619 tprints(", ..."); 620 tprints("]"); 621 free(buf); 622} 623 624static void 625do_msghdr(struct tcb *tcp, struct msghdr *msg, unsigned long data_size) 626{ 627 tprintf("{msg_name(%d)=", msg->msg_namelen); 628 printsock(tcp, (long)msg->msg_name, msg->msg_namelen); 629 630 tprintf(", msg_iov(%lu)=", (unsigned long)msg->msg_iovlen); 631 632 tprint_iov_upto(tcp, (unsigned long)msg->msg_iovlen, 633 (unsigned long)msg->msg_iov, IOV_DECODE_STR, data_size); 634 635#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL 636 tprintf(", msg_controllen=%lu", (unsigned long)msg->msg_controllen); 637 if (msg->msg_controllen) 638 printcmsghdr(tcp, (unsigned long) msg->msg_control, 639 msg->msg_controllen); 640 tprints(", msg_flags="); 641 printflags(msg_flags, msg->msg_flags, "MSG_???"); 642#else /* !HAVE_STRUCT_MSGHDR_MSG_CONTROL */ 643 tprintf("msg_accrights=%#lx, msg_accrightslen=%u", 644 (unsigned long) msg->msg_accrights, msg->msg_accrightslen); 645#endif /* !HAVE_STRUCT_MSGHDR_MSG_CONTROL */ 646 tprints("}"); 647} 648 649struct msghdr32 { 650 uint32_t /* void* */ msg_name; 651 uint32_t /* socklen_t */msg_namelen; 652 uint32_t /* iovec* */ msg_iov; 653 uint32_t /* size_t */ msg_iovlen; 654 uint32_t /* void* */ msg_control; 655 uint32_t /* size_t */ msg_controllen; 656 uint32_t /* int */ msg_flags; 657}; 658struct mmsghdr32 { 659 struct msghdr32 msg_hdr; 660 uint32_t /* unsigned */ msg_len; 661}; 662 663#ifndef HAVE_STRUCT_MMSGHDR 664struct mmsghdr { 665 struct msghdr msg_hdr; 666 unsigned msg_len; 667}; 668#endif 669 670#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 671static void 672copy_from_msghdr32(struct msghdr *to_msg, struct msghdr32 *from_msg32) 673{ 674 to_msg->msg_name = (void*)(long)from_msg32->msg_name; 675 to_msg->msg_namelen = from_msg32->msg_namelen; 676 to_msg->msg_iov = (void*)(long)from_msg32->msg_iov; 677 to_msg->msg_iovlen = from_msg32->msg_iovlen; 678 to_msg->msg_control = (void*)(long)from_msg32->msg_control; 679 to_msg->msg_controllen = from_msg32->msg_controllen; 680 to_msg->msg_flags = from_msg32->msg_flags; 681} 682#endif 683 684static bool 685extractmsghdr(struct tcb *tcp, long addr, struct msghdr *msg) 686{ 687#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 688 if (current_wordsize == 4) { 689 struct msghdr32 msg32; 690 691 if (umove(tcp, addr, &msg32) < 0) 692 return false; 693 copy_from_msghdr32(msg, &msg32); 694 } else 695#endif 696 if (umove(tcp, addr, msg) < 0) 697 return false; 698 return true; 699} 700 701static bool 702extractmmsghdr(struct tcb *tcp, long addr, unsigned int idx, struct mmsghdr *mmsg) 703{ 704#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 705 if (current_wordsize == 4) { 706 struct mmsghdr32 mmsg32; 707 708 addr += sizeof(struct mmsghdr32) * idx; 709 if (umove(tcp, addr, &mmsg32) < 0) 710 return false; 711 712 copy_from_msghdr32(&mmsg->msg_hdr, &mmsg32.msg_hdr); 713 mmsg->msg_len = mmsg32.msg_len; 714 } else 715#endif 716 { 717 addr += sizeof(*mmsg) * idx; 718 if (umove(tcp, addr, mmsg) < 0) 719 return false; 720 } 721 return true; 722} 723 724static void 725printmsghdr(struct tcb *tcp, long addr, unsigned long data_size) 726{ 727 struct msghdr msg; 728 729 if (verbose(tcp) && extractmsghdr(tcp, addr, &msg)) 730 do_msghdr(tcp, &msg, data_size); 731 else 732 printaddr(addr); 733} 734 735void 736dumpiov_in_msghdr(struct tcb *tcp, long addr, unsigned long data_size) 737{ 738 struct msghdr msg; 739 740 if (extractmsghdr(tcp, addr, &msg)) 741 dumpiov_upto(tcp, msg.msg_iovlen, (long)msg.msg_iov, data_size); 742} 743 744static void 745printmmsghdr(struct tcb *tcp, long addr, unsigned int idx, unsigned long msg_len) 746{ 747 struct mmsghdr mmsg; 748 749 if (extractmmsghdr(tcp, addr, idx, &mmsg)) { 750 tprints("{"); 751 do_msghdr(tcp, &mmsg.msg_hdr, msg_len ? msg_len : mmsg.msg_len); 752 tprintf(", %u}", mmsg.msg_len); 753 } 754 else 755 printaddr(addr); 756} 757 758static void 759decode_mmsg(struct tcb *tcp, unsigned long msg_len) 760{ 761 /* mmsgvec */ 762 if (syserror(tcp)) { 763 printaddr(tcp->u_arg[1]); 764 } else { 765 unsigned int len = tcp->u_rval; 766 unsigned int i; 767 768 tprints("{"); 769 for (i = 0; i < len; ++i) { 770 if (i) 771 tprints(", "); 772 printmmsghdr(tcp, tcp->u_arg[1], i, msg_len); 773 } 774 tprints("}"); 775 } 776 /* vlen */ 777 tprintf(", %u, ", (unsigned int) tcp->u_arg[2]); 778 /* flags */ 779 printflags(msg_flags, tcp->u_arg[3], "MSG_???"); 780} 781 782void 783dumpiov_in_mmsghdr(struct tcb *tcp, long addr) 784{ 785 unsigned int len = tcp->u_rval; 786 unsigned int i; 787 struct mmsghdr mmsg; 788 789 for (i = 0; i < len; ++i) { 790 if (extractmmsghdr(tcp, addr, i, &mmsg)) { 791 tprintf(" = %lu buffers in vector %u\n", 792 (unsigned long)mmsg.msg_hdr.msg_iovlen, i); 793 dumpiov_upto(tcp, mmsg.msg_hdr.msg_iovlen, 794 (long)mmsg.msg_hdr.msg_iov, mmsg.msg_len); 795 } 796 } 797} 798 799/* 800 * low bits of the socket type define real socket type, 801 * other bits are socket type flags. 802 */ 803static void 804tprint_sock_type(unsigned int flags) 805{ 806 const char *str = xlookup(socktypes, flags & SOCK_TYPE_MASK); 807 808 if (str) { 809 tprints(str); 810 flags &= ~SOCK_TYPE_MASK; 811 if (!flags) 812 return; 813 tprints("|"); 814 } 815 printflags(sock_type_flags, flags, "SOCK_???"); 816} 817 818SYS_FUNC(socket) 819{ 820 printxval(addrfams, tcp->u_arg[0], "AF_???"); 821 tprints(", "); 822 tprint_sock_type(tcp->u_arg[1]); 823 tprints(", "); 824 switch (tcp->u_arg[0]) { 825 case AF_INET: 826 case AF_INET6: 827 printxval(inet_protocols, tcp->u_arg[2], "IPPROTO_???"); 828 break; 829 830 case AF_NETLINK: 831 printxval(netlink_protocols, tcp->u_arg[2], "NETLINK_???"); 832 break; 833 834#ifdef HAVE_BLUETOOTH_BLUETOOTH_H 835 case AF_BLUETOOTH: 836 printxval(bt_protocols, tcp->u_arg[2], "BTPROTO_???"); 837 break; 838#endif 839 840 default: 841 tprintf("%lu", tcp->u_arg[2]); 842 break; 843 } 844 845 return RVAL_DECODED | RVAL_FD; 846} 847 848SYS_FUNC(bind) 849{ 850 printfd(tcp, tcp->u_arg[0]); 851 tprints(", "); 852 printsock(tcp, tcp->u_arg[1], tcp->u_arg[2]); 853 tprintf(", %lu", tcp->u_arg[2]); 854 855 return RVAL_DECODED; 856} 857 858SYS_FUNC(listen) 859{ 860 printfd(tcp, tcp->u_arg[0]); 861 tprints(", "); 862 tprintf("%lu", tcp->u_arg[1]); 863 864 return RVAL_DECODED; 865} 866 867static int 868do_sockname(struct tcb *tcp, int flags_arg) 869{ 870 if (entering(tcp)) { 871 printfd(tcp, tcp->u_arg[0]); 872 tprints(", "); 873 return 0; 874 } 875 876 int len; 877 if (!tcp->u_arg[2] || !verbose(tcp) || syserror(tcp) || 878 umove(tcp, tcp->u_arg[2], &len) < 0) { 879 printaddr(tcp->u_arg[1]); 880 tprints(", "); 881 printaddr(tcp->u_arg[2]); 882 } else { 883 printsock(tcp, tcp->u_arg[1], len); 884 tprintf(", [%d]", len); 885 } 886 887 if (flags_arg >= 0) { 888 tprints(", "); 889 printflags(sock_type_flags, tcp->u_arg[flags_arg], 890 "SOCK_???"); 891 } 892 return 0; 893} 894 895SYS_FUNC(accept) 896{ 897 do_sockname(tcp, -1); 898 return RVAL_FD; 899} 900 901SYS_FUNC(accept4) 902{ 903 do_sockname(tcp, 3); 904 return RVAL_FD; 905} 906 907SYS_FUNC(send) 908{ 909 printfd(tcp, tcp->u_arg[0]); 910 tprints(", "); 911 printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]); 912 tprintf(", %lu, ", tcp->u_arg[2]); 913 /* flags */ 914 printflags(msg_flags, tcp->u_arg[3], "MSG_???"); 915 916 return RVAL_DECODED; 917} 918 919SYS_FUNC(sendto) 920{ 921 printfd(tcp, tcp->u_arg[0]); 922 tprints(", "); 923 printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]); 924 tprintf(", %lu, ", tcp->u_arg[2]); 925 /* flags */ 926 printflags(msg_flags, tcp->u_arg[3], "MSG_???"); 927 /* to address */ 928 tprints(", "); 929 printsock(tcp, tcp->u_arg[4], tcp->u_arg[5]); 930 /* to length */ 931 tprintf(", %lu", tcp->u_arg[5]); 932 933 return RVAL_DECODED; 934} 935 936SYS_FUNC(sendmsg) 937{ 938 printfd(tcp, tcp->u_arg[0]); 939 tprints(", "); 940 printmsghdr(tcp, tcp->u_arg[1], (unsigned long) -1L); 941 /* flags */ 942 tprints(", "); 943 printflags(msg_flags, tcp->u_arg[2], "MSG_???"); 944 945 return RVAL_DECODED; 946} 947 948SYS_FUNC(sendmmsg) 949{ 950 if (entering(tcp)) { 951 /* sockfd */ 952 printfd(tcp, tcp->u_arg[0]); 953 tprints(", "); 954 if (!verbose(tcp)) { 955 printaddr(tcp->u_arg[1]); 956 tprintf(", %u, ", (unsigned int) tcp->u_arg[2]); 957 printflags(msg_flags, tcp->u_arg[3], "MSG_???"); 958 } 959 } else { 960 if (verbose(tcp)) 961 decode_mmsg(tcp, (unsigned long) -1L); 962 } 963 return 0; 964} 965 966SYS_FUNC(recv) 967{ 968 if (entering(tcp)) { 969 printfd(tcp, tcp->u_arg[0]); 970 tprints(", "); 971 } else { 972 if (syserror(tcp)) 973 printaddr(tcp->u_arg[1]); 974 else 975 printstr(tcp, tcp->u_arg[1], tcp->u_rval); 976 977 tprintf(", %lu, ", tcp->u_arg[2]); 978 printflags(msg_flags, tcp->u_arg[3], "MSG_???"); 979 } 980 return 0; 981} 982 983SYS_FUNC(recvfrom) 984{ 985 int fromlen; 986 987 if (entering(tcp)) { 988 printfd(tcp, tcp->u_arg[0]); 989 tprints(", "); 990 } else { 991 /* buf */ 992 if (syserror(tcp)) { 993 printaddr(tcp->u_arg[1]); 994 } else { 995 printstr(tcp, tcp->u_arg[1], tcp->u_rval); 996 } 997 /* len */ 998 tprintf(", %lu, ", tcp->u_arg[2]); 999 /* flags */ 1000 printflags(msg_flags, tcp->u_arg[3], "MSG_???"); 1001 tprints(", "); 1002 if (syserror(tcp) || !tcp->u_arg[4] || !tcp->u_arg[5] || 1003 umove(tcp, tcp->u_arg[5], &fromlen) < 0) { 1004 /* from address, len */ 1005 printaddr(tcp->u_arg[4]); 1006 tprints(", "); 1007 printaddr(tcp->u_arg[5]); 1008 return 0; 1009 } 1010 /* from address */ 1011 printsock(tcp, tcp->u_arg[4], fromlen); 1012 /* from length */ 1013 tprintf(", [%u]", fromlen); 1014 } 1015 return 0; 1016} 1017 1018SYS_FUNC(recvmsg) 1019{ 1020 if (entering(tcp)) { 1021 printfd(tcp, tcp->u_arg[0]); 1022 tprints(", "); 1023 } else { 1024 if (syserror(tcp)) 1025 printaddr(tcp->u_arg[1]); 1026 else 1027 printmsghdr(tcp, tcp->u_arg[1], tcp->u_rval); 1028 /* flags */ 1029 tprints(", "); 1030 printflags(msg_flags, tcp->u_arg[2], "MSG_???"); 1031 } 1032 return 0; 1033} 1034 1035SYS_FUNC(recvmmsg) 1036{ 1037 static char str[sizeof("left") + TIMESPEC_TEXT_BUFSIZE]; 1038 1039 if (entering(tcp)) { 1040 printfd(tcp, tcp->u_arg[0]); 1041 tprints(", "); 1042 if (verbose(tcp)) { 1043 /* Abusing tcp->auxstr as temp storage. 1044 * Will be used and cleared on syscall exit. 1045 */ 1046 tcp->auxstr = sprint_timespec(tcp, tcp->u_arg[4]); 1047 } else { 1048 printaddr(tcp->u_arg[1]); 1049 tprintf(", %u, ", (unsigned int) tcp->u_arg[2]); 1050 printflags(msg_flags, tcp->u_arg[3], "MSG_???"); 1051 tprints(", "); 1052 print_timespec(tcp, tcp->u_arg[4]); 1053 } 1054 return 0; 1055 } else { 1056 if (verbose(tcp)) { 1057 decode_mmsg(tcp, 0); 1058 tprints(", "); 1059 /* timeout on entrance */ 1060 tprints(tcp->auxstr); 1061 tcp->auxstr = NULL; 1062 } 1063 if (syserror(tcp)) 1064 return 0; 1065 if (tcp->u_rval == 0) { 1066 tcp->auxstr = "Timeout"; 1067 return RVAL_STR; 1068 } 1069 if (!verbose(tcp)) 1070 return 0; 1071 /* timeout on exit */ 1072 snprintf(str, sizeof(str), "left %s", 1073 sprint_timespec(tcp, tcp->u_arg[4])); 1074 tcp->auxstr = str; 1075 return RVAL_STR; 1076 } 1077} 1078 1079#include "xlat/shutdown_modes.h" 1080 1081SYS_FUNC(shutdown) 1082{ 1083 printfd(tcp, tcp->u_arg[0]); 1084 tprints(", "); 1085 printxval(shutdown_modes, tcp->u_arg[1], "SHUT_???"); 1086 1087 return RVAL_DECODED; 1088} 1089 1090SYS_FUNC(getsockname) 1091{ 1092 return do_sockname(tcp, -1); 1093} 1094 1095static void 1096printpair_fd(struct tcb *tcp, const int i0, const int i1) 1097{ 1098 tprints("["); 1099 printfd(tcp, i0); 1100 tprints(", "); 1101 printfd(tcp, i1); 1102 tprints("]"); 1103} 1104 1105static void 1106decode_pair_fd(struct tcb *tcp, const long addr) 1107{ 1108 int pair[2]; 1109 1110 if (umove_or_printaddr(tcp, addr, &pair)) 1111 return; 1112 1113 printpair_fd(tcp, pair[0], pair[1]); 1114} 1115 1116static int 1117do_pipe(struct tcb *tcp, int flags_arg) 1118{ 1119 if (exiting(tcp)) { 1120 decode_pair_fd(tcp, tcp->u_arg[0]); 1121 if (flags_arg >= 0) { 1122 tprints(", "); 1123 printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???"); 1124 } 1125 } 1126 return 0; 1127} 1128 1129SYS_FUNC(pipe) 1130{ 1131#ifdef HAVE_GETRVAL2 1132 if (exiting(tcp) && !syserror(tcp)) 1133 printpair_fd(tcp, tcp->u_rval, getrval2(tcp)); 1134 return 0; 1135#else 1136 return do_pipe(tcp, -1); 1137#endif 1138} 1139 1140SYS_FUNC(pipe2) 1141{ 1142 return do_pipe(tcp, 1); 1143} 1144 1145SYS_FUNC(socketpair) 1146{ 1147 if (entering(tcp)) { 1148 printxval(addrfams, tcp->u_arg[0], "AF_???"); 1149 tprints(", "); 1150 tprint_sock_type(tcp->u_arg[1]); 1151 tprintf(", %lu", tcp->u_arg[2]); 1152 } else { 1153 tprints(", "); 1154 decode_pair_fd(tcp, tcp->u_arg[3]); 1155 } 1156 return 0; 1157} 1158 1159#include "xlat/sockoptions.h" 1160#include "xlat/sockipoptions.h" 1161#include "xlat/getsockipoptions.h" 1162#include "xlat/setsockipoptions.h" 1163#include "xlat/sockipv6options.h" 1164#include "xlat/getsockipv6options.h" 1165#include "xlat/setsockipv6options.h" 1166#include "xlat/sockipxoptions.h" 1167#include "xlat/sockrawoptions.h" 1168#include "xlat/sockpacketoptions.h" 1169#include "xlat/socksctpoptions.h" 1170#include "xlat/socktcpoptions.h" 1171 1172static void 1173print_sockopt_fd_level_name(struct tcb *tcp, int fd, unsigned int level, 1174 unsigned int name, bool is_getsockopt) 1175{ 1176 printfd(tcp, fd); 1177 tprints(", "); 1178 printxval(socketlayers, level, "SOL_??"); 1179 tprints(", "); 1180 1181 switch (level) { 1182 case SOL_SOCKET: 1183 printxval(sockoptions, name, "SO_???"); 1184 break; 1185 case SOL_IP: 1186 printxvals(name, "IP_???", sockipoptions, 1187 is_getsockopt ? getsockipoptions : setsockipoptions, NULL); 1188 break; 1189 case SOL_IPV6: 1190 printxvals(name, "IPV6_???", sockipv6options, 1191 is_getsockopt ? getsockipv6options : setsockipv6options, NULL); 1192 break; 1193 case SOL_IPX: 1194 printxval(sockipxoptions, name, "IPX_???"); 1195 break; 1196 case SOL_PACKET: 1197 printxval(sockpacketoptions, name, "PACKET_???"); 1198 break; 1199 case SOL_TCP: 1200 printxval(socktcpoptions, name, "TCP_???"); 1201 break; 1202 case SOL_SCTP: 1203 printxval(socksctpoptions, name, "SCTP_???"); 1204 break; 1205 case SOL_RAW: 1206 printxval(sockrawoptions, name, "RAW_???"); 1207 break; 1208 1209 /* Other SOL_* protocol levels still need work. */ 1210 1211 default: 1212 tprintf("%u", name); 1213 } 1214 1215 tprints(", "); 1216} 1217 1218static void 1219print_linger(struct tcb *tcp, long addr, int len) 1220{ 1221 struct linger linger; 1222 1223 if (len != sizeof(linger) || 1224 umove(tcp, addr, &linger) < 0) { 1225 printaddr(addr); 1226 return; 1227 } 1228 1229 tprintf("{onoff=%d, linger=%d}", 1230 linger.l_onoff, 1231 linger.l_linger); 1232} 1233 1234#ifdef SO_PEERCRED 1235static void 1236print_ucred(struct tcb *tcp, long addr, int len) 1237{ 1238 struct ucred uc; 1239 1240 if (len != sizeof(uc) || 1241 umove(tcp, addr, &uc) < 0) { 1242 printaddr(addr); 1243 } else { 1244 tprintf("{pid=%u, uid=%u, gid=%u}", 1245 (unsigned) uc.pid, 1246 (unsigned) uc.uid, 1247 (unsigned) uc.gid); 1248 } 1249} 1250#endif /* SO_PEERCRED */ 1251 1252#ifdef PACKET_STATISTICS 1253static void 1254print_tpacket_stats(struct tcb *tcp, long addr, int len) 1255{ 1256 struct tpacket_stats stats; 1257 1258 if (len != sizeof(stats) || 1259 umove(tcp, addr, &stats) < 0) { 1260 printaddr(addr); 1261 } else { 1262 tprintf("{packets=%u, drops=%u}", 1263 stats.tp_packets, 1264 stats.tp_drops); 1265 } 1266} 1267#endif /* PACKET_STATISTICS */ 1268 1269#include "xlat/icmpfilterflags.h" 1270 1271static void 1272print_icmp_filter(struct tcb *tcp, const long addr, int len) 1273{ 1274 struct icmp_filter filter = {}; 1275 1276 if (len > (int) sizeof(filter)) 1277 len = sizeof(filter); 1278 else if (len <= 0) { 1279 printaddr(addr); 1280 return; 1281 } 1282 1283 if (umoven_or_printaddr(tcp, addr, len, &filter)) 1284 return; 1285 1286 tprints("~("); 1287 printflags(icmpfilterflags, ~filter.data, "ICMP_???"); 1288 tprints(")"); 1289} 1290 1291static void 1292print_getsockopt(struct tcb *tcp, unsigned int level, unsigned int name, 1293 long addr, int len) 1294{ 1295 if (addr && verbose(tcp)) 1296 switch (level) { 1297 case SOL_SOCKET: 1298 switch (name) { 1299 case SO_LINGER: 1300 print_linger(tcp, addr, len); 1301 goto done; 1302#ifdef SO_PEERCRED 1303 case SO_PEERCRED: 1304 print_ucred(tcp, addr, len); 1305 goto done; 1306#endif 1307 } 1308 break; 1309 1310 case SOL_PACKET: 1311 switch (name) { 1312#ifdef PACKET_STATISTICS 1313 case PACKET_STATISTICS: 1314 print_tpacket_stats(tcp, addr, len); 1315 goto done; 1316#endif 1317 } 1318 break; 1319 1320 case SOL_RAW: 1321 switch (name) { 1322 case ICMP_FILTER: 1323 print_icmp_filter(tcp, addr, len); 1324 goto done; 1325 } 1326 break; 1327 } 1328 1329 /* default arg printing */ 1330 1331 if (verbose(tcp)) { 1332 if (len == sizeof(int)) { 1333 printnum_int(tcp, addr, "%d"); 1334 } else { 1335 printstr(tcp, addr, len); 1336 } 1337 } else { 1338 printaddr(addr); 1339 } 1340done: 1341 tprintf(", [%d]", len); 1342} 1343 1344SYS_FUNC(getsockopt) 1345{ 1346 if (entering(tcp)) { 1347 print_sockopt_fd_level_name(tcp, tcp->u_arg[0], 1348 tcp->u_arg[1], tcp->u_arg[2], true); 1349 } else { 1350 int len; 1351 1352 if (syserror(tcp) || umove(tcp, tcp->u_arg[4], &len) < 0) { 1353 printaddr(tcp->u_arg[3]); 1354 tprints(", "); 1355 printaddr(tcp->u_arg[4]); 1356 } else { 1357 print_getsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2], 1358 tcp->u_arg[3], len); 1359 } 1360 } 1361 return 0; 1362} 1363 1364#ifdef IP_ADD_MEMBERSHIP 1365static void 1366print_mreq(struct tcb *tcp, long addr, unsigned int len) 1367{ 1368 struct ip_mreq mreq; 1369 1370 if (len < sizeof(mreq)) { 1371 printstr(tcp, addr, len); 1372 return; 1373 } 1374 if (umove_or_printaddr(tcp, addr, &mreq)) 1375 return; 1376 1377 tprints("{imr_multiaddr=inet_addr("); 1378 print_quoted_string(inet_ntoa(mreq.imr_multiaddr), 1379 16, QUOTE_0_TERMINATED); 1380 tprints("), imr_interface=inet_addr("); 1381 print_quoted_string(inet_ntoa(mreq.imr_interface), 1382 16, QUOTE_0_TERMINATED); 1383 tprints(")}"); 1384} 1385#endif /* IP_ADD_MEMBERSHIP */ 1386 1387#ifdef IPV6_ADD_MEMBERSHIP 1388static void 1389print_mreq6(struct tcb *tcp, long addr, unsigned int len) 1390{ 1391 struct ipv6_mreq mreq; 1392 1393 if (len < sizeof(mreq)) 1394 goto fail; 1395 1396 if (umove_or_printaddr(tcp, addr, &mreq)) 1397 return; 1398 1399 const struct in6_addr *in6 = &mreq.ipv6mr_multiaddr; 1400 char address[INET6_ADDRSTRLEN]; 1401 1402 if (!inet_ntop(AF_INET6, in6, address, sizeof(address))) 1403 goto fail; 1404 1405 tprints("{ipv6mr_multiaddr=inet_pton("); 1406 print_quoted_string(address, sizeof(address), QUOTE_0_TERMINATED); 1407 tprints("), ipv6mr_interface="); 1408 print_ifindex(mreq.ipv6mr_interface); 1409 tprints("}"); 1410 return; 1411 1412fail: 1413 printstr(tcp, addr, len); 1414} 1415#endif /* IPV6_ADD_MEMBERSHIP */ 1416 1417#ifdef MCAST_JOIN_GROUP 1418static void 1419print_group_req(struct tcb *tcp, long addr, int len) 1420{ 1421 struct group_req greq; 1422 1423 if (len != sizeof(greq) || 1424 umove(tcp, addr, &greq) < 0) { 1425 printaddr(addr); 1426 return; 1427 } 1428 1429 tprintf("{gr_interface=%u, gr_group=", greq.gr_interface); 1430 print_sockaddr(tcp, &greq.gr_group, sizeof(greq.gr_group)); 1431 tprintf("}"); 1432 1433} 1434#endif /* MCAST_JOIN_GROUP */ 1435 1436#ifdef PACKET_RX_RING 1437static void 1438print_tpacket_req(struct tcb *tcp, long addr, int len) 1439{ 1440 struct tpacket_req req; 1441 1442 if (len != sizeof(req) || 1443 umove(tcp, addr, &req) < 0) { 1444 printaddr(addr); 1445 } else { 1446 tprintf("{block_size=%u, block_nr=%u, " 1447 "frame_size=%u, frame_nr=%u}", 1448 req.tp_block_size, 1449 req.tp_block_nr, 1450 req.tp_frame_size, 1451 req.tp_frame_nr); 1452 } 1453} 1454#endif /* PACKET_RX_RING */ 1455 1456#ifdef PACKET_ADD_MEMBERSHIP 1457# include "xlat/packet_mreq_type.h" 1458 1459static void 1460print_packet_mreq(struct tcb *tcp, long addr, int len) 1461{ 1462 struct packet_mreq mreq; 1463 1464 if (len != sizeof(mreq) || 1465 umove(tcp, addr, &mreq) < 0) { 1466 printaddr(addr); 1467 } else { 1468 unsigned int i; 1469 1470 tprintf("{mr_ifindex=%u, mr_type=", mreq.mr_ifindex); 1471 printxval(packet_mreq_type, mreq.mr_type, "PACKET_MR_???"); 1472 tprintf(", mr_alen=%u, mr_address=", mreq.mr_alen); 1473 if (mreq.mr_alen > ARRAY_SIZE(mreq.mr_address)) 1474 mreq.mr_alen = ARRAY_SIZE(mreq.mr_address); 1475 for (i = 0; i < mreq.mr_alen; ++i) 1476 tprintf("%02x", mreq.mr_address[i]); 1477 tprints("}"); 1478 } 1479} 1480#endif /* PACKET_ADD_MEMBERSHIP */ 1481 1482static void 1483print_setsockopt(struct tcb *tcp, unsigned int level, unsigned int name, 1484 long addr, int len) 1485{ 1486 if (addr && verbose(tcp)) 1487 switch (level) { 1488 case SOL_SOCKET: 1489 switch (name) { 1490 case SO_LINGER: 1491 print_linger(tcp, addr, len); 1492 goto done; 1493 } 1494 break; 1495 1496 case SOL_IP: 1497 switch (name) { 1498#ifdef IP_ADD_MEMBERSHIP 1499 case IP_ADD_MEMBERSHIP: 1500 case IP_DROP_MEMBERSHIP: 1501 print_mreq(tcp, addr, len); 1502 goto done; 1503#endif /* IP_ADD_MEMBERSHIP */ 1504#ifdef MCAST_JOIN_GROUP 1505 case MCAST_JOIN_GROUP: 1506 case MCAST_LEAVE_GROUP: 1507 print_group_req(tcp, addr, len); 1508 goto done; 1509#endif /* MCAST_JOIN_GROUP */ 1510 } 1511 break; 1512 1513 case SOL_IPV6: 1514 switch (name) { 1515#ifdef IPV6_ADD_MEMBERSHIP 1516 case IPV6_ADD_MEMBERSHIP: 1517 case IPV6_DROP_MEMBERSHIP: 1518# ifdef IPV6_JOIN_ANYCAST 1519 case IPV6_JOIN_ANYCAST: 1520# endif 1521# ifdef IPV6_LEAVE_ANYCAST 1522 case IPV6_LEAVE_ANYCAST: 1523# endif 1524 print_mreq6(tcp, addr, len); 1525 goto done; 1526#endif /* IPV6_ADD_MEMBERSHIP */ 1527 } 1528 break; 1529 1530 case SOL_PACKET: 1531 switch (name) { 1532#ifdef PACKET_RX_RING 1533 case PACKET_RX_RING: 1534# ifdef PACKET_TX_RING 1535 case PACKET_TX_RING: 1536# endif 1537 print_tpacket_req(tcp, addr, len); 1538 goto done; 1539#endif /* PACKET_RX_RING */ 1540#ifdef PACKET_ADD_MEMBERSHIP 1541 case PACKET_ADD_MEMBERSHIP: 1542 case PACKET_DROP_MEMBERSHIP: 1543 print_packet_mreq(tcp, addr, len); 1544 goto done; 1545#endif /* PACKET_ADD_MEMBERSHIP */ 1546 } 1547 break; 1548 1549 case SOL_RAW: 1550 switch (name) { 1551 case ICMP_FILTER: 1552 print_icmp_filter(tcp, addr, len); 1553 goto done; 1554 } 1555 break; 1556 } 1557 1558 /* default arg printing */ 1559 1560 if (verbose(tcp)) { 1561 if (len == sizeof(int)) { 1562 printnum_int(tcp, addr, "%d"); 1563 } else { 1564 printstr(tcp, addr, len); 1565 } 1566 } else { 1567 printaddr(addr); 1568 } 1569done: 1570 tprintf(", %d", len); 1571} 1572 1573SYS_FUNC(setsockopt) 1574{ 1575 print_sockopt_fd_level_name(tcp, tcp->u_arg[0], 1576 tcp->u_arg[1], tcp->u_arg[2], false); 1577 print_setsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2], 1578 tcp->u_arg[3], tcp->u_arg[4]); 1579 1580 return RVAL_DECODED; 1581} 1582