sd-dhcp-server: check address conflict more carefully

- Even if we found a matching static lease, check if there is no
  conflicting lease.
- Accept an address request that is different from the previous one.
- Also return NAK if the server address is requested.
This commit is contained in:
Yu Watanabe
2024-01-04 05:10:47 +09:00
parent cb0ba4b41b
commit 0596f5939f
2 changed files with 21 additions and 18 deletions
+19 -16
View File
@@ -1050,10 +1050,19 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz
return 0;
/* for now pick a random free address from the pool */
if (static_lease)
if (static_lease) {
if (existing_lease != hashmap_get(server->bound_leases_by_address, UINT32_TO_PTR(static_lease->address)))
/* The address is already assigned to another host. Refusing. */
return 0;
/* Found a matching static lease. */
address = static_lease->address;
else if (existing_lease)
} else if (existing_lease && address_is_in_pool(server, existing_lease->address))
/* If we previously assigned an address to the host, then reuse it. */
address = existing_lease->address;
else {
struct siphash state;
uint64_t hash;
@@ -1151,30 +1160,24 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz
/* Silently ignore Rapid Commit option in REQUEST message. */
req->rapid_commit = false;
/* disallow our own address */
if (address == server->address)
return 0;
if (static_lease) {
/* Found a static lease for the client ID. */
if (static_lease->address != address)
/* The client requested an address which is different from the static lease. Refuse. */
/* 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)))
/* The requested address is already assigned to another host. Refusing. */
return server_send_nak_or_ignore(server, init_reboot, req);
/* Found a static lease for the client ID. */
return server_ack_request(server, req, address);
}
if (address_is_in_pool(server, address)) {
if (address_is_in_pool(server, address))
/* The requested address is in the pool. */
if (existing_lease && existing_lease->address != address)
/* We previously assigned an address, but the client requested another one. Refuse. */
return server_send_nak_or_ignore(server, init_reboot, req);
return server_ack_request(server, req, address);
}
/* Refuse otherwise. */
return server_send_nak_or_ignore(server, init_reboot, req);
}
+2 -2
View File
@@ -184,7 +184,7 @@ static void test_message_handler(void) {
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == 0);
test.option_server_id.address = htobe32(INADDR_LOOPBACK);
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 4);
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == 0);
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == DHCP_ACK);
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3);
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == DHCP_ACK);
@@ -200,7 +200,7 @@ static void test_message_handler(void) {
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == DHCP_ACK);
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 30);
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL) == 0);
assert_se(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';