[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