From: Yu Watanabe Date: Mon, 3 Oct 2022 15:19:13 +0000 (+0900) Subject: network: ndisc: also introduce timer event source to drop outdated settings X-Git-Tag: v252-rc1~16^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=773024685b37170395a11716f8e4ad99d3580455;p=thirdparty%2Fsystemd.git network: ndisc: also introduce timer event source to drop outdated settings Otherwise, settings based on previously received RA messages will never removed without receiving a new RA message. --- diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 57335216115..69d5eb9d1b9 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -332,7 +332,7 @@ int link_stop_engines(Link *link, bool may_keep_dhcp) { if (k < 0) r = log_link_warning_errno(link, k, "Could not remove DHCPv6 PD addresses and routes: %m"); - k = sd_ndisc_stop(link->ndisc); + k = ndisc_stop(link); if (k < 0) r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Discovery: %m"); diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 362f439940a..9f1cdca3127 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -147,6 +147,7 @@ typedef struct Link { sd_dhcp_server *dhcp_server; sd_ndisc *ndisc; + sd_event_source *ndisc_expire; Set *ndisc_rdnss; Set *ndisc_dnssl; unsigned ndisc_messages; diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 6452010d2d4..124c7771053 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -10,6 +10,7 @@ #include "sd-ndisc.h" +#include "event-util.h" #include "missing_network.h" #include "networkd-address-generation.h" #include "networkd-address.h" @@ -874,6 +875,69 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) { return r; } +static int ndisc_setup_expire(Link *link); + +static int ndisc_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) { + Link *link = ASSERT_PTR(userdata); + usec_t now_usec; + + assert(link->manager); + + assert_se(sd_event_now(link->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0); + + (void) ndisc_drop_outdated(link, now_usec); + (void) ndisc_setup_expire(link); + return 0; +} + +static int ndisc_setup_expire(Link *link) { + usec_t lifetime_usec = USEC_INFINITY; + NDiscDNSSL *dnssl; + NDiscRDNSS *rdnss; + Address *address; + Route *route; + int r; + + assert(link); + assert(link->manager); + + SET_FOREACH(route, link->routes) { + if (route->source != NETWORK_CONFIG_SOURCE_NDISC) + continue; + + if (!route_exists(route)) + continue; + + lifetime_usec = MIN(lifetime_usec, route->lifetime_usec); + } + + SET_FOREACH(address, link->addresses) { + if (address->source != NETWORK_CONFIG_SOURCE_NDISC) + continue; + + if (!address_exists(address)) + continue; + + lifetime_usec = MIN(lifetime_usec, address->lifetime_valid_usec); + } + + SET_FOREACH(rdnss, link->ndisc_rdnss) + lifetime_usec = MIN(lifetime_usec, rdnss->lifetime_usec); + + SET_FOREACH(dnssl, link->ndisc_dnssl) + lifetime_usec = MIN(lifetime_usec, dnssl->lifetime_usec); + + if (lifetime_usec == USEC_INFINITY) + return 0; + + r = event_reset_time(link->manager->event, &link->ndisc_expire, CLOCK_BOOTTIME, + lifetime_usec, 0, ndisc_expire_handler, link, 0, "ndisc-expiration", true); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to update expiration timer for ndisc: %m"); + + return 0; +} + static int ndisc_start_dhcp6_client(Link *link, sd_ndisc_router *rt) { int r; @@ -961,6 +1025,10 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { if (r < 0) return r; + r = ndisc_setup_expire(link); + if (r < 0) + return r; + if (link->ndisc_messages == 0) link->ndisc_configured = true; else @@ -1101,6 +1169,15 @@ int link_request_ndisc(Link *link) { return 0; } +int ndisc_stop(Link *link) { + assert(link); + + link->ndisc_expire = sd_event_source_disable_unref(link->ndisc_expire); + + return sd_ndisc_stop(link->ndisc); +} + + void ndisc_vacuum(Link *link) { NDiscRDNSS *r; NDiscDNSSL *d; diff --git a/src/network/networkd-ndisc.h b/src/network/networkd-ndisc.h index bdbe2f41f1d..b696db9df13 100644 --- a/src/network/networkd-ndisc.h +++ b/src/network/networkd-ndisc.h @@ -40,6 +40,7 @@ bool link_ipv6_accept_ra_enabled(Link *link); void network_adjust_ipv6_accept_ra(Network *network); int ndisc_start(Link *link); +int ndisc_stop(Link *link); void ndisc_vacuum(Link *link); void ndisc_flush(Link *link);