]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/address-generation: also provide used tokens when generating address
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 9 Apr 2024 02:26:16 +0000 (11:26 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 9 Apr 2024 03:06:32 +0000 (12:06 +0900)
Then, assign the token to the corresponding Address object.

src/network/networkd-address-generation.c
src/network/networkd-address-generation.h
src/network/networkd-dhcp-prefix-delegation.c
src/network/networkd-ndisc.c
src/network/networkd-radv.c

index 293dc75157445358b924b1808647525361228bba..9957ce86efaab230f3de358168ac6538c90d0d10 100644 (file)
@@ -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);
 }
 
index 00f5a55eda790b33a40241b37614ea6db44f1a30..68828b44ca016594b19025f97d3c343a01b210fa 100644 (file)
@@ -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);
index 3ae62b51cab49eb3147d53f47e283aa7f92d3cc4..6e83163b047251f1bc2482ce5cac9c275aaaa4f4 100644 (file)
@@ -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)
index 487a1e63098efed550050ce713b0b34138304a8b..e160014c5ab34ecf4ab8d83a9769f0799bcad08b 100644 (file)
@@ -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
index 82c62dad815ef0ef2dfff68c60d47ebf856c9d68..279ea8d043b1dda972be9ae56cf5b9f532736686 100644 (file)
@@ -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)