return 0;
}
-void dhcp_pd_prefix_lost(Link *uplink) {
+static void dhcp_pd_mark_unreachable_route(Manager *manager, NetworkConfigSource source) {
+ assert(manager);
+
+ Route *route;
+ SET_FOREACH(route, manager->routes) {
+ if (route->source != source)
+ continue;
+ if (route->family != AF_INET6)
+ continue;
+ if (route->nexthop.ifindex != 0) /* IPv6 unreachable has 0 ifindex. */
+ continue;
+ if (!route_type_is_reject(route->type))
+ continue;
+
+ route_mark(route);
+ }
+}
+
+static int dhcp_pd_remove_unreachable_route(Manager *manager, NetworkConfigSource source, bool only_marked) {
+ int ret = 0;
+
+ assert(manager);
+
Route *route;
+ SET_FOREACH(route, manager->routes) {
+ if (route->source != source)
+ continue;
+ if (route->family != AF_INET6)
+ continue;
+ if (route->nexthop.ifindex != 0) /* IPv6 unreachable has 0 ifindex. */
+ continue;
+ if (!route_type_is_reject(route->type))
+ continue;
+ if (only_marked && !route_is_marked(route))
+ continue;
+
+ RET_GATHER(ret, route_remove_and_cancel(route, manager));
+ }
+
+ return ret;
+}
+
+static void dhcp_pd_prefix_lost(Link *uplink, NetworkConfigSource source) {
Link *link;
int r;
link_enter_failed(link);
}
- SET_FOREACH(route, uplink->manager->routes) {
- if (!IN_SET(route->source, NETWORK_CONFIG_SOURCE_DHCP4, NETWORK_CONFIG_SOURCE_DHCP6))
- continue;
- if (route->family != AF_INET6)
- continue;
- if (route->type != RTN_UNREACHABLE)
- continue;
- if (!set_contains(uplink->dhcp_pd_prefixes,
- &(struct in_addr_prefix) {
- .family = AF_INET6,
- .prefixlen = route->dst_prefixlen,
- .address = route->dst }))
- continue;
-
- (void) route_remove_and_cancel(route, uplink->manager);
- }
+ (void) dhcp_pd_remove_unreachable_route(uplink->manager, source, /* only_marked = */ false);
set_clear(uplink->dhcp_pd_prefixes);
}
void dhcp4_pd_prefix_lost(Link *uplink) {
Link *tunnel;
- dhcp_pd_prefix_lost(uplink);
+ assert(uplink);
+ assert(uplink->manager);
+
+ dhcp_pd_prefix_lost(uplink, NETWORK_CONFIG_SOURCE_DHCP4);
if (uplink->dhcp4_6rd_tunnel_name &&
link_get_by_name(uplink->manager, uplink->dhcp4_6rd_tunnel_name, &tunnel) >= 0)
(void) link_remove(tunnel);
}
+void dhcp6_pd_prefix_lost(Link *uplink) {
+ dhcp_pd_prefix_lost(uplink, NETWORK_CONFIG_SOURCE_DHCP6);
+}
+
static int dhcp4_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
int r;
return r;
/* Request unreachable route */
+ dhcp_pd_mark_unreachable_route(uplink->manager, NETWORK_CONFIG_SOURCE_DHCP4);
r = dhcp4_request_unreachable_route(uplink, &pd_prefix, pd_prefixlen, lifetime_usec, &server_address);
if (r < 0)
return r;
+ (void) dhcp_pd_remove_unreachable_route(uplink->manager, NETWORK_CONFIG_SOURCE_DHCP4, /* only_marked = */ true);
/* Create or update 6rd SIT tunnel device. */
r = dhcp4_pd_create_6rd_tunnel(uplink, dhcp4_pd_6rd_tunnel_create_handler);
assert(uplink);
assert(uplink->dhcp6_lease);
+ assert(uplink->manager);
r = sd_dhcp6_lease_get_server_address(uplink->dhcp6_lease, &server_address.in6);
if (r < 0)
return log_link_warning_errno(uplink, r, "Failed to get server address of DHCPv6 lease: %m");
+ dhcp_pd_mark_unreachable_route(uplink->manager, NETWORK_CONFIG_SOURCE_DHCP6);
+
/* First, logs acquired prefixes and request unreachable routes. */
FOREACH_DHCP6_PD_PREFIX(uplink->dhcp6_lease) {
usec_t lifetime_valid_usec;
return r;
}
+ (void) dhcp_pd_remove_unreachable_route(uplink->manager, NETWORK_CONFIG_SOURCE_DHCP6, /* only_marked = */ true);
+
/* Then, assign subnet prefixes. */
HASHMAP_FOREACH(link, uplink->manager->links_by_index) {
if (!dhcp_pd_is_uplink(link, uplink, /* accept_auto = */ true))
int r;
link_mark_addresses(link, NETWORK_CONFIG_SOURCE_DHCP6);
- manager_mark_routes(link->manager, NULL, NETWORK_CONFIG_SOURCE_DHCP6);
r = sd_dhcp6_client_get_lease(client, &lease);
if (r < 0)
return r;
} else if (sd_dhcp6_lease_has_pd_prefix(lease_old))
/* When we had PD prefixes but not now, we need to remove them. */
- dhcp_pd_prefix_lost(link);
+ dhcp6_pd_prefix_lost(link);
if (link->dhcp6_messages == 0) {
link->dhcp6_configured = true;
log_link_info(link, "DHCPv6 lease lost");
if (sd_dhcp6_lease_has_pd_prefix(link->dhcp6_lease))
- dhcp_pd_prefix_lost(link);
+ dhcp6_pd_prefix_lost(link);
link->dhcp6_lease = sd_dhcp6_lease_unref(link->dhcp6_lease);