[PATCH v9 4/4] Netlink: Add support for NLMSG_ERROR and NLMSG_DONE

Fabien Siron fabien.siron at epita.fr
Wed Jul 6 15:49:25 UTC 2016


Manage netlink "error" messages and "done" messages mainly to avoid
later garbage printing.

* netlink.c (nlmsg_data, decode_netlink_nlmsghdr, decode_netlink_error):
New functions.
(decode_netlink_msg): Change return type to int and call
decode_netlink_nlmsghdr() and decode_netlink_error().
(decode_netlink): Break loop if decode_netlink_msg() returns 0.
---
 netlink.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 58 insertions(+), 11 deletions(-)

diff --git a/netlink.c b/netlink.c
index fc746ed..aea1bc7 100644
--- a/netlink.c
+++ b/netlink.c
@@ -26,6 +26,7 @@
  */
 
 #include "defs.h"
+#include <string.h>
 #include <sys/socket.h>
 #include <linux/netlink.h>
 #include "xlat/netlink_flags.h"
@@ -69,34 +70,79 @@ next_nlmsg(struct nlmsghdr *nlmsghdr, unsigned long addr, unsigned long *len) {
 		return 0;
 }
 
+static unsigned long
+nlmsg_data(unsigned long nlh) {
+	return nlh + NLMSG_LENGTH(0);
+}
+
 static void
-decode_netlink_msg(struct tcb *tcp, struct nlmsghdr *nlmsghdr,
-		   unsigned long addr, unsigned long size)
+decode_netlink_nlmsghdr(struct tcb *tcp, struct nlmsghdr *nlmsghdr)
 {
-	if (size < sizeof(struct nlmsghdr)) {
-		printstr(tcp, addr, size);
-		return;
-	}
-
-	tprintf("{{len=%u, type=", nlmsghdr->nlmsg_len);
+	tprintf("{len=%u, type=", nlmsghdr->nlmsg_len);
 
 	printxval(netlink_types, nlmsghdr->nlmsg_type, "NLMSG_???");
 
 	tprints(", flags=");
 	printflags(netlink_flags, nlmsghdr->nlmsg_flags, "NLM_F_???");
-	/* manage get/new requests */
 
 	tprintf(", seq=%u, pid=%u}", nlmsghdr->nlmsg_seq,
 		nlmsghdr->nlmsg_pid);
+}
+
+static void
+decode_netlink_error(struct tcb *tcp, unsigned long addr, unsigned long size)
+{
+	struct nlmsgerr err;
+
+	if (umove_or_printaddr(tcp, addr, &err) < 0)
+		return;
+
+	tprintf(", {error=\"%s\", msg=", strerror(-err.error));
+
+	decode_netlink_nlmsghdr(tcp, &err.msg);
+
+	tprints("}");
+}
+
+static int
+decode_netlink_msg(struct tcb *tcp, struct nlmsghdr *nlmsghdr,
+		   unsigned long addr, unsigned long size)
+{
+	if (size < sizeof(struct nlmsghdr)) {
+		printstr(tcp, addr, size);
+		return 0;
+	}
+
+	tprints("{");
+
+	decode_netlink_nlmsghdr(tcp, nlmsghdr);
 
 	if (nlmsghdr->nlmsg_len - sizeof(struct nlmsghdr) > 0) {
-		tprints(", ");
+		unsigned long data;
+		data = nlmsg_data(addr);
+
+		if (nlmsghdr->nlmsg_type < NLMSG_MIN_TYPE)
+		{
+			switch (nlmsghdr->nlmsg_type)
+			{
+			case NLMSG_ERROR:
+				decode_netlink_error(tcp, data,
+						     nlmsghdr->nlmsg_len -
+						     sizeof(struct nlmsghdr));
+			case NLMSG_DONE:
+				tprints("}");
+				return 0;
+			}
+		}
 
+		tprints(", ");
 		printstr(tcp, addr + sizeof(struct nlmsghdr),
 			 nlmsghdr->nlmsg_len - sizeof(struct nlmsghdr));
 	}
 
 	tprints("}");
+
+	return 1;
 }
 
 void
@@ -128,7 +174,8 @@ decode_netlink(struct tcb *tcp, unsigned long addr, unsigned long total_size) {
 			tprints("[");
 		}
 
-		decode_netlink_msg(tcp, &nlmsghdr, addr, size);
+		if (!decode_netlink_msg(tcp, &nlmsghdr, addr, size))
+			break;
 
 		if (size > nlmsghdr.nlmsg_len)
 			tprints(", ");
-- 
2.9.0





More information about the Strace-devel mailing list