diff mbox

[RFC,ABI,2/8] lib/nlattr: Add parsing netlink and validate using callback

Message ID 1464100526-31730-3-git-send-email-leonro@mellanox.com (mailing list archive)
State RFC
Headers show

Commit Message

Leon Romanovsky May 24, 2016, 2:35 p.m. UTC
From: Matan Barak <matanb@mellanox.com>

When parsing netlink packets, users may want to do some extra
validations on the netlink attributes. Adding nla_parse_cb, which
gets an extra callback parameter. This function is invoked for every
netlink attribute. If the callback fails, parsing will fail as well.

Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Haggai Eran <haggaie@mellanox.com>
---
 include/linux/netlink.h |  1 -
 include/net/netlink.h   |  5 +++++
 lib/nlattr.c            | 43 ++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 45 insertions(+), 4 deletions(-)
diff mbox

Patch

diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index da14ab6..a08b63b 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -117,7 +117,6 @@  netlink_skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
 
 #define NLMSG_DEFAULT_SIZE (NLMSG_GOODSIZE - NLMSG_HDRLEN)
 
-
 struct netlink_callback {
 	struct sk_buff		*skb;
 	const struct nlmsghdr	*nlh;
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 0e31727..70ba851 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -149,6 +149,8 @@ 
  *   nla_find()				find attribute in stream of attributes
  *   nla_find_nested()			find attribute in nested attributes
  *   nla_parse()			parse and validate stream of attrs
+ *   nla_parse_cb()			parse stream of attrs and call to
+ *						callback for every nlattr
  *   nla_parse_nested()			parse nested attribuets
  *   nla_for_each_attr()		loop over all attributes
  *   nla_for_each_nested()		loop over the nested attributes
@@ -237,6 +239,9 @@  int nla_validate(const struct nlattr *head, int len, int maxtype,
 		 const struct nla_policy *policy);
 int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
 	      int len, const struct nla_policy *policy);
+int nla_parse_cb(struct nlattr **tb, int maxtype, const struct nlattr *head,
+		 int len, const struct nla_policy *policy,
+		 int (*cb)(const struct nlattr *, void *), void *cb_priv);
 int nla_policy_len(const struct nla_policy *, int);
 struct nlattr *nla_find(const struct nlattr *head, int len, int attrtype);
 size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize);
diff --git a/lib/nlattr.c b/lib/nlattr.c
index f5907d2..ec79387 100644
--- a/lib/nlattr.c
+++ b/lib/nlattr.c
@@ -165,22 +165,28 @@  nla_policy_len(const struct nla_policy *p, int n)
 EXPORT_SYMBOL(nla_policy_len);
 
 /**
- * nla_parse - Parse a stream of attributes into a tb buffer
+ * nla_parse_cb - Parse a stream of attributes into a tb buffer with callback
  * @tb: destination array with maxtype+1 elements
  * @maxtype: maximum attribute type to be expected
  * @head: head of attribute stream
  * @len: length of attribute stream
  * @policy: validation policy
+ * @cb: callback function and data, must not be NULL
+ * @cb_priv: private data for the callback
  *
  * Parses a stream of attributes and stores a pointer to each attribute in
  * the tb array accessible via the attribute type. Attributes with a type
  * exceeding maxtype will be silently ignored for backwards compatibility
  * reasons. policy may be set to NULL if no validation is required.
+ * For every validated nla, the function calls the user-space callback.
+ * If the callback fails (returns with non-zero value), parsing is terminated
+ * and this value is returned as error.
  *
  * Returns 0 on success or a negative error code.
  */
-int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
-	      int len, const struct nla_policy *policy)
+int nla_parse_cb(struct nlattr **tb, int maxtype, const struct nlattr *head,
+		 int len, const struct nla_policy *policy,
+		 int (*cb)(const struct nlattr *, void *), void *cb_priv)
 {
 	const struct nlattr *nla;
 	int rem, err;
@@ -196,6 +202,9 @@  int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
 				if (err < 0)
 					goto errout;
 			}
+			err = cb(nla, cb_priv);
+			if (err)
+				goto errout;
 
 			tb[type] = (struct nlattr *)nla;
 		}
@@ -209,6 +218,34 @@  int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
 errout:
 	return err;
 }
+EXPORT_SYMBOL(nla_parse_cb);
+
+static int nla_pass_all_cb(const struct nlattr *nla, void *priv)
+{
+	return 0;
+}
+
+/**
+ * nla_parse - Parse a stream of attributes into a tb buffer
+ * @tb: destination array with maxtype+1 elements
+ * @maxtype: maximum attribute type to be expected
+ * @head: head of attribute stream
+ * @len: length of attribute stream
+ * @policy: validation policy
+ *
+ * Parses a stream of attributes and stores a pointer to each attribute in
+ * the tb array accessible via the attribute type. Attributes with a type
+ * exceeding maxtype will be silently ignored for backwards compatibility
+ * reasons. policy may be set to NULL if no validation is required.
+ *
+ * Returns 0 on success or a negative error code.
+ */
+int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
+	      int len, const struct nla_policy *policy)
+{
+	return nla_parse_cb(tb, maxtype, head, len, policy, nla_pass_all_cb,
+			    NULL);
+}
 EXPORT_SYMBOL(nla_parse);
 
 /**