[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