summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/n-dhcp4/src/n-dhcp4-c-probe.c15
-rw-r--r--src/n-dhcp4/src/n-dhcp4-private.h1
2 files changed, 14 insertions, 2 deletions
diff --git a/src/n-dhcp4/src/n-dhcp4-c-probe.c b/src/n-dhcp4/src/n-dhcp4-c-probe.c
index dcd51c6f3e..284aa428e9 100644
--- a/src/n-dhcp4/src/n-dhcp4-c-probe.c
+++ b/src/n-dhcp4/src/n-dhcp4-c-probe.c
@@ -1089,6 +1089,7 @@ 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);
@@ -1128,11 +1129,21 @@ 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;
+
+ /* 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:
diff --git a/src/n-dhcp4/src/n-dhcp4-private.h b/src/n-dhcp4/src/n-dhcp4-private.h
index 858c3d3ab0..6b366884be 100644
--- a/src/n-dhcp4/src/n-dhcp4-private.h
+++ b/src/n-dhcp4/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 */