diff options
Diffstat (limited to 'src/n-dhcp4')
| -rw-r--r-- | src/n-dhcp4/src/n-dhcp4-c-lease.c | 64 | ||||
| -rw-r--r-- | src/n-dhcp4/src/n-dhcp4-c-probe.c | 52 | ||||
| -rw-r--r-- | src/n-dhcp4/src/n-dhcp4-client.c | 4 | ||||
| -rw-r--r-- | src/n-dhcp4/src/n-dhcp4-private.h | 1 |
4 files changed, 50 insertions, 71 deletions
diff --git a/src/n-dhcp4/src/n-dhcp4-c-lease.c b/src/n-dhcp4/src/n-dhcp4-c-lease.c index bae2f674..be0d7886 100644 --- a/src/n-dhcp4/src/n-dhcp4-c-lease.c +++ b/src/n-dhcp4/src/n-dhcp4-c-lease.c @@ -251,7 +251,7 @@ _c_public_ void n_dhcp4_client_lease_get_lifetime(NDhcp4ClientLease *lease, uint * * Return: 0 on success, * N_DHCP4_E_UNSET if the lease doesn't contain a server-identifier, or - * N_DCHP4_E_INTERNAL if the server-identifier is not valid. + * N_DHCP4_E_INTERNAL if the server-identifier is not valid. */ _c_public_ int n_dhcp4_client_lease_get_server_identifier(NDhcp4ClientLease *lease, struct in_addr *addr) { uint8_t *data; @@ -279,25 +279,25 @@ _c_public_ int n_dhcp4_client_lease_get_server_identifier(NDhcp4ClientLease *lea * * Return: 0 on success, * N_DHCP4_E_UNSET if the lease does not contain a file name, or - * N_DCHP4_E_INTERNAL if the file name is invalid. + * N_DHCP4_E_INTERNAL if the file name is invalid. */ _c_public_ int n_dhcp4_client_lease_get_file(NDhcp4ClientLease *lease, const char **file) { NDhcp4Message *message; if (lease->message->options[N_DHCP4_OPTION_OVERLOAD].size > 0 && ((*lease->message->options[N_DHCP4_OPTION_OVERLOAD].value) & N_DHCP4_OVERLOAD_FILE)) { - /* The field is overloaded to contain other options */ - return N_DHCP4_E_UNSET; + /* The field is overloaded to contain other options */ + return N_DHCP4_E_UNSET; } message = &lease->message->message; if (message->file[0] == '\0') - return N_DHCP4_E_UNSET; + return N_DHCP4_E_UNSET; if (!memchr(message->file, '\0', sizeof(message->file))) { - /* The field is NULL-terminated (RFC 2131 section 2) */ - return N_DHCP4_E_INTERNAL; + /* The field is NULL-terminated (RFC 2131 section 2) */ + return N_DHCP4_E_INTERNAL; } *file = (const char *) message->file; @@ -316,7 +316,7 @@ _c_public_ int n_dhcp4_client_lease_get_file(NDhcp4ClientLease *lease, const cha * be queried, and only options that were explicitly requested can be queried. * * Return: 0 on success, - * N_DCHP4_E_INTERNAL if an invalid option is queried, + * N_DHCP4_E_INTERNAL if an invalid option is queried, * N_DHCP4_E_UNSET if the lease did not contain the option, or * a negative error code on failure. */ @@ -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/src/n-dhcp4-c-probe.c b/src/n-dhcp4/src/n-dhcp4-c-probe.c index 283c1693..284aa428 100644 --- a/src/n-dhcp4/src/n-dhcp4-c-probe.c +++ b/src/n-dhcp4/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/src/n-dhcp4-client.c b/src/n-dhcp4/src/n-dhcp4-client.c index 1dedbf30..3b4a70c8 100644 --- a/src/n-dhcp4/src/n-dhcp4-client.c +++ b/src/n-dhcp4/src/n-dhcp4-client.c @@ -214,8 +214,8 @@ _c_public_ void n_dhcp4_client_config_set_mac(NDhcp4ClientConfig *config, const _c_public_ void n_dhcp4_client_config_set_broadcast_mac(NDhcp4ClientConfig *config, const uint8_t *mac, size_t n_mac) { config->n_broadcast_mac = n_mac; - if (n_mac > sizeof(config->mac)) - n_mac = sizeof(config->mac); + if (n_mac > sizeof(config->broadcast_mac)) + n_mac = sizeof(config->broadcast_mac); memcpy(config->broadcast_mac, mac, n_mac); } diff --git a/src/n-dhcp4/src/n-dhcp4-private.h b/src/n-dhcp4/src/n-dhcp4-private.h index 858c3d3a..6b366884 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 */ |