summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2022-06-07 09:08:21 +0200
committerThomas Haller <thaller@redhat.com>2022-06-07 09:08:21 +0200
commite38f0be7368db99d84472edec5adad6bf0248ab0 (patch)
treec3b015ee469fbd37749c4c3992dc04e67cf51ce4
parent3a49d158e035f7eb3258453f678e575da236e569 (diff)
downloadNetworkManager-e38f0be7368db99d84472edec5adad6bf0248ab0.tar.gz
Squashed 'src/n-dhcp4/' changes from e4af93228e37..7db7dc4bab53
7db7dc4bab53 probe: merge branch 'th/decline-fixes' bb61737788dd probe: fix internal state after declining lease c5d0f38ab7a9 probe: maintain the probe's lease list in "n-dhcp4-c-probe.c" 48bf2788336e probe: return error when calling accept/decline/select in unexpected state git-subtree-dir: src/n-dhcp4 git-subtree-split: 7db7dc4bab5312218135464d8550a86845ca6fdd
-rw-r--r--src/n-dhcp4-c-lease.c48
-rw-r--r--src/n-dhcp4-c-probe.c52
-rw-r--r--src/n-dhcp4-private.h1
3 files changed, 40 insertions, 61 deletions
diff --git a/src/n-dhcp4-c-lease.c b/src/n-dhcp4-c-lease.c
index eaa9627652..be0d78869b 100644
--- a/src/n-dhcp4-c-lease.c
+++ b/src/n-dhcp4-c-lease.c
@@ -351,32 +351,15 @@ _c_public_ int n_dhcp4_client_lease_query(NDhcp4ClientLease *lease, uint8_t opti
* selected none of the others can be.
*
* Return: 0 on success, or a negative error code on failure.
+ * Returns -ENOTRECOVERABLE when called in an unexpected state.
*/
_c_public_ int n_dhcp4_client_lease_select(NDhcp4ClientLease *lease) {
- NDhcp4ClientLease *l, *t_l;
- NDhcp4ClientProbe *probe;
- int r;
-
- /* XXX error handling, this must be an OFFER */
-
if (!lease->probe)
return -ENOTRECOVERABLE;
if (lease->probe->current_lease)
return -ENOTRECOVERABLE;
- r = n_dhcp4_client_probe_transition_select(lease->probe, lease->message, n_dhcp4_gettime(CLOCK_BOOTTIME));
- if (r)
- return r;
-
- /*
- * Only one of the offered leases can be selected, so flush the list.
- * All offered lease, including this one are now dead.
- */
- probe = lease->probe;
- c_list_for_each_entry_safe(l, t_l, &probe->lease_list, probe_link)
- n_dhcp4_client_lease_unlink(l);
-
- return 0;
+ return n_dhcp4_client_probe_transition_select(lease->probe, lease->message, n_dhcp4_gettime(CLOCK_BOOTTIME));
}
/**
@@ -390,24 +373,15 @@ _c_public_ int n_dhcp4_client_lease_select(NDhcp4ClientLease *lease) {
* can be accepted.
*
* Return: 0 on success, or a negative error code on failure.
+ * Returns -ENOTRECOVERABLE when called in an unexpected state.
*/
_c_public_ int n_dhcp4_client_lease_accept(NDhcp4ClientLease *lease) {
- int r;
-
- /* XXX error handling, this must be an ACK */
-
if (!lease->probe)
return -ENOTRECOVERABLE;
if (lease->probe->current_lease != lease)
return -ENOTRECOVERABLE;
- r = n_dhcp4_client_probe_transition_accept(lease->probe, lease->message);
- if (r)
- return r;
-
- n_dhcp4_client_lease_unlink(lease);
-
- return 0;
+ return n_dhcp4_client_probe_transition_accept(lease->probe, lease->message);
}
/**
@@ -421,23 +395,13 @@ _c_public_ int n_dhcp4_client_lease_accept(NDhcp4ClientLease *lease) {
* decline.
*
* Return: 0 on success, or a negative error code on failure.
+ * Returns -ENOTRECOVERABLE when called in an unexpected state.
*/
_c_public_ int n_dhcp4_client_lease_decline(NDhcp4ClientLease *lease, const char *error) {
- int r;
-
- /* XXX: error handling, this must be an ACK */
-
if (!lease->probe)
return -ENOTRECOVERABLE;
if (lease->probe->current_lease != lease)
return -ENOTRECOVERABLE;
- r = n_dhcp4_client_probe_transition_decline(lease->probe, lease->message, error, n_dhcp4_gettime(CLOCK_BOOTTIME));
- if (r)
- return r;
-
- lease->probe->current_lease = n_dhcp4_client_lease_unref(lease->probe->current_lease);
- n_dhcp4_client_lease_unlink(lease);
-
- return 0;
+ return n_dhcp4_client_probe_transition_decline(lease->probe, lease->message, error, n_dhcp4_gettime(CLOCK_BOOTTIME));
}
diff --git a/src/n-dhcp4-c-probe.c b/src/n-dhcp4-c-probe.c
index 283c1693cf..284aa428e9 100644
--- a/src/n-dhcp4-c-probe.c
+++ b/src/n-dhcp4-c-probe.c
@@ -1024,6 +1024,7 @@ static int n_dhcp4_client_probe_transition_nak(NDhcp4ClientProbe *probe) {
int n_dhcp4_client_probe_transition_select(NDhcp4ClientProbe *probe, NDhcp4Incoming *offer, uint64_t ns_now) {
_c_cleanup_(n_dhcp4_outgoing_freep) NDhcp4Outgoing *request = NULL;
+ NDhcp4ClientLease *l, *t_l;
int r;
switch (probe->state) {
@@ -1042,11 +1043,16 @@ int n_dhcp4_client_probe_transition_select(NDhcp4ClientProbe *probe, NDhcp4Incom
else
request = NULL; /* consumed */
- /* XXX: ignore other offers */
-
probe->state = N_DHCP4_CLIENT_PROBE_STATE_REQUESTING;
- break;
+ /*
+ * Only one of the offered leases can be selected, so flush the list.
+ * All offered lease, including this one are now dead.
+ */
+ c_list_for_each_entry_safe(l, t_l, &probe->lease_list, probe_link)
+ n_dhcp4_client_lease_unlink(l);
+
+ return 0;
case N_DHCP4_CLIENT_PROBE_STATE_INIT:
case N_DHCP4_CLIENT_PROBE_STATE_INIT_REBOOT:
case N_DHCP4_CLIENT_PROBE_STATE_REBOOTING:
@@ -1057,11 +1063,9 @@ int n_dhcp4_client_probe_transition_select(NDhcp4ClientProbe *probe, NDhcp4Incom
case N_DHCP4_CLIENT_PROBE_STATE_REBINDING:
case N_DHCP4_CLIENT_PROBE_STATE_EXPIRED:
default:
- /* ignore */
- break;
+ /* user called in invalid state. Return error. */
+ return -ENOTRECOVERABLE;
}
-
- return 0;
}
/**
@@ -1085,10 +1089,11 @@ int n_dhcp4_client_probe_transition_accept(NDhcp4ClientProbe *probe, NDhcp4Incom
return r;
probe->state = N_DHCP4_CLIENT_PROBE_STATE_BOUND;
-
+ probe->ns_decline_restart_delay = 0;
+ n_dhcp4_client_lease_unlink(probe->current_lease);
n_dhcp4_client_arm_timer(probe->client);
- break;
+ return 0;
case N_DHCP4_CLIENT_PROBE_STATE_INIT:
case N_DHCP4_CLIENT_PROBE_STATE_INIT_REBOOT:
@@ -1100,11 +1105,9 @@ int n_dhcp4_client_probe_transition_accept(NDhcp4ClientProbe *probe, NDhcp4Incom
case N_DHCP4_CLIENT_PROBE_STATE_REBINDING:
case N_DHCP4_CLIENT_PROBE_STATE_EXPIRED:
default:
- /* ignore */
- break;
+ /* user called in invalid state. Return error. */
+ return -ENOTRECOVERABLE;
}
-
- return 0;
}
/**
@@ -1126,9 +1129,22 @@ int n_dhcp4_client_probe_transition_decline(NDhcp4ClientProbe *probe, NDhcp4Inco
else
request = NULL; /* consumed */
- /* XXX: what state to transition to? */
+ n_dhcp4_client_lease_unlink(probe->current_lease);
+ probe->current_lease = n_dhcp4_client_lease_unref(probe->current_lease);
+
+ probe->state = N_DHCP4_CLIENT_PROBE_STATE_INIT;
- break;
+ /* RFC2131, 3.1, 5.) The client SHOULD wait a minimum of ten seconds before restarting
+ * the configuration process to avoid excessive network traffic in case of looping.
+ *
+ * Let's go beyond that, and use an exponential backoff. */
+ probe->ns_decline_restart_delay = C_CLAMP(probe->ns_decline_restart_delay * 2u,
+ UINT64_C(10) * UINT64_C(1000000000),
+ UINT64_C(300) * UINT64_C(1000000000));
+ probe->ns_deferred = n_dhcp4_gettime(CLOCK_BOOTTIME) + probe->ns_decline_restart_delay;
+
+ n_dhcp4_client_arm_timer(probe->client);
+ return 0;
case N_DHCP4_CLIENT_PROBE_STATE_INIT:
case N_DHCP4_CLIENT_PROBE_STATE_INIT_REBOOT:
@@ -1140,11 +1156,9 @@ int n_dhcp4_client_probe_transition_decline(NDhcp4ClientProbe *probe, NDhcp4Inco
case N_DHCP4_CLIENT_PROBE_STATE_REBINDING:
case N_DHCP4_CLIENT_PROBE_STATE_EXPIRED:
default:
- /* ignore */
- break;
+ /* user called in invalid state. Return error. */
+ return -ENOTRECOVERABLE;
}
-
- return 0;
}
/**
diff --git a/src/n-dhcp4-private.h b/src/n-dhcp4-private.h
index 858c3d3ab0..6b366884be 100644
--- a/src/n-dhcp4-private.h
+++ b/src/n-dhcp4-private.h
@@ -378,6 +378,7 @@ struct NDhcp4ClientProbe {
uint64_t ns_deferred; /* timeout for deferred action */
uint64_t ns_reinit;
uint64_t ns_nak_restart_delay; /* restart delay after a nak */
+ uint64_t ns_decline_restart_delay; /* restart delay after a decline */
NDhcp4ClientLease *current_lease; /* current lease */
NDhcp4CConnection connection; /* client connection wrapper */