]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: ndisc: also introduce timer event source to drop outdated settings
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 3 Oct 2022 15:19:13 +0000 (00:19 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 3 Oct 2022 15:25:14 +0000 (00:25 +0900)
Otherwise, settings based on previously received RA messages will never
removed without receiving a new RA message.

src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-ndisc.c
src/network/networkd-ndisc.h

index 57335216115807dbeec869214c85011354125ab9..69d5eb9d1b9c1868617f6208b92e123cc5b95dd3 100644 (file)
@@ -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");
 
index 362f439940a8f7e24f41b62b01d98117614d31c9..9f1cdca31272a2153b3132d8bd029d848edf0988 100644 (file)
@@ -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;
index 6452010d2d43a15748189093aa169f23146443de..124c7771053217424f69423d034207f566ea100b 100644 (file)
@@ -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;
index bdbe2f41f1d7de8c112fa3ec40234de9bc994c20..b696db9df13471b5cc36b9a923463e466f4b7a63 100644 (file)
@@ -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);