summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2021-02-22 22:39:31 +0900
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-03-12 17:35:57 +0100
commitd2cda53bcb814b4c5973fa3da4fbc2e75bbd0b1d (patch)
treea46506b816976705b6c44daf0affcb58b5ac884a
parent78b39de4444598f47ecc04e9c4ee6073b43a991b (diff)
downloadsystemd-d2cda53bcb814b4c5973fa3da4fbc2e75bbd0b1d.tar.gz
dhcp6: do not set T1 and T2 by dhcp6_option_append_pd() in client
Fixes #18090. (cherry picked from commit 73b49d433c2c8e6304c8b82538bd4231d070fce4)
-rw-r--r--src/libsystemd-network/dhcp6-internal.h2
-rw-r--r--src/libsystemd-network/dhcp6-option.c129
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c15
3 files changed, 88 insertions, 58 deletions
diff --git a/src/libsystemd-network/dhcp6-internal.h b/src/libsystemd-network/dhcp6-internal.h
index 9a32b007fc..681c462315 100644
--- a/src/libsystemd-network/dhcp6-internal.h
+++ b/src/libsystemd-network/dhcp6-internal.h
@@ -97,7 +97,7 @@ typedef struct DHCP6IA DHCP6IA;
int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
size_t optlen, const void *optval);
int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia);
-int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix);
+int dhcp6_option_append_pd(uint8_t **buf, size_t *buflen, const DHCP6IA *pd, const DHCP6Address *hint_pd_prefix);
int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn);
int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char * const *user_class);
int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char * const *user_class);
diff --git a/src/libsystemd-network/dhcp6-option.c b/src/libsystemd-network/dhcp6-option.c
index 0b32acd38a..9314016024 100644
--- a/src/libsystemd-network/dhcp6-option.c
+++ b/src/libsystemd-network/dhcp6-option.c
@@ -184,6 +184,90 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia) {
return option_append_hdr(&ia_hdr, &ia_buflen, ia->type, len + ia_addrlen);
}
+static int option_append_pd_prefix(uint8_t **buf, size_t *buflen, const DHCP6Address *prefix) {
+ struct iapdprefix p;
+ int r;
+
+ assert(buf);
+ assert(*buf);
+ assert(buflen);
+ assert(prefix);
+
+ if (prefix->iapdprefix.prefixlen == 0)
+ return -EINVAL;
+
+ /* Do not append T1 and T2. */
+
+ p = (struct iapdprefix) {
+ .prefixlen = prefix->iapdprefix.prefixlen,
+ .address = prefix->iapdprefix.address,
+ };
+
+ r = option_append_hdr(buf, buflen, SD_DHCP6_OPTION_IA_PD_PREFIX, sizeof(struct iapdprefix));
+ if (r < 0)
+ return r;
+
+ memcpy(*buf, &p, sizeof(struct iapdprefix));
+
+ *buf += sizeof(struct iapdprefix);
+ *buflen -= sizeof(struct iapdprefix);
+
+ return offsetof(DHCP6Option, data) + sizeof(struct iapdprefix);
+}
+
+int dhcp6_option_append_pd(uint8_t **buf, size_t *buflen, const DHCP6IA *pd, const DHCP6Address *hint_pd_prefix) {
+ struct ia_pd ia_pd;
+ size_t len, pd_buflen;
+ uint8_t *pd_hdr;
+ int r;
+
+ assert_return(buf, -EINVAL);
+ assert_return(*buf, -EINVAL);
+ assert_return(buflen, -EINVAL);
+ assert_return(pd, -EINVAL);
+ assert_return(pd->type == SD_DHCP6_OPTION_IA_PD, -EINVAL);
+
+ /* Do not set T1 and T2. */
+ ia_pd = (struct ia_pd) {
+ .id = pd->ia_pd.id,
+ };
+ len = sizeof(struct ia_pd);
+
+ if (*buflen < offsetof(DHCP6Option, data) + len)
+ return -ENOBUFS;
+
+ pd_hdr = *buf;
+ pd_buflen = *buflen;
+
+ /* The header will be written at the end of this function. */
+ *buf += offsetof(DHCP6Option, data);
+ *buflen -= offsetof(DHCP6Option, data);
+
+ memcpy(*buf, &ia_pd, len);
+
+ *buf += sizeof(struct ia_pd);
+ *buflen -= sizeof(struct ia_pd);
+
+ DHCP6Address *prefix;
+ LIST_FOREACH(addresses, prefix, pd->addresses) {
+ r = option_append_pd_prefix(buf, buflen, prefix);
+ if (r < 0)
+ return r;
+
+ len += r;
+ }
+
+ if (hint_pd_prefix) {
+ r = option_append_pd_prefix(buf, buflen, hint_pd_prefix);
+ if (r < 0 && r != -EINVAL)
+ return r;
+
+ len += r;
+ }
+
+ return option_append_hdr(&pd_hdr, &pd_buflen, pd->type, len);
+}
+
int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) {
uint8_t buffer[1 + DNS_WIRE_FORMAT_HOSTNAME_MAX];
int r;
@@ -286,51 +370,6 @@ int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char * const
return dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_VENDOR_CLASS, total, p);
}
-int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix) {
- DHCP6Option *option = (DHCP6Option *)buf;
- size_t i = sizeof(*option) + sizeof(pd->ia_pd);
- DHCP6PDPrefixOption *prefix_opt;
- DHCP6Address *prefix;
-
- assert_return(buf, -EINVAL);
- assert_return(pd, -EINVAL);
- assert_return(pd->type == SD_DHCP6_OPTION_IA_PD, -EINVAL);
-
- if (len < i)
- return -ENOBUFS;
-
- option->code = htobe16(SD_DHCP6_OPTION_IA_PD);
-
- memcpy(&option->data, &pd->ia_pd, sizeof(pd->ia_pd));
- LIST_FOREACH(addresses, prefix, pd->addresses) {
- if (len < i + sizeof(*prefix_opt))
- return -ENOBUFS;
-
- prefix_opt = (DHCP6PDPrefixOption *)&buf[i];
- prefix_opt->option.code = htobe16(SD_DHCP6_OPTION_IA_PD_PREFIX);
- prefix_opt->option.len = htobe16(sizeof(prefix_opt->iapdprefix));
-
- memcpy(&prefix_opt->iapdprefix, &prefix->iapdprefix, sizeof(struct iapdprefix));
- i += sizeof(*prefix_opt);
- }
-
- if (hint_pd_prefix && hint_pd_prefix->iapdprefix.prefixlen > 0) {
- if (len < i + sizeof(*prefix_opt))
- return -ENOBUFS;
-
- prefix_opt = (DHCP6PDPrefixOption *)&buf[i];
- prefix_opt->option.code = htobe16(SD_DHCP6_OPTION_IA_PD_PREFIX);
- prefix_opt->option.len = htobe16(sizeof(prefix_opt->iapdprefix));
-
- memcpy(&prefix_opt->iapdprefix, &hint_pd_prefix->iapdprefix, sizeof(struct iapdprefix));
- i += sizeof(*prefix_opt);
- }
-
- option->len = htobe16(i - sizeof(*option));
-
- return i;
-}
-
static int option_parse_hdr(uint8_t **buf, size_t *buflen, uint16_t *optcode, size_t *optlen) {
DHCP6Option *option = (DHCP6Option*) *buf;
uint16_t len;
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index d5020519cd..66f87c4b95 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -707,12 +707,9 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
}
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
- r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd, &client->hint_pd_prefix);
+ r = dhcp6_option_append_pd(&opt, &optlen, &client->ia_pd, &client->hint_pd_prefix);
if (r < 0)
return r;
-
- opt += r;
- optlen -= r;
}
break;
@@ -771,12 +768,9 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
}
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD) && client->lease->pd.addresses) {
- r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL);
+ r = dhcp6_option_append_pd(&opt, &optlen, &client->lease->pd, NULL);
if (r < 0)
return r;
-
- opt += r;
- optlen -= r;
}
break;
@@ -823,12 +817,9 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
}
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
- r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL);
+ r = dhcp6_option_append_pd(&opt, &optlen, &client->lease->pd, NULL);
if (r < 0)
return r;
-
- opt += r;
- optlen -= r;
}
break;