From 9e4dee4cec64df8db016227d25c2285827ab2665 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 7 Feb 2022 05:37:02 +0900 Subject: [PATCH] sd-dhcp6-client: use OrderedSet for vendor option This also fixes memleak. --- src/libsystemd-network/dhcp6-internal.h | 5 +++-- src/libsystemd-network/dhcp6-option.c | 4 ++-- src/libsystemd-network/sd-dhcp6-client.c | 12 +++++++++--- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/libsystemd-network/dhcp6-internal.h b/src/libsystemd-network/dhcp6-internal.h index 40578220d3..75bf879540 100644 --- a/src/libsystemd-network/dhcp6-internal.h +++ b/src/libsystemd-network/dhcp6-internal.h @@ -18,6 +18,7 @@ #include "list.h" #include "macro.h" #include "network-common.h" +#include "ordered-set.h" #include "sparse-endian.h" typedef struct sd_dhcp6_option { @@ -124,7 +125,7 @@ typedef struct sd_dhcp6_client { usec_t information_request_time_usec; usec_t information_refresh_time_usec; OrderedHashmap *extra_options; - OrderedHashmap *vendor_options; + OrderedSet *vendor_options; /* Ignore ifindex when generating iaid. See dhcp_identifier_set_iaid(). */ bool test_mode; @@ -137,7 +138,7 @@ 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, OrderedHashmap *vendor_options); +int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedSet *vendor_options); int dhcp6_option_parse( const uint8_t *buf, diff --git a/src/libsystemd-network/dhcp6-option.c b/src/libsystemd-network/dhcp6-option.c index ac032f07fd..544887b9bc 100644 --- a/src/libsystemd-network/dhcp6-option.c +++ b/src/libsystemd-network/dhcp6-option.c @@ -246,7 +246,7 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, return 0; } -int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHashmap *vendor_options) { +int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedSet *vendor_options) { sd_dhcp6_option *options; int r; @@ -255,7 +255,7 @@ int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHash assert(buflen); assert(vendor_options); - ORDERED_HASHMAP_FOREACH(options, vendor_options) { + ORDERED_SET_FOREACH(options, vendor_options) { _cleanup_free_ uint8_t *p = NULL; size_t total; diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 87f297e2d6..b59dce74a9 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -249,9 +249,14 @@ int sd_dhcp6_client_add_vendor_option(sd_dhcp6_client *client, sd_dhcp6_option * assert_return(client, -EINVAL); assert_return(!sd_dhcp6_client_is_running(client), -EBUSY); - assert_return(v, -EINVAL); - r = ordered_hashmap_ensure_put(&client->vendor_options, &dhcp6_option_hash_ops, v, v); + if (!v) { + /* Clear the previous assignments. */ + ordered_set_clear(client->vendor_options); + return 0; + } + + r = ordered_set_ensure_put(&client->vendor_options, &dhcp6_option_hash_ops, v); if (r < 0) return r; @@ -706,7 +711,7 @@ static int client_append_common_options_in_managed_mode( return r; } - if (!ordered_hashmap_isempty(client->vendor_options)) { + if (!ordered_set_isempty(client->vendor_options)) { r = dhcp6_option_append_vendor_option(opt, optlen, client->vendor_options); if (r < 0) return r; @@ -1500,6 +1505,7 @@ static sd_dhcp6_client *dhcp6_client_free(sd_dhcp6_client *client) { free(client->mudurl); dhcp6_ia_clear_addresses(&client->ia_pd); ordered_hashmap_free(client->extra_options); + ordered_set_free(client->vendor_options); strv_free(client->user_class); strv_free(client->vendor_class); free(client->ifname);