]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: introduce Token= setting in [IPv6Prefix]
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 24 Sep 2021 19:12:31 +0000 (04:12 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 6 Oct 2021 16:24:50 +0000 (01:24 +0900)
Closes #20149.

man/systemd.network.xml
src/network/networkd-address-generation.c
src/network/networkd-address-generation.h
src/network/networkd-network-gperf.gperf
src/network/networkd-radv.c
src/network/networkd-radv.h
test/fuzz/fuzz-network-parser/directives.network

index 1459ba83d9b545b44c3e8f43a91b693bc8bc6d27..77ed77918cf6273933a50fcec09acef368715c2a 100644 (file)
@@ -2729,6 +2729,16 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
         </para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>Token=</varname></term>
+        <listitem>
+          <para>Specifies an optional address generation mode for assigning an address in each
+          prefix. This accepts the same syntax as <varname>Token=</varname> in the [IPv6AcceptRA]
+          section. If <varname>Assign=</varname> is set to false, then this setting will be ignored.
+          Defaults to unset, which means the EUI-64 algorithm will be used.</para>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>RouteMetric=</varname></term>
         <listitem>
index bea765a3b0db11a2d145521a84baab4e10c23b50..04b80dee86e40f84251c8d88b5069654081ab201 100644 (file)
@@ -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);
index 7e8b01e0a85a1cd5af955fa3e11236349b90db93..8aa5d4d3f582aad4b2994ed35e620c5501fe7b12 100644 (file)
@@ -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);
index c8b1521d903277a6d08e121780207824f76b77f1..b670038d2ae43d9ce5451b45c1eb8aa3f12ccd54 100644 (file)
@@ -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)
index b9ba0ff9baaa49ed1962446851f91e724c0ab62f..34e6a41c34a536e2cace85557db3c9a6b2d27c3a 100644 (file)
@@ -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,
index aec3d3386fb1482c0400eacd70f02d3a5e563127..5c869d8623e61c7bc8df47f940318bf873b03720 100644 (file)
@@ -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);
index 9b5ecccedbbc4d2d1336c99c063780be1e36869f..ea02d4c640fba2466a20ec4573fffc9e01e72dfe 100644 (file)
@@ -247,6 +247,7 @@ PreferredLifetimeSec=
 AddressAutoconfiguration=
 ValidLifetimeSec=
 Assign=
+Token=
 RouteMetric=
 [IPv6RoutePrefix]
 Route=