[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 <y5c4l3@proton.me>
pull/1304/head
y5c4l3 2024-09-14 04:06:56 +08:00
parent c85ad12468
commit 0022a8212b
No known key found for this signature in database
GPG Key ID: 8500E37BDE22F379
1 changed files with 14 additions and 0 deletions

View File

@ -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 ) )