diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c index dc4868300a..24bafb8b4a 100644 --- a/src/network/networkd-dhcp-prefix-delegation.c +++ b/src/network/networkd-dhcp-prefix-delegation.c @@ -184,7 +184,7 @@ int dhcp6_pd_remove(Link *link, bool only_marked) { if (k < 0) r = k; - route_cancel_request(route); + route_cancel_request(route, link); } } else { Address *address; @@ -655,6 +655,7 @@ static int dhcp6_pd_finalize(Link *link) { } void dhcp6_pd_prefix_lost(Link *dhcp6_link) { + Route *route; Link *link; int r; @@ -662,7 +663,7 @@ void dhcp6_pd_prefix_lost(Link *dhcp6_link) { assert(dhcp6_link->manager); HASHMAP_FOREACH(link, dhcp6_link->manager->links_by_index) { - if (link == dhcp6_link) + if (!dhcp6_pd_is_uplink(link, dhcp6_link, /* accept_auto = */ true)) continue; r = dhcp6_pd_remove(link, /* only_marked = */ false); @@ -670,6 +671,25 @@ void dhcp6_pd_prefix_lost(Link *dhcp6_link) { link_enter_failed(link); } + SET_FOREACH(route, dhcp6_link->manager->routes) { + if (route->source != NETWORK_CONFIG_SOURCE_DHCP6) + continue; + if (route->family != AF_INET6) + continue; + if (route->type != RTN_UNREACHABLE) + continue; + if (!set_contains(dhcp6_link->dhcp6_pd_prefixes, + &(struct in_addr_prefix) { + .family = AF_INET6, + .prefixlen = route->dst_prefixlen, + .address = route->dst })) + continue; + + (void) route_remove(route); + + route_cancel_request(route, dhcp6_link); + } + set_clear(dhcp6_link->dhcp6_pd_prefixes); } diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 1ee0052a75..cd30cae7c9 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -71,7 +71,7 @@ static int dhcp4_remove_address_and_routes(Link *link, bool only_marked) { if (k < 0) r = k; - route_cancel_request(route); + route_cancel_request(route, link); } SET_FOREACH(address, link->addresses) { diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index f86efca5c7..b9831e7fa1 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -63,7 +63,7 @@ static int dhcp6_remove(Link *link, bool only_marked) { if (k < 0) r = k; - route_cancel_request(route); + route_cancel_request(route, link); } SET_FOREACH(address, link->addresses) { diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 470c969329..df5e580aef 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -90,7 +90,7 @@ static int ndisc_remove(Link *link, struct in6_addr *router) { if (k < 0) r = k; - route_cancel_request(route); + route_cancel_request(route, link); } SET_FOREACH(address, link->addresses) { diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 003c8dcde4..8e4081a8e3 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -1260,24 +1260,25 @@ static int route_configure( return 0; } -void route_cancel_request(Route *route) { +void route_cancel_request(Route *route, Link *link) { Request req; assert(route); + link = route->link ?: link; + + assert(link); + if (!route_is_requesting(route)) return; - if (!route->link) - return; - req = (Request) { - .link = route->link, + .link = link, .type = REQUEST_TYPE_ROUTE, .route = route, }; - request_drop(ordered_set_get(route->link->manager->request_queue, &req)); + request_drop(ordered_set_get(link->manager->request_queue, &req)); route_cancel_requesting(route); } diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index a3194de1ae..e3e22a5985 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -86,7 +86,7 @@ int link_drop_routes(Link *link); int link_drop_foreign_routes(Link *link); void link_foreignize_routes(Link *link); -void route_cancel_request(Route *route); +void route_cancel_request(Route *route, Link *link); int link_request_route( Link *link, Route *route,