]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #31730 from yuwata/network-dhcp-server-lease-file-follow-ups
authorLuca Boccassi <bluca@debian.org>
Mon, 25 Mar 2024 14:32:05 +0000 (14:32 +0000)
committerGitHub <noreply@github.com>
Mon, 25 Mar 2024 14:32:05 +0000 (14:32 +0000)
network: several follow-ups for DHCP server lease file

src/network/networkd-address.c
src/network/networkd-address.h
src/network/networkd-dhcp-server.c
src/network/networkd-dhcp-server.h
test/test-network/systemd-networkd-tests.py

index 38cdadcf61bb1a93b06160f8c4d1e0fbcfaf0c52..542298c8c3019a7460f45faca518fe8a95f25c05 100644 (file)
@@ -1495,6 +1495,10 @@ static int address_acquire(Link *link, const Address *address, union in_addr_uni
         assert(address);
         assert(ret);
 
+        r = address_acquire_from_dhcp_server_leases_file(link, address, ret);
+        if (r != -ENOENT)
+                return r;
+
         r = address_pool_acquire(link->manager, address->family, address->prefixlen, &a);
         if (r < 0)
                 return r;
index 3efbe6f48e6d56e13661127287af8ba37f47fd92..ac6179a9248f4770ae9d3e270497937842afb7dc 100644 (file)
@@ -57,6 +57,7 @@ struct Address {
         bool scope_set:1;
         bool ip_masquerade_done:1;
         bool requested_as_null:1;
+        bool used_by_dhcp_server:1;
 
         /* duplicate_address_detection is only used by static or IPv4 dynamic addresses.
          * To control DAD for IPv6 dynamic addresses, set IFA_F_NODAD to flags. */
index a1869a855998b2c5666c4626a7eba1f73eb3e0df..292022f32283978aff6b11cc1376edf9ad537c44 100644 (file)
@@ -7,6 +7,7 @@
 #include "sd-dhcp-server.h"
 
 #include "dhcp-protocol.h"
+#include "dhcp-server-lease-internal.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "network-common.h"
@@ -82,6 +83,7 @@ int network_adjust_dhcp_server(Network *network, Set **addresses) {
                         /* TODO: check if the prefix length is small enough for the pool. */
 
                         network->dhcp_server_address = address;
+                        address->used_by_dhcp_server = true;
                         break;
                 }
                 if (!network->dhcp_server_address) {
@@ -128,6 +130,7 @@ int network_adjust_dhcp_server(Network *network, Set **addresses) {
                 a->prefixlen = network->dhcp_server_address_prefixlen;
                 a->in_addr.in = network->dhcp_server_address_in_addr;
                 a->requested_as_null = !in4_addr_is_set(&network->dhcp_server_address_in_addr);
+                a->used_by_dhcp_server = true;
 
                 r = address_section_verify(a);
                 if (r < 0)
@@ -144,6 +147,49 @@ int network_adjust_dhcp_server(Network *network, Set **addresses) {
         return 0;
 }
 
+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;
+        int r;
+
+        assert(link);
+        assert(link->manager);
+        assert(address);
+        assert(ret);
+
+        /* If the DHCP server address is configured as a null address, reuse the server address of the
+         * previous instance. */
+        if (address->family != AF_INET)
+                return -ENOENT;
+
+        if (!address->used_by_dhcp_server)
+                return -ENOENT;
+
+        if (!link_dhcp4_server_enabled(link))
+                return -ENOENT;
+
+        if (link->manager->persistent_storage_fd < 0)
+                return -EBUSY; /* The persistent storage is not ready, try later again. */
+
+        _cleanup_free_ char *lease_file = path_join("dhcp-server-lease", link->ifname);
+        if (!lease_file)
+                return -ENOMEM;
+
+        r = dhcp_server_leases_file_get_server_address(
+                        link->manager->persistent_storage_fd,
+                        lease_file,
+                        &a,
+                        &prefixlen);
+        if (r < 0)
+                return r;
+
+        if (prefixlen != address->prefixlen)
+                return -ENOENT;
+
+        ret->in = a;
+        return 0;
+}
+
 int link_start_dhcp4_server(Link *link) {
         int r;
 
index dbc7d95cadba470a3f94f01f8ba99f19c5e607a5..e839fac00b44675b4251779bc8799213c7c78bd6 100644 (file)
@@ -2,14 +2,16 @@
 #pragma once
 
 #include "conf-parser.h"
+#include "in-addr-util.h"
 #include "set.h"
 
+typedef struct Address Address;
 typedef struct Link Link;
 typedef struct Manager Manager;
 typedef struct Network Network;
 
 int network_adjust_dhcp_server(Network *network, Set **addresses);
-
+int address_acquire_from_dhcp_server_leases_file(Link *link, const Address *address, union in_addr_union *ret);
 int link_request_dhcp_server(Link *link);
 
 int link_start_dhcp4_server(Link *link);
index 1bf79d974c1743c505cdc989852a45ae80c7aaf2..866c548fbe404a4c25511f6e7bb662647d010490 100755 (executable)
@@ -5771,6 +5771,28 @@ class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
         output = networkctl_status('veth-peer')
         self.assertIn(f'Offered DHCP leases: {client_address}', output)
 
+        # Check if the same addresses are used even if the service is restarted.
+        restart_networkd()
+        self.wait_online('veth99:routable', 'veth-peer:routable')
+
+        output = check_output('ip -4 address show dev veth-peer')
+        print(output)
+        self.assertIn(f'{server_address}', output)
+
+        output = check_output('ip -4 address show dev veth99')
+        print(output)
+        self.assertIn(f'{client_address}', output)
+
+        output = networkctl_status('veth99')
+        print(output)
+        self.assertRegex(output, rf'Address: {client_address} \(DHCP4 via {server_address}\)')
+        self.assertIn(f'Gateway: {server_address}', output)
+        self.assertIn(f'DNS: {server_address}', output)
+        self.assertIn(f'NTP: {server_address}', output)
+
+        output = networkctl_status('veth-peer')
+        self.assertIn(f'Offered DHCP leases: {client_address}', output)
+
     def test_dhcp_server_with_uplink(self):
         copy_network_unit('25-veth.netdev', '25-dhcp-client.network', '25-dhcp-server-downstream.network',
                           '12-dummy.netdev', '25-dhcp-server-uplink.network')