diff options
author | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2021-12-27 19:10:35 +0100 |
---|---|---|
committer | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2021-12-27 21:00:04 +0100 |
commit | a39cd2cc0b0c64235457c07e2b618318bbdfcacd (patch) | |
tree | 8406aeb44a408fb4692ebcf5d9d32054d5c54994 /sysdep/bsd | |
parent | b9f38727a7ba7c9c7e383ade80dbf77086dfce05 (diff) |
BSD: Assume onlink flag on ifaces with only host addresses
The BSD kernel does not support the onlink flag and BIRD does not use
direct routes for next hop validation, instead depends on interface
address ranges. We would like to handle PtMP cases with only host
addresses configured, like:
ifconfig wg0 192.168.0.10/32
route add 192.168.0.4 -iface wg0
route add 192.168.0.8 -iface wg0
To accept BIRD routes with onlink next-hop, like:
route 192.168.42.0/24 via 192.168.0.4%wg0 onlink
BIRD would dismiss the route when receiving from the kernel, as the
next-hop 192.168.0.4 is not part of any interface subnet and onlink
flag is not kept by the BSD kernel.
The commit fixes this by assuming that for routes received from the
kernel, any next-hop is onlink on ifaces with only host addresses.
Thanks to Stefan Haller for the original patch.
Diffstat (limited to 'sysdep/bsd')
-rw-r--r-- | sysdep/bsd/krt-sock.c | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index 5c905bc9..521f43f3 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -366,6 +366,30 @@ krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old) } } +/** + * krt_assume_onlink - check if routes on interface are considered onlink + * @iface: The interface of the next hop + * @ipv6: Switch to only consider IPv6 or IPv4 addresses. + * + * The BSD kernel does not support an onlink flag. If the interface has only + * host addresses configured, all routes should be considered as onlink and + * the function returns 1. + */ +static int +krt_assume_onlink(struct iface *iface, int ipv6) +{ + const u8 type = ipv6 ? NET_IP6 : NET_IP4; + + struct ifa *ifa; + WALK_LIST(ifa, iface->addrs) + { + if ((ifa->prefix.type == type) && !(ifa->flags & IA_HOST)) + return 0; + } + + return 1; +} + #define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0) static void @@ -528,15 +552,21 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan) a.dest = RTD_UNICAST; if (flags & RTF_GATEWAY) { - neighbor *ng; a.nh.gw = igate; /* Clean up embedded interface ID returned in link-local address */ if (ipa_is_link_local(a.nh.gw)) _I0(a.nh.gw) = 0xfe800000; - ng = neigh_find(&p->p, a.nh.gw, a.nh.iface, 0); - if (!ng || (ng->scope == SCOPE_HOST)) + /* The BSD kernel does not support an onlink flag. We heuristically + set the onlink flag, if the iface has only host addresses. */ + if (krt_assume_onlink(a.nh.iface, ipv6)) + a.nh.flags |= RNF_ONLINK; + + neighbor *nbr; + nbr = neigh_find(&p->p, a.nh.gw, a.nh.iface, + (a.nh.flags & RNF_ONLINK) ? NEF_ONLINK : 0); + if (!nbr || (nbr->scope == SCOPE_HOST)) { /* Ignore routes with next-hop 127.0.0.1, host routes with such next-hop appear on OpenBSD for address aliases. */ |