1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-10-26 17:25:34 +03:00

DHCP: when adding static routes set scopes properly (#5982)

DHCP responses could include static routes, but unfortunately not an
option to tell what scope to use. So it's important that the client sets
it properly.

This mimics what the `ip route add` command does when adding a static
route without an explicit scope:

* If the destination IP is on the local host, use scope `host`
* Otherwise if the gateway IP is null (direct route), use scope `link`
* If anything else, use the current default `global`.

Fixes #5979.
This commit is contained in:
Daniel Wang 2017-05-20 04:05:18 -07:00 committed by Zbigniew Jędrzejewski-Szmek
parent 07755554ab
commit d6eac9bd06
2 changed files with 20 additions and 5 deletions

View File

@ -998,9 +998,11 @@
<varlistentry>
<term><varname>UseRoutes=</varname></term>
<listitem>
<para>When true (the default), the static routes will be
requested from the DHCP server and added to the routing
table with a metric of 1024.</para>
<para>When true (the default), the static routes will be requested from the DHCP server and added to the
routing table with a metric of 1024, and a scope of "global", "link" or "host", depending on the route's
destination and gateway. If the destination is on the local host, e.g., 127.x.x.x, or the same as the
link's own address, the scope will be set to "host". Otherwise if the gateway is null (a direct route), a
"link" scope will be used. For anything else, scope defaults to "global".</para>
</listitem>
</varlistentry>

View File

@ -52,8 +52,21 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
return 1;
}
static int route_scope_from_address(const Route *route, const struct in_addr *self_addr) {
assert(route);
assert(self_addr);
if (in_addr_is_localhost(AF_INET, &route->dst) ||
(self_addr->s_addr && route->dst.in.s_addr == self_addr->s_addr))
return RT_SCOPE_HOST;
else if (in4_addr_is_null(&route->gw.in))
return RT_SCOPE_LINK;
else
return RT_SCOPE_UNIVERSE;
}
static int link_set_dhcp_routes(Link *link) {
struct in_addr gateway;
struct in_addr gateway, address;
_cleanup_free_ sd_dhcp_route **static_routes = NULL;
int r, n, i;
@ -69,7 +82,6 @@ static int link_set_dhcp_routes(Link *link) {
return log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m");
if (r >= 0) {
struct in_addr address;
_cleanup_route_free_ Route *route = NULL;
_cleanup_route_free_ Route *route_gw = NULL;
@ -141,6 +153,7 @@ static int link_set_dhcp_routes(Link *link) {
assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0);
route->priority = link->network->dhcp_route_metric;
route->table = link->network->dhcp_route_table;
route->scope = route_scope_from_address(route, &address);
r = route_configure(route, link, dhcp4_route_handler);
if (r < 0)