From: Stephen Worley Date: Tue, 26 Mar 2019 05:03:06 +0000 (-0400) Subject: zebra: Fix extended ack error message parsing X-Git-Tag: 7.1_pulled~134^2 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=4cebb2b6f66466e916de9c5171ce13cb6dbb3447;p=mirror%2Ffrr.git zebra: Fix extended ack error message parsing Fix the macros for reading NLA attribute info from an extended error ack. We were processing the data using route attributes (rtattr) which is identical in size to nlattr but probably should not be used. Further, we were incorrectly calculating the length of the inner netlink message that cause the error. We have to read passed that in order to access all the nlattr's. Signed-off-by: Stephen Worley --- diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index c5fbfd4481..fe37a33358 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -606,50 +606,56 @@ const char *nl_rttype_to_str(uint8_t rttype) return lookup_msg(rttype_str, rttype, ""); } -#define NL_OK(nla, len) \ +#define NLA_OK(nla, len) \ ((len) >= (int)sizeof(struct nlattr) \ && (nla)->nla_len >= sizeof(struct nlattr) \ && (nla)->nla_len <= (len)) -#define NL_NEXT(nla, attrlen) \ - ((attrlen) -= RTA_ALIGN((nla)->nla_len), \ - (struct nlattr *)(((char *)(nla)) + RTA_ALIGN((nla)->nla_len))) -#define NL_RTA(r) \ - ((struct nlattr *)(((char *)(r)) \ - + NLMSG_ALIGN(sizeof(struct nlmsgerr)))) +#define NLA_NEXT(nla, attrlen) \ + ((attrlen) -= NLA_ALIGN((nla)->nla_len), \ + (struct nlattr *)(((char *)(nla)) + NLA_ALIGN((nla)->nla_len))) +#define NLA_LENGTH(len) (NLA_ALIGN(sizeof(struct nlattr)) + (len)) +#define NLA_DATA(nla) ((struct nlattr *)(((char *)(nla)) + NLA_LENGTH(0))) + +#define ERR_NLA(err, inner_len) \ + ((struct nlattr *)(((char *)(err)) \ + + NLMSG_ALIGN(sizeof(struct nlmsgerr)) \ + + NLMSG_ALIGN((inner_len)))) static void netlink_parse_nlattr(struct nlattr **tb, int max, struct nlattr *nla, int len) { - while (NL_OK(nla, len)) { + while (NLA_OK(nla, len)) { if (nla->nla_type <= max) tb[nla->nla_type] = nla; - nla = NL_NEXT(nla, len); + nla = NLA_NEXT(nla, len); } } static void netlink_parse_extended_ack(struct nlmsghdr *h) { - struct nlattr *tb[NLMSGERR_ATTR_MAX + 1]; - const struct nlmsgerr *err = - (const struct nlmsgerr *)((uint8_t *)h - + NLMSG_ALIGN( - sizeof(struct nlmsghdr))); + struct nlattr *tb[NLMSGERR_ATTR_MAX + 1] = {}; + const struct nlmsgerr *err = (const struct nlmsgerr *)NLMSG_DATA(h); const struct nlmsghdr *err_nlh = NULL; - uint32_t hlen = sizeof(*err); + /* Length not including nlmsghdr */ + uint32_t len = 0; + /* Inner error netlink message length */ + uint32_t inner_len = 0; const char *msg = NULL; uint32_t off = 0; if (!(h->nlmsg_flags & NLM_F_CAPPED)) - hlen += h->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr)); + inner_len = (uint32_t)NLMSG_PAYLOAD(&err->msg, 0); + + len = (uint32_t)(NLMSG_PAYLOAD(h, sizeof(struct nlmsgerr)) - inner_len); - memset(tb, 0, sizeof(tb)); - netlink_parse_nlattr(tb, NLMSGERR_ATTR_MAX, NL_RTA(h), hlen); + netlink_parse_nlattr(tb, NLMSGERR_ATTR_MAX, ERR_NLA(err, inner_len), + len); if (tb[NLMSGERR_ATTR_MSG]) - msg = (const char *)RTA_DATA(tb[NLMSGERR_ATTR_MSG]); + msg = (const char *)NLA_DATA(tb[NLMSGERR_ATTR_MSG]); if (tb[NLMSGERR_ATTR_OFFS]) { - off = *(uint32_t *)RTA_DATA(tb[NLMSGERR_ATTR_OFFS]); + off = *(uint32_t *)NLA_DATA(tb[NLMSGERR_ATTR_OFFS]); if (off > h->nlmsg_len) { zlog_err("Invalid offset for NLMSGERR_ATTR_OFFS");