From 0022a8212b908a1e2f4a0fc522d097bb6a61ba91 Mon Sep 17 00:00:00 2001 From: y5c4l3 Date: Sat, 14 Sep 2024 04:06:56 +0800 Subject: [PATCH] [ipv6] Use IPv6 fallback route when scope matching fails When routing to an IPv6 destination, the lookup process ignores routes that are out of scope. This means any global unicast address is unreachable if the link only advertises a ULA prefix, which could be unwanted when subsequent hops implement address translations, like NPTv6. This patch implements fallback routing with best efforts, preferring the largest IPv6 route scope which is iterated in the first place. Signed-off-by: y5c4l3 --- src/net/ipv6.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/net/ipv6.c b/src/net/ipv6.c index 8ee0804d3..ef61a8b47 100644 --- a/src/net/ipv6.c +++ b/src/net/ipv6.c @@ -308,6 +308,7 @@ struct ipv6_miniroute * ipv6_route ( unsigned int scope_id, struct in6_addr **dest ) { struct ipv6_miniroute *miniroute; struct ipv6_miniroute *chosen = NULL; + struct ipv6_miniroute *fallback = NULL; unsigned int best = 0; unsigned int match_len; unsigned int score; @@ -327,6 +328,13 @@ struct ipv6_miniroute * ipv6_route ( unsigned int scope_id, if ( ! ( miniroute->flags & IPV6_HAS_ADDRESS ) ) continue; + /* Choose a fallback route acting as default gateway. + * Prefer the route with the largest scope that comes + * first. + */ + if ( ! fallback || ( miniroute->scope > fallback->scope ) ) + fallback = miniroute; + /* Skip entries with a non-matching scope ID, if * destination specifies a scope ID. */ @@ -364,6 +372,12 @@ struct ipv6_miniroute * ipv6_route ( unsigned int scope_id, } } + /* If no route scope is matched, use the fallback route to + * show best efforts. + */ + if ( ! chosen ) + chosen = fallback; + /* Return chosen route, if any */ if ( chosen ) { if ( ! IN6_IS_ADDR_MULTICAST ( *dest ) )