network/ndisc: check if there exists a conflicting address

Follow-up for 0a0c2672db.

Before the commit, if a conflicting address exists or already requested,
then the configuration of newly requested address (especially, prefix
length) is mostly ignored silently.

However, after the commit, even if there exists a conflicting address,
networkd anyway tries to configure the newly requested address, and
enter failed state. Such situation can be triggered, e.g. when the DHCPv6
client is started earlier than NDisc, by WithoutRA=solicit.

Fixes #31263.
This commit is contained in:
Yu Watanabe
2024-02-14 13:59:04 +09:00
parent 9e79ef9120
commit e720ad88f3
+20 -1
View File
@@ -269,7 +269,26 @@ static int ndisc_request_address(Address *address, Link *link, sd_ndisc_router *
if (r < 0)
return r;
is_new = address_get(link, address, NULL) < 0;
Address *existing;
if (address_get_harder(link, address, &existing) < 0)
is_new = true;
else if (address_can_update(existing, address))
is_new = false;
else if (existing->source == NETWORK_CONFIG_SOURCE_DHCP6) {
/* SLAAC address is preferred over DHCPv6 address. */
log_link_debug(link, "Conflicting DHCPv6 address %s exists, removing.",
IN_ADDR_PREFIX_TO_STRING(existing->family, &existing->in_addr, existing->prefixlen));
r = address_remove(existing, link);
if (r < 0)
return r;
is_new = true;
} else {
/* Conflicting static address is configured?? */
log_link_debug(link, "Conflicting address %s exists, ignoring request.",
IN_ADDR_PREFIX_TO_STRING(existing->family, &existing->in_addr, existing->prefixlen));
return 0;
}
r = link_request_address(link, address, &link->ndisc_messages,
ndisc_address_handler, NULL);