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