summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2022-09-06 17:13:58 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2022-10-26 10:08:53 +0200
commitaddb4e3a0c610b47ed4baa727310803a302a6ba2 (patch)
tree651530c8b745cdee738b074ea9b35872ab833b44
parent15d55e5a6841abd7efad21d5a098abe1978a89fc (diff)
downloadNetworkManager-addb4e3a0c610b47ed4baa727310803a302a6ba2.tar.gz
device: generate a new AC6 address when DAD fails
For addresses that fail DAD we need to call nm_ndisc_dad_failed() to generate a new address if addrgenmode is stable-privacy. https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/1046
-rw-r--r--src/core/devices/nm-device.c42
1 files changed, 30 insertions, 12 deletions
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index 48fe6cbbd4..a8624754a4 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -4135,18 +4135,30 @@ _dev_l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, N
/* Check if AC6 addresses completed DAD */
if (NM_FLAGS_ANY(notify_data->platform_change_on_idle.obj_type_flags,
nmp_object_type_to_flags(NMP_OBJECT_TYPE_IP6_ADDRESS))
- && priv->ipac6_data.state == NM_DEVICE_IP_STATE_PENDING && priv->ipac6_data.l3cd
- && nm_l3cfg_check_ready(l3cfg,
- priv->ipac6_data.l3cd,
- AF_INET6,
- NM_L3CFG_CHECK_READY_FLAGS_IP6_DAD_READY,
- NULL)) {
- if (nm_l3cfg_has_temp_not_available_obj(priv->l3cfg, AF_INET6))
- _dev_l3_cfg_commit(self, FALSE);
-
- nm_clear_l3cd(&priv->ipac6_data.l3cd);
- _dev_ipac6_set_state(self, NM_DEVICE_IP_STATE_READY);
- _dev_ip_state_check_async(self, AF_INET6);
+ && priv->ipac6_data.state == NM_DEVICE_IP_STATE_PENDING && priv->ipac6_data.l3cd) {
+ gs_unref_array GArray *conflicts = NULL;
+ gboolean ready;
+
+ ready = nm_l3cfg_check_ready(l3cfg,
+ priv->ipac6_data.l3cd,
+ AF_INET6,
+ NM_L3CFG_CHECK_READY_FLAGS_IP6_DAD_READY,
+ &conflicts);
+ if (conflicts) {
+ /* nm_ndisc_dad_failed() will emit a new "NDisc:config-received"
+ * signal; _dev_ipac6_ndisc_config_changed() will be called
+ * synchronously to update the current state and schedule a commit. */
+ nm_ndisc_dad_failed(priv->ipac6_data.ndisc, conflicts, TRUE);
+ } else if (ready) {
+ if (nm_l3cfg_has_temp_not_available_obj(priv->l3cfg, AF_INET6))
+ _dev_l3_cfg_commit(self, FALSE);
+
+ nm_clear_l3cd(&priv->ipac6_data.l3cd);
+ _dev_ipac6_set_state(self, NM_DEVICE_IP_STATE_READY);
+ _dev_ip_state_check_async(self, AF_INET6);
+ } else {
+ /* wait */
+ }
}
_dev_ipmanual_check_ready(self);
@@ -11435,6 +11447,12 @@ _dev_ipac6_ndisc_config_changed(NMNDisc *ndisc,
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
gboolean ready;
+ /* The ndisc configuration changes when we receive a new RA or
+ * when a lifetime expires; but also when DAD fails for a
+ * SLAAC address and we need to regenerate new stable-privacy
+ * addresses. In all these cases we update the AC6 configuration,
+ * schedule a commit and update the AC state. */
+
_dev_ipac6_grace_period_start(self, 0, TRUE);
_dev_l3_register_l3cds_set_one_full(self,