]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/network/networkd-link.c
network: ignore requested ipv6 routing policy rule when ipv6 is disabled by sysctl
[thirdparty/systemd.git] / src / network / networkd-link.c
index fb315dd39b942c1a733b895bc6f7485c855701ba..0c243508a4314ef3f01c1196c13fe748a4f6f280 100644 (file)
@@ -687,6 +687,8 @@ int link_stop_clients(Link *link, bool may_keep_dhcp) {
         assert(link->manager);
         assert(link->manager->event);
 
+        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);
@@ -830,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);
@@ -911,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) {
@@ -1192,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) {
@@ -2486,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;
@@ -2497,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)
@@ -2513,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)
@@ -2580,7 +2623,7 @@ 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->keep_configuration & (KEEP_CONFIGURATION_DHCP_ON_START | KEEP_CONFIGURATION_STATIC))) {
+            link->network->keep_configuration != KEEP_CONFIGURATION_YES) {
                 r = link_drop_foreign_config(link);
                 if (r < 0)
                         return r;