mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-22 13:33:56 +03:00
network: dhcp4: ignore gateway in static routes if destination is link-local or in the same network
This also configures routes to gateways in static routes if the destination is not in the same network.
This commit is contained in:
parent
b714d9a6e3
commit
7f206276ad
@ -143,19 +143,6 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int route_scope_from_address(const Route *route, const struct in_addr *self_addr) {
|
||||
assert(route);
|
||||
assert(self_addr);
|
||||
|
||||
if (in4_addr_is_localhost(&route->dst.in) ||
|
||||
(in4_addr_is_set(self_addr) && in4_addr_equal(&route->dst.in, self_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 dhcp_route_configure(Route *route, Link *link) {
|
||||
Route *ret;
|
||||
int r;
|
||||
@ -250,11 +237,95 @@ static int link_set_dhcp_route_to_gateway(Link *link, const struct in_addr *gw)
|
||||
return dhcp_route_configure(route, link);
|
||||
}
|
||||
|
||||
static int dhcp_route_configure_auto(
|
||||
Route *route,
|
||||
Link *link,
|
||||
const struct in_addr *gw) {
|
||||
|
||||
struct in_addr address, netmask, prefix;
|
||||
uint8_t prefixlen;
|
||||
int r;
|
||||
|
||||
assert(route);
|
||||
assert(link);
|
||||
assert(link->dhcp_lease);
|
||||
assert(gw);
|
||||
|
||||
/* The route object may be reused in an iteration. All elements must be set or cleared. */
|
||||
|
||||
r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
prefix.s_addr = address.s_addr & netmask.s_addr;
|
||||
prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
|
||||
|
||||
if (in4_addr_is_localhost(&route->dst.in)) {
|
||||
if (in4_addr_is_set(gw))
|
||||
log_link_debug(link, "DHCP: requested route destination "IPV4_ADDRESS_FMT_STR"/%u is localhost, "
|
||||
"ignoring gateway address "IPV4_ADDRESS_FMT_STR,
|
||||
IPV4_ADDRESS_FMT_VAL(route->dst.in), route->dst_prefixlen, IPV4_ADDRESS_FMT_VAL(*gw));
|
||||
|
||||
route->scope = RT_SCOPE_HOST;
|
||||
route->gw_family = AF_UNSPEC;
|
||||
route->gw = IN_ADDR_NULL;
|
||||
route->prefsrc = IN_ADDR_NULL;
|
||||
|
||||
} else if (in4_addr_equal(&route->dst.in, &address)) {
|
||||
if (in4_addr_is_set(gw))
|
||||
log_link_debug(link, "DHCP: requested route destination "IPV4_ADDRESS_FMT_STR"/%u is equivalent to the acquired address, "
|
||||
"ignoring gateway address "IPV4_ADDRESS_FMT_STR,
|
||||
IPV4_ADDRESS_FMT_VAL(route->dst.in), route->dst_prefixlen, IPV4_ADDRESS_FMT_VAL(*gw));
|
||||
|
||||
route->scope = RT_SCOPE_HOST;
|
||||
route->gw_family = AF_UNSPEC;
|
||||
route->gw = IN_ADDR_NULL;
|
||||
route->prefsrc.in = address;
|
||||
|
||||
} else if (route->dst_prefixlen >= prefixlen &&
|
||||
(route->dst.in.s_addr & netmask.s_addr) == prefix.s_addr) {
|
||||
if (in4_addr_is_set(gw))
|
||||
log_link_debug(link, "DHCP: requested route destination "IPV4_ADDRESS_FMT_STR"/%u is in the assigned network "
|
||||
IPV4_ADDRESS_FMT_STR"/%u, ignoring gateway address "IPV4_ADDRESS_FMT_STR,
|
||||
IPV4_ADDRESS_FMT_VAL(route->dst.in), route->dst_prefixlen,
|
||||
IPV4_ADDRESS_FMT_VAL(prefix), prefixlen,
|
||||
IPV4_ADDRESS_FMT_VAL(*gw));
|
||||
|
||||
route->scope = RT_SCOPE_LINK;
|
||||
route->gw_family = AF_UNSPEC;
|
||||
route->gw = IN_ADDR_NULL;
|
||||
route->prefsrc.in = address;
|
||||
|
||||
} else {
|
||||
if (in4_addr_is_null(gw)) {
|
||||
log_link_debug(link, "DHCP: requested route destination "IPV4_ADDRESS_FMT_STR"/%u is not in the assigned network "
|
||||
IPV4_ADDRESS_FMT_STR"/%u, but no gateway is specified, ignoring.",
|
||||
IPV4_ADDRESS_FMT_VAL(route->dst.in), route->dst_prefixlen,
|
||||
IPV4_ADDRESS_FMT_VAL(prefix), prefixlen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = link_set_dhcp_route_to_gateway(link, gw);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
route->scope = RT_SCOPE_UNIVERSE;
|
||||
route->gw_family = AF_INET;
|
||||
route->gw.in = *gw;
|
||||
route->prefsrc.in = address;
|
||||
}
|
||||
|
||||
return dhcp_route_configure(route, 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);
|
||||
@ -263,10 +334,6 @@ static int link_set_dhcp_static_routes(Link *link) {
|
||||
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.");
|
||||
@ -303,11 +370,13 @@ static int link_set_dhcp_static_routes(Link *link) {
|
||||
route->mtu = link->network->dhcp_route_mtu;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
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 = sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in);
|
||||
r = sd_dhcp_route_get_gateway(static_routes[i], &gw);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -319,13 +388,7 @@ static int link_set_dhcp_static_routes(Link *link) {
|
||||
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);
|
||||
r = dhcp_route_configure_auto(route, link, &gw);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user