]> granicus.if.org Git - strace/commitdiff
getsockopt, setsockopt: do not decode structures in non-verbose mode
authorDmitry V. Levin <ldv@altlinux.org>
Thu, 29 Jan 2015 03:11:41 +0000 (03:11 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Thu, 29 Jan 2015 03:35:07 +0000 (03:35 +0000)
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.

net.c

diff --git a/net.c b/net.c
index 875354b8af65bbc48092e39d478f803163804e85..16998e9da1316cf6a4dc2717c7c8f2eefacfcae1 100644 (file)
--- 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;
 }