diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index d9c3dae85c..70fe1e5038 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -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; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 3efbe6f48e..ac6179a924 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -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. */ diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c index a1869a8559..292022f322 100644 --- a/src/network/networkd-dhcp-server.c +++ b/src/network/networkd-dhcp-server.c @@ -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; diff --git a/src/network/networkd-dhcp-server.h b/src/network/networkd-dhcp-server.h index dbc7d95cad..e839fac00b 100644 --- a/src/network/networkd-dhcp-server.h +++ b/src/network/networkd-dhcp-server.h @@ -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);