[PATCH 1/2] rtnl_addr: decode ifaddrmsg netlink attributes

JingPiao Chen chenjingpiao at gmail.com
Sun Aug 20 12:17:18 UTC 2017


* rtnl_addr.c: Include <arpa/inet.h> and <linux/netdevice.h>.
(decode_ifa_address, decode_ifa_cacheinfo,
decode_ifa_flags): New functions.
(ifaddrmsg_nla_decoders): New array.
(decode_ifaddrmsg): Use it.
---
 rtnl_addr.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 93 insertions(+), 1 deletion(-)

diff --git a/rtnl_addr.c b/rtnl_addr.c
index c7e37ea..c4bde06 100644
--- a/rtnl_addr.c
+++ b/rtnl_addr.c
@@ -32,16 +32,106 @@
 #include "nlattr.h"
 #include "print_fields.h"
 
+#include <arpa/inet.h>
+
 #include "netlink.h"
 #include <linux/rtnetlink.h>
 #ifdef HAVE_LINUX_IF_ADDR_H
 # include <linux/if_addr.h>
 #endif
+#include <linux/netdevice.h>
 
 #include "xlat/ifaddrflags.h"
 #include "xlat/routing_scopes.h"
 #include "xlat/rtnl_addr_attrs.h"
 
+static bool
+decode_ifa_address(struct tcb *const tcp,
+		   const kernel_ulong_t addr,
+		   const unsigned int len,
+		   const void *const opaque_data)
+{
+	const struct ifaddrmsg *const ifaddr = opaque_data;
+	const unsigned int addr_len =
+		len < MAX_ADDR_LEN ? len : MAX_ADDR_LEN;
+	char buf[MAX_ADDR_LEN];
+
+	if (!umoven_or_printaddr(tcp, addr, addr_len, buf)) {
+		switch (ifaddr->ifa_family) {
+		case AF_INET: {
+			char str[INET_ADDRSTRLEN];
+
+			if (addr_len < sizeof(struct in_addr)
+			    || !inet_ntop(AF_INET, buf, str, sizeof(str)))
+				return false;
+			tprints(str);
+			break;
+		}
+		case AF_INET6: {
+			char str[INET6_ADDRSTRLEN];
+
+			if (addr_len < sizeof(struct in6_addr)
+			    || !inet_ntop(AF_INET6, buf, str, sizeof(str)))
+				break;
+			tprints(str);
+			break;
+		}
+		default:
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static bool
+decode_ifa_cacheinfo(struct tcb *const tcp,
+		     const kernel_ulong_t addr,
+		     const unsigned int len,
+		     const void *const opaque_data)
+{
+	struct ifa_cacheinfo ci;
+
+	if (len < sizeof(ci))
+		return false;
+	else if (!umove_or_printaddr(tcp, addr, &ci)) {
+		PRINT_FIELD_U("{", ci, ifa_prefered);
+		PRINT_FIELD_U(", ", ci, ifa_valid);
+		PRINT_FIELD_U(", ", ci, cstamp);
+		PRINT_FIELD_U(", ", ci, tstamp);
+		tprintf("}");
+	}
+
+	return true;
+}
+
+static bool
+decode_ifa_flags(struct tcb *const tcp,
+		 const kernel_ulong_t addr,
+		 const unsigned int len,
+		 const void *const opaque_data)
+{
+	uint32_t ifa_flags;
+
+	if (len < sizeof(ifa_flags))
+		return false;
+	else if (!umove_or_printaddr(tcp, addr, &ifa_flags))
+		printflags(ifaddrflags, ifa_flags, "IFA_F_???");
+
+	return true;
+}
+
+static const nla_decoder_t ifaddrmsg_nla_decoders[] = {
+	[IFA_ADDRESS]	= decode_ifa_address,
+	[IFA_LOCAL]	= decode_ifa_address,
+	[IFA_LABEL]	= decode_nla_str,
+	[IFA_BROADCAST]	= decode_ifa_address,
+	[IFA_ANYCAST]	= decode_ifa_address,
+	[IFA_CACHEINFO]	= decode_ifa_cacheinfo,
+	[IFA_MULTICAST]	= decode_ifa_address,
+	[IFA_FLAGS]	= decode_ifa_flags
+};
+
 DECL_NETLINK_ROUTE_DECODER(decode_ifaddrmsg)
 {
 	struct ifaddrmsg ifaddr = { .ifa_family = family };
@@ -71,6 +161,8 @@ DECL_NETLINK_ROUTE_DECODER(decode_ifaddrmsg)
 	if (decode_nla && len > offset) {
 		tprints(", ");
 		decode_nlattr(tcp, addr + offset, len - offset,
-			      rtnl_addr_attrs, "IFA_???", NULL, 0, NULL);
+			      rtnl_addr_attrs, "IFA_???",
+			      ifaddrmsg_nla_decoders,
+			      ARRAY_SIZE(ifaddrmsg_nla_decoders), &ifaddr);
 	}
 }
-- 
2.7.4





More information about the Strace-devel mailing list