From e0ed978e753c57b65b89e860b49fd29acb0b43ad Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Thu, 12 Dec 2024 04:04:07 +0100 Subject: [PATCH] Netlink: Handle onlink flag on BSD-Netlink MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On BSD, the onlink flag is not tracked or reported by kernel. We are using an heuristic that assigns the onlink flag to routes scanned from the kernel. We should use the same heuristic even in BSD-Netlink case, as the onlink flag is not reported here too. Thanks to Björn König for the original patch. --- sysdep/bsd/krt-sock.c | 24 ------------------------ sysdep/cf/README | 1 + sysdep/cf/bsd-netlink.h | 1 + sysdep/cf/bsd.h | 1 + sysdep/linux/netlink.c | 10 ++++++++++ sysdep/unix/krt.c | 24 ++++++++++++++++++++++++ sysdep/unix/krt.h | 1 + 7 files changed, 38 insertions(+), 24 deletions(-) diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index d13e20a3..e8e555af 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -394,30 +394,6 @@ krt_replace_rte(struct krt_proto *p, net *n UNUSED, 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 diff --git a/sysdep/cf/README b/sysdep/cf/README index af65aaec..cdaf5da1 100644 --- a/sysdep/cf/README +++ b/sysdep/cf/README @@ -5,6 +5,7 @@ CONFIG_AUTO_ROUTES Device routes are added automagically by the kernel CONFIG_SELF_CONSCIOUS We're able to recognize whether route was installed by us CONFIG_MULTIPLE_TABLES The kernel supports multiple routing tables CONFIG_SINGLE_ROUTE There is only one route per network +CONFIG_ASSUME_ONLINK Assume ONLINK flag on scanned routes based on a heuristic CONFIG_MC_PROPER_SRC Multicast packets have source address according to socket saddr field CONFIG_SKIP_MC_BIND Don't call bind on multicast socket (def for *BSD) diff --git a/sysdep/cf/bsd-netlink.h b/sysdep/cf/bsd-netlink.h index 69297867..a65106a3 100644 --- a/sysdep/cf/bsd-netlink.h +++ b/sysdep/cf/bsd-netlink.h @@ -10,6 +10,7 @@ #define CONFIG_SELF_CONSCIOUS #define CONFIG_MULTIPLE_TABLES #define CONFIG_SINGLE_ROUTE +#define CONFIG_ASSUME_ONLINK #define CONFIG_SKIP_MC_BIND #define CONFIG_NO_IFACE_BIND diff --git a/sysdep/cf/bsd.h b/sysdep/cf/bsd.h index 22c54277..56ba0a1a 100644 --- a/sysdep/cf/bsd.h +++ b/sysdep/cf/bsd.h @@ -10,6 +10,7 @@ #define CONFIG_SELF_CONSCIOUS #define CONFIG_MULTIPLE_TABLES #define CONFIG_SINGLE_ROUTE +#define CONFIG_ASSUME_ONLINK #define CONFIG_SKIP_MC_BIND #define CONFIG_NO_IFACE_BIND diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index 533cc268..299f132f 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -788,6 +788,11 @@ nl_parse_multipath(struct nl_parse_state *s, struct krt_proto *p, const net_addr if (ipa_nonzero(rv->gw)) { +#ifdef CONFIG_ASSUME_ONLINK + if (krt_assume_onlink(rv->iface, ipa_is_ip6(rv->gw))) + rv->flags |= RNF_ONLINK; +#endif + neighbor *nbr; nbr = neigh_find(&p->p, rv->gw, rv->iface, (rv->flags & RNF_ONLINK) ? NEF_ONLINK : 0); @@ -1739,6 +1744,11 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) if ((i->rtm_family == AF_INET6) && ipa_in_netX(ra->nh.gw, (net_addr *) &sit)) return; +#ifdef CONFIG_ASSUME_ONLINK + if (krt_assume_onlink(ra->nh.iface, ipa_is_ip6(ra->nh.gw))) + ra->nh.flags |= RNF_ONLINK; +#endif + neighbor *nbr; nbr = neigh_find(&p->p, ra->nh.gw, ra->nh.iface, (ra->nh.flags & RNF_ONLINK) ? NEF_ONLINK : 0); diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index 51d0718c..5baaf18b 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -909,6 +909,30 @@ krt_scan_timer_kick(struct krt_proto *p) tm_start(p->scan_timer, 0); } +/** + * 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. This is used when CONFIG_ASSUME_ONLINK is set. + */ +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; +} + /* * Updates diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h index e25f0b12..2b1dfa96 100644 --- a/sysdep/unix/krt.h +++ b/sysdep/unix/krt.h @@ -83,6 +83,7 @@ void kif_request_scan(void); void krt_use_shared_scan(void); void krt_got_route(struct krt_proto *p, struct rte *e, s8 src); void krt_got_route_async(struct krt_proto *p, struct rte *e, int new, s8 src); +int krt_assume_onlink(struct iface *iface, int ipv6); static inline int krt_get_sync_error(struct krt_proto *p, struct rte *e)