dhcp: introduce EXTENDED state for renewals

Currently the DHCP client reports the BOUND state not only when the
lease is obtained initially but also when it is renewed. Having a
different state for the renewal will be used by NMDevice in the next
patch to determine whether the lease needs to be accept()ed or not.

(cherry picked from commit a4ddb56923)
This commit is contained in:
Beniamino Galvani 2020-01-28 15:45:51 +01:00
parent a01198863a
commit 5182ca8782
6 changed files with 31 additions and 22 deletions

View file

@ -7900,6 +7900,7 @@ dhcp4_state_changed (NMDhcpClient *client,
switch (state) {
case NM_DHCP_STATE_BOUND:
case NM_DHCP_STATE_EXTENDED:
if (!ip4_config) {
_LOGW (LOGD_DHCP4, "failed to get IPv4 config in response to DHCP event.");
dhcp4_fail (self, state);
@ -8694,6 +8695,7 @@ dhcp6_state_changed (NMDhcpClient *client,
switch (state) {
case NM_DHCP_STATE_BOUND:
case NM_DHCP_STATE_EXTENDED:
nm_clear_g_source (&priv->dhcp6.grace_id);
/* If the server sends multiple IPv6 addresses, we receive a state
* changed event for each of them. Use the event ID to merge IPv6

View file

@ -317,6 +317,7 @@ nm_dhcp_client_get_use_fqdn (NMDhcpClient *self)
static const char *state_table[NM_DHCP_STATE_MAX + 1] = {
[NM_DHCP_STATE_UNKNOWN] = "unknown",
[NM_DHCP_STATE_BOUND] = "bound",
[NM_DHCP_STATE_EXTENDED] = "extended",
[NM_DHCP_STATE_TIMEOUT] = "timeout",
[NM_DHCP_STATE_EXPIRE] = "expire",
[NM_DHCP_STATE_DONE] = "done",
@ -336,13 +337,14 @@ static NMDhcpState
reason_to_state (NMDhcpClient *self, const char *iface, const char *reason)
{
if (g_ascii_strcasecmp (reason, "bound") == 0 ||
g_ascii_strcasecmp (reason, "bound6") == 0 ||
g_ascii_strcasecmp (reason, "renew") == 0 ||
g_ascii_strcasecmp (reason, "renew6") == 0 ||
g_ascii_strcasecmp (reason, "reboot") == 0 ||
g_ascii_strcasecmp (reason, "rebind") == 0 ||
g_ascii_strcasecmp (reason, "rebind6") == 0)
g_ascii_strcasecmp (reason, "bound6") == 0)
return NM_DHCP_STATE_BOUND;
else if (g_ascii_strcasecmp (reason, "renew") == 0 ||
g_ascii_strcasecmp (reason, "renew6") == 0 ||
g_ascii_strcasecmp (reason, "reboot") == 0 ||
g_ascii_strcasecmp (reason, "rebind") == 0 ||
g_ascii_strcasecmp (reason, "rebind6") == 0)
return NM_DHCP_STATE_EXTENDED;
else if (g_ascii_strcasecmp (reason, "timeout") == 0)
return NM_DHCP_STATE_TIMEOUT;
else if (g_ascii_strcasecmp (reason, "nak") == 0 ||
@ -415,7 +417,7 @@ nm_dhcp_client_set_state (NMDhcpClient *self,
NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
gs_free char *event_id = NULL;
if (new_state == NM_DHCP_STATE_BOUND) {
if (NM_IN_SET (new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED)) {
g_return_if_fail (NM_IS_IP_CONFIG (ip_config, priv->addr_family));
g_return_if_fail (options);
} else {
@ -430,10 +432,11 @@ nm_dhcp_client_set_state (NMDhcpClient *self,
/* The client may send same-state transitions for RENEW/REBIND events and
* the lease may have changed, so handle same-state transitions for the
* BOUND state. Ignore same-state transitions for other events since
* the lease won't have changed and the state was already handled.
* EXTENDED and BOUND states. Ignore same-state transitions for other
* events since the lease won't have changed and the state was already handled.
*/
if ((priv->state == new_state) && (new_state != NM_DHCP_STATE_BOUND))
if ( (priv->state == new_state)
&& !NM_IN_SET (new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED))
return;
if (_LOGI_ENABLED ()) {
@ -448,7 +451,7 @@ nm_dhcp_client_set_state (NMDhcpClient *self,
}
if ( priv->addr_family == AF_INET6
&& new_state == NM_DHCP_STATE_BOUND) {
&& NM_IN_SET (new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED)) {
char *start, *iaid;
iaid = g_hash_table_lookup (options, "iaid");
@ -877,7 +880,7 @@ nm_dhcp_client_handle_event (gpointer unused,
_LOGD ("DHCP state '%s' -> '%s' (reason: '%s')",
state_to_string (old_state), state_to_string (new_state), reason);
if (new_state == NM_DHCP_STATE_BOUND) {
if (NM_IN_SET (new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED)) {
GVariantIter iter;
const char *name;
GVariant *value;
@ -918,7 +921,7 @@ nm_dhcp_client_handle_event (gpointer unused,
nm_dhcp_client_emit_ipv6_prefix_delegated (self, &prefix);
} else {
/* Fail if no valid IP config was received */
if ( new_state == NM_DHCP_STATE_BOUND
if ( NM_IN_SET (new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED)
&& !ip_config) {
_LOGW ("client bound but IP config not received");
new_state = NM_DHCP_STATE_FAIL;

View file

@ -43,7 +43,8 @@
typedef enum {
NM_DHCP_STATE_UNKNOWN = 0,
NM_DHCP_STATE_BOUND, /* new lease or lease changed */
NM_DHCP_STATE_BOUND, /* new lease */
NM_DHCP_STATE_EXTENDED, /* lease extended */
NM_DHCP_STATE_TIMEOUT, /* timed out contacting server */
NM_DHCP_STATE_DONE, /* client quit or stopped */
NM_DHCP_STATE_EXPIRE, /* lease expired or NAKed */

View file

@ -977,7 +977,7 @@ lease_save (NMDhcpNettools *self, NDhcp4ClientLease *lease, const char *lease_fi
}
static void
bound4_handle (NMDhcpNettools *self, NDhcp4ClientLease *lease)
bound4_handle (NMDhcpNettools *self, NDhcp4ClientLease *lease, gboolean extended)
{
NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE (self);
const char *iface = nm_dhcp_client_get_iface (NM_DHCP_CLIENT (self));
@ -985,7 +985,7 @@ bound4_handle (NMDhcpNettools *self, NDhcp4ClientLease *lease)
gs_unref_hashtable GHashTable *options = NULL;
GError *error = NULL;
_LOGT ("lease available");
_LOGT ("lease available (%s)", extended ? "extended" : "new");
ip4_config = lease_to_ip4_config (nm_dhcp_client_get_multi_idx (NM_DHCP_CLIENT (self)),
iface,
@ -1006,7 +1006,7 @@ bound4_handle (NMDhcpNettools *self, NDhcp4ClientLease *lease)
lease_save (self, lease, priv->lease_file);
nm_dhcp_client_set_state (NM_DHCP_CLIENT (self),
NM_DHCP_STATE_BOUND,
extended ? NM_DHCP_STATE_EXTENDED : NM_DHCP_STATE_BOUND,
NM_IP_CONFIG_CAST (ip4_config),
options);
}
@ -1037,10 +1037,10 @@ dhcp4_event_handle (NMDhcpNettools *self,
break;
case N_DHCP4_CLIENT_EVENT_GRANTED:
priv->lease = n_dhcp4_client_lease_ref (event->granted.lease);
bound4_handle (self, event->granted.lease);
bound4_handle (self, event->granted.lease, FALSE);
break;
case N_DHCP4_CLIENT_EVENT_EXTENDED:
bound4_handle (self, event->extended.lease);
bound4_handle (self, event->extended.lease, TRUE);
break;
case N_DHCP4_CLIENT_EVENT_DOWN:
/* ignore down events, they are purely informational */

View file

@ -477,7 +477,7 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
/*****************************************************************************/
static void
bound4_handle (NMDhcpSystemd *self)
bound4_handle (NMDhcpSystemd *self, gboolean extended)
{
NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (self);
const char *iface = nm_dhcp_client_get_iface (NM_DHCP_CLIENT (self));
@ -514,7 +514,7 @@ bound4_handle (NMDhcpSystemd *self)
dhcp_lease_save (lease, priv->lease_file);
nm_dhcp_client_set_state (NM_DHCP_CLIENT (self),
NM_DHCP_STATE_BOUND,
extended ? NM_DHCP_STATE_EXTENDED : NM_DHCP_STATE_BOUND,
NM_IP_CONFIG_CAST (ip4_config),
options);
}
@ -538,8 +538,10 @@ dhcp_event_cb (sd_dhcp_client *client, int event, gpointer user_data)
break;
case SD_DHCP_CLIENT_EVENT_RENEW:
case SD_DHCP_CLIENT_EVENT_IP_CHANGE:
bound4_handle (self, TRUE);
break;
case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE:
bound4_handle (self);
bound4_handle (self, FALSE);
break;
case SD_DHCP_CLIENT_EVENT_SELECTING:
break;

View file

@ -106,6 +106,7 @@ dhcp4_state_changed (NMDhcpClient *client,
switch (state) {
case NM_DHCP_STATE_BOUND:
case NM_DHCP_STATE_EXTENDED:
g_assert (ip4_config);
g_assert (nm_ip4_config_get_ifindex (ip4_config) == gl.ifindex);