mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-02 11:58:06 +02:00
platform/netlink: add nlmsg_parse_error() helper
This commit is contained in:
parent
6e7d8f0335
commit
494b3d82c1
4 changed files with 50 additions and 0 deletions
|
|
@ -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"),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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[],
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue