Zbigniew Jędrzejewski-Szmek f4a676
From c19df00f6def1ee74ae0812b529f2a1b589c256f Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek f4a676
From: Daniel Wang <wonderfly@users.noreply.github.com>
Zbigniew Jędrzejewski-Szmek f4a676
Date: Sat, 20 May 2017 04:05:18 -0700
Zbigniew Jędrzejewski-Szmek f4a676
Subject: [PATCH] DHCP: when adding static routes set scopes properly (#5982)
Zbigniew Jędrzejewski-Szmek f4a676
Zbigniew Jędrzejewski-Szmek f4a676
DHCP responses could include static routes, but unfortunately not an
Zbigniew Jędrzejewski-Szmek f4a676
option to tell what scope to use. So it's important that the client sets
Zbigniew Jędrzejewski-Szmek f4a676
it properly.
Zbigniew Jędrzejewski-Szmek f4a676
Zbigniew Jędrzejewski-Szmek f4a676
This mimics what the `ip route add` command does when adding a static
Zbigniew Jędrzejewski-Szmek f4a676
route without an explicit scope:
Zbigniew Jędrzejewski-Szmek f4a676
Zbigniew Jędrzejewski-Szmek f4a676
* If the destination IP is on the local host, use scope `host`
Zbigniew Jędrzejewski-Szmek f4a676
* Otherwise if the gateway IP is null (direct route), use scope `link`
Zbigniew Jędrzejewski-Szmek f4a676
* If anything else, use the current default `global`.
Zbigniew Jędrzejewski-Szmek f4a676
Zbigniew Jędrzejewski-Szmek f4a676
Fixes #5979.
Zbigniew Jędrzejewski-Szmek f4a676
(cherry picked from commit d6eac9bd06066c8d041449538a9cdee0fd928835)
Zbigniew Jędrzejewski-Szmek f4a676
---
Zbigniew Jędrzejewski-Szmek f4a676
 man/systemd.network.xml      |  8 +++++---
Zbigniew Jędrzejewski-Szmek f4a676
 src/network/networkd-dhcp4.c | 17 +++++++++++++++--
Zbigniew Jędrzejewski-Szmek f4a676
 2 files changed, 20 insertions(+), 5 deletions(-)
Zbigniew Jędrzejewski-Szmek f4a676
Zbigniew Jędrzejewski-Szmek f4a676
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
Zbigniew Jędrzejewski-Szmek f4a676
index b807ebf29b..aaa7b0968d 100644
Zbigniew Jędrzejewski-Szmek f4a676
--- a/man/systemd.network.xml
Zbigniew Jędrzejewski-Szmek f4a676
+++ b/man/systemd.network.xml
Zbigniew Jędrzejewski-Szmek f4a676
@@ -937,9 +937,11 @@
Zbigniew Jędrzejewski-Szmek f4a676
         <varlistentry>
Zbigniew Jędrzejewski-Szmek f4a676
           <term><varname>UseRoutes=</varname></term>
Zbigniew Jędrzejewski-Szmek f4a676
           <listitem>
Zbigniew Jędrzejewski-Szmek f4a676
-            <para>When true (the default), the static routes will be
Zbigniew Jędrzejewski-Szmek f4a676
-            requested from the DHCP server and added to the routing
Zbigniew Jędrzejewski-Szmek f4a676
-            table with a metric of 1024.</para>
Zbigniew Jędrzejewski-Szmek f4a676
+            <para>When true (the default), the static routes will be requested from the DHCP server and added to the
Zbigniew Jędrzejewski-Szmek f4a676
+              routing table with a metric of 1024, and a scope of "global", "link" or "host", depending on the route's
Zbigniew Jędrzejewski-Szmek f4a676
+              destination and gateway. If the destination is on the local host, e.g., 127.x.x.x, or the same as the
Zbigniew Jędrzejewski-Szmek f4a676
+              link's own address, the scope will be set to "host". Otherwise if the gateway is null (a direct route), a
Zbigniew Jędrzejewski-Szmek f4a676
+              "link" scope will be used. For anything else, scope defaults to "global".</para>
Zbigniew Jędrzejewski-Szmek f4a676
           </listitem>
Zbigniew Jędrzejewski-Szmek f4a676
         </varlistentry>
Zbigniew Jędrzejewski-Szmek f4a676
 
Zbigniew Jędrzejewski-Szmek f4a676
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
Zbigniew Jędrzejewski-Szmek f4a676
index c5c5b95c8f..ae0f78daab 100644
Zbigniew Jędrzejewski-Szmek f4a676
--- a/src/network/networkd-dhcp4.c
Zbigniew Jędrzejewski-Szmek f4a676
+++ b/src/network/networkd-dhcp4.c
Zbigniew Jędrzejewski-Szmek f4a676
@@ -52,8 +52,21 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
Zbigniew Jędrzejewski-Szmek f4a676
         return 1;
Zbigniew Jędrzejewski-Szmek f4a676
 }
