/* for now pick a random free address from the pool */
if (static_lease) {
- if (existing_lease != hashmap_get(server->bound_leases_by_address, UINT32_TO_PTR(static_lease->address)))
+ sd_dhcp_server_lease *l = hashmap_get(server->bound_leases_by_address, UINT32_TO_PTR(static_lease->address));
+ if (l && l != existing_lease)
/* The address is already assigned to another host. Refusing. */
return 0;
/* The client requested an address which is different from the static lease. Refusing. */
return server_send_nak_or_ignore(server, init_reboot, req);
- if (existing_lease != hashmap_get(server->bound_leases_by_address, UINT32_TO_PTR(address)))
+ sd_dhcp_server_lease *l = hashmap_get(server->bound_leases_by_address, UINT32_TO_PTR(address));
+ if (l && l != existing_lease)
/* The requested address is already assigned to another host. Refusing. */
return server_send_nak_or_ignore(server, init_reboot, req);
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 30);
ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_ACK);
+ /* add the static lease for the client ID */
+ ASSERT_OK(sd_dhcp_server_stop(server));
+ ASSERT_OK(sd_dhcp_server_set_static_lease(server, &(struct in_addr){ .s_addr = htobe32(INADDR_LOOPBACK + 31) },
+ (uint8_t[7]){ 0x01, 'A', 'B', 'C', 'D', 'E', 'F' }, 7));
+ ASSERT_OK(sd_dhcp_server_start(server));
+
+ /* discover */
+ test.option_type.type = DHCP_DISCOVER;
+ ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_OFFER);
+
+ /* request neither bound nor static address */
+ test.option_type.type = DHCP_REQUEST;
+ test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 29);
+ ASSERT_OK_ZERO(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL));
+
+ /* request the currently assigned address */
+ test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 30);
+ ASSERT_OK_ZERO(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL));
+
+ /* request the new static address */
+ test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 31);
+ ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_ACK);
+
+ /* release the bound static lease */
+ test.message.ciaddr = htobe32(INADDR_LOOPBACK + 31);
+ test.option_type.type = DHCP_RELEASE;
+ ASSERT_OK_ZERO(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL));
+
+ /* drop the static lease for the client ID */
+ ASSERT_OK(sd_dhcp_server_stop(server));
+ ASSERT_OK(sd_dhcp_server_set_static_lease(server, NULL, (uint8_t[7]){ 0x01, 'A', 'B', 'C', 'D', 'E', 'F' }, 7));
+ ASSERT_OK(sd_dhcp_server_start(server));
+
+ /* request a new non-static address */
+ test.message.ciaddr = 0;
+ test.option_type.type = DHCP_REQUEST;
+ test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 29);
+ ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_ACK);
+
/* request address reserved for static lease (unmatching client ID) */
test.option_client_id.id[6] = 'H';
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 42);