* netlink_sock_diag.c: Include "xlat/inet_diag_bytecodes.h".
(inet_diag_req_nla_decoders): New array.
(decode_inet_diag_req_compat, decode_inet_diag_req_v2): Use it.
* linux/inet_diag.h (inet_diag_bc_op, inet_diag_hostcond,
inet_diag_markcond): New structures.
(INET_DIAG_BC_*): New enum.
* xlat/inet_diag_bytecodes.in: New file.
---
 linux/inet_diag.h           |  32 ++++++++
 netlink_sock_diag.c         | 176 +++++++++++++++++++++++++++++++++++++++++++-
 xlat/inet_diag_bytecodes.in |  11 +++
 3 files changed, 217 insertions(+), 2 deletions(-)
 create mode 100644 xlat/inet_diag_bytecodes.in

diff --git a/linux/inet_diag.h b/linux/inet_diag.h
index 24302db..ec6356c 100644
--- a/linux/inet_diag.h
+++ b/linux/inet_diag.h
@@ -39,6 +39,38 @@ enum {
        INET_DIAG_REQ_BYTECODE,
 };
 
+struct inet_diag_bc_op {
+       unsigned char code;
+       unsigned char yes;
+       unsigned short no;
+};
+
+enum {
+       INET_DIAG_BC_NOP,
+       INET_DIAG_BC_JMP,
+       INET_DIAG_BC_S_GE,
+       INET_DIAG_BC_S_LE,
+       INET_DIAG_BC_D_GE,
+       INET_DIAG_BC_D_LE,
+       INET_DIAG_BC_AUTO,
+       INET_DIAG_BC_S_COND,
+       INET_DIAG_BC_D_COND,
+       INET_DIAG_BC_DEV_COND,   /* u32 ifindex */
+       INET_DIAG_BC_MARK_COND,
+};
+
+struct inet_diag_hostcond {
+       uint8_t family;
+       uint8_t prefix_len;
+       int port;
+       uint32_t addr[0];
+};
+
+struct inet_diag_markcond {
+       uint32_t mark;
+       uint32_t mask;
+};
+
 /* Info structure */
 struct inet_diag_msg {
        uint8_t idiag_family;
diff --git a/netlink_sock_diag.c b/netlink_sock_diag.c
index b5b750a..f31b1ff 100644
--- a/netlink_sock_diag.c
+++ b/netlink_sock_diag.c
@@ -43,6 +43,7 @@
 #include <linux/unix_diag.h>
 
 #include "xlat/inet_diag_attrs.h"
+#include "xlat/inet_diag_bytecodes.h"
 #include "xlat/inet_diag_extended_flags.h"
 #include "xlat/inet_diag_req_attrs.h"
 
@@ -634,6 +635,175 @@ print_inet_diag_sockid(const struct inet_diag_sockid *id, 
const uint8_t family)
                id->idiag_if, id->idiag_cookie[0], id->idiag_cookie[1]);
 }
 
+
+static void
+decode_inet_addr(struct tcb *tcp, kernel_ulong_t addr,
+                kernel_ulong_t len, const int family)
+{
+       switch (family) {
+       case AF_INET: {
+               struct in_addr in_addr;
+
+               if (len < sizeof(in_addr)) {
+                       printstrn(tcp, addr, len);
+                       break;
+               }
+
+               if (umove_or_printaddr(tcp, addr, &in_addr))
+                       break;
+
+               print_inet_addr(family, &in_addr.s_addr,
+                               sizeof(in_addr.s_addr), "addr.s_addr");
+               break;
+       }
+       case AF_INET6: {
+               struct in6_addr in6_addr;
+
+               if (len < sizeof(in6_addr)) {
+                       printstrn(tcp, addr, len);
+                       break;
+               }
+               if (umove_or_printaddr(tcp, addr, &in6_addr))
+                       break;
+
+               print_inet_addr(family, in6_addr.s6_addr,
+                               sizeof(in6_addr.s6_addr),"addr.s6_addr");
+               break;
+       }
+       default:
+               tprints("addr=");
+               printstrn(tcp, addr, len);
+               break;
+       }
+}
+
+static void
+decode_inet_diag_hostcond(struct tcb *tcp, kernel_ulong_t addr,
+                         kernel_ulong_t len)
+{
+       struct inet_diag_hostcond cond;
+
+       if (len < sizeof(cond)) {
+               printstrn(tcp, addr, len);
+               return;
+       }
+       if (umove_or_printaddr(tcp, addr, &cond))
+               return;
+
+       tprints("{family=");
+       printxval(addrfams, cond.family, "AF_???");
+       tprintf(", prefix_len=%u, port=%d", cond.prefix_len, cond.port);
+
+       if (len > sizeof(cond)) {
+               tprints(", ");
+               decode_inet_addr(tcp, addr + sizeof(cond),
+                                len - sizeof(cond), cond.family);
+       }
+       tprints("}");
+}
+
+static void
+print_inet_diag_bc_op(const struct inet_diag_bc_op *const op)
+{
+       tprints("{code=");
+       printxval(inet_diag_bytecodes, op->code, "INET_DIAG_BC_???");
+       tprintf(", yes=%u, no=%hu}", op->yes, op->no);
+}
+
+static void
+decode_inet_diag_markcond(struct tcb *tcp, kernel_ulong_t addr,
+                         kernel_ulong_t len)
+{
+       struct inet_diag_markcond markcond;
+
+       if (len < sizeof(markcond)) {
+               printstrn(tcp, addr, len);
+               return;
+       }
+       if (umove_or_printaddr(tcp, addr, &markcond))
+               return;
+
+       tprintf("{mark=%" PRIu32 ", mask=%" PRIu32 "}",
+               markcond.mark, markcond.mask);
+}
+
+static void
+decode_bytecode_data(struct tcb *tcp, kernel_ulong_t addr,
+                    kernel_ulong_t len, const unsigned char code)
+{
+       switch (code) {
+       case INET_DIAG_BC_S_COND:
+       case INET_DIAG_BC_D_COND:
+               decode_inet_diag_hostcond(tcp, addr, len);
+               break;
+       case INET_DIAG_BC_DEV_COND: {
+               uint32_t ifindex;
+
+               if (len < sizeof(ifindex)) {
+                       printstrn(tcp, addr, len);
+                       break;
+               }
+               if (umove_or_printaddr(tcp, addr, &ifindex))
+                       break;
+
+               tprintf("%" PRIu32, ifindex);
+               break;
+       }
+       case INET_DIAG_BC_S_GE:
+       case INET_DIAG_BC_S_LE:
+       case INET_DIAG_BC_D_GE:
+       case INET_DIAG_BC_D_LE: {
+               struct inet_diag_bc_op op;
+
+               if (len < sizeof(op)) {
+                       printstrn(tcp, addr, len);
+                       break;
+               }
+               if (umove_or_printaddr(tcp, addr, &op))
+                       break;
+
+               print_inet_diag_bc_op(&op);
+               break;
+       }
+       case INET_DIAG_BC_MARK_COND:
+               decode_inet_diag_markcond(tcp, addr, len);
+               break;
+       case INET_DIAG_BC_AUTO:
+       case INET_DIAG_BC_JMP:
+       case INET_DIAG_BC_NOP:
+       default:
+               printstrn(tcp, addr, len);
+               break;
+       }
+}
+
+static bool
+decode_inet_diag_bc_op(struct tcb *tcp, kernel_ulong_t addr,
+                      kernel_ulong_t len, const void *const opaque_data)
+{
+       struct inet_diag_bc_op op;
+
+       if (len < sizeof(op))
+               return false;
+       if (umove_or_printaddr(tcp, addr, &op))
+               return true;
+
+       tprints("{");
+       print_inet_diag_bc_op(&op);
+       if (len > sizeof(op)) {
+               tprints(", ");
+               decode_bytecode_data(tcp, addr + sizeof(op),
+                                    len - sizeof(op), op.code);
+       }
+       tprints("}");
+
+       return true;
+}
+
+static const nla_decoder_t inet_diag_req_nla_decoders[] = {
+       [INET_DIAG_REQ_BYTECODE] = decode_inet_diag_bc_op
+};
+
 static void
 decode_inet_diag_req_compat(struct tcb *const tcp,
                            const struct nlmsghdr *const nlmsghdr,
@@ -677,7 +847,8 @@ decode_inet_diag_req_compat(struct tcb *const tcp,
                tprints(", ");
                decode_nlattr(tcp, addr + offset, len - offset,
                              inet_diag_req_attrs, "INET_DIAG_REQ_???",
-                             NULL, 0, NULL);
+                             inet_diag_req_nla_decoders,
+                             ARRAY_SIZE(inet_diag_req_nla_decoders), NULL);
        }
 }
 
@@ -722,7 +893,8 @@ decode_inet_diag_req_v2(struct tcb *const tcp,
                tprints(", ");
                decode_nlattr(tcp, addr + offset, len - offset,
                              inet_diag_req_attrs, "INET_DIAG_REQ_???",
-                             NULL, 0, NULL);
+                             inet_diag_req_nla_decoders,
+                             ARRAY_SIZE(inet_diag_req_nla_decoders), NULL);
        }
 }
 
diff --git a/xlat/inet_diag_bytecodes.in b/xlat/inet_diag_bytecodes.in
new file mode 100644
index 0000000..e75f424
--- /dev/null
+++ b/xlat/inet_diag_bytecodes.in
@@ -0,0 +1,11 @@
+INET_DIAG_BC_NOP       0
+INET_DIAG_BC_JMP       1
+INET_DIAG_BC_S_GE      2
+INET_DIAG_BC_S_LE      3
+INET_DIAG_BC_D_GE      4
+INET_DIAG_BC_D_LE      5
+INET_DIAG_BC_AUTO      6
+INET_DIAG_BC_S_COND    7
+INET_DIAG_BC_D_COND    8
+INET_DIAG_BC_DEV_COND  9
+INET_DIAG_BC_MARK_COND 10
-- 
2.7.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Strace-devel mailing list
Strace-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/strace-devel

Reply via email to