From 0a195d4186260a57fc32a69f103d1040c1e27972 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 27 Jan 2022 16:19:10 +0900 Subject: [PATCH 01/19] sd-dhcp-server: do not log "STOPPED" when already stopped --- src/libsystemd-network/sd-dhcp-server.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 1d27d28959..f80e687ca7 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -165,8 +165,6 @@ DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR( static sd_dhcp_server *dhcp_server_free(sd_dhcp_server *server) { assert(server); - log_dhcp_server(server, "UNREF"); - sd_dhcp_server_stop(server); sd_event_unref(server->event); @@ -280,9 +278,13 @@ sd_event *sd_dhcp_server_get_event(sd_dhcp_server *server) { } int sd_dhcp_server_stop(sd_dhcp_server *server) { + bool running; + if (!server) return 0; + running = sd_dhcp_server_is_running(server); + server->receive_message = sd_event_source_disable_unref(server->receive_message); server->receive_broadcast = sd_event_source_disable_unref(server->receive_broadcast); @@ -290,7 +292,8 @@ int sd_dhcp_server_stop(sd_dhcp_server *server) { server->fd = safe_close(server->fd); server->fd_broadcast = safe_close(server->fd_broadcast); - log_dhcp_server(server, "STOPPED"); + if (running) + log_dhcp_server(server, "STOPPED"); return 0; } From a2a801926da67999b4bbbecc43f797e26adf7c65 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 28 Jan 2022 01:05:52 +0900 Subject: [PATCH 02/19] sd-dhcp-server: refuse zero length client ID --- src/libsystemd-network/sd-dhcp-server.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index f80e687ca7..2f7a429139 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -134,7 +134,7 @@ int sd_dhcp_server_is_in_relay_mode(sd_dhcp_server *server) { void client_id_hash_func(const DHCPClientId *id, struct siphash *state) { assert(id); - assert(id->length); + assert(id->length > 0); assert(id->data); siphash24_compress(&id->length, sizeof(id->length), state); @@ -144,8 +144,10 @@ void client_id_hash_func(const DHCPClientId *id, struct siphash *state) { int client_id_compare_func(const DHCPClientId *a, const DHCPClientId *b) { int r; - assert(!a->length || a->data); - assert(!b->length || b->data); + assert(a->length > 0); + assert(a->data); + assert(b->length > 0); + assert(b->data); r = CMP(a->length, b->length); if (r != 0) @@ -1579,6 +1581,7 @@ int sd_dhcp_server_set_static_lease( assert_return(server, -EINVAL); assert_return(client_id, -EINVAL); + assert_return(client_id_size > 0, -EINVAL); assert_return(!sd_dhcp_server_is_running(server), -EBUSY); /* Static lease with an empty or omitted address is a valid entry, @@ -1605,8 +1608,6 @@ int sd_dhcp_server_set_static_lease( *lease = (DHCPLease) { .address = address->s_addr, .client_id.length = client_id_size, - .gateway = 0, - .expiration = 0, }; lease->client_id.data = memdup(client_id, client_id_size); if (!lease->client_id.data) From 6277e48fa9322c7c2fef2dc12021f5c7d23e21df Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 28 Jan 2022 01:23:39 +0900 Subject: [PATCH 03/19] sd-dhcp-server: do not use implicit cast to boolean from integer --- src/libsystemd-network/sd-dhcp-server.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 2f7a429139..7624e52858 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -316,7 +316,7 @@ static int dhcp_server_send_unicast_raw( assert(server); assert(server->ifindex > 0); - assert(server->address); + assert(server->address != 0); assert(hlen > 0); assert(chaddr); assert(packet); @@ -429,7 +429,7 @@ int dhcp_server_send_packet(sd_dhcp_server *server, assert(server); assert(req); - assert(req->max_optlen); + assert(req->max_optlen > 0); assert(req->message); assert(optoffset <= req->max_optlen); assert(packet); @@ -477,12 +477,12 @@ int dhcp_server_send_packet(sd_dhcp_server *server, client, because the client may not have a correct network address or subnet mask, and the client may not be answering ARP requests. */ - if (req->message->giaddr) { + if (req->message->giaddr != 0) { destination = req->message->giaddr; destination_port = DHCP_PORT_SERVER; if (type == DHCP_NAK) packet->dhcp.flags = htobe16(0x8000); - } else if (req->message->ciaddr && type != DHCP_NAK) + } else if (req->message->ciaddr != 0 && type != DHCP_NAK) destination = req->message->ciaddr; bool l2_broadcast = requested_broadcast(req->message) || type == DHCP_NAK; @@ -786,7 +786,7 @@ static int ensure_sane_request(sd_dhcp_server *server, DHCPRequest *req, DHCPMes static int get_pool_offset(sd_dhcp_server *server, be32_t requested_ip) { assert(server); - if (!server->pool_size) + if (server->pool_size == 0) return -EINVAL; if (be32toh(requested_ip) < (be32toh(server->subnet) | server->pool_offset) || @@ -979,7 +979,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz log_dhcp_server(server, "DISCOVER (0x%x)", be32toh(req->message->xid)); - if (!server->pool_size) + if (server->pool_size == 0) /* no pool allocated */ return 0; @@ -1038,7 +1038,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz /* see RFC 2131, section 4.3.2 */ - if (req->server_id) { + if (req->server_id != 0) { log_dhcp_server(server, "REQUEST (selecting) (0x%x)", be32toh(req->message->xid)); @@ -1047,22 +1047,22 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz /* client did not pick us */ return 0; - if (req->message->ciaddr) + if (req->message->ciaddr != 0) /* this MUST be zero */ return 0; - if (!req->requested_ip) + if (req->requested_ip == 0) /* this must be filled in with the yiaddr from the chosen OFFER */ return 0; address = req->requested_ip; - } else if (req->requested_ip) { + } else if (req->requested_ip != 0) { log_dhcp_server(server, "REQUEST (init-reboot) (0x%x)", be32toh(req->message->xid)); /* INIT-REBOOT */ - if (req->message->ciaddr) + if (req->message->ciaddr != 0) /* this MUST be zero */ return 0; @@ -1074,7 +1074,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz be32toh(req->message->xid)); /* REBINDING / RENEWING */ - if (!req->message->ciaddr) + if (req->message->ciaddr == 0) /* this MUST be filled in with clients IP address */ return 0; From 48be485b71a02066c0ee3665b98500563df4d0fd Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 28 Jan 2022 01:24:20 +0900 Subject: [PATCH 04/19] sd-dhcp-server: rename argument and add one missing assertion --- src/libsystemd-network/sd-dhcp-server.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 7624e52858..cb1d06ce57 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -490,17 +490,22 @@ int dhcp_server_send_packet(sd_dhcp_server *server, destination, destination_port, packet, optoffset, l2_broadcast); } -static int server_message_init(sd_dhcp_server *server, DHCPPacket **ret, - uint8_t type, size_t *_optoffset, - DHCPRequest *req) { +static int server_message_init( + sd_dhcp_server *server, + DHCPPacket **ret, + uint8_t type, + size_t *ret_optoffset, + DHCPRequest *req) { + _cleanup_free_ DHCPPacket *packet = NULL; size_t optoffset = 0; int r; assert(server); assert(ret); - assert(_optoffset); + assert(ret_optoffset); assert(IN_SET(type, DHCP_OFFER, DHCP_ACK, DHCP_NAK)); + assert(req); packet = malloc0(sizeof(DHCPPacket) + req->max_optlen); if (!packet) @@ -516,7 +521,7 @@ static int server_message_init(sd_dhcp_server *server, DHCPPacket **ret, packet->dhcp.flags = req->message->flags; packet->dhcp.giaddr = req->message->giaddr; - *_optoffset = optoffset; + *ret_optoffset = optoffset; *ret = TAKE_PTR(packet); return 0; From 37e219800fc34c0e6e54e02d943102957f945b56 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 28 Jan 2022 01:24:35 +0900 Subject: [PATCH 05/19] sd-dhcp-server: fix indentation --- src/libsystemd-network/sd-dhcp-server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index cb1d06ce57..68a7916f64 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -1366,8 +1366,8 @@ int sd_dhcp_server_start(sd_dhcp_server *server) { return 0; on_error: - sd_dhcp_server_stop(server); - return r; + sd_dhcp_server_stop(server); + return r; } int sd_dhcp_server_forcerenew(sd_dhcp_server *server) { From 8a7d048d1ddb8916482f1422405d3e0e4bccb279 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 27 Jan 2022 00:17:23 +0900 Subject: [PATCH 06/19] sd-dhcp-server: set DHCPLease::server before hashmap_put() Otherwise, if the second push is failed, then the first hashmap contains dirty entry. Also, this makes hashmap_remove_value() used when removing leases to make not wrong lease is removed from the hashmap. Note, this just hide the root cause of the issue #22253, which will be fixed in later commit. Fixes #22253. --- src/libsystemd-network/sd-dhcp-server.c | 34 ++++++++++--------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 68a7916f64..921dad5c05 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -30,19 +30,10 @@ static DHCPLease *dhcp_lease_free(DHCPLease *lease) { return NULL; if (lease->server) { - DHCPLease *e; - - e = hashmap_get(lease->server->bound_leases_by_client_id, &lease->client_id); - if (e == lease) { - hashmap_remove(lease->server->bound_leases_by_address, UINT32_TO_PTR(lease->address)); - hashmap_remove(lease->server->bound_leases_by_client_id, &lease->client_id); - } - - e = hashmap_get(lease->server->static_leases_by_client_id, &lease->client_id); - if (e == lease) { - hashmap_remove(lease->server->static_leases_by_address, UINT32_TO_PTR(lease->address)); - hashmap_remove(lease->server->static_leases_by_client_id, &lease->client_id); - } + hashmap_remove_value(lease->server->bound_leases_by_address, UINT32_TO_PTR(lease->address), lease); + hashmap_remove_value(lease->server->bound_leases_by_client_id, &lease->client_id, lease); + hashmap_remove_value(lease->server->static_leases_by_address, UINT32_TO_PTR(lease->address), lease); + hashmap_remove_value(lease->server->static_leases_by_client_id, &lease->client_id, lease); } free(lease->client_id.data); @@ -1118,7 +1109,10 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz log_dhcp_server(server, "ACK (0x%x)", be32toh(req->message->xid)); - dhcp_lease_free(hashmap_remove(server->bound_leases_by_client_id, &lease->client_id)); + dhcp_lease_free(hashmap_get(server->bound_leases_by_client_id, &lease->client_id)); + + lease->server = server; /* This must be set just before hashmap_put(). */ + r = hashmap_ensure_put(&server->bound_leases_by_client_id, &dhcp_lease_hash_ops, &lease->client_id, lease); if (r < 0) return log_dhcp_server_errno(server, r, "Could not save lease: %m"); @@ -1127,7 +1121,6 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz if (r < 0) return log_dhcp_server_errno(server, r, "Could not save lease: %m"); - lease->server = server; TAKE_PTR(lease); if (server->callback) @@ -1168,6 +1161,8 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz log_dhcp_server(server, "ACK (0x%x)", be32toh(req->message->xid)); + lease->server = server; /* This must be set just before hashmap_put(). */ + r = hashmap_ensure_put(&server->bound_leases_by_client_id, &dhcp_lease_hash_ops, &lease->client_id, lease); if (r < 0) return log_dhcp_server_errno(server, r, "Could not save lease: %m"); @@ -1175,7 +1170,6 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz if (r < 0) return log_dhcp_server_errno(server, r, "Could not save lease: %m"); - lease->server = server; TAKE_PTR(new_lease); if (server->callback) @@ -1599,13 +1593,10 @@ int sd_dhcp_server_set_static_lease( .data = client_id, }; - dhcp_lease_free(hashmap_remove(server->static_leases_by_client_id, &c)); + dhcp_lease_free(hashmap_get(server->static_leases_by_client_id, &c)); return 0; } - if (hashmap_contains(server->static_leases_by_address, UINT32_TO_PTR(address->s_addr))) - return -EEXIST; - lease = new(DHCPLease, 1); if (!lease) return -ENOMEM; @@ -1618,6 +1609,8 @@ int sd_dhcp_server_set_static_lease( if (!lease->client_id.data) return -ENOMEM; + lease->server = server; /* This must be set just before hashmap_put(). */ + r = hashmap_ensure_put(&server->static_leases_by_client_id, &dhcp_lease_hash_ops, &lease->client_id, lease); if (r < 0) return r; @@ -1625,7 +1618,6 @@ int sd_dhcp_server_set_static_lease( if (r < 0) return r; - lease->server = server; TAKE_PTR(lease); return 0; } From eb5bff9c9de2bd218f5ac431e3aead4b5747ecd9 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 28 Jan 2022 02:14:47 +0900 Subject: [PATCH 07/19] sd-dhcp-server: rename server_send_nak() -> server_send_nak_or_ignore() And logs error in the function. --- src/libsystemd-network/sd-dhcp-server.c | 29 ++++++++++++++----------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 921dad5c05..d6bc08e6c4 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -615,16 +615,28 @@ static int server_send_offer_or_ack( return dhcp_server_send_packet(server, req, packet, type, offset); } -static int server_send_nak(sd_dhcp_server *server, DHCPRequest *req) { +static int server_send_nak_or_ignore(sd_dhcp_server *server, bool init_reboot, DHCPRequest *req) { _cleanup_free_ DHCPPacket *packet = NULL; size_t offset; int r; + /* When a request is refused, RFC 2131, section 4.3.2 mentioned we should send NAK when the + * client is in INITREBOOT. If the client is in other state, there is nothing mentioned in the + * RFC whether we should send NAK or not. Hence, let's silently ignore the request. */ + + if (!init_reboot) + return 0; + r = server_message_init(server, &packet, DHCP_NAK, &offset, req); if (r < 0) - return r; + return log_dhcp_server_errno(server, r, "Failed to create NAK message: %m"); - return dhcp_server_send_packet(server, req, packet, DHCP_NAK, offset); + r = dhcp_server_send_packet(server, req, packet, DHCP_NAK, offset); + if (r < 0) + return log_dhcp_server_errno(server, r, "Could not send NAK message: %m"); + + log_dhcp_server(server, "NAK (0x%x)", be32toh(req->message->xid)); + return DHCP_NAK; } static int server_send_forcerenew( @@ -1176,18 +1188,9 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz server->callback(server, SD_DHCP_SERVER_EVENT_LEASE_CHANGED, server->callback_userdata); return DHCP_ACK; - - } else if (init_reboot) { - r = server_send_nak(server, req); - if (r < 0) - /* this only fails on critical errors */ - return log_dhcp_server_errno(server, r, "Could not send nak: %m"); - - log_dhcp_server(server, "NAK (0x%x)", be32toh(req->message->xid)); - return DHCP_NAK; } - break; + return server_send_nak_or_ignore(server, init_reboot, req); } case DHCP_RELEASE: { From 5cc8be890db8611b9003304769ec82c3548be6e1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 28 Jan 2022 02:10:23 +0900 Subject: [PATCH 08/19] sd-dhcp-server: rename get_pool_offset() -> address_is_in_pool() As, the value of pool_offset is not used. --- src/libsystemd-network/sd-dhcp-server.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index d6bc08e6c4..820bec888e 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -791,17 +791,17 @@ static int ensure_sane_request(sd_dhcp_server *server, DHCPRequest *req, DHCPMes return 0; } -static int get_pool_offset(sd_dhcp_server *server, be32_t requested_ip) { +static bool address_is_in_pool(sd_dhcp_server *server, be32_t address) { assert(server); if (server->pool_size == 0) - return -EINVAL; + return false; - if (be32toh(requested_ip) < (be32toh(server->subnet) | server->pool_offset) || - be32toh(requested_ip) >= (be32toh(server->subnet) | (server->pool_offset + server->pool_size))) - return -ERANGE; + if (be32toh(address) < (be32toh(server->subnet) | server->pool_offset) || + be32toh(address) >= (be32toh(server->subnet) | (server->pool_offset + server->pool_size))) + return false; - return be32toh(requested_ip & ~server->netmask) - server->pool_offset; + return true; } static int append_agent_information_option(sd_dhcp_server *server, DHCPMessage *message, size_t opt_length, size_t size) { @@ -1039,10 +1039,8 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz return 1; case DHCP_REQUEST: { - DHCPLease *existing_lease_by_address; be32_t address; bool init_reboot = false; - int pool_offset; /* see RFC 2131, section 4.3.2 */ @@ -1093,9 +1091,6 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz if (address == server->address) return 0; - pool_offset = get_pool_offset(server, address); - existing_lease_by_address = hashmap_get(server->bound_leases_by_address, UINT32_TO_PTR(address)); - /* verify that the requested address is from the pool, and either owned by the current client or free */ if (static_lease && static_lease->address == address) { @@ -1139,8 +1134,10 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz server->callback(server, SD_DHCP_SERVER_EVENT_LEASE_CHANGED, server->callback_userdata); return DHCP_ACK; + } - } else if (pool_offset >= 0 && existing_lease_by_address == existing_lease) { + DHCPLease *existing_lease_by_address = hashmap_get(server->bound_leases_by_address, UINT32_TO_PTR(address)); + if (address_is_in_pool(server, address) && existing_lease_by_address == existing_lease) { _cleanup_(dhcp_lease_freep) DHCPLease *new_lease = NULL; usec_t time_now, expiration; DHCPLease *lease; From e2ba408084935fffa0c73007528de7babf9309c8 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 28 Jan 2022 03:50:16 +0900 Subject: [PATCH 09/19] sd-dhcp-server: do not assign an address from pool when a static lease for the client ID exists --- src/libsystemd-network/sd-dhcp-server.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 820bec888e..ddcd6910e9 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -1091,9 +1091,13 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz if (address == server->address) return 0; - /* verify that the requested address is from the pool, and either - owned by the current client or free */ - if (static_lease && static_lease->address == address) { + 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. */ + return server_send_nak_or_ignore(server, init_reboot, req); + _cleanup_(dhcp_lease_freep) DHCPLease *lease = NULL; usec_t time_now, expiration; From 7e98fe05a0b9cdfdad326f34189cd37257d9d4e4 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 28 Jan 2022 03:50:57 +0900 Subject: [PATCH 10/19] sd-dhcp-server: explicitly refuse when conflicting address is requested --- src/libsystemd-network/sd-dhcp-server.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index ddcd6910e9..2f429020bb 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -1140,14 +1140,17 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz return DHCP_ACK; } - DHCPLease *existing_lease_by_address = hashmap_get(server->bound_leases_by_address, UINT32_TO_PTR(address)); - if (address_is_in_pool(server, address) && existing_lease_by_address == existing_lease) { + 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); + _cleanup_(dhcp_lease_freep) DHCPLease *new_lease = NULL; usec_t time_now, expiration; DHCPLease *lease; - /* Note that in the above condition we accept the case that both leases are NULL. */ - r = sd_event_now(server->event, clock_boottime_or_monotonic(), &time_now); if (r < 0) return r; From bd1a3eb65b9e308028c18e1ed7ffde474a3b1244 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 28 Jan 2022 02:25:37 +0900 Subject: [PATCH 11/19] sd-dhcp-server: do not assign address reserved for static leases to non-matching clients This fix the root cause of the issue #22253. --- src/libsystemd-network/sd-dhcp-server.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 2f429020bb..904298ebb0 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -801,6 +801,9 @@ static bool address_is_in_pool(sd_dhcp_server *server, be32_t address) { be32toh(address) >= (be32toh(server->subnet) | (server->pool_offset + server->pool_size))) return false; + if (hashmap_contains(server->static_leases_by_address, UINT32_TO_PTR(address))) + return false; + return true; } From 8b572f7ab207c01050b39555c2cc49cdcdc4e665 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 28 Jan 2022 02:44:10 +0900 Subject: [PATCH 12/19] sd-dhcp-server: split out logic to ACK request --- src/libsystemd-network/sd-dhcp-server.c | 140 ++++++++++-------------- 1 file changed, 55 insertions(+), 85 deletions(-) diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 904298ebb0..9e462694c0 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -919,6 +919,59 @@ static int prepare_new_lease( return 0; } +static int server_ack_request(sd_dhcp_server *server, DHCPRequest *req, DHCPLease *existing_lease, be32_t address) { + usec_t time_now, expiration; + int r; + + assert(server); + assert(req); + assert(address != 0); + + r = sd_event_now(server->event, clock_boottime_or_monotonic(), &time_now); + if (r < 0) + return r; + + expiration = usec_add(req->lifetime * USEC_PER_SEC, time_now); + + if (existing_lease) { + assert(existing_lease->server); + assert(existing_lease->address == address); + existing_lease->expiration = expiration; + + } else { + _cleanup_(dhcp_lease_freep) DHCPLease *lease = NULL; + + r = prepare_new_lease(&lease, address, &req->client_id, + req->message->htype, req->message->hlen, + req->message->chaddr, req->message->giaddr, expiration); + if (r < 0) + return log_dhcp_server_errno(server, r, "Failed to create new lease: %m"); + + lease->server = server; /* This must be set just before hashmap_put(). */ + + r = hashmap_ensure_put(&server->bound_leases_by_client_id, &dhcp_lease_hash_ops, &lease->client_id, lease); + if (r < 0) + return log_dhcp_server_errno(server, r, "Could not save lease: %m"); + + r = hashmap_ensure_put(&server->bound_leases_by_address, NULL, UINT32_TO_PTR(lease->address), lease); + if (r < 0) + return log_dhcp_server_errno(server, r, "Could not save lease: %m"); + + TAKE_PTR(lease); + } + + r = server_send_offer_or_ack(server, req, address, DHCP_ACK); + if (r < 0) + return log_dhcp_server_errno(server, r, "Could not send ACK: %m"); + + log_dhcp_server(server, "ACK (0x%x)", be32toh(req->message->xid)); + + if (server->callback) + server->callback(server, SD_DHCP_SERVER_EVENT_LEASE_CHANGED, server->callback_userdata); + + return DHCP_ACK; +} + static int dhcp_server_cleanup_expired_leases(sd_dhcp_server *server) { DHCPLease *lease; usec_t time_now; @@ -1101,46 +1154,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz /* The client requested an address which is different from the static lease. Refuse. */ return server_send_nak_or_ignore(server, init_reboot, req); - _cleanup_(dhcp_lease_freep) DHCPLease *lease = NULL; - usec_t time_now, expiration; - - r = sd_event_now(server->event, clock_boottime_or_monotonic(), &time_now); - if (r < 0) - return r; - - expiration = usec_add(req->lifetime * USEC_PER_SEC, time_now); - - r = prepare_new_lease(&lease, static_lease->address, &req->client_id, - req->message->htype, req->message->hlen, - req->message->chaddr, req->message->giaddr, expiration); - if (r < 0) - return r; - - r = server_send_offer_or_ack(server, req, address, DHCP_ACK); - if (r < 0) - /* this only fails on critical errors */ - return log_dhcp_server_errno(server, r, "Could not send ack: %m"); - - log_dhcp_server(server, "ACK (0x%x)", be32toh(req->message->xid)); - - dhcp_lease_free(hashmap_get(server->bound_leases_by_client_id, &lease->client_id)); - - lease->server = server; /* This must be set just before hashmap_put(). */ - - r = hashmap_ensure_put(&server->bound_leases_by_client_id, &dhcp_lease_hash_ops, &lease->client_id, lease); - if (r < 0) - return log_dhcp_server_errno(server, r, "Could not save lease: %m"); - - r = hashmap_ensure_put(&server->bound_leases_by_address, NULL, UINT32_TO_PTR(lease->address), lease); - if (r < 0) - return log_dhcp_server_errno(server, r, "Could not save lease: %m"); - - TAKE_PTR(lease); - - if (server->callback) - server->callback(server, SD_DHCP_SERVER_EVENT_LEASE_CHANGED, server->callback_userdata); - - return DHCP_ACK; + return server_ack_request(server, req, existing_lease, address); } if (address_is_in_pool(server, address)) { @@ -1150,51 +1164,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz /* We previously assigned an address, but the client requested another one. Refuse. */ return server_send_nak_or_ignore(server, init_reboot, req); - _cleanup_(dhcp_lease_freep) DHCPLease *new_lease = NULL; - usec_t time_now, expiration; - DHCPLease *lease; - - r = sd_event_now(server->event, clock_boottime_or_monotonic(), &time_now); - if (r < 0) - return r; - - expiration = usec_add(req->lifetime * USEC_PER_SEC, time_now); - - if (!existing_lease) { - r = prepare_new_lease(&new_lease, address, &req->client_id, - req->message->htype, req->message->hlen, - req->message->chaddr, req->message->giaddr, expiration); - if (r < 0) - return r; - - lease = new_lease; - } else { - existing_lease->expiration = expiration; - lease = existing_lease; - } - - r = server_send_offer_or_ack(server, req, address, DHCP_ACK); - if (r < 0) - /* this only fails on critical errors */ - return log_dhcp_server_errno(server, r, "Could not send ack: %m"); - - log_dhcp_server(server, "ACK (0x%x)", be32toh(req->message->xid)); - - lease->server = server; /* This must be set just before hashmap_put(). */ - - r = hashmap_ensure_put(&server->bound_leases_by_client_id, &dhcp_lease_hash_ops, &lease->client_id, lease); - if (r < 0) - return log_dhcp_server_errno(server, r, "Could not save lease: %m"); - r = hashmap_ensure_put(&server->bound_leases_by_address, NULL, UINT32_TO_PTR(lease->address), lease); - if (r < 0) - return log_dhcp_server_errno(server, r, "Could not save lease: %m"); - - TAKE_PTR(new_lease); - - if (server->callback) - server->callback(server, SD_DHCP_SERVER_EVENT_LEASE_CHANGED, server->callback_userdata); - - return DHCP_ACK; + return server_ack_request(server, req, existing_lease, address); } return server_send_nak_or_ignore(server, init_reboot, req); From 7e0a8bf1ce6f3e2d988b905a065ce0b8e2132d70 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 27 Jan 2022 16:06:13 +0900 Subject: [PATCH 13/19] test-dhcp-server: use log_tests_skipped_errno() --- src/libsystemd-network/test-dhcp-server.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libsystemd-network/test-dhcp-server.c b/src/libsystemd-network/test-dhcp-server.c index b0e37352c3..076579b0c7 100644 --- a/src/libsystemd-network/test-dhcp-server.c +++ b/src/libsystemd-network/test-dhcp-server.c @@ -58,7 +58,7 @@ static int test_basic(sd_event *event, bool bind_to_interface) { r = sd_dhcp_server_start(server); if (r == -EPERM) - return log_info_errno(r, "sd_dhcp_server_start failed: %m"); + return r; assert_se(r >= 0); assert_se(sd_dhcp_server_start(server) >= 0); @@ -236,12 +236,12 @@ int main(int argc, char *argv[]) { assert_se(sd_event_new(&e) >= 0); r = test_basic(e, true); - if (r != 0) - return log_tests_skipped("cannot start dhcp server(bound to interface)"); + if (r < 0) + return log_tests_skipped_errno(r, "cannot start dhcp server(bound to interface)"); r = test_basic(e, false); - if (r != 0) - return log_tests_skipped("cannot start dhcp server(non-bound to interface)"); + if (r < 0) + return log_tests_skipped_errno(r, "cannot start dhcp server(non-bound to interface)"); test_message_handler(); test_client_id_hash(); From 4e2319afe444b94df8c052a7390597bfdb6cc939 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 27 Jan 2022 16:11:02 +0900 Subject: [PATCH 14/19] test-dhcp-server: move sd-event allocation --- src/libsystemd-network/test-dhcp-server.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libsystemd-network/test-dhcp-server.c b/src/libsystemd-network/test-dhcp-server.c index 076579b0c7..f2d0158a79 100644 --- a/src/libsystemd-network/test-dhcp-server.c +++ b/src/libsystemd-network/test-dhcp-server.c @@ -20,8 +20,9 @@ static void test_pool(struct in_addr *address, unsigned size, int ret) { assert_se(sd_dhcp_server_configure_pool(server, address, 8, 0, size) == ret); } -static int test_basic(sd_event *event, bool bind_to_interface) { +static int test_basic(bool bind_to_interface) { _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; struct in_addr address_lo = { .s_addr = htobe32(INADDR_LOOPBACK), }; @@ -30,6 +31,8 @@ static int test_basic(sd_event *event, bool bind_to_interface) { }; int r; + assert_se(sd_event_new(&event) >= 0); + /* attach to loopback interface */ assert_se(sd_dhcp_server_new(&server, 1) >= 0); assert_se(server); @@ -228,18 +231,15 @@ static void test_client_id_hash(void) { } int main(int argc, char *argv[]) { - _cleanup_(sd_event_unrefp) sd_event *e; int r; test_setup_logging(LOG_DEBUG); - assert_se(sd_event_new(&e) >= 0); - - r = test_basic(e, true); + r = test_basic(true); if (r < 0) return log_tests_skipped_errno(r, "cannot start dhcp server(bound to interface)"); - r = test_basic(e, false); + r = test_basic(false); if (r < 0) return log_tests_skipped_errno(r, "cannot start dhcp server(non-bound to interface)"); From 4f3cb2465a0fc0a272aa7a64876466e122ee7d31 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 27 Jan 2022 16:07:48 +0900 Subject: [PATCH 15/19] test-dhcp-server: run a test earlier which does not require privilege --- src/libsystemd-network/test-dhcp-server.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libsystemd-network/test-dhcp-server.c b/src/libsystemd-network/test-dhcp-server.c index f2d0158a79..394a8e401d 100644 --- a/src/libsystemd-network/test-dhcp-server.c +++ b/src/libsystemd-network/test-dhcp-server.c @@ -235,6 +235,8 @@ int main(int argc, char *argv[]) { test_setup_logging(LOG_DEBUG); + test_client_id_hash(); + r = test_basic(true); if (r < 0) return log_tests_skipped_errno(r, "cannot start dhcp server(bound to interface)"); @@ -244,7 +246,6 @@ int main(int argc, char *argv[]) { return log_tests_skipped_errno(r, "cannot start dhcp server(non-bound to interface)"); test_message_handler(); - test_client_id_hash(); return 0; } From 99e65b7df34d4c664fc1b33101e634081734f34d Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 27 Jan 2022 15:40:40 +0900 Subject: [PATCH 16/19] test-dhcp-server: add usual headers --- src/libsystemd-network/test-dhcp-server.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libsystemd-network/test-dhcp-server.c b/src/libsystemd-network/test-dhcp-server.c index 394a8e401d..cc3043a407 100644 --- a/src/libsystemd-network/test-dhcp-server.c +++ b/src/libsystemd-network/test-dhcp-server.c @@ -31,6 +31,8 @@ static int test_basic(bool bind_to_interface) { }; int r; + log_debug("/* %s(bind_to_interface=%s) */", __func__, yes_no(bind_to_interface)); + assert_se(sd_event_new(&event) >= 0); /* attach to loopback interface */ @@ -112,6 +114,8 @@ static void test_message_handler(void) { .s_addr = htobe32(INADDR_LOOPBACK), }; + log_debug("/* %s */", __func__); + assert_se(sd_dhcp_server_new(&server, 1) >= 0); assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) >= 0); assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0); @@ -205,6 +209,8 @@ static void test_client_id_hash(void) { '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', }; + log_debug("/* %s */", __func__); + a.data = (uint8_t*)strdup("abcd"); b.data = (uint8_t*)strdup("abcd"); From 7b5445e74eaef9178482c81851ab82912b512671 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 27 Jan 2022 16:04:20 +0900 Subject: [PATCH 17/19] test-dhcp-server: add tests for setting static DHCP lease --- src/libsystemd-network/test-dhcp-server.c | 39 +++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/libsystemd-network/test-dhcp-server.c b/src/libsystemd-network/test-dhcp-server.c index cc3043a407..2f499d99e3 100644 --- a/src/libsystemd-network/test-dhcp-server.c +++ b/src/libsystemd-network/test-dhcp-server.c @@ -236,12 +236,51 @@ static void test_client_id_hash(void) { free(b.data); } +static void test_static_lease(void) { + _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL; + + log_debug("/* %s */", __func__); + + assert_se(sd_dhcp_server_new(&server, 1) >= 0); + + assert_se(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x01020304 }, + (uint8_t*) &(uint32_t) { 0x01020304 }, sizeof(uint32_t)) >= 0); + /* Duplicated entry. */ + assert_se(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x01020304 }, + (uint8_t*) &(uint32_t) { 0x01020304 }, sizeof(uint32_t)) == -EEXIST); + /* Address is conflicted. */ + assert_se(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x01020304 }, + (uint8_t*) &(uint32_t) { 0x01020305 }, sizeof(uint32_t)) == -EEXIST); + /* Client ID is conflicted. */ + assert_se(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x01020305 }, + (uint8_t*) &(uint32_t) { 0x01020304 }, sizeof(uint32_t)) == -EEXIST); + + assert_se(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x01020305 }, + (uint8_t*) &(uint32_t) { 0x01020305 }, sizeof(uint32_t)) >= 0); + /* Remove the previous entry. */ + assert_se(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x00000000 }, + (uint8_t*) &(uint32_t) { 0x01020305 }, sizeof(uint32_t)) >= 0); + /* Then, set a different address. */ + assert_se(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x01020306 }, + (uint8_t*) &(uint32_t) { 0x01020305 }, sizeof(uint32_t)) >= 0); + /* Remove again. */ + assert_se(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x00000000 }, + (uint8_t*) &(uint32_t) { 0x01020305 }, sizeof(uint32_t)) >= 0); + /* Try to remove non-existent entry. */ + assert_se(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x00000000 }, + (uint8_t*) &(uint32_t) { 0x01020305 }, sizeof(uint32_t)) >= 0); + /* Try to remove non-existent entry. */ + assert_se(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x00000000 }, + (uint8_t*) &(uint32_t) { 0x01020306 }, sizeof(uint32_t)) >= 0); +} + int main(int argc, char *argv[]) { int r; test_setup_logging(LOG_DEBUG); test_client_id_hash(); + test_static_lease(); r = test_basic(true); if (r < 0) From 6796c5a9c4706dbf264d05a67d7bf6010d2cd630 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 28 Jan 2022 03:07:28 +0900 Subject: [PATCH 18/19] test-dhcp-server: add tests for static lease --- src/libsystemd-network/test-dhcp-server.c | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/libsystemd-network/test-dhcp-server.c b/src/libsystemd-network/test-dhcp-server.c index 2f499d99e3..a19735b420 100644 --- a/src/libsystemd-network/test-dhcp-server.c +++ b/src/libsystemd-network/test-dhcp-server.c @@ -113,11 +113,17 @@ static void test_message_handler(void) { struct in_addr address_lo = { .s_addr = htobe32(INADDR_LOOPBACK), }; + struct in_addr static_lease_address = { + .s_addr = htobe32(INADDR_LOOPBACK + 42), + }; + static uint8_t static_lease_client_id[7] = {0x01, 'A', 'B', 'C', 'D', 'E', 'G' }; log_debug("/* %s */", __func__); assert_se(sd_dhcp_server_new(&server, 1) >= 0); assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) >= 0); + assert_se(sd_dhcp_server_set_static_lease(server, &static_lease_address, static_lease_client_id, + ELEMENTSOF(static_lease_client_id)) >= 0); assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0); assert_se(sd_dhcp_server_start(server) >= 0); @@ -187,6 +193,26 @@ static void test_message_handler(void) { test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 30); assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); + + /* 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); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); + + /* request unmatching address */ + test.option_client_id.id[6] = 'G'; + test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 41); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); + + /* request matching address */ + test.option_client_id.id[6] = 'G'; + test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 42); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK); + + /* try again */ + test.option_client_id.id[6] = 'G'; + test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 42); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK); } static uint64_t client_id_hash_helper(DHCPClientId *id, uint8_t key[HASH_KEY_SIZE]) { From a46abf2e345ac35f8f30aee9c22b0640980dc65b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 28 Jan 2022 10:12:00 +0900 Subject: [PATCH 19/19] fuzz-dhcp-server: add static leases --- src/libsystemd-network/fuzz-dhcp-server.c | 62 +++++++++++++++-------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/src/libsystemd-network/fuzz-dhcp-server.c b/src/libsystemd-network/fuzz-dhcp-server.c index 6a57850992..b35f1ac6da 100644 --- a/src/libsystemd-network/fuzz-dhcp-server.c +++ b/src/libsystemd-network/fuzz-dhcp-server.c @@ -17,13 +17,42 @@ ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) { return 0; } +static void add_lease(sd_dhcp_server *server, const struct in_addr *server_address, uint8_t i) { + static const uint8_t chaddr[] = {3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3}; + DHCPLease *lease; + + assert(server); + + assert_se(lease = new0(DHCPLease, 1)); + lease->client_id.length = 2; + assert_se(lease->client_id.data = malloc(2)); + lease->client_id.data[0] = 2; + lease->client_id.data[1] = i; + lease->address = htobe32(UINT32_C(10) << 24 | i); + lease->gateway = server_address->s_addr; + lease->expiration = UINT64_MAX; + lease->htype = ARPHRD_ETHER; + lease->hlen = ETH_ALEN; + memcpy(lease->chaddr, chaddr, ETH_ALEN); + assert_se(hashmap_ensure_put(&server->bound_leases_by_client_id, &dhcp_lease_hash_ops, &lease->client_id, lease) >= 0); + assert_se(hashmap_ensure_put(&server->bound_leases_by_address, NULL, UINT32_TO_PTR(lease->address), lease) >= 0); + lease->server = server; +} + +static void add_static_lease(sd_dhcp_server *server, uint8_t i) { + uint8_t id[2] = { 2, i }; + + assert(server); + + assert_se(sd_dhcp_server_set_static_lease(server, + &(struct in_addr) { .s_addr = htobe32(UINT32_C(10) << 24 | i)}, + id, ELEMENTSOF(id)) >= 0); +} + int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL; - struct in_addr address = {.s_addr = htobe32(UINT32_C(10) << 24 | UINT32_C(1))}; - static const uint8_t chaddr[] = {3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3}; + struct in_addr address = { .s_addr = htobe32(UINT32_C(10) << 24 | UINT32_C(1))}; _cleanup_free_ uint8_t *duped = NULL; - uint8_t *client_id; - DHCPLease *lease; if (size < sizeof(DHCPMessage)) return 0; @@ -36,24 +65,13 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { assert_se(server->fd >= 0); assert_se(sd_dhcp_server_configure_pool(server, &address, 24, 0, 0) >= 0); - /* add a lease to the pool to expose additional code paths */ - client_id = malloc(2); - assert_se(client_id); - client_id[0] = 2; - client_id[1] = 2; - lease = new0(DHCPLease, 1); - assert_se(lease); - lease->client_id.length = 2; - lease->client_id.data = client_id; - lease->address = htobe32(UINT32_C(10) << 24 | UINT32_C(2)); - lease->gateway = htobe32(UINT32_C(10) << 24 | UINT32_C(1)); - lease->expiration = UINT64_MAX; - lease->htype = ARPHRD_ETHER; - lease->hlen = ETH_ALEN; - memcpy(lease->chaddr, chaddr, ETH_ALEN); - assert_se(hashmap_ensure_put(&server->bound_leases_by_client_id, &dhcp_lease_hash_ops, &lease->client_id, lease) >= 0); - assert_se(hashmap_ensure_put(&server->bound_leases_by_address, NULL, UINT32_TO_PTR(lease->address), lease) >= 0); - lease->server = server; + /* add leases to the pool to expose additional code paths */ + add_lease(server, &address, 2); + add_lease(server, &address, 3); + + /* add static leases */ + add_static_lease(server, 3); + add_static_lease(server, 4); (void) dhcp_server_handle_message(server, (DHCPMessage*) duped, size);