mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-03-08 20:58:20 +03:00
dhcp6: gracefully handle NoBinding error
When we receive NoBinding status code, the requesting binding (address or any other information) does not exist anymore in the server. Hence, resending the request is meaningless. Let's restart the transaction from the beginning in that case. (cherry picked from commit 1929c1fcb2f305206c01a6fc79cd038d6d9615f5)
This commit is contained in:
parent
c67a388aef
commit
97474b03e7
@ -82,3 +82,14 @@ static const char * const dhcp6_message_status_table[_DHCP6_STATUS_MAX] = {
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, DHCP6Status);
|
||||
|
||||
int dhcp6_message_status_to_errno(DHCP6Status s) {
|
||||
switch (s) {
|
||||
case DHCP6_STATUS_SUCCESS:
|
||||
return 0;
|
||||
case DHCP6_STATUS_NO_BINDING:
|
||||
return -EADDRNOTAVAIL;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
@ -154,3 +154,4 @@ const char *dhcp6_message_type_to_string(DHCP6MessageType s) _const_;
|
||||
DHCP6MessageType dhcp6_message_type_from_string(const char *s) _pure_;
|
||||
const char *dhcp6_message_status_to_string(DHCP6Status s) _const_;
|
||||
DHCP6Status dhcp6_message_status_from_string(const char *s) _pure_;
|
||||
int dhcp6_message_status_to_errno(DHCP6Status s);
|
||||
|
@ -48,7 +48,7 @@ static void fuzz_client(sd_dhcp6_client *client, const uint8_t *data, size_t siz
|
||||
assert_se(IN_SET(client->state, DHCP6_STATE_REQUEST, DHCP6_STATE_BOUND));
|
||||
break;
|
||||
case DHCP6_STATE_REQUEST:
|
||||
assert_se(client->state == DHCP6_STATE_BOUND);
|
||||
assert_se(IN_SET(client->state, DHCP6_STATE_BOUND, DHCP6_STATE_SOLICITATION));
|
||||
break;
|
||||
default:
|
||||
assert_not_reached();
|
||||
|
@ -536,13 +536,9 @@ static void client_notify(sd_dhcp6_client *client, int event) {
|
||||
client->callback(client, event, client->userdata);
|
||||
}
|
||||
|
||||
static void client_stop(sd_dhcp6_client *client, int error) {
|
||||
DHCP6_CLIENT_DONT_DESTROY(client);
|
||||
|
||||
static void client_cleanup(sd_dhcp6_client *client) {
|
||||
assert(client);
|
||||
|
||||
client_notify(client, error);
|
||||
|
||||
client->lease = sd_dhcp6_lease_unref(client->lease);
|
||||
|
||||
/* Reset IRT here. Otherwise, we cannot restart the client in the information requesting mode,
|
||||
@ -559,6 +555,16 @@ static void client_stop(sd_dhcp6_client *client, int error) {
|
||||
client_set_state(client, DHCP6_STATE_STOPPED);
|
||||
}
|
||||
|
||||
static void client_stop(sd_dhcp6_client *client, int error) {
|
||||
DHCP6_CLIENT_DONT_DESTROY(client);
|
||||
|
||||
assert(client);
|
||||
|
||||
client_notify(client, error);
|
||||
|
||||
client_cleanup(client);
|
||||
}
|
||||
|
||||
static int client_append_common_options_in_managed_mode(
|
||||
sd_dhcp6_client *client,
|
||||
uint8_t **opt,
|
||||
@ -1124,6 +1130,20 @@ static int client_process_reply(
|
||||
return log_invalid_message_type(client, message);
|
||||
|
||||
r = dhcp6_lease_new_from_message(client, message, len, timestamp, server_address, &lease);
|
||||
if (r == -EADDRNOTAVAIL) {
|
||||
|
||||
/* If NoBinding status code is received, we cannot request the address anymore.
|
||||
* Let's restart transaction from the beginning. */
|
||||
|
||||
if (client->state == DHCP6_STATE_REQUEST)
|
||||
/* The lease is not acquired yet, hence it is not necessary to notify the restart. */
|
||||
client_cleanup(client);
|
||||
else
|
||||
/* We need to notify the previous lease was expired. */
|
||||
client_stop(client, SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE);
|
||||
|
||||
return client_start_transaction(client, DHCP6_STATE_SOLICITATION);
|
||||
}
|
||||
if (r < 0)
|
||||
return log_dhcp6_client_errno(client, r, "Failed to process received reply message, ignoring: %m");
|
||||
|
||||
|
@ -512,7 +512,7 @@ static int dhcp6_lease_parse_message(
|
||||
return log_dhcp6_client_errno(client, r, "Failed to parse status code: %m");
|
||||
|
||||
if (r > 0)
|
||||
return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
|
||||
return log_dhcp6_client_errno(client, dhcp6_message_status_to_errno(r),
|
||||
"Received %s message with non-zero status: %s%s%s",
|
||||
dhcp6_message_type_to_string(message->type),
|
||||
strempty(msg), isempty(msg) ? "" : ": ",
|
||||
|
Loading…
x
Reference in New Issue
Block a user