From: Yu Watanabe Date: Fri, 2 Oct 2020 02:26:12 +0000 (+0900) Subject: network: introduce link_drop_foreign_addresses() X-Git-Tag: v247-rc1~117^2~55 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f8f2f880d4b7bee6ec64aef4c252e4064c67d133;p=thirdparty%2Fsystemd.git network: introduce link_drop_foreign_addresses() --- diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 454be9a066f..86ea5c2da17 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -542,6 +542,85 @@ int address_remove( return 0; } +static bool link_is_static_address_configured(Link *link, Address *address) { + Address *net_address; + + assert(link); + assert(address); + + if (!link->network) + return false; + + LIST_FOREACH(addresses, net_address, link->network->static_addresses) + if (address_equal(net_address, address)) + return true; + else if (address->family == AF_INET6 && net_address->family == AF_INET6 && + in_addr_equal(AF_INET6, &address->in_addr, &net_address->in_addr_peer) > 0) + return true; + + return false; +} + +static bool link_address_is_dynamic(Link *link, Address *address) { + Route *route; + + assert(link); + assert(address); + + if (address->cinfo.ifa_prefered != CACHE_INFO_INFINITY_LIFE_TIME) + return true; + + /* Even when the address is leased from a DHCP server, networkd assign the address + * without lifetime when KeepConfiguration=dhcp. So, let's check that we have + * corresponding routes with RTPROT_DHCP. */ + SET_FOREACH(route, link->routes_foreign) { + if (route->protocol != RTPROT_DHCP) + continue; + + if (address->family != route->family) + continue; + + if (in_addr_equal(address->family, &address->in_addr, &route->prefsrc)) + return true; + } + + return false; +} + +int link_drop_foreign_addresses(Link *link) { + Address *address; + int k, r = 0; + + assert(link); + + SET_FOREACH(address, link->addresses_foreign) { + /* 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; + + if (link_address_is_dynamic(link, address)) { + if (link->network && FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) + continue; + } else if (link->network && FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC)) + continue; + + if (link_is_static_address_configured(link, address)) { + k = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL); + if (k < 0) { + log_link_error_errno(link, k, "Failed to add address: %m"); + if (r >= 0) + r = k; + } + } else { + k = address_remove(address, link, NULL); + if (k < 0 && r >= 0) + r = k; + } + } + + 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 b8a397d6cbe..66334239372 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_foreign_addresses(Link *link); void address_hash_func(const Address *a, struct siphash *state); int address_compare_func(const Address *a1, const Address *a2); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 929fbddd9cb..4ea97b2acb3 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -163,7 +163,7 @@ bool link_ipv4ll_enabled(Link *link, AddressFamily mask) { return link->network->link_local & mask; } -static bool link_ipv6ll_enabled(Link *link) { +bool link_ipv6ll_enabled(Link *link) { assert(link); if (!socket_ipv6_is_supported()) @@ -2320,51 +2320,6 @@ static int link_set_ipv4_accept_local(Link *link) { return 0; } -static bool link_is_static_address_configured(Link *link, Address *address) { - Address *net_address; - - assert(link); - assert(address); - - if (!link->network) - return false; - - LIST_FOREACH(addresses, net_address, link->network->static_addresses) - if (address_equal(net_address, address)) - return true; - else if (address->family == AF_INET6 && net_address->family == AF_INET6 && - in_addr_equal(AF_INET6, &address->in_addr, &net_address->in_addr_peer) > 0) - return true; - - return false; -} - -static bool link_address_is_dynamic(Link *link, Address *address) { - Route *route; - - assert(link); - assert(address); - - if (address->cinfo.ifa_prefered != CACHE_INFO_INFINITY_LIFE_TIME) - return true; - - /* Even when the address is leased from a DHCP server, networkd assign the address - * without lifetime when KeepConfiguration=dhcp. So, let's check that we have - * corresponding routes with RTPROT_DHCP. */ - SET_FOREACH(route, link->routes_foreign) { - if (route->protocol != RTPROT_DHCP) - continue; - - if (address->family != route->family) - continue; - - if (in_addr_equal(address->family, &address->in_addr, &route->prefsrc)) - return true; - } - - return false; -} - static int link_enumerate_ipv6_tentative_addresses(Link *link) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; sd_netlink_message *addr; @@ -2408,7 +2363,6 @@ static int link_enumerate_ipv6_tentative_addresses(Link *link) { } static int link_drop_foreign_config(Link *link) { - Address *address; int r; /* The kernel doesn't notify us about tentative addresses; @@ -2419,27 +2373,9 @@ static int link_drop_foreign_config(Link *link) { return r; } - SET_FOREACH(address, link->addresses_foreign) { - /* 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; - - if (link_address_is_dynamic(link, address)) { - if (link->network && FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) - continue; - } else if (link->network && FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC)) - continue; - - if (link_is_static_address_configured(link, address)) { - r = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL); - if (r < 0) - return log_link_error_errno(link, r, "Failed to add address: %m"); - } else { - r = address_remove(address, link, NULL); - if (r < 0) - return r; - } - } + r = link_drop_foreign_addresses(link); + if (r < 0) + return r; r = link_drop_foreign_neighbors(link); if (r < 0) diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index aadbddc910c..670ae9783d2 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -226,6 +226,7 @@ int link_save_and_clean(Link *link); int link_carrier_reset(Link *link); bool link_has_carrier(Link *link); +bool link_ipv6ll_enabled(Link *link); int link_ipv6ll_gained(Link *link, const struct in6_addr *address); int link_set_mtu(Link *link, uint32_t mtu);