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;
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));
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);
*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) {