From 5582b36c384fc522c23ef1ac032001882d033aff Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 1 Mar 2024 12:10:49 +0900 Subject: [PATCH] network/dhcp-server: save leases in state directory 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 | 8 +++- src/network/networkd-dhcp-server.c | 63 +++++++++++++++++++++++++- src/network/networkd-dhcp-server.h | 3 ++ src/network/networkd-manager-varlink.c | 3 ++ 4 files changed, 74 insertions(+), 3 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 9be90e17c5e..472add2f984 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -428,7 +428,13 @@ 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 + networkctl1 + for more details. + + diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c index 81ef6d80f75..57019400e6a 100644 --- a/src/network/networkd-dhcp-server.c +++ b/src/network/networkd-dhcp-server.c @@ -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; } diff --git a/src/network/networkd-dhcp-server.h b/src/network/networkd-dhcp-server.h index 960232ade6b..b845a6d1c77 100644 --- a/src/network/networkd-dhcp-server.h +++ b/src/network/networkd-dhcp-server.h @@ -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); diff --git a/src/network/networkd-manager-varlink.c b/src/network/networkd-manager-varlink.c index a85751491e5..f3b265fed50 100644 --- a/src/network/networkd-manager-varlink.c +++ b/src/network/networkd-manager-varlink.c @@ -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); } -- 2.47.3