summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2022-08-16 08:47:17 +0900
committerGitHub <noreply@github.com>2022-08-16 08:47:17 +0900
commit4f4e9104f3be3f0851a3ec95b247b161200b10c2 (patch)
tree336f395a81b8f29b9d63f1fee117466a08927942 /src
parentb23b11719d841cfcf471483e922b97e598a96e90 (diff)
parent4c275f362fa11888682dfbf6ec7c8cfd6127597f (diff)
downloadsystemd-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.c11
-rw-r--r--src/libsystemd-network/dhcp6-protocol.h1
-rw-r--r--src/libsystemd-network/fuzz-dhcp6-client.c2
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c33
-rw-r--r--src/libsystemd-network/sd-dhcp6-lease.c2
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) ? "" : ": ",