]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/address: introduce address_remove_and_cancel() 30697/head
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 2 Jan 2024 19:40:29 +0000 (04:40 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 2 Jan 2024 19:43:34 +0000 (04:43 +0900)
Then, replace address_remove_and_drop() with it.

If an address is requested, and the request is already called,
we may not received its reply and notification from the kernel, and
the corresponding address object may not be remmbered. Even in such
case, we need to remove the address, otherwise the address will come
later after the function called.

src/network/networkd-address.c
src/network/networkd-address.h
src/network/networkd-dhcp-prefix-delegation.c
src/network/networkd-dhcp4.c
src/network/networkd-dhcp6.c
src/network/networkd-ipv4acd.c
src/network/networkd-ipv4ll.c
src/network/networkd-ndisc.c

index dd1814bb9947b7c2a960d9589b1754e1cfa41a9c..f0924c93228f8b716768c7a2440dbf503e3a4065 100644 (file)
@@ -1089,7 +1089,6 @@ static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
 
 int address_remove(Address *address, Link *link) {
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
-        Request *req;
         int r;
 
         assert(address);
@@ -1119,8 +1118,6 @@ int address_remove(Address *address, Link *link) {
         link_ref(link);
 
         address_enter_removing(address);
-        if (address_get_request(link, address, &req) >= 0)
-                address_enter_removing(req->userdata);
 
         /* The operational state is determined by address state and carrier state. Hence, if we remove
          * an address, the operational state may be changed. */
@@ -1128,16 +1125,30 @@ int address_remove(Address *address, Link *link) {
         return 0;
 }
 
-int address_remove_and_drop(Address *address) {
-        if (!address || !address->link)
-                return 0;
+int address_remove_and_cancel(Address *address, Link *link) {
+        bool waiting = false;
+        Request *req;
 
-        address_cancel_request(address);
+        assert(address);
+        assert(link);
+        assert(link->manager);
 
-        if (address_exists(address))
-                return address_remove(address, address->link);
+        /* If the address is remembered by the link, then use the remembered object. */
+        (void) address_get(link, address, &address);
 
-        return address_drop(address);
+        /* Cancel the request for the address.  If the request is already called but we have not received the
+         * notification about the request, then explicitly remove the address. */
+        if (address_get_request(link, address, &req) >= 0) {
+                waiting = req->waiting_reply;
+                request_detach(link->manager, req);
+                address_cancel_requesting(address);
+        }
+
+        /* If we know the address will come or already exists, remove it. */
+        if (waiting || (address->link && address_exists(address)))
+                return address_remove(address, link);
+
+        return 0;
 }
 
 bool link_address_is_dynamic(const Link *link, const Address *address) {
@@ -1632,27 +1643,6 @@ int link_request_static_addresses(Link *link) {
         return 0;
 }
 
-void address_cancel_request(Address *address) {
-        Request req;
-
-        assert(address);
-        assert(address->link);
-
-        if (!address_is_requesting(address))
-                return;
-
-        req = (Request) {
-                .link = address->link,
-                .type = REQUEST_TYPE_ADDRESS,
-                .userdata = address,
-                .hash_func = (hash_func_t) address_hash_func,
-                .compare_func = (compare_func_t) address_compare_func,
-        };
-
-        request_detach(address->link->manager, &req);
-        address_cancel_requesting(address);
-}
-
 int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
         _cleanup_(address_freep) Address *tmp = NULL;
         struct ifa_cacheinfo cinfo;
index 786005c1e4bac441ca8ca41afbf694dae4d462f8..53e7a798212578e60ffc120bb071211b59835217 100644 (file)
@@ -90,7 +90,7 @@ int address_get(Link *link, const Address *in, Address **ret);
 int address_get_harder(Link *link, const Address *in, Address **ret);
 int address_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, const char *error_msg);
 int address_remove(Address *address, Link *link);
-int address_remove_and_drop(Address *address);
+int address_remove_and_cancel(Address *address, Link *link);
 int address_dup(const Address *src, Address **ret);
 bool address_is_ready(const Address *a);
 bool link_check_addresses_ready(Link *link, NetworkConfigSource source);
@@ -114,7 +114,6 @@ static inline int link_get_ipv4_address(Link *link, const struct in_addr *addres
 int manager_get_address(Manager *manager, int family, const union in_addr_union *address, unsigned char prefixlen, Address **ret);
 bool manager_has_address(Manager *manager, int family, const union in_addr_union *address);
 
-void address_cancel_request(Address *address);
 int link_request_address(
                 Link *link,
                 const Address *address,
index ad49f2ee8b2b50f125cafd931d151be9a43525c0..f5d97dd7af2399903a6e559b5cf0632b04d23510 100644 (file)
@@ -192,7 +192,7 @@ int dhcp_pd_remove(Link *link, bool only_marked) {
 
                         link_remove_dhcp_pd_subnet_prefix(link, &prefix);
 
-                        RET_GATHER(ret, address_remove_and_drop(address));
+                        RET_GATHER(ret, address_remove_and_cancel(address, link));
                 }
         }
 
index bca426f623774c2df5bcdcc6af05fbc9e7aa4a68..8aee30e7266435f7f9ec4b7bfc41945caa28a739 100644 (file)
@@ -263,7 +263,7 @@ static int dhcp4_remove_address_and_routes(Link *link, bool only_marked) {
                 if (only_marked && !address_is_marked(address))
                         continue;
 
-                RET_GATHER(ret, address_remove_and_drop(address));
+                RET_GATHER(ret, address_remove_and_cancel(address, link));
         }
 
         return ret;
index 6854533eed658860bc4d5c7103cb3b5d5cb215af..6d8b3c3ce26bc6f92f510f9ad954ade7ad0854c0 100644 (file)
@@ -71,7 +71,7 @@ static int dhcp6_remove(Link *link, bool only_marked) {
                 if (only_marked && !address_is_marked(address))
                         continue;
 
-                RET_GATHER(ret, address_remove_and_drop(address));
+                RET_GATHER(ret, address_remove_and_cancel(address, link));
         }
 
         return ret;
index ee1f31ef0c6fcd27921f4a9efc8e50471c85e08b..de03293fff330fdfae5c8e8ef282382c0eb12ac2 100644 (file)
@@ -92,6 +92,8 @@ static int static_ipv4acd_address_remove(Link *link, Address *address, bool on_c
         else
                 log_link_debug(link, "Removing address %s, as the ACD client is stopped.", IN4_ADDR_TO_STRING(&address->in_addr.in));
 
+        /* Do not call address_remove_and_cancel() here. Otherwise, the request is cancelled, and the
+         * interface may be in configured state without the address. */
         r = address_remove(address, link);
         if (r < 0)
                 return log_link_warning_errno(link, r, "Failed to remove address %s: %m", IN4_ADDR_TO_STRING(&address->in_addr.in));
index 3fccb6d13c9ade11d86fae8451c96ba709669f0b..629a3734095f2f1c872f154a07c1ed0ac7b96155 100644 (file)
@@ -57,7 +57,6 @@ static int address_new_from_ipv4ll(Link *link, Address **ret) {
 
 static int ipv4ll_address_lost(Link *link) {
         _cleanup_(address_freep) Address *address = NULL;
-        Address *existing;
         int r;
 
         assert(link);
@@ -70,19 +69,10 @@ static int ipv4ll_address_lost(Link *link) {
         if (r < 0)
                 return r;
 
-        if (address_get(link, address, &existing) < 0)
-                return 0;
-
-        if (existing->source != NETWORK_CONFIG_SOURCE_IPV4LL)
-                return 0;
-
-        if (!address_exists(existing))
-                return 0;
-
         log_link_debug(link, "IPv4 link-local release "IPV4_ADDRESS_FMT_STR,
                        IPV4_ADDRESS_FMT_VAL(address->in_addr.in));
 
-        return address_remove(existing, link);
+        return address_remove_and_cancel(address, link);
 }
 
 static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
index ddd60a1e574914d027e333fa8120458b2ec6df7d..369e205a99a229b49c346772c1ac8a1dac761bf3 100644 (file)
@@ -1137,7 +1137,7 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) {
                 if (address->lifetime_valid_usec >= timestamp_usec)
                         continue; /* the address is still valid */
 
-                r = address_remove_and_drop(address);
+                r = address_remove_and_cancel(address, link);
                 if (r < 0)
                         RET_GATHER(ret, log_link_warning_errno(link, r, "Failed to remove outdated SLAAC address, ignoring: %m"));
         }