Re: decoding of input/output args ?

2015-08-19 Thread Dmitry V. Levin
On Wed, Aug 19, 2015 at 04:59:38PM -0400, Mike Frysinger wrote:
> On 19 Aug 2015 22:36, Dmitry V. Levin wrote:
> > On Wed, Aug 19, 2015 at 03:17:39PM -0400, Mike Frysinger wrote:
> > > some syscalls have arguments that are read/write.  for example, 
> > > getsockopt 
> > > passes in a pointer to a length that has to be set correctly first, and 
> > > then
> > > the kernel will adjust it when returning.  being able to see both values 
> > > is
> > > important when getting an error so you can see what the user sent up and 
> > > what
> > > the kernel sent back.
> > > 
> > > are there examples in strace to look at ?  perhaps something like:
> > > getsockopt(4, SOL_IP, IPT_SO_GET_ENTRIES, "...", [2900->2804]) = 0
> > > and when you get an error it'd be:
> > > getsockopt(4, SOL_IP, IPT_SO_GET_ENTRIES, 0x12345, [2900->2900]) = EINVAL
> > 
> > I think there is no need to print it in case of an error,
> > when it's known to be unchanged.
> > 
> > We have several examples in the code:
> > $ git grep '[^a-z] => ' *.c
> > mtd.c:  tprints(" => ");
> > mtd.c:  tprints(" => ");
> > sendfile.c: tprints(" => ");
> > sendfile.c: tprints(" => ");
> > sock.c: tprints(" => ");
> > v4l2.c: tprints(exiting(tcp) && code != VIDIOC_G_FMT ? 
> > " => " : ", ");
> > v4l2.c: tprints(exiting(tcp) && code == VIDIOC_S_PARM ? " => {" 
> > : ", {");
> > v4l2.c: tprints(exiting(tcp) ? " => " : ", {id=");
> > v4l2.c: tprints(code != VIDIOC_G_EXT_CTRLS && exiting(tcp) ? " 
> > => " : ", ");
> > 
> > The most recent one is from commits v4.10-319-g22f8b27 and
> > v4.10-320-g4918285.
> 
> output format looks fine.

[before => after] might look better, but
[before] => [after] is easier to implement.

> but there's another wrinkle here :).  sendfile is 
> easy -- the leading args are input only, and the last one is input/output,
> so incremental output is not an issue.  getsockopt is inputs, then output,
> then input/output.  so i can't print the last input in the entering code path
> and then print the output in the exiting code path.  i need to read the curr
> value, save it in the tcp structure somehow (?), and then read that back out
> in the exiting code path.

This is not the first time a necessity to save some data between entering
and exiting stages of a syscall parser is mentioned.  For example, there
was a discussion back in July about adding a private data field
to struct tcb: http://sourceforge.net/p/strace/mailman/message/34262875/

However, none of those ideas have been implemented yet.


-- 
ldv


pgpiWIY1g_K1w.pgp
Description: PGP signature
--
___
Strace-devel mailing list
Strace-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/strace-devel


Re: decoding of input/output args ?

2015-08-19 Thread Mike Frysinger
On 19 Aug 2015 22:36, Dmitry V. Levin wrote:
> On Wed, Aug 19, 2015 at 03:17:39PM -0400, Mike Frysinger wrote:
> > some syscalls have arguments that are read/write.  for example, getsockopt 
> > passes in a pointer to a length that has to be set correctly first, and then
> > the kernel will adjust it when returning.  being able to see both values is
> > important when getting an error so you can see what the user sent up and 
> > what
> > the kernel sent back.
> > 
> > are there examples in strace to look at ?  perhaps something like:
> > getsockopt(4, SOL_IP, IPT_SO_GET_ENTRIES, "...", [2900->2804]) = 0
> > and when you get an error it'd be:
> > getsockopt(4, SOL_IP, IPT_SO_GET_ENTRIES, 0x12345, [2900->2900]) = EINVAL
> 
> I think there is no need to print it in case of an error,
> when it's known to be unchanged.
> 
> We have several examples in the code:
> $ git grep '[^a-z] => ' *.c
> mtd.c:tprints(" => ");
> mtd.c:tprints(" => ");
> sendfile.c:   tprints(" => ");
> sendfile.c:   tprints(" => ");
> sock.c:   tprints(" => ");
> v4l2.c:   tprints(exiting(tcp) && code != VIDIOC_G_FMT ? 
> " => " : ", ");
> v4l2.c:   tprints(exiting(tcp) && code == VIDIOC_S_PARM ? " => {" 
> : ", {");
> v4l2.c:   tprints(exiting(tcp) ? " => " : ", {id=");
> v4l2.c:   tprints(code != VIDIOC_G_EXT_CTRLS && exiting(tcp) ? " 
> => " : ", ");
> 
> The most recent one is from commits v4.10-319-g22f8b27 and
> v4.10-320-g4918285.

output format looks fine.  but there's another wrinkle here :).  sendfile is 
easy -- the leading args are input only, and the last one is input/output,
so incremental output is not an issue.  getsockopt is inputs, then output,
then input/output.  so i can't print the last input in the entering code path
and then print the output in the exiting code path.  i need to read the curr
value, save it in the tcp structure somehow (?), and then read that back out
in the exiting code path.

int getsockopt(int sockfd, int level, int optname,
   void *optval, socklen_t *optlen);

if (entering(tcp)) {
... print sockfd/level/optname ...
tprintf("%i, %i, %i, ", tcp->u_arg[0], tcp->u_arg[1], 
tcp->u_arg[2]);
... save current *optlen value ...
umove(tcp, tcp->u_arg[4], &tcp->scratch);
} else {
... print optval output ...
print_getsockopt(... tcp->u_arg[3] ...);
... print the *optlen value ...
umove(tcp, tcp->u_arg[4], &len);
tprintf("[%d]", tcp->scratch);
if (tcp->scratch != len)
tprintf(" => [%d]", len);
}

tips ?
-mike


signature.asc
Description: Digital signature
--
___
Strace-devel mailing list
Strace-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/strace-devel


Re: decoding of input/output args ?

2015-08-19 Thread Dmitry V. Levin
On Wed, Aug 19, 2015 at 03:17:39PM -0400, Mike Frysinger wrote:
> some syscalls have arguments that are read/write.  for example, getsockopt 
> passes in a pointer to a length that has to be set correctly first, and then
> the kernel will adjust it when returning.  being able to see both values is
> important when getting an error so you can see what the user sent up and what
> the kernel sent back.
> 
> are there examples in strace to look at ?  perhaps something like:
> getsockopt(4, SOL_IP, IPT_SO_GET_ENTRIES, "...", [2900->2804]) = 0
> and when you get an error it'd be:
> getsockopt(4, SOL_IP, IPT_SO_GET_ENTRIES, 0x12345, [2900->2900]) = EINVAL

I think there is no need to print it in case of an error,
when it's known to be unchanged.

We have several examples in the code:
$ git grep '[^a-z] => ' *.c
mtd.c:  tprints(" => ");
mtd.c:  tprints(" => ");
sendfile.c: tprints(" => ");
sendfile.c: tprints(" => ");
sock.c: tprints(" => ");
v4l2.c: tprints(exiting(tcp) && code != VIDIOC_G_FMT ? " => " : 
", ");
v4l2.c: tprints(exiting(tcp) && code == VIDIOC_S_PARM ? " => {" : ", 
{");
v4l2.c: tprints(exiting(tcp) ? " => " : ", {id=");
v4l2.c: tprints(code != VIDIOC_G_EXT_CTRLS && exiting(tcp) ? " => " : 
", ");

The most recent one is from commits v4.10-319-g22f8b27 and
v4.10-320-g4918285.


-- 
ldv


pgp2iAAk7aOhi.pgp
Description: PGP signature
--
___
Strace-devel mailing list
Strace-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/strace-devel


decoding of input/output args ?

2015-08-19 Thread Mike Frysinger
some syscalls have arguments that are read/write.  for example, getsockopt 
passes in a pointer to a length that has to be set correctly first, and then
the kernel will adjust it when returning.  being able to see both values is
important when getting an error so you can see what the user sent up and what
the kernel sent back.

are there examples in strace to look at ?  perhaps something like:
getsockopt(4, SOL_IP, IPT_SO_GET_ENTRIES, "...", [2900->2804]) = 0
and when you get an error it'd be:
getsockopt(4, SOL_IP, IPT_SO_GET_ENTRIES, 0x12345, [2900->2900]) = EINVAL
-mike


signature.asc
Description: Digital signature
--
___
Strace-devel mailing list
Strace-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/strace-devel


Re: [PATCH/RFC] decode extend getsockopt/setsockopt options

2015-08-19 Thread Dmitry V. Levin
On Wed, Aug 19, 2015 at 01:26:56PM -0400, Mike Frysinger wrote:
> On 19 Aug 2015 18:56, Dmitry V. Levin wrote:
> > On Tue, Aug 18, 2015 at 05:03:20PM -0400, Mike Frysinger wrote:
> > [...]
> > > * 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.
> > > ---
> > > RFC: i'm not terribly happy with the printxvals logic.  open to 
> > > suggestions.
> > 
> > What's it in the printxvals logic that doesn't make you happy?
> 
> using varargs all the time when the previous code was just a simple func.
> seems like it's adding a good amount of overhead.  maybe i'm pessimistic
> as i haven't done any perf checks.

We can have two separate functions, it's not a big deal.


-- 
ldv


pgpttFux_rawT.pgp
Description: PGP signature
--
___
Strace-devel mailing list
Strace-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/strace-devel


[PATCH v3] decode extend getsockopt/setsockopt options

2015-08-19 Thread Mike Frysinger
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.
---
v3
- rework xarargs logic

 configure.ac   |  8 
 defs.h |  3 ++-
 net.c  | 31 ++-
 util.c | 23 +--
 xlat/getsockipoptions.in   | 26 ++
 xlat/getsockipv6options.in |  7 +++
 xlat/setsockipoptions.in   | 28 
 xlat/setsockipv6options.in |  5 +
 8 files changed, 119 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 ])
 AC_CHECK_TYPES([struct sigcontext],,, [#include ])
 AC_CHECK_HEADERS([netinet/tcp.h netinet/udp.h],,, [#include ])
+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 
+#include ])
 
 AC_CHECK_TYPES([struct mmsghdr],,, [#include ])
 AC_CHECK_MEMBERS([struct msghdr.msg_control],,, [#include ])
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 
 #endif
 
+#if defined(HAVE_LINUX_IP_VS_H)
+# include 
+#endif
 #if defined(HAVE_LINUX_NETLINK_H)
 # include 
 #endif
+#if defined(HAVE_LINUX_NETFILTER_ARP_ARP_TABLES_H)
+# include 
+#endif
+#if defined(HAVE_LINUX_NETFILTER_BRIDGE_EBTABLES_H)
+# include 
+#endif
+#if defined(HAVE_LINUX_NETFILTER_IPV4_IP_TABLES_H)
+# include 
+#endif
+#if defined(HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H)
+# include 
+#endif
 #if defined(HAVE_LINUX_IF_PACKET_H)
 # include 
 #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 t

Re: [PATCH/RFC] decode extend getsockopt/setsockopt options

2015-08-19 Thread Mike Frysinger
On 19 Aug 2015 18:56, Dmitry V. Levin wrote:
> On Tue, Aug 18, 2015 at 05:03:20PM -0400, Mike Frysinger wrote:
> [...]
> > * 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.
> > ---
> > RFC: i'm not terribly happy with the printxvals logic.  open to suggestions.
> 
> What's it in the printxvals logic that doesn't make you happy?

using varargs all the time when the previous code was just a simple func.
seems like it's adding a good amount of overhead.  maybe i'm pessimistic
as i haven't done any perf checks.

> On Wed, Aug 19, 2015 at 09:14:59AM -0400, Mike Frysinger wrote:
> [...]
> > @@ -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);
> >  }
> >  
> >  /*
> 
> Wouldn't it be a bit simpler to write it this way:
> 
> @@ -207,14 +208,22 @@ 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;
>  
> - if (str)
> - tprints(str);
> - else
> - tprintf("%#x /* %s */", val, dflt);
> + va_start(args, xlat);
> + for (; xlat; xlat = va_arg(args, const struct xlat *)) {
> + const char *str = xlookup(xlat, val);
> +
> + if (str) {
> + tprints(str);
> + return;
> + }
> + }
> + va_end(args);
> +
> + tprintf("%#x /* %s */", val, dflt);
>  }

seems like it'd work too.  although both versions have a bug -- they don't
call va_end before returning.  in my version i could turn it into a break,
but this one needs a 2nd call.  most likely not a big issue.
-mike


signature.asc
Description: Digital signature
--
___
Strace-devel mailing list
Strace-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/strace-devel


Re: compile error for MIPS

2015-08-19 Thread Dmitry V. Levin
On Tue, Aug 18, 2015 at 01:55:09PM +0200, Thomas Schmiedl wrote:
> Hello Dmitry,
> 
> could you explain, how to do this (I'm not a developer). I only imported 
> a preconfigured VM in VirtualBox 
> (http://sourceforge.net/projects/freetz-linux/) and build using this 
> tutorial (http://freetz.org/wiki/help/howtos/development/compile_own_progs).

Could you fetch a snapshot from git://git.code.sf.net/p/strace/code.git
and try to build it?  It contains some _MIPS_SIM related diagnostics.


-- 
ldv


pgpj22wASmftm.pgp
Description: PGP signature
--
___
Strace-devel mailing list
Strace-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/strace-devel


Re: [PATCH/RFC] decode extend getsockopt/setsockopt options

2015-08-19 Thread Dmitry V. Levin
On Tue, Aug 18, 2015 at 05:03:20PM -0400, Mike Frysinger wrote:
[...]
> * 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.
> ---
> RFC: i'm not terribly happy with the printxvals logic.  open to suggestions.

What's it in the printxvals logic that doesn't make you happy?

On Wed, Aug 19, 2015 at 09:14:59AM -0400, Mike Frysinger wrote:
[...]
> @@ -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);
>  }
>  
>  /*

Wouldn't it be a bit simpler to write it this way:

@@ -207,14 +208,22 @@ 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;
 
-   if (str)
-   tprints(str);
-   else
-   tprintf("%#x /* %s */", val, dflt);
+   va_start(args, xlat);
+   for (; xlat; xlat = va_arg(args, const struct xlat *)) {
+   const char *str = xlookup(xlat, val);
+
+   if (str) {
+   tprints(str);
+   return;
+   }
+   }
+   va_end(args);
+
+   tprintf("%#x /* %s */", val, dflt);
 }
 
 /*

-- 
ldv


pgpBqgCXsRhQD.pgp
Description: PGP signature
--
___
Strace-devel mailing list
Strace-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/strace-devel


[PATCH/RFC v2] decode extend getsockopt/setsockopt options

2015-08-19 Thread Mike Frysinger
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 ])
 AC_CHECK_TYPES([struct sigcontext],,, [#include ])
 AC_CHECK_HEADERS([netinet/tcp.h netinet/udp.h],,, [#include ])
+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 
+#include ])
 
 AC_CHECK_TYPES([struct mmsghdr],,, [#include ])
 AC_CHECK_MEMBERS([struct msghdr.msg_control],,, [#include ])
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 
 #endif
 
+#if defined(HAVE_LINUX_IP_VS_H)
+# include 
+#endif
 #if defined(HAVE_LINUX_NETLINK_H)
 # include 
 #endif
+#if defined(HAVE_LINUX_NETFILTER_ARP_ARP_TABLES_H)
+# include 
+#endif
+#if defined(HAVE_LINUX_NETFILTER_BRIDGE_EBTABLES_H)
+# include 
+#endif
+#if defined(HAVE_LINUX_NETFILTER_IPV4_IP_TABLES_H)
+# include 
+#endif
+#if defined(HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H)
+# include 
+#endif
 #if defined(HAVE_LINUX_IF_PACKET_H)
 # include 
 #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