[PATCH v2 17/18] netlink: decode AF_INET inet_diag_req attributes
JingPiao Chen
chenjingpiao at gmail.com
Tue Jun 27 10:10:19 UTC 2017
* 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 a90dda7..eb8bf45 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, 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(struct inet_diag_bc_op *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, 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, 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
More information about the Strace-devel
mailing list