mirror of
https://github.com/systemd/systemd
synced 2024-07-01 07:34:28 +00:00
network/ndisc: drop configurations when received RA with zero lifetime
This commit is contained in:
parent
828b5dbf2f
commit
479d3e1994
|
@ -273,6 +273,39 @@ static int ndisc_request_route(Route *route, Link *link, sd_ndisc_router *rt) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ndisc_remove_route(Route *route, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(route);
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
|
||||
ndisc_set_route_priority(link, route);
|
||||
|
||||
if (!route->table_set)
|
||||
route->table = link_get_ipv6_accept_ra_route_table(link);
|
||||
|
||||
r = route_adjust_nexthops(route, link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (route->pref_set) {
|
||||
ndisc_set_route_priority(link, route);
|
||||
return route_remove_and_cancel(route, link->manager);
|
||||
}
|
||||
|
||||
uint8_t pref;
|
||||
FOREACH_ARGUMENT(pref, SD_NDISC_PREFERENCE_LOW, SD_NDISC_PREFERENCE_MEDIUM, SD_NDISC_PREFERENCE_HIGH) {
|
||||
route->pref = pref;
|
||||
ndisc_set_route_priority(link, route);
|
||||
r = route_remove_and_cancel(route, link->manager);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
|
||||
int r;
|
||||
|
||||
|
@ -340,6 +373,55 @@ static int ndisc_request_address(Address *address, Link *link, sd_ndisc_router *
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ndisc_router_drop_default(Link *link, sd_ndisc_router *rt) {
|
||||
_cleanup_(route_unrefp) Route *route = NULL;
|
||||
struct in6_addr gateway;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->network);
|
||||
assert(rt);
|
||||
|
||||
r = sd_ndisc_router_get_address(rt, &gateway);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to get router address from RA: %m");
|
||||
|
||||
r = route_new(&route);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
route->family = AF_INET6;
|
||||
route->nexthop.family = AF_INET6;
|
||||
route->nexthop.gw.in6 = gateway;
|
||||
|
||||
r = ndisc_remove_route(route, link);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to remove the default gateway configured by RA: %m");
|
||||
|
||||
Route *route_gw;
|
||||
HASHMAP_FOREACH(route_gw, link->network->routes_by_section) {
|
||||
_cleanup_(route_unrefp) Route *tmp = NULL;
|
||||
|
||||
if (!route_gw->gateway_from_dhcp_or_ra)
|
||||
continue;
|
||||
|
||||
if (route_gw->nexthop.family != AF_INET6)
|
||||
continue;
|
||||
|
||||
r = route_dup(route_gw, NULL, &tmp);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
tmp->nexthop.gw.in6 = gateway;
|
||||
|
||||
r = ndisc_remove_route(tmp, link);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Could not remove semi-static gateway: %m");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
|
||||
usec_t lifetime_usec;
|
||||
struct in6_addr gateway;
|
||||
|
@ -350,6 +432,13 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
|
|||
assert(link->network);
|
||||
assert(rt);
|
||||
|
||||
/* If the router lifetime is zero, the router should not be used as the default gateway. */
|
||||
r = sd_ndisc_router_get_lifetime(rt, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return ndisc_router_drop_default(link, rt);
|
||||
|
||||
if (!link->network->ipv6_accept_ra_use_gateway &&
|
||||
hashmap_isempty(link->network->routes_by_section))
|
||||
return 0;
|
||||
|
@ -578,9 +667,22 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
|
|||
address->lifetime_valid_usec = lifetime_valid_usec;
|
||||
address->lifetime_preferred_usec = lifetime_preferred_usec;
|
||||
|
||||
r = ndisc_request_address(address, link, rt);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Could not request SLAAC address: %m");
|
||||
/* draft-ietf-6man-slaac-renum-07 section 4.2
|
||||
* https://datatracker.ietf.org/doc/html/draft-ietf-6man-slaac-renum-07#section-4.2
|
||||
*
|
||||
* If the advertised prefix is equal to the prefix of an address configured by stateless
|
||||
* autoconfiguration in the list, the valid lifetime and the preferred lifetime of the
|
||||
* address should be updated by processing the Valid Lifetime and the Preferred Lifetime
|
||||
* (respectively) in the received advertisement. */
|
||||
if (lifetime_valid_usec == 0) {
|
||||
r = address_remove_and_cancel(address, link);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Could not remove SLAAC address: %m");
|
||||
} else {
|
||||
r = ndisc_request_address(address, link, rt);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Could not request SLAAC address: %m");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -636,7 +738,7 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
|
|||
|
||||
static int ndisc_router_drop_onlink_prefix(Link *link, sd_ndisc_router *rt) {
|
||||
_cleanup_(route_unrefp) Route *route = NULL;
|
||||
unsigned prefixlen, preference;
|
||||
unsigned prefixlen;
|
||||
struct in6_addr prefix;
|
||||
usec_t lifetime_usec;
|
||||
int r;
|
||||
|
@ -669,11 +771,6 @@ static int ndisc_router_drop_onlink_prefix(Link *link, sd_ndisc_router *rt) {
|
|||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to get prefix length: %m");
|
||||
|
||||
/* Prefix Information option does not have preference, hence we use the 'main' preference here */
|
||||
r = sd_ndisc_router_get_preference(rt, &preference);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to get router preference from RA: %m");
|
||||
|
||||
r = route_new(&route);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
@ -681,16 +778,8 @@ static int ndisc_router_drop_onlink_prefix(Link *link, sd_ndisc_router *rt) {
|
|||
route->family = AF_INET6;
|
||||
route->dst.in6 = prefix;
|
||||
route->dst_prefixlen = prefixlen;
|
||||
route->table = link_get_ipv6_accept_ra_route_table(link);
|
||||
route->pref = preference;
|
||||
ndisc_set_route_priority(link, route);
|
||||
route->protocol = RTPROT_RA;
|
||||
|
||||
r = route_adjust_nexthops(route, link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = route_remove_and_cancel(route, link->manager);
|
||||
r = ndisc_remove_route(route, link);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Could not remove prefix route: %m");
|
||||
|
||||
|
@ -715,7 +804,7 @@ static int ndisc_router_process_prefix(Link *link, sd_ndisc_router *rt) {
|
|||
* A router SHOULD NOT send a prefix option for the link-local prefix and a host SHOULD ignore such
|
||||
* a prefix option. */
|
||||
if (in6_addr_is_link_local(&a)) {
|
||||
log_link_debug(link, "Received link-local prefix, ignoring autonomous prefix.");
|
||||
log_link_debug(link, "Received link-local prefix, ignoring prefix.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user