From: Dmitry V. Levin Date: Thu, 29 Jan 2015 03:11:41 +0000 (+0000) Subject: getsockopt, setsockopt: do not decode structures in non-verbose mode X-Git-Tag: v4.10~156 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0509c8ed6db16c10d26801e6be8acc923eba2a32;p=strace getsockopt, setsockopt: do not decode structures in non-verbose mode Move the code that is common between getsockopt and setsockopt parsers to a separate function. Move printers specific to getsockopt and setsockopt to separate functions, choose appropriate parsers depending on verbose mode. Move parsers of specific socket options to separate functions. * net.c (printicmpfilter): Rename to print_icmp_filter. (printsockopt): Remove. (print_sockopt_fd_level_name, print_linger, print_ucred, print_tpacket_stats, print_getsockopt, print_tpacket_req, print_packet_mreq, print_setsockopt): New functions. (sys_getsockopt, sys_setsockopt): Use them. --- diff --git a/net.c b/net.c index 875354b8..16998e9d 100644 --- a/net.c +++ b/net.c @@ -1089,155 +1089,127 @@ sys_socketpair(struct tcb *tcp) return 0; } -int -sys_getsockopt(struct tcb *tcp) +static void +print_sockopt_fd_level_name(struct tcb *tcp, int fd, int level, int name) { - if (entering(tcp)) { - printfd(tcp, tcp->u_arg[0]); - tprints(", "); - printxval(socketlayers, tcp->u_arg[1], "SOL_???"); - tprints(", "); - switch (tcp->u_arg[1]) { - case SOL_SOCKET: - printxval(sockoptions, tcp->u_arg[2], "SO_???"); - break; + printfd(tcp, fd); + tprints(", "); + printxval(socketlayers, level, "SOL_??"); + tprints(", "); + + switch (level) { + case SOL_SOCKET: + printxval(sockoptions, name, "SO_???"); + break; #ifdef SOL_IP - case SOL_IP: - printxval(sockipoptions, tcp->u_arg[2], "IP_???"); - break; + case SOL_IP: + printxval(sockipoptions, name, "IP_???"); + break; #endif #ifdef SOL_IPV6 - case SOL_IPV6: - printxval(sockipv6options, tcp->u_arg[2], "IPV6_???"); - break; + case SOL_IPV6: + printxval(sockipv6options, name, "IPV6_???"); + break; #endif #ifdef SOL_IPX - case SOL_IPX: - printxval(sockipxoptions, tcp->u_arg[2], "IPX_???"); - break; + case SOL_IPX: + printxval(sockipxoptions, name, "IPX_???"); + break; #endif #ifdef SOL_PACKET - case SOL_PACKET: - printxval(sockpacketoptions, tcp->u_arg[2], "PACKET_???"); - break; + case SOL_PACKET: + printxval(sockpacketoptions, name, "PACKET_???"); + break; #endif #ifdef SOL_TCP - case SOL_TCP: - printxval(socktcpoptions, tcp->u_arg[2], "TCP_???"); - break; + case SOL_TCP: + printxval(socktcpoptions, name, "TCP_???"); + break; #endif #ifdef SOL_SCTP - case SOL_SCTP: - printxval(socksctpoptions, tcp->u_arg[2], "SCTP_???"); - break; + case SOL_SCTP: + printxval(socksctpoptions, name, "SCTP_???"); + break; +#endif +#ifdef SOL_RAW + case SOL_RAW: + printxval(sockrawoptions, name, "RAW_???"); + break; #endif - /* SOL_AX25 SOL_ROSE SOL_ATALK SOL_NETROM SOL_UDP SOL_DECNET SOL_X25 - * etc. still need work */ - default: - tprintf("%lu", tcp->u_arg[2]); - break; - } - tprints(", "); - } else { - int len; - if (syserror(tcp) || umove(tcp, tcp->u_arg[4], &len) < 0) { - tprintf("%#lx, %#lx", - tcp->u_arg[3], tcp->u_arg[4]); - return 0; - } + /* Other SOL_* protocol levels still need work. */ + + default: + tprintf("%u", name); + } + + tprints(", "); +} - switch (tcp->u_arg[1]) { - case SOL_SOCKET: - switch (tcp->u_arg[2]) { #ifdef SO_LINGER - case SO_LINGER: - if (len == sizeof(struct linger)) { - struct linger linger; - if (umove(tcp, - tcp->u_arg[3], - &linger) < 0) - break; - tprintf("{onoff=%d, linger=%d}, " - "[%d]", - linger.l_onoff, - linger.l_linger, - len); - return 0; - } - break; -#endif +static void +print_linger(struct tcb *tcp, long addr, int len) +{ + struct linger linger; + + if (len != sizeof(linger) || + umove(tcp, addr, &linger) < 0) { + tprintf("%#lx", addr); + return; + } + + tprintf("{onoff=%d, linger=%d}", + linger.l_onoff, + linger.l_linger); +} +#endif /* SO_LINGER */ + #ifdef SO_PEERCRED - case SO_PEERCRED: - if (len == sizeof(struct ucred)) { - struct ucred uc; - if (umove(tcp, - tcp->u_arg[3], - &uc) < 0) - break; - tprintf("{pid=%ld, uid=%ld, gid=%ld}, " - "[%d]", - (long)uc.pid, - (long)uc.uid, - (long)uc.gid, - len); - return 0; - } - break; -#endif - } - break; - case SOL_PACKET: - switch (tcp->u_arg[2]) { +static void +print_ucred(struct tcb *tcp, long addr, int len) +{ + struct ucred uc; + + if (len != sizeof(uc) || + umove(tcp, addr, &uc) < 0) { + tprintf("%#lx", addr); + } else { + tprintf("{pid=%u, uid=%u, gid=%u}", + (unsigned) uc.pid, + (unsigned) uc.uid, + (unsigned) uc.gid); + } +} +#endif /* SO_PEERCRED */ + #ifdef PACKET_STATISTICS - case PACKET_STATISTICS: - if (len == sizeof(struct tpacket_stats)) { - struct tpacket_stats stats; - if (umove(tcp, - tcp->u_arg[3], - &stats) < 0) - break; - tprintf("{packets=%u, drops=%u}, " - "[%d]", - stats.tp_packets, - stats.tp_drops, - len); - return 0; - } - break; -#endif - } - break; - } +static void +print_tpacket_stats(struct tcb *tcp, long addr, int len) +{ + struct tpacket_stats stats; - if (len == sizeof(int)) { - printnum_int(tcp, tcp->u_arg[3], "%d"); - } - else { - printstr(tcp, tcp->u_arg[3], len); - } - tprintf(", [%d]", len); + if (len != sizeof(stats) || + umove(tcp, addr, &stats) < 0) { + tprintf("%#lx", addr); + } else { + tprintf("{packets=%u, drops=%u}", + stats.tp_packets, + stats.tp_drops); } - return 0; } +#endif /* PACKET_STATISTICS */ -#if defined(ICMP_FILTER) -static void printicmpfilter(struct tcb *tcp, long addr) +#ifdef ICMP_FILTER +static void +print_icmp_filter(struct tcb *tcp, long addr, int len) { struct icmp_filter filter; - if (!addr) { - tprints("NULL"); - return; - } - if (syserror(tcp) || !verbose(tcp)) { + if (len != sizeof(filter) || + umove(tcp, addr, &filter) < 0) { tprintf("%#lx", addr); return; } - if (umove(tcp, addr, &filter) < 0) { - tprints("{...}"); - return; - } tprints("~("); printflags(icmpfilterflags, ~filter.data, "ICMP_???"); @@ -1245,126 +1217,173 @@ static void printicmpfilter(struct tcb *tcp, long addr) } #endif /* ICMP_FILTER */ -static int -printsockopt(struct tcb *tcp, int level, int name, long addr, int len) +static void +print_getsockopt(struct tcb *tcp, int level, int name, long addr, int len) { - printxval(socketlayers, level, "SOL_??"); - tprints(", "); + if (addr && verbose(tcp)) switch (level) { case SOL_SOCKET: - printxval(sockoptions, name, "SO_???"); switch (name) { -#if defined(SO_LINGER) +#ifdef SO_LINGER case SO_LINGER: - if (len == sizeof(struct linger)) { - struct linger linger; - if (umove(tcp, addr, &linger) < 0) - break; - tprintf(", {onoff=%d, linger=%d}", - linger.l_onoff, - linger.l_linger); - return 0; - } - break; + print_linger(tcp, addr, len); + goto done; +#endif +#ifdef SO_PEERCRED + case SO_PEERCRED: + print_ucred(tcp, addr, len); + goto done; #endif } break; -#ifdef SOL_IP - case SOL_IP: - printxval(sockipoptions, name, "IP_???"); + +#ifdef SOL_PACKET + case SOL_PACKET: + switch (name) { +# ifdef PACKET_STATISTICS + case PACKET_STATISTICS: + print_tpacket_stats(tcp, addr, len); + goto done; +# endif + } break; -#endif -#ifdef SOL_IPV6 - case SOL_IPV6: - printxval(sockipv6options, name, "IPV6_???"); +#endif /* SOL_PACKET */ + +#ifdef SOL_RAW + case SOL_RAW: + switch (name) { +# ifdef ICMP_FILTER + case ICMP_FILTER: + print_icmp_filter(tcp, addr, len); + goto done; +# endif + } break; +#endif /* SOL_RAW */ + } + + /* default arg printing */ + + if (verbose(tcp)) { + if (len == sizeof(int)) { + printnum_int(tcp, addr, "%d"); + } else { + printstr(tcp, addr, len); + } + } else { + tprintf("%#lx", addr); + } +done: + tprintf(", [%d]", len); +} + +int +sys_getsockopt(struct tcb *tcp) +{ + if (entering(tcp)) { + print_sockopt_fd_level_name(tcp, tcp->u_arg[0], + tcp->u_arg[1], tcp->u_arg[2]); + } else { + int len; + + if (syserror(tcp) || umove(tcp, tcp->u_arg[4], &len) < 0) { + tprintf("%#lx, %#lx", + tcp->u_arg[3], tcp->u_arg[4]); + } else { + print_getsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2], + tcp->u_arg[3], len); + } + } + return 0; +} + +#ifdef PACKET_RX_RING +static void +print_tpacket_req(struct tcb *tcp, long addr, int len) +{ + struct tpacket_req req; + + if (len != sizeof(req) || + umove(tcp, addr, &req) < 0) { + tprintf("%#lx", addr); + } else { + tprintf("{block_size=%u, block_nr=%u, " + "frame_size=%u, frame_nr=%u}", + req.tp_block_size, + req.tp_block_nr, + req.tp_frame_size, + req.tp_frame_nr); + } +} +#endif /* PACKET_RX_RING */ + +static void +print_setsockopt(struct tcb *tcp, int level, int name, long addr, int len) +{ + if (addr && verbose(tcp)) + switch (level) { + case SOL_SOCKET: + switch (name) { +#ifdef SO_LINGER + case SO_LINGER: + print_linger(tcp, addr, len); + goto done; #endif -#ifdef SOL_IPX - case SOL_IPX: - printxval(sockipxoptions, name, "IPX_???"); + } break; -#endif + #ifdef SOL_PACKET case SOL_PACKET: - printxval(sockpacketoptions, name, "PACKET_???"); - /* TODO: decode packate_mreq for PACKET_*_MEMBERSHIP */ switch (name) { -#ifdef PACKET_RX_RING +# ifdef PACKET_RX_RING case PACKET_RX_RING: -#endif -#ifdef PACKET_TX_RING +# ifdef PACKET_TX_RING case PACKET_TX_RING: -#endif -#if defined(PACKET_RX_RING) || defined(PACKET_TX_RING) - if (len == sizeof(struct tpacket_req)) { - struct tpacket_req req; - if (umove(tcp, addr, &req) < 0) - break; - tprintf(", {block_size=%u, block_nr=%u, frame_size=%u, frame_nr=%u}", - req.tp_block_size, - req.tp_block_nr, - req.tp_frame_size, - req.tp_frame_nr); - return 0; - } - break; -#endif /* PACKET_RX_RING || PACKET_TX_RING */ +# endif + print_tpacket_req(tcp, addr, len); + goto done; +# endif /* PACKET_RX_RING */ + /* TODO: decode packate_mreq for PACKET_*_MEMBERSHIP */ } break; -#endif -#ifdef SOL_TCP - case SOL_TCP: - printxval(socktcpoptions, name, "TCP_???"); - break; -#endif -#ifdef SOL_SCTP - case SOL_SCTP: - printxval(socksctpoptions, name, "SCTP_???"); - break; -#endif +#endif /* SOL_PACKET */ + #ifdef SOL_RAW case SOL_RAW: - printxval(sockrawoptions, name, "RAW_???"); switch (name) { -#if defined(ICMP_FILTER) - case ICMP_FILTER: - tprints(", "); - printicmpfilter(tcp, addr); - return 0; -#endif +# ifdef ICMP_FILTER + case ICMP_FILTER: + print_icmp_filter(tcp, addr, len); + goto done; +# endif } break; -#endif - - /* SOL_AX25 SOL_ATALK SOL_NETROM SOL_UDP SOL_DECNET SOL_X25 - * etc. still need work */ - - default: - tprintf("%u", name); +#endif /* SOL_RAW */ } /* default arg printing */ - tprints(", "); - - if (len == sizeof(int)) { - printnum_int(tcp, addr, "%d"); - } - else { - printstr(tcp, addr, len); + if (verbose(tcp)) { + if (len == sizeof(int)) { + printnum_int(tcp, addr, "%d"); + } else { + printstr(tcp, addr, len); + } + } else { + tprintf("%#lx", addr); } - return 0; +done: + tprintf(", %d", len); } int sys_setsockopt(struct tcb *tcp) { if (entering(tcp)) { - printfd(tcp, tcp->u_arg[0]); - tprints(", "); - printsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2], - tcp->u_arg[3], tcp->u_arg[4]); - tprintf(", %lu", tcp->u_arg[4]); + print_sockopt_fd_level_name(tcp, tcp->u_arg[0], + tcp->u_arg[1], tcp->u_arg[2]); + print_setsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2], + tcp->u_arg[3], tcp->u_arg[4]); } return 0; }