From: Susant Sahani Date: Wed, 26 Jul 2023 09:44:13 +0000 (+0530) Subject: network: ndisc - drop routes of lifetime 0 X-Git-Tag: v255-rc1~668^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F28496%2Fhead;p=thirdparty%2Fsystemd.git network: ndisc - drop routes of lifetime 0 A Lifetime of 0 indicates that the router is not a default router anymore and associated default route should be discarded from host's routing table. https://datatracker.ietf.org/doc/html/rfc4861 ``` Router Lifetime 16-bit unsigned integer. The lifetime associated with the default router in units of seconds. The field can contain values up to 65535 and receivers should handle any value, while the sending rules in Section 6 limit the lifetime to 9000 seconds. A Lifetime of 0 indicates that the router is not a default router and SHOULD NOT appear on the default router list. The Router Lifetime applies only to the router's usefulness as a default router; it does not apply to information contained in other message fields or options. Options that need time limits for their information include their own lifetime fields. ``` --- diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 61776d3c262..c6ca7f95e2d 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -978,7 +978,7 @@ static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) { } } -static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) { +static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec, const struct in6_addr *router) { bool updated = false; NDiscDNSSL *dnssl; NDiscRDNSS *rdnss; @@ -1002,6 +1002,9 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) { if (route->lifetime_usec >= timestamp_usec) continue; /* the route is still valid */ + if (router && !in6_addr_equal(&route->provider.in6, router)) + continue; + k = route_remove_and_drop(route); if (k < 0) r = log_link_warning_errno(link, k, "Failed to remove outdated SLAAC route, ignoring: %m"); @@ -1014,6 +1017,9 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) { if (address->lifetime_valid_usec >= timestamp_usec) continue; /* the address is still valid */ + if (router && !in6_addr_equal(&address->provider.in6, router)) + continue; + k = address_remove_and_drop(address); if (k < 0) r = log_link_warning_errno(link, k, "Failed to remove outdated SLAAC address, ignoring: %m"); @@ -1023,6 +1029,9 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) { if (rdnss->lifetime_usec >= timestamp_usec) continue; /* the DNS server is still valid */ + if (router && !in6_addr_equal(&rdnss->router, router)) + continue; + free(set_remove(link->ndisc_rdnss, rdnss)); updated = true; } @@ -1031,6 +1040,9 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) { if (dnssl->lifetime_usec >= timestamp_usec) continue; /* the DNS domain is still valid */ + if (router && !in6_addr_equal(&dnssl->router, router)) + continue; + free(set_remove(link->ndisc_dnssl, dnssl)); updated = true; } @@ -1039,6 +1051,9 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) { if (cp->lifetime_usec >= timestamp_usec) continue; /* the captive portal is still valid */ + if (router && !in6_addr_equal(&cp->router, router)) + continue; + ndisc_captive_portal_free(set_remove(link->ndisc_captive_portals, cp)); updated = true; } @@ -1059,7 +1074,7 @@ static int ndisc_expire_handler(sd_event_source *s, uint64_t usec, void *userdat assert_se(sd_event_now(link->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0); - (void) ndisc_drop_outdated(link, now_usec); + (void) ndisc_drop_outdated(link, now_usec, NULL); (void) ndisc_setup_expire(link); return 0; } @@ -1160,6 +1175,7 @@ static int ndisc_start_dhcp6_client(Link *link, sd_ndisc_router *rt) { } static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { + uint16_t router_lifetime_sec; struct in6_addr router; usec_t timestamp_usec; int r; @@ -1192,12 +1208,28 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { log_link_debug(link, "Received RA without timestamp, ignoring."); return 0; } + + r = ndisc_drop_outdated(link, timestamp_usec, NULL); if (r < 0) return r; - r = ndisc_drop_outdated(link, timestamp_usec); + r = sd_ndisc_router_get_lifetime(rt, &router_lifetime_sec); if (r < 0) - return r; + return log_link_warning_errno(link, r, "Failed to get lifetime of RA message: %m"); + + /* https://datatracker.ietf.org/doc/html/rfc4861 + * Router Lifetime: A Lifetime of 0 indicates that the router is not a default router + * and SHOULD NOT appear on the default router list. + */ + if (router_lifetime_sec == 0) { + log_link_debug(link, "Received RA with lifetime = 0, dropping configurations."); + + r = ndisc_drop_outdated(link, USEC_INFINITY, &router); + if (r < 0) + log_link_warning_errno(link, r, "Failed to process RA with zero lifetime, ignoring: %m"); + + return 0; + } r = ndisc_start_dhcp6_client(link, rt); if (r < 0)