]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/dhcp-server: save leases in state directory
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 1 Mar 2024 03:10:49 +0000 (12:10 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 11 Mar 2024 16:57:17 +0000 (01:57 +0900)
Then, we can read the lease file on restart, and the DHCP server will be
able to manage previously assigned addresses.

To save leases in the state directory /var/lib/systemd/network/, this
adds systemd-networkd-dhcp-server.service, and by default
systemd-networkd does not start the DHCP server without the heler
service started.

Closes #29991.

man/systemd.network.xml
src/network/networkd-dhcp-server.c
src/network/networkd-dhcp-server.h
src/network/networkd-manager-varlink.c

index 9be90e17c5e42e1d59e6d263eab097f77e00d2fa..472add2f98407329b755969fffd59ffec5b8d87c 100644 (file)
           Defaults to <literal>no</literal>. Further settings for the DHCP server may be set in the
           [DHCPServer] section described below.</para>
 
-        <xi:include href="version-info.xml" xpointer="v215"/>
+          <para>Even if this is enabled, the DHCP server will not be started automatically. It will be
+          started after <filename>systemd-networkd-persistent-storage.service</filename> is started, which
+          calls <command>networkctl persistent-storage yes</command>. See
+          <citerefentry><refentrytitle>networkctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+          for more details.</para>
+
+          <xi:include href="version-info.xml" xpointer="v215"/>
         </listitem>
       </varlistentry>
 
index 81ef6d80f759156c4b12bf3f4cdc19c83a4490df..57019400e6a28effc4c0021297194be236c3bc07 100644 (file)
@@ -20,6 +20,7 @@
 #include "networkd-queue.h"
 #include "networkd-route-util.h"
 #include "parse-util.h"
+#include "path-util.h"
 #include "socket-netlink.h"
 #include "string-table.h"
 #include "string-util.h"
@@ -143,6 +144,55 @@ int network_adjust_dhcp_server(Network *network, Set **addresses) {
         return 0;
 }
 
+static int link_start_dhcp4_server(Link *link) {
+        int r;
+
+        assert(link);
+        assert(link->manager);
+
+        if (!link->dhcp_server)
+                return 0; /* Not configured yet. */
+
+        if (!link_has_carrier(link))
+                return 0;
+
+        /* 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) &&
+            !link->manager->persistent_storage_is_ready)
+                return 0;
+
+        r = sd_dhcp_server_start(link->dhcp_server);
+        if (r < 0)
+                return r;
+
+        log_link_debug(link, "Offering DHCPv4 leases");
+        return 0;
+}
+
+void manager_toggle_dhcp4_server_state(Manager *manager, bool start) {
+        Link *link;
+        int r;
+
+        assert(manager);
+
+        HASHMAP_FOREACH(link, manager->links_by_index) {
+                if (!link->dhcp_server)
+                        continue;
+                if (sd_dhcp_server_is_in_relay_mode(link->dhcp_server))
+                        continue;
+
+                if (start)
+                        r = link_start_dhcp4_server(link);
+                else
+                        r = sd_dhcp_server_stop(link->dhcp_server);
+                if (r < 0)
+                        log_link_debug_errno(link, r, "Failed to %s DHCP server, ignoring: %m",
+                                             start ? "start" : "stop");
+        }
+}
+
 static int dhcp_server_find_uplink(Link *link, Link **ret) {
         assert(link);
 
@@ -522,11 +572,20 @@ static int dhcp4_server_configure(Link *link) {
                         return log_link_error_errno(link, r, "Failed to set DHCPv4 static lease for DHCP server: %m");
         }
 
-        r = sd_dhcp_server_start(link->dhcp_server);
+        if (!sd_dhcp_server_is_in_relay_mode(link->dhcp_server)) {
+                _cleanup_free_ char *lease_file = path_join("/var/lib/systemd/network/dhcp-server-lease/", link->ifname);
+                if (!lease_file)
+                        return log_oom();
+
+                r = sd_dhcp_server_set_lease_file(link->dhcp_server, lease_file);
+                if (r < 0)
+                        log_link_warning_errno(link, r, "Failed to load DHCPv4 server leases, ignoring: %m");
+        }
+
+        r = link_start_dhcp4_server(link);
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not start DHCPv4 server instance: %m");
 
-        log_link_debug(link, "Offering DHCPv4 leases");
         return 0;
 }
 
index 960232ade6b9ed68ed0d2be0df766cbc10632a97..b845a6d1c777f41467dc909eb512e161277ee71c 100644 (file)
@@ -5,12 +5,15 @@
 #include "set.h"
 
 typedef struct Link Link;
+typedef struct Manager Manager;
 typedef struct Network Network;
 
 int network_adjust_dhcp_server(Network *network, Set **addresses);
 
 int link_request_dhcp_server(Link *link);
 
+void manager_toggle_dhcp4_server_state(Manager *manager, bool start);
+
 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);
index a85751491e584f21d0f4e516ed62a97ee2490bb2..f3b265fed50eb8afee8d4a11e81977a8880668eb 100644 (file)
@@ -5,6 +5,7 @@
 #include "bus-polkit.h"
 #include "fs-util.h"
 #include "lldp-rx-internal.h"
+#include "networkd-dhcp-server.h"
 #include "networkd-manager-varlink.h"
 #include "stat-util.h"
 #include "varlink.h"
@@ -211,6 +212,8 @@ static int vl_method_set_persistent_storage(Varlink *vlink, JsonVariant *paramet
                         log_debug_errno(errno, "Failed to remove /run/systemd/netif/persistent-storage-ready, ignoring: %m");
         }
 
+        manager_toggle_dhcp4_server_state(manager, ready);
+
         return varlink_reply(vlink, NULL);
 }