]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: address: also set IFA_FLAGS on remove
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 11 Feb 2021 17:56:43 +0000 (02:56 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 12 Feb 2021 14:09:21 +0000 (23:09 +0900)
If an address is assigned with IFA_F_MANAGETEMPADDR, then the flag must
be also set on remove. Otherwise, temporary addresses will not be
removed. See also inet6_rtm_deladdr() in kernel's net/ipv6/addrconf.c.

Fixes #13218.

src/network/networkd-address.c

index d7fbb6eac53a828e66c6c8a080f9bbcfb4ecf7d3..c3e92d987193316d9a0e1e00acba49d04f0c32d5 100644 (file)
@@ -517,6 +517,39 @@ static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
         return 1;
 }
 
+static int address_set_netlink_message(const Address *address, sd_netlink_message *req, Link *link) {
+        uint32_t flags;
+        int r;
+
+        assert(address);
+        assert(req);
+        assert(link);
+
+        r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not set prefixlen: %m");
+
+        /* On remove, only IFA_F_MANAGETEMPADDR flag for IPv6 addresses are used. But anyway, set all
+         * flags here unconditionally. Without setting the flag, the template addresses generated by
+         * kernel will not be removed automatically when the main address is removed. */
+        flags = address->flags | IFA_F_PERMANENT;
+        r = sd_rtnl_message_addr_set_flags(req, flags & 0xff);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not set flags: %m");
+
+        if (flags & ~0xff) {
+                r = sd_netlink_message_append_u32(req, IFA_FLAGS, flags);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not set extended flags: %m");
+        }
+
+        r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
+
+        return 0;
+}
+
 int address_remove(
                 const Address *address,
                 Link *link,
@@ -539,13 +572,9 @@ int address_remove(
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not allocate RTM_DELADDR message: %m");
 
-        r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
+        r = address_set_netlink_message(address, req, link);
         if (r < 0)
-                return log_link_error_errno(link, r, "Could not set prefixlen: %m");
-
-        r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
+                return r;
 
         r = netlink_call_async(link->manager->rtnl, NULL, req,
                                callback ?: address_remove_handler,
@@ -809,7 +838,6 @@ int address_configure(
 
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         Address *acquired_address, *a;
-        uint32_t flags;
         bool update;
         int r;
 
@@ -846,29 +874,14 @@ int address_configure(
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not allocate RTM_NEWADDR message: %m");
 
-        r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
+        r = address_set_netlink_message(address, req, link);
         if (r < 0)
-                return log_link_error_errno(link, r, "Could not set prefixlen: %m");
-
-        flags = address->flags | IFA_F_PERMANENT;
-        r = sd_rtnl_message_addr_set_flags(req, flags & 0xff);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not set flags: %m");
-
-        if (flags & ~0xff) {
-                r = sd_netlink_message_append_u32(req, IFA_FLAGS, flags);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not set extended flags: %m");
-        }
+                return r;
 
         r = sd_rtnl_message_addr_set_scope(req, address->scope);
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not set scope: %m");
 
-        r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
-
         if (in_addr_is_null(address->family, &address->in_addr_peer) == 0) {
                 r = netlink_message_append_in_addr_union(req, IFA_ADDRESS, address->family, &address->in_addr_peer);
                 if (r < 0)