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.
This commit is contained in:
Beniamino Galvani 2020-01-28 15:45:51 +01:00
parent 182a8021f3
commit a4ddb56923
6 changed files with 31 additions and 22 deletions

View file

@ -7926,6 +7926,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);
@ -8720,6 +8721,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

@ -976,7 +976,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));
@ -984,7 +984,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,
@ -1005,7 +1005,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);
}
@ -1036,10 +1036,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);