mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-05 11:48:50 +00:00
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 <sworley@cumulusnetworks.com>
This commit is contained in:
parent
dfff60ed31
commit
4cebb2b6f6
@ -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);
|
||||
|
||||
memset(tb, 0, sizeof(tb));
|
||||
netlink_parse_nlattr(tb, NLMSGERR_ATTR_MAX, NL_RTA(h), hlen);
|
||||
len = (uint32_t)(NLMSG_PAYLOAD(h, sizeof(struct nlmsgerr)) - inner_len);
|
||||
|
||||
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");
|
||||
|
Loading…
Reference in New Issue
Block a user