diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-02-22 22:39:31 +0900 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2021-03-12 17:35:57 +0100 |
commit | d2cda53bcb814b4c5973fa3da4fbc2e75bbd0b1d (patch) | |
tree | a46506b816976705b6c44daf0affcb58b5ac884a | |
parent | 78b39de4444598f47ecc04e9c4ee6073b43a991b (diff) | |
download | systemd-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.h | 2 | ||||
-rw-r--r-- | src/libsystemd-network/dhcp6-option.c | 129 | ||||
-rw-r--r-- | src/libsystemd-network/sd-dhcp6-client.c | 15 |
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; |