summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authord0u9 <d0u9.su@outlook.com>2018-01-23 14:13:43 +0800
committerd0u9 <d0u9.su@outlook.com>2018-01-24 00:02:55 +0800
commit52057832033ac8f6c6969e4ae3a7e65db1c9f540 (patch)
tree5af32d0dd5a3ca7c8735bf38ebdff4067fef779b
parent4eba9c8f43f9389063fb510f38d3e16ee8f6a715 (diff)
downloadlibnl-52057832033ac8f6c6969e4ae3a7e65db1c9f540.tar.gz
Fix for cgroup filter addition problem.
Currently, due to the incomplete netlink datagram sent by libnl, cgroup filter addition is not fully functional. The datagram generated by `tc` command includes an empty attribute section, which is stripped off in the libnl counterpart. In this commit, a new `interface nla_nest_end_keep_empty()` is added. This function closes attribute without stripping off empty attribute.
-rw-r--r--include/netlink/attr.h1
-rw-r--r--lib/attr.c49
-rw-r--r--lib/route/tc.c5
-rw-r--r--libnl-3.sym1
4 files changed, 55 insertions, 1 deletions
diff --git a/include/netlink/attr.h b/include/netlink/attr.h
index da9eee4e..e47aa5d5 100644
--- a/include/netlink/attr.h
+++ b/include/netlink/attr.h
@@ -143,6 +143,7 @@ extern int nla_put_nested(struct nl_msg *, int,
const struct nl_msg *);
extern struct nlattr * nla_nest_start(struct nl_msg *, int);
extern int nla_nest_end(struct nl_msg *, struct nlattr *);
+extern int nla_nest_end_keep_empty(struct nl_msg *, struct nlattr *);
extern void nla_nest_cancel(struct nl_msg *, const struct nlattr *);
extern int nla_parse_nested(struct nlattr **, int, struct nlattr *,
const struct nla_policy *);
diff --git a/lib/attr.c b/lib/attr.c
index b81e550b..d90fa479 100644
--- a/lib/attr.c
+++ b/lib/attr.c
@@ -962,6 +962,55 @@ int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
}
/**
+ * Finalize nesting of attributes without stripping off empty attributes.
+ * @arg msg Netlink message.
+ * @arg start Container attribute as returned from nla_nest_start().
+ *
+ * Corrects the container attribute header to include the appeneded attributes.
+ * Keep empty attribute if NO actual attribute payload exists.
+ *
+ * @return 0 on success or a negative error code.
+ */
+int nla_nest_end_keep_empty(struct nl_msg *msg, struct nlattr *start)
+{
+ size_t pad, len;
+
+ len = (void *) nlmsg_tail(msg->nm_nlh) - (void *) start;
+
+ if (len > USHRT_MAX) {
+ /*
+ * Max nlattr size is exceeded, trim the attribute header again
+ */
+ nla_nest_cancel(msg, start);
+
+ /* Return error only if nlattr size was exceeded */
+ return -NLE_ATTRSIZE;
+ }
+
+ start->nla_len = len;
+
+ pad = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) - msg->nm_nlh->nlmsg_len;
+ if (pad > 0) {
+ /*
+ * Data inside attribute does not end at a alignment boundry.
+ * Pad accordingly and accoun for the additional space in
+ * the message. nlmsg_reserve() may never fail in this situation,
+ * the allocate message buffer must be a multiple of NLMSG_ALIGNTO.
+ */
+ if (!nlmsg_reserve(msg, pad, 0))
+ BUG();
+
+ NL_DBG(2, "msg %p: attr <%p> %d: added %zu bytes of padding\n",
+ msg, start, start->nla_type, pad);
+ }
+
+ NL_DBG(2, "msg %p: attr <%p> %d: closing nesting, len=%u\n",
+ msg, start, start->nla_type, start->nla_len);
+
+ return 0;
+}
+
+/**
* Cancel the addition of a nested attribute
* @arg msg Netlink message
* @arg attr Nested netlink attribute
diff --git a/lib/route/tc.c b/lib/route/tc.c
index 5dc43e17..62efd354 100644
--- a/lib/route/tc.c
+++ b/lib/route/tc.c
@@ -226,7 +226,10 @@ int rtnl_tc_msg_build(struct rtnl_tc *tc, int type, int flags,
if ((err = ops->to_msg_fill(tc, data, msg)) < 0)
goto nla_put_failure;
- nla_nest_end(msg, opts);
+ if (strcmp("cgroup", tc->tc_kind))
+ nla_nest_end(msg, opts);
+ else
+ nla_nest_end_keep_empty(msg, opts);
} else if ((err = ops->to_msg_fill_raw(tc, data, msg)) < 0)
goto nla_put_failure;
}
diff --git a/libnl-3.sym b/libnl-3.sym
index 4546a40c..42b38b7b 100644
--- a/libnl-3.sym
+++ b/libnl-3.sym
@@ -260,6 +260,7 @@ global:
nla_memcpy;
nla_nest_cancel;
nla_nest_end;
+ nla_nest_end_keep_empty;
nla_nest_start;
nla_next;
nla_ok;