]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: configure IPv4 DAD per link address
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 4 Oct 2020 00:14:15 +0000 (09:14 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 6 Oct 2020 17:57:58 +0000 (02:57 +0900)
Previously, IPv4 DAD is configured in each Address object stored in
Network object. If a .network file matches multipe links, then it causes
an assertion. To prevent it, now IPv4 DAD is configured in each Address
object belogs to Link object.

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

index a79b99b35a589e737675f46f383e99ddaaba1ce3..0d2fa60eddb82bfd19432f7eb4220d7c65b281bb 100644 (file)
@@ -106,7 +106,7 @@ Address *address_free(Address *address) {
                 ordered_hashmap_remove(address->network->addresses_by_section, address->section);
         }
 
-        if (address->link && !address->acd) {
+        if (address->link) {
                 NDiscAddress *n;
 
                 set_remove(address->link->addresses, address);
@@ -793,6 +793,8 @@ static int address_acquire(Link *link, const Address *original, Address **ret) {
         return 1;
 }
 
+static int ipv4_dad_configure(Address *address);
+
 int address_configure(
                 Address *address,
                 Link *link,
@@ -905,16 +907,8 @@ int address_configure(
                 return log_link_error_errno(link, r, "Could not add address: %m");
         }
 
-        if (address->acd) {
-                assert(address->family == AF_INET);
-                if (DEBUG_LOGGING) {
-                        _cleanup_free_ char *pretty = NULL;
-
-                        (void) in_addr_to_string(address->family, &address->in_addr, &pretty);
-                        log_link_debug(link, "Starting IPv4ACD client. Probing address %s", strna(pretty));
-                }
-
-                r = sd_ipv4acd_start(address->acd, true);
+        if (FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV4)) {
+                r = ipv4_dad_configure(a);
                 if (r < 0)
                         log_link_warning_errno(link, r, "Failed to start IPv4ACD client, ignoring: %m");
         }
@@ -1363,29 +1357,37 @@ static void static_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) {
         return;
 }
 
-static int ipv4_dad_configure(Link *link, Address *address) {
+static int ipv4_dad_configure(Address *address) {
         int r;
 
-        assert(link);
         assert(address);
-        assert(address->family == AF_INET);
-        assert(!address->link && address->network);
+        assert(address->link);
 
-        address->link = link;
+        if (address->family != AF_INET)
+                return 0;
 
-        r = sd_ipv4acd_new(&address->acd);
-        if (r < 0)
-                return r;
+        if (DEBUG_LOGGING) {
+                _cleanup_free_ char *pretty = NULL;
 
-        r = sd_ipv4acd_attach_event(address->acd, link->manager->event, 0);
-        if (r < 0)
-                return r;
+                (void) in_addr_to_string(address->family, &address->in_addr, &pretty);
+                log_link_debug(address->link, "Starting IPv4ACD client. Probing address %s", strna(pretty));
+        }
+
+        if (!address->acd) {
+                r = sd_ipv4acd_new(&address->acd);
+                if (r < 0)
+                        return r;
+
+                r = sd_ipv4acd_attach_event(address->acd, address->link->manager->event, 0);
+                if (r < 0)
+                        return r;
+        }
 
-        r = sd_ipv4acd_set_ifindex(address->acd, link->ifindex);
+        r = sd_ipv4acd_set_ifindex(address->acd, address->link->ifindex);
         if (r < 0)
                 return r;
 
-        r = sd_ipv4acd_set_mac(address->acd, &link->mac);
+        r = sd_ipv4acd_set_mac(address->acd, &address->link->mac);
         if (r < 0)
                 return r;
 
@@ -1397,37 +1399,16 @@ static int ipv4_dad_configure(Link *link, Address *address) {
         if (r < 0)
                 return r;
 
-        return 0;
+        return sd_ipv4acd_start(address->acd, true);
 }
 
-int link_configure_ipv4_dad(Link *link) {
-        Address *address;
-        int r;
-
-        assert(link);
-        assert(link->network);
-
-        ORDERED_HASHMAP_FOREACH(address, link->network->addresses_by_section)
-                if (address->family == AF_INET &&
-                    FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV4)) {
-                        r = ipv4_dad_configure(link, address);
-                        if (r < 0)
-                                return log_link_error_errno(link, r, "Failed to configure IPv4ACD: %m");
-                }
-
-        return 0;
-}
-
-int link_stop_ipv4_dad(Link *link) {
+int ipv4_dad_stop(Link *link) {
         Address *address;
         int k, r = 0;
 
         assert(link);
 
-        if (!link->network)
-                return 0;
-
-        ORDERED_HASHMAP_FOREACH(address, link->network->addresses_by_section) {
+        SET_FOREACH(address, link->addresses) {
                 if (!address->acd)
                         continue;
 
index e935b6ffa9a69d287799e2d390b3fe01f81f7ffa..816e84550b2f2bff76dff01478f0775afb6945b1 100644 (file)
@@ -64,8 +64,8 @@ int link_drop_addresses(Link *link);
 int link_drop_foreign_addresses(Link *link);
 int link_serialize_addresses(Link *link, FILE *f);
 int link_deserialize_addresses(Link *link, const char *addresses);
-int link_configure_ipv4_dad(Link *link);
-int link_stop_ipv4_dad(Link *link);
+
+int ipv4_dad_stop(Link *link);
 
 int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m);
 
index b8145ea65177d74e6bf9985a4b0cbc4de9752113..ce708edabb4bbab97fb793e331b404319504a4be 100644 (file)
@@ -628,7 +628,7 @@ int link_stop_clients(Link *link, bool may_keep_dhcp) {
                         r = log_link_warning_errno(link, k, "Could not stop IPv4 link-local: %m");
         }
 
-        k = link_stop_ipv4_dad(link);
+        k = ipv4_dad_stop(link);
         if (k < 0)
                 r = log_link_warning_errno(link, k, "Could not stop IPv4 ACD client: %m");
 
@@ -1998,10 +1998,6 @@ int link_configure(Link *link) {
         if (r < 0)
                 return r;
 
-        r = link_configure_ipv4_dad(link);
-        if (r < 0)
-                return r;
-
         return link_configure_continue(link);
 }