chiark / gitweb /
sd-dhcp-server: fix a leak
[elogind.git] / src / libsystemd-network / sd-dhcp-server.c
index 4a0683387534371282656c47c3782a5ee76050fa..d9495024ab9476c5990238b97abfee1b50337b9d 100644 (file)
@@ -544,7 +544,7 @@ static int get_pool_offset(sd_dhcp_server *server, be32_t requested_ip) {
 
         if (be32toh(requested_ip) < be32toh(server->pool_start) ||
             be32toh(requested_ip) >= be32toh(server->pool_start) +
-                                                  + server->pool_size)
+                                             + server->pool_size)
                 return -EINVAL;
 
         return be32toh(requested_ip) - be32toh(server->pool_start);
@@ -623,6 +623,15 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
 
                 break;
         }
+        case DHCP_DECLINE:
+                log_dhcp_server(server, "DECLINE (0x%x)",
+                                be32toh(req->message->xid));
+
+                /* TODO: make sure we don't offer this address again */
+
+                return 1;
+
+                break;
         case DHCP_REQUEST:
         {
                 be32_t address;
@@ -688,8 +697,10 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
                                 lease->address = req->requested_ip;
                                 lease->client_id.data = memdup(req->client_id.data,
                                                                req->client_id.length);
-                                if (!lease->client_id.data)
+                                if (!lease->client_id.data) {
+                                        free(lease);
                                         return -ENOMEM;
+                                }
                                 lease->client_id.length = req->client_id.length;
                         } else
                                 lease = existing_lease;
@@ -734,6 +745,31 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
 
                 break;
         }
+        case DHCP_RELEASE: {
+                int pool_offset;
+
+                log_dhcp_server(server, "RELEASE (0x%x)",
+                                be32toh(req->message->xid));
+
+                if (!existing_lease)
+                        return 0;
+
+                if (existing_lease->address != req->message->ciaddr)
+                        return 0;
+
+                pool_offset = get_pool_offset(server, req->message->ciaddr);
+                if (pool_offset < 0)
+                        return 0;
+
+                if (server->bound_leases[pool_offset] == existing_lease) {
+                        server->bound_leases[pool_offset] = NULL;
+                        hashmap_remove(server->leases_by_client_id, existing_lease);
+                        dhcp_lease_free(existing_lease);
+
+                        return 1;
+                } else
+                        return 0;
+        }
         }
 
         return 0;