sd-dhcp6-client: unify dhcp6_option_append_{ia,pd}()

This commit is contained in:
Yu Watanabe
2022-02-14 14:43:45 +09:00
parent 877bfc78fd
commit 29858a0f9e
3 changed files with 66 additions and 91 deletions
-1
View File
@@ -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);
+65 -89
View File
@@ -282,10 +282,66 @@ int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHash
return 0;
}
static int option_append_ia_address(uint8_t **buf, size_t *buflen, const struct iaaddr *address) {
struct iaaddr a;
int r;
assert(buf);
assert(*buf);
assert(buflen);
assert(address);
/* Do not append T1 and T2. */
a = (struct iaaddr) {
.address = address->address,
};
r = option_append_hdr(buf, buflen, SD_DHCP6_OPTION_IAADDR, sizeof(struct iaaddr));
if (r < 0)
return r;
memcpy(*buf, &a, sizeof(struct iaaddr));
*buf += sizeof(struct iaaddr);
*buflen -= sizeof(struct iaaddr);
return offsetof(DHCP6Option, data) + sizeof(struct iaaddr);
}
static int option_append_pd_prefix(uint8_t **buf, size_t *buflen, const struct iapdprefix *prefix) {
struct iapdprefix p;
int r;
assert(buf);
assert(*buf);
assert(buflen);
assert(prefix);
if (prefix->prefixlen == 0)
return -EINVAL;
/* Do not append T1 and T2. */
p = (struct iapdprefix) {
.prefixlen = prefix->prefixlen,
.address = prefix->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_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia) {
size_t ia_buflen, ia_addrlen = 0;
struct ia_header header;
DHCP6Address *addr;
const DHCP6Address *addr;
size_t ia_buflen;
uint8_t *ia_hdr;
uint16_t len;
int r;
@@ -299,6 +355,7 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia) {
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,
@@ -322,89 +379,6 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia) {
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,
};
r = option_append_hdr(buf, buflen, SD_DHCP6_OPTION_IAADDR, sizeof(struct iaaddr));
if (r < 0)
return r;
memcpy(*buf, &a, sizeof(struct iaaddr));
*buf += sizeof(struct iaaddr);
*buflen -= sizeof(struct iaaddr);
ia_addrlen += offsetof(DHCP6Option, data) + sizeof(struct iaaddr);
}
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) {
struct ia_header header;
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. */
len = sizeof(struct ia_header);
header = (struct ia_header) {
.id = pd->header.id,
};
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);
@@ -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) {
+1 -1
View File
@@ -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;
}