sd-dhcp-lease: store static routes and classless static routes in different arrays

When classless static routes option is provided, then static routes
option should not be used. Hence, let's not mix and store them in one
storage.

This introduce sd_dhcp_lease_get_static_routes() and
sd_dhcp_lease_get_classless_routes().
This commit is contained in:
Yu Watanabe
2022-02-02 10:02:44 +09:00
parent 64a6b5ed21
commit 32f8a613c5
5 changed files with 132 additions and 120 deletions
+42 -38
View File
@@ -404,67 +404,66 @@ static int dhcp4_request_route_auto(
}
static int dhcp4_request_static_routes(Link *link, struct in_addr *ret_default_gw) {
_cleanup_free_ sd_dhcp_route **static_routes = NULL;
bool classless_route = false, static_route = false;
_cleanup_free_ sd_dhcp_route **static_routes = NULL, **classless_routes = NULL;
size_t n_static_routes, n_classless_routes, n;
struct in_addr default_gw = {};
int n, r;
sd_dhcp_route **routes;
int r;
assert(link);
assert(link->dhcp_lease);
assert(ret_default_gw);
n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes);
if (IN_SET(n, 0, -ENODATA)) {
r = sd_dhcp_lease_get_static_routes(link->dhcp_lease, &static_routes);
if (r == -ENODATA)
n_static_routes = 0;
else if (r < 0)
return r;
else
n_static_routes = r;
r = sd_dhcp_lease_get_classless_routes(link->dhcp_lease, &classless_routes);
if (r == -ENODATA)
n_classless_routes = 0;
else if (r < 0)
return r;
else
n_classless_routes = r;
if (n_classless_routes == 0 && n_static_routes == 0) {
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)
if (n_classless_routes > 0 && n_static_routes > 0)
log_link_debug(link, "Classless static routes received from DHCP server: ignoring static-route option");
if (!link->network->dhcp_use_routes) {
if (!classless_route)
return 0;
/* Even if UseRoutes=no, try to find default gateway to make semi-static routes and
* routes to DNS or NTP servers can be configured in later steps. */
for (int i = 0; i < n; i++) {
for (size_t i = 0; i < n_classless_routes; i++) {
struct in_addr dst;
uint8_t prefixlen;
if (sd_dhcp_route_get_option(static_routes[i]) != SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE)
continue;
r = sd_dhcp_route_get_destination(static_routes[i], &dst);
r = sd_dhcp_route_get_destination(classless_routes[i], &dst);
if (r < 0)
return r;
if (in4_addr_is_set(&dst))
continue;
r = sd_dhcp_route_get_destination_prefix_length(static_routes[i], &prefixlen);
r = sd_dhcp_route_get_destination_prefix_length(classless_routes[i], &prefixlen);
if (r < 0)
return r;
if (prefixlen != 0)
continue;
r = sd_dhcp_route_get_gateway(static_routes[i], ret_default_gw);
r = sd_dhcp_route_get_gateway(classless_routes[i], ret_default_gw);
if (r < 0)
return r;
@@ -476,36 +475,41 @@ static int dhcp4_request_static_routes(Link *link, struct in_addr *ret_default_g
return 0;
}
for (int i = 0; i < n; i++) {
if (n_classless_routes > 0) {
n = n_classless_routes;
routes = classless_routes;
} else if (n_static_routes > 0){
n = n_static_routes;
routes = static_routes;
} else
assert_not_reached();
for (size_t i = 0; i < n; i++) {
_cleanup_(route_freep) Route *route = NULL;
struct in_addr gw;
if (sd_dhcp_route_get_option(static_routes[i]) !=
(classless_route ? SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE : SD_DHCP_OPTION_STATIC_ROUTE))
continue;
r = route_new(&route);
if (r < 0)
return r;
route->gw_family = AF_INET;
r = sd_dhcp_route_get_gateway(static_routes[i], &gw);
r = sd_dhcp_route_get_gateway(routes[i], &gw);
if (r < 0)
return r;
r = sd_dhcp_route_get_destination(static_routes[i], &route->dst.in);
r = sd_dhcp_route_get_destination(routes[i], &route->dst.in);
if (r < 0)
return r;
r = sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen);
r = sd_dhcp_route_get_destination_prefix_length(routes[i], &route->dst_prefixlen);
if (r < 0)
return r;
/* When classless static routes are provided, then router option will be ignored. To
* use the default gateway later in other routes, e.g., routes to dns servers, here we
* need to find the default gateway in the classless static routes. */
if (classless_route &&
if (n_classless_routes > 0 &&
in4_addr_is_null(&route->dst.in) && route->dst_prefixlen == 0 &&
in4_addr_is_null(&default_gw))
default_gw = gw;
@@ -516,7 +520,7 @@ static int dhcp4_request_static_routes(Link *link, struct in_addr *ret_default_g
}
*ret_default_gw = default_gw;
return classless_route;
return n_classless_routes > 0;
}
static int dhcp4_request_gateway(Link *link, struct in_addr *gw) {