Merge pull request #24299 from yuwata/dhcp6-no-binding

dhcp6: gracefully handle NoBinding error
This commit is contained in:
Yu Watanabe 2022-08-16 08:47:17 +09:00 committed by GitHub
commit 4f4e9104f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 42 additions and 7 deletions

View file

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

View file

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

View file

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

View file

@ -543,13 +543,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,
@ -566,6 +562,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,
@ -684,6 +690,9 @@ static int client_append_oro(sd_dhcp6_client *client, uint8_t **opt, size_t *opt
req_opts = client->req_opts;
}
if (n == 0)
return 0;
return dhcp6_option_append(opt, optlen, SD_DHCP6_OPTION_ORO, n * sizeof(be16_t), req_opts);
}
@ -1133,6 +1142,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");

View file

@ -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) ? "" : ": ",