diff --git a/src/libsystemd-network/sd-dhcp-server-lease.c b/src/libsystemd-network/sd-dhcp-server-lease.c index 024aff731b1..a4230297561 100644 --- a/src/libsystemd-network/sd-dhcp-server-lease.c +++ b/src/libsystemd-network/sd-dhcp-server-lease.c @@ -174,6 +174,11 @@ sd_dhcp_server_lease* dhcp_server_get_static_lease(sd_dhcp_server *server, const if ((static_lease->address & server->netmask) != server->subnet) return NULL; + /* Check if the address is neither the subnet nor the broadcast address. */ + if (static_lease->address == server->subnet || + static_lease->address == (server->subnet | ~server->netmask)) + return NULL; + /* Check if the address is different from the server address. */ if (static_lease->address == server->address) return NULL; diff --git a/src/libsystemd-network/test-dhcp-server.c b/src/libsystemd-network/test-dhcp-server.c index 2ae184e4019..d0d7bd3014c 100644 --- a/src/libsystemd-network/test-dhcp-server.c +++ b/src/libsystemd-network/test-dhcp-server.c @@ -489,6 +489,58 @@ TEST(dhcp_server_static_lease_client_id_change) { check_bound_lease(server, static_address, &client_id_mac); } +TEST(dhcp_server_static_lease_special_addresses) { + _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL; + ASSERT_OK(sd_dhcp_server_new(&server, 4242)); + ASSERT_OK(sd_dhcp_server_configure_pool(server, &(struct in_addr) { htobe32(INADDR_LOOPBACK) }, + 8, 0, 0)); + + sd_dhcp_client_id client_id_subnet = { + .size = 7, + .id.type = 1, + .id.eth.haddr = { 'A', 'B', 'C', 'D', 'E', 'G' }, + }; + sd_dhcp_client_id client_id_broadcast = { + .size = 7, + .id.type = 1, + .id.eth.haddr = { 'A', 'B', 'C', 'D', 'E', 'H' }, + }; + sd_dhcp_client_id client_id_normal = { + .size = 7, + .id.type = 1, + .id.eth.haddr = { 'A', 'B', 'C', 'D', 'E', 'I' }, + }; + + ASSERT_OK(sd_dhcp_server_set_static_lease( + server, + &(struct in_addr) { .s_addr = server->subnet }, + client_id_subnet.raw, + client_id_subnet.size, + /* hostname= */ NULL)); + ASSERT_OK(sd_dhcp_server_set_static_lease( + server, + &(struct in_addr) { .s_addr = server->subnet | ~server->netmask }, + client_id_broadcast.raw, + client_id_broadcast.size, + /* hostname= */ NULL)); + ASSERT_OK(sd_dhcp_server_set_static_lease( + server, + &(struct in_addr) { .s_addr = htobe32(INADDR_LOOPBACK + 42) }, + client_id_normal.raw, + client_id_normal.size, + /* hostname= */ NULL)); + + /* Static lease lookup is used while processing DHCPDISCOVER. */ + DHCPRequest req = { .client_id = client_id_subnet }; + ASSERT_NULL(dhcp_server_get_static_lease(server, &req)); + + req.client_id = client_id_broadcast; + ASSERT_NULL(dhcp_server_get_static_lease(server, &req)); + + req.client_id = client_id_normal; + ASSERT_NOT_NULL(dhcp_server_get_static_lease(server, &req)); +} + TEST(sd_dhcp_server_set_static_lease) { _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL; ASSERT_OK(sd_dhcp_server_new(&server, 4242));