1 /* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk (at) cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko (at) hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com> 5 * Copyright (c) 1996-2000 Wichert Akkerman <wichert (at) cistron.nl> 6 * Copyright (c) 1999-2018 The strace developers. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "defs.h" 33 #include "print_fields.h" 34 35 #include <sys/stat.h> 36 #include <sys/socket.h> 37 #include <sys/uio.h> 38 #include <sys/un.h> 39 #include <netinet/in.h> 40 #ifdef HAVE_NETINET_TCP_H 41 # include <netinet/tcp.h> 42 #endif 43 #ifdef HAVE_NETINET_UDP_H 44 # include <netinet/udp.h> 45 #endif 46 #ifdef HAVE_NETINET_SCTP_H 47 # include <netinet/sctp.h> 48 #endif 49 #include <arpa/inet.h> 50 #include <net/if.h> 51 #include <asm/types.h> 52 #ifdef HAVE_NETIPX_IPX_H 53 # include <netipx/ipx.h> 54 #else 55 # include <linux/ipx.h> 56 #endif 57 58 #if defined(HAVE_LINUX_IP_VS_H) 59 # include <linux/ip_vs.h> 60 #endif 61 #include "netlink.h" 62 #if defined(HAVE_LINUX_NETFILTER_ARP_ARP_TABLES_H) 63 # include <linux/netfilter_arp/arp_tables.h> 64 #endif 65 #if defined(HAVE_LINUX_NETFILTER_BRIDGE_EBTABLES_H) 66 # include <linux/netfilter_bridge/ebtables.h> 67 #endif 68 #if defined(HAVE_LINUX_NETFILTER_IPV4_IP_TABLES_H) 69 # include <linux/netfilter_ipv4/ip_tables.h> 70 #endif 71 #if defined(HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H) 72 # include <linux/netfilter_ipv6/ip6_tables.h> 73 #endif 74 #include <linux/if_packet.h> 75 #include <linux/icmp.h> 76 77 #include "xlat/socktypes.h" 78 #include "xlat/sock_type_flags.h" 79 #ifndef SOCK_TYPE_MASK 80 # define SOCK_TYPE_MASK 0xf 81 #endif 82 83 #include "xlat/socketlayers.h" 84 85 #include "xlat/inet_protocols.h" 86 87 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H 88 # include <bluetooth/bluetooth.h> 89 # include "xlat/bt_protocols.h" 90 #endif 91 92 static void 93 decode_sockbuf(struct tcb *const tcp, const int fd, const kernel_ulong_t addr, 94 const kernel_ulong_t addrlen) 95 { 96 97 switch (verbose(tcp) ? getfdproto(tcp, fd) : SOCK_PROTO_UNKNOWN) { 98 case SOCK_PROTO_NETLINK: 99 decode_netlink(tcp, fd, addr, addrlen); 100 break; 101 default: 102 printstrn(tcp, addr, addrlen); 103 } 104 } 105 106 /* 107 * low bits of the socket type define real socket type, 108 * other bits are socket type flags. 109 */ 110 static void 111 tprint_sock_type(unsigned int flags) 112 { 113 const char *str = xlookup(socktypes, flags & SOCK_TYPE_MASK); 114 115 if (str) { 116 tprints(str); 117 flags &= ~SOCK_TYPE_MASK; 118 if (!flags) 119 return; 120 tprints("|"); 121 } 122 printflags(sock_type_flags, flags, "SOCK_???"); 123 } 124 125 SYS_FUNC(socket) 126 { 127 printxval(addrfams, tcp->u_arg[0], "AF_???"); 128 tprints(", "); 129 tprint_sock_type(tcp->u_arg[1]); 130 tprints(", "); 131 switch (tcp->u_arg[0]) { 132 case AF_INET: 133 case AF_INET6: 134 printxval(inet_protocols, tcp->u_arg[2], "IPPROTO_???"); 135 break; 136 137 case AF_NETLINK: 138 printxval(netlink_protocols, tcp->u_arg[2], "NETLINK_???"); 139 break; 140 141 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H 142 case AF_BLUETOOTH: 143 printxval(bt_protocols, tcp->u_arg[2], "BTPROTO_???"); 144 break; 145 #endif 146 147 default: 148 tprintf("%" PRI_klu, tcp->u_arg[2]); 149 break; 150 } 151 152 return RVAL_DECODED | RVAL_FD; 153 } 154 155 static bool 156 fetch_socklen(struct tcb *const tcp, int *const plen, 157 const kernel_ulong_t sockaddr, const kernel_ulong_t socklen) 158 { 159 return verbose(tcp) && sockaddr && socklen 160 && umove(tcp, socklen, plen) == 0; 161 } 162 163 static int 164 decode_sockname(struct tcb *tcp) 165 { 166 int ulen, rlen; 167 168 if (entering(tcp)) { 169 printfd(tcp, tcp->u_arg[0]); 170 tprints(", "); 171 if (fetch_socklen(tcp, &ulen, tcp->u_arg[1], tcp->u_arg[2])) { 172 set_tcb_priv_ulong(tcp, ulen); 173 return 0; 174 } else { 175 printaddr(tcp->u_arg[1]); 176 tprints(", "); 177 printaddr(tcp->u_arg[2]); 178 return RVAL_DECODED; 179 } 180 } 181 182 ulen = get_tcb_priv_ulong(tcp); 183 184 if (syserror(tcp) || umove(tcp, tcp->u_arg[2], &rlen) < 0) { 185 printaddr(tcp->u_arg[1]); 186 tprintf(", [%d]", ulen); 187 } else { 188 decode_sockaddr(tcp, tcp->u_arg[1], ulen > rlen ? rlen : ulen); 189 if (ulen != rlen) 190 tprintf(", [%d->%d]", ulen, rlen); 191 else 192 tprintf(", [%d]", rlen); 193 } 194 195 return RVAL_DECODED; 196 } 197 198 SYS_FUNC(accept) 199 { 200 return decode_sockname(tcp) | RVAL_FD; 201 } 202 203 SYS_FUNC(accept4) 204 { 205 int rc = decode_sockname(tcp); 206 207 if (rc & RVAL_DECODED) { 208 tprints(", "); 209 printflags(sock_type_flags, tcp->u_arg[3], "SOCK_???"); 210 } 211 212 return rc | RVAL_FD; 213 } 214 215 SYS_FUNC(send) 216 { 217 printfd(tcp, tcp->u_arg[0]); 218 tprints(", "); 219 decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]); 220 tprintf(", %" PRI_klu ", ", tcp->u_arg[2]); 221 /* flags */ 222 printflags(msg_flags, tcp->u_arg[3], "MSG_???"); 223 224 return RVAL_DECODED; 225 } 226 227 SYS_FUNC(sendto) 228 { 229 printfd(tcp, tcp->u_arg[0]); 230 tprints(", "); 231 decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]); 232 tprintf(", %" PRI_klu ", ", tcp->u_arg[2]); 233 /* flags */ 234 printflags(msg_flags, tcp->u_arg[3], "MSG_???"); 235 /* to address */ 236 const int addrlen = tcp->u_arg[5]; 237 tprints(", "); 238 decode_sockaddr(tcp, tcp->u_arg[4], addrlen); 239 /* to length */ 240 tprintf(", %d", addrlen); 241 242 return RVAL_DECODED; 243 } 244 245 SYS_FUNC(recv) 246 { 247 if (entering(tcp)) { 248 printfd(tcp, tcp->u_arg[0]); 249 tprints(", "); 250 } else { 251 if (syserror(tcp)) { 252 printaddr(tcp->u_arg[1]); 253 } else { 254 decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1], 255 tcp->u_rval); 256 } 257 258 tprintf(", %" PRI_klu ", ", tcp->u_arg[2]); 259 printflags(msg_flags, tcp->u_arg[3], "MSG_???"); 260 } 261 return 0; 262 } 263 264 SYS_FUNC(recvfrom) 265 { 266 int ulen, rlen; 267 268 if (entering(tcp)) { 269 printfd(tcp, tcp->u_arg[0]); 270 tprints(", "); 271 if (fetch_socklen(tcp, &ulen, tcp->u_arg[4], tcp->u_arg[5])) { 272 set_tcb_priv_ulong(tcp, ulen); 273 } 274 } else { 275 /* buf */ 276 if (syserror(tcp)) { 277 printaddr(tcp->u_arg[1]); 278 } else { 279 decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1], 280 tcp->u_rval); 281 } 282 /* size */ 283 tprintf(", %" PRI_klu ", ", tcp->u_arg[2]); 284 /* flags */ 285 printflags(msg_flags, tcp->u_arg[3], "MSG_???"); 286 tprints(", "); 287 288 ulen = get_tcb_priv_ulong(tcp); 289 290 if (!fetch_socklen(tcp, &rlen, tcp->u_arg[4], tcp->u_arg[5])) { 291 /* from address */ 292 printaddr(tcp->u_arg[4]); 293 tprints(", "); 294 /* from length */ 295 printaddr(tcp->u_arg[5]); 296 return 0; 297 } 298 if (syserror(tcp)) { 299 /* from address */ 300 printaddr(tcp->u_arg[4]); 301 /* from length */ 302 tprintf(", [%d]", ulen); 303 return 0; 304 } 305 /* from address */ 306 decode_sockaddr(tcp, tcp->u_arg[4], ulen > rlen ? rlen : ulen); 307 /* from length */ 308 if (ulen != rlen) 309 tprintf(", [%d->%d]", ulen, rlen); 310 else 311 tprintf(", [%d]", rlen); 312 } 313 return 0; 314 } 315 316 SYS_FUNC(getsockname) 317 { 318 return decode_sockname(tcp); 319 } 320 321 static void 322 printpair_fd(struct tcb *tcp, const int i0, const int i1) 323 { 324 tprints("["); 325 printfd(tcp, i0); 326 tprints(", "); 327 printfd(tcp, i1); 328 tprints("]"); 329 } 330 331 static void 332 decode_pair_fd(struct tcb *const tcp, const kernel_ulong_t addr) 333 { 334 int pair[2]; 335 336 if (umove_or_printaddr(tcp, addr, &pair)) 337 return; 338 339 printpair_fd(tcp, pair[0], pair[1]); 340 } 341 342 static int 343 do_pipe(struct tcb *tcp, int flags_arg) 344 { 345 if (exiting(tcp)) { 346 decode_pair_fd(tcp, tcp->u_arg[0]); 347 if (flags_arg >= 0) { 348 tprints(", "); 349 printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???"); 350 } 351 } 352 return 0; 353 } 354 355 SYS_FUNC(pipe) 356 { 357 #if HAVE_ARCH_GETRVAL2 358 if (exiting(tcp) && !syserror(tcp)) 359 printpair_fd(tcp, tcp->u_rval, getrval2(tcp)); 360 return 0; 361 #else 362 return do_pipe(tcp, -1); 363 #endif 364 } 365 366 SYS_FUNC(pipe2) 367 { 368 return do_pipe(tcp, 1); 369 } 370 371 SYS_FUNC(socketpair) 372 { 373 if (entering(tcp)) { 374 printxval(addrfams, tcp->u_arg[0], "AF_???"); 375 tprints(", "); 376 tprint_sock_type(tcp->u_arg[1]); 377 tprintf(", %" PRI_klu, tcp->u_arg[2]); 378 } else { 379 tprints(", "); 380 decode_pair_fd(tcp, tcp->u_arg[3]); 381 } 382 return 0; 383 } 384 385 #include "xlat/sockoptions.h" 386 #include "xlat/sockipoptions.h" 387 #include "xlat/getsockipoptions.h" 388 #include "xlat/setsockipoptions.h" 389 #include "xlat/sockipv6options.h" 390 #include "xlat/getsockipv6options.h" 391 #include "xlat/setsockipv6options.h" 392 #include "xlat/sockipxoptions.h" 393 #include "xlat/socknetlinkoptions.h" 394 #include "xlat/sockpacketoptions.h" 395 #include "xlat/sockrawoptions.h" 396 #include "xlat/socksctpoptions.h" 397 #include "xlat/socktcpoptions.h" 398 399 static void 400 print_sockopt_fd_level_name(struct tcb *tcp, int fd, unsigned int level, 401 unsigned int name, bool is_getsockopt) 402 { 403 printfd(tcp, fd); 404 tprints(", "); 405 printxval(socketlayers, level, "SOL_??"); 406 tprints(", "); 407 408 switch (level) { 409 case SOL_SOCKET: 410 printxval(sockoptions, name, "SO_???"); 411 break; 412 case SOL_IP: 413 printxvals(name, "IP_???", sockipoptions, 414 is_getsockopt ? getsockipoptions : setsockipoptions, NULL); 415 break; 416 case SOL_IPV6: 417 printxvals(name, "IPV6_???", sockipv6options, 418 is_getsockopt ? getsockipv6options : setsockipv6options, NULL); 419 break; 420 case SOL_IPX: 421 printxval(sockipxoptions, name, "IPX_???"); 422 break; 423 case SOL_PACKET: 424 printxval(sockpacketoptions, name, "PACKET_???"); 425 break; 426 case SOL_TCP: 427 printxval(socktcpoptions, name, "TCP_???"); 428 break; 429 case SOL_SCTP: 430 printxval(socksctpoptions, name, "SCTP_???"); 431 break; 432 case SOL_RAW: 433 printxval(sockrawoptions, name, "RAW_???"); 434 break; 435 case SOL_NETLINK: 436 printxval(socknetlinkoptions, name, "NETLINK_???"); 437 break; 438 439 /* Other SOL_* protocol levels still need work. */ 440 441 default: 442 tprintf("%u", name); 443 } 444 445 tprints(", "); 446 } 447 448 static void 449 print_set_linger(struct tcb *const tcp, const kernel_ulong_t addr, 450 const int len) 451 { 452 struct linger linger; 453 454 if (len < (int) sizeof(linger)) { 455 printaddr(addr); 456 } else if (!umove_or_printaddr(tcp, addr, &linger)) { 457 PRINT_FIELD_D("{", linger, l_onoff); 458 PRINT_FIELD_D(", ", linger, l_linger); 459 tprints("}"); 460 } 461 } 462 463 static void 464 print_get_linger(struct tcb *const tcp, const kernel_ulong_t addr, 465 unsigned int len) 466 { 467 struct linger linger; 468 469 if (len < sizeof(linger)) { 470 if (len != sizeof(linger.l_onoff)) { 471 printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX); 472 return; 473 } 474 } else { 475 len = sizeof(linger); 476 } 477 478 if (umoven(tcp, addr, len, &linger) < 0) { 479 printaddr(addr); 480 return; 481 } 482 483 PRINT_FIELD_D("{", linger, l_onoff); 484 if (len == sizeof(linger)) 485 PRINT_FIELD_D(", ", linger, l_linger); 486 tprints("}"); 487 } 488 489 #ifdef SO_PEERCRED 490 static void 491 print_ucred(struct tcb *const tcp, const kernel_ulong_t addr, unsigned int len) 492 { 493 struct ucred uc; 494 495 if (len < sizeof(uc)) { 496 if (len != sizeof(uc.pid) 497 && len != offsetofend(struct ucred, uid)) { 498 printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX); 499 return; 500 } 501 } else { 502 len = sizeof(uc); 503 } 504 505 if (umoven(tcp, addr, len, &uc) < 0) { 506 printaddr(addr); 507 return; 508 } 509 510 PRINT_FIELD_D("{", uc, pid); 511 if (len > sizeof(uc.pid)) 512 PRINT_FIELD_UID(", ", uc, uid); 513 if (len == sizeof(uc)) 514 PRINT_FIELD_UID(", ", uc, gid); 515 tprints("}"); 516 } 517 #endif /* SO_PEERCRED */ 518 519 #ifdef PACKET_STATISTICS 520 static void 521 print_tpacket_stats(struct tcb *const tcp, const kernel_ulong_t addr, 522 const int len) 523 { 524 struct tpacket_stats stats; 525 526 if (len != sizeof(stats) || 527 umove(tcp, addr, &stats) < 0) { 528 printaddr(addr); 529 } else { 530 PRINT_FIELD_U("{", stats, tp_packets); 531 PRINT_FIELD_U("{", stats, tp_drops); 532 tprints("}"); 533 } 534 } 535 #endif /* PACKET_STATISTICS */ 536 537 #include "xlat/icmpfilterflags.h" 538 539 static void 540 print_icmp_filter(struct tcb *const tcp, const kernel_ulong_t addr, int len) 541 { 542 struct icmp_filter filter = {}; 543 544 if (len > (int) sizeof(filter)) 545 len = sizeof(filter); 546 else if (len <= 0) { 547 printaddr(addr); 548 return; 549 } 550 551 if (umoven_or_printaddr(tcp, addr, len, &filter)) 552 return; 553 554 tprints("~("); 555 printflags(icmpfilterflags, ~filter.data, "ICMP_???"); 556 tprints(")"); 557 } 558 559 static bool 560 print_uint32(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data) 561 { 562 tprintf("%u", *(uint32_t *) elem_buf); 563 564 return true; 565 } 566 567 static void 568 print_getsockopt(struct tcb *const tcp, const unsigned int level, 569 const unsigned int name, const kernel_ulong_t addr, 570 const int ulen, const int rlen) 571 { 572 if (addr && verbose(tcp)) 573 switch (level) { 574 case SOL_SOCKET: 575 switch (name) { 576 case SO_LINGER: 577 print_get_linger(tcp, addr, rlen); 578 return; 579 #ifdef SO_PEERCRED 580 case SO_PEERCRED: 581 print_ucred(tcp, addr, rlen); 582 return; 583 #endif 584 #ifdef SO_ATTACH_FILTER 585 case SO_ATTACH_FILTER: 586 if (rlen && (unsigned short) rlen == (unsigned int) rlen) 587 print_sock_fprog(tcp, addr, rlen); 588 else 589 printaddr(addr); 590 return; 591 #endif /* SO_ATTACH_FILTER */ 592 } 593 break; 594 595 case SOL_PACKET: 596 switch (name) { 597 #ifdef PACKET_STATISTICS 598 case PACKET_STATISTICS: 599 print_tpacket_stats(tcp, addr, rlen); 600 return; 601 #endif 602 } 603 break; 604 605 case SOL_RAW: 606 switch (name) { 607 case ICMP_FILTER: 608 print_icmp_filter(tcp, addr, rlen); 609 return; 610 } 611 break; 612 613 case SOL_NETLINK: 614 if (ulen < 0 || rlen < 0) { 615 /* 616 * As the kernel neither accepts nor returns a negative 617 * length, in case of successful getsockopt syscall 618 * invocation these negative values must have come 619 * from userspace. 620 */ 621 printaddr(addr); 622 return; 623 } 624 switch (name) { 625 case NETLINK_LIST_MEMBERSHIPS: { 626 uint32_t buf; 627 print_array(tcp, addr, MIN(ulen, rlen) / sizeof(buf), 628 &buf, sizeof(buf), 629 umoven_or_printaddr, print_uint32, 0); 630 break; 631 } 632 default: 633 printnum_int(tcp, addr, "%d"); 634 break; 635 } 636 return; 637 } 638 639 /* default arg printing */ 640 641 if (verbose(tcp)) { 642 if (rlen == sizeof(int)) { 643 printnum_int(tcp, addr, "%d"); 644 } else { 645 printstrn(tcp, addr, rlen); 646 } 647 } else { 648 printaddr(addr); 649 } 650 } 651 652 SYS_FUNC(getsockopt) 653 { 654 int ulen, rlen; 655 656 if (entering(tcp)) { 657 print_sockopt_fd_level_name(tcp, tcp->u_arg[0], 658 tcp->u_arg[1], tcp->u_arg[2], true); 659 660 if (verbose(tcp) && tcp->u_arg[4] 661 && umove(tcp, tcp->u_arg[4], &ulen) == 0) { 662 set_tcb_priv_ulong(tcp, ulen); 663 return 0; 664 } else { 665 printaddr(tcp->u_arg[3]); 666 tprints(", "); 667 printaddr(tcp->u_arg[4]); 668 return RVAL_DECODED; 669 } 670 } else { 671 ulen = get_tcb_priv_ulong(tcp); 672 673 if (syserror(tcp) || umove(tcp, tcp->u_arg[4], &rlen) < 0) { 674 printaddr(tcp->u_arg[3]); 675 tprintf(", [%d]", ulen); 676 } else { 677 print_getsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2], 678 tcp->u_arg[3], ulen, rlen); 679 if (ulen != rlen) 680 tprintf(", [%d->%d]", ulen, rlen); 681 else 682 tprintf(", [%d]", rlen); 683 } 684 } 685 return 0; 686 } 687 688 #ifdef IP_ADD_MEMBERSHIP 689 static void 690 print_mreq(struct tcb *const tcp, const kernel_ulong_t addr, 691 const int len) 692 { 693 struct ip_mreq mreq; 694 695 if (len < (int) sizeof(mreq)) { 696 printaddr(addr); 697 } else if (!umove_or_printaddr(tcp, addr, &mreq)) { 698 PRINT_FIELD_INET4_ADDR("{", mreq, imr_multiaddr); 699 PRINT_FIELD_INET4_ADDR(", ", mreq, imr_interface); 700 tprints("}"); 701 } 702 } 703 #endif /* IP_ADD_MEMBERSHIP */ 704 705 #ifdef IPV6_ADD_MEMBERSHIP 706 static void 707 print_mreq6(struct tcb *const tcp, const kernel_ulong_t addr, 708 const int len) 709 { 710 struct ipv6_mreq mreq; 711 712 if (len < (int) sizeof(mreq)) { 713 printaddr(addr); 714 } else if (!umove_or_printaddr(tcp, addr, &mreq)) { 715 PRINT_FIELD_INET_ADDR("{", mreq, ipv6mr_multiaddr, AF_INET6); 716 PRINT_FIELD_IFINDEX(", ", mreq, ipv6mr_interface); 717 tprints("}"); 718 } 719 } 720 #endif /* IPV6_ADD_MEMBERSHIP */ 721 722 #ifdef PACKET_RX_RING 723 static void 724 print_tpacket_req(struct tcb *const tcp, const kernel_ulong_t addr, const int len) 725 { 726 struct tpacket_req req; 727 728 if (len != sizeof(req) || 729 umove(tcp, addr, &req) < 0) { 730 printaddr(addr); 731 } else { 732 PRINT_FIELD_U("{", req, tp_block_size); 733 PRINT_FIELD_U(", ", req, tp_block_nr); 734 PRINT_FIELD_U(", ", req, tp_frame_size); 735 PRINT_FIELD_U(", ", req, tp_frame_nr); 736 tprints("}"); 737 } 738 } 739 #endif /* PACKET_RX_RING */ 740 741 #ifdef PACKET_ADD_MEMBERSHIP 742 # include "xlat/packet_mreq_type.h" 743 744 static void 745 print_packet_mreq(struct tcb *const tcp, const kernel_ulong_t addr, const int len) 746 { 747 struct packet_mreq mreq; 748 749 if (len != sizeof(mreq) || 750 umove(tcp, addr, &mreq) < 0) { 751 printaddr(addr); 752 } else { 753 unsigned int i; 754 755 PRINT_FIELD_IFINDEX("{", mreq, mr_ifindex); 756 PRINT_FIELD_XVAL(", ", mreq, mr_type, packet_mreq_type, 757 "PACKET_MR_???"); 758 PRINT_FIELD_U(", ", mreq, mr_alen); 759 tprints(", mr_address="); 760 if (mreq.mr_alen > ARRAY_SIZE(mreq.mr_address)) 761 mreq.mr_alen = ARRAY_SIZE(mreq.mr_address); 762 for (i = 0; i < mreq.mr_alen; ++i) 763 tprintf("%02x", mreq.mr_address[i]); 764 tprints("}"); 765 } 766 } 767 #endif /* PACKET_ADD_MEMBERSHIP */ 768 769 static void 770 print_setsockopt(struct tcb *const tcp, const unsigned int level, 771 const unsigned int name, const kernel_ulong_t addr, 772 const int len) 773 { 774 if (addr && verbose(tcp)) 775 switch (level) { 776 case SOL_SOCKET: 777 switch (name) { 778 case SO_LINGER: 779 print_set_linger(tcp, addr, len); 780 return; 781 #ifdef SO_ATTACH_FILTER 782 case SO_ATTACH_FILTER: 783 # ifdef SO_ATTACH_REUSEPORT_CBPF 784 case SO_ATTACH_REUSEPORT_CBPF: 785 # endif 786 if ((unsigned int) len == get_sock_fprog_size()) 787 decode_sock_fprog(tcp, addr); 788 else 789 printaddr(addr); 790 return; 791 #endif /* SO_ATTACH_FILTER */ 792 } 793 break; 794 795 case SOL_IP: 796 switch (name) { 797 #ifdef IP_ADD_MEMBERSHIP 798 case IP_ADD_MEMBERSHIP: 799 case IP_DROP_MEMBERSHIP: 800 print_mreq(tcp, addr, len); 801 return; 802 #endif /* IP_ADD_MEMBERSHIP */ 803 #ifdef MCAST_JOIN_GROUP 804 case MCAST_JOIN_GROUP: 805 case MCAST_LEAVE_GROUP: 806 print_group_req(tcp, addr, len); 807 return; 808 #endif /* MCAST_JOIN_GROUP */ 809 } 810 break; 811 812 case SOL_IPV6: 813 switch (name) { 814 #ifdef IPV6_ADD_MEMBERSHIP 815 case IPV6_ADD_MEMBERSHIP: 816 case IPV6_DROP_MEMBERSHIP: 817 # ifdef IPV6_JOIN_ANYCAST 818 case IPV6_JOIN_ANYCAST: 819 # endif 820 # ifdef IPV6_LEAVE_ANYCAST 821 case IPV6_LEAVE_ANYCAST: 822 # endif 823 print_mreq6(tcp, addr, len); 824 return; 825 #endif /* IPV6_ADD_MEMBERSHIP */ 826 #ifdef MCAST_JOIN_GROUP 827 case MCAST_JOIN_GROUP: 828 case MCAST_LEAVE_GROUP: 829 print_group_req(tcp, addr, len); 830 return; 831 #endif /* MCAST_JOIN_GROUP */ 832 } 833 break; 834 835 case SOL_PACKET: 836 switch (name) { 837 #ifdef PACKET_RX_RING 838 case PACKET_RX_RING: 839 # ifdef PACKET_TX_RING 840 case PACKET_TX_RING: 841 # endif 842 print_tpacket_req(tcp, addr, len); 843 return; 844 #endif /* PACKET_RX_RING */ 845 #ifdef PACKET_ADD_MEMBERSHIP 846 case PACKET_ADD_MEMBERSHIP: 847 case PACKET_DROP_MEMBERSHIP: 848 print_packet_mreq(tcp, addr, len); 849 return; 850 #endif /* PACKET_ADD_MEMBERSHIP */ 851 } 852 break; 853 854 case SOL_RAW: 855 switch (name) { 856 case ICMP_FILTER: 857 print_icmp_filter(tcp, addr, len); 858 return; 859 } 860 break; 861 862 case SOL_NETLINK: 863 if (len < (int) sizeof(int)) 864 printaddr(addr); 865 else 866 printnum_int(tcp, addr, "%d"); 867 return; 868 } 869 870 /* default arg printing */ 871 872 if (verbose(tcp)) { 873 if (len == sizeof(int)) { 874 printnum_int(tcp, addr, "%d"); 875 } else { 876 printstrn(tcp, addr, len); 877 } 878 } else { 879 printaddr(addr); 880 } 881 } 882 883 SYS_FUNC(setsockopt) 884 { 885 print_sockopt_fd_level_name(tcp, tcp->u_arg[0], 886 tcp->u_arg[1], tcp->u_arg[2], false); 887 print_setsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2], 888 tcp->u_arg[3], tcp->u_arg[4]); 889 tprintf(", %d", (int) tcp->u_arg[4]); 890 891 return RVAL_DECODED; 892 } 893