]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: move address generation methods to network-address-generation.[ch]
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 1 Oct 2021 07:44:25 +0000 (16:44 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 6 Oct 2021 16:03:06 +0000 (01:03 +0900)
src/network/meson.build
src/network/networkd-address-generation.c [new file with mode: 0644]
src/network/networkd-address-generation.h [new file with mode: 0644]
src/network/networkd-address.c
src/network/networkd-address.h
src/network/networkd-dhcp6.c
src/network/networkd-ndisc.c
src/network/networkd-ndisc.h
src/network/networkd-network-gperf.gperf
src/network/networkd-radv.c

index 2ea12c8d030e8f683d232c8d84ba4e22fe2a7325..dedfc90f4df322bc5cafbcbfb92936c68f3e568a 100644 (file)
@@ -51,6 +51,8 @@ sources = files('''
         netdev/macsec.h
         netdev/xfrm.c
         netdev/xfrm.h
+        networkd-address-generation.c
+        networkd-address-generation.h
         networkd-address-label.c
         networkd-address-label.h
         networkd-address-pool.c
diff --git a/src/network/networkd-address-generation.c b/src/network/networkd-address-generation.c
new file mode 100644 (file)
index 0000000..cb582b2
--- /dev/null
@@ -0,0 +1,323 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <net/if_arp.h>
+
+#include "sd-id128.h"
+
+#include "memory-util.h"
+#include "networkd-address-generation.h"
+#include "networkd-link.h"
+#include "networkd-network.h"
+#include "string-util.h"
+
+#define DAD_CONFLICTS_IDGEN_RETRIES_RFC7217 3
+
+/* https://tools.ietf.org/html/rfc5453 */
+/* https://www.iana.org/assignments/ipv6-interface-ids/ipv6-interface-ids.xml */
+
+#define SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291               ((struct in6_addr) { .s6_addr = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } })
+#define SUBNET_ROUTER_ANYCAST_PREFIXLEN                     8
+#define RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291 ((struct in6_addr) { .s6_addr = { 0x02, 0x00, 0x5E, 0xFF, 0xFE } })
+#define RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN       5
+#define RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291           ((struct in6_addr) { .s6_addr = { 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } })
+#define RESERVED_SUBNET_ANYCAST_PREFIXLEN                   7
+
+#define NDISC_APP_ID   SD_ID128_MAKE(13,ac,81,a7,d5,3f,49,78,92,79,5d,0c,29,3a,bc,7e)
+
+typedef enum IPv6TokenAddressGeneration {
+        IPV6_TOKEN_ADDRESS_GENERATION_NONE,
+        IPV6_TOKEN_ADDRESS_GENERATION_STATIC,
+        IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE,
+        _IPV6_TOKEN_ADDRESS_GENERATION_MAX,
+        _IPV6_TOKEN_ADDRESS_GENERATION_INVALID = -EINVAL,
+} IPv6TokenAddressGeneration;
+
+typedef struct IPv6Token {
+        IPv6TokenAddressGeneration address_generation_type;
+
+        uint8_t dad_counter;
+        struct in6_addr prefix;
+} IPv6Token;
+
+int generate_ipv6_eui_64_address(const Link *link, struct in6_addr *ret) {
+        assert(link);
+        assert(ret);
+
+        if (link->iftype == ARPHRD_INFINIBAND) {
+                /* see RFC4391 section 8 */
+                memcpy(&ret->s6_addr[8], &link->hw_addr.infiniband[12], 8);
+                ret->s6_addr[8] ^= 1 << 1;
+
+                return 0;
+        }
+
+        /* see RFC4291 section 2.5.1 */
+        ret->s6_addr[8]  = link->hw_addr.ether.ether_addr_octet[0];
+        ret->s6_addr[8] ^= 1 << 1;
+        ret->s6_addr[9]  = link->hw_addr.ether.ether_addr_octet[1];
+        ret->s6_addr[10] = link->hw_addr.ether.ether_addr_octet[2];
+        ret->s6_addr[11] = 0xff;
+        ret->s6_addr[12] = 0xfe;
+        ret->s6_addr[13] = link->hw_addr.ether.ether_addr_octet[3];
+        ret->s6_addr[14] = link->hw_addr.ether.ether_addr_octet[4];
+        ret->s6_addr[15] = link->hw_addr.ether.ether_addr_octet[5];
+
+        return 0;
+}
+
+static bool stable_private_address_is_valid(const struct in6_addr *addr) {
+        assert(addr);
+
+        /* According to rfc4291, generated address should not be in the following ranges. */
+
+        if (memcmp(addr, &SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291, SUBNET_ROUTER_ANYCAST_PREFIXLEN) == 0)
+                return false;
+
+        if (memcmp(addr, &RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291, RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN) == 0)
+                return false;
+
+        if (memcmp(addr, &RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291, RESERVED_SUBNET_ANYCAST_PREFIXLEN) == 0)
+                return false;
+
+        return true;
+}
+
+static int make_stable_private_address(Link *link, const struct in6_addr *prefix, uint8_t prefix_len, uint8_t dad_counter, struct in6_addr **ret) {
+        _cleanup_free_ struct in6_addr *addr = NULL;
+        sd_id128_t secret_key;
+        struct siphash state;
+        uint64_t rid;
+        size_t l;
+        int r;
+
+        /* According to rfc7217 section 5.1
+         * RID = F(Prefix, Net_Iface, Network_ID, DAD_Counter, secret_key) */
+
+        r = sd_id128_get_machine_app_specific(NDISC_APP_ID, &secret_key);
+        if (r < 0)
+                return log_link_warning_errno(link, r, "Failed to generate key for IPv6 stable private address: %m");
+
+        siphash24_init(&state, secret_key.bytes);
+
+        l = MAX(DIV_ROUND_UP(prefix_len, 8), 8);
+        siphash24_compress(prefix, l, &state);
+        siphash24_compress_string(link->ifname, &state);
+        /* Only last 8 bytes of IB MAC are stable */
+        if (link->iftype == ARPHRD_INFINIBAND)
+                siphash24_compress(&link->hw_addr.infiniband[12], 8, &state);
+        else
+                siphash24_compress(link->hw_addr.bytes, link->hw_addr.length, &state);
+        siphash24_compress(&dad_counter, sizeof(uint8_t), &state);
+
+        rid = htole64(siphash24_finalize(&state));
+
+        addr = new(struct in6_addr, 1);
+        if (!addr)
+                return log_oom();
+
+        memcpy(addr->s6_addr, prefix->s6_addr, l);
+        memcpy(addr->s6_addr + l, &rid, 16 - l);
+
+        if (!stable_private_address_is_valid(addr)) {
+                *ret = NULL;
+                return 0;
+        }
+
+        *ret = TAKE_PTR(addr);
+        return 1;
+}
+
+int ndisc_router_generate_addresses(Link *link, struct in6_addr *address, uint8_t prefixlen, Set **ret) {
+        _cleanup_set_free_free_ Set *addresses = NULL;
+        IPv6Token *j;
+        int r;
+
+        assert(link);
+        assert(address);
+        assert(ret);
+
+        addresses = set_new(&in6_addr_hash_ops);
+        if (!addresses)
+                return log_oom();
+
+        ORDERED_SET_FOREACH(j, link->network->ipv6_tokens) {
+                _cleanup_free_ struct in6_addr *new_address = NULL;
+
+                if (j->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
+                    && (in6_addr_is_null(&j->prefix) || in6_addr_equal(&j->prefix, address))) {
+                        /* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop
+                         * does not actually attempt Duplicate Address Detection; the counter will be incremented
+                         * only when the address generation algorithm produces an invalid address, and the loop
+                         * may exit with an address which ends up being unusable due to duplication on the link. */
+                        for (; j->dad_counter < DAD_CONFLICTS_IDGEN_RETRIES_RFC7217; j->dad_counter++) {
+                                r = make_stable_private_address(link, address, prefixlen, j->dad_counter, &new_address);
+                                if (r < 0)
+                                        return r;
+                                if (r > 0)
+                                        break;
+                        }
+                } else if (j->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_STATIC) {
+                        new_address = new(struct in6_addr, 1);
+                        if (!new_address)
+                                return log_oom();
+
+                        memcpy(new_address->s6_addr, address->s6_addr, 8);
+                        memcpy(new_address->s6_addr + 8, j->prefix.s6_addr + 8, 8);
+                }
+
+                if (new_address) {
+                        r = set_put(addresses, new_address);
+                        if (r < 0)
+                                return log_link_error_errno(link, r, "Failed to store SLAAC address: %m");
+                        else if (r == 0)
+                                log_link_debug_errno(link, r, "Generated SLAAC address is duplicated, ignoring.");
+                        else
+                                TAKE_PTR(new_address);
+                }
+        }
+
+        /* fall back to EUI-64 if no tokens provided addresses */
+        if (set_isempty(addresses)) {
+                _cleanup_free_ struct in6_addr *new_address = NULL;
+
+                new_address = newdup(struct in6_addr, address, 1);
+                if (!new_address)
+                        return log_oom();
+
+                r = generate_ipv6_eui_64_address(link, new_address);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Failed to generate EUI64 address: %m");
+
+                r = set_put(addresses, new_address);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Failed to store SLAAC address: %m");
+
+                TAKE_PTR(new_address);
+        }
+
+        *ret = TAKE_PTR(addresses);
+
+        return 0;
+}
+
+static int ipv6token_new(IPv6Token **ret) {
+        IPv6Token *p;
+
+        p = new(IPv6Token, 1);
+        if (!p)
+                return -ENOMEM;
+
+        *p = (IPv6Token) {
+                 .address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_NONE,
+        };
+
+        *ret = TAKE_PTR(p);
+
+        return 0;
+}
+
+static void ipv6_token_hash_func(const IPv6Token *p, struct siphash *state) {
+        siphash24_compress(&p->address_generation_type, sizeof(p->address_generation_type), state);
+        siphash24_compress(&p->prefix, sizeof(p->prefix), state);
+}
+
+static int ipv6_token_compare_func(const IPv6Token *a, const IPv6Token *b) {
+        int r;
+
+        r = CMP(a->address_generation_type, b->address_generation_type);
+        if (r != 0)
+                return r;
+
+        return memcmp(&a->prefix, &b->prefix, sizeof(struct in6_addr));
+}
+
+DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
+                ipv6_token_hash_ops,
+                IPv6Token,
+                ipv6_token_hash_func,
+                ipv6_token_compare_func,
+                free);
+
+int config_parse_address_generation_type(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        _cleanup_free_ IPv6Token *token = NULL;
+        union in_addr_union buffer;
+        Network *network = data;
+        const char *p;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (isempty(rvalue)) {
+                network->ipv6_tokens = ordered_set_free(network->ipv6_tokens);
+                return 0;
+        }
+
+        r = ipv6token_new(&token);
+        if (r < 0)
+                return log_oom();
+
+        if ((p = startswith(rvalue, "prefixstable"))) {
+                token->address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE;
+                if (*p == ':')
+                        p++;
+                else if (*p == '\0')
+                        p = NULL;
+                else {
+                        log_syntax(unit, LOG_WARNING, filename, line, 0,
+                                   "Invalid IPv6 token mode in %s=, ignoring assignment: %s",
+                                   lvalue, rvalue);
+                        return 0;
+                }
+        } else {
+                token->address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_STATIC;
+                p = startswith(rvalue, "static:");
+                if (!p)
+                        p = rvalue;
+        }
+
+        if (p) {
+                r = in_addr_from_string(AF_INET6, p, &buffer);
+                if (r < 0) {
+                        log_syntax(unit, LOG_WARNING, filename, line, r,
+                                   "Failed to parse IP address in %s=, ignoring assignment: %s",
+                                   lvalue, rvalue);
+                        return 0;
+                }
+                if (token->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_STATIC &&
+                    in_addr_is_null(AF_INET6, &buffer)) {
+                        log_syntax(unit, LOG_WARNING, filename, line, 0,
+                                   "IPv6 address in %s= cannot be the ANY address, ignoring assignment: %s",
+                                   lvalue, rvalue);
+                        return 0;
+                }
+                token->prefix = buffer.in6;
+        }
+
+        r = ordered_set_ensure_put(&network->ipv6_tokens, &ipv6_token_hash_ops, token);
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r == -EEXIST)
+                log_syntax(unit, LOG_DEBUG, filename, line, r,
+                           "IPv6 token '%s' is duplicated, ignoring: %m", rvalue);
+        else if (r < 0)
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to store IPv6 token '%s', ignoring: %m", rvalue);
+        else
+                TAKE_PTR(token);
+
+        return 0;
+}
diff --git a/src/network/networkd-address-generation.h b/src/network/networkd-address-generation.h
new file mode 100644 (file)
index 0000000..573fc72
--- /dev/null
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "conf-parser.h"
+#include "in-addr-util.h"
+#include "set.h"
+
+typedef struct Link Link;
+
+int generate_ipv6_eui_64_address(const Link *link, struct in6_addr *ret);
+
+int ndisc_router_generate_addresses(Link *link, struct in6_addr *address, uint8_t prefixlen, Set **ret);
+
+CONFIG_PARSER_PROTOTYPE(config_parse_address_generation_type);
index 002827eb7845e6387c7611562a13c4985d4c8e72..33afdb0335de4dc3aa45ada18b3692469d962fd4 100644 (file)
@@ -57,32 +57,6 @@ static int address_flags_to_string_alloc(uint32_t flags, int family, char **ret)
         return 0;
 }
 
-int generate_ipv6_eui_64_address(const Link *link, struct in6_addr *ret) {
-        assert(link);
-        assert(ret);
-
-        if (link->iftype == ARPHRD_INFINIBAND) {
-                /* see RFC4391 section 8 */
-                memcpy(&ret->s6_addr[8], &link->hw_addr.infiniband[12], 8);
-                ret->s6_addr[8] ^= 1 << 1;
-
-                return 0;
-        }
-
-        /* see RFC4291 section 2.5.1 */
-        ret->s6_addr[8]  = link->hw_addr.ether.ether_addr_octet[0];
-        ret->s6_addr[8] ^= 1 << 1;
-        ret->s6_addr[9]  = link->hw_addr.ether.ether_addr_octet[1];
-        ret->s6_addr[10] = link->hw_addr.ether.ether_addr_octet[2];
-        ret->s6_addr[11] = 0xff;
-        ret->s6_addr[12] = 0xfe;
-        ret->s6_addr[13] = link->hw_addr.ether.ether_addr_octet[3];
-        ret->s6_addr[14] = link->hw_addr.ether.ether_addr_octet[4];
-        ret->s6_addr[15] = link->hw_addr.ether.ether_addr_octet[5];
-
-        return 0;
-}
-
 int address_new(Address **ret) {
         _cleanup_(address_freep) Address *address = NULL;
 
index 0fd3163fc4ef4f2d3c66f75934260b6f9294b810..20e957ccafb7ff2cc794b976a398edf04b2e4143 100644 (file)
@@ -67,8 +67,6 @@ int address_dup(const Address *src, Address **ret);
 bool address_is_ready(const Address *a);
 void address_set_broadcast(Address *a);
 
-int generate_ipv6_eui_64_address(const Link *link, struct in6_addr *ret);
-
 DEFINE_NETWORK_SECTION_FUNCTIONS(Address, address_free);
 
 int link_drop_addresses(Link *link);
index 23a0f5fb53d8e9036fb68d66a71523b0cb8779b5..9ea253b2ac595f416fa64adba527c71782631fcc 100644 (file)
@@ -14,6 +14,7 @@
 #include "hostname-util.h"
 #include "in-addr-prefix-util.h"
 #include "missing_network.h"
+#include "networkd-address-generation.h"
 #include "networkd-address.h"
 #include "networkd-dhcp6.h"
 #include "networkd-link.h"
index 6e6d65603397d689a570eb83b5cde95643e90296..4bab4137cd76a9e367c57a21b29619e0ce282d06 100644 (file)
@@ -5,12 +5,12 @@
 
 #include <arpa/inet.h>
 #include <netinet/icmp6.h>
-#include <net/if_arp.h>
 #include <linux/if.h>
 
 #include "sd-ndisc.h"
 
 #include "missing_network.h"
+#include "networkd-address-generation.h"
 #include "networkd-address.h"
 #include "networkd-dhcp6.h"
 #include "networkd-manager.h"
 #define NDISC_DNSSL_MAX 64U
 #define NDISC_RDNSS_MAX 64U
 
-#define DAD_CONFLICTS_IDGEN_RETRIES_RFC7217 3
-
-/* https://tools.ietf.org/html/rfc5453 */
-/* https://www.iana.org/assignments/ipv6-interface-ids/ipv6-interface-ids.xml */
-
-#define SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291               ((struct in6_addr) { .s6_addr = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } })
-#define SUBNET_ROUTER_ANYCAST_PREFIXLEN                     8
-#define RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291 ((struct in6_addr) { .s6_addr = { 0x02, 0x00, 0x5E, 0xFF, 0xFE } })
-#define RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN       5
-#define RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291           ((struct in6_addr) { .s6_addr = { 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } })
-#define RESERVED_SUBNET_ANYCAST_PREFIXLEN                   7
-
-#define NDISC_APP_ID SD_ID128_MAKE(13,ac,81,a7,d5,3f,49,78,92,79,5d,0c,29,3a,bc,7e)
-
-typedef enum IPv6TokenAddressGeneration {
-        IPV6_TOKEN_ADDRESS_GENERATION_NONE,
-        IPV6_TOKEN_ADDRESS_GENERATION_STATIC,
-        IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE,
-        _IPV6_TOKEN_ADDRESS_GENERATION_MAX,
-        _IPV6_TOKEN_ADDRESS_GENERATION_INVALID = -EINVAL,
-} IPv6TokenAddressGeneration;
-
-typedef struct IPv6Token {
-        IPv6TokenAddressGeneration address_generation_type;
-
-        uint8_t dad_counter;
-        struct in6_addr prefix;
-} IPv6Token;
-
 bool link_ipv6_accept_ra_enabled(Link *link) {
         assert(link);
 
@@ -408,141 +379,6 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
         return 0;
 }
 
-static bool stable_private_address_is_valid(const struct in6_addr *addr) {
-        assert(addr);
-
-        /* According to rfc4291, generated address should not be in the following ranges. */
-
-        if (memcmp(addr, &SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291, SUBNET_ROUTER_ANYCAST_PREFIXLEN) == 0)
-                return false;
-
-        if (memcmp(addr, &RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291, RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN) == 0)
-                return false;
-
-        if (memcmp(addr, &RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291, RESERVED_SUBNET_ANYCAST_PREFIXLEN) == 0)
-                return false;
-
-        return true;
-}
-
-static int make_stable_private_address(Link *link, const struct in6_addr *prefix, uint8_t prefix_len, uint8_t dad_counter, struct in6_addr **ret) {
-        _cleanup_free_ struct in6_addr *addr = NULL;
-        sd_id128_t secret_key;
-        struct siphash state;
-        uint64_t rid;
-        size_t l;
-        int r;
-
-        /* According to rfc7217 section 5.1
-         * RID = F(Prefix, Net_Iface, Network_ID, DAD_Counter, secret_key) */
-
-        r = sd_id128_get_machine_app_specific(NDISC_APP_ID, &secret_key);
-        if (r < 0)
-                return log_link_warning_errno(link, r, "Failed to generate key for IPv6 stable private address: %m");
-
-        siphash24_init(&state, secret_key.bytes);
-
-        l = MAX(DIV_ROUND_UP(prefix_len, 8), 8);
-        siphash24_compress(prefix, l, &state);
-        siphash24_compress_string(link->ifname, &state);
-        /* Only last 8 bytes of IB MAC are stable */
-        if (link->iftype == ARPHRD_INFINIBAND)
-                siphash24_compress(&link->hw_addr.infiniband[12], 8, &state);
-        else
-                siphash24_compress(link->hw_addr.bytes, link->hw_addr.length, &state);
-        siphash24_compress(&dad_counter, sizeof(uint8_t), &state);
-
-        rid = htole64(siphash24_finalize(&state));
-
-        addr = new(struct in6_addr, 1);
-        if (!addr)
-                return log_oom();
-
-        memcpy(addr->s6_addr, prefix->s6_addr, l);
-        memcpy(addr->s6_addr + l, &rid, 16 - l);
-
-        if (!stable_private_address_is_valid(addr)) {
-                *ret = NULL;
-                return 0;
-        }
-
-        *ret = TAKE_PTR(addr);
-        return 1;
-}
-
-static int ndisc_router_generate_addresses(Link *link, struct in6_addr *address, uint8_t prefixlen, Set **ret) {
-        _cleanup_set_free_free_ Set *addresses = NULL;
-        IPv6Token *j;
-        int r;
-
-        assert(link);
-        assert(address);
-        assert(ret);
-
-        addresses = set_new(&in6_addr_hash_ops);
-        if (!addresses)
-                return log_oom();
-
-        ORDERED_SET_FOREACH(j, link->network->ipv6_tokens) {
-                _cleanup_free_ struct in6_addr *new_address = NULL;
-
-                if (j->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
-                    && (in6_addr_is_null(&j->prefix) || in6_addr_equal(&j->prefix, address))) {
-                        /* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop
-                         * does not actually attempt Duplicate Address Detection; the counter will be incremented
-                         * only when the address generation algorithm produces an invalid address, and the loop
-                         * may exit with an address which ends up being unusable due to duplication on the link. */
-                        for (; j->dad_counter < DAD_CONFLICTS_IDGEN_RETRIES_RFC7217; j->dad_counter++) {
-                                r = make_stable_private_address(link, address, prefixlen, j->dad_counter, &new_address);
-                                if (r < 0)
-                                        return r;
-                                if (r > 0)
-                                        break;
-                        }
-                } else if (j->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_STATIC) {
-                        new_address = new(struct in6_addr, 1);
-                        if (!new_address)
-                                return log_oom();
-
-                        memcpy(new_address->s6_addr, address->s6_addr, 8);
-                        memcpy(new_address->s6_addr + 8, j->prefix.s6_addr + 8, 8);
-                }
-
-                if (new_address) {
-                        r = set_put(addresses, new_address);
-                        if (r < 0)
-                                return log_link_error_errno(link, r, "Failed to store SLAAC address: %m");
-                        else if (r == 0)
-                                log_link_debug_errno(link, r, "Generated SLAAC address is duplicated, ignoring.");
-                        else
-                                TAKE_PTR(new_address);
-                }
-        }
-
-        /* fall back to EUI-64 if no tokens provided addresses */
-        if (set_isempty(addresses)) {
-                _cleanup_free_ struct in6_addr *new_address = NULL;
-
-                new_address = newdup(struct in6_addr, address, 1);
-                if (!new_address)
-                        return log_oom();
-
-                r = generate_ipv6_eui_64_address(link, new_address);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Failed to generate EUI64 address: %m");
-
-                r = set_put(addresses, new_address);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Failed to store SLAAC address: %m");
-
-                TAKE_PTR(new_address);
-        }
-
-        *ret = TAKE_PTR(addresses);
-
-        return 0;
-}
-
 static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) {
         uint32_t lifetime_valid, lifetime_preferred;
         _cleanup_set_free_free_ Set *addresses = NULL;
@@ -1214,128 +1050,6 @@ void ndisc_flush(Link *link) {
         link->ndisc_dnssl = set_free(link->ndisc_dnssl);
 }
 
-static int ipv6token_new(IPv6Token **ret) {
-        IPv6Token *p;
-
-        p = new(IPv6Token, 1);
-        if (!p)
-                return -ENOMEM;
-
-        *p = (IPv6Token) {
-                 .address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_NONE,
-        };
-
-        *ret = TAKE_PTR(p);
-
-        return 0;
-}
-
-static void ipv6_token_hash_func(const IPv6Token *p, struct siphash *state) {
-        siphash24_compress(&p->address_generation_type, sizeof(p->address_generation_type), state);
-        siphash24_compress(&p->prefix, sizeof(p->prefix), state);
-}
-
-static int ipv6_token_compare_func(const IPv6Token *a, const IPv6Token *b) {
-        int r;
-
-        r = CMP(a->address_generation_type, b->address_generation_type);
-        if (r != 0)
-                return r;
-
-        return memcmp(&a->prefix, &b->prefix, sizeof(struct in6_addr));
-}
-
-DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
-                ipv6_token_hash_ops,
-                IPv6Token,
-                ipv6_token_hash_func,
-                ipv6_token_compare_func,
-                free);
-
-int config_parse_address_generation_type(
-                const char *unit,
-                const char *filename,
-                unsigned line,
-                const char *section,
-                unsigned section_line,
-                const char *lvalue,
-                int ltype,
-                const char *rvalue,
-                void *data,
-                void *userdata) {
-
-        _cleanup_free_ IPv6Token *token = NULL;
-        union in_addr_union buffer;
-        Network *network = data;
-        const char *p;
-        int r;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        if (isempty(rvalue)) {
-                network->ipv6_tokens = ordered_set_free(network->ipv6_tokens);
-                return 0;
-        }
-
-        r = ipv6token_new(&token);
-        if (r < 0)
-                return log_oom();
-
-        if ((p = startswith(rvalue, "prefixstable"))) {
-                token->address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE;
-                if (*p == ':')
-                        p++;
-                else if (*p == '\0')
-                        p = NULL;
-                else {
-                        log_syntax(unit, LOG_WARNING, filename, line, 0,
-                                   "Invalid IPv6 token mode in %s=, ignoring assignment: %s",
-                                   lvalue, rvalue);
-                        return 0;
-                }
-        } else {
-                token->address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_STATIC;
-                p = startswith(rvalue, "static:");
-                if (!p)
-                        p = rvalue;
-        }
-
-        if (p) {
-                r = in_addr_from_string(AF_INET6, p, &buffer);
-                if (r < 0) {
-                        log_syntax(unit, LOG_WARNING, filename, line, r,
-                                   "Failed to parse IP address in %s=, ignoring assignment: %s",
-                                   lvalue, rvalue);
-                        return 0;
-                }
-                if (token->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_STATIC &&
-                    in_addr_is_null(AF_INET6, &buffer)) {
-                        log_syntax(unit, LOG_WARNING, filename, line, 0,
-                                   "IPv6 address in %s= cannot be the ANY address, ignoring assignment: %s",
-                                   lvalue, rvalue);
-                        return 0;
-                }
-                token->prefix = buffer.in6;
-        }
-
-        r = ordered_set_ensure_put(&network->ipv6_tokens, &ipv6_token_hash_ops, token);
-        if (r == -ENOMEM)
-                return log_oom();
-        if (r == -EEXIST)
-                log_syntax(unit, LOG_DEBUG, filename, line, r,
-                           "IPv6 token '%s' is duplicated, ignoring: %m", rvalue);
-        else if (r < 0)
-                log_syntax(unit, LOG_WARNING, filename, line, r,
-                           "Failed to store IPv6 token '%s', ignoring: %m", rvalue);
-        else
-                TAKE_PTR(token);
-
-        return 0;
-}
-
 static const char* const ipv6_accept_ra_start_dhcp6_client_table[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX] = {
         [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO]     = "no",
         [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS] = "always",
index 514089c2259a967726c1b48634fd503eee8e0866..ed50ebbf9a742870ffcbf11d71fe433734549a61 100644 (file)
@@ -44,6 +44,5 @@ int ndisc_start(Link *link);
 void ndisc_vacuum(Link *link);
 void ndisc_flush(Link *link);
 
-CONFIG_PARSER_PROTOTYPE(config_parse_address_generation_type);
 CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_accept_ra_start_dhcp6_client);
 CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_accept_ra_use_domains);
index 29bb5b3b7394cafc88fb70e54eb94fd387a15f95..6794ac40dbaa717367274b50967f80b1dd4b54d2 100644 (file)
@@ -8,6 +8,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
 #include "in-addr-prefix-util.h"
 #include "netem.h"
 #include "net-condition.h"
+#include "networkd-address-generation.h"
 #include "networkd-address-label.h"
 #include "networkd-address.h"
 #include "networkd-bridge-fdb.h"
index 6a873d7669118dde88a792b5c3795566d7b22faa..82b8e8bf3bbfbef2af28fe5603894c52a9d65764 100644 (file)
@@ -7,6 +7,7 @@
 #include <arpa/inet.h>
 
 #include "dns-domain.h"
+#include "networkd-address-generation.h"
 #include "networkd-address.h"
 #include "networkd-link.h"
 #include "networkd-manager.h"