[PATCH 2/3] genl,netlink: Move extended ACK code to netlink-private

Andrew Zaborowski <andrew.zaborowski at intel.com>
Newsgroups dev.linux.lists.ell
Message-ID <[email protected]>
Since extended ACK parsing can be also useful for rtnl, move it from
genl.c to netlink.c and declare in netlink-private.h.
---
 ell/genl.c            | 61 ++++---------------------------------------
 ell/netlink-private.h | 15 +++++++++++
 ell/netlink.c         | 56 ++++++++++++++++++++++++++++++++++++++-
 3 files changed, 75 insertions(+), 57 deletions(-)

diff --git a/ell/genl.c b/ell/genl.c
index 61b7b3a..c6965db 100644
--- a/ell/genl.c
+++ b/ell/genl.c
@@ -33,9 +33,9 @@
 #include "log.h"
 #include "queue.h"
 #include "io.h"
+#include "private.h"
 #include "netlink-private.h"
 #include "genl.h"
-#include "private.h"
 
 #define MAX_NESTING_LEVEL 4
 #define GENL_DEBUG(fmt, args...)	\
@@ -722,17 +722,6 @@ static bool match_request_hid(const void *a, const void *b)
 	return request->handle_id == id;
 }
 
-#define NLA_OK(nla,len)         ((len) >= (int) sizeof(struct nlattr) && \
-				(nla)->nla_len >= sizeof(struct nlattr) && \
-				(nla)->nla_len <= (len))
-#define NLA_NEXT(nla,attrlen)	((attrlen) -= NLMSG_ALIGN((nla)->nla_len), \
-				(struct nlattr*)(((char*)(nla)) + \
-				NLMSG_ALIGN((nla)->nla_len)))
-
-#define NLA_LENGTH(len)		(NLMSG_ALIGN(sizeof(struct nlattr)) + (len))
-#define NLA_DATA(nla)		((void*)(((char*)(nla)) + NLA_LENGTH(0)))
-#define NLA_PAYLOAD(nla)	((int)((nla)->nla_len) - NLA_LENGTH(0))
-
 static struct l_genl_msg *msg_alloc(uint8_t cmd, uint8_t version, uint32_t size)
 {
 	struct l_genl_msg *msg;
@@ -774,52 +763,13 @@ static bool msg_grow(struct l_genl_msg *msg, uint32_t needed)
 static struct l_genl_msg *msg_create(const struct nlmsghdr *nlmsg)
 {
 	struct l_genl_msg *msg;
+	const char *error_msg = NULL;
 
 	msg = l_new(struct l_genl_msg, 1);
 
-	if (nlmsg->nlmsg_type == NLMSG_ERROR) {
-		struct nlmsgerr *err = NLMSG_DATA(nlmsg);
-		unsigned int offset = 0;
-		struct nlattr *nla;
-		int len;
-
-		msg->error = err->error;
-
-		if (!(nlmsg->nlmsg_flags & NLM_F_ACK_TLVS))
-			goto done;
-
-		/*
-		 * If the message is capped, then err->msg.nlmsg_len contains
-		 * the length of the original message and thus can't be used
-		 * to calculate the offset
-		 */
-		if (!(nlmsg->nlmsg_flags & NLM_F_CAPPED))
-			offset = err->msg.nlmsg_len - sizeof(struct nlmsghdr);
-
-		/*
-		 * Attributes start past struct nlmsgerr.  The offset is 0
-		 * for NLM_F_CAPPED messages.  Otherwise the original message
-		 * is included, and thus the offset takes err->msg.nlmsg_len
-		 * into account
-		 */
-		nla = (void *)(err + 1) + offset;
-
-		/* Calculate bytes taken up by header + nlmsgerr contents */
-		offset += sizeof(struct nlmsghdr) + sizeof(struct nlmsgerr);
-		if (nlmsg->nlmsg_len <= offset)
-			goto done;
-
-		len = nlmsg->nlmsg_len - offset;
-
-		for (; NLA_OK(nla, len); nla = NLA_NEXT(nla, len)) {
-			if ((nla->nla_type & NLA_TYPE_MASK) !=
-					NLMSGERR_ATTR_MSG)
-				continue;
-
-			msg->error_msg = l_strdup(NLA_DATA(nla));
-			goto done;
-		}
-	}
+	if (netlink_parse_ext_ack(nlmsg, &error_msg, NULL) &&
+			error_msg)
+		msg->error_msg = l_strdup(error_msg);
 
 	msg->data = l_memdup(nlmsg, nlmsg->nlmsg_len);
 
@@ -833,7 +783,6 @@ static struct l_genl_msg *msg_create(const struct nlmsghdr *nlmsg)
 		msg->version = genlmsg->version;
 	}
 
-done:
 	return l_genl_msg_ref(msg);
 }
 
diff --git a/ell/netlink-private.h b/ell/netlink-private.h
index fff30af..fab0ab9 100644
--- a/ell/netlink-private.h
+++ b/ell/netlink-private.h
@@ -23,3 +23,18 @@
 #ifndef SOL_NETLINK
 #define SOL_NETLINK 270
 #endif
+
+#define NLA_OK(nla,len)         ((len) >= (int) sizeof(struct nlattr) && \
+				(nla)->nla_len >= sizeof(struct nlattr) && \
+				(nla)->nla_len <= (len))
+#define NLA_NEXT(nla,attrlen)	((attrlen) -= NLMSG_ALIGN((nla)->nla_len), \
+				(struct nlattr*)(((char*)(nla)) + \
+				NLMSG_ALIGN((nla)->nla_len)))
+
+#define NLA_LENGTH(len)		(NLMSG_ALIGN(sizeof(struct nlattr)) + (len))
+#define NLA_DATA(nla)		((void*)(((char*)(nla)) + NLA_LENGTH(0)))
+#define NLA_PAYLOAD(nla)	((int)((nla)->nla_len) - NLA_LENGTH(0))
+
+bool netlink_parse_ext_ack(const struct nlmsghdr *nlmsg,
+				const char **out_error_msg,
+				uint32_t *out_error_offset);
diff --git a/ell/netlink.c b/ell/netlink.c
index 4b6d800..32d021b 100644
--- a/ell/netlink.c
+++ b/ell/netlink.c
@@ -32,9 +32,9 @@
 #include "hashmap.h"
 #include "queue.h"
 #include "io.h"
+#include "private.h"
 #include "netlink-private.h"
 #include "netlink.h"
-#include "private.h"
 
 struct command {
 	unsigned int id;
@@ -611,3 +611,57 @@ LIB_EXPORT bool l_netlink_set_debug(struct l_netlink *netlink,
 
 	return true;
 }
+
+bool netlink_parse_ext_ack(const struct nlmsghdr *nlmsg,
+				const char **out_error_msg,
+				uint32_t *out_error_offset)
+{
+	const struct nlmsgerr *err;
+	unsigned int offset = 0;
+	struct nlattr *nla;
+	int len;
+
+	if (nlmsg->nlmsg_type != NLMSG_ERROR ||
+			!(nlmsg->nlmsg_flags & NLM_F_ACK_TLVS))
+		return false;
+
+	err = NLMSG_DATA(nlmsg);
+
+	/*
+	 * If the message is capped, then err->msg.nlmsg_len contains the
+	 * length of the original message and thus can't be used to
+	 * calculate the offset.
+	 */
+	if (!(nlmsg->nlmsg_flags & NLM_F_CAPPED))
+		offset = err->msg.nlmsg_len - sizeof(struct nlmsghdr);
+
+	/*
+	 * Attributes start past struct nlmsgerr.  The offset is 0 for
+	 * NLM_F_CAPPED messages.  Otherwise the original message is
+	 * included, and thus the offset takes err->msg.nlmsg_len into
+	 * account.
+	 */
+	nla = (void *)(err + 1) + offset;
+
+	/* Calculate bytes taken up by header + nlmsgerr contents */
+	offset += sizeof(struct nlmsghdr) + sizeof(struct nlmsgerr);
+	if (nlmsg->nlmsg_len <= offset)
+		return false;
+
+	len = nlmsg->nlmsg_len - offset;
+
+	for (; NLA_OK(nla, len); nla = NLA_NEXT(nla, len)) {
+		switch (nla->nla_type & NLA_TYPE_MASK) {
+		case NLMSGERR_ATTR_MSG:
+			if (out_error_msg)
+				*out_error_msg = NLA_DATA(nla);
+			break;
+		case NLMSGERR_ATTR_OFFS:
+			if (out_error_offset)
+				*out_error_offset = l_get_u32(NLA_DATA(nla));
+			break;
+		}
+	}
+
+	return true;
+}
-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.