summaryrefslogtreecommitdiffstats
path: root/src/network/networkd-dhcp-prefix-delegation.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/networkd-dhcp-prefix-delegation.c')
-rw-r--r--src/network/networkd-dhcp-prefix-delegation.c136
1 files changed, 89 insertions, 47 deletions
diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c
index af2fe9e..2e660b7 100644
--- a/src/network/networkd-dhcp-prefix-delegation.c
+++ b/src/network/networkd-dhcp-prefix-delegation.c
@@ -101,6 +101,7 @@ static int link_get_by_dhcp_pd_subnet_prefix(Manager *manager, const struct in6_
static int dhcp_pd_get_assigned_subnet_prefix(Link *link, const struct in6_addr *pd_prefix, uint8_t pd_prefix_len, struct in6_addr *ret) {
assert(link);
+ assert(link->manager);
assert(pd_prefix);
if (!link_dhcp_pd_is_enabled(link))
@@ -128,11 +129,14 @@ static int dhcp_pd_get_assigned_subnet_prefix(Link *link, const struct in6_addr
} else {
Route *route;
- SET_FOREACH(route, link->routes) {
+ SET_FOREACH(route, link->manager->routes) {
if (route->source != NETWORK_CONFIG_SOURCE_DHCP_PD)
continue;
assert(route->family == AF_INET6);
+ if (route->nexthop.ifindex != link->ifindex)
+ continue;
+
if (in6_addr_prefix_covers(pd_prefix, pd_prefix_len, &route->dst.in6) > 0) {
if (ret)
*ret = route->dst.in6;
@@ -145,7 +149,7 @@ static int dhcp_pd_get_assigned_subnet_prefix(Link *link, const struct in6_addr
}
int dhcp_pd_remove(Link *link, bool only_marked) {
- int k, r = 0;
+ int ret = 0;
assert(link);
assert(link->manager);
@@ -159,9 +163,11 @@ int dhcp_pd_remove(Link *link, bool only_marked) {
if (!link->network->dhcp_pd_assign) {
Route *route;
- SET_FOREACH(route, link->routes) {
+ SET_FOREACH(route, link->manager->routes) {
if (route->source != NETWORK_CONFIG_SOURCE_DHCP_PD)
continue;
+ if (route->nexthop.ifindex != link->ifindex)
+ continue;
if (only_marked && !route_is_marked(route))
continue;
@@ -170,11 +176,7 @@ int dhcp_pd_remove(Link *link, bool only_marked) {
link_remove_dhcp_pd_subnet_prefix(link, &route->dst.in6);
- k = route_remove(route);
- if (k < 0)
- r = k;
-
- route_cancel_request(route, link);
+ RET_GATHER(ret, route_remove_and_cancel(route, link->manager));
}
} else {
Address *address;
@@ -195,13 +197,11 @@ int dhcp_pd_remove(Link *link, bool only_marked) {
link_remove_dhcp_pd_subnet_prefix(link, &prefix);
- k = address_remove_and_drop(address);
- if (k < 0)
- r = k;
+ RET_GATHER(ret, address_remove_and_cancel(address, link));
}
}
- return r;
+ return ret;
}
static int dhcp_pd_check_ready(Link *link);
@@ -270,7 +270,7 @@ static int dhcp_pd_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Reques
assert(link);
- r = route_configure_handler_internal(rtnl, m, link, "Failed to add prefix route for DHCP delegated subnet prefix");
+ r = route_configure_handler_internal(rtnl, m, link, route, "Failed to add prefix route for DHCP delegated subnet prefix");
if (r <= 0)
return r;
@@ -282,11 +282,12 @@ static int dhcp_pd_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Reques
}
static int dhcp_pd_request_route(Link *link, const struct in6_addr *prefix, usec_t lifetime_usec) {
- _cleanup_(route_freep) Route *route = NULL;
+ _cleanup_(route_unrefp) Route *route = NULL;
Route *existing;
int r;
assert(link);
+ assert(link->manager);
assert(link->network);
assert(prefix);
@@ -305,13 +306,16 @@ static int dhcp_pd_request_route(Link *link, const struct in6_addr *prefix, usec
route->priority = link->network->dhcp_pd_route_metric;
route->lifetime_usec = lifetime_usec;
- if (route_get(NULL, link, route, &existing) < 0)
+ r = route_adjust_nexthops(route, link);
+ if (r < 0)
+ return r;
+
+ if (route_get(link->manager, route, &existing) < 0)
link->dhcp_pd_configured = false;
else
route_unmark(existing);
- r = link_request_route(link, TAKE_PTR(route), true, &link->dhcp_pd_messages,
- dhcp_pd_route_handler, NULL);
+ r = link_request_route(link, route, &link->dhcp_pd_messages, dhcp_pd_route_handler);
if (r < 0)
return log_link_error_errno(link, r, "Failed to request DHCP-PD prefix route: %m");
@@ -349,14 +353,50 @@ static void log_dhcp_pd_address(Link *link, const Address *address) {
FORMAT_LIFETIME(address->lifetime_preferred_usec));
}
+static int dhcp_pd_request_address_one(Address *address, Link *link) {
+ Address *existing;
+
+ assert(address);
+ assert(link);
+
+ log_dhcp_pd_address(link, address);
+
+ if (address_get(link, address, &existing) < 0)
+ link->dhcp_pd_configured = false;
+ else
+ address_unmark(existing);
+
+ return link_request_address(link, address, &link->dhcp_pd_messages, dhcp_pd_address_handler, NULL);
+}
+
+int dhcp_pd_reconfigure_address(Address *address, Link *link) {
+ int r;
+
+ assert(address);
+ assert(address->source == NETWORK_CONFIG_SOURCE_DHCP_PD);
+ assert(link);
+
+ r = regenerate_address(address, link);
+ if (r <= 0)
+ return r;
+
+ r = dhcp_pd_request_address_one(address, link);
+ if (r < 0)
+ return r;
+
+ if (!link->dhcp_pd_configured)
+ link_set_state(link, LINK_STATE_CONFIGURING);
+
+ link_check_ready(link);
+ return 0;
+}
+
static int dhcp_pd_request_address(
Link *link,
const struct in6_addr *prefix,
usec_t lifetime_preferred_usec,
usec_t lifetime_valid_usec) {
- _cleanup_set_free_ Set *addresses = NULL;
- struct in6_addr *a;
int r;
assert(link);
@@ -366,13 +406,15 @@ static int dhcp_pd_request_address(
if (!link->network->dhcp_pd_assign)
return 0;
- r = dhcp_pd_generate_addresses(link, prefix, &addresses);
+ _cleanup_hashmap_free_ Hashmap *tokens_by_address = NULL;
+ r = dhcp_pd_generate_addresses(link, prefix, &tokens_by_address);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to generate addresses for acquired DHCP delegated prefix: %m");
- SET_FOREACH(a, addresses) {
- _cleanup_(address_freep) Address *address = NULL;
- Address *existing;
+ IPv6Token *token;
+ struct in6_addr *a;
+ HASHMAP_FOREACH_KEY(token, a, tokens_by_address) {
+ _cleanup_(address_unrefp) Address *address = NULL;
r = address_new(&address);
if (r < 0)
@@ -386,20 +428,13 @@ static int dhcp_pd_request_address(
address->lifetime_valid_usec = lifetime_valid_usec;
SET_FLAG(address->flags, IFA_F_MANAGETEMPADDR, link->network->dhcp_pd_manage_temporary_address);
address->route_metric = link->network->dhcp_pd_route_metric;
-
- log_dhcp_pd_address(link, address);
+ address->token = ipv6_token_ref(token);
r = free_and_strdup_warn(&address->netlabel, link->network->dhcp_pd_netlabel);
if (r < 0)
return r;
- if (address_get(link, address, &existing) < 0)
- link->dhcp_pd_configured = false;
- else
- address_unmark(existing);
-
- r = link_request_address(link, address, &link->dhcp_pd_messages,
- dhcp_pd_address_handler, NULL);
+ r = dhcp_pd_request_address_one(address, link);
if (r < 0)
return log_link_error_errno(link, r, "Failed to request DHCP delegated prefix address: %m");
}
@@ -550,7 +585,7 @@ static int dhcp_pd_prepare(Link *link) {
return 0;
link_mark_addresses(link, NETWORK_CONFIG_SOURCE_DHCP_PD);
- link_mark_routes(link, NETWORK_CONFIG_SOURCE_DHCP_PD);
+ manager_mark_routes(link->manager, link, NETWORK_CONFIG_SOURCE_DHCP_PD);
return 1;
}
@@ -607,9 +642,7 @@ void dhcp_pd_prefix_lost(Link *uplink) {
.address = route->dst }))
continue;
- (void) route_remove(route);
-
- route_cancel_request(route, uplink);
+ (void) route_remove_and_cancel(route, uplink->manager);
}
set_clear(uplink->dhcp_pd_prefixes);
@@ -630,7 +663,7 @@ static int dhcp4_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message
assert(link);
- r = route_configure_handler_internal(rtnl, m, link, "Failed to set unreachable route for DHCPv4 delegated prefix");
+ r = route_configure_handler_internal(rtnl, m, link, route, "Failed to set unreachable route for DHCPv4 delegated prefix");
if (r <= 0)
return r;
@@ -646,7 +679,7 @@ static int dhcp6_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message
assert(link);
- r = route_configure_handler_internal(rtnl, m, link, "Failed to set unreachable route for DHCPv6 delegated prefix");
+ r = route_configure_handler_internal(rtnl, m, link, route, "Failed to set unreachable route for DHCPv6 delegated prefix");
if (r <= 0)
return r;
@@ -668,11 +701,12 @@ static int dhcp_request_unreachable_route(
route_netlink_handler_t callback,
bool *configured) {
- _cleanup_(route_freep) Route *route = NULL;
+ _cleanup_(route_unrefp) Route *route = NULL;
Route *existing;
int r;
assert(link);
+ assert(link->manager);
assert(addr);
assert(IN_SET(source, NETWORK_CONFIG_SOURCE_DHCP4, NETWORK_CONFIG_SOURCE_DHCP6));
assert(server_address);
@@ -700,12 +734,16 @@ static int dhcp_request_unreachable_route(
route->priority = IP6_RT_PRIO_USER;
route->lifetime_usec = lifetime_usec;
- if (route_get(link->manager, NULL, route, &existing) < 0)
+ r = route_adjust_nexthops(route, link);
+ if (r < 0)
+ return r;
+
+ if (route_get(link->manager, route, &existing) < 0)
*configured = false;
else
route_unmark(existing);
- r = link_request_route(link, TAKE_PTR(route), true, counter, callback, NULL);
+ r = link_request_route(link, route, counter, callback);
if (r < 0)
return log_link_error_errno(link, r, "Failed to request unreachable route for DHCP delegated prefix %s: %m",
IN6_ADDR_PREFIX_TO_STRING(addr, prefixlen));
@@ -774,11 +812,12 @@ static int dhcp_pd_prefix_add(Link *link, const struct in6_addr *prefix, uint8_t
}
static int dhcp4_pd_request_default_gateway_on_6rd_tunnel(Link *link, const struct in_addr *br_address, usec_t lifetime_usec) {
- _cleanup_(route_freep) Route *route = NULL;
+ _cleanup_(route_unrefp) Route *route = NULL;
Route *existing;
int r;
assert(link);
+ assert(link->manager);
assert(br_address);
r = route_new(&route);
@@ -787,20 +826,23 @@ static int dhcp4_pd_request_default_gateway_on_6rd_tunnel(Link *link, const stru
route->source = NETWORK_CONFIG_SOURCE_DHCP_PD;
route->family = AF_INET6;
- route->gw_family = AF_INET6;
- route->gw.in6.s6_addr32[3] = br_address->s_addr;
+ route->nexthop.family = AF_INET6;
+ route->nexthop.gw.in6.s6_addr32[3] = br_address->s_addr;
route->scope = RT_SCOPE_UNIVERSE;
route->protocol = RTPROT_DHCP;
route->priority = IP6_RT_PRIO_USER;
route->lifetime_usec = lifetime_usec;
- if (route_get(NULL, link, route, &existing) < 0) /* This is a new route. */
+ r = route_adjust_nexthops(route, link);
+ if (r < 0)
+ return r;
+
+ if (route_get(link->manager, route, &existing) < 0) /* This is a new route. */
link->dhcp_pd_configured = false;
else
route_unmark(existing);
- r = link_request_route(link, TAKE_PTR(route), true, &link->dhcp_pd_messages,
- dhcp_pd_route_handler, NULL);
+ r = link_request_route(link, route, &link->dhcp_pd_messages, dhcp_pd_route_handler);
if (r < 0)
return log_link_debug_errno(link, r, "Failed to request default gateway for DHCP delegated prefix: %m");