]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: ndisc: drop addresses and friends when RA with zero lifetime is received
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 3 Oct 2022 02:54:20 +0000 (11:54 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 3 Oct 2022 17:52:46 +0000 (02:52 +0900)
Routers may send options with zero lifetime if previously announced
information is outdated. Hence, if we receive such messages, then we
need to drop relevant addresses or friends.

See e.g. https://www.rfc-editor.org/rfc/rfc4861#section-12.

Follow-up for 2ccada8dc4a3571468a335808fd6fe49b8c6c6dd.

src/network/networkd-address.c
src/network/networkd-ndisc.c
src/network/networkd-route.c

index 60d3c6286ed800b42b25faa863f6628d0607d85a..259cd312c9925b423f66dcd75b657b60f1b86fd7 100644 (file)
@@ -1154,7 +1154,7 @@ int link_request_address(
                 address_netlink_handler_t netlink_handler,
                 Request **ret) {
 
-        Address *acquired, *existing;
+        Address *acquired, *existing = NULL;
         int r;
 
         assert(link);
@@ -1187,7 +1187,13 @@ int link_request_address(
                 address_set_broadcast(address, link);
         }
 
-        if (address_get(link, address, &existing) < 0) {
+        (void) address_get(link, address, &existing);
+
+        if (address->lifetime_valid_usec == 0)
+                /* The requested address is outdated. Let's remove it. */
+                return address_remove_and_drop(existing);
+
+        if (!existing) {
                 _cleanup_(address_freep) Address *tmp = NULL;
 
                 if (consume_object)
index 124c7771053217424f69423d034207f566ea100b..f2057a2d9802731124b00b2f960ad7562859cbe8 100644 (file)
@@ -235,9 +235,6 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
         if (r < 0)
                 return log_link_error_errno(link, r, "Failed to get gateway lifetime from RA: %m");
 
-        if (lifetime_sec == 0) /* not a default router */
-                return 0;
-
         r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
         if (r < 0)
                 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
@@ -351,11 +348,6 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
         if (r < 0)
                 return log_link_error_errno(link, r, "Failed to get prefix valid lifetime: %m");
 
-        if (lifetime_valid_sec == 0) {
-                log_link_debug(link, "Ignoring prefix as its valid lifetime is zero.");
-                return 0;
-        }
-
         r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred_sec);
         if (r < 0)
                 return log_link_error_errno(link, r, "Failed to get prefix preferred lifetime: %m");
@@ -412,9 +404,6 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
         if (r < 0)
                 return log_link_error_errno(link, r, "Failed to get prefix lifetime: %m");
 
-        if (lifetime_sec == 0)
-                return 0;
-
         r = sd_ndisc_router_get_timestamp(rt, CLOCK_BOOTTIME, &timestamp_usec);
         if (r < 0)
                 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
@@ -515,9 +504,6 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
         if (r < 0)
                 return log_link_error_errno(link, r, "Failed to get route lifetime from RA: %m");
 
-        if (lifetime_sec == 0)
-                return 0;
-
         r = sd_ndisc_router_route_get_address(rt, &dst);
         if (r < 0)
                 return log_link_error_errno(link, r, "Failed to get route destination address: %m");
@@ -623,9 +609,6 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
         if (r < 0)
                 return log_link_error_errno(link, r, "Failed to get RDNSS lifetime: %m");
 
-        if (lifetime_sec == 0)
-                return 0;
-
         lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec);
 
         n = sd_ndisc_router_rdnss_get_addresses(rt, &a);
@@ -643,6 +626,13 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
                         .address = a[j],
                 };
 
+                if (lifetime_usec == 0) {
+                        /* The entry is outdated. */
+                        free(set_remove(link->ndisc_rdnss, &d));
+                        updated = true;
+                        continue;
+                }
+
                 rdnss = set_get(link->ndisc_rdnss, &d);
                 if (rdnss) {
                         rdnss->router = router;
@@ -716,9 +706,6 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
         if (r < 0)
                 return log_link_error_errno(link, r, "Failed to get DNSSL lifetime: %m");
 
-        if (lifetime_sec == 0)
-                return 0;
-
         lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec);
 
         r = sd_ndisc_router_dnssl_get_domains(rt, &l);
@@ -741,6 +728,13 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
 
                 strcpy(NDISC_DNSSL_DOMAIN(s), *j);
 
+                if (lifetime_usec == 0) {
+                        /* The entry is outdated. */
+                        free(set_remove(link->ndisc_dnssl, s));
+                        updated = true;
+                        continue;
+                }
+
                 dnssl = set_get(link->ndisc_dnssl, s);
                 if (dnssl) {
                         dnssl->router = router;
index 2b17959ca2ebb6bba3c64b8fba715d3e9c729e9b..514845f7c5c70778cf64de747c66dbd19d8510ba 100644 (file)
@@ -1426,7 +1426,7 @@ int link_request_route(
                 route_netlink_handler_t netlink_handler,
                 Request **ret) {
 
-        Route *existing;
+        Route *existing = NULL;
         int r;
 
         assert(link);
@@ -1435,7 +1435,13 @@ int link_request_route(
         assert(route->source != NETWORK_CONFIG_SOURCE_FOREIGN);
         assert(!route_needs_convert(route));
 
-        if (route_get(link->manager, link, route, &existing) < 0) {
+        (void) route_get(link->manager, link, route, &existing);
+
+        if (route->lifetime_usec == 0)
+                /* The requested route is outdated. Let's remove it. */
+                return route_remove_and_drop(existing);
+
+        if (!existing) {
                 _cleanup_(route_freep) Route *tmp = NULL;
 
                 if (consume_object)