summaryrefslogtreecommitdiff
path: root/src/network
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2021-04-12 08:22:24 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2021-04-22 12:49:56 +0900
commit7872d0f7b634570ef25cfec885c3985e642beec3 (patch)
tree070312f15796066c7ceea4d1fec69b65eb43f7d0 /src/network
parentc0fef8f349a650bde3929ff14585916cb1581eda (diff)
downloadsystemd-7872d0f7b634570ef25cfec885c3985e642beec3.tar.gz
network: dhcp4: introduce link_set_dhcp_static_routes()
Diffstat (limited to 'src/network')
-rw-r--r--src/network/networkd-dhcp4.c152
1 files changed, 89 insertions, 63 deletions
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index 050be0a167..85e56c5a8c 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -266,13 +266,94 @@ static int link_set_dhcp_prefix_route(Link *link) {
return dhcp_route_configure(route, link);
}
-static int link_set_dhcp_routes(Link *link) {
+static int link_set_dhcp_static_routes(Link *link) {
_cleanup_free_ sd_dhcp_route **static_routes = NULL;
bool classless_route = false, static_route = false;
+ _cleanup_(route_freep) Route *route = NULL;
+ struct in_addr address;
+ int n, r;
+
+ assert(link);
+ assert(link->dhcp_lease);
+
+ if (!link->network->dhcp_use_routes)
+ return 0;
+
+ r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
+ if (r < 0)
+ return r;
+
+ n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes);
+ if (IN_SET(n, 0, -ENODATA)) {
+ log_link_debug(link, "DHCP: No static routes received from DHCP server.");
+ return 0;
+ }
+ if (n < 0)
+ return n;
+
+ for (int i = 0; i < n; i++) {
+ switch (sd_dhcp_route_get_option(static_routes[i])) {
+ case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
+ classless_route = true;
+ break;
+ case SD_DHCP_OPTION_STATIC_ROUTE:
+ static_route = true;
+ break;
+ }
+ }
+
+ /* if the DHCP server returns both a Classless Static Routes option and a Static Routes option,
+ * the DHCP client MUST ignore the Static Routes option. */
+ if (classless_route && static_route)
+ log_link_warning(link, "Classless static routes received from DHCP server: ignoring static-route option");
+
+ r = route_new(&route);
+ if (r < 0)
+ return r;
+
+ route->family = AF_INET;
+ route->gw_family = AF_INET;
+ route->protocol = RTPROT_DHCP;
+ route->priority = link->network->dhcp_route_metric;
+ route->table = link_get_dhcp_route_table(link);
+ route->mtu = link->network->dhcp_route_mtu;
+
+ for (int i = 0; i < n; i++) {
+ if (sd_dhcp_route_get_option(static_routes[i]) !=
+ (classless_route ? SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE : SD_DHCP_OPTION_STATIC_ROUTE))
+ continue;
+
+ r = sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in);
+ if (r < 0)
+ return r;
+
+ r = sd_dhcp_route_get_destination(static_routes[i], &route->dst.in);
+ if (r < 0)
+ return r;
+
+ r = sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen);
+ if (r < 0)
+ return r;
+
+ route->scope = route_scope_from_address(route, &address);
+ if (IN_SET(route->scope, RT_SCOPE_LINK, RT_SCOPE_UNIVERSE))
+ route->prefsrc.in = address;
+ else
+ route->prefsrc = IN_ADDR_NULL;
+
+ r = dhcp_route_configure(route, link);
+ if (r < 0)
+ return r;
+ }
+
+ return classless_route;
+}
+
+static int link_set_dhcp_routes(Link *link) {
struct in_addr address;
uint32_t table;
Route *rt;
- int r, n;
+ int r;
assert(link);
@@ -303,65 +384,14 @@ static int link_set_dhcp_routes(Link *link) {
if (r < 0)
return log_link_error_errno(link, r, "DHCP error: 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");
- else if (n < 0)
- return log_link_error_errno(link, n, "DHCP: could not get routes: %m");
-
- for (int i = 0; i < n; i++) {
- switch (sd_dhcp_route_get_option(static_routes[i])) {
- case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
- classless_route = true;
- break;
- case SD_DHCP_OPTION_STATIC_ROUTE:
- static_route = true;
- break;
- }
- }
-
- if (link->network->dhcp_use_routes) {
- /* if the DHCP server returns both a Classless Static Routes option and a Static Routes option,
- * the DHCP client MUST ignore the Static Routes option. */
- if (classless_route && static_route)
- log_link_warning(link, "Classless static routes received from DHCP server: ignoring static-route option");
-
- for (int i = 0; i < n; i++) {
- _cleanup_(route_freep) Route *route = NULL;
-
- if (classless_route &&
- sd_dhcp_route_get_option(static_routes[i]) != SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE)
- continue;
-
- 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;
- route->gw_family = AF_INET;
- 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->mtu = link->network->dhcp_route_mtu;
- route->scope = route_scope_from_address(route, &address);
- if (IN_SET(route->scope, RT_SCOPE_LINK, RT_SCOPE_UNIVERSE))
- route->prefsrc.in = address;
-
- if (set_contains(link->dhcp_routes, route))
- continue;
-
- r = dhcp_route_configure(route, link);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not set route: %m");
- }
- }
-
- if (link->network->dhcp_use_gateway) {
+ r = link_set_dhcp_static_routes(link);
+ if (r < 0)
+ return log_link_error_errno(link, r, "DHCP error: Could not set static routes: %m");
+ if (r == 0 && link->network->dhcp_use_gateway) {
const struct in_addr *router;
+ /* 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. */
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.");
@@ -369,10 +399,6 @@ static int link_set_dhcp_routes(Link *link) {
return log_link_error_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.");
- else if (classless_route)
- /* 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. */
- log_link_warning(link, "Classless static routes received from DHCP server: ignoring router option");
else {
_cleanup_(route_freep) Route *route = NULL, *route_gw = NULL;