Zbigniew Jędrzejewski-Szmek f4a676
 
Zbigniew Jędrzejewski-Szmek f4a676
+static int route_scope_from_address(const Route *route, const struct in_addr *self_addr) {
Zbigniew Jędrzejewski-Szmek f4a676
+        assert(route);
Zbigniew Jędrzejewski-Szmek f4a676
+        assert(self_addr);
Zbigniew Jędrzejewski-Szmek f4a676
+
Zbigniew Jędrzejewski-Szmek f4a676
+        if (in_addr_is_localhost(AF_INET, &route->dst) ||
Zbigniew Jędrzejewski-Szmek f4a676
+            (self_addr->s_addr && route->dst.in.s_addr == self_addr->s_addr))
Zbigniew Jędrzejewski-Szmek f4a676
+                return RT_SCOPE_HOST;
Zbigniew Jędrzejewski-Szmek f4a676
+        else if (in4_addr_is_null(&route->gw.in))
Zbigniew Jędrzejewski-Szmek f4a676
+                return RT_SCOPE_LINK;
Zbigniew Jędrzejewski-Szmek f4a676
+        else
Zbigniew Jędrzejewski-Szmek f4a676
+                return RT_SCOPE_UNIVERSE;
Zbigniew Jędrzejewski-Szmek f4a676
+}
Zbigniew Jędrzejewski-Szmek f4a676
+
Zbigniew Jędrzejewski-Szmek f4a676
 static int link_set_dhcp_routes(Link *link) {
Zbigniew Jędrzejewski-Szmek f4a676
-        struct in_addr gateway;
Zbigniew Jędrzejewski-Szmek f4a676
+        struct in_addr gateway, address;
Zbigniew Jędrzejewski-Szmek f4a676
         _cleanup_free_ sd_dhcp_route **static_routes = NULL;
Zbigniew Jędrzejewski-Szmek f4a676
         int r, n, i;
Zbigniew Jędrzejewski-Szmek f4a676
 
Zbigniew Jędrzejewski-Szmek f4a676
@@ -69,7 +82,6 @@ static int link_set_dhcp_routes(Link *link) {
Zbigniew Jędrzejewski-Szmek f4a676
                 return log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m");
Zbigniew Jędrzejewski-Szmek f4a676
 
Zbigniew Jędrzejewski-Szmek f4a676
         if (r >= 0) {
Zbigniew Jędrzejewski-Szmek f4a676
-                struct in_addr address;
Zbigniew Jędrzejewski-Szmek f4a676
                 _cleanup_route_free_ Route *route = NULL;
Zbigniew Jędrzejewski-Szmek f4a676
                 _cleanup_route_free_ Route *route_gw = NULL;
Zbigniew Jędrzejewski-Szmek f4a676
 
Zbigniew Jędrzejewski-Szmek f4a676
@@ -141,6 +153,7 @@ static int link_set_dhcp_routes(Link *link) {
Zbigniew Jędrzejewski-Szmek f4a676
                 assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0);
Zbigniew Jędrzejewski-Szmek f4a676
                 route->priority = link->network->dhcp_route_metric;
Zbigniew Jędrzejewski-Szmek f4a676
                 route->table = link->network->dhcp_route_table;
Zbigniew Jędrzejewski-Szmek f4a676
+                route->scope = route_scope_from_address(route, &address);
Zbigniew Jędrzejewski-Szmek f4a676
 
Zbigniew Jędrzejewski-Szmek f4a676
                 r = route_configure(route, link, dhcp4_route_handler);
Zbigniew Jędrzejewski-Szmek f4a676
                 if (r < 0)