From: Yu Watanabe Date: Fri, 24 Sep 2021 19:12:31 +0000 (+0900) Subject: network: introduce Token= setting in [IPv6Prefix] X-Git-Tag: v250-rc1~552^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e609cd0694ed6fe23f165f6b32312c77432baa4d;p=thirdparty%2Fsystemd.git network: introduce Token= setting in [IPv6Prefix] Closes #20149. --- diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 1459ba83d9b..77ed77918cf 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -2729,6 +2729,16 @@ Token=prefixstable:2002:da8:1:: + + Token= + + Specifies an optional address generation mode for assigning an address in each + prefix. This accepts the same syntax as Token= in the [IPv6AcceptRA] + section. If Assign= is set to false, then this setting will be ignored. + Defaults to unset, which means the EUI-64 algorithm will be used. + + + RouteMetric= diff --git a/src/network/networkd-address-generation.c b/src/network/networkd-address-generation.c index bea765a3b0d..04b80dee86e 100644 --- a/src/network/networkd-address-generation.c +++ b/src/network/networkd-address-generation.c @@ -22,6 +22,7 @@ #define DHCP6PD_APP_ID SD_ID128_MAKE(fb,b9,37,ca,4a,ed,4a,4d,b0,70,7f,aa,71,c0,c9,85) #define NDISC_APP_ID SD_ID128_MAKE(13,ac,81,a7,d5,3f,49,78,92,79,5d,0c,29,3a,bc,7e) +#define RADV_APP_ID SD_ID128_MAKE(1f,1e,90,c8,5c,78,4f,dc,8e,61,2d,59,0d,53,c1,25) typedef enum AddressGenerationType { ADDRESS_GENERATION_EUI64, @@ -236,6 +237,10 @@ int ndisc_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t 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) { + return generate_addresses(link, tokens, &RADV_APP_ID, prefix, prefixlen, ret); +} + static void ipv6_token_hash_func(const IPv6Token *p, struct siphash *state) { siphash24_compress(&p->type, sizeof(p->type), state); siphash24_compress(&p->address, sizeof(p->address), state); diff --git a/src/network/networkd-address-generation.h b/src/network/networkd-address-generation.h index 7e8b01e0a85..8aa5d4d3f58 100644 --- a/src/network/networkd-address-generation.h +++ b/src/network/networkd-address-generation.h @@ -11,5 +11,6 @@ void generate_eui64_address(const Link *link, const struct in6_addr *prefix, str int dhcp6_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); CONFIG_PARSER_PROTOTYPE(config_parse_address_generation_type); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index c8b1521d903..b670038d2ae 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -348,6 +348,7 @@ IPv6Prefix.ValidLifetimeSec, config_parse_prefix_lifetime, IPv6Prefix.PreferredLifetimeSec, config_parse_prefix_lifetime, 0, 0 IPv6Prefix.Assign, config_parse_prefix_assign, 0, 0 IPv6Prefix.RouteMetric, config_parse_prefix_metric, 0, 0 +IPv6Prefix.Token, config_parse_prefix_token, 0, 0 IPv6RoutePrefix.Route, config_parse_route_prefix, 0, 0 IPv6RoutePrefix.LifetimeSec, config_parse_route_prefix_lifetime, 0, 0 LLDP.MUDURL, config_parse_mud_url, 0, offsetof(Network, lldp_mudurl) diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index b9ba0ff9baa..34e6a41c34a 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -69,6 +69,7 @@ Prefix *prefix_free(Prefix *prefix) { network_config_section_free(prefix->section); sd_radv_prefix_unref(prefix->radv_prefix); + set_free(prefix->tokens); return mfree(prefix); } @@ -204,8 +205,8 @@ int link_request_radv_addresses(Link *link) { return 0; HASHMAP_FOREACH(p, link->network->prefixes_by_section) { - _cleanup_(address_freep) Address *address = NULL; - struct in6_addr prefix; + _cleanup_set_free_ Set *addresses = NULL; + struct in6_addr prefix, *a; uint8_t prefixlen; if (!p->assign) @@ -215,7 +216,7 @@ int link_request_radv_addresses(Link *link) { if (r < 0) return r; - /* generate_eui64_address() below requires the prefix length <= 64. */ + /* radv_generate_addresses() below requires the prefix length <= 64. */ if (prefixlen > 64) { _cleanup_free_ char *str = NULL; @@ -226,20 +227,27 @@ int link_request_radv_addresses(Link *link) { continue; } - r = address_new(&address); + r = radv_generate_addresses(link, p->tokens, &prefix, prefixlen, &addresses); if (r < 0) - return log_oom(); + return r; - generate_eui64_address(link, &prefix, &address->in_addr.in6); + SET_FOREACH(a, addresses) { + _cleanup_(address_freep) Address *address = NULL; - address->source = NETWORK_CONFIG_SOURCE_STATIC; - address->family = AF_INET6; - address->prefixlen = prefixlen; - address->route_metric = p->route_metric; + r = address_new(&address); + if (r < 0) + return -ENOMEM; - r = link_request_static_address(link, TAKE_PTR(address), true); - if (r < 0) - return r; + address->source = NETWORK_CONFIG_SOURCE_STATIC; + address->family = AF_INET6; + address->in_addr.in6 = *a; + address->prefixlen = prefixlen; + address->route_metric = p->route_metric; + + r = link_request_static_address(link, TAKE_PTR(address), true); + if (r < 0) + return r; + } } return 0; @@ -875,6 +883,41 @@ int config_parse_prefix_metric( return 0; } +int config_parse_prefix_token( + 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_(prefix_free_or_set_invalidp) Prefix *p = NULL; + Network *network = userdata; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(userdata); + + r = prefix_new_static(network, filename, section_line, &p); + if (r < 0) + return log_oom(); + + r = config_parse_address_generation_type(unit, filename, line, section, section_line, + lvalue, ltype, rvalue, &p->tokens, userdata); + if (r < 0) + return r; + + TAKE_PTR(p); + return 0; +} + int config_parse_route_prefix( const char *unit, const char *filename, diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h index aec3d3386fb..5c869d8623e 100644 --- a/src/network/networkd-radv.h +++ b/src/network/networkd-radv.h @@ -35,6 +35,7 @@ typedef struct Prefix { bool assign; uint32_t route_metric; + Set *tokens; } Prefix; typedef struct RoutePrefix { @@ -70,6 +71,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_prefix_flags); CONFIG_PARSER_PROTOTYPE(config_parse_prefix_lifetime); CONFIG_PARSER_PROTOTYPE(config_parse_prefix_assign); CONFIG_PARSER_PROTOTYPE(config_parse_prefix_metric); +CONFIG_PARSER_PROTOTYPE(config_parse_prefix_token); CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns); CONFIG_PARSER_PROTOTYPE(config_parse_radv_search_domains); CONFIG_PARSER_PROTOTYPE(config_parse_route_prefix); diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 9b5ecccedbb..ea02d4c640f 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -247,6 +247,7 @@ PreferredLifetimeSec= AddressAutoconfiguration= ValidLifetimeSec= Assign= +Token= RouteMetric= [IPv6RoutePrefix] Route=