]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: unset Link.ndisc_configured only when a new address or route is requested
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 30 Nov 2022 02:10:21 +0000 (11:10 +0900)
committerLuca Boccassi <luca.boccassi@gmail.com>
Thu, 1 Dec 2022 22:15:09 +0000 (23:15 +0100)
This fixes an issue introduced by af2aea8bb64b0dc42ecbe5549216eb567681a803.

When an outdated address or route is passed to link_request_address()/route(),
then they return 0 and the address or route will not be assigned. Such
situation can happen when we receive RA with zero lifetime. In that
case, we should not unset Link.ndisc_configured flag, otherwise even
no new address nor route will assigned, the interface will enter to the
configuring state, and unnecessary DBus property change is emit and the state
file will be updated. That makes resolved or timesyncd triggered to
reconfigure the interface.

Fixes #25456.

src/network/networkd-ndisc.c

index 6ee098a0154d210794d9e2f72588429ed6d9ff86..c7ed5fcfe1a2b5da6898e7386565ed9e4e63c3d5 100644 (file)
@@ -168,6 +168,7 @@ static void ndisc_set_route_priority(Link *link, Route *route) {
 static int ndisc_request_route(Route *in, Link *link, sd_ndisc_router *rt) {
         _cleanup_(route_freep) Route *route = in;
         struct in6_addr router;
+        bool is_new;
         int r;
 
         assert(route);
@@ -186,11 +187,16 @@ static int ndisc_request_route(Route *in, Link *link, sd_ndisc_router *rt) {
         if (!route->protocol_set)
                 route->protocol = RTPROT_RA;
 
-        if (route_get(NULL, link, route, NULL) < 0)
+        is_new = route_get(NULL, link, route, NULL) < 0;
+
+        r = link_request_route(link, TAKE_PTR(route), true, &link->ndisc_messages,
+                               ndisc_route_handler, NULL);
+        if (r < 0)
+                return r;
+        if (r > 0 && is_new)
                 link->ndisc_configured = false;
 
-        return link_request_route(link, TAKE_PTR(route), true, &link->ndisc_messages,
-                                  ndisc_route_handler, NULL);
+        return 0;
 }
 
 static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
@@ -212,6 +218,7 @@ static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Reques
 static int ndisc_request_address(Address *in, Link *link, sd_ndisc_router *rt) {
         _cleanup_(address_freep) Address *address = in;
         struct in6_addr router;
+        bool is_new;
         int r;
 
         assert(address);
@@ -229,11 +236,16 @@ static int ndisc_request_address(Address *in, Link *link, sd_ndisc_router *rt) {
         if (r < 0)
                 return r;
 
-        if (address_get(link, address, NULL) < 0)
+        is_new = address_get(link, address, NULL) < 0;
+
+        r = link_request_address(link, TAKE_PTR(address), true, &link->ndisc_messages,
+                                 ndisc_address_handler, NULL);
+        if (r < 0)
+                return r;
+        if (r > 0 && is_new)
                 link->ndisc_configured = false;
 
-        return link_request_address(link, TAKE_PTR(address), true, &link->ndisc_messages,
-                                    ndisc_address_handler, NULL);
+        return 0;
 }
 
 static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {