diff options
author | Thomas Haller <thaller@redhat.com> | 2022-08-05 22:17:35 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2022-08-09 08:02:40 +0200 |
commit | 494b3d82c104903167395fa8fe61f7b263f0cc06 (patch) | |
tree | 7a8506603d05225343bd45d4eaba309a1cbed01a | |
parent | 6e7d8f0335e36c0cccb34d915a67532fd9df92ca (diff) | |
download | NetworkManager-494b3d82c104903167395fa8fe61f7b263f0cc06.tar.gz |
platform/netlink: add nlmsg_parse_error() helper
-rw-r--r-- | src/libnm-glib-aux/nm-errno.c | 1 | ||||
-rw-r--r-- | src/libnm-glib-aux/nm-errno.h | 1 | ||||
-rw-r--r-- | src/libnm-platform/nm-netlink.c | 46 | ||||
-rw-r--r-- | src/libnm-platform/nm-netlink.h | 2 |
4 files changed, 50 insertions, 0 deletions
diff --git a/src/libnm-glib-aux/nm-errno.c b/src/libnm-glib-aux/nm-errno.c index 14d93d64c9..b76386a6fe 100644 --- a/src/libnm-glib-aux/nm-errno.c +++ b/src/libnm-glib-aux/nm-errno.c @@ -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"), diff --git a/src/libnm-glib-aux/nm-errno.h b/src/libnm-glib-aux/nm-errno.h index 62c8379f83..f893a528b2 100644 --- a/src/libnm-glib-aux/nm-errno.h +++ b/src/libnm-glib-aux/nm-errno.h @@ -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, diff --git a/src/libnm-platform/nm-netlink.c b/src/libnm-platform/nm-netlink.c index 3d89a4c1d6..36841d5626 100644 --- a/src/libnm-platform/nm-netlink.c +++ b/src/libnm-platform/nm-netlink.c @@ -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) { diff --git a/src/libnm-platform/nm-netlink.h b/src/libnm-platform/nm-netlink.h index 1b4267c517..fd1450cc12 100644 --- a/src/libnm-platform/nm-netlink.h +++ b/src/libnm-platform/nm-netlink.h @@ -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[], |