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
This commit is contained in:
Thomas Haller 2022-06-07 09:08:21 +02:00
parent 3a49d158e0
commit e38f0be736
3 changed files with 40 additions and 61 deletions

View file

@ -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));
}

View file

@ -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;
}
/**

View file

@ -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 */