diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 33c559cddb..804d51be11 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -3604,6 +3604,20 @@ ServerAddress=192.168.0.1/24
+
+ IPv6OnlyPreferredSec=
+
+
+ Takes a timespan. Controls the
+ RFC 8925 IPv6-Only Preferred option.
+ Specifies the DHCPv4 option to indicate that a host supports an IPv6-only mode and is willing to
+ forgo obtaining an IPv4 address if the network provides IPv6 connectivity. Defaults to unset, and
+ not send the option. The minimum allowed value is 300 seconds.
+
+
+
+
+
SendOption=
diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c
index dacbb7e129..569398571c 100644
--- a/src/network/networkd-dhcp-server.c
+++ b/src/network/networkd-dhcp-server.c
@@ -6,8 +6,10 @@
#include "sd-dhcp-server.h"
+#include "dhcp-protocol.h"
#include "fd-util.h"
#include "fileio.h"
+#include "network-common.h"
#include "networkd-address.h"
#include "networkd-dhcp-server-bus.h"
#include "networkd-dhcp-server-static-lease.h"
@@ -402,6 +404,10 @@ static int dhcp4_server_configure(Link *link) {
return log_link_error_errno(link, r, "Failed to set default lease time for DHCPv4 server instance: %m");
}
+ r = sd_dhcp_server_set_ipv6_only_preferred_usec(link->dhcp_server, link->network->dhcp_server_ipv6_only_preferred_usec);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Failed to set IPv6 only preferred time for DHCPv4 server instance: %m");
+
r = sd_dhcp_server_set_boot_server_address(link->dhcp_server, &link->network->dhcp_server_boot_server_address);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to set boot server address for DHCPv4 server instance: %m");
@@ -726,3 +732,45 @@ int config_parse_dhcp_server_address(
network->dhcp_server_address_prefixlen = prefixlen;
return 0;
}
+
+int config_parse_dhcp_server_ipv6_only_preferred(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ usec_t t, *usec = ASSERT_PTR(data);
+ int r;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+
+ if (isempty(rvalue)) {
+ *usec = 0;
+ return 0;
+ }
+
+ r = parse_sec(rvalue, &t);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to parse [%s] %s=, ignoring assignment: %s", section, lvalue, rvalue);
+ return 0;
+ }
+
+ if (t < MIN_V6ONLY_WAIT_USEC && !network_test_mode_enabled()) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Invalid [%s] %s=, ignoring assignment: %s", section, lvalue, rvalue);
+ return 0;
+ }
+
+ *usec = t;
+ return 0;
+}
diff --git a/src/network/networkd-dhcp-server.h b/src/network/networkd-dhcp-server.h
index 4fd4429deb..960232ade6 100644
--- a/src/network/networkd-dhcp-server.h
+++ b/src/network/networkd-dhcp-server.h
@@ -14,3 +14,4 @@ int link_request_dhcp_server(Link *link);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_relay_agent_suboption);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_emit);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_address);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ipv6_only_preferred);
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 42e989e116..6b3609989f 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -313,6 +313,7 @@ DHCPServer.RelayAgentCircuitId, config_parse_dhcp_server_relay_agen
DHCPServer.RelayAgentRemoteId, config_parse_dhcp_server_relay_agent_suboption, 0, offsetof(Network, dhcp_server_relay_agent_remote_id)
DHCPServer.MaxLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_max_lease_time_usec)
DHCPServer.DefaultLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_default_lease_time_usec)
+DHCPServer.IPv6OnlyPreferredSec, config_parse_dhcp_server_ipv6_only_preferred, 0, offsetof(Network, dhcp_server_ipv6_only_preferred_usec)
DHCPServer.EmitDNS, config_parse_bool, 0, offsetof(Network, dhcp_server_emit[SD_DHCP_LEASE_DNS].emit)
DHCPServer.DNS, config_parse_dhcp_server_emit, 0, offsetof(Network, dhcp_server_emit[SD_DHCP_LEASE_DNS])
DHCPServer.EmitNTP, config_parse_bool, 0, offsetof(Network, dhcp_server_emit[SD_DHCP_LEASE_NTP].emit)
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index cc2cf36f5c..0fc0851797 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -221,6 +221,7 @@ struct Network {
struct in_addr dhcp_server_boot_server_address;
char *dhcp_server_boot_server_name;
char *dhcp_server_boot_filename;
+ usec_t dhcp_server_ipv6_only_preferred_usec;
/* link-local addressing support */
AddressFamily link_local;