[prev in list] [next in list] [prev in thread] [next in thread] 

List:       strace
Subject:    [PATCH/RFC v2] decode extend getsockopt/setsockopt options
From:       Mike Frysinger <vapier () gentoo ! org>
Date:       2015-08-19 13:14:59
Message-ID: 1439990099-2215-1-git-send-email-vapier () gentoo ! org
[Download RAW message or body]

Currently the code assumes the set of valid options between getsockopt
and setsockopt are exactly the same and thus maintains one list.  The
kernel unfortunately does not do this -- it allows for different opts
between the get and set functions.  See the {g,s}et_opt{min,max} fields
in the various netfilter subcores.

To support this, extend the printxval function to take multiple sets of
xlats as varargs.  Then we add the new get/set lists, and pass them down
in the net code when decoding things.

A simple example is iptables; before:
	getsockopt(4, SOL_IP, 0x40 /* IP_??? */, ...) = 0
	getsockopt(4, SOL_IP, 0x41 /* IP_??? */, ...) = 0
after:
	getsockopt(4, SOL_IP, IPT_SO_GET_INFO, ...) = 0
	getsockopt(4, SOL_IP, IPT_SO_GET_ENTRIES, ...) = 0

If these were setsockopt calls, then 0x40 & 0x41 would be
IPT_SO_SET_REPLACE & IPT_SO_SET_ADD_COUNTERS.

* configure.ac: Check for netfilter headers.
* defs.h (printxvals): New prototype.
(printxval): Change to a define.
* net.c: Include netfilter headers and new sockopts headers.
(print_sockopt_fd_level_name): Add a is_getsockopt argument.  Change SOL_IP
and SOL_IPV6 decoding to use printxvals, and use is_getsockopt to pass more
xlats down.
(getsockopt): Call print_sockopt_fd_level_name with is_getsockopt as true.
(setsockopt): Call print_sockopt_fd_level_name with is_getsockopt as false.
* util.c (printxval): Rename to ...
(printxvals): ... this.  Rewrite to be varargs based.
* xlat/getsockipoptions.in: New xlat list.
* xlat/getsockipv6options.in, xlat/setsockipoptions.in,
xlat/setsockipv6options.in: Likewise.
---
v2
	- fix a few typos

 configure.ac               |  8 ++++++++
 defs.h                     |  3 ++-
 net.c                      | 31 ++++++++++++++++++++++++++-----
 util.c                     | 25 +++++++++++++++++++------
 xlat/getsockipoptions.in   | 26 ++++++++++++++++++++++++++
 xlat/getsockipv6options.in |  7 +++++++
 xlat/setsockipoptions.in   | 28 ++++++++++++++++++++++++++++
 xlat/setsockipv6options.in |  5 +++++
 8 files changed, 121 insertions(+), 12 deletions(-)
 create mode 100644 xlat/getsockipoptions.in
 create mode 100644 xlat/getsockipv6options.in
 create mode 100644 xlat/setsockipoptions.in
 create mode 100644 xlat/setsockipv6options.in

diff --git a/configure.ac b/configure.ac
index fbd20d2..4fedbf5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -261,6 +261,7 @@ AC_CHECK_HEADERS(m4_normalize([
 	linux/falloc.h
 	linux/filter.h
 	linux/hiddev.h
+	linux/ip_vs.h
 	linux/mmtimer.h
 	linux/perf_event.h
 	linux/seccomp.h
@@ -287,6 +288,13 @@ AC_CHECK_HEADERS([linux/icmp.h linux/in6.h linux/netlink.h linux/if_packet.h],
 AC_CHECK_HEADERS([asm/sigcontext.h], [], [], [#include <signal.h>])
 AC_CHECK_TYPES([struct sigcontext],,, [#include <signal.h>])
 AC_CHECK_HEADERS([netinet/tcp.h netinet/udp.h],,, [#include <netinet/in.h>])
+AC_CHECK_HEADERS(m4_normalize([
+	linux/netfilter_arp/arp_tables.h
+	linux/netfilter_bridge/ebtables.h
+	linux/netfilter_ipv4/ip_tables.h
+	linux/netfilter_ipv6/ip6_tables.h
+]), [], [], [#include <netinet/in.h>
+#include <net/if.h>])
 
 AC_CHECK_TYPES([struct mmsghdr],,, [#include <sys/socket.h>])
 AC_CHECK_MEMBERS([struct msghdr.msg_control],,, [#include <sys/socket.h>])
diff --git a/defs.h b/defs.h
index 857175d..9933983 100644
--- a/defs.h
+++ b/defs.h
@@ -516,7 +516,8 @@ extern int printllval(struct tcb *, const char *, int)
 	ATTRIBUTE_FORMAT((printf, 2, 0));
 
 extern void printaddr(long);
-extern void printxval(const struct xlat *, const unsigned int, const char *);
+extern void printxvals(const unsigned int, const char *, const struct xlat *, ...);
+#define printxval(xlat, val, dflt) printxvals(val, dflt, xlat, NULL)
 extern int printargs(struct tcb *);
 extern int printargs_lu(struct tcb *);
 extern int printargs_ld(struct tcb *);
diff --git a/net.c b/net.c
index 7e73528..40b5a5c 100644
--- a/net.c
+++ b/net.c
@@ -52,9 +52,24 @@
 # include <linux/ipx.h>
 #endif
 
+#if defined(HAVE_LINUX_IP_VS_H)
+# include <linux/ip_vs.h>
+#endif
 #if defined(HAVE_LINUX_NETLINK_H)
 # include <linux/netlink.h>
 #endif
+#if defined(HAVE_LINUX_NETFILTER_ARP_ARP_TABLES_H)
+# include <linux/netfilter_arp/arp_tables.h>
+#endif
+#if defined(HAVE_LINUX_NETFILTER_BRIDGE_EBTABLES_H)
+# include <linux/netfilter_bridge/ebtables.h>
+#endif
+#if defined(HAVE_LINUX_NETFILTER_IPV4_IP_TABLES_H)
+# include <linux/netfilter_ipv4/ip_tables.h>
+#endif
+#if defined(HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H)
+# include <linux/netfilter_ipv6/ip6_tables.h>
+#endif
 #if defined(HAVE_LINUX_IF_PACKET_H)
 # include <linux/if_packet.h>
 #endif
@@ -989,7 +1004,11 @@ SYS_FUNC(socketpair)
 
 #include "xlat/sockoptions.h"
 #include "xlat/sockipoptions.h"
+#include "xlat/getsockipoptions.h"
+#include "xlat/setsockipoptions.h"
 #include "xlat/sockipv6options.h"
+#include "xlat/getsockipv6options.h"
+#include "xlat/setsockipv6options.h"
 #include "xlat/sockipxoptions.h"
 #include "xlat/sockrawoptions.h"
 #include "xlat/sockpacketoptions.h"
@@ -997,7 +1016,7 @@ SYS_FUNC(socketpair)
 #include "xlat/socktcpoptions.h"
 
 static void
-print_sockopt_fd_level_name(struct tcb *tcp, int fd, int level, int name)
+print_sockopt_fd_level_name(struct tcb *tcp, int fd, int level, int name, bool is_getsockopt)
 {
 	printfd(tcp, fd);
 	tprints(", ");
@@ -1009,10 +1028,12 @@ print_sockopt_fd_level_name(struct tcb *tcp, int fd, int level, int name)
 		printxval(sockoptions, name, "SO_???");
 		break;
 	case SOL_IP:
-		printxval(sockipoptions, name, "IP_???");
+		printxvals(name, "IP_???", sockipoptions,
+			is_getsockopt ? getsockipoptions : setsockipoptions, NULL);
 		break;
 	case SOL_IPV6:
-		printxval(sockipv6options, name, "IPV6_???");
+		printxvals(name, "IPV6_???", sockipv6options,
+			is_getsockopt ? getsockipv6options : setsockipv6options, NULL);
 		break;
 	case SOL_IPX:
 		printxval(sockipxoptions, name, "IPX_???");
@@ -1172,7 +1193,7 @@ SYS_FUNC(getsockopt)
 {
 	if (entering(tcp)) {
 		print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
-					    tcp->u_arg[1], tcp->u_arg[2]);
+					    tcp->u_arg[1], tcp->u_arg[2], true);
 	} else {
 		int len;
 
@@ -1435,7 +1456,7 @@ done:
 SYS_FUNC(setsockopt)
 {
 	print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
-				    tcp->u_arg[1], tcp->u_arg[2]);
+				    tcp->u_arg[1], tcp->u_arg[2], false);
 	print_setsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
 			 tcp->u_arg[3], tcp->u_arg[4]);
 
diff --git a/util.c b/util.c
index 2a22cac..7682235 100644
--- a/util.c
+++ b/util.c
@@ -34,6 +34,7 @@
 #include "defs.h"
 #include <sys/param.h>
 #include <fcntl.h>
+#include <stdarg.h>
 #ifdef HAVE_SYS_XATTR_H
 # include <sys/xattr.h>
 #endif
@@ -207,14 +208,26 @@ next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits)
  * Print entry in struct xlat table, if there.
  */
 void
-printxval(const struct xlat *xlat, const unsigned int val, const char *dflt)
+printxvals(const unsigned int val, const char *dflt, const struct xlat *xlat, ...)
 {
-	const char *str = xlookup(xlat, val);
+	va_list args;
+	const char *str;
+
+	va_start(args, xlat);
+	while (xlat) {
+		str = xlookup(xlat, val);
+		if (str) {
+			tprints(str);
+			return;
+		}
 
-	if (str)
-		tprints(str);
-	else
-		tprintf("%#x /* %s */", val, dflt);
+		xlat = va_arg(args, const struct xlat *);
+		if (!xlat) {
+			tprintf("%#x /* %s */", val, dflt);
+			break;
+		}
+	}
+	va_end(args);
 }
 
 /*
diff --git a/xlat/getsockipoptions.in b/xlat/getsockipoptions.in
new file mode 100644
index 0000000..afa964b
--- /dev/null
+++ b/xlat/getsockipoptions.in
@@ -0,0 +1,26 @@
+// Options specific to getsockopt(SOL_IP); common {g,s}etsockopt(SOL_IP)
+// options should be in sockipoptions.in instead.
+
+ARPT_SO_GET_INFO
+ARPT_SO_GET_ENTRIES
+ARPT_SO_GET_REVISION_MATCH
+ARPT_SO_GET_REVISION_TARGET
+
+EBT_SO_GET_INFO
+EBT_SO_GET_ENTRIES
+EBT_SO_GET_INIT_INFO
+EBT_SO_GET_INIT_ENTRIES
+
+IP_VS_SO_GET_VERSION
+IP_VS_SO_GET_INFO
+IP_VS_SO_GET_SERVICES
+IP_VS_SO_GET_SERVICE
+IP_VS_SO_GET_DESTS
+IP_VS_SO_GET_DEST
+IP_VS_SO_GET_TIMEOUT
+IP_VS_SO_GET_DAEMON
+
+IPT_SO_GET_INFO
+IPT_SO_GET_ENTRIES
+IPT_SO_GET_REVISION_MATCH
+IPT_SO_GET_REVISION_TARGET
diff --git a/xlat/getsockipv6options.in b/xlat/getsockipv6options.in
new file mode 100644
index 0000000..d9c89ec
--- /dev/null
+++ b/xlat/getsockipv6options.in
@@ -0,0 +1,7 @@
+// Options specific to getsockopt(SOL_IPV6); common {g,s}etsockopt(SOL_IPV6)
+// options should be in sockipv6options.in instead.
+
+IP6T_SO_GET_INFO
+IP6T_SO_GET_ENTRIES
+IP6T_SO_GET_REVISION_MATCH
+IP6T_SO_GET_REVISION_TARGET
diff --git a/xlat/setsockipoptions.in b/xlat/setsockipoptions.in
new file mode 100644
index 0000000..3996393
--- /dev/null
+++ b/xlat/setsockipoptions.in
@@ -0,0 +1,28 @@
+// Options specific to setsockopt(SOL_IP); common {g,s}etsockopt(SOL_IP)
+// options should be in sockipoptions.in instead.
+
+ARPT_SO_SET_REPLACE
+ARPT_SO_SET_ADD_COUNTERS
+
+EBT_SO_SET_ENTRIES
+EBT_SO_SET_COUNTERS
+
+IP_VS_SO_SET_NONE
+IP_VS_SO_SET_INSERT
+IP_VS_SO_SET_ADD
+IP_VS_SO_SET_EDIT
+IP_VS_SO_SET_DEL
+IP_VS_SO_SET_FLUSH
+IP_VS_SO_SET_LIST
+IP_VS_SO_SET_ADDDEST
+IP_VS_SO_SET_DELDEST
+IP_VS_SO_SET_EDITDEST
+IP_VS_SO_SET_TIMEOUT
+IP_VS_SO_SET_STARTDAEMON
+IP_VS_SO_SET_STOPDAEMON
+IP_VS_SO_SET_RESTORE
+IP_VS_SO_SET_SAVE
+IP_VS_SO_SET_ZERO
+
+IPT_SO_SET_REPLACE
+IPT_SO_SET_ADD_COUNTERS
diff --git a/xlat/setsockipv6options.in b/xlat/setsockipv6options.in
new file mode 100644
index 0000000..8be0c97
--- /dev/null
+++ b/xlat/setsockipv6options.in
@@ -0,0 +1,5 @@
+// Options specific to setsockopt(SOL_IPV6); common {g,s}etsockopt(SOL_IPV6)
+// options should be in sockipv6options.in instead.
+
+IP6T_SO_SET_REPLACE
+IP6T_SO_SET_ADD_COUNTERS
-- 
2.4.4


------------------------------------------------------------------------------
_______________________________________________
Strace-devel mailing list
Strace-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/strace-devel
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic