diff options
Diffstat (limited to 'src/network/networkd-dhcp-prefix-delegation.c')
-rw-r--r-- | src/network/networkd-dhcp-prefix-delegation.c | 136 |
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"); |