From 2a877f4560362eb9a330460c05713edd031c9228 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 8 Jul 2020 11:19:13 +0900 Subject: [PATCH] network: set dhcp6_xxx_configured flag after routes/addresses are assigned --- src/network/networkd-dhcp6.c | 122 ++++++++++++++++++++++++++--------- src/network/networkd-dhcp6.h | 1 + src/network/networkd-link.c | 5 +- src/network/networkd-link.h | 9 ++- 4 files changed, 105 insertions(+), 32 deletions(-) diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 73b49a5ec04..77522afed4a 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -24,7 +24,6 @@ #include "radv-internal.h" #include "web-util.h" -static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link); static Link *dhcp6_prefix_get(Manager *m, struct in6_addr *addr); static int dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link); static int dhcp6_prefix_remove_all(Manager *m, Link *link); @@ -33,7 +32,7 @@ static int dhcp6_assign_delegated_prefix(Link *link, const struct in6_addr *pref uint32_t lifetime_preferred, uint32_t lifetime_valid); -static bool dhcp6_get_prefix_delegation(Link *link) { +bool dhcp6_get_prefix_delegation(Link *link) { if (!link->network) return false; @@ -172,11 +171,9 @@ static int dhcp6_pd_prefix_assign(Link *link, struct in6_addr *prefix, if (r < 0) return r; - if (link->network->dhcp6_pd_assign_prefix) { - r = dhcp6_assign_delegated_prefix(link, prefix, prefix_len, lifetime_preferred, lifetime_valid); - if (r < 0) - return r; - } + r = dhcp6_assign_delegated_prefix(link, prefix, prefix_len, lifetime_preferred, lifetime_valid); + if (r < 0) + return r; return 0; } @@ -324,13 +321,25 @@ static int dhcp6_route_handler(sd_netlink *nl, sd_netlink_message *m, Link *link int r; assert(link); + assert(link->dhcp6_route_messages > 0); + + link->dhcp6_route_messages--; if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) - log_link_message_warning_errno(link, m, r, "Received error when adding unreachable route for DHCPv6 delegated subnet"); + if (r < 0 && r != -EEXIST) { + log_link_message_warning_errno(link, m, r, "Failed to add unreachable route for DHCPv6 delegated subnet"); + link_enter_failed(link); + return 1; + } + + if (link->dhcp6_route_messages == 0) { + log_link_debug(link, "Unreachable routes for DHCPv6 delegated subnets set"); + link->dhcp6_route_configured = true; + link_check_ready(link); + } return 1; } @@ -342,6 +351,8 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) { uint8_t pd_prefix_len; int r; + link->dhcp6_route_configured = false; + r = sd_dhcp6_client_get_lease(client, &lease); if (r < 0) return r; @@ -386,6 +397,8 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) { pd_prefix_len); continue; } + if (r > 0) + link->dhcp6_route_messages++; log_link_debug(link, "Configuring unreachable route for %s/%u", strnull(buf), pd_prefix_len); @@ -435,6 +448,14 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) { * fulfill those with the next available pd delegated prefix. */ } + if (link->dhcp6_route_messages == 0) { + link->dhcp6_route_configured = true; + link_check_ready(link); + } else { + log_link_debug(link, "Setting unreachable routes for DHCPv6 delegated subnets"); + link_set_state(link, LINK_STATE_CONFIGURING); + } + return 0; } @@ -506,6 +527,9 @@ static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link * int r; assert(link); + assert(link->dhcp6_address_messages > 0); + + link->dhcp6_address_messages--; if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; @@ -518,10 +542,14 @@ static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link * } else if (r >= 0) (void) manager_rtnl_process_address(rtnl, m, link->manager); - r = link_request_set_routes(link); - if (r < 0) { - link_enter_failed(link); - return 1; + if (link->dhcp6_address_messages == 0) { + log_link_debug(link, "DHCPv6 addresses set"); + link->dhcp6_address_configured = true; + r = link_request_set_routes(link); + if (r < 0) { + link_enter_failed(link); + return 1; + } } return 1; @@ -556,6 +584,8 @@ static int dhcp6_address_change( r = address_configure(addr, link, dhcp6_address_handler, true); if (r < 0) return log_link_warning_errno(link, r, "Could not assign DHCPv6 address: %m"); + if (r > 0) + link->dhcp6_address_messages++; return 0; } @@ -566,12 +596,14 @@ static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link) { struct in6_addr ip6_addr; uint32_t lifetime_preferred, lifetime_valid; + + link->dhcp6_address_configured = false; + r = sd_dhcp6_client_get_lease(client, &lease); if (r < 0) return r; sd_dhcp6_lease_reset_address_iter(lease); - while (sd_dhcp6_lease_get_address(lease, &ip6_addr, &lifetime_preferred, &lifetime_valid) >= 0) { @@ -581,6 +613,14 @@ static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link) { return r; } + if (link->dhcp6_address_messages == 0) { + link->dhcp6_address_configured = true; + return link_request_set_routes(link); + } else { + log_link_debug(link, "Setting DHCPv6 addresses"); + link_set_state(link, LINK_STATE_CONFIGURING); + } + return 0; } @@ -605,7 +645,6 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) { (void) dhcp6_prefix_remove_all(link->manager, link); link_dirty(link); - link->dhcp6_configured = false; break; case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE: @@ -617,7 +656,7 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) { r = dhcp6_lease_pd_prefix_acquired(client, link); if (r < 0) - log_link_debug(link, "DHCPv6 did not receive prefixes to delegate"); + log_link_debug_errno(link, r, "DHCPv6 did not receive prefixes to delegate"); _fallthrough_; case SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST: @@ -628,7 +667,6 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) { } link_dirty(link); - link->dhcp6_configured = true; break; default: @@ -665,7 +703,7 @@ int dhcp6_request_address(Link *link, int ir) { r = sd_dhcp6_client_set_address_request(link->dhcp6_client, false); - if (r < 0 ) + if (r < 0) return r; ir = false; @@ -865,21 +903,30 @@ static Link *dhcp6_prefix_get(Manager *m, struct in6_addr *addr) { return hashmap_get(m->dhcp6_prefixes, addr); } -static int dhcp6_route_add_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) { +static int dhcp6_pd_route_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) { int r; assert(link); + assert(link->dhcp6_pd_route_messages > 0); + + link->dhcp6_pd_route_messages--; if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EEXIST) { - log_link_message_warning_errno(link, m, r, "Received error adding DHCPv6 Prefix Delegation route"); + log_link_message_warning_errno(link, m, r, "Failed to add DHCPv6 Prefix Delegation route"); link_enter_failed(link); return 1; } + if (link->dhcp6_pd_route_messages == 0) { + log_link_debug(link, "DHCPv6 prefix delegation routes set"); + link->dhcp6_pd_route_configured = true; + link_check_ready(link); + } + return 1; } @@ -901,9 +948,14 @@ static int dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) { route->dst.in6 = *addr; route->dst_prefixlen = 64; - r = route_configure(route, link, dhcp6_route_add_handler); + link->dhcp6_pd_route_configured = false; + link_set_state(link, LINK_STATE_CONFIGURING); + + r = route_configure(route, link, dhcp6_pd_route_handler); if (r < 0) return r; + if (r > 0) + link->dhcp6_pd_route_messages++; (void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf); log_link_debug(link, "Adding prefix route %s/64", strnull(buf)); @@ -998,26 +1050,33 @@ static int dhcp6_prefix_remove_all(Manager *m, Link *link) { return 0; } -static int dhcp6_assign_delegeted_prefix_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int dhcp6_pd_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; assert(link); + assert(link->dhcp6_pd_address_messages > 0); + + link->dhcp6_pd_address_messages--; if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EEXIST) { - log_link_message_warning_errno(link, m, r, "Could not set DHCPv6 delegated prefix address "); + log_link_message_warning_errno(link, m, r, "Could not set DHCPv6 delegated prefix address"); link_enter_failed(link); return 1; } else if (r >= 0) (void) manager_rtnl_process_address(rtnl, m, link->manager); - r = link_request_set_routes(link); - if (r < 0) { - link_enter_failed(link); - return 1; + if (link->dhcp6_pd_address_messages == 0) { + log_link_debug(link, "DHCPv6 delegated prefix addresses set"); + link->dhcp6_pd_address_configured = true; + r = link_request_set_routes(link); + if (r < 0) { + link_enter_failed(link); + return 1; + } } return 1; @@ -1036,8 +1095,10 @@ static int dhcp6_assign_delegated_prefix(Link *link, assert(link->network); assert(prefix); - if (!link->network->dhcp6_pd_assign_prefix) + if (!link->network->dhcp6_pd_assign_prefix) { + link->dhcp6_pd_address_configured = true; return 0; + } r = address_new(&address); if (r < 0) @@ -1058,11 +1119,14 @@ static int dhcp6_assign_delegated_prefix(Link *link, address->cinfo.ifa_prefered = lifetime_preferred; address->cinfo.ifa_valid = lifetime_valid; + link->dhcp6_pd_address_configured = false; link_set_state(link, LINK_STATE_CONFIGURING); - r = address_configure(address, link, dhcp6_assign_delegeted_prefix_address_handler, true); + r = address_configure(address, link, dhcp6_pd_address_handler, true); if (r < 0) return log_link_warning_errno(link, r, "Failed to set acquired DHCPv6 delegated prefix address: %m"); + if (r > 0) + link->dhcp6_pd_address_messages++; return 0; } diff --git a/src/network/networkd-dhcp6.h b/src/network/networkd-dhcp6.h index 858559a1e09..cc416b98d2e 100644 --- a/src/network/networkd-dhcp6.h +++ b/src/network/networkd-dhcp6.h @@ -17,6 +17,7 @@ typedef enum DHCP6ClientStartMode { typedef struct Link Link; typedef struct Manager Manager; +bool dhcp6_get_prefix_delegation(Link *link); int dhcp6_request_prefix_delegation(Link *link); int dhcp6_configure(Link *link); int dhcp6_request_address(Link *link, int ir); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 71e6976a30a..cd864c690b6 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1141,9 +1141,10 @@ void link_check_ready(Link *link) { in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address)) return; - if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link) || link_ipv6_accept_ra_enabled(link)) && + if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link) || dhcp6_get_prefix_delegation(link) || link_ipv6_accept_ra_enabled(link)) && !link->dhcp4_configured && - !link->dhcp6_configured && + !(link->dhcp6_address_configured && link->dhcp6_route_configured) && + !(link->dhcp6_pd_address_configured && link->dhcp6_pd_route_configured) && !link->ndisc_configured && !(link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4) && link->ipv4ll_address)) /* When DHCP or RA is enabled, at least one protocol must provide an address, or diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index f615e7e62dc..4333cfa175b 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -100,10 +100,17 @@ typedef struct Link { char *lease_file; uint32_t original_mtu; unsigned dhcp4_messages; + unsigned dhcp6_address_messages; + unsigned dhcp6_route_messages; + unsigned dhcp6_pd_address_messages; + unsigned dhcp6_pd_route_messages; bool dhcp4_route_failed:1; bool dhcp4_route_retrying:1; bool dhcp4_configured:1; - bool dhcp6_configured:1; + bool dhcp6_address_configured:1; + bool dhcp6_route_configured:1; + bool dhcp6_pd_address_configured:1; + bool dhcp6_pd_route_configured:1; unsigned ndisc_messages; bool ndisc_configured;