From 5f04a209eae0a2a04eb60fd7235b3fcdf3cc81ba Mon Sep 17 00:00:00 2001 From: Susant Sahani <145210+ssahani@users.noreply.github.com> Date: Wed, 22 Nov 2017 12:13:55 +0530 Subject: [PATCH] networkd:DHCP-client ignore default route if classless static route is set (#6885) 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. fixes #5695. --- src/network/networkd-dhcp4.c | 67 +++++++++++++++++------------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index bfce641858..83b5a39052 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -94,13 +94,44 @@ 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"); + n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes); + if (n == -ENODATA) + return 0; + if (n < 0) + return log_link_warning_errno(link, n, "DHCP error: could not get routes: %m"); + + for (i = 0; i < n; i++) { + _cleanup_route_free_ Route *route = NULL; + + r = route_new(&route); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate route: %m"); + + route->family = AF_INET; + route->protocol = RTPROT_DHCP; + assert_se(sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in) >= 0); + assert_se(sd_dhcp_route_get_destination(static_routes[i], &route->dst.in) >= 0); + 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 = table; + route->scope = route_scope_from_address(route, &address); + + r = route_configure(route, link, dhcp4_route_handler); + if (r < 0) + return log_link_warning_errno(link, r, "Could not set host route: %m"); + + link->dhcp4_messages++; + } + r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway); if (r == -ENODATA) log_link_info_errno(link, r, "DHCP: No routes received from DHCP server: %m"); else if (r < 0) log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m"); - if (r >= 0) { + /* 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 (r >= 0 && link->dhcp4_messages <= 0) { _cleanup_route_free_ Route *route = NULL; _cleanup_route_free_ Route *route_gw = NULL; @@ -148,40 +179,6 @@ static int link_set_dhcp_routes(Link *link) { link->dhcp4_messages++; } - n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes); - if (n == -ENODATA) - log_link_info_errno(link, n, "DHCP: No routes received from DHCP server: %m"); - else if (n < 0) - log_link_warning_errno(link, n, "DHCP error: could not get routes: %m"); - - for (i = 0; i < n; i++) { - _cleanup_route_free_ Route *route = NULL; - - r = route_new(&route); - if (r < 0) - return log_link_error_errno(link, r, "Could not allocate route: %m"); - - route->family = AF_INET; - route->protocol = RTPROT_DHCP; - assert_se(sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in) >= 0); - assert_se(sd_dhcp_route_get_destination(static_routes[i], &route->dst.in) >= 0); - 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 = table; - route->scope = route_scope_from_address(route, &address); - - r = route_configure(route, link, dhcp4_route_handler); - if (r < 0) - return log_link_warning_errno(link, r, "Could not set host route: %m"); - - link->dhcp4_messages++; - } - - if (link->dhcp4_messages == 0) { - link->dhcp4_configured = true; - link_check_ready(link); - } - return 0; } -- 2.25.1