]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: dhcp6pd: assign addresses in the delegated prefix instead of a subnet prefix...
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 5 Dec 2021 12:38:48 +0000 (21:38 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 7 Dec 2021 10:46:37 +0000 (19:46 +0900)
src/network/networkd-address-generation.c
src/network/networkd-address-generation.h
src/network/networkd-dhcp-prefix-delegation.c
test/test-network/systemd-networkd-tests.py

index 739ca97c2ed1e983a0aad93f7d7f7a0bae14ab15..4cf4dd590eeb7038e0b21759ec82f04ef231c311 100644 (file)
@@ -252,8 +252,8 @@ static int generate_addresses(
         return 0;
 }
 
-int dhcp6_pd_generate_addresses(Link *link, const struct in6_addr *prefix, Set **ret) {
-        return generate_addresses(link, link->network->dhcp6_pd_tokens, &DHCP6PD_APP_ID, prefix, 64, ret);
+int dhcp6_pd_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret) {
+        return generate_addresses(link, link->network->dhcp6_pd_tokens, &DHCP6PD_APP_ID, prefix, prefixlen, ret);
 }
 
 int ndisc_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret) {
index 391a6ccc970820f7c053d402c137e5a970582690..d8d9d6e8f0e30918c852fa3e39e274e11b5aad81 100644 (file)
@@ -7,7 +7,7 @@
 
 typedef struct Link Link;
 
-int dhcp6_pd_generate_addresses(Link *link, const struct in6_addr *prefix, Set **ret);
+int dhcp6_pd_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, Set **ret);
 int radv_generate_addresses(Link *link, Set *tokens, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret);
 
index 61df70fd55d8cf079b0186e9599e6f4ab604a45d..f32c2cbed5ed0aac067246e9b0ac250b175d44ec 100644 (file)
@@ -296,7 +296,7 @@ static int dhcp6_pd_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
         return 1;
 }
 
-static int dhcp6_pd_request_route(Link *link, const struct in6_addr *prefix, usec_t lifetime_usec) {
+static int dhcp6_pd_request_route(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, usec_t lifetime_usec) {
         _cleanup_(route_freep) Route *route = NULL;
         Route *existing;
         int r;
@@ -315,7 +315,7 @@ static int dhcp6_pd_request_route(Link *link, const struct in6_addr *prefix, use
         route->source = NETWORK_CONFIG_SOURCE_DHCP6PD;
         route->family = AF_INET6;
         route->dst.in6 = *prefix;
-        route->dst_prefixlen = 64;
+        route->dst_prefixlen = prefixlen;
         route->protocol = RTPROT_DHCP;
         route->priority = link->network->dhcp6_pd_route_metric;
         route->lifetime_usec = lifetime_usec;
@@ -375,6 +375,7 @@ static void log_dhcp6_pd_address(Link *link, const Address *address) {
 static int dhcp6_pd_request_address(
                 Link *link,
                 const struct in6_addr *prefix,
+                uint8_t prefixlen,
                 usec_t lifetime_preferred_usec,
                 usec_t lifetime_valid_usec) {
 
@@ -389,7 +390,7 @@ static int dhcp6_pd_request_address(
         if (!link->network->dhcp6_pd_assign)
                 return 0;
 
-        r = dhcp6_pd_generate_addresses(link, prefix, &addresses);
+        r = dhcp6_pd_generate_addresses(link, prefix, prefixlen, &addresses);
         if (r < 0)
                 return log_link_warning_errno(link, r, "Failed to generate addresses for acquired DHCPv6 delegated prefix: %m");
 
@@ -404,10 +405,11 @@ static int dhcp6_pd_request_address(
                 address->source = NETWORK_CONFIG_SOURCE_DHCP6PD;
                 address->family = AF_INET6;
                 address->in_addr.in6 = *a;
-                address->prefixlen = 64;
+                address->prefixlen = prefixlen;
                 address->lifetime_preferred_usec = lifetime_preferred_usec;
                 address->lifetime_valid_usec = lifetime_valid_usec;
-                SET_FLAG(address->flags, IFA_F_MANAGETEMPADDR, link->network->dhcp6_pd_manage_temporary_address);
+                if (prefixlen == 64)
+                        SET_FLAG(address->flags, IFA_F_MANAGETEMPADDR, link->network->dhcp6_pd_manage_temporary_address);
                 address->route_metric = link->network->dhcp6_pd_route_metric;
 
                 log_dhcp6_pd_address(link, address);
@@ -542,13 +544,13 @@ static int dhcp6_pd_assign_prefix(
                                                       strna(buf));
         }
 
-        r = dhcp6_pd_request_route(link, &prefix, lifetime_valid_usec);
+        r = dhcp6_pd_request_route(link, &prefix, 64, lifetime_valid_usec);
         if (r < 0)
                 return log_link_warning_errno(link, r,
                                               "Failed to assign/update route for prefix %s: %m",
                                               strna(buf));
 
-        r = dhcp6_pd_request_address(link, &prefix, lifetime_preferred_usec, lifetime_valid_usec);
+        r = dhcp6_pd_request_address(link, &prefix, 64, lifetime_preferred_usec, lifetime_valid_usec);
         if (r < 0)
                 return log_link_warning_errno(link, r,
                                               "Failed to assign/update address for prefix %s: %m",
@@ -564,6 +566,41 @@ static int dhcp6_pd_assign_prefix(
         return 1;
 }
 
+static int dhcp6_pd_assign_prefix_on_uplink(
+                Link *link,
+                const struct in6_addr *pd_prefix,
+                uint8_t pd_prefix_len,
+                usec_t lifetime_preferred_usec,
+                usec_t lifetime_valid_usec) {
+
+        _cleanup_free_ char *buf = NULL;
+        int r;
+
+        assert(link);
+        assert(link->network);
+        assert(pd_prefix);
+
+        (void) in6_addr_prefix_to_string(pd_prefix, pd_prefix_len, &buf);
+
+        if (link->network->dhcp6_pd_announce)
+                log_link_debug(link, "Ignoring Announce= setting on upstream interface.");
+
+        r = dhcp6_pd_request_route(link, pd_prefix, pd_prefix_len, lifetime_valid_usec);
+        if (r < 0)
+                return log_link_warning_errno(link, r,
+                                              "Failed to assign/update route for prefix %s: %m",
+                                              strna(buf));
+
+        r = dhcp6_pd_request_address(link, pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec);
+        if (r < 0)
+                return log_link_warning_errno(link, r,
+                                              "Failed to assign/update address for prefix %s: %m",
+                                              strna(buf));
+
+        log_link_debug(link, "Assigned prefix %s", strna(buf));
+        return 1;
+}
+
 static int dhcp6_pd_prepare(Link *link) {
         if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
                 return 0;
@@ -778,7 +815,10 @@ static int dhcp6_pd_assign_prefixes(Link *link, Link *uplink) {
                 lifetime_preferred_usec = usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec);
                 lifetime_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec);
 
-                r = dhcp6_pd_assign_prefix(link, &pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec);
+                if (link == uplink)
+                        r = dhcp6_pd_assign_prefix_on_uplink(link, &pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec);
+                else
+                        r = dhcp6_pd_assign_prefix(link, &pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec);
                 if (r < 0)
                         return r;
         }
index 99eb89e3ee079ad1787583d782b56e6483aae945..f9af5f14d30ac18070f76ed101d0fe49ae82f1a5 100755 (executable)
@@ -5063,7 +5063,7 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities):
         dummy99: auto -> 0x03 (No address assignment)
         veth97:  0x08
         veth98:  0x09
-        veth99:  0x10
+        veth99:  0x10 (ignored, as it is upstream)
         '''
 
         print('### ip -6 address show dev veth99 scope global')
@@ -5072,12 +5072,9 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities):
         # IA_NA
         self.assertRegex(output, 'inet6 3ffe:501:ffff:100::[0-9]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
         # address in IA_PD (Token=static)
-        self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]10:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
+        self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]00:1a:2b:3c:4d/56 (metric 256 |)scope global dynamic')
         # address in IA_PD (Token=eui64)
-        self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]10:1034:56ff:fe78:9abc/64 (metric 256 |)scope global dynamic mngtmpaddr')
-        # address in IA_PD (temporary)
-        # Note that the temporary addresses may appear after the link enters configured state
-        self.wait_address('veth99', 'inet6 3ffe:501:ffff:[2-9a-f]10:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
+        self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]00:1034:56ff:fe78:9abc/56 (metric 256 |)scope global dynamic')
 
         print('### ip -6 address show dev test1 scope global')
         output = check_output('ip -6 address show dev test1 scope global')
@@ -5085,6 +5082,7 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities):
         # address in IA_PD (Token=static)
         self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]00:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
         # address in IA_PD (temporary)
+        # Note that the temporary addresses may appear after the link enters configured state
         self.wait_address('test1', 'inet6 3ffe:501:ffff:[2-9a-f]00:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
 
         print('### ip -6 address show dev dummy98 scope global')
@@ -5149,7 +5147,7 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities):
         print('### ip -6 route show dev veth99')
         output = check_output('ip -6 route show dev veth99')
         print(output)
-        self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]10::/64 proto kernel metric [0-9]* expires')
+        self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]00::/56 proto kernel metric [0-9]* expires')
 
         print('### ip -6 route show dev test1')
         output = check_output('ip -6 route show dev test1')