diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2022-08-16 08:47:17 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-16 08:47:17 +0900 |
commit | 4f4e9104f3be3f0851a3ec95b247b161200b10c2 (patch) | |
tree | 336f395a81b8f29b9d63f1fee117466a08927942 /src | |
parent | b23b11719d841cfcf471483e922b97e598a96e90 (diff) | |
parent | 4c275f362fa11888682dfbf6ec7c8cfd6127597f (diff) | |
download | systemd-4f4e9104f3be3f0851a3ec95b247b161200b10c2.tar.gz |
Merge pull request #24299 from yuwata/dhcp6-no-binding
dhcp6: gracefully handle NoBinding error
Diffstat (limited to 'src')
-rw-r--r-- | src/libsystemd-network/dhcp6-protocol.c | 11 | ||||
-rw-r--r-- | src/libsystemd-network/dhcp6-protocol.h | 1 | ||||
-rw-r--r-- | src/libsystemd-network/fuzz-dhcp6-client.c | 2 | ||||
-rw-r--r-- | src/libsystemd-network/sd-dhcp6-client.c | 33 | ||||
-rw-r--r-- | src/libsystemd-network/sd-dhcp6-lease.c | 2 |
5 files changed, 42 insertions, 7 deletions
diff --git a/src/libsystemd-network/dhcp6-protocol.c b/src/libsystemd-network/dhcp6-protocol.c index c399a7ac50..f965ea40fe 100644 --- a/src/libsystemd-network/dhcp6-protocol.c +++ b/src/libsystemd-network/dhcp6-protocol.c @@ -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; + } +} diff --git a/src/libsystemd-network/dhcp6-protocol.h b/src/libsystemd-network/dhcp6-protocol.h index f4e47857e3..18217691b7 100644 --- a/src/libsystemd-network/dhcp6-protocol.h +++ b/src/libsystemd-network/dhcp6-protocol.h @@ -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); diff --git a/src/libsystemd-network/fuzz-dhcp6-client.c b/src/libsystemd-network/fuzz-dhcp6-client.c index 3b53c5c6a8..a1c34365c0 100644 --- a/src/libsystemd-network/fuzz-dhcp6-client.c +++ b/src/libsystemd-network/fuzz-dhcp6-client.c @@ -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(); diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 273dd35e04..2611490067 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -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"); diff --git a/src/libsystemd-network/sd-dhcp6-lease.c b/src/libsystemd-network/sd-dhcp6-lease.c index f588514cb6..57c23965ed 100644 --- a/src/libsystemd-network/sd-dhcp6-lease.c +++ b/src/libsystemd-network/sd-dhcp6-lease.c @@ -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) ? "" : ": ", |