[PATCH v5 1/8] netlink: decode AF_INET inet_diag_req attributes
JingPiao Chen
chenjingpiao at gmail.com
Tue Jul 11 02:50:08 UTC 2017
* netlink_sock_diag.c: Include "xlat/inet_diag_bytecodes.h".
(decode_inet_addr, decode_inet_diag_hostcond,
print_inet_diag_bc_op, decode_inet_diag_markcond,
decode_bytecode_data, decode_inet_diag_bc_op): New functions.
(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 | 170 +++++++++++++++++++++++++++++++++++++++++++-
xlat/inet_diag_bytecodes.in | 12 ++++
3 files changed, 212 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 1bb832e..121c8cb 100644
--- a/netlink_sock_diag.c
+++ b/netlink_sock_diag.c
@@ -45,6 +45,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"
@@ -619,6 +620,169 @@ print_inet_diag_sockid(const struct inet_diag_sockid *id, const uint8_t family)
} while (0)
static void
+decode_inet_addr(struct tcb *const tcp,
+ const kernel_ulong_t addr,
+ const kernel_ulong_t len,
+ const int family)
+{
+ union {
+ struct in_addr a4;
+ struct in6_addr a6;
+ } addrbuf;
+ size_t size = 0;
+
+ switch (family) {
+ case AF_INET:
+ size = sizeof(addrbuf.a4);
+ break;
+ case AF_INET6:
+ size = sizeof(addrbuf.a6);
+ break;
+ }
+
+ if (!size || len < size) {
+ tprints("addr=");
+ printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
+ return;
+ }
+
+ if (umoven(tcp, addr, size, &addrbuf) < 0) {
+ tprints("addr=");
+ printaddr(addr);
+ return;
+ }
+
+ print_inet_addr(family, &addrbuf, size, "addr");
+}
+
+static void
+decode_inet_diag_hostcond(struct tcb *const tcp,
+ const kernel_ulong_t addr,
+ const kernel_ulong_t len)
+{
+ struct inet_diag_hostcond cond;
+
+ if (len < sizeof(cond)) {
+ printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
+ return;
+ }
+ if (umove_or_printaddr(tcp, addr, &cond))
+ return;
+
+ PRINT_FIELD_XVAL("{", cond, family, addrfams, "AF_???");
+ PRINT_FIELD_U(", ", cond, prefix_len);
+ PRINT_FIELD_U(", ", 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)
+{
+ PRINT_FIELD_XVAL("{", *op, code, inet_diag_bytecodes,
+ "INET_DIAG_BC_???");
+ PRINT_FIELD_U(", ", *op, yes);
+ PRINT_FIELD_U(", ", *op, no);
+ tprints("}");
+}
+
+static void
+decode_inet_diag_markcond(struct tcb *const tcp,
+ const kernel_ulong_t addr,
+ const kernel_ulong_t len)
+{
+ struct inet_diag_markcond markcond;
+
+ if (len < sizeof(markcond))
+ printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
+ else if (!umove_or_printaddr(tcp, addr, &markcond)) {
+ PRINT_FIELD_U("{", markcond, mark);
+ PRINT_FIELD_U(", ", markcond, mask);
+ tprints("}");
+ }
+}
+
+static void
+decode_bytecode_data(struct tcb *const tcp,
+ const kernel_ulong_t addr,
+ const 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))
+ printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
+ else if (!umove_or_printaddr(tcp, addr, &ifindex))
+ print_ifindex(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))
+ printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
+ else if (!umove_or_printaddr(tcp, addr, &op))
+ 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:
+ printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
+ break;
+ }
+}
+
+static bool
+decode_inet_diag_bc_op(struct tcb *const tcp,
+ const kernel_ulong_t addr,
+ const 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;
+
+ if (len > sizeof(op))
+ 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,
const uint8_t family,
@@ -656,7 +820,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);
}
}
@@ -697,7 +862,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..ccaf0da
--- /dev/null
+++ b/xlat/inet_diag_bytecodes.in
@@ -0,0 +1,12 @@
+#unconditional
+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
+INET_DIAG_BC_MARK_COND
--
2.7.4
More information about the Strace-devel
mailing list