summaryrefslogtreecommitdiff
path: root/sysdep/linux
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2019-07-15 18:16:55 +0200
committerOndrej Zajicek (work) <santiago@crfreenet.org>2019-07-15 18:16:55 +0200
commit2eaf65ec607b68748744fa8e0d596cf1f3ba117a (patch)
treec644569f741b0813648947c236fc7b973386a0fb /sysdep/linux
parent8235c4747dcc92de2ea991f78cdf9c6b8fa7f522 (diff)
Netlink: Fix parsing of multipath routes with MPLS labels
Diffstat (limited to 'sysdep/linux')
-rw-r--r--sysdep/linux/netlink.c31
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)