diff options
author | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2019-07-15 18:16:55 +0200 |
---|---|---|
committer | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2019-07-15 18:16:55 +0200 |
commit | 2eaf65ec607b68748744fa8e0d596cf1f3ba117a (patch) | |
tree | c644569f741b0813648947c236fc7b973386a0fb /sysdep | |
parent | 8235c4747dcc92de2ea991f78cdf9c6b8fa7f522 (diff) |
Netlink: Fix parsing of multipath routes with MPLS labels
Diffstat (limited to 'sysdep')
-rw-r--r-- | sysdep/linux/netlink.c | 31 |
1 files changed, 16 insertions, 15 deletions
diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index 85067bf5..05328663 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -467,10 +467,21 @@ static inline ip_addr rta_get_via(struct rtattr *a) static u32 rta_mpls_stack[MPLS_MAX_LABEL_STACK]; static inline int rta_get_mpls(struct rtattr *a, u32 *stack) { + if (!a) + return 0; + if (RTA_PAYLOAD(a) % 4) log(L_WARN "KRT: Strange length of received MPLS stack: %u", RTA_PAYLOAD(a)); - return mpls_get(RTA_DATA(a), RTA_PAYLOAD(a) & ~0x3, stack); + int labels = mpls_get(RTA_DATA(a), RTA_PAYLOAD(a) & ~0x3, stack); + + if (labels < 0) + { + log(L_WARN "KRT: Too long MPLS stack received, ignoring"); + labels = 0; + } + + return labels; } #endif @@ -706,7 +717,7 @@ nl_parse_multipath(struct nl_parse_state *s, struct krt_proto *p, struct rtattr rv->gw = IPA_NONE; #ifdef HAVE_MPLS_KERNEL - if (a[RTA_ENCAP_TYPE]) + if (a[RTA_ENCAP] && a[RTA_ENCAP_TYPE]) { if (rta_get_u16(a[RTA_ENCAP_TYPE]) != LWTUNNEL_ENCAP_MPLS) { log(L_WARN "KRT: Unknown encapsulation method %d in multipath", rta_get_u16(a[RTA_ENCAP_TYPE])); @@ -717,7 +728,6 @@ nl_parse_multipath(struct nl_parse_state *s, struct krt_proto *p, struct rtattr nl_attr_len = RTA_PAYLOAD(a[RTA_ENCAP]); nl_parse_attrs(RTA_DATA(a[RTA_ENCAP]), encap_mpls_want, enca, sizeof(enca)); rv->labels = rta_get_mpls(enca[RTA_DST], rv->label); - break; } #endif @@ -1623,7 +1633,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) return; } - ra->nh = *nh; + nexthop_link(ra, nh); break; } @@ -1683,9 +1693,8 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) } #ifdef HAVE_MPLS_KERNEL - int labels = 0; if ((i->rtm_family == AF_MPLS) && a[RTA_NEWDST] && !ra->nh.next) - labels = rta_get_mpls(a[RTA_NEWDST], ra->nh.label); + ra->nh.labels = rta_get_mpls(a[RTA_NEWDST], ra->nh.label); if (a[RTA_ENCAP] && a[RTA_ENCAP_TYPE] && !ra->nh.next) { @@ -1696,7 +1705,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) struct rtattr *enca[BIRD_RTA_MAX]; nl_attr_len = RTA_PAYLOAD(a[RTA_ENCAP]); nl_parse_attrs(RTA_DATA(a[RTA_ENCAP]), encap_mpls_want, enca, sizeof(enca)); - labels = rta_get_mpls(enca[RTA_DST], ra->nh.label); + ra->nh.labels = rta_get_mpls(enca[RTA_DST], ra->nh.label); break; } default: @@ -1704,14 +1713,6 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) break; } } - - if (labels < 0) - { - log(L_WARN "KRT: Too long MPLS stack received, ignoring."); - ra->nh.labels = 0; - } - else - ra->nh.labels = labels; #endif if (i->rtm_scope != def_scope) |