[PATCH 4/5] netlink: add a basic rtnetlink parser of link messages

JingPiao Chen chenjingpiao at gmail.com
Tue Jul 25 14:30:02 UTC 2017


* defs.h (arp_hardware_types, iffflags): New xlat prototypes.
* netlink_route.c: Include "print_fields.h" and <linux/rtnetlink.h>.
(decode_ifinfomsg): New function.
(netlink_route_decoder_t): New typedef.
(route_decoders): New array.
(decode_netlink_route): Use it.

Co-authored-by: Fabien Siron <fabien.siron at epita.fr>
---
 defs.h          |  2 ++
 netlink_route.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/defs.h b/defs.h
index a9d0b00..dec87bf 100644
--- a/defs.h
+++ b/defs.h
@@ -287,11 +287,13 @@ struct tcb {
 #include "xlat.h"
 
 extern const struct xlat addrfams[];
+extern const struct xlat arp_hardware_types[];
 extern const struct xlat at_flags[];
 extern const struct xlat clocknames[];
 extern const struct xlat dirent_types[];
 extern const struct xlat ethernet_protocols[];
 extern const struct xlat evdev_abs[];
+extern const struct xlat iffflags[];
 extern const struct xlat inet_protocols[];
 extern const struct xlat msg_flags[];
 extern const struct xlat netlink_protocols[];
diff --git a/netlink_route.c b/netlink_route.c
index dc5a13f..3da6dfb 100644
--- a/netlink_route.c
+++ b/netlink_route.c
@@ -29,6 +29,9 @@
 
 #include "defs.h"
 #include "netlink.h"
+#include "print_fields.h"
+
+#include <linux/rtnetlink.h>
 
 #include "xlat/nl_route_types.h"
 
@@ -46,19 +49,69 @@ decode_family(struct tcb *const tcp, const uint8_t family,
 	tprints("}");
 }
 
+static void
+decode_ifinfomsg(struct tcb *tcp,
+		 const struct nlmsghdr *nlmsghdr,
+		 const uint8_t family,
+		 const kernel_ulong_t addr,
+		 const unsigned int len)
+{
+	struct ifinfomsg ifinfo = { .ifi_family = family };
+	const size_t offset = sizeof(ifinfo.ifi_family);
+
+	PRINT_FIELD_XVAL("{", ifinfo, ifi_family, addrfams, "AF_???");
+
+	tprints(", ");
+	if (len >= sizeof(ifinfo)) {
+		if (!umoven_or_printaddr(tcp, addr + offset,
+					 sizeof(ifinfo) - offset,
+					 (void *) &ifinfo + offset)) {
+			PRINT_FIELD_XVAL("", ifinfo, ifi_type,
+					 arp_hardware_types, "ARPHRD_???");
+			PRINT_FIELD_IFINDEX(", ", ifinfo, ifi_index);
+			PRINT_FIELD_FLAGS(", ", ifinfo, ifi_flags,
+					  iffflags, "IFF_???");
+			PRINT_FIELD_X(", ", ifinfo, ifi_change);
+		}
+	} else
+		tprints("...");
+	tprints("}");
+}
+
+typedef void (*netlink_route_decoder_t)(struct tcb *,
+				        const struct nlmsghdr *,
+					uint8_t family,
+					kernel_ulong_t addr,
+					unsigned int len);
+
+static const netlink_route_decoder_t route_decoders[] = {
+	[RTM_DELLINK - RTM_BASE] = decode_ifinfomsg,
+	[RTM_GETLINK - RTM_BASE] = decode_ifinfomsg,
+	[RTM_NEWLINK - RTM_BASE] = decode_ifinfomsg,
+	[RTM_SETLINK - RTM_BASE] = decode_ifinfomsg
+};
+
 bool
 decode_netlink_route(struct tcb *const tcp,
 		     const struct nlmsghdr *const nlmsghdr,
 		     const kernel_ulong_t addr,
 		     const unsigned int len)
 {
+	unsigned int type = nlmsghdr->nlmsg_type;
 	uint8_t family;
 
 	if (nlmsghdr->nlmsg_type == NLMSG_DONE)
 		return false;
 
-	if (!umove_or_printaddr(tcp, addr, &family))
-		decode_family(tcp, family, addr, len);
+	if (!umove_or_printaddr(tcp, addr, &family)) {
+		if (type > RTM_BASE
+		    && type - RTM_BASE < ARRAY_SIZE(route_decoders)
+		    && route_decoders[type - RTM_BASE]) {
+			route_decoders[type - RTM_BASE](tcp, nlmsghdr,
+							family, addr, len);
+		} else
+			decode_family(tcp, family, addr, len);
+	}
 
 	return true;
 }
-- 
2.7.4





More information about the Strace-devel mailing list