diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index b7896fdc0b..45170d31ba 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -11617,7 +11617,7 @@ _dev_ipdhcpx_start(NMDevice *self, int addr_family) /* Take the NML3ConfigData from the previous lease (if any) that was passed to the NMDhcpClient. * This may be the old lease only used during the duration of a reapply until we get the * new lease. */ - previous_lease = nm_dhcp_client_get_lease(priv->ipdhcp_data_x[IS_IPv4].client); + previous_lease = nm_dhcp_client_get_lease(priv->ipdhcp_data_x[IS_IPv4].client, TRUE); if (!priv->ipdhcp_data_x[IS_IPv4].config) { priv->ipdhcp_data_x[IS_IPv4].config = nm_dhcp_config_new(addr_family, previous_lease); diff --git a/src/core/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c index f50a8e9fda..18ad4024b4 100644 --- a/src/core/dhcp/nm-dhcp-client.c +++ b/src/core/dhcp/nm-dhcp-client.c @@ -280,10 +280,25 @@ nm_dhcp_client_create_options_dict(NMDhcpClient *self, gboolean static_keys) return options; } +/** + * nm_dhcp_client_get_lease(): + * @self: the client + * @ignore_acd_pending: FALSE means to only return the lease that already + * passed ACD, thus it is in use by us. TRUE means to return a new lease + * that might still be pending of Address Collision Detection (ACD) check, + * if there is one, or return the current lease that passed ACD if not. + * + * Returns the current lease that passed ACD or a pending lease still under + * ACD check. + * + */ const NML3ConfigData * -nm_dhcp_client_get_lease(NMDhcpClient *self) +nm_dhcp_client_get_lease(NMDhcpClient *self, gboolean ignore_acd_pending) { - return NM_DHCP_CLIENT_GET_PRIVATE(self)->l3cd_curr; + if (ignore_acd_pending) + return NM_DHCP_CLIENT_GET_PRIVATE(self)->l3cd_curr; + else + return NM_DHCP_CLIENT_GET_PRIVATE(self)->l3cd_next; } /*****************************************************************************/ diff --git a/src/core/dhcp/nm-dhcp-client.h b/src/core/dhcp/nm-dhcp-client.h index 431d08f383..f26d88d86f 100644 --- a/src/core/dhcp/nm-dhcp-client.h +++ b/src/core/dhcp/nm-dhcp-client.h @@ -246,7 +246,7 @@ const NMDhcpClientConfig *nm_dhcp_client_get_config(NMDhcpClient *self); pid_t nm_dhcp_client_get_pid(NMDhcpClient *self); -const NML3ConfigData *nm_dhcp_client_get_lease(NMDhcpClient *self); +const NML3ConfigData *nm_dhcp_client_get_lease(NMDhcpClient *self, gboolean ignore_acd_pending); void nm_dhcp_client_stop(NMDhcpClient *self, gboolean release); diff --git a/src/core/dhcp/nm-dhcp-nettools.c b/src/core/dhcp/nm-dhcp-nettools.c index 61490fb662..27bb136b0a 100644 --- a/src/core/dhcp/nm-dhcp-nettools.c +++ b/src/core/dhcp/nm-dhcp-nettools.c @@ -1542,7 +1542,10 @@ stop(NMDhcpClient *client, gboolean release) NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self); if (release) { - if (n_dhcp4_client_probe_release(priv->probe)) + /* After we receive a lease from server, it doesn't matter if we completed ACD, + * we should send the release message. */ + if (nm_dhcp_client_get_lease(client, FALSE) + && n_dhcp4_client_probe_release(priv->probe) < 0) _LOGT("dhcp-client4: failed to send request with RELEASE message"); } diff --git a/src/n-dhcp4/src/n-dhcp4-c-connection.c b/src/n-dhcp4/src/n-dhcp4-c-connection.c index 7024b71ac9..e76ea16592 100644 --- a/src/n-dhcp4/src/n-dhcp4-c-connection.c +++ b/src/n-dhcp4/src/n-dhcp4-c-connection.c @@ -1010,9 +1010,9 @@ static const char *message_type_to_str(uint8_t type) { } } -static int n_dhcp4_c_connection_send_request(NDhcp4CConnection *connection, - NDhcp4Outgoing *request, - uint64_t timestamp) { +int n_dhcp4_c_connection_send_request(NDhcp4CConnection *connection, + NDhcp4Outgoing *request, + uint64_t timestamp) { char server_addr[INET_ADDRSTRLEN]; char client_addr[INET_ADDRSTRLEN]; char error_msg[128]; diff --git a/src/n-dhcp4/src/n-dhcp4-c-probe.c b/src/n-dhcp4/src/n-dhcp4-c-probe.c index ee3a8886bd..7a6def340c 100644 --- a/src/n-dhcp4/src/n-dhcp4-c-probe.c +++ b/src/n-dhcp4/src/n-dhcp4-c-probe.c @@ -1137,7 +1137,7 @@ int n_dhcp4_client_probe_transition_decline(NDhcp4ClientProbe *probe, NDhcp4Inco if (r) return r; - r = n_dhcp4_c_connection_start_request(&probe->connection, request, ns_now); + r = n_dhcp4_c_connection_send_request(&probe->connection, request, ns_now); if (r) return r; else @@ -1332,11 +1332,15 @@ int n_dhcp4_client_probe_release(NDhcp4ClientProbe *probe) { _c_cleanup_(n_dhcp4_outgoing_freep) NDhcp4Outgoing *request_out = NULL; int r; + if (probe->connection.state != N_DHCP4_C_CONNECTION_STATE_DRAINING + && probe->connection.state != N_DHCP4_C_CONNECTION_STATE_UDP) + return -ENOTRECOVERABLE; + r = n_dhcp4_c_connection_release_new(&probe->connection, &request_out, NULL); if (r) return r; - r = n_dhcp4_c_connection_start_request(&probe->connection, request_out, 0); + r = n_dhcp4_c_connection_send_request(&probe->connection, request_out, 0); if (r) return r; diff --git a/src/n-dhcp4/src/n-dhcp4-private.h b/src/n-dhcp4/src/n-dhcp4-private.h index 40404001a8..dbfe9b4ad0 100644 --- a/src/n-dhcp4/src/n-dhcp4-private.h +++ b/src/n-dhcp4/src/n-dhcp4-private.h @@ -642,6 +642,9 @@ int n_dhcp4_c_connection_release_new(NDhcp4CConnection *connection, int n_dhcp4_c_connection_start_request(NDhcp4CConnection *connection, NDhcp4Outgoing *request, uint64_t timestamp); +int n_dhcp4_c_connection_send_request(NDhcp4CConnection *connection, + NDhcp4Outgoing *request, + uint64_t timestamp); int n_dhcp4_c_connection_dispatch_timer(NDhcp4CConnection *connection, uint64_t timestamp); int n_dhcp4_c_connection_dispatch_io(NDhcp4CConnection *connection,