]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-dhcp-server: clear out expired leases when processing requests
authorToke Høiland-Jørgensen <toke@redhat.com>
Thu, 28 Oct 2021 20:36:51 +0000 (22:36 +0200)
committerToke Høiland-Jørgensen <toke@redhat.com>
Fri, 29 Oct 2021 13:29:05 +0000 (15:29 +0200)
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.

src/libsystemd-network/sd-dhcp-server.c

index 45ac70b4616322fec61a802ca246918059f4ed3a..39ac5e86fa23686b7f9e3bcece3f11852b887e33 100644 (file)
@@ -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);