has = true;
}
+ if (has || source != NETWORK_CONFIG_SOURCE_DHCP6)
+ return has;
+
+ /* If there is no DHCPv6 addresses, but all conflicting addresses are successfully configured, then
+ * let's handle the DHCPv6 client successfully configured addresses. Otherwise, if the conflicted
+ * addresses are static or foreign, and there is no other dynamic addressing protocol enabled, then
+ * the link will never enter the configured state. See also link_check_ready(). */
+ SET_FOREACH(a, link->addresses) {
+ if (source >= 0 && a->source == NETWORK_CONFIG_SOURCE_DHCP6)
+ continue;
+ if (!a->also_requested_by_dhcp6)
+ continue;
+ if (address_is_marked(a))
+ continue;
+ if (!address_exists(a))
+ continue;
+ if (!address_is_ready(a))
+ return false;
+ has = true;
+ }
+
return has;
}
nft_set_context_clear(&address->nft_set_context);
(void) nft_set_context_dup(&a->nft_set_context, &address->nft_set_context);
address->requested_as_null = a->requested_as_null;
+ address->also_requested_by_dhcp6 = a->also_requested_by_dhcp6;
address->callback = a->callback;
ipv6_token_ref(a->token);
bool ip_masquerade_done:1;
bool requested_as_null:1;
bool used_by_dhcp_server:1;
+ /* If this address is configured by non-DHCPv6 protocol (i.e. statically, NDISC, or any foreign
+ * methods), and the DHCPv6 client requests the same address, set this flag.
+ * See link_check_addresses_ready() and verify_dhcp6_address(). */
+ bool also_requested_by_dhcp6: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. */
bool by_ndisc = existing->source == NETWORK_CONFIG_SOURCE_NDISC;
log_link_full(link,
- LOG_WARNING,
+ /* Downgrade the log level if we have logged about the conflict previously. */
+ existing->also_requested_by_dhcp6 ? LOG_DEBUG : LOG_WARNING,
"Ignoring DHCPv6 address %s (valid %s, preferred %s) which conflicts with %s%s.%s",
IN6_ADDR_PREFIX_TO_STRING(&address->in_addr.in6, address->prefixlen),
FORMAT_LIFETIME(address->lifetime_valid_usec),
by_ndisc ? " assigned by NDisc" : "",
by_ndisc ? "\nHint: use IPv6Token= setting to change the address generated by NDisc or set UseAutonomousPrefix=no." : "");
+ existing->also_requested_by_dhcp6 = true;
return -EEXIST;
}