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.
This commit is contained in:
Thomas Haller 2019-02-15 11:26:03 +01:00
parent 6245569c6d
commit cf22d28c2e

View file

@ -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);