]> git.proxmox.com Git - systemd.git/commitdiff
Cherry-pick fix from upstream master to adjust UseGateway= default
authorDan Streetman <ddstreet@canonical.com>
Fri, 8 May 2020 20:00:46 +0000 (16:00 -0400)
committerDan Streetman <ddstreet@canonical.com>
Fri, 8 May 2020 20:05:30 +0000 (16:05 -0400)
- network: change UseGateway= default to UseRoutes= setting
- network: honor SetDNSRoutes= even if UseGateway=False

LP: #1867375

debian/patches/network-change-UseGateway-default-to-UseRoutes-setting.patch [new file with mode: 0644]
debian/patches/network-honor-SetDNSRoutes-even-if-UseGateway-False.patch [new file with mode: 0644]
debian/patches/series
debian/patches/test-modify-add-tests-for-UseRoutes-and-UseGateway-config.patch [new file with mode: 0644]
debian/patches/test-verify-RoutesToDNS-is-independent-of-UseGateway.patch [new file with mode: 0644]

diff --git a/debian/patches/network-change-UseGateway-default-to-UseRoutes-setting.patch b/debian/patches/network-change-UseGateway-default-to-UseRoutes-setting.patch
new file mode 100644 (file)
index 0000000..57ff350
--- /dev/null
@@ -0,0 +1,84 @@
+From: Dan Streetman <ddstreet@canonical.com>
+Date: Wed, 15 Apr 2020 14:40:21 -0400
+Subject: network: change UseGateway= default to UseRoutes= setting
+
+Anyone previously using the UseRoutes=false parameter expected their
+dhcp4-provided gateway route to be ignored, as well.  However, with
+the introduction of the UseGateway= parameter, this is no longer true.
+
+In order to keep backwards compatibility, this sets the UseGateway=
+default value to whatever UseRoutes= has been set to.
+
+(cherry picked from commit 589397a27759bd650b3674029cb0ef73347c913b)
+---
+ man/systemd.network.xml                  | 5 +++--
+ src/network/networkd-network-gperf.gperf | 2 +-
+ src/network/networkd-network.c           | 5 ++++-
+ src/network/networkd-network.h           | 2 +-
+ 4 files changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/man/systemd.network.xml b/man/systemd.network.xml
+index 120347d..5175704 100644
+--- a/man/systemd.network.xml
++++ b/man/systemd.network.xml
+@@ -1477,8 +1477,9 @@
+         <varlistentry>
+           <term><varname>UseGateway=</varname></term>
+           <listitem>
+-            <para>When true (the default), the gateway will be requested from the DHCP server and added to the
+-            routing table with a metric of 1024, and a scope of "link".</para>
++            <para>When true, the gateway will be requested from the DHCP server and added to the routing table with a
++            metric of 1024, and a scope of "link".  When unset, the value specified with <option>UseRoutes=</option>
++            is used.</para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
+index d3dda3d..1a07ae9 100644
+--- a/src/network/networkd-network-gperf.gperf
++++ b/src/network/networkd-network-gperf.gperf
+@@ -162,7 +162,7 @@ DHCPv4.UseMTU,                               config_parse_bool,
+ DHCPv4.UseHostname,                          config_parse_bool,                                        0,                             offsetof(Network, dhcp_use_hostname)
+ DHCPv4.UseDomains,                           config_parse_dhcp_use_domains,                            0,                             offsetof(Network, dhcp_use_domains)
+ DHCPv4.UseRoutes,                            config_parse_bool,                                        0,                             offsetof(Network, dhcp_use_routes)
+-DHCPv4.UseGateway,                           config_parse_bool,                                        0,                             offsetof(Network, dhcp_use_gateway)
++DHCPv4.UseGateway,                           config_parse_tristate,                                    0,                             offsetof(Network, dhcp_use_gateway)
+ DHCPv4.RequestOptions,                       config_parse_dhcp_request_options,                        0,                             0
+ DHCPv4.Anonymize,                            config_parse_bool,                                        0,                             offsetof(Network, dhcp_anonymize)
+ DHCPv4.SendHostname,                         config_parse_bool,                                        0,                             offsetof(Network, dhcp_send_hostname)
+diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
+index c643419..093d298 100644
+--- a/src/network/networkd-network.c
++++ b/src/network/networkd-network.c
+@@ -265,6 +265,9 @@ int network_verify(Network *network) {
+                 network->dhcp_use_mtu = false;
+         }
++        if (network->dhcp_use_gateway < 0)
++                network->dhcp_use_gateway = network->dhcp_use_routes;
++
+         if (network->dhcp_critical >= 0) {
+                 if (network->keep_configuration >= 0)
+                         log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
+@@ -383,7 +386,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
+                 .dhcp_use_dns = true,
+                 .dhcp_use_hostname = true,
+                 .dhcp_use_routes = true,
+-                .dhcp_use_gateway = true,
++                .dhcp_use_gateway = -1,
+                 /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
+                 .dhcp_send_hostname = true,
+                 .dhcp_send_release = true,
+diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
+index 0d46dbb..6231618 100644
+--- a/src/network/networkd-network.h
++++ b/src/network/networkd-network.h
+@@ -110,7 +110,7 @@ struct Network {
+         bool dhcp_use_sip;
+         bool dhcp_use_mtu;
+         bool dhcp_use_routes;
+-        bool dhcp_use_gateway;
++        int dhcp_use_gateway;
+         bool dhcp_use_timezone;
+         bool rapid_commit;
+         bool dhcp_use_hostname;
diff --git a/debian/patches/network-honor-SetDNSRoutes-even-if-UseGateway-False.patch b/debian/patches/network-honor-SetDNSRoutes-even-if-UseGateway-False.patch
new file mode 100644 (file)
index 0000000..5035ed8
--- /dev/null
@@ -0,0 +1,156 @@
+From: Dan Streetman <ddstreet@canonical.com>
+Date: Wed, 15 Apr 2020 18:05:14 -0400
+Subject: network: honor SetDNSRoutes= even if UseGateway=False
+
+(cherry picked from commit 244490f5e0a98f83190e92033fbdaa1bbcd9b000)
+---
+ src/network/networkd-dhcp4.c | 129 +++++++++++++++++++++----------------------
+ 1 file changed, 64 insertions(+), 65 deletions(-)
+
+diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
+index 3f65804..f2b9def 100644
+--- a/src/network/networkd-dhcp4.c
++++ b/src/network/networkd-dhcp4.c
+@@ -323,78 +323,77 @@ static int link_set_dhcp_routes(Link *link) {
+                 }
+         }
+-        if (!link->network->dhcp_use_gateway)
+-                return 0;
+-
+-        r = sd_dhcp_lease_get_router(link->dhcp_lease, &router);
+-        if (IN_SET(r, 0, -ENODATA))
+-                log_link_info(link, "DHCP: No gateway received from DHCP server.");
+-        else if (r < 0)
+-                log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m");
+-        else if (in4_addr_is_null(&router[0]))
+-                log_link_info(link, "DHCP: Received gateway is null.");
+-
+-        /* According to RFC 3442: If the DHCP server returns both a Classless Static Routes option and
+-           a Router option, the DHCP client MUST ignore the Router option. */
+-        if (classless_route && static_route)
+-                log_link_warning(link, "Classless static routes received from DHCP server: ignoring static-route option and router option");
+-
+-        if (r > 0 && !classless_route && !in4_addr_is_null(&router[0])) {
+-                _cleanup_(route_freep) Route *route = NULL, *route_gw = NULL;
+-
+-                r = route_new(&route_gw);
+-                if (r < 0)
+-                        return log_link_error_errno(link, r,  "Could not allocate route: %m");
+-
+-                /* The dhcp netmask may mask out the gateway. Add an explicit
+-                 * route for the gw host so that we can route no matter the
+-                 * netmask or existing kernel route tables. */
+-                route_gw->family = AF_INET;
+-                route_gw->dst.in = router[0];
+-                route_gw->dst_prefixlen = 32;
+-                route_gw->prefsrc.in = address;
+-                route_gw->scope = RT_SCOPE_LINK;
+-                route_gw->protocol = RTPROT_DHCP;
+-                route_gw->priority = link->network->dhcp_route_metric;
+-                route_gw->table = table;
+-                route_gw->mtu = link->network->dhcp_route_mtu;
+-
+-                r = dhcp_route_configure(&route_gw, link);
+-                if (r < 0)
+-                        return log_link_error_errno(link, r, "Could not set host route: %m");
++        if (link->network->dhcp_use_gateway) {
++                r = sd_dhcp_lease_get_router(link->dhcp_lease, &router);
++                if (IN_SET(r, 0, -ENODATA))
++                        log_link_info(link, "DHCP: No gateway received from DHCP server.");
++                else if (r < 0)
++                        log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m");
++                else if (in4_addr_is_null(&router[0]))
++                        log_link_info(link, "DHCP: Received gateway is null.");
++
++                /* According to RFC 3442: If the DHCP server returns both a Classless Static Routes option and
++                   a Router option, the DHCP client MUST ignore the Router option. */
++                if (classless_route && static_route)
++                        log_link_warning(link, "Classless static routes received from DHCP server: ignoring static-route option and router option");
++
++                if (r > 0 && !classless_route && !in4_addr_is_null(&router[0])) {
++                        _cleanup_(route_freep) Route *route = NULL, *route_gw = NULL;
++
++                        r = route_new(&route_gw);
++                        if (r < 0)
++                                return log_link_error_errno(link, r,  "Could not allocate route: %m");
++
++                        /* The dhcp netmask may mask out the gateway. Add an explicit
++                         * route for the gw host so that we can route no matter the
++                         * netmask or existing kernel route tables. */
++                        route_gw->family = AF_INET;
++                        route_gw->dst.in = router[0];
++                        route_gw->dst_prefixlen = 32;
++                        route_gw->prefsrc.in = address;
++                        route_gw->scope = RT_SCOPE_LINK;
++                        route_gw->protocol = RTPROT_DHCP;
++                        route_gw->priority = link->network->dhcp_route_metric;
++                        route_gw->table = table;
++                        route_gw->mtu = link->network->dhcp_route_mtu;
++
++                        r = dhcp_route_configure(&route_gw, link);
++                        if (r < 0)
++                                return log_link_error_errno(link, r, "Could not set host route: %m");
+-                r = route_new(&route);
+-                if (r < 0)
+-                        return log_link_error_errno(link, r, "Could not allocate route: %m");
++                        r = route_new(&route);
++                        if (r < 0)
++                                return log_link_error_errno(link, r, "Could not allocate route: %m");
+-                route->family = AF_INET;
+-                route->gw.in = router[0];
+-                route->prefsrc.in = address;
+-                route->protocol = RTPROT_DHCP;
+-                route->priority = link->network->dhcp_route_metric;
+-                route->table = table;
+-                route->mtu = link->network->dhcp_route_mtu;
++                        route->family = AF_INET;
++                        route->gw.in = router[0];
++                        route->prefsrc.in = address;
++                        route->protocol = RTPROT_DHCP;
++                        route->priority = link->network->dhcp_route_metric;
++                        route->table = table;
++                        route->mtu = link->network->dhcp_route_mtu;
+-                r = dhcp_route_configure(&route, link);
+-                if (r < 0)
+-                        return log_link_error_errno(link, r, "Could not set router: %m");
+-        }
++                        r = dhcp_route_configure(&route, link);
++                        if (r < 0)
++                                return log_link_error_errno(link, r, "Could not set router: %m");
++                }
+-        Route *rt;
+-        LIST_FOREACH(routes, rt, link->network->static_routes) {
+-                if (!rt->gateway_from_dhcp)
+-                        continue;
++                Route *rt;
++                LIST_FOREACH(routes, rt, link->network->static_routes) {
++                        if (!rt->gateway_from_dhcp)
++                                continue;
+-                if (rt->family != AF_INET)
+-                        continue;
++                        if (rt->family != AF_INET)
++                                continue;
+-                rt->gw.in = router[0];
++                        rt->gw.in = router[0];
+-                r = route_configure(rt, link, dhcp4_route_handler);
+-                if (r < 0)
+-                        return log_link_error_errno(link, r, "Could not set gateway: %m");
+-                if (r > 0)
+-                        link->dhcp4_messages++;
++                        r = route_configure(rt, link, dhcp4_route_handler);
++                        if (r < 0)
++                                return log_link_error_errno(link, r, "Could not set gateway: %m");
++                        if (r > 0)
++                                link->dhcp4_messages++;
++                }
+         }
+         return link_set_dns_routes(link, &address);
index 91d8bc7b237617b543adac3fcb951605c14155f4..4de21d20c0b63d0c91013f979f8361f9f33938c5 100644 (file)
@@ -7,6 +7,10 @@ units-drop-systemd-remount-fs.service-dependency-from-mor.patch
 units-make-sure-systemd-pstore-stops-at-shutdown.patch
 network-add-a-flag-to-ignore-gateway-provided-by-DHCP-ser.patch
 test-network-add-a-test-case-for-DHCPv4.UseGateway-no.patch
+network-change-UseGateway-default-to-UseRoutes-setting.patch
+test-modify-add-tests-for-UseRoutes-and-UseGateway-config.patch
+network-honor-SetDNSRoutes-even-if-UseGateway-False.patch
+test-verify-RoutesToDNS-is-independent-of-UseGateway.patch
 userdb-when-doing-client-side-NSS-look-ups-optionally-avo.patch
 basic-add-_cleanup_-wrappers-for-pthread_mutex_-lock-unlo.patch
 nss-systemd-use-_cleanup_-for-pthread_mutex_-lock-unlock.patch
diff --git a/debian/patches/test-modify-add-tests-for-UseRoutes-and-UseGateway-config.patch b/debian/patches/test-modify-add-tests-for-UseRoutes-and-UseGateway-config.patch
new file mode 100644 (file)
index 0000000..8bc1a27
--- /dev/null
@@ -0,0 +1,210 @@
+From: Dan Streetman <ddstreet@canonical.com>
+Date: Wed, 15 Apr 2020 16:26:20 -0400
+Subject: test: modify/add tests for UseRoutes= and UseGateway= configuration
+
+The last commit changed the UseGateway= default to the value of UseRoutes=
+so the tests need to check for all combinations of the two parameters.
+
+(cherry picked from commit 7c0d36ff5fc31d00e26661fd2ad45291ed0eb6f7)
+---
+ .../conf/dhcp-client-ipv4-use-gateway-no.network   |  9 ----
+ .../conf/dhcp-client-ipv4-use-routes-no.network    |  9 ----
+ ...dhcp-client-ipv4-use-routes-use-gateway.network |  9 ++++
+ .../use-gateway-False.conf                         |  2 +
+ .../use-gateway-True.conf                          |  2 +
+ .../use-routes-False.conf                          |  2 +
+ .../use-routes-True.conf                           |  2 +
+ test/test-network/systemd-networkd-tests.py        | 58 +++++++++++++++-------
+ 8 files changed, 56 insertions(+), 37 deletions(-)
+ delete mode 100644 test/test-network/conf/dhcp-client-ipv4-use-gateway-no.network
+ delete mode 100644 test/test-network/conf/dhcp-client-ipv4-use-routes-no.network
+ create mode 100644 test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network
+ create mode 100644 test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-gateway-False.conf
+ create mode 100644 test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-gateway-True.conf
+ create mode 100644 test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-routes-False.conf
+ create mode 100644 test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-routes-True.conf
+
+diff --git a/test/test-network/conf/dhcp-client-ipv4-use-gateway-no.network b/test/test-network/conf/dhcp-client-ipv4-use-gateway-no.network
+deleted file mode 100644
+index fb31772..0000000
+--- a/test/test-network/conf/dhcp-client-ipv4-use-gateway-no.network
++++ /dev/null
+@@ -1,9 +0,0 @@
+-[Match]
+-Name=veth99
+-
+-[Network]
+-DHCP=ipv4
+-IPv6AcceptRA=false
+-
+-[DHCPv4]
+-UseGateway=no
+diff --git a/test/test-network/conf/dhcp-client-ipv4-use-routes-no.network b/test/test-network/conf/dhcp-client-ipv4-use-routes-no.network
+deleted file mode 100644
+index 21e21fa..0000000
+--- a/test/test-network/conf/dhcp-client-ipv4-use-routes-no.network
++++ /dev/null
+@@ -1,9 +0,0 @@
+-[Match]
+-Name=veth99
+-
+-[Network]
+-DHCP=ipv4
+-IPv6AcceptRA=false
+-
+-[DHCPv4]
+-UseRoutes=no
+diff --git a/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network b/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network
+new file mode 100644
+index 0000000..b0d0d86
+--- /dev/null
++++ b/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network
+@@ -0,0 +1,9 @@
++[Match]
++Name=veth99
++
++[Network]
++DHCP=ipv4
++IPv6AcceptRA=false
++
++[DHCPv4]
++RoutesToDNS=yes
+diff --git a/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-gateway-False.conf b/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-gateway-False.conf
+new file mode 100644
+index 0000000..78d0493
+--- /dev/null
++++ b/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-gateway-False.conf
+@@ -0,0 +1,2 @@
++[DHCPv4]
++UseGateway=no
+diff --git a/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-gateway-True.conf b/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-gateway-True.conf
+new file mode 100644
+index 0000000..f6f597b
+--- /dev/null
++++ b/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-gateway-True.conf
+@@ -0,0 +1,2 @@
++[DHCPv4]
++UseGateway=yes
+diff --git a/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-routes-False.conf b/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-routes-False.conf
+new file mode 100644
+index 0000000..38fa983
+--- /dev/null
++++ b/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-routes-False.conf
+@@ -0,0 +1,2 @@
++[DHCPv4]
++UseRoutes=no
+diff --git a/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-routes-True.conf b/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-routes-True.conf
+new file mode 100644
+index 0000000..3b2d0ab
+--- /dev/null
++++ b/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-routes-True.conf
+@@ -0,0 +1,2 @@
++[DHCPv4]
++UseRoutes=yes
+diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py
+index f7b6974..798e155 100755
+--- a/test/test-network/systemd-networkd-tests.py
++++ b/test/test-network/systemd-networkd-tests.py
+@@ -3,6 +3,7 @@
+ # systemd-networkd tests
+ import argparse
++import itertools
+ import os
+ import re
+ import shutil
+@@ -2826,8 +2827,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
+         'dhcp-client-ipv4-dhcp-settings.network',
+         'dhcp-client-ipv4-only-ipv6-disabled.network',
+         'dhcp-client-ipv4-only.network',
+-        'dhcp-client-ipv4-use-gateway-no.network',
+-        'dhcp-client-ipv4-use-routes-no.network',
++        'dhcp-client-ipv4-use-routes-use-gateway.network',
+         'dhcp-client-ipv6-only.network',
+         'dhcp-client-ipv6-rapid-commit.network',
+         'dhcp-client-keep-configuration-dhcp-on-stop.network',
+@@ -2842,7 +2842,6 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
+         'dhcp-client-use-dns-no.network',
+         'dhcp-client-use-dns-yes.network',
+         'dhcp-client-use-domains.network',
+-        'dhcp-client-use-routes-no.network',
+         'dhcp-client-vrf.network',
+         'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
+         'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
+@@ -2851,7 +2850,6 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
+         'dhcp-server-decline.network',
+         'dhcp-server-veth-peer.network',
+         'dhcp-v4-server-veth-peer.network',
+-        'dhcp-client-use-domains.network',
+         'static.network']
+     def setUp(self):
+@@ -2932,8 +2930,21 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
+         self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
+         self.assertRegex(output, r'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
+-    def test_dhcp_client_ipv4_use_routes_no(self):
+-        copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-use-routes-no.network')
++    def test_dhcp_client_ipv4_use_routes_gateway(self):
++        for (routes, gateway) in itertools.product([True, False, None], repeat=2):
++            self.setUp()
++            with self.subTest(routes=routes, gateway=gateway):
++                self._test_dhcp_client_ipv4_use_routes_gateway(routes, gateway)
++            self.tearDown()
++
++    def _test_dhcp_client_ipv4_use_routes_gateway(self, routes, gateway):
++        testunit = 'dhcp-client-ipv4-use-routes-use-gateway.network'
++        testunits = ['25-veth.netdev', 'dhcp-server-veth-peer.network', testunit]
++        if routes != None:
++            testunits.append(f'{testunit}.d/use-routes-{routes}.conf');
++        if gateway != None:
++            testunits.append(f'{testunit}.d/use-gateway-{gateway}.conf');
++        copy_unit_to_networkd_unit_path(*testunits, dropins=False)
+         start_networkd()
+         self.wait_online(['veth-peer:carrier'])
+@@ -2942,22 +2953,31 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
+         output = check_output('ip route show dev veth99')
+         print(output)
+-        self.assertNotRegex(output, r'192.168.5.5')
+-        self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.181 metric 1024')
+-        self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
+-    def test_dhcp_client_ipv4_use_gateway_no(self):
+-        copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-use-gateway-no.network')
++        # UseRoutes= defaults to true
++        useroutes = routes in [True, None]
++        # UseGateway= defaults to useroutes
++        usegateway = useroutes if gateway == None else gateway
+-        start_networkd()
+-        self.wait_online(['veth-peer:carrier'])
+-        start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
+-        self.wait_online(['veth99:routable', 'veth-peer:routable'])
++        # Check UseRoutes=
++        if useroutes:
++            self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.181 metric 1024')
++        else:
++            self.assertNotRegex(output, r'192.168.5.5')
+-        output = check_output('ip route show dev veth99')
+-        print(output)
+-        self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.181 metric 1024')
+-        self.assertNotRegex(output, r'default via 192.168.5.1')
++        # Check UseGateway=
++        if usegateway:
++            self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.181 metric 1024')
++        else:
++            self.assertNotRegex(output, r'default via 192.168.5.1')
++
++        # check for routes to DNS server, only if using gateway
++        if usegateway:
++            self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
++            self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
++        else:
++            self.assertNotRegex(output, r'192.168.5.6')
++            self.assertNotRegex(output, r'192.168.5.7')
+     def test_dhcp_client_ipv4_ipv6(self):
+         copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
diff --git a/debian/patches/test-verify-RoutesToDNS-is-independent-of-UseGateway.patch b/debian/patches/test-verify-RoutesToDNS-is-independent-of-UseGateway.patch
new file mode 100644 (file)
index 0000000..c0a58ac
--- /dev/null
@@ -0,0 +1,82 @@
+From: Dan Streetman <ddstreet@canonical.com>
+Date: Wed, 15 Apr 2020 18:30:33 -0400
+Subject: test: verify RoutesToDNS= is independent of UseGateway=
+
+(cherry picked from commit 06c2b0c76bf7e2756f8e9ef18765c85dee99ae14)
+---
+ .../conf/dhcp-client-ipv4-use-routes-use-gateway.network   |  3 ---
+ .../use-dns-routes-False.conf                              |  2 ++
+ .../use-dns-routes-True.conf                               |  2 ++
+ test/test-network/systemd-networkd-tests.py                | 14 ++++++++------
+ 4 files changed, 12 insertions(+), 9 deletions(-)
+ create mode 100644 test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-dns-routes-False.conf
+ create mode 100644 test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-dns-routes-True.conf
+
+diff --git a/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network b/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network
+index b0d0d86..c980bf9 100644
+--- a/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network
++++ b/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network
+@@ -4,6 +4,3 @@ Name=veth99
+ [Network]
+ DHCP=ipv4
+ IPv6AcceptRA=false
+-
+-[DHCPv4]
+-RoutesToDNS=yes
+diff --git a/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-dns-routes-False.conf b/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-dns-routes-False.conf
+new file mode 100644
+index 0000000..9c561fb
+--- /dev/null
++++ b/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-dns-routes-False.conf
+@@ -0,0 +1,2 @@
++[DHCPv4]
++RoutesToDNS=no
+diff --git a/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-dns-routes-True.conf b/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-dns-routes-True.conf
+new file mode 100644
+index 0000000..2504c20
+--- /dev/null
++++ b/test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-dns-routes-True.conf
+@@ -0,0 +1,2 @@
++[DHCPv4]
++RoutesToDNS=yes
+diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py
+index 798e155..3c805ca 100755
+--- a/test/test-network/systemd-networkd-tests.py
++++ b/test/test-network/systemd-networkd-tests.py
+@@ -2931,19 +2931,21 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
+         self.assertRegex(output, r'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
+     def test_dhcp_client_ipv4_use_routes_gateway(self):
+-        for (routes, gateway) in itertools.product([True, False, None], repeat=2):
++        for (routes, gateway, dnsroutes) in itertools.product([True, False, None], repeat=3):
+             self.setUp()
+-            with self.subTest(routes=routes, gateway=gateway):
+-                self._test_dhcp_client_ipv4_use_routes_gateway(routes, gateway)
++            with self.subTest(routes=routes, gateway=gateway, dnsroutes=dnsroutes):
++                self._test_dhcp_client_ipv4_use_routes_gateway(routes, gateway, dnsroutes)
+             self.tearDown()
+-    def _test_dhcp_client_ipv4_use_routes_gateway(self, routes, gateway):
++    def _test_dhcp_client_ipv4_use_routes_gateway(self, routes, gateway, dnsroutes):
+         testunit = 'dhcp-client-ipv4-use-routes-use-gateway.network'
+         testunits = ['25-veth.netdev', 'dhcp-server-veth-peer.network', testunit]
+         if routes != None:
+             testunits.append(f'{testunit}.d/use-routes-{routes}.conf');
+         if gateway != None:
+             testunits.append(f'{testunit}.d/use-gateway-{gateway}.conf');
++        if dnsroutes != None:
++            testunits.append(f'{testunit}.d/use-dns-routes-{dnsroutes}.conf');
+         copy_unit_to_networkd_unit_path(*testunits, dropins=False)
+         start_networkd()
+@@ -2971,8 +2973,8 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
+         else:
+             self.assertNotRegex(output, r'default via 192.168.5.1')
+-        # check for routes to DNS server, only if using gateway
+-        if usegateway:
++        # Check RoutesToDNS=, which defaults to false
++        if dnsroutes:
+             self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
+             self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
+         else: