diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2022-09-06 10:34:04 +0200 |
---|---|---|
committer | Beniamino Galvani <bgalvani@redhat.com> | 2022-09-06 10:34:04 +0200 |
commit | 12e5b944f6a2a7c94a3f046eedba78ee56beb4d5 (patch) | |
tree | 39fc201cf42473d93c934a54c23ecb4f81a88ffd | |
parent | 9eb8cbca769e8e462bacdc4db424633ca093e3e4 (diff) | |
parent | e4aefbc5561375bf89a09c051a9c48a16855d234 (diff) | |
download | NetworkManager-12e5b944f6a2a7c94a3f046eedba78ee56beb4d5.tar.gz |
dhcp: merge branch 'bg/dhcp6-dad-pt2'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1363
https://bugzilla.redhat.com/show_bug.cgi?id=2096386
-rw-r--r-- | src/core/dhcp/nm-dhcp-client.c | 175 | ||||
-rw-r--r-- | src/core/dhcp/nm-dhcp-helper.c | 19 |
2 files changed, 125 insertions, 69 deletions
diff --git a/src/core/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c index 34873ac2e3..68246280e3 100644 --- a/src/core/dhcp/nm-dhcp-client.c +++ b/src/core/dhcp/nm-dhcp-client.c @@ -115,9 +115,6 @@ typedef struct _NMDhcpClientPrivate { in_addr_t addr; NMOptionBool state; } acd; - struct { - GDBusMethodInvocation *invocation; - } bound; } v4; struct { GSource *lladdr_timeout_source; @@ -125,6 +122,8 @@ typedef struct _NMDhcpClientPrivate { } v6; }; + GDBusMethodInvocation *invocation; + struct { gulong id; bool wait_dhcp_commit : 1; @@ -909,13 +908,10 @@ _accept(NMDhcpClient *self, const NML3ConfigData *l3cd, GError **error) { NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); - if (!NM_IS_IPv4(priv->config.addr_family)) + if (!priv->invocation) return TRUE; - if (!priv->v4.bound.invocation) - return TRUE; - - g_dbus_method_invocation_return_value(g_steal_pointer(&priv->v4.bound.invocation), NULL); + g_dbus_method_invocation_return_value(g_steal_pointer(&priv->invocation), NULL); return TRUE; } @@ -939,20 +935,17 @@ decline(NMDhcpClient *self, const NML3ConfigData *l3cd, const char *error_messag { NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); - if (!NM_IS_IPv4(priv->config.addr_family)) - return TRUE; - - if (!priv->v4.bound.invocation) { + if (!priv->invocation) { nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, "calling decline in unexpected script state"); return FALSE; } - - g_dbus_method_invocation_return_error(g_steal_pointer(&priv->v4.bound.invocation), + g_dbus_method_invocation_return_error(g_steal_pointer(&priv->invocation), NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, - "acd failed"); + NM_IS_IPv4(priv->config.addr_family) ? "ACD failed" + : "DAD failed"); return TRUE; } @@ -1043,8 +1036,11 @@ ipv6_lladdr_find(NMDhcpClient *self) return NULL; } -static const NMPlatformIP6Address * -ipv6_tentative_addr_find(NMDhcpClient *self) +static void +ipv6_tentative_addr_check(NMDhcpClient *self, + GPtrArray **tentative, + GPtrArray **missing, + const NMPlatformIP6Address **valid) { NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); NMDedupMultiIter iter; @@ -1062,16 +1058,26 @@ ipv6_tentative_addr_find(NMDhcpClient *self) NMP_CACHE_ID_TYPE_OBJECT_TYPE, &needle)); if (!pladdr) { - /* Address was removed from platform */ + /* 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); + } continue; } if (NM_FLAGS_HAS(pladdr->n_ifa_flags, IFA_F_TENTATIVE) - && !NM_FLAGS_HAS(pladdr->n_ifa_flags, IFA_F_OPTIMISTIC)) - return pladdr; - } + && !NM_FLAGS_HAS(pladdr->n_ifa_flags, IFA_F_OPTIMISTIC)) { + if (tentative) { + if (!*tentative) + *tentative = g_ptr_array_new(); + g_ptr_array_add(*tentative, (gpointer) addr); + } + } - return NULL; + NM_SET_OUT(valid, addr); + } } static void @@ -1108,21 +1114,61 @@ 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) { - const NMPlatformIP6Address *tentative; + gs_unref_ptrarray GPtrArray *tentative = NULL; + gs_unref_ptrarray GPtrArray *missing = 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); + if (tentative) { + for (i = 0; i < tentative->len; i++) { + _LOGD("still waiting DAD for address: %s", + nm_platform_ip6_address_to_string(tentative->pdata[i], str, sizeof(str))); + } + } else { + /* done */ - tentative = ipv6_tentative_addr_find(self); - if (!tentative) { - _LOGD("addresses in the lease completed DAD"); priv->l3cfg_notify.wait_ipv6_dad = FALSE; nm_clear_g_source_inst(&priv->v6.dad_timeout_source); l3_cfg_notify_check_connected(self); - _emit_notify( - self, - &((NMDhcpClientNotifyData){.notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE, - .lease_update = { - .l3cd = priv->l3cd_curr, - .accepted = TRUE, - }})); + + if (missing) { + for (i = 0; i < missing->len; i++) { + _LOGE("DAD failed for address: %s", + nm_platform_ip6_address_to_string(missing->pdata[i], str, sizeof(str))); + } + } + + if (valid) { + /* at least one non-duplicate address */ + _LOGD("addresses in the lease completed DAD: accept the lease"); + + if (_dhcp_client_accept(self, priv->l3cd_curr, &error)) { + _emit_notify(self, + &((NMDhcpClientNotifyData){ + .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE, + .lease_update = { + .l3cd = priv->l3cd_curr, + .accepted = TRUE, + }})); + } else { + gs_free char *reason = + g_strdup_printf("error accepting lease: %s", error->message); + + _LOGD("accept failed: %s", error->message); + _emit_notify(self, + &((NMDhcpClientNotifyData){ + .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_IT_LOOKS_BAD, + .it_looks_bad.reason = reason, + })); + } + } else { + _LOGD("decline the lease"); + if (!_dhcp_client_decline(self, priv->l3cd_curr, "DAD failed", &error)) + _LOGD("decline failed: %s", error->message); + } } } @@ -1155,20 +1201,23 @@ l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMDhcp address4->peer_address)) goto wait_dhcp_commit_done; } else { - const NMPlatformIP6Address *address6 = (const NMPlatformIP6Address *) lease_address; - const NMPlatformIP6Address *tentative; - char str[NM_UTILS_TO_STRING_BUFFER_SIZE]; + const NMPlatformIP6Address *address6 = (const NMPlatformIP6Address *) lease_address; + gs_unref_ptrarray GPtrArray *tentative = NULL; + char str[NM_UTILS_TO_STRING_BUFFER_SIZE]; + guint i; if (!nm_l3_config_data_lookup_address_6(committed_l3cd, &address6->address)) goto wait_dhcp_commit_done; - tentative = ipv6_tentative_addr_find(self); + ipv6_tentative_addr_check(self, &tentative, NULL, NULL); if (tentative) { priv->l3cfg_notify.wait_ipv6_dad = TRUE; priv->v6.dad_timeout_source = nm_g_timeout_add_seconds_source(30, ipv6_dad_timeout, self); - _LOGD("wait DAD for address %s", - nm_platform_ip6_address_to_string(tentative, str, sizeof(str))); + for (i = 0; i < tentative->len; i++) { + _LOGD("wait DAD for address %s", + nm_platform_ip6_address_to_string(tentative->pdata[i], str, sizeof(str))); + } } else { priv->l3cfg_notify.wait_ipv6_dad = FALSE; nm_clear_g_source_inst(&priv->v6.dad_timeout_source); @@ -1179,22 +1228,22 @@ l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMDhcp l3_cfg_notify_check_connected(self); - _LOGD("accept lease"); + if (priv->config.addr_family == AF_INET || !priv->l3cfg_notify.wait_ipv6_dad) { + _LOGD("accept lease"); - if (!_dhcp_client_accept(self, priv->l3cd_curr, &error)) { - gs_free char *reason = g_strdup_printf("error accepting lease: %s", error->message); + if (!_dhcp_client_accept(self, priv->l3cd_curr, &error)) { + gs_free char *reason = g_strdup_printf("error accepting lease: %s", error->message); - _LOGD("accept failed: %s", error->message); + _LOGD("accept failed: %s", error->message); - _emit_notify(self, - &((NMDhcpClientNotifyData){ - .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_IT_LOOKS_BAD, - .it_looks_bad.reason = reason, - })); - goto wait_dhcp_commit_done; - } + _emit_notify(self, + &((NMDhcpClientNotifyData){ + .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_IT_LOOKS_BAD, + .it_looks_bad.reason = reason, + })); + goto wait_dhcp_commit_done; + } - if (priv->config.addr_family == AF_INET || !priv->l3cfg_notify.wait_ipv6_dad) { _emit_notify( self, &((NMDhcpClientNotifyData){.notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE, @@ -1368,8 +1417,8 @@ nm_dhcp_client_stop(NMDhcpClient *self, gboolean release) priv->is_stopped = TRUE; - if (NM_IS_IPv4(priv->config.addr_family) && priv->v4.bound.invocation) { - g_dbus_method_invocation_return_error(g_steal_pointer(&priv->v4.bound.invocation), + if (priv->invocation) { + g_dbus_method_invocation_return_error(g_steal_pointer(&priv->invocation), NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "dhcp stopping"); @@ -1528,7 +1577,6 @@ nm_dhcp_client_handle_event(gpointer unused, NMPlatformIP6Address prefix = { 0, }; - int IS_IPv4; g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE); g_return_val_if_fail(iface != NULL, FALSE); @@ -1625,16 +1673,13 @@ nm_dhcp_client_handle_event(gpointer unused, client_event_type = NM_DHCP_CLIENT_EVENT_TYPE_FAIL; } - IS_IPv4 = NM_IS_IPv4(priv->config.addr_family); - - if (IS_IPv4 && priv->v4.bound.invocation) - g_dbus_method_invocation_return_value(g_steal_pointer(&priv->v4.bound.invocation), NULL); + if (priv->invocation) + g_dbus_method_invocation_return_value(g_steal_pointer(&priv->invocation), NULL); - if (IS_IPv4 - && NM_IN_SET(client_event_type, - NM_DHCP_CLIENT_EVENT_TYPE_BOUND, - NM_DHCP_CLIENT_EVENT_TYPE_EXTENDED)) - priv->v4.bound.invocation = g_steal_pointer(&invocation); + if (NM_IN_SET(client_event_type, + NM_DHCP_CLIENT_EVENT_TYPE_BOUND, + NM_DHCP_CLIENT_EVENT_TYPE_EXTENDED)) + priv->invocation = g_steal_pointer(&invocation); _nm_dhcp_client_notify(self, client_event_type, l3cd); @@ -1785,10 +1830,6 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps * explicitly initialize the respective union member. */ if (NM_IS_IPv4(priv->config.addr_family)) { priv->v4 = (typeof(priv->v4)){ - .bound = - { - .invocation = NULL, - }, .acd = { .addr = INADDR_ANY, diff --git a/src/core/dhcp/nm-dhcp-helper.c b/src/core/dhcp/nm-dhcp-helper.c index 5a17f4e8ab..78db617c6a 100644 --- a/src/core/dhcp/nm-dhcp-helper.c +++ b/src/core/dhcp/nm-dhcp-helper.c @@ -114,6 +114,8 @@ main(int argc, char *argv[]) gint64 time_start; gint64 time_end; gint64 remaining_time; + gboolean IS_IPv4; + const char *reason; /* Connecting to the unix socket can fail with EAGAIN if there are too * many pending connections and the server can't accept them in time @@ -124,7 +126,19 @@ main(int argc, char *argv[]) time_end = time_start + (5000 * 1000L); try_count = 0; - _LOGi("nm-dhcp-helper: event called"); + reason = getenv("reason"); + + _LOGi("nm-dhcp-helper: event called: %s", reason); + + IS_IPv4 = !NM_IN_STRSET(reason, + "PREINIT6", + "BOUND6", + "RENEW6", + "REBIND6", + "DEPREF6", + "EXPIRE6", + "RELEASE6", + "STOP6"); do_connect: try_count++; @@ -244,5 +258,6 @@ out: } _LOGi("success: %s", success ? "YES" : "NO"); - return success ? EXIT_SUCCESS : EXIT_FAILURE; + /* The error code to send a decline depends on the address family */ + return success ? EXIT_SUCCESS : (IS_IPv4 ? 1 : 3); } |