From: Toke Høiland-Jørgensen Date: Thu, 28 Oct 2021 20:36:51 +0000 (+0200) Subject: sd-dhcp-server: clear out expired leases when processing requests X-Git-Tag: v250-rc1~380^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d635a7f9e4c58c5578f4fe2989bb799325067232;p=thirdparty%2Fsystemd.git sd-dhcp-server: clear out expired leases when processing requests The DHCP server configuration supports setting a maximum lease time, but old leases are never actually cleared out if the client doesn't send a RELEASE. This causes the pool to run out of addresses on networks where clients just disappear, which is a fairly common occurrence on wireless networks. Fix this by cleaning up expired leases before processing client requests, so addresses can be reused for new clients. --- diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 45ac70b4616..39ac5e86fa2 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -854,6 +854,27 @@ static int prepare_new_lease( return 0; } +static int dhcp_server_cleanup_expired_leases(sd_dhcp_server *server) { + DHCPLease *lease; + usec_t time_now; + int r; + + assert(server); + + r = sd_event_now(server->event, clock_boottime_or_monotonic(), &time_now); + if (r < 0) + return r; + + HASHMAP_FOREACH(lease, server->bound_leases_by_client_id) { + if (lease->expiration < time_now) { + log_dhcp_server(server, "CLEAN (0x%x)", be32toh(lease->address)); + dhcp_lease_free(lease); + } + } + + return 0; +} + #define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30) int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, size_t length) { @@ -883,6 +904,10 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz /* this only fails on critical errors */ return r; + r = dhcp_server_cleanup_expired_leases(server); + if (r < 0) + return r; + existing_lease = hashmap_get(server->bound_leases_by_client_id, &req->client_id); static_lease = hashmap_get(server->static_leases_by_client_id, &req->client_id);