summaryrefslogtreecommitdiff
path: root/src/libsystemd-network
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2022-10-12 09:18:07 +0200
committerGitHub <noreply@github.com>2022-10-12 09:18:07 +0200
commit1d3fae91f7d450d05bcd2c1f25decb5ff4acb74a (patch)
tree83741fb8e15a14d9b6a13a2ff5dc63900a292693 /src/libsystemd-network
parentdd4212105e49b830d4c77169991dfab4e113613f (diff)
parent9d2d346aaeda53c3dc0c4b3077ec2e39fdfa61c4 (diff)
downloadsystemd-1d3fae91f7d450d05bcd2c1f25decb5ff4acb74a.tar.gz
Merge pull request #24867 from yuwata/sd-dhcp6-client-large-packet
sd-dhcp6-client: allow to build large packet
Diffstat (limited to 'src/libsystemd-network')
-rw-r--r--src/libsystemd-network/dhcp6-option.c190
-rw-r--r--src/libsystemd-network/dhcp6-option.h12
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c123
-rw-r--r--src/libsystemd-network/test-dhcp6-client.c26
4 files changed, 152 insertions, 199 deletions
diff --git a/src/libsystemd-network/dhcp6-option.c b/src/libsystemd-network/dhcp6-option.c
index 5e91e86f53..0b8393ca2c 100644
--- a/src/libsystemd-network/dhcp6-option.c
+++ b/src/libsystemd-network/dhcp6-option.c
@@ -211,47 +211,55 @@ bool dhcp6_option_can_request(uint16_t option) {
}
}
-static int option_append_hdr(uint8_t **buf, size_t *buflen, uint16_t optcode, size_t optlen) {
- assert_return(buf, -EINVAL);
- assert_return(*buf, -EINVAL);
- assert_return(buflen, -EINVAL);
+static int option_append_hdr(uint8_t **buf, size_t *offset, uint16_t optcode, size_t optlen) {
+ assert(buf);
+ assert(*buf);
+ assert(offset);
- if (optlen > 0xffff || *buflen < optlen + offsetof(DHCP6Option, data))
+ if (optlen > 0xffff)
return -ENOBUFS;
- unaligned_write_be16(*buf + offsetof(DHCP6Option, code), optcode);
- unaligned_write_be16(*buf + offsetof(DHCP6Option, len), optlen);
+ if (optlen + offsetof(DHCP6Option, data) > SIZE_MAX - *offset)
+ return -ENOBUFS;
+
+ if (!GREEDY_REALLOC(*buf, *offset + optlen + offsetof(DHCP6Option, data)))
+ return -ENOMEM;
- *buf += offsetof(DHCP6Option, data);
- *buflen -= offsetof(DHCP6Option, data);
+ unaligned_write_be16(*buf + *offset + offsetof(DHCP6Option, code), optcode);
+ unaligned_write_be16(*buf + *offset + offsetof(DHCP6Option, len), optlen);
+ *offset += offsetof(DHCP6Option, data);
return 0;
}
-int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
- size_t optlen, const void *optval) {
+int dhcp6_option_append(
+ uint8_t **buf,
+ size_t *offset,
+ uint16_t code,
+ size_t optlen,
+ const void *optval) {
+
int r;
- assert_return(optval || optlen == 0, -EINVAL);
+ assert(optval || optlen == 0);
- r = option_append_hdr(buf, buflen, code, optlen);
+ r = option_append_hdr(buf, offset, code, optlen);
if (r < 0)
return r;
- *buf = mempcpy_safe(*buf, optval, optlen);
- *buflen -= optlen;
+ memcpy_safe(*buf + *offset, optval, optlen);
+ *offset += optlen;
return 0;
}
-int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedSet *vendor_options) {
+int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *offset, OrderedSet *vendor_options) {
sd_dhcp6_option *options;
int r;
assert(buf);
assert(*buf);
- assert(buflen);
- assert(vendor_options);
+ assert(offset);
ORDERED_SET_FOREACH(options, vendor_options) {
_cleanup_free_ uint8_t *p = NULL;
@@ -268,7 +276,7 @@ int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedSet
unaligned_write_be16(p + 6, options->length);
memcpy(p + 8, options->data, options->length);
- r = dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_VENDOR_OPTS, total, p);
+ r = dhcp6_option_append(buf, offset, SD_DHCP6_OPTION_VENDOR_OPTS, total, p);
if (r < 0)
return r;
}
@@ -276,13 +284,12 @@ int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedSet
return 0;
}
-static int option_append_ia_address(uint8_t **buf, size_t *buflen, const struct iaaddr *address) {
+static int option_append_ia_address(uint8_t **buf, size_t *offset, const struct iaaddr *address) {
struct iaaddr a;
- int r;
assert(buf);
assert(*buf);
- assert(buflen);
+ assert(offset);
assert(address);
/* Do not append T1 and T2. */
@@ -290,23 +297,15 @@ static int option_append_ia_address(uint8_t **buf, size_t *buflen, const struct
.address = address->address,
};
- r = option_append_hdr(buf, buflen, SD_DHCP6_OPTION_IAADDR, sizeof(struct iaaddr));
- if (r < 0)
- return r;
-
- *buf = mempcpy(*buf, &a, sizeof(struct iaaddr));
- *buflen -= sizeof(struct iaaddr);
-
- return offsetof(DHCP6Option, data) + sizeof(struct iaaddr);
+ return dhcp6_option_append(buf, offset, SD_DHCP6_OPTION_IAADDR, sizeof(struct iaaddr), &a);
}
-static int option_append_pd_prefix(uint8_t **buf, size_t *buflen, const struct iapdprefix *prefix) {
+static int option_append_pd_prefix(uint8_t **buf, size_t *offset, const struct iapdprefix *prefix) {
struct iapdprefix p;
- int r;
assert(buf);
assert(*buf);
- assert(buflen);
+ assert(offset);
assert(prefix);
if (prefix->prefixlen == 0)
@@ -318,27 +317,19 @@ static int option_append_pd_prefix(uint8_t **buf, size_t *buflen, const struct i
.address = prefix->address,
};
- r = option_append_hdr(buf, buflen, SD_DHCP6_OPTION_IA_PD_PREFIX, sizeof(struct iapdprefix));
- if (r < 0)
- return r;
-
- *buf = mempcpy(*buf, &p, sizeof(struct iapdprefix));
- *buflen -= sizeof(struct iapdprefix);
-
- return offsetof(DHCP6Option, data) + sizeof(struct iapdprefix);
+ return dhcp6_option_append(buf, offset, SD_DHCP6_OPTION_IA_PD_PREFIX, sizeof(struct iapdprefix), &p);
}
-int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia) {
+int dhcp6_option_append_ia(uint8_t **buf, size_t *offset, const DHCP6IA *ia) {
+ _cleanup_free_ uint8_t *data = NULL;
struct ia_header header;
- size_t ia_buflen;
- uint8_t *ia_hdr;
- uint16_t len;
+ size_t len;
int r;
- assert_return(buf, -EINVAL);
- assert_return(*buf, -EINVAL);
- assert_return(buflen, -EINVAL);
- assert_return(ia, -EINVAL);
+ assert(buf);
+ assert(*buf);
+ assert(offset);
+ assert(ia);
/* client should not send set T1 and T2. See, RFC 8415, and issue #18090. */
@@ -362,43 +353,38 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia) {
assert_not_reached();
}
- if (*buflen < offsetof(DHCP6Option, data) + len)
- return -ENOBUFS;
-
- ia_hdr = *buf;
- ia_buflen = *buflen;
-
- /* The header will be written at the end of this function. */
- *buf += offsetof(DHCP6Option, data);
- *buflen -= offsetof(DHCP6Option, data);
+ if (!GREEDY_REALLOC(data, len))
+ return -ENOMEM;
- *buf = mempcpy(*buf, &header, len);
- *buflen -= len;
+ memcpy(data, &header, len);
LIST_FOREACH(addresses, addr, ia->addresses) {
if (ia->type == SD_DHCP6_OPTION_IA_PD)
- r = option_append_pd_prefix(buf, buflen, &addr->iapdprefix);
+ r = option_append_pd_prefix(&data, &len, &addr->iapdprefix);
else
- r = option_append_ia_address(buf, buflen, &addr->iaaddr);
+ r = option_append_ia_address(&data, &len, &addr->iaaddr);
if (r < 0)
return r;
-
- len += r;
}
- return option_append_hdr(&ia_hdr, &ia_buflen, ia->type, len);
+ return dhcp6_option_append(buf, offset, ia->type, len, data);
}
-int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) {
+int dhcp6_option_append_fqdn(uint8_t **buf, size_t *offset, const char *fqdn) {
uint8_t buffer[1 + DNS_WIRE_FORMAT_HOSTNAME_MAX];
int r;
- assert_return(buf && *buf && buflen && fqdn, -EINVAL);
+ assert(buf);
+ assert(*buf);
+ assert(offset);
+
+ if (isempty(fqdn))
+ return 0;
buffer[0] = DHCP6_FQDN_FLAG_S; /* Request server to perform AAAA RR DNS updates */
/* Store domain name after flags field */
- r = dns_name_to_wire_format(fqdn, buffer + 1, sizeof(buffer) - 1, false);
+ r = dns_name_to_wire_format(fqdn, buffer + 1, sizeof(buffer) - 1, false);
if (r <= 0)
return r;
@@ -411,82 +397,70 @@ int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) {
if (dns_name_is_single_label(fqdn))
r--;
- r = dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_CLIENT_FQDN, 1 + r, buffer);
-
- return r;
+ return dhcp6_option_append(buf, offset, SD_DHCP6_OPTION_CLIENT_FQDN, 1 + r, buffer);
}
-int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char * const *user_class) {
+int dhcp6_option_append_user_class(uint8_t **buf, size_t *offset, char * const *user_class) {
_cleanup_free_ uint8_t *p = NULL;
- size_t total = 0, offset = 0;
+ size_t n = 0;
assert(buf);
assert(*buf);
- assert(buflen);
- assert(!strv_isempty(user_class));
+ assert(offset);
+
+ if (strv_isempty(user_class))
+ return 0;
STRV_FOREACH(s, user_class) {
size_t len = strlen(*s);
- uint8_t *q;
- if (len > 0xffff || len == 0)
+ if (len > UINT16_MAX || len == 0)
return -EINVAL;
- q = realloc(p, total + len + 2);
- if (!q)
- return -ENOMEM;
- p = q;
-
- unaligned_write_be16(&p[offset], len);
- memcpy(&p[offset + 2], *s, len);
+ if (!GREEDY_REALLOC(p, n + len + 2))
+ return -ENOMEM;
- offset += 2 + len;
- total += 2 + len;
+ unaligned_write_be16(p + n, len);
+ memcpy(p + n + 2, *s, len);
+ n += len + 2;
}
- return dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_USER_CLASS, total, p);
+ return dhcp6_option_append(buf, offset, SD_DHCP6_OPTION_USER_CLASS, n, p);
}
-int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char * const *vendor_class) {
+int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *offset, char * const *vendor_class) {
_cleanup_free_ uint8_t *p = NULL;
- uint32_t enterprise_identifier;
- size_t total, offset;
+ size_t n = 0;
assert(buf);
assert(*buf);
- assert(buflen);
- assert(!strv_isempty(vendor_class));
+ assert(offset);
- enterprise_identifier = htobe32(SYSTEMD_PEN);
+ if (strv_isempty(vendor_class))
+ return 0;
- p = memdup(&enterprise_identifier, sizeof(enterprise_identifier));
- if (!p)
+ if (!GREEDY_REALLOC(p, sizeof(be32_t)))
return -ENOMEM;
- total = sizeof(enterprise_identifier);
- offset = total;
+ /* Enterprise Identifier */
+ unaligned_write_be32(p, SYSTEMD_PEN);
+ n += sizeof(be32_t);
STRV_FOREACH(s, vendor_class) {
size_t len = strlen(*s);
- uint8_t *q;
if (len > UINT16_MAX || len == 0)
return -EINVAL;
- q = realloc(p, total + len + 2);
- if (!q)
+ if (!GREEDY_REALLOC(p, n + len + 2))
return -ENOMEM;
- p = q;
-
- unaligned_write_be16(&p[offset], len);
- memcpy(&p[offset + 2], *s, len);
-
- offset += 2 + len;
- total += 2 + len;
+ unaligned_write_be16(p + n, len);
+ memcpy(p + n + 2, *s, len);
+ n += len + 2;
}
- return dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_VENDOR_CLASS, total, p);
+ return dhcp6_option_append(buf, offset, SD_DHCP6_OPTION_VENDOR_CLASS, n, p);
}
int dhcp6_option_parse(
diff --git a/src/libsystemd-network/dhcp6-option.h b/src/libsystemd-network/dhcp6-option.h
index 80aba7f37f..36841dd270 100644
--- a/src/libsystemd-network/dhcp6-option.h
+++ b/src/libsystemd-network/dhcp6-option.h
@@ -72,13 +72,13 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DHCP6IA*, dhcp6_ia_free);
bool dhcp6_option_can_request(uint16_t option);
-int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
+int dhcp6_option_append(uint8_t **buf, size_t *offset, 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_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);
-int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedSet *vendor_options);
+int dhcp6_option_append_ia(uint8_t **buf, size_t *offset, const DHCP6IA *ia);
+int dhcp6_option_append_fqdn(uint8_t **buf, size_t *offset, const char *fqdn);
+int dhcp6_option_append_user_class(uint8_t **buf, size_t *offset, char * const *user_class);
+int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *offset, char * const *vendor_class);
+int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *offset, OrderedSet *vendor_options);
int dhcp6_option_parse(
const uint8_t *buf,
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index 606e48ce6f..375f984940 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -574,8 +574,8 @@ static void client_stop(sd_dhcp6_client *client, int error) {
static int client_append_common_options_in_managed_mode(
sd_dhcp6_client *client,
- uint8_t **opt,
- size_t *optlen,
+ uint8_t **buf,
+ size_t *offset,
const DHCP6IA *ia_na,
const DHCP6IA *ia_pd) {
@@ -587,44 +587,37 @@ static int client_append_common_options_in_managed_mode(
DHCP6_STATE_REQUEST,
DHCP6_STATE_RENEW,
DHCP6_STATE_REBIND));
- assert(opt);
- assert(optlen);
+ assert(buf);
+ assert(*buf);
+ assert(offset);
if (FLAGS_SET(client->request_ia, DHCP6_REQUEST_IA_NA) && ia_na) {
- r = dhcp6_option_append_ia(opt, optlen, ia_na);
+ r = dhcp6_option_append_ia(buf, offset, ia_na);
if (r < 0)
return r;
}
if (FLAGS_SET(client->request_ia, DHCP6_REQUEST_IA_PD) && ia_pd) {
- r = dhcp6_option_append_ia(opt, optlen, ia_pd);
+ r = dhcp6_option_append_ia(buf, offset, ia_pd);
if (r < 0)
return r;
}
- if (client->fqdn) {
- r = dhcp6_option_append_fqdn(opt, optlen, client->fqdn);
- if (r < 0)
- return r;
- }
+ r = dhcp6_option_append_fqdn(buf, offset, client->fqdn);
+ if (r < 0)
+ return r;
- if (client->user_class) {
- r = dhcp6_option_append_user_class(opt, optlen, client->user_class);
- if (r < 0)
- return r;
- }
+ r = dhcp6_option_append_user_class(buf, offset, client->user_class);
+ if (r < 0)
+ return r;
- if (client->vendor_class) {
- r = dhcp6_option_append_vendor_class(opt, optlen, client->vendor_class);
- if (r < 0)
- return r;
- }
+ r = dhcp6_option_append_vendor_class(buf, offset, client->vendor_class);
+ if (r < 0)
+ return r;
- if (!ordered_set_isempty(client->vendor_options)) {
- r = dhcp6_option_append_vendor_option(opt, optlen, client->vendor_options);
- if (r < 0)
- return r;
- }
+ r = dhcp6_option_append_vendor_option(buf, offset, client->vendor_options);
+ if (r < 0)
+ return r;
return 0;
}
@@ -648,41 +641,42 @@ static DHCP6MessageType client_message_type_from_state(sd_dhcp6_client *client)
}
}
-static int client_append_oro(sd_dhcp6_client *client, uint8_t **opt, size_t *optlen) {
- _cleanup_free_ be16_t *buf = NULL;
+static int client_append_oro(sd_dhcp6_client *client, uint8_t **buf, size_t *offset) {
+ _cleanup_free_ be16_t *p = NULL;
be16_t *req_opts;
size_t n;
assert(client);
- assert(opt);
- assert(optlen);
+ assert(buf);
+ assert(*buf);
+ assert(offset);
switch (client->state) {
case DHCP6_STATE_INFORMATION_REQUEST:
n = client->n_req_opts;
- buf = new(be16_t, n + 2);
- if (!buf)
+ p = new(be16_t, n + 2);
+ if (!p)
return -ENOMEM;
- memcpy_safe(buf, client->req_opts, n * sizeof(be16_t));
- buf[n++] = htobe16(SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME); /* RFC 8415 section 21.23 */
- buf[n++] = htobe16(SD_DHCP6_OPTION_INF_MAX_RT); /* RFC 8415 section 21.25 */
+ memcpy_safe(p, client->req_opts, n * sizeof(be16_t));
+ p[n++] = htobe16(SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME); /* RFC 8415 section 21.23 */
+ p[n++] = htobe16(SD_DHCP6_OPTION_INF_MAX_RT); /* RFC 8415 section 21.25 */
- typesafe_qsort(buf, n, be16_compare_func);
- req_opts = buf;
+ typesafe_qsort(p, n, be16_compare_func);
+ req_opts = p;
break;
case DHCP6_STATE_SOLICITATION:
n = client->n_req_opts;
- buf = new(be16_t, n + 1);
- if (!buf)
+ p = new(be16_t, n + 1);
+ if (!p)
return -ENOMEM;
- memcpy_safe(buf, client->req_opts, n * sizeof(be16_t));
- buf[n++] = htobe16(SD_DHCP6_OPTION_SOL_MAX_RT); /* RFC 8415 section 21.24 */
+ memcpy_safe(p, client->req_opts, n * sizeof(be16_t));
+ p[n++] = htobe16(SD_DHCP6_OPTION_SOL_MAX_RT); /* RFC 8415 section 21.24 */
- typesafe_qsort(buf, n, be16_compare_func);
- req_opts = buf;
+ typesafe_qsort(p, n, be16_compare_func);
+ req_opts = p;
break;
default:
@@ -693,18 +687,18 @@ static int client_append_oro(sd_dhcp6_client *client, uint8_t **opt, size_t *opt
if (n == 0)
return 0;
- return dhcp6_option_append(opt, optlen, SD_DHCP6_OPTION_ORO, n * sizeof(be16_t), req_opts);
+ return dhcp6_option_append(buf, offset, SD_DHCP6_OPTION_ORO, n * sizeof(be16_t), req_opts);
}
int dhcp6_client_send_message(sd_dhcp6_client *client) {
- _cleanup_free_ DHCP6Message *message = NULL;
+ _cleanup_free_ uint8_t *buf = NULL;
struct in6_addr all_servers =
IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT;
struct sd_dhcp6_option *j;
- size_t len, optlen = 512;
- uint8_t *opt;
usec_t elapsed_usec, time_now;
be16_t elapsed_time;
+ DHCP6Message *message;
+ size_t offset;
int r;
assert(client);
@@ -714,16 +708,13 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) {
if (r < 0)
return r;
- len = sizeof(DHCP6Message) + optlen;
-
- message = malloc0(len);
- if (!message)
+ if (!GREEDY_REALLOC0(buf, offsetof(DHCP6Message, options)))
return -ENOMEM;
- opt = (uint8_t *)(message + 1);
-
+ message = (DHCP6Message*) buf;
message->transaction_id = client->transaction_id;
message->type = client_message_type_from_state(client);
+ offset = offsetof(DHCP6Message, options);
switch (client->state) {
case DHCP6_STATE_INFORMATION_REQUEST:
@@ -731,12 +722,12 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) {
case DHCP6_STATE_SOLICITATION:
if (client->rapid_commit) {
- r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
+ r = dhcp6_option_append(&buf, &offset, SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
if (r < 0)
return r;
}
- r = client_append_common_options_in_managed_mode(client, &opt, &optlen,
+ r = client_append_common_options_in_managed_mode(client, &buf, &offset,
&client->ia_na, &client->ia_pd);
if (r < 0)
return r;
@@ -745,7 +736,7 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) {
case DHCP6_STATE_REQUEST:
case DHCP6_STATE_RENEW:
- r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_SERVERID,
+ r = dhcp6_option_append(&buf, &offset, SD_DHCP6_OPTION_SERVERID,
client->lease->serverid_len,
client->lease->serverid);
if (r < 0)
@@ -756,7 +747,7 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) {
assert(client->lease);
- r = client_append_common_options_in_managed_mode(client, &opt, &optlen,
+ r = client_append_common_options_in_managed_mode(client, &buf, &offset,
client->lease->ia_na, client->lease->ia_pd);
if (r < 0)
return r;
@@ -769,24 +760,24 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) {
}
if (client->mudurl) {
- r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_MUD_URL_V6,
+ r = dhcp6_option_append(&buf, &offset, SD_DHCP6_OPTION_MUD_URL_V6,
strlen(client->mudurl), client->mudurl);
if (r < 0)
return r;
}
- r = client_append_oro(client, &opt, &optlen);
+ r = client_append_oro(client, &buf, &offset);
if (r < 0)
return r;
- assert(client->duid_len);
- r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_CLIENTID,
+ assert(client->duid_len > 0);
+ r = dhcp6_option_append(&buf, &offset, SD_DHCP6_OPTION_CLIENTID,
client->duid_len, &client->duid);
if (r < 0)
return r;
ORDERED_HASHMAP_FOREACH(j, client->extra_options) {
- r = dhcp6_option_append(&opt, &optlen, j->option, j->length, j->data);
+ r = dhcp6_option_append(&buf, &offset, j->option, j->length, j->data);
if (r < 0)
return r;
}
@@ -796,18 +787,16 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) {
* been trying to complete a DHCP message exchange. */
elapsed_usec = MIN(usec_sub_unsigned(time_now, client->transaction_start) / USEC_PER_MSEC / 10, (usec_t) UINT16_MAX);
elapsed_time = htobe16(elapsed_usec);
- r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ELAPSED_TIME, sizeof(elapsed_time), &elapsed_time);
+ r = dhcp6_option_append(&buf, &offset, SD_DHCP6_OPTION_ELAPSED_TIME, sizeof(elapsed_time), &elapsed_time);
if (r < 0)
return r;
- r = dhcp6_network_send_udp_socket(client->fd, &all_servers, message,
- len - optlen);
+ r = dhcp6_network_send_udp_socket(client->fd, &all_servers, buf, offset);
if (r < 0)
return r;
log_dhcp6_client(client, "Sent %s",
- dhcp6_message_type_to_string(message->type));
-
+ dhcp6_message_type_to_string(client_message_type_from_state(client)));
return 0;
}
diff --git a/src/libsystemd-network/test-dhcp6-client.c b/src/libsystemd-network/test-dhcp6-client.c
index e5c09f9664..c3c89514f8 100644
--- a/src/libsystemd-network/test-dhcp6-client.c
+++ b/src/libsystemd-network/test-dhcp6-client.c
@@ -179,7 +179,7 @@ TEST(parse_domain) {
}
TEST(option) {
- uint8_t packet[] = {
+ static const uint8_t packet[] = {
'F', 'O', 'O', 'H', 'O', 'G', 'E',
0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x07,
'A', 'B', 'C', 'D', 'E', 'F', 'G',
@@ -187,7 +187,7 @@ TEST(option) {
'1', '2', '3', '4', '5', '6', '7', '8', '9',
'B', 'A', 'R',
};
- uint8_t result[] = {
+ static const uint8_t result[] = {
'F', 'O', 'O', 'H', 'O', 'G', 'E',
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -195,10 +195,9 @@ TEST(option) {
'B', 'A', 'R',
};
_cleanup_free_ uint8_t *buf = NULL;
- size_t offset, pos, optlen, outlen = sizeof(result);
+ size_t offset, pos, optlen;
const uint8_t *optval;
uint16_t optcode;
- uint8_t *out;
assert_se(sizeof(packet) == sizeof(result));
@@ -227,15 +226,10 @@ TEST(option) {
assert_se(optlen == 7);
assert_se(optval == packet + 11);
+ free(buf);
+ assert_se(buf = memdup(result, sizeof(result)));
pos = 7;
- outlen -= 7;
- out = &result[pos];
-
- assert_se(dhcp6_option_append(&out, &outlen, optcode, optlen, optval) >= 0);
-
- pos += 4 + optlen;
- assert_se(out == &result[pos]);
- assert_se(*out == 0x00);
+ assert_se(dhcp6_option_append(&buf, &pos, optcode, optlen, optval) >= 0);
assert_se(dhcp6_option_parse(packet, sizeof(packet), &offset, &optcode, &optlen, &optval) >= 0);
@@ -243,13 +237,9 @@ TEST(option) {
assert_se(optlen == 9);
assert_se(optval == packet + 22);
- assert_se(dhcp6_option_append(&out, &outlen, optcode, optlen, optval) >= 0);
-
- pos += 4 + optlen;
- assert_se(out == &result[pos]);
- assert_se(*out == 'B');
+ assert_se(dhcp6_option_append(&buf, &pos, optcode, optlen, optval) >= 0);
- assert_se(memcmp(packet, result, sizeof(packet)) == 0);
+ assert_se(memcmp(packet, buf, sizeof(packet)) == 0);
}
TEST(option_status) {