From: Yu Watanabe Date: Sun, 6 Feb 2022 05:56:59 +0000 (+0900) Subject: sd-dhcp6-client: unify dhcp6_option_append_{ia,pd}() X-Git-Tag: v251-rc1~291^2~55 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=29858a0f9e42552c948493af4c47e5158fa40e57;p=thirdparty%2Fsystemd.git sd-dhcp6-client: unify dhcp6_option_append_{ia,pd}() --- diff --git a/src/libsystemd-network/dhcp6-internal.h b/src/libsystemd-network/dhcp6-internal.h index ad77a9c44c5..23738d31972 100644 --- a/src/libsystemd-network/dhcp6-internal.h +++ b/src/libsystemd-network/dhcp6-internal.h @@ -81,7 +81,6 @@ bool dhcp6_option_can_request(uint16_t option); 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 *buflen, const DHCP6IA *pd); 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 f570e78875d..5099fa152c3 100644 --- a/src/libsystemd-network/dhcp6-option.c +++ b/src/libsystemd-network/dhcp6-option.c @@ -282,75 +282,33 @@ int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHash return 0; } -int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia) { - size_t ia_buflen, ia_addrlen = 0; - struct ia_header header; - DHCP6Address *addr; - uint8_t *ia_hdr; - uint16_t len; +static int option_append_ia_address(uint8_t **buf, size_t *buflen, const struct iaaddr *address) { + struct iaaddr a; int r; - assert_return(buf, -EINVAL); - assert_return(*buf, -EINVAL); - assert_return(buflen, -EINVAL); - assert_return(ia, -EINVAL); - - /* client should not send set T1 and T2. See, RFC 8415, and issue #18090. */ - - switch (ia->type) { - case SD_DHCP6_OPTION_IA_NA: - len = sizeof(struct ia_header); - header = (struct ia_header) { - .id = ia->header.id, - }; - break; - - case SD_DHCP6_OPTION_IA_TA: - len = sizeof(be32_t); /* IA_TA does not have lifetime. */ - header = (struct ia_header) { - .id = ia->header.id, - }; - break; - - default: - assert_not_reached(); - } - - if (*buflen < offsetof(DHCP6Option, data) + len) - return -ENOBUFS; - - ia_hdr = *buf; - ia_buflen = *buflen; - - *buf += offsetof(DHCP6Option, data); - *buflen -= offsetof(DHCP6Option, data); - - memcpy(*buf, &header, len); - - *buf += len; - *buflen -= len; - - LIST_FOREACH(addresses, addr, ia->addresses) { - struct iaaddr a = { - .address = addr->iaaddr.address, - }; + assert(buf); + assert(*buf); + assert(buflen); + assert(address); - r = option_append_hdr(buf, buflen, SD_DHCP6_OPTION_IAADDR, sizeof(struct iaaddr)); - if (r < 0) - return r; + /* Do not append T1 and T2. */ + a = (struct iaaddr) { + .address = address->address, + }; - memcpy(*buf, &a, sizeof(struct iaaddr)); + r = option_append_hdr(buf, buflen, SD_DHCP6_OPTION_IAADDR, sizeof(struct iaaddr)); + if (r < 0) + return r; - *buf += sizeof(struct iaaddr); - *buflen -= sizeof(struct iaaddr); + memcpy(*buf, &a, sizeof(struct iaaddr)); - ia_addrlen += offsetof(DHCP6Option, data) + sizeof(struct iaaddr); - } + *buf += sizeof(struct iaaddr); + *buflen -= sizeof(struct iaaddr); - return option_append_hdr(&ia_hdr, &ia_buflen, ia->type, len + ia_addrlen); + return offsetof(DHCP6Option, data) + sizeof(struct iaaddr); } -static int option_append_pd_prefix(uint8_t **buf, size_t *buflen, const DHCP6Address *prefix) { +static int option_append_pd_prefix(uint8_t **buf, size_t *buflen, const struct iapdprefix *prefix) { struct iapdprefix p; int r; @@ -359,14 +317,13 @@ static int option_append_pd_prefix(uint8_t **buf, size_t *buflen, const DHCP6Add assert(buflen); assert(prefix); - if (prefix->iapdprefix.prefixlen == 0) + if (prefix->prefixlen == 0) return -EINVAL; /* Do not append T1 and T2. */ - p = (struct iapdprefix) { - .prefixlen = prefix->iapdprefix.prefixlen, - .address = prefix->iapdprefix.address, + .prefixlen = prefix->prefixlen, + .address = prefix->address, }; r = option_append_hdr(buf, buflen, SD_DHCP6_OPTION_IA_PD_PREFIX, sizeof(struct iapdprefix)); @@ -381,29 +338,46 @@ static int option_append_pd_prefix(uint8_t **buf, size_t *buflen, const DHCP6Add return offsetof(DHCP6Option, data) + sizeof(struct iapdprefix); } -int dhcp6_option_append_pd(uint8_t **buf, size_t *buflen, const DHCP6IA *pd) { +int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia) { struct ia_header header; - size_t len, pd_buflen; - uint8_t *pd_hdr; + const DHCP6Address *addr; + size_t ia_buflen; + uint8_t *ia_hdr; + uint16_t len; 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); + assert_return(ia, -EINVAL); - /* Do not set T1 and T2. */ - len = sizeof(struct ia_header); - header = (struct ia_header) { - .id = pd->header.id, - }; + /* client should not send set T1 and T2. See, RFC 8415, and issue #18090. */ + + switch (ia->type) { + case SD_DHCP6_OPTION_IA_NA: + case SD_DHCP6_OPTION_IA_PD: + len = sizeof(struct ia_header); + header = (struct ia_header) { + .id = ia->header.id, + }; + break; + + case SD_DHCP6_OPTION_IA_TA: + len = sizeof(be32_t); /* IA_TA does not have lifetime. */ + header = (struct ia_header) { + .id = ia->header.id, + }; + break; + + default: + assert_not_reached(); + } if (*buflen < offsetof(DHCP6Option, data) + len) return -ENOBUFS; - pd_hdr = *buf; - pd_buflen = *buflen; + ia_hdr = *buf; + ia_buflen = *buflen; /* The header will be written at the end of this function. */ *buf += offsetof(DHCP6Option, data); @@ -413,16 +387,18 @@ int dhcp6_option_append_pd(uint8_t **buf, size_t *buflen, const DHCP6IA *pd) { *buf += len; *buflen -= len; - DHCP6Address *prefix; - LIST_FOREACH(addresses, prefix, pd->addresses) { - r = option_append_pd_prefix(buf, buflen, prefix); + LIST_FOREACH(addresses, addr, ia->addresses) { + if (ia->type == SD_DHCP6_OPTION_IA_PD) + r = option_append_pd_prefix(buf, buflen, &addr->iapdprefix); + else + r = option_append_ia_address(buf, buflen, &addr->iaaddr); if (r < 0) return r; len += r; } - return option_append_hdr(&pd_hdr, &pd_buflen, pd->type, len); + return option_append_hdr(&ia_hdr, &ia_buflen, ia->type, len); } int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) { diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index b60950740af..89d91f92891 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -702,7 +702,7 @@ static int client_append_common_options_in_managed_mode( } if (FLAGS_SET(client->request_ia, DHCP6_REQUEST_IA_PD) && ia_pd) { - r = dhcp6_option_append_pd(opt, optlen, ia_pd); + r = dhcp6_option_append_ia(opt, optlen, ia_pd); if (r < 0) return r; }