Add support for DHCP static route options

This adds support for DHCP options 33 and 121: Static Route and
Classless Static Route. To enable this feature, set UseRoutes=true
in .network file. Returned routes are added to the routing table.
This commit is contained in:
Eugene Yakubovich
2014-06-29 15:18:21 +02:00
committed by Tom Gundersen
parent ed942a9eb2
commit e1ea665eda
12 changed files with 404 additions and 6 deletions
+83 -2
View File
@@ -402,6 +402,51 @@ static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
return 1;
}
static int link_set_dhcp_routes(Link *link) {
struct sd_dhcp_route *static_routes;
size_t static_routes_size;
int r;
unsigned i;
assert(link);
r = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes, &static_routes_size);
if (r < 0) {
if (r != -ENOENT)
log_warning_link(link, "DHCP error: %s", strerror(-r));
return r;
}
for (i = 0; i < static_routes_size; i++) {
_cleanup_route_free_ Route *route = NULL;
r = route_new_dynamic(&route);
if (r < 0) {
log_error_link(link, "Could not allocate route: %s",
strerror(-r));
return r;
}
route->family = AF_INET;
route->in_addr.in = static_routes[i].gw_addr;
route->dst_addr.in = static_routes[i].dst_addr;
route->dst_prefixlen = static_routes[i].dst_prefixlen;
route->metrics = DHCP_STATIC_ROUTE_METRIC;
r = route_configure(route, link, &route_handler);
if (r < 0) {
log_warning_link(link,
"could not set host route: %s", strerror(-r));
return r;
}
link_ref(link);
link->route_messages ++;
}
return 0;
}
static int link_enter_set_routes(Link *link) {
Route *rt;
int r;
@@ -525,6 +570,9 @@ static int link_enter_set_routes(Link *link) {
link_ref(link);
link->route_messages ++;
}
if (link->network->dhcp_routes)
link_set_dhcp_routes(link);
}
if (link->route_messages == 0) {
@@ -901,12 +949,11 @@ static int link_set_mtu(Link *link, uint32_t mtu) {
static int dhcp_lease_lost(Link *link) {
_cleanup_address_free_ Address *address = NULL;
_cleanup_route_free_ Route *route_gw = NULL;
_cleanup_route_free_ Route *route = NULL;
struct in_addr addr;
struct in_addr netmask;
struct in_addr gateway;
unsigned prefixlen;
unsigned i;
int r;
assert(link);
@@ -914,10 +961,36 @@ static int dhcp_lease_lost(Link *link) {
log_warning_link(link, "DHCP lease lost");
if (link->network->dhcp_routes) {
struct sd_dhcp_route *routes;
size_t routes_size;
r = sd_dhcp_lease_get_routes(link->dhcp_lease, &routes, &routes_size);
if (r >= 0) {
for (i = 0; i < routes_size; i++) {
_cleanup_route_free_ Route *route = NULL;
r = route_new_dynamic(&route);
if (r >= 0) {
route->family = AF_INET;
route->in_addr.in = routes[i].gw_addr;
route->dst_addr.in = routes[i].dst_addr;
route->dst_prefixlen = routes[i].dst_prefixlen;
route_drop(route, link, &route_drop_handler);
link_ref(link);
}
}
}
}
r = address_new_dynamic(&address);
if (r >= 0) {
r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
if (r >= 0) {
_cleanup_route_free_ Route *route_gw = NULL;
_cleanup_route_free_ Route *route = NULL;
r = route_new_dynamic(&route_gw);
if (r >= 0) {
route_gw->family = AF_INET;
@@ -1952,6 +2025,14 @@ static int link_configure(Link *link) {
if (r < 0)
return r;
}
if (link->network->dhcp_routes) {
r = sd_dhcp_client_set_request_option(link->dhcp_client, DHCP_OPTION_STATIC_ROUTE);
if (r < 0)
return r;
r = sd_dhcp_client_set_request_option(link->dhcp_client, DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
if (r < 0)
return r;
}
}
if (link->network->dhcp_server) {