From e38f0be7368db99d84472edec5adad6bf0248ab0 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 7 Jun 2022 09:08:21 +0200 Subject: [PATCH] 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 --- src/n-dhcp4-c-lease.c | 48 +++++---------------------------------- src/n-dhcp4-c-probe.c | 52 +++++++++++++++++++++++++++---------------- src/n-dhcp4-private.h | 1 + 3 files changed, 40 insertions(+), 61 deletions(-) diff --git a/src/n-dhcp4-c-lease.c b/src/n-dhcp4-c-lease.c index eaa962765..be0d78869 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 283c1693c..284aa428e 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); - break; + 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: 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 858c3d3ab..6b366884b 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 */