diff --git a/man/networkd.conf.xml b/man/networkd.conf.xml
index f7b3b4711c..3b592e9a67 100644
--- a/man/networkd.conf.xml
+++ b/man/networkd.conf.xml
@@ -283,6 +283,27 @@ DUIDRawData=00:00:ab:11:f9:2a:c2:77:29:f9:5c:00
+
+ [DHCPServer] Section Options
+
+ This section configures the default setting of the DHCP server. The following options are available
+ in the [DHCPServer] section:
+
+
+
+ PersistLeases=
+
+ Specifies the default value for per-network PersistLeases=.
+ Takes a boolean. See for details in
+ systemd.network5.
+ Defaults to yes.
+
+
+
+
+
+
+
See Also
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index e143aebb1b..4f0510030a 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -428,9 +428,12 @@
Defaults to no. Further settings for the DHCP server may be set in the
[DHCPServer] section described below.
- Even if this is enabled, the DHCP server will not be started automatically. It will be
- started after systemd-networkd-persistent-storage.service is started, which
- calls networkctl persistent-storage yes. See
+ Even if this is enabled, the DHCP server will not be started automatically and wait for the
+ persistent storage being ready to load/save leases in the storage, unless
+ RelayTarget= or PersistLeases=no are specified in the
+ [DHCPServer] section. It will be started after
+ systemd-networkd-persistent-storage.service is started, which calls
+ networkctl persistent-storage yes. See
networkctl1
for more details.
@@ -3903,6 +3906,22 @@ ServerAddress=192.168.0.1/24
+
+ PersistLeases=
+
+ Takes a boolean. When true, the DHCP server will load and save leases in the persistent
+ storage. When false, the DHCP server will neither load nor save leases in the persistent storage.
+ Hence, bound leases will be lost when the interface is reconfigured e.g. by
+ networkctl reconfigure, or systemd-networkd.service
+ is restarted. That may cause address conflict on the network. So, please take an extra care when
+ disable this setting. When unspecified, the value specified in the same setting in
+ networkd.conf5,
+ which defaults to yes, will be used.
+
+
+
+
+
diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c
index 292022f322..44b8aaa977 100644
--- a/src/network/networkd-dhcp-server.c
+++ b/src/network/networkd-dhcp-server.c
@@ -147,6 +147,20 @@ int network_adjust_dhcp_server(Network *network, Set **addresses) {
return 0;
}
+static bool dhcp_server_persist_leases(Link *link) {
+ assert(link);
+ assert(link->manager);
+ assert(link->network);
+
+ if (in4_addr_is_set(&link->network->dhcp_server_relay_target))
+ return false; /* On relay mode. Nothing saved in the persistent storage. */
+
+ if (link->network->dhcp_server_persist_leases >= 0)
+ return link->network->dhcp_server_persist_leases;
+
+ return link->manager->dhcp_server_persist_leases;
+}
+
int address_acquire_from_dhcp_server_leases_file(Link *link, const Address *address, union in_addr_union *ret) {
struct in_addr a;
uint8_t prefixlen;
@@ -168,6 +182,9 @@ int address_acquire_from_dhcp_server_leases_file(Link *link, const Address *addr
if (!link_dhcp4_server_enabled(link))
return -ENOENT;
+ if (!dhcp_server_persist_leases(link))
+ return -ENOENT;
+
if (link->manager->persistent_storage_fd < 0)
return -EBUSY; /* The persistent storage is not ready, try later again. */
@@ -208,7 +225,7 @@ int link_start_dhcp4_server(Link *link) {
/* TODO: Maybe, also check the system time is synced. If the system does not have RTC battery, then
* the realtime clock in not usable in the early boot stage, and all saved leases may be wrongly
* handled as expired and dropped. */
- if (!sd_dhcp_server_is_in_relay_mode(link->dhcp_server)) {
+ if (dhcp_server_persist_leases(link)) {
if (link->manager->persistent_storage_fd < 0)
return 0; /* persistent storage is not ready. */
@@ -239,7 +256,7 @@ void manager_toggle_dhcp4_server_state(Manager *manager, bool start) {
HASHMAP_FOREACH(link, manager->links_by_index) {
if (!link->dhcp_server)
continue;
- if (sd_dhcp_server_is_in_relay_mode(link->dhcp_server))
+ if (!dhcp_server_persist_leases(link))
continue;
/* Even if 'start' is true, first we need to stop the server. Otherwise, we cannot (re)set
diff --git a/src/network/networkd-gperf.gperf b/src/network/networkd-gperf.gperf
index bff64633e0..f443fa3ece 100644
--- a/src/network/networkd-gperf.gperf
+++ b/src/network/networkd-gperf.gperf
@@ -34,6 +34,7 @@ DHCPv4.DUIDType, config_parse_duid_type,
DHCPv4.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Manager, dhcp_duid)
DHCPv6.DUIDType, config_parse_duid_type, 0, offsetof(Manager, dhcp6_duid)
DHCPv6.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Manager, dhcp6_duid)
+DHCPServer.PersistLeases, config_parse_bool, 0, offsetof(Manager, dhcp_server_persist_leases)
/* Deprecated */
DHCP.DUIDType, config_parse_manager_duid_type, 0, 0
DHCP.DUIDRawData, config_parse_manager_duid_rawdata, 0, 0
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 15f5e8a6cc..77dfc65a8a 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -602,6 +602,7 @@ int manager_new(Manager **ret, bool test_mode) {
.dhcp_duid.type = DUID_TYPE_EN,
.dhcp6_duid.type = DUID_TYPE_EN,
.duid_product_uuid.type = DUID_TYPE_UUID,
+ .dhcp_server_persist_leases = true,
.ip_forwarding = { -1, -1, },
};
diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h
index fd9ab341c8..28a2803845 100644
--- a/src/network/networkd-manager.h
+++ b/src/network/networkd-manager.h
@@ -42,6 +42,7 @@ struct Manager {
bool manage_foreign_routes;
bool manage_foreign_rules;
bool manage_foreign_nexthops;
+ bool dhcp_server_persist_leases;
Set *dirty_links;
Set *new_wlan_ifindices;
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index dffc40308c..34c81a0747 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -350,6 +350,7 @@ DHCPServer.BootServerAddress, config_parse_in_addr_non_null,
DHCPServer.BootServerName, config_parse_dns_name, 0, offsetof(Network, dhcp_server_boot_server_name)
DHCPServer.BootFilename, config_parse_string, CONFIG_PARSE_STRING_SAFE_AND_ASCII, offsetof(Network, dhcp_server_boot_filename)
DHCPServer.RapidCommit, config_parse_bool, 0, offsetof(Network, dhcp_server_rapid_commit)
+SHCPServer.PersistLeases, config_parse_tristate, 0, offsetof(Network, dhcp_server_persist_leases)
DHCPServerStaticLease.Address, config_parse_dhcp_static_lease_address, 0, 0
DHCPServerStaticLease.MACAddress, config_parse_dhcp_static_lease_hwaddr, 0, 0
Bridge.Cost, config_parse_uint32, 0, offsetof(Network, cost)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 3d418006d6..eaa3676ede 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -426,6 +426,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
.dhcp_server_emit_router = true,
.dhcp_server_emit_timezone = true,
.dhcp_server_rapid_commit = true,
+ .dhcp_server_persist_leases = -1,
.router_lifetime_usec = RADV_DEFAULT_ROUTER_LIFETIME_USEC,
.router_dns_lifetime_usec = RADV_DEFAULT_VALID_LIFETIME_USEC,
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 467789bd68..723091fc8a 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -230,6 +230,7 @@ struct Network {
char *dhcp_server_boot_filename;
usec_t dhcp_server_ipv6_only_preferred_usec;
bool dhcp_server_rapid_commit;
+ int dhcp_server_persist_leases;
/* link-local addressing support */
AddressFamily link_local;
diff --git a/src/network/networkd.conf b/src/network/networkd.conf
index 2994b8b70c..bad7e8855a 100644
--- a/src/network/networkd.conf
+++ b/src/network/networkd.conf
@@ -32,3 +32,6 @@
[DHCPv6]
#DUIDType=vendor
#DUIDRawData=
+
+[DHCPServer]
+#PersistLeases=yes