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 74#include "xlat/socktypes.h" 75#include "xlat/sock_type_flags.h" 76#ifndef SOCK_TYPE_MASK 77# define SOCK_TYPE_MASK 0xf 78#endif 79 80#include "xlat/socketlayers.h" 81 82#include "xlat/inet_protocols.h" 83#include "xlat/netlink_protocols.h" 84 85#ifdef HAVE_BLUETOOTH_BLUETOOTH_H 86# include <bluetooth/bluetooth.h> 87# include "xlat/bt_protocols.h" 88#endif 89 90void 91print_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 106static void 107decode_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, 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 */ 124static void 125tprint_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 139SYS_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 169SYS_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 180SYS_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 189static bool 190fetch_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 197static int 198decode_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 232SYS_FUNC(accept) 233{ 234 return decode_sockname(tcp) | RVAL_FD; 235} 236 237SYS_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 249SYS_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 261SYS_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 279SYS_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 298SYS_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 352SYS_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 361SYS_FUNC(getsockname) 362{ 363 return decode_sockname(tcp); 364} 365 366static void 367printpair_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 376static void 377decode_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 387static int 388do_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 400SYS_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 411SYS_FUNC(pipe2) 412{ 413 return do_pipe(tcp, 1); 414} 415 416SYS_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 443static void 444print_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 489static void 490print_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 506static void 507print_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 524static void 525print_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 543static void 544print_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 563static void 564print_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 } 613done: 614 tprintf(", [%d]", len); 615} 616 617SYS_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 638static void 639print_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 tprints("{imr_multiaddr=inet_addr("); 652 print_quoted_string(inet_ntoa(mreq.imr_multiaddr), 653 16, QUOTE_0_TERMINATED); 654 tprints("), imr_interface=inet_addr("); 655 print_quoted_string(inet_ntoa(mreq.imr_interface), 656 16, QUOTE_0_TERMINATED); 657 tprints(")}"); 658} 659#endif /* IP_ADD_MEMBERSHIP */ 660 661#ifdef IPV6_ADD_MEMBERSHIP 662static void 663print_mreq6(struct tcb *const tcp, const kernel_ulong_t addr, 664 const unsigned int len) 665{ 666 struct ipv6_mreq mreq; 667 668 if (len < sizeof(mreq)) 669 goto fail; 670 671 if (umove_or_printaddr(tcp, addr, &mreq)) 672 return; 673 674 const struct in6_addr *in6 = &mreq.ipv6mr_multiaddr; 675 char address[INET6_ADDRSTRLEN]; 676 677 if (!inet_ntop(AF_INET6, in6, address, sizeof(address))) 678 goto fail; 679 680 tprints("{ipv6mr_multiaddr=inet_pton("); 681 print_quoted_string(address, sizeof(address), QUOTE_0_TERMINATED); 682 tprints("), ipv6mr_interface="); 683 print_ifindex(mreq.ipv6mr_interface); 684 tprints("}"); 685 return; 686 687fail: 688 printstrn(tcp, addr, len); 689} 690#endif /* IPV6_ADD_MEMBERSHIP */ 691 692#ifdef MCAST_JOIN_GROUP 693static void 694print_group_req(struct tcb *const tcp, const kernel_ulong_t addr, const int len) 695{ 696 struct group_req greq; 697 698 if (len != sizeof(greq) || 699 umove(tcp, addr, &greq) < 0) { 700 printaddr(addr); 701 return; 702 } 703 704 tprintf("{gr_interface=%u, gr_group=", greq.gr_interface); 705 print_sockaddr(tcp, &greq.gr_group, sizeof(greq.gr_group)); 706 tprints("}"); 707 708} 709#endif /* MCAST_JOIN_GROUP */ 710 711#ifdef PACKET_RX_RING 712static void 713print_tpacket_req(struct tcb *const tcp, const kernel_ulong_t addr, const int len) 714{ 715 struct tpacket_req req; 716 717 if (len != sizeof(req) || 718 umove(tcp, addr, &req) < 0) { 719 printaddr(addr); 720 } else { 721 tprintf("{block_size=%u, block_nr=%u, " 722 "frame_size=%u, frame_nr=%u}", 723 req.tp_block_size, 724 req.tp_block_nr, 725 req.tp_frame_size, 726 req.tp_frame_nr); 727 } 728} 729#endif /* PACKET_RX_RING */ 730 731#ifdef PACKET_ADD_MEMBERSHIP 732# include "xlat/packet_mreq_type.h" 733 734static void 735print_packet_mreq(struct tcb *const tcp, const kernel_ulong_t addr, const int len) 736{ 737 struct packet_mreq mreq; 738 739 if (len != sizeof(mreq) || 740 umove(tcp, addr, &mreq) < 0) { 741 printaddr(addr); 742 } else { 743 unsigned int i; 744 745 tprintf("{mr_ifindex=%u, mr_type=", mreq.mr_ifindex); 746 printxval(packet_mreq_type, mreq.mr_type, "PACKET_MR_???"); 747 tprintf(", mr_alen=%u, mr_address=", mreq.mr_alen); 748 if (mreq.mr_alen > ARRAY_SIZE(mreq.mr_address)) 749 mreq.mr_alen = ARRAY_SIZE(mreq.mr_address); 750 for (i = 0; i < mreq.mr_alen; ++i) 751 tprintf("%02x", mreq.mr_address[i]); 752 tprints("}"); 753 } 754} 755#endif /* PACKET_ADD_MEMBERSHIP */ 756 757static void 758print_setsockopt(struct tcb *const tcp, const unsigned int level, 759 const unsigned int name, const kernel_ulong_t addr, 760 const int len) 761{ 762 if (addr && verbose(tcp)) 763 switch (level) { 764 case SOL_SOCKET: 765 switch (name) { 766 case SO_LINGER: 767 print_linger(tcp, addr, len); 768 goto done; 769 } 770 break; 771 772 case SOL_IP: 773 switch (name) { 774#ifdef IP_ADD_MEMBERSHIP 775 case IP_ADD_MEMBERSHIP: 776 case IP_DROP_MEMBERSHIP: 777 print_mreq(tcp, addr, len); 778 goto done; 779#endif /* IP_ADD_MEMBERSHIP */ 780#ifdef MCAST_JOIN_GROUP 781 case MCAST_JOIN_GROUP: 782 case MCAST_LEAVE_GROUP: 783 print_group_req(tcp, addr, len); 784 goto done; 785#endif /* MCAST_JOIN_GROUP */ 786 } 787 break; 788 789 case SOL_IPV6: 790 switch (name) { 791#ifdef IPV6_ADD_MEMBERSHIP 792 case IPV6_ADD_MEMBERSHIP: 793 case IPV6_DROP_MEMBERSHIP: 794# ifdef IPV6_JOIN_ANYCAST 795 case IPV6_JOIN_ANYCAST: 796# endif 797# ifdef IPV6_LEAVE_ANYCAST 798 case IPV6_LEAVE_ANYCAST: 799# endif 800 print_mreq6(tcp, addr, len); 801 goto done; 802#endif /* IPV6_ADD_MEMBERSHIP */ 803 } 804 break; 805 806 case SOL_PACKET: 807 switch (name) { 808#ifdef PACKET_RX_RING 809 case PACKET_RX_RING: 810# ifdef PACKET_TX_RING 811 case PACKET_TX_RING: 812# endif 813 print_tpacket_req(tcp, addr, len); 814 goto done; 815#endif /* PACKET_RX_RING */ 816#ifdef PACKET_ADD_MEMBERSHIP 817 case PACKET_ADD_MEMBERSHIP: 818 case PACKET_DROP_MEMBERSHIP: 819 print_packet_mreq(tcp, addr, len); 820 goto done; 821#endif /* PACKET_ADD_MEMBERSHIP */ 822 } 823 break; 824 825 case SOL_RAW: 826 switch (name) { 827 case ICMP_FILTER: 828 print_icmp_filter(tcp, addr, len); 829 goto done; 830 } 831 break; 832 } 833 834 /* default arg printing */ 835 836 if (verbose(tcp)) { 837 if (len == sizeof(int)) { 838 printnum_int(tcp, addr, "%d"); 839 } else { 840 printstrn(tcp, addr, len); 841 } 842 } else { 843 printaddr(addr); 844 } 845done: 846 tprintf(", %d", len); 847} 848 849SYS_FUNC(setsockopt) 850{ 851 print_sockopt_fd_level_name(tcp, tcp->u_arg[0], 852 tcp->u_arg[1], tcp->u_arg[2], false); 853 print_setsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2], 854 tcp->u_arg[3], tcp->u_arg[4]); 855 856 return RVAL_DECODED; 857} 858