diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2024-04-09 04:26:16 +0200 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2024-04-09 05:06:32 +0200 |
commit | e700e482576ad9982da3bab62f613d1b7b52516f (patch) | |
tree | 53eafdf0cf61613a044b99ea3b9ce21f2a8f2782 /src | |
parent | network/address: make Address object optionally take reference to IPv6Token (diff) | |
download | systemd-e700e482576ad9982da3bab62f613d1b7b52516f.tar.xz systemd-e700e482576ad9982da3bab62f613d1b7b52516f.zip |
network/address-generation: also provide used tokens when generating address
Then, assign the token to the corresponding Address object.
Diffstat (limited to 'src')
-rw-r--r-- | src/network/networkd-address-generation.c | 90 | ||||
-rw-r--r-- | src/network/networkd-address-generation.h | 8 | ||||
-rw-r--r-- | src/network/networkd-dhcp-prefix-delegation.c | 10 | ||||
-rw-r--r-- | src/network/networkd-ndisc.c | 11 | ||||
-rw-r--r-- | src/network/networkd-radv.c | 11 |
5 files changed, 88 insertions, 42 deletions
diff --git a/src/network/networkd-address-generation.c b/src/network/networkd-address-generation.c index 293dc75157..9957ce86ef 100644 --- a/src/network/networkd-address-generation.c +++ b/src/network/networkd-address-generation.c @@ -71,6 +71,15 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( ipv6_token_compare_func, ipv6_token_unref); +DEFINE_PRIVATE_HASH_OPS_FULL( + ipv6_token_by_addr_hash_ops, + struct in6_addr, + in6_addr_hash_func, + in6_addr_compare_func, + free, + IPv6Token, + ipv6_token_unref); + static int ipv6_token_new(AddressGenerationType type, const struct in6_addr *addr, const sd_id128_t *secret_key, IPv6Token **ret) { IPv6Token *p; @@ -107,6 +116,44 @@ static int ipv6_token_add(Set **tokens, AddressGenerationType type, const struct return set_ensure_consume(tokens, &ipv6_token_hash_ops, p); } +static int ipv6_token_put_by_addr(Hashmap **tokens_by_address, const struct in6_addr *addr, IPv6Token *token) { + _cleanup_free_ struct in6_addr *copy = NULL; + int r; + + assert(tokens_by_address); + assert(addr); + assert(token); + + copy = newdup(struct in6_addr, addr, 1); + if (!copy) + return -ENOMEM; + + r = hashmap_ensure_put(tokens_by_address, &ipv6_token_by_addr_hash_ops, copy, token); + if (r == -EEXIST) + return 0; + if (r < 0) + return r; + + TAKE_PTR(copy); + ipv6_token_ref(token); + return 1; +} + +static int ipv6_token_type_put_by_addr(Hashmap **tokens_by_addr, const struct in6_addr *addr, AddressGenerationType type) { + _cleanup_(ipv6_token_unrefp) IPv6Token *token = NULL; + int r; + + assert(tokens_by_addr); + assert(addr); + + r = ipv6_token_new(type, &(struct in6_addr) {}, &SD_ID128_NULL, &token); + if (r < 0) + return r; + + return ipv6_token_put_by_addr(tokens_by_addr, addr, token); +} + + static int generate_eui64_address(const Link *link, const struct in6_addr *prefix, struct in6_addr *ret) { assert(link); assert(prefix); @@ -247,10 +294,10 @@ static int generate_addresses( const sd_id128_t *app_id, const struct in6_addr *prefix, uint8_t prefixlen, - Set **ret) { + Hashmap **ret) { - _cleanup_set_free_ Set *addresses = NULL; - struct in6_addr masked; + _cleanup_hashmap_free_ Hashmap *tokens_by_address = NULL; + struct in6_addr masked, addr; IPv6Token *j; int r; @@ -264,8 +311,6 @@ static int generate_addresses( in6_addr_mask(&masked, prefixlen); SET_FOREACH(j, tokens) { - struct in6_addr addr, *copy; - switch (j->type) { case ADDRESS_GENERATION_EUI64: if (generate_eui64_address(link, &masked, &addr) < 0) @@ -290,48 +335,43 @@ static int generate_addresses( assert_not_reached(); } - copy = newdup(struct in6_addr, &addr, 1); - if (!copy) - return -ENOMEM; - - r = set_ensure_consume(&addresses, &in6_addr_hash_ops_free, copy); + r = ipv6_token_put_by_addr(&tokens_by_address, &addr, j); if (r < 0) return r; } /* fall back to EUI-64 if no token is provided */ - if (set_isempty(addresses)) { - _cleanup_free_ struct in6_addr *addr = NULL; + if (hashmap_isempty(tokens_by_address)) { + AddressGenerationType type; - addr = new(struct in6_addr, 1); - if (!addr) - return -ENOMEM; - - if (IN_SET(link->iftype, ARPHRD_ETHER, ARPHRD_INFINIBAND)) - r = generate_eui64_address(link, &masked, addr); - else - r = generate_stable_private_address(link, app_id, &SD_ID128_NULL, &masked, addr); + if (IN_SET(link->iftype, ARPHRD_ETHER, ARPHRD_INFINIBAND)) { + type = ADDRESS_GENERATION_EUI64; + r = generate_eui64_address(link, &masked, &addr); + } else { + type = ADDRESS_GENERATION_PREFIXSTABLE; + r = generate_stable_private_address(link, app_id, &SD_ID128_NULL, &masked, &addr); + } if (r < 0) return r; - r = set_ensure_consume(&addresses, &in6_addr_hash_ops_free, TAKE_PTR(addr)); + r = ipv6_token_type_put_by_addr(&tokens_by_address, &addr, type); if (r < 0) return r; } - *ret = TAKE_PTR(addresses); + *ret = TAKE_PTR(tokens_by_address); return 0; } -int dhcp_pd_generate_addresses(Link *link, const struct in6_addr *prefix, Set **ret) { +int dhcp_pd_generate_addresses(Link *link, const struct in6_addr *prefix, Hashmap **ret) { return generate_addresses(link, link->network->dhcp_pd_tokens, &DHCP_PD_APP_ID, prefix, 64, ret); } -int ndisc_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret) { +int ndisc_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Hashmap **ret) { return generate_addresses(link, link->network->ndisc_tokens, &NDISC_APP_ID, prefix, prefixlen, ret); } -int radv_generate_addresses(Link *link, Set *tokens, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret) { +int radv_generate_addresses(Link *link, Set *tokens, const struct in6_addr *prefix, uint8_t prefixlen, Hashmap **ret) { return generate_addresses(link, tokens, &RADV_APP_ID, prefix, prefixlen, ret); } diff --git a/src/network/networkd-address-generation.h b/src/network/networkd-address-generation.h index 00f5a55eda..68828b44ca 100644 --- a/src/network/networkd-address-generation.h +++ b/src/network/networkd-address-generation.h @@ -2,8 +2,8 @@ #pragma once #include "conf-parser.h" +#include "hashmap.h" #include "in-addr-util.h" -#include "set.h" typedef struct IPv6Token IPv6Token; typedef struct Link Link; @@ -11,8 +11,8 @@ typedef struct Link Link; IPv6Token* ipv6_token_ref(IPv6Token *token); IPv6Token* ipv6_token_unref(IPv6Token *token); -int dhcp_pd_generate_addresses(Link *link, const struct in6_addr *prefix, Set **ret); -int ndisc_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret); -int radv_generate_addresses(Link *link, Set *tokens, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret); +int dhcp_pd_generate_addresses(Link *link, const struct in6_addr *prefix, Hashmap **ret); +int ndisc_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Hashmap **ret); +int radv_generate_addresses(Link *link, Set *tokens, const struct in6_addr *prefix, uint8_t prefixlen, Hashmap **ret); CONFIG_PARSER_PROTOTYPE(config_parse_address_generation_type); diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c index 3ae62b51ca..6e83163b04 100644 --- a/src/network/networkd-dhcp-prefix-delegation.c +++ b/src/network/networkd-dhcp-prefix-delegation.c @@ -375,8 +375,6 @@ static int dhcp_pd_request_address( usec_t lifetime_preferred_usec, usec_t lifetime_valid_usec) { - _cleanup_set_free_ Set *addresses = NULL; - struct in6_addr *a; int r; assert(link); @@ -386,11 +384,14 @@ static int dhcp_pd_request_address( if (!link->network->dhcp_pd_assign) return 0; - r = dhcp_pd_generate_addresses(link, prefix, &addresses); + _cleanup_hashmap_free_ Hashmap *tokens_by_address = NULL; + r = dhcp_pd_generate_addresses(link, prefix, &tokens_by_address); if (r < 0) return log_link_warning_errno(link, r, "Failed to generate addresses for acquired DHCP delegated prefix: %m"); - SET_FOREACH(a, addresses) { + IPv6Token *token; + struct in6_addr *a; + HASHMAP_FOREACH_KEY(token, a, tokens_by_address) { _cleanup_(address_unrefp) Address *address = NULL; r = address_new(&address); @@ -405,6 +406,7 @@ static int dhcp_pd_request_address( address->lifetime_valid_usec = lifetime_valid_usec; SET_FLAG(address->flags, IFA_F_MANAGETEMPADDR, link->network->dhcp_pd_manage_temporary_address); address->route_metric = link->network->dhcp_pd_route_metric; + address->token = ipv6_token_ref(token); r = free_and_strdup_warn(&address->netlabel, link->network->dhcp_pd_netlabel); if (r < 0) diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 487a1e6309..e160014c5a 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -1028,8 +1028,7 @@ static int ndisc_router_process_hop_limit(Link *link, sd_ndisc_router *rt) { static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) { usec_t lifetime_valid_usec, lifetime_preferred_usec; - _cleanup_set_free_ Set *addresses = NULL; - struct in6_addr prefix, *a; + struct in6_addr prefix; uint8_t prefixlen; int r; @@ -1067,11 +1066,14 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r if (lifetime_preferred_usec > lifetime_valid_usec) return 0; - r = ndisc_generate_addresses(link, &prefix, prefixlen, &addresses); + _cleanup_hashmap_free_ Hashmap *tokens_by_address = NULL; + r = ndisc_generate_addresses(link, &prefix, prefixlen, &tokens_by_address); if (r < 0) return log_link_warning_errno(link, r, "Failed to generate SLAAC addresses: %m"); - SET_FOREACH(a, addresses) { + IPv6Token *token; + struct in6_addr *a; + HASHMAP_FOREACH_KEY(token, a, tokens_by_address) { _cleanup_(address_unrefp) Address *address = NULL; r = address_new(&address); @@ -1084,6 +1086,7 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR; address->lifetime_valid_usec = lifetime_valid_usec; address->lifetime_preferred_usec = lifetime_preferred_usec; + address->token = ipv6_token_ref(token); /* draft-ietf-6man-slaac-renum-07 section 4.2 * https://datatracker.ietf.org/doc/html/draft-ietf-6man-slaac-renum-07#section-4.2 diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 82c62dad81..279ea8d043 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -243,9 +243,6 @@ int link_request_radv_addresses(Link *link) { return 0; HASHMAP_FOREACH(p, link->network->prefixes_by_section) { - _cleanup_set_free_ Set *addresses = NULL; - struct in6_addr *a; - if (!p->assign) continue; @@ -253,11 +250,14 @@ int link_request_radv_addresses(Link *link) { if (p->prefixlen > 64) continue; - r = radv_generate_addresses(link, p->tokens, &p->prefix, p->prefixlen, &addresses); + _cleanup_hashmap_free_ Hashmap *tokens_by_address = NULL; + r = radv_generate_addresses(link, p->tokens, &p->prefix, p->prefixlen, &tokens_by_address); if (r < 0) return r; - SET_FOREACH(a, addresses) { + IPv6Token *token; + struct in6_addr *a; + HASHMAP_FOREACH_KEY(token, a, tokens_by_address) { _cleanup_(address_unrefp) Address *address = NULL; r = address_new(&address); @@ -269,6 +269,7 @@ int link_request_radv_addresses(Link *link) { address->in_addr.in6 = *a; address->prefixlen = p->prefixlen; address->route_metric = p->route_metric; + address->token = ipv6_token_ref(token); r = link_request_static_address(link, address); if (r < 0) |