From d7fbb9f50c9aa06a0ae9c3129900aed7cb3e425e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 2 Oct 2020 11:30:33 +0900 Subject: [PATCH] network: introduce link_drop_addresses() --- src/network/networkd-address.c | 60 ++++++++++++++++++++++++++++++++++ src/network/networkd-address.h | 1 + src/network/networkd-link.c | 52 ++--------------------------- 3 files changed, 64 insertions(+), 49 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 86ea5c2da17..bb97fdacfeb 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -621,6 +621,66 @@ int link_drop_foreign_addresses(Link *link) { return r; } +static int remove_static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(m); + assert(link); + assert(link->ifname); + assert(link->address_remove_messages > 0); + + link->address_remove_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 != -EADDRNOTAVAIL) + log_link_message_warning_errno(link, m, r, "Could not drop address"); + else if (r >= 0) + (void) manager_rtnl_process_address(rtnl, m, link->manager); + + if (link->address_remove_messages == 0 && link->request_static_addresses) { + link_set_state(link, LINK_STATE_CONFIGURING); + r = link_set_addresses(link); + if (r < 0) + link_enter_failed(link); + } + + return 1; +} + +int link_drop_addresses(Link *link) { + Address *address, *pool_address; + int k, r = 0; + + assert(link); + + SET_FOREACH(address, link->addresses) { + /* we consider IPv6LL addresses to be managed by the kernel */ + if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1 && link_ipv6ll_enabled(link)) + continue; + + k = address_remove(address, link, remove_static_address_handler); + if (k < 0 && r >= 0) { + r = k; + continue; + } + + link->address_remove_messages++; + + /* If this address came from an address pool, clean up the pool */ + LIST_FOREACH(addresses, pool_address, link->pool_addresses) + if (address_equal(address, pool_address)) { + LIST_REMOVE(addresses, link->pool_addresses, pool_address); + address_free(pool_address); + break; + } + } + + return r; +} + static int address_acquire(Link *link, Address *original, Address **ret) { union in_addr_union in_addr = IN_ADDR_NULL; struct in_addr broadcast = {}; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 66334239372..472e8ee79a5 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -76,6 +76,7 @@ int generate_ipv6_eui_64_address(Link *link, struct in6_addr *ret); DEFINE_NETWORK_SECTION_FUNCTIONS(Address, address_free); int link_set_addresses(Link *link); +int link_drop_addresses(Link *link); int link_drop_foreign_addresses(Link *link); void address_hash_func(const Address *a, struct siphash *state); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 4ea97b2acb3..f2314e65f2c 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2384,58 +2384,12 @@ static int link_drop_foreign_config(Link *link) { return link_drop_foreign_routes(link); } -static int remove_static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - int r; - - assert(m); - assert(link); - assert(link->ifname); - assert(link->address_remove_messages > 0); - - link->address_remove_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 != -EADDRNOTAVAIL) - log_link_message_warning_errno(link, m, r, "Could not drop address"); - else if (r >= 0) - (void) manager_rtnl_process_address(rtnl, m, link->manager); - - if (link->address_remove_messages == 0 && link->request_static_addresses) { - link_set_state(link, LINK_STATE_CONFIGURING); - r = link_set_addresses(link); - if (r < 0) - link_enter_failed(link); - } - - return 1; -} - static int link_drop_config(Link *link) { - Address *address, *pool_address; int r; - SET_FOREACH(address, link->addresses) { - /* we consider IPv6LL addresses to be managed by the kernel */ - if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1 && link_ipv6ll_enabled(link)) - continue; - - r = address_remove(address, link, remove_static_address_handler); - if (r < 0) - return r; - - link->address_remove_messages++; - - /* If this address came from an address pool, clean up the pool */ - LIST_FOREACH(addresses, pool_address, link->pool_addresses) - if (address_equal(address, pool_address)) { - LIST_REMOVE(addresses, link->pool_addresses, pool_address); - address_free(pool_address); - break; - } - } + r = link_drop_addresses(link); + if (r < 0) + return r; r = link_drop_neighbors(link); if (r < 0)