[PATCH v4 09/11] netlink: decode AF_INET inet_diag_req attributes

JingPiao Chen chenjingpiao at gmail.com
Thu Jul 6 01:57:35 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         | 188 +++++++++++++++++++++++++++++++++++++++++++-
 xlat/inet_diag_bytecodes.in |  12 +++
 3 files changed, 230 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 42860aa..29d61cb 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"
 
@@ -620,6 +621,187 @@ print_inet_diag_sockid(const struct inet_diag_sockid *id, const uint8_t family)
 }
 
 static void
+decode_inet_addr(struct tcb *const tcp,
+		 const kernel_ulong_t addr,
+		 const 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 *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);
+		return;
+	}
+	if (umove_or_printaddr(tcp, addr, &markcond))
+		return;
+
+	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);
+			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)) {
+			printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
+			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:
+		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,
@@ -657,7 +839,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);
 	}
 }
 
@@ -698,7 +881,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