]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: honour static IPv6LL addresses in network_adjust_*()
authorr-vdp <ramses@well-founded.dev>
Mon, 13 Apr 2026 17:03:27 +0000 (19:03 +0200)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 14 May 2026 18:30:01 +0000 (03:30 +0900)
link_radv_enabled() and link_ndisc_enabled() use
link_ipv6ll_enabled_harder(), which considers a static fe80:: address
in [Address] sufficient to run radv/ndisc even when LinkLocalAddressing=
(or IPv6LinkLocalAddressGenerationMode=none, which network_verify()
folds into the same flag) disables the kernel-generated link-local.

network_adjust_radv()/ndisc()/dhcp() however only check the raw
link_local flag and zero router_prefix_delegation / ndisc / dhcp&IPV6
at parse time, so the runtime gate never gets a chance to fire.

Factor the static-LL lookup out of link_ipv6ll_enabled_harder() into a
Network-level helper and use it in the three network_adjust_*()
functions, bringing parse-time and runtime behaviour in line.

src/network/networkd-dhcp-common.c
src/network/networkd-ipv6ll.c
src/network/networkd-ipv6ll.h
src/network/networkd-ndisc.c
src/network/networkd-radv.c

index 5d83835580971c60c4a4de795db4274c8acfce35..d2e51e7e91bc32f7bcf990fbb324ace4a138d3f4 100644 (file)
@@ -19,6 +19,7 @@
 #include "iovec-util.h"
 #include "networkd-dhcp-common.h"
 #include "networkd-dhcp-prefix-delegation.h"
+#include "networkd-ipv6ll.h"
 #include "networkd-link.h"
 #include "networkd-manager.h"
 #include "networkd-network.h"
@@ -100,6 +101,7 @@ void network_adjust_dhcp(Network *network) {
         }
 
         if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6) &&
+            !network_has_static_ipv6ll_address(network) &&
             FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV6)) {
                 log_warning("%s: DHCPv6 client is enabled but IPv6 link-local addressing is disabled. "
                             "Disabling DHCPv6 client.", network->filename);
index 546229a2e29298a5f9bc54e3c92bad6a153fb5bc..654fbdb6a8ca4b981b3877fb38093bf438aadd80 100644 (file)
@@ -42,6 +42,22 @@ bool link_ipv6ll_enabled(Link *link) {
         return link->network->link_local & ADDRESS_FAMILY_IPV6;
 }
 
+bool network_has_static_ipv6ll_address(const Network *network) {
+        assert(network);
+
+        Address *a;
+        ORDERED_HASHMAP_FOREACH(a, network->addresses_by_section) {
+                if (a->family != AF_INET6)
+                        continue;
+                if (in6_addr_is_set(&a->in_addr_peer.in6))
+                        continue;
+                if (in6_addr_is_link_local(&a->in_addr.in6))
+                        return true;
+        }
+
+        return false;
+}
+
 bool link_ipv6ll_enabled_harder(Link *link) {
         assert(link);
 
@@ -54,17 +70,7 @@ bool link_ipv6ll_enabled_harder(Link *link) {
         if (!link->network)
                 return false;
 
-        Address *a;
-        ORDERED_HASHMAP_FOREACH(a, link->network->addresses_by_section) {
-                if (a->family != AF_INET6)
-                        continue;
-                if (in6_addr_is_set(&a->in_addr_peer.in6))
-                        continue;
-                if (in6_addr_is_link_local(&a->in_addr.in6))
-                        return true;
-        }
-
-        return false;
+        return network_has_static_ipv6ll_address(link->network);
 }
 
 IPv6LinkLocalAddressGenMode link_get_ipv6ll_addrgen_mode(Link *link) {
index 62ce9d957ebd080c97a699a4a12c3c4aeec74d02..73fa51fbef1ce85c59dc30e48ce156b2be04f967 100644 (file)
@@ -16,6 +16,7 @@ typedef enum IPv6LinkLocalAddressGenMode {
 
 bool link_ipv6ll_enabled(Link *link);
 bool link_ipv6ll_enabled_harder(Link *link);
+bool network_has_static_ipv6ll_address(const Network *network);
 
 IPv6LinkLocalAddressGenMode link_get_ipv6ll_addrgen_mode(Link *link);
 int ipv6ll_addrgen_mode_fill_message(sd_netlink_message *message, IPv6LinkLocalAddressGenMode mode);
index e6b03c0826cad1b61b83882ac2b3cf0c6bf4fd35..4e15da958881aa16aacceda7926dfb3555787a6a 100644 (file)
@@ -17,6 +17,7 @@
 #include "networkd-address.h"
 #include "networkd-address-generation.h"
 #include "networkd-dhcp6.h"
+#include "networkd-ipv6ll.h"
 #include "networkd-link.h"
 #include "networkd-manager.h"
 #include "networkd-ndisc.h"
@@ -91,7 +92,8 @@ bool link_ndisc_enabled(Link *link) {
 void network_adjust_ndisc(Network *network) {
         assert(network);
 
-        if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) {
+        if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6) &&
+            !network_has_static_ipv6ll_address(network)) {
                 if (network->ndisc > 0)
                         log_warning("%s: IPv6AcceptRA= is enabled but IPv6 link-local addressing is disabled or not supported. "
                                     "Disabling IPv6AcceptRA=.", network->filename);
index a71e01dfbf474cee9625b1e0369299f541e3be0d..02322d4dabad5d1d1102ca7992f9cf6cda0e0a52 100644 (file)
@@ -14,6 +14,7 @@
 #include "networkd-address.h"
 #include "networkd-address-generation.h"
 #include "networkd-dhcp-prefix-delegation.h"
+#include "networkd-ipv6ll.h"
 #include "networkd-link.h"
 #include "networkd-manager.h"
 #include "networkd-network.h"
@@ -815,7 +816,8 @@ void network_adjust_radv(Network *network) {
                 /* For backward compatibility. */
                 network->dhcp_pd = FLAGS_SET(network->router_prefix_delegation, RADV_PREFIX_DELEGATION_DHCP6);
 
-        if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) {
+        if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6) &&
+            !network_has_static_ipv6ll_address(network)) {
                 if (network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE)
                         log_warning("%s: IPv6PrefixDelegation= is enabled but IPv6 link-local addressing is disabled. "
                                     "Disabling IPv6PrefixDelegation=.", network->filename);