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 875354b..16998e9 100644
--- a/net.c
+++ b/net.c
@@ -1089,185 +1089,17 @@
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;
-#ifdef SOL_IP
- case SOL_IP:
- printxval(sockipoptions, tcp->u_arg[2], "IP_???");
- break;
-#endif
-#ifdef SOL_IPV6
- case SOL_IPV6:
- printxval(sockipv6options, tcp->u_arg[2], "IPV6_???");
- break;
-#endif
-#ifdef SOL_IPX
- case SOL_IPX:
- printxval(sockipxoptions, tcp->u_arg[2], "IPX_???");
- break;
-#endif
-#ifdef SOL_PACKET
- case SOL_PACKET:
- printxval(sockpacketoptions, tcp->u_arg[2], "PACKET_???");
- break;
-#endif
-#ifdef SOL_TCP
- case SOL_TCP:
- printxval(socktcpoptions, tcp->u_arg[2], "TCP_???");
- break;
-#endif
-#ifdef SOL_SCTP
- case SOL_SCTP:
- printxval(socksctpoptions, tcp->u_arg[2], "SCTP_???");
- 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;
- }
-
- 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
-#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]) {
-#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;
- }
-
- if (len == sizeof(int)) {
- printnum_int(tcp, tcp->u_arg[3], "%d");
- }
- else {
- printstr(tcp, tcp->u_arg[3], len);
- }
- tprintf(", [%d]", len);
- }
- return 0;
-}
-
-#if defined(ICMP_FILTER)
-static void printicmpfilter(struct tcb *tcp, long addr)
-{
- struct icmp_filter filter;
-
- if (!addr) {
- tprints("NULL");
- return;
- }
- if (syserror(tcp) || !verbose(tcp)) {
- tprintf("%#lx", addr);
- return;
- }
- if (umove(tcp, addr, &filter) < 0) {
- tprints("{...}");
- return;
- }
-
- tprints("~(");
- printflags(icmpfilterflags, ~filter.data, "ICMP_???");
- tprints(")");
-}
-#endif /* ICMP_FILTER */
-
-static int
-printsockopt(struct tcb *tcp, int level, int name, long addr, int len)
-{
+ printfd(tcp, fd);
+ tprints(", ");
printxval(socketlayers, level, "SOL_??");
tprints(", ");
+
switch (level) {
case SOL_SOCKET:
printxval(sockoptions, name, "SO_???");
- switch (name) {
-#if defined(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;
-#endif
- }
break;
#ifdef SOL_IP
case SOL_IP:
@@ -1287,29 +1119,6 @@
#ifdef SOL_PACKET
case SOL_PACKET:
printxval(sockpacketoptions, name, "PACKET_???");
- /* TODO: decode packate_mreq for PACKET_*_MEMBERSHIP */
- switch (name) {
-#ifdef PACKET_RX_RING
- case PACKET_RX_RING:
-#endif
-#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 */
- }
break;
#endif
#ifdef SOL_TCP
@@ -1325,46 +1134,256 @@
#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
- }
break;
#endif
- /* SOL_AX25 SOL_ATALK SOL_NETROM SOL_UDP SOL_DECNET SOL_X25
- * etc. still need work */
+ /* Other SOL_* protocol levels still need work. */
default:
tprintf("%u", name);
}
+ tprints(", ");
+}
+
+#ifdef SO_LINGER
+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
+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
+static void
+print_tpacket_stats(struct tcb *tcp, long addr, int len)
+{
+ struct tpacket_stats stats;
+
+ if (len != sizeof(stats) ||
+ umove(tcp, addr, &stats) < 0) {
+ tprintf("%#lx", addr);
+ } else {
+ tprintf("{packets=%u, drops=%u}",
+ stats.tp_packets,
+ stats.tp_drops);
+ }
+}
+#endif /* PACKET_STATISTICS */
+
+#ifdef ICMP_FILTER
+static void
+print_icmp_filter(struct tcb *tcp, long addr, int len)
+{
+ struct icmp_filter filter;
+
+ if (len != sizeof(filter) ||
+ umove(tcp, addr, &filter) < 0) {
+ tprintf("%#lx", addr);
+ return;
+ }
+
+ tprints("~(");
+ printflags(icmpfilterflags, ~filter.data, "ICMP_???");
+ tprints(")");
+}
+#endif /* ICMP_FILTER */
+
+static void
+print_getsockopt(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 SO_PEERCRED
+ case SO_PEERCRED:
+ print_ucred(tcp, addr, len);
+ goto done;
+#endif
+ }
+ break;
+
+#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 /* 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 */
- tprints(", ");
-
- if (len == sizeof(int)) {
- printnum_int(tcp, addr, "%d");
+ if (verbose(tcp)) {
+ if (len == sizeof(int)) {
+ printnum_int(tcp, addr, "%d");
+ } else {
+ printstr(tcp, addr, len);
+ }
+ } else {
+ tprintf("%#lx", addr);
}
- else {
- printstr(tcp, addr, len);
+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
+ }
+ break;
+
+#ifdef SOL_PACKET
+ case SOL_PACKET:
+ switch (name) {
+# ifdef PACKET_RX_RING
+ case PACKET_RX_RING:
+# ifdef PACKET_TX_RING
+ case 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 /* 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_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;
}