summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2022-09-22 14:02:23 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2022-10-26 10:08:53 +0200
commit8e85c86add19bfdd8059f06bdacfa387b2aea2b4 (patch)
tree4db7f330091adc21006bd127d605d1bbc28f78e1
parent922ef4344ed2d4d9dbb96fef12d00586255bda9d (diff)
dhcp: improve detection of DADFAILED addresses
Instead of assuming any address that disappeared was because of a DAD failure, check explicitly that either: - the address is still present with DADFAILED flag (in case it was a permanent address), or - the address was removed and platform recorded that it had the DADFAILED flag.
-rw-r--r--src/core/dhcp/nm-dhcp-client.c43
1 files changed, 22 insertions, 21 deletions
diff --git a/src/core/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c
index bd67be1b86..19a44c6ac6 100644
--- a/src/core/dhcp/nm-dhcp-client.c
+++ b/src/core/dhcp/nm-dhcp-client.c
@@ -1039,35 +1039,33 @@ ipv6_lladdr_find(NMDhcpClient *self)
static void
ipv6_tentative_addr_check(NMDhcpClient *self,
GPtrArray **tentative,
- GPtrArray **missing,
+ GPtrArray **dadfailed,
const NMPlatformIP6Address **valid)
{
NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
NMDedupMultiIter iter;
const NMPlatformIP6Address *addr;
- NML3Cfg *l3cfg = priv->config.l3cfg;
+ NML3Cfg *l3cfg = priv->config.l3cfg;
+ NMPlatform *platform = nm_l3cfg_get_platform(l3cfg);
+ int ifindex = nm_l3cfg_get_ifindex(l3cfg);
/* For each address in the lease, check whether it's tentative
- * in platform. */
+ * or dad-failed in platform. */
nm_l3_config_data_iter_ip6_address_for_each (&iter, priv->l3cd_curr, &addr) {
const NMPlatformIP6Address *pladdr;
- NMPObject needle;
-
- nmp_object_stackinit_id_ip6_address(&needle, nm_l3cfg_get_ifindex(l3cfg), &addr->address);
- pladdr = NMP_OBJECT_CAST_IP6_ADDRESS(nm_platform_lookup_obj(nm_l3cfg_get_platform(l3cfg),
- NMP_CACHE_ID_TYPE_OBJECT_TYPE,
- &needle));
- if (!pladdr) {
- /* address removed: we assume that's because DAD failed */
- if (missing) {
- if (!*missing)
- *missing = g_ptr_array_new();
- g_ptr_array_add(*missing, (gpointer) addr);
+
+ pladdr = nm_platform_ip6_address_get(platform, ifindex, &addr->address);
+ if ((pladdr && NM_FLAGS_HAS(pladdr->n_ifa_flags, IFA_F_DADFAILED))
+ || (!pladdr && nm_platform_ip6_dadfailed_check(platform, ifindex, &addr->address))) {
+ if (dadfailed) {
+ if (!*dadfailed)
+ *dadfailed = g_ptr_array_new();
+ g_ptr_array_add(*dadfailed, (gpointer) addr);
}
continue;
}
- if (NM_FLAGS_HAS(pladdr->n_ifa_flags, IFA_F_TENTATIVE)
+ if (pladdr && NM_FLAGS_HAS(pladdr->n_ifa_flags, IFA_F_TENTATIVE)
&& !NM_FLAGS_HAS(pladdr->n_ifa_flags, IFA_F_OPTIMISTIC)) {
if (tentative) {
if (!*tentative)
@@ -1076,6 +1074,9 @@ ipv6_tentative_addr_check(NMDhcpClient *self,
}
}
+ /* Here the address is non-tentative or it was removed externally by the user.
+ * In both cases it has completed DAD.
+ */
NM_SET_OUT(valid, addr);
}
}
@@ -1115,13 +1116,13 @@ l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMDhcp
if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE
&& priv->l3cfg_notify.wait_ipv6_dad) {
gs_unref_ptrarray GPtrArray *tentative = NULL;
- gs_unref_ptrarray GPtrArray *missing = NULL;
+ gs_unref_ptrarray GPtrArray *dadfailed = NULL;
const NMPlatformIP6Address *valid = NULL;
char str[NM_UTILS_TO_STRING_BUFFER_SIZE];
guint i;
gs_free_error GError *error = NULL;
- ipv6_tentative_addr_check(self, &tentative, &missing, &valid);
+ ipv6_tentative_addr_check(self, &tentative, &dadfailed, &valid);
if (tentative) {
for (i = 0; i < tentative->len; i++) {
_LOGD("still waiting DAD for address: %s",
@@ -1134,10 +1135,10 @@ l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMDhcp
nm_clear_g_source_inst(&priv->v6.dad_timeout_source);
l3_cfg_notify_check_connected(self);
- if (missing) {
- for (i = 0; i < missing->len; i++) {
+ if (dadfailed) {
+ for (i = 0; i < dadfailed->len; i++) {
_LOGE("DAD failed for address: %s",
- nm_platform_ip6_address_to_string(missing->pdata[i], str, sizeof(str)));
+ nm_platform_ip6_address_to_string(dadfailed->pdata[i], str, sizeof(str)));
}
}