diff options
-rw-r--r-- | src/libsystemd-network/dhcp6-option.c | 190 | ||||
-rw-r--r-- | src/libsystemd-network/dhcp6-option.h | 12 | ||||
-rw-r--r-- | src/libsystemd-network/sd-dhcp6-client.c | 123 | ||||
-rw-r--r-- | src/libsystemd-network/test-dhcp6-client.c | 26 |
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) { |