diff options
author | Thomas Haller <thaller@redhat.com> | 2019-02-15 11:26:03 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2019-02-21 21:02:39 +0100 |
commit | f1d607853a6660218e90c336290d7c2e5453743d (patch) | |
tree | 0da45de58112e3f536796c7851083d30211a4fac | |
parent | f94cef84d1b7efd1b2211d3ed870eabc0193ea6c (diff) | |
download | NetworkManager-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.h | 72 |
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); |