]> 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 924cc8ce6af25b32f1eea102debb813b4551ee07..0c243508a4314ef3f01c1196c13fe748a4f6f280 100644 (file)
@@ -132,7 +132,7 @@ bool link_ipv4ll_enabled(Link *link, AddressFamilyBoolean mask) {
         if (!link->network)
                 return false;
 
-        if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "ip6gre", "ip6tnl", "sit", "vti", "vti6", "can", "vcan", "vxcan"))
+        if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "ip6gre", "ip6tnl", "sit", "vti", "vti6", "can", "vcan", "vxcan", "nlmon"))
                 return false;
 
         /* L3 or L3S mode do not support ARP. */
@@ -142,6 +142,9 @@ bool link_ipv4ll_enabled(Link *link, AddressFamilyBoolean mask) {
         if (link->network->bond)
                 return false;
 
+        if (link->network->bond)
+                return false;
+
         return link->network->link_local & mask;
 }
 
@@ -157,7 +160,7 @@ static bool link_ipv6ll_enabled(Link *link) {
         if (!link->network)
                 return false;
 
-        if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "sit", "vti", "can", "vcan", "vxcan"))
+        if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "sit", "vti", "can", "vcan", "vxcan", "nlmon"))
                 return false;
 
         if (link->network->bond)
@@ -677,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");
@@ -728,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);
 }
@@ -826,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);
@@ -907,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) {
@@ -962,7 +968,8 @@ void link_check_ready(Link *link) {
                 return;
 
         if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link)) &&
-            !(link->dhcp4_configured || link->dhcp6_configured) &&
+            !link->dhcp4_configured &&
+            !link->dhcp6_configured &&
             !(link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4) && link->ipv4ll_address && link->ipv4ll_route))
                 /* When DHCP is enabled, at least one protocol must provide an address, or
                  * an IPv4ll fallback address must be configured. */
@@ -1187,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) {
@@ -2481,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;
@@ -2492,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)
@@ -2508,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)
@@ -2574,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;
@@ -3260,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;