platform/netlink: add nlmsg_parse_error() helper

This commit is contained in:
Thomas Haller 2022-08-05 22:17:35 +02:00
parent 6e7d8f0335
commit 494b3d82c1
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
4 changed files with 50 additions and 0 deletions

View file

@ -28,6 +28,7 @@ static NM_UTILS_LOOKUP_STR_DEFINE(
NM_UTILS_LOOKUP_STR_ITEM(NME_NL_ATTRSIZE, "NME_NL_ATTRSIZE"),
NM_UTILS_LOOKUP_STR_ITEM(NME_NL_BAD_SOCK, "NME_NL_BAD_SOCK"),
NM_UTILS_LOOKUP_STR_ITEM(NME_NL_DUMP_INTR, "NME_NL_DUMP_INTR"),
NM_UTILS_LOOKUP_STR_ITEM(NME_NL_MSG_INVAL, "NME_NL_MSG_INVAL"),
NM_UTILS_LOOKUP_STR_ITEM(NME_NL_MSG_OVERFLOW, "NME_NL_MSG_OVERFLOW"),
NM_UTILS_LOOKUP_STR_ITEM(NME_NL_MSG_TOOSHORT, "NME_NL_MSG_TOOSHORT"),
NM_UTILS_LOOKUP_STR_ITEM(NME_NL_MSG_TRUNC, "NME_NL_MSG_TRUNC"),

View file

@ -39,6 +39,7 @@ enum _NMErrno {
/* netlink errors. */
NME_NL_SEQ_MISMATCH,
NME_NL_MSG_INVAL,
NME_NL_MSG_TRUNC,
NME_NL_MSG_TOOSHORT,
NME_NL_DUMP_INTR,

View file

@ -291,6 +291,52 @@ nlmsg_reserve(struct nl_msg *n, uint32_t len, uint32_t pad)
/*****************************************************************************/
int
nlmsg_parse_error(const struct nlmsghdr *nlh, const char **out_extack_msg)
{
const struct nlmsgerr *e;
nm_assert(nlh);
NM_SET_OUT(out_extack_msg, NULL);
if (nlh->nlmsg_type != NLMSG_ERROR)
return -NME_NL_MSG_INVAL;
if (nlh->nlmsg_len < nlmsg_size(sizeof(struct nlmsgerr))) {
/* Truncated error message, the default action
* is to stop parsing. The user may overrule
* this action by returning NL_SKIP or
* NL_PROCEED (dangerous) */
return -NME_NL_MSG_TRUNC;
}
e = nlmsg_data(nlh);
if (!e->error)
return 0;
if (NM_FLAGS_HAS(nlh->nlmsg_flags, NLM_F_ACK_TLVS) && out_extack_msg
&& nlh->nlmsg_len >= sizeof(*e) + e->msg.nlmsg_len) {
static const struct nla_policy policy[] = {
[NLMSGERR_ATTR_MSG] = {.type = NLA_STRING},
[NLMSGERR_ATTR_OFFS] = {.type = NLA_U32},
};
struct nlattr *tb[G_N_ELEMENTS(policy)];
struct nlattr *tlvs;
tlvs = (struct nlattr *) ((char *) e + sizeof(*e) + e->msg.nlmsg_len - NLMSG_HDRLEN);
if (nla_parse_arr(tb, tlvs, nlh->nlmsg_len - sizeof(*e) - e->msg.nlmsg_len, policy) >= 0) {
if (tb[NLMSGERR_ATTR_MSG])
*out_extack_msg = nla_get_string(tb[NLMSGERR_ATTR_MSG]);
}
}
return -nm_errno_from_native(e->error);
}
/*****************************************************************************/
struct nlattr *
nla_reserve(struct nl_msg *msg, int attrtype, int attrlen)
{

View file

@ -497,6 +497,8 @@ nlmsg_find_attr(struct nlmsghdr *nlh, int hdrlen, int attrtype)
return nla_find(nlmsg_attrdata(nlh, hdrlen), nlmsg_attrlen(nlh, hdrlen), attrtype);
}
int nlmsg_parse_error(const struct nlmsghdr *nlh, const char **out_extack_msg);
int nlmsg_parse(const struct nlmsghdr *nlh,
int hdrlen,
struct nlattr *tb[],