summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2013-03-13 16:53:07 +0100
committerThomas Graf <tgraf@suug.ch>2013-03-14 12:46:01 +0100
commit9e6cdbf6fc60f95e232c4ca34004606da9536d01 (patch)
tree16ee3ee5574e986e1875df669cba6c541c0aaffb
parent4d7680c19c131175e2ec431de9a026230c968a7e (diff)
attr: Add nla_nest_cancel() to remove partially added nested attributes
Signed-off-by: Thomas Graf <tgraf@suug.ch>
-rw-r--r--doc/core.txt1
-rw-r--r--include/netlink/attr.h1
-rw-r--r--lib/attr.c25
3 files changed, 25 insertions, 2 deletions
diff --git a/doc/core.txt b/doc/core.txt
index 8a26dba..1e951d0 100644
--- a/doc/core.txt
+++ b/doc/core.txt
@@ -2316,6 +2316,7 @@ int put_opts(struct nl_msg *msg)
return 0;
nla_put_failure:
+ nla_nest_cancel(msg, opts);
return -EMSGSIZE;
}
--------
diff --git a/include/netlink/attr.h b/include/netlink/attr.h
index 69ecb08..0ed3da3 100644
--- a/include/netlink/attr.h
+++ b/include/netlink/attr.h
@@ -124,6 +124,7 @@ extern int nla_put_msecs(struct nl_msg *, int, unsigned long);
extern int nla_put_nested(struct nl_msg *, int, struct nl_msg *);
extern struct nlattr * nla_nest_start(struct nl_msg *, int);
extern int nla_nest_end(struct nl_msg *, struct nlattr *);
+extern void nla_nest_cancel(struct nl_msg *, struct nlattr *);
extern int nla_parse_nested(struct nlattr **, int, struct nlattr *,
struct nla_policy *);
extern int nla_is_nested(struct nlattr *);
diff --git a/lib/attr.c b/lib/attr.c
index 26bece3..2c03fa1 100644
--- a/lib/attr.c
+++ b/lib/attr.c
@@ -820,8 +820,7 @@ int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
* Kernel can't handle empty nested attributes, trim the
* attribute header again
*/
- msg->nm_nlh->nlmsg_len -= NLA_HDRLEN;
- memset(nlmsg_tail(msg->nm_nlh), 0, NLA_HDRLEN);
+ nla_nest_cancel(msg, start);
return 0;
}
@@ -850,6 +849,28 @@ int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
}
/**
+ * Cancel the addition of a nested attribute
+ * @arg msg Netlink message
+ * @arg attr Nested netlink attribute
+ *
+ * Removes any partially added nested Netlink attribute from the message
+ * by resetting the message to the size before the call to nla_nest_start()
+ * and by overwriting any potentially touched message segments with 0.
+ */
+void nla_nest_cancel(struct nl_msg *msg, struct nlattr *attr)
+{
+ ssize_t len;
+
+ len = (void *) nlmsg_tail(msg->nm_nlh) - (void *) attr;
+ if (len < 0)
+ BUG();
+ else if (len > 0) {
+ msg->nm_nlh->nlmsg_len -= len;
+ memset(nlmsg_tail(msg->nm_nlh), 0, len);
+ }
+}
+
+/**
* Create attribute index based on nested attribute
* @arg tb Index array to be filled (maxtype+1 elements).
* @arg maxtype Maximum attribute type expected and accepted.