network/ndisc: do not remove static routes when received RA with zero lifetime

Similar to the previous commit, but for preventing from removing static
routes on receiving RA with zero lifetime.

Fixes a regresson caused by 479d3e1994.
Fixes #33346.
This commit is contained in:
Yu Watanabe 2024-06-24 16:20:27 +09:00
parent 7af3e8cd00
commit fd436c8d67

View file

@ -304,18 +304,44 @@ static int ndisc_remove_route(Route *route, Link *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;
uint8_t pref, pref_original = route->pref;
FOREACH_ARGUMENT(pref, SD_NDISC_PREFERENCE_LOW, SD_NDISC_PREFERENCE_MEDIUM, SD_NDISC_PREFERENCE_HIGH) {
Route *existing;
Request *req;
/* If the preference is specified by the user config (that is, for semi-static routes),
* rather than RA, then only search conflicting routes that have the same preference. */
if (route->pref_set && pref != pref_original)
continue;
route->pref = pref;
ndisc_set_route_priority(link, route);
r = route_remove_and_cancel(route, link->manager);
if (r < 0)
return r;
/* Unfortunately, we cannot directly pass 'route' to route_remove_and_cancel() here, as the
* same or similar route may be configured or requested statically. */
/* First, check if the route is already requested. If there is an existing route, and also an
* existing pending request, then the source may be updated by the request. So, we first need
* to check the source of the requested route. */
if (route_get_request(link->manager, route, &req) >= 0) {
existing = ASSERT_PTR(req->userdata);
if (existing->source == NETWORK_CONFIG_SOURCE_STATIC)
continue;
r = route_remove_and_cancel(existing, link->manager);
if (r < 0)
return r;
}
/* Then, check if the route exists. */
if (route_get(link->manager, route, &existing) >= 0) {
if (existing->source == NETWORK_CONFIG_SOURCE_STATIC)
continue;
r = route_remove_and_cancel(existing, link->manager);
if (r < 0)
return r;
}
}
return 0;