]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: disable kernel creating prefix route when RouteTable= is set
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 22 Jul 2019 02:22:28 +0000 (11:22 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 22 Jul 2019 02:34:22 +0000 (11:34 +0900)
Closes #8726.

src/network/networkd-dhcp4.c
test/test-network/systemd-networkd-tests.py

index f20254fc827d58b90b780116c0fab4468529efea..356b9e9d316a331bfeff242583338713cb5b939b 100644 (file)
@@ -85,6 +85,11 @@ static int route_scope_from_address(const Route *route, const struct in_addr *se
                 return RT_SCOPE_UNIVERSE;
 }
 
+static bool link_noprefixroute(Link *link) {
+        return link->network->dhcp_route_table_set &&
+                link->network->dhcp_route_table != RT_TABLE_MAIN;
+}
+
 static int dhcp_route_configure(Route **route, Link *link) {
         int r;
 
@@ -193,6 +198,31 @@ static int link_set_dhcp_routes(Link *link) {
         if (r < 0)
                 return log_link_warning_errno(link, r, "DHCP error: could not get address: %m");
 
+        if (link_noprefixroute(link)) {
+                _cleanup_(route_freep) Route *prefix_route = NULL;
+                struct in_addr netmask;
+
+                r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "DHCP error: No netmask: %m");
+
+                r = route_new(&prefix_route);
+                if (r < 0)
+                        return log_link_error_errno(link, r,  "Could not allocate route: %m");
+
+                prefix_route->family = AF_INET;
+                prefix_route->dst.in.s_addr = address.s_addr & netmask.s_addr;
+                prefix_route->dst_prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
+                prefix_route->prefsrc.in = address;
+                prefix_route->scope = RT_SCOPE_LINK;
+                prefix_route->protocol = RTPROT_DHCP;
+                prefix_route->table = table;
+
+                r = dhcp_route_configure(&prefix_route, link);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not set prefix route: %m");
+        }
+
         n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes);
         if (n == -ENODATA)
                 log_link_debug_errno(link, n, "DHCP: No routes received from DHCP server: %m");
@@ -443,6 +473,30 @@ static int dhcp_remove_dns_routes(Link *link, sd_dhcp_lease *lease, const struct
                 (void) route_remove(route, link, NULL);
         }
 
+        if (link_noprefixroute(link)) {
+                _cleanup_(route_freep) Route *prefix_route = NULL;
+                struct in_addr netmask;
+
+                r = route_new(&prefix_route);
+                if (r < 0)
+                        return log_link_error_errno(link, r,  "Could not allocate route: %m");
+
+                r = sd_dhcp_lease_get_netmask(lease, &netmask);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "DHCP error: No netmask: %m");
+
+                prefix_route->family = AF_INET;
+                prefix_route->dst.in.s_addr = address->s_addr & netmask.s_addr;
+                prefix_route->dst_prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
+                prefix_route->prefsrc.in = *address;
+                prefix_route->scope = RT_SCOPE_LINK;
+                prefix_route->protocol = RTPROT_DHCP;
+                prefix_route->table = table;
+
+                if (remove_all || !set_contains(link->dhcp_routes, prefix_route))
+                        (void) route_remove(prefix_route, link, NULL);
+        }
+
         return 0;
 }
 
@@ -610,6 +664,7 @@ static int dhcp4_update_address(Link *link,
         addr->cinfo.ifa_valid = lifetime;
         addr->prefixlen = prefixlen;
         addr->broadcast.s_addr = address->s_addr | ~netmask->s_addr;
+        addr->prefix_route = link_noprefixroute(link);
 
         /* allow reusing an existing address and simply update its lifetime
          * in case it already exists */
index d73895aeab1b548f1a479644ca1e4db905ecdc06..171df79eca496984f41549d83b19d36aa415eee7 100755 (executable)
@@ -2465,16 +2465,17 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         self.assertRegex(output, '192.168.5')
         self.assertRegex(output, '1492')
 
-        # issue #8726
         print('## ip route show table main dev veth99')
         output = check_output('ip route show table main dev veth99')
         print(output)
-        self.assertNotRegex(output, 'proto dhcp')
+        # See issue #8726
+        self.assertEqual(output, '')
 
         print('## ip route show table 211 dev veth99')
         output = check_output('ip route show table 211 dev veth99')
         print(output)
         self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
+        self.assertRegex(output, '192.168.5.0/24 proto dhcp')
         self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
         self.assertRegex(output, '192.168.5.1 proto dhcp scope link')