]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: do not enable IPv4 ACD for IPv4 link-local address if ACD is disabled explicitly
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 22 Mar 2022 13:01:08 +0000 (22:01 +0900)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 23 Mar 2022 16:59:38 +0000 (17:59 +0100)
The commit 1cf4ed142d6c1e2b9dc6a0bc74b6a83ae30b0f8e makes the IPv4 ACD
enabled unconditionally for IPv4 link-local addresses even if users
explicitly disable ACD.

This makes the IPv4 ACD is enabled by default, but honor user setting.

Fixes #22763.

man/systemd.network.xml
src/network/networkd-address.c
src/network/networkd-address.h

index bc2d1615f9348c58005e93427c0fe8aff33656bf..c849cfc4fee3aae35d192558c09f17b2015f262a 100644 (file)
@@ -1045,7 +1045,8 @@ Table=1234</programlisting></para>
           Detection. See <ulink url="https://tools.ietf.org/html/rfc5227">RFC 5227</ulink>.
           When <literal>ipv6</literal>, performs IPv6 Duplicate Address Detection. See
           <ulink url="https://tools.ietf.org/html/rfc4862">RFC 4862</ulink>. Defaults to
-          <literal>ipv6</literal>.</para>
+          <literal>ipv4</literal> for IPv4 link-local addresses, <literal>ipv6</literal> for IPv6
+          addresses, and <literal>none</literal> otherwise.</para>
         </listitem>
       </varlistentry>
 
index 19a357130b5935a9b687d67024888536d3128eb1..eba28cfc678e41ad77abe6aa6ee5862561df0a9f 100644 (file)
@@ -68,7 +68,6 @@ int address_new(Address **ret) {
                 .lifetime_valid_usec = USEC_INFINITY,
                 .lifetime_preferred_usec = USEC_INFINITY,
                 .set_broadcast = -1,
-                .duplicate_address_detection = ADDRESS_FAMILY_IPV6,
         };
 
         *ret = TAKE_PTR(address);
@@ -106,6 +105,8 @@ static int address_new_static(Network *network, const char *filename, unsigned s
         address->network = network;
         address->section = TAKE_PTR(n);
         address->source = NETWORK_CONFIG_SOURCE_STATIC;
+        /* This will be adjusted in address_section_verify(). */
+        address->duplicate_address_detection = _ADDRESS_FAMILY_INVALID;
 
         r = ordered_hashmap_ensure_put(&network->addresses_by_section, &config_section_hash_ops, address->section, address);
         if (r < 0)
@@ -1951,6 +1952,8 @@ static int address_section_verify(Address *address) {
                                          address->section->filename, address->section->line);
         }
 
+        assert(IN_SET(address->family, AF_INET, AF_INET6));
+
         if (in4_addr_is_set(&address->broadcast) &&
             (address->family == AF_INET6 || address->prefixlen > 30 ||
              in_addr_is_set(address->family, &address->in_addr_peer))) {
@@ -1977,17 +1980,24 @@ static int address_section_verify(Address *address) {
                         address->scope = RT_SCOPE_LINK;
         }
 
+        if (address->duplicate_address_detection < 0) {
+                if (address->family == AF_INET6)
+                        address->duplicate_address_detection = ADDRESS_FAMILY_IPV6;
+                else if (in4_addr_is_link_local(&address->in_addr.in))
+                        address->duplicate_address_detection = ADDRESS_FAMILY_IPV4;
+                else
+                        address->duplicate_address_detection = ADDRESS_FAMILY_NO;
+        } else if (address->duplicate_address_detection == ADDRESS_FAMILY_IPV6 && address->family == AF_INET)
+                log_warning("%s: DuplicateAddressDetection=ipv6 is specified for IPv4 address, ignoring.",
+                            address->section->filename);
+        else if (address->duplicate_address_detection == ADDRESS_FAMILY_IPV4 && address->family == AF_INET6)
+                log_warning("%s: DuplicateAddressDetection=ipv4 is specified for IPv6 address, ignoring.",
+                            address->section->filename);
+
         if (address->family == AF_INET6 &&
             !FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV6))
                 address->flags |= IFA_F_NODAD;
 
-        if (address->family == AF_INET && in4_addr_is_link_local(&address->in_addr.in) &&
-            !FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV4)) {
-                log_debug("%s: An IPv4 link-local address is specified, enabling IPv4 Address Conflict Detection (ACD).",
-                          address->section->filename);
-                address->duplicate_address_detection |= ADDRESS_FAMILY_IPV4;
-        }
-
         return 0;
 }
 
index 563a3de4e27baae633dc0af2ff9360b1a58b91f9..0237c1cb98c51d42cf8b1967d1d66d501f8ca444 100644 (file)
@@ -53,6 +53,9 @@ struct Address {
 
         bool scope_set:1;
         bool ip_masquerade_done:1;
+
+        /* duplicate_address_detection is only used by static or IPv4 dynamic addresses.
+         * To control DAD for IPv6 dynamic addresses, set IFA_F_NODAD to flags. */
         AddressFamily duplicate_address_detection;
         sd_ipv4acd *acd;