summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-02-15 11:26:03 +0100
committerThomas Haller <thaller@redhat.com>2019-02-21 21:02:39 +0100
commitf1d607853a6660218e90c336290d7c2e5453743d (patch)
tree0da45de58112e3f536796c7851083d30211a4fac
parentf94cef84d1b7efd1b2211d3ed870eabc0193ea6c (diff)
downloadNetworkManager-f1d607853a6660218e90c336290d7c2e5453743d.tar.gz
platform/netlink: add nla_parse* macros that safely determine the max-type
The common idiom is to stack allocate the tb array. Hence, the maxtype is redundant. Add macros that autodetect the maxtype based on the C type infomation. Also, there is a static assertion that the size of the policy (if provided) matches.
-rw-r--r--src/platform/nm-netlink.h72
1 files changed, 66 insertions, 6 deletions
diff --git a/src/platform/nm-netlink.h b/src/platform/nm-netlink.h
index 1fde9f507a..562af9553c 100644
--- a/src/platform/nm-netlink.h
+++ b/src/platform/nm-netlink.h
@@ -87,6 +87,24 @@ struct nla_policy {
/*****************************************************************************/
+/* static asserts that @tb and @policy are suitable arguments to nla_parse(). */
+#define _nl_static_assert_tb(tb, policy) \
+ G_STMT_START { \
+ \
+ G_STATIC_ASSERT_EXPR (G_N_ELEMENTS (tb) > 0); \
+ \
+ /* we allow @policy to be either NULL or a C array. */ \
+ G_STATIC_ASSERT_EXPR ( sizeof (policy) == sizeof (NULL) \
+ || G_N_ELEMENTS (tb) == (sizeof (policy) / sizeof (struct nla_policy))); \
+ \
+ /* For above check to work, we don't support policy being an array with same size as
+ * sizeof(NULL), otherwise, the compile time check breaks down. */ \
+ G_STATIC_ASSERT_EXPR (sizeof (NULL) != G_N_ELEMENTS (tb) * sizeof (struct nla_policy)); \
+ \
+ } G_STMT_END
+
+/*****************************************************************************/
+
static inline int
nla_attr_size(int payload)
{
@@ -274,16 +292,35 @@ void nla_nest_cancel (struct nl_msg *msg, const struct nlattr *attr);
struct nlattr *nla_nest_start (struct nl_msg *msg, int attrtype);
int nla_nest_end (struct nl_msg *msg, struct nlattr *start);
-int nla_parse (struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
+int nla_parse (struct nlattr *tb[],
+ int maxtype,
+ struct nlattr *head,
+ int len,
const struct nla_policy *policy);
+#define nla_parse_arr(tb, head, len, policy) \
+ ({ \
+ _nl_static_assert_tb ((tb), (policy)); \
+ \
+ nla_parse ((tb), G_N_ELEMENTS (tb) - 1, (head), (len), (policy)); \
+ })
+
static inline int
-nla_parse_nested (struct nlattr *tb[], int maxtype, struct nlattr *nla,
+nla_parse_nested (struct nlattr *tb[],
+ int maxtype,
+ struct nlattr *nla,
const struct nla_policy *policy)
{
return nla_parse (tb, maxtype, nla_data(nla), nla_len(nla), policy);
}
+#define nla_parse_nested_arr(tb, nla, policy) \
+ ({ \
+ _nl_static_assert_tb ((tb), (policy)); \
+ \
+ nla_parse_nested ((tb), G_N_ELEMENTS (tb) - 1, (nla), (policy)); \
+ })
+
/*****************************************************************************/
struct nl_msg *nlmsg_alloc (void);
@@ -396,8 +433,19 @@ nlmsg_find_attr (struct nlmsghdr *nlh, int hdrlen, int attrtype)
attrtype);
}
-int nlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
- int maxtype, const struct nla_policy *policy);
+int nlmsg_parse (struct nlmsghdr *nlh,
+ int hdrlen,
+ struct nlattr *tb[],
+ int maxtype,
+ const struct nla_policy *policy);
+
+#define nlmsg_parse_arr(nlh, hdrlen, tb, policy) \
+ ({ \
+ _nl_static_assert_tb ((tb), (policy)); \
+ G_STATIC_ASSERT_EXPR ((hdrlen) >= 0); \
+ \
+ nlmsg_parse ((nlh), (hdrlen), (tb), G_N_ELEMENTS (tb) - 1, (policy)); \
+ })
struct nlmsghdr *nlmsg_put (struct nl_msg *n, uint32_t pid, uint32_t seq,
int type, int payload, int flags);
@@ -499,8 +547,20 @@ struct nlattr *genlmsg_attrdata (const struct genlmsghdr *gnlh, int hdrlen);
int genlmsg_len (const struct genlmsghdr *gnlh);
int genlmsg_attrlen (const struct genlmsghdr *gnlh, int hdrlen);
int genlmsg_valid_hdr (struct nlmsghdr *nlh, int hdrlen);
-int genlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
- int maxtype, const struct nla_policy *policy);
+
+int genlmsg_parse (struct nlmsghdr *nlh,
+ int hdrlen,
+ struct nlattr *tb[],
+ int maxtype,
+ const struct nla_policy *policy);
+
+#define genlmsg_parse_arr(nlh, hdrlen, tb, policy) \
+ ({ \
+ _nl_static_assert_tb ((tb), (policy)); \
+ G_STATIC_ASSERT_EXPR ((hdrlen) >= 0); \
+ \
+ genlmsg_parse ((nlh), (hdrlen), (tb), G_N_ELEMENTS (tb) - 1, (policy)); \
+ })
int genl_ctrl_resolve (struct nl_sock *sk, const char *name);