X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fsystemd.git;a=blobdiff_plain;f=src%2Fnetwork%2Fnetworkd-link.c;h=0c243508a4314ef3f01c1196c13fe748a4f6f280;hp=6613992a091f5fe043a7c24d676dc568f9f1498b;hb=7ef7e5509b637e660e89ba8a938930ec01de6e54;hpb=2bb24885de191d5a9d8abbac0bca0c1da0559847 diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 6613992a091..0c243508a43 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -680,14 +680,17 @@ static void link_enter_unmanaged(Link *link) { link_dirty(link); } -int link_stop_clients(Link *link) { +int link_stop_clients(Link *link, bool may_keep_dhcp) { int r = 0, k; assert(link); assert(link->manager); assert(link->manager->event); - if (link->dhcp_client) { + dhcp4_release_old_lease(link); + + if (link->dhcp_client && (!may_keep_dhcp || !link->network || + !FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP_ON_STOP))) { k = sd_dhcp_client_stop(link->dhcp_client); if (k < 0) r = log_link_warning_errno(link, k, "Could not stop DHCPv4 client: %m"); @@ -731,7 +734,7 @@ void link_enter_failed(Link *link) { link_set_state(link, LINK_STATE_FAILED); - link_stop_clients(link); + link_stop_clients(link, false); link_dirty(link); } @@ -829,14 +832,14 @@ static int link_request_set_routing_policy_rule(Link *link) { continue; } - r = routing_policy_rule_configure(rule, link, NULL, false); + r = routing_policy_rule_configure(rule, link, NULL); if (r < 0) { log_link_warning_errno(link, r, "Could not set routing policy rules: %m"); link_enter_failed(link); return r; } - - link->routing_policy_rule_messages++; + if (r > 0) + link->routing_policy_rule_messages++; } routing_policy_rule_purge(link->manager, link); @@ -910,8 +913,8 @@ int link_request_set_routes(Link *link) { link_enter_failed(link); return r; } - - link->route_messages++; + if (r > 0) + link->route_messages++; } if (link->route_messages == 0) { @@ -1191,8 +1194,8 @@ static int link_request_set_addresses(Link *link) { link_enter_failed(link); return r; } - - link->address_messages++; + if (r > 0) + link->address_messages++; } LIST_FOREACH(labels, label, link->network->address_labels) { @@ -2485,6 +2488,33 @@ static bool link_is_static_route_configured(Link *link, Route *route) { return false; } +static bool link_address_is_dynamic(Link *link, Address *address) { + Route *route; + Iterator i; + + 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, i) { + 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_drop_foreign_config(Link *link) { Address *address; Route *route; @@ -2496,6 +2526,12 @@ static int link_drop_foreign_config(Link *link) { if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1) continue; + if (link_address_is_dynamic(link, address)) { + if (FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) + continue; + } else if (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) @@ -2512,6 +2548,14 @@ static int link_drop_foreign_config(Link *link) { if (route->protocol == RTPROT_KERNEL) continue; + if (route->protocol == RTPROT_STATIC && + FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC)) + continue; + + if (route->protocol == RTPROT_DHCP && + FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) + continue; + if (link_is_static_route_configured(link, route)) { r = route_add(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL); if (r < 0) @@ -2578,7 +2622,8 @@ static int link_configure(Link *link) { /* Drop foreign config, but ignore loopback or critical devices. * We do not want to remove loopback address or addresses used for root NFS. */ - if (!(link->flags & IFF_LOOPBACK) && !(link->network->dhcp_critical)) { + if (!(link->flags & IFF_LOOPBACK) && + link->network->keep_configuration != KEEP_CONFIGURATION_YES) { r = link_drop_foreign_config(link); if (r < 0) return r; @@ -3264,7 +3309,7 @@ static int link_carrier_lost(Link *link) { if (link->setting_mtu) return 0; - r = link_stop_clients(link); + r = link_stop_clients(link, false); if (r < 0) { link_enter_failed(link); return r;