summaryrefslogtreecommitdiffstats
path: root/sysdep/linux/netlink/netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdep/linux/netlink/netlink.c')
-rw-r--r--sysdep/linux/netlink/netlink.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/sysdep/linux/netlink/netlink.c b/sysdep/linux/netlink/netlink.c
index 03d4388..f45fe15 100644
--- a/sysdep/linux/netlink/netlink.c
+++ b/sysdep/linux/netlink/netlink.c
@@ -390,7 +390,6 @@ nl_parse_addr(struct nlmsghdr *h)
else
{
ip_addr netmask = ipa_mkmask(ifa.pxlen);
- ip_addr xbrd;
ifa.prefix = ipa_and(ifa.ip, netmask);
ifa.brd = ipa_or(ifa.ip, ipa_not(netmask));
#ifndef IPV6
@@ -398,6 +397,7 @@ nl_parse_addr(struct nlmsghdr *h)
ifa.opposite = ipa_opposite(ifa.ip, i->ifa_prefixlen);
if ((ifi->flags & IF_BROADCAST) && a[IFA_BROADCAST])
{
+ ip_addr xbrd;
memcpy(&xbrd, RTA_DATA(a[IFA_BROADCAST]), sizeof(xbrd));
ipa_ntoh(xbrd);
if (ipa_equal(xbrd, ifa.prefix) || ipa_equal(xbrd, ifa.brd))
@@ -472,6 +472,9 @@ krt_capable(rte *e)
switch (a->dest)
{
case RTD_ROUTER:
+ if (ipa_has_link_scope(a->gw) && (a->iface == NULL))
+ return 0;
+
case RTD_DEVICE:
case RTD_BLACKHOLE:
case RTD_UNREACHABLE:
@@ -514,6 +517,11 @@ nl_send_route(struct krt_proto *p, rte *e, int new)
case RTD_ROUTER:
r.r.rtm_type = RTN_UNICAST;
nl_add_attr_ipa(&r.h, sizeof(r), RTA_GATEWAY, a->gw);
+
+ /* a->iface != NULL checked in krt_capable() */
+ if (ipa_has_link_scope(a->gw))
+ nl_add_attr_u32(&r.h, sizeof(r), RTA_OIF, a->iface->index);
+
break;
case RTD_DEVICE:
if (!a->iface)
@@ -678,6 +686,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
}
if (a[RTA_GATEWAY])
{
+ struct iface *ifa = if_find_by_index(oif);
neighbor *ng;
ra.dest = RTD_ROUTER;
memcpy(&ra.gw, RTA_DATA(a[RTA_GATEWAY]), sizeof(ra.gw));
@@ -696,15 +705,19 @@ nl_parse_route(struct nlmsghdr *h, int scan)
}
else
{
- /* standard route */
- ng = neigh_find(&p->p, &ra.gw, 0);
+ ng = neigh_find2(&p->p, &ra.gw, ifa, 0);
if (ng && ng->scope)
- ra.iface = ng->iface;
+ {
+ if (ng->iface != ifa)
+ log(L_WARN "KRT: Route with unexpected iface for %I/%d", net->n.prefix, net->n.pxlen);
+ ra.iface = ng->iface;
+ }
else
{
log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", ra.gw, net->n.prefix, net->n.pxlen);
return;
}
+
}
}
else