diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index b623a4aa75..0d3805fa8a 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -2612,6 +2612,14 @@ Token=prefixstable:2002:da8:1::
+
+ UseCaptivePortal=
+
+ When true (the default), the captive portal received in the Router Advertisement will be recorded
+ and made available to client programs and displayed in the networkctl status output per-link.
+
+
+
UseAutonomousPrefix=
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index ab0d252b94..6a7ef24651 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -284,6 +284,7 @@ IPv6AcceptRA.DHCPv6Client, config_parse_ipv6_accept_ra_start_d
IPv6AcceptRA.RouteTable, config_parse_dhcp_or_ra_route_table, AF_INET6, 0
IPv6AcceptRA.RouteMetric, config_parse_ipv6_accept_ra_route_metric, 0, 0
IPv6AcceptRA.QuickAck, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_quickack)
+IPv6AcceptRA.UseCaptivePortal, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_captive_portal)
IPv6AcceptRA.RouterAllowList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_allow_listed_router)
IPv6AcceptRA.RouterDenyList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_deny_listed_router)
IPv6AcceptRA.PrefixAllowList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_allow_listed_prefix)
diff --git a/src/network/networkd-state-file.c b/src/network/networkd-state-file.c
index 5f5cb3239d..c9366e97d8 100644
--- a/src/network/networkd-state-file.c
+++ b/src/network/networkd-state-file.c
@@ -623,11 +623,21 @@ int link_save(Link *link) {
log_link_warning(link, "DHCPv6 Captive Portal (%s) does not match DHCPv4 (%s). Ignoring DHCPv6 portal.",
dhcp6_captive_portal, dhcp_captive_portal);
+ if (link->network->ipv6_accept_ra_use_captive_portal && link->ndisc_captive_portal) {
+ if (dhcp_captive_portal && !streq(dhcp_captive_portal, link->ndisc_captive_portal))
+ log_link_warning(link, "IPv6RA captive portal (%s) does not match DHCPv4 (%s). Ignorning IPv6RA portal.",
+ link->ndisc_captive_portal, dhcp_captive_portal);
+ if (dhcp6_captive_portal && !streq(dhcp6_captive_portal, link->ndisc_captive_portal))
+ log_link_warning(link, "IPv6RA captive portal (%s) does not match DHCPv6 (%s). Ignorning IPv6RA portal.",
+ link->ndisc_captive_portal, dhcp6_captive_portal);
+ }
if (dhcp_captive_portal)
fprintf(f, "CAPTIVE_PORTAL=%s\n", dhcp_captive_portal);
else if (dhcp6_captive_portal)
fprintf(f, "CAPTIVE_PORTAL=%s\n", dhcp6_captive_portal);
+ else if (link->ndisc_captive_portal)
+ fprintf(f, "CAPTIVE_PORTAL=%s\n", link->ndisc_captive_portal);
/************************************************************/