From 2859932bd64d61a89f85fa027762bc16961fcf53 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 22 Mar 2022 22:01:08 +0900 Subject: [PATCH] network: do not enable IPv4 ACD for IPv4 link-local address if ACD is disabled explicitly 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 | 3 ++- src/network/networkd-address.c | 26 ++++++++++++++++++-------- src/network/networkd-address.h | 3 +++ 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index bc2d1615f93..c849cfc4fee 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -1045,7 +1045,8 @@ Table=1234 Detection. See RFC 5227. When ipv6, performs IPv6 Duplicate Address Detection. See RFC 4862. Defaults to - ipv6. + ipv4 for IPv4 link-local addresses, ipv6 for IPv6 + addresses, and none otherwise. diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 19a357130b5..eba28cfc678 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -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; } diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 563a3de4e27..0237c1cb98c 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -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;