sd-dhcp-server: store more information in DHCPRequest

This makes DHCPRequest stores
- the message type of the received message,
- acquired address,
- found static DHCP lease,

This also moves call of dhcp_request_get_lifetime_timestamp() from
dhcp_server_ack() to dhcp_server_set_lease(), and rename
DHCPRequest.server_id -> .server_address.

No functional change, just refactoring.
This commit is contained in:
Yu Watanabe
2026-05-22 04:30:34 +09:00
parent 252f3855fe
commit e359c6df65
6 changed files with 51 additions and 45 deletions
@@ -28,7 +28,7 @@ extern const struct hash_ops dhcp_server_lease_hash_ops;
int dhcp_server_put_lease(sd_dhcp_server *server, sd_dhcp_server_lease *lease, bool is_static);
int dhcp_server_set_lease(sd_dhcp_server *server, be32_t address, DHCPRequest *req, usec_t expiration);
int dhcp_server_set_lease(sd_dhcp_server *server, DHCPRequest *req);
int dhcp_server_cleanup_expired_leases(sd_dhcp_server *server);
sd_dhcp_server_lease* dhcp_server_get_static_lease(sd_dhcp_server *server, const DHCPRequest *req);
+26 -27
View File
@@ -112,7 +112,7 @@ static int parse_request(uint8_t code, uint8_t len, const void *option, void *us
break;
case SD_DHCP_OPTION_SERVER_IDENTIFIER:
if (len == 4)
memcpy(&req->server_id, option, sizeof(be32_t));
memcpy(&req->server_address, option, sizeof(be32_t));
break;
case SD_DHCP_OPTION_CLIENT_IDENTIFIER:
@@ -169,7 +169,7 @@ static int dhcp_server_parse_message(sd_dhcp_server *server, DHCPMessage *messag
r = dhcp_option_parse(message, length, parse_request, req, &error_message);
if (r < 0)
return r;
int type = r;
req->type = r;
r = ensure_sane_request(server, req, message);
if (r < 0)
@@ -177,26 +177,21 @@ static int dhcp_server_parse_message(sd_dhcp_server *server, DHCPMessage *messag
*ret = TAKE_PTR(req);
*ret_error_message = TAKE_PTR(error_message);
return type;
return 0;
}
static int dhcp_server_ack(sd_dhcp_server *server, DHCPRequest *req, be32_t address) {
usec_t expiration;
static int dhcp_server_ack(sd_dhcp_server *server, DHCPRequest *req) {
int r;
assert(server);
assert(req);
assert(address != 0);
assert(req->address != INADDR_ANY);
r = dhcp_request_get_lifetime_timestamp(req, CLOCK_BOOTTIME, &expiration);
if (r < 0)
return r;
r = dhcp_server_set_lease(server, address, req, expiration);
r = dhcp_server_set_lease(server, req);
if (r < 0)
return log_dhcp_server_errno(server, r, "Failed to create new lease: %m");
r = server_send_offer_or_ack(server, req, address, DHCP_ACK);
r = server_send_offer_or_ack(server, req, DHCP_ACK);
if (r < 0)
return log_dhcp_server_errno(server, r, "Could not send ACK: %m");
@@ -223,8 +218,6 @@ static int dhcp_server_process_discover(sd_dhcp_server *server, DHCPRequest *req
/* no pool allocated */
return 0;
be32_t address = INADDR_ANY;
/* for now pick a random free address from the pool */
if (static_lease) {
sd_dhcp_server_lease *l = hashmap_get(server->bound_leases_by_address, UINT32_TO_PTR(static_lease->address));
@@ -233,12 +226,13 @@ static int dhcp_server_process_discover(sd_dhcp_server *server, DHCPRequest *req
return 0;
/* Found a matching static lease. */
address = static_lease->address;
req->static_lease = static_lease;
req->address = static_lease->address;
} else if (existing_lease && dhcp_server_address_is_in_pool(server, existing_lease->address))
/* If we previously assigned an address to the host, then reuse it. */
address = existing_lease->address;
req->address = existing_lease->address;
else {
struct siphash state;
@@ -257,20 +251,20 @@ static int dhcp_server_process_discover(sd_dhcp_server *server, DHCPRequest *req
for (unsigned i = 0; i < server->pool_size; i++) {
be32_t a = server->subnet | htobe32(server->pool_offset + (hash + i) % server->pool_size);
if (dhcp_server_address_available(server, a)) {
address = a;
req->address = a;
break;
}
}
}
if (address == INADDR_ANY)
if (req->address == INADDR_ANY)
/* no free addresses left */
return 0;
if (server->rapid_commit && req->rapid_commit)
return dhcp_server_ack(server, req, address);
return dhcp_server_ack(server, req);
r = server_send_offer_or_ack(server, req, address, DHCP_OFFER);
r = server_send_offer_or_ack(server, req, DHCP_OFFER);
if (r < 0)
/* this only fails on critical errors */
return log_dhcp_server_errno(server, r, "Could not send offer: %m");
@@ -292,12 +286,12 @@ static int dhcp_server_process_request(sd_dhcp_server *server, DHCPRequest *req)
/* see RFC 2131, section 4.3.2 */
if (req->server_id != 0) {
if (req->server_address != INADDR_ANY) {
log_dhcp_server(server, "REQUEST (selecting) (0x%x)",
be32toh(req->message->xid));
/* SELECTING */
if (req->server_id != server->address)
if (req->server_address != server->address)
/* client did not pick us */
return 0;
@@ -348,13 +342,19 @@ static int dhcp_server_process_request(sd_dhcp_server *server, DHCPRequest *req)
/* The requested address is already assigned to another host. Refusing. */
return server_send_nak_or_ignore(server, init_reboot, req);
req->static_lease = static_lease;
req->address = address;
/* Found a static lease for the client ID. */
return dhcp_server_ack(server, req, address);
return dhcp_server_ack(server, req);
}
if (dhcp_server_address_is_in_pool(server, address))
if (dhcp_server_address_is_in_pool(server, address)) {
/* The requested address is in the pool. */
return dhcp_server_ack(server, req, address);
req->address = address;
return dhcp_server_ack(server, req);
}
/* Refuse otherwise. */
return server_send_nak_or_ignore(server, init_reboot, req);
@@ -408,7 +408,6 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz
r = dhcp_server_parse_message(server, message, length, &req, &error_message);
if (r < 0)
return r;
int type = r;
dhcp_request_set_timestamp(req, timestamp);
@@ -416,7 +415,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz
if (r < 0)
return r;
switch (type) {
switch (req->type) {
case DHCP_DISCOVER:
return dhcp_server_process_discover(server, req);
case DHCP_REQUEST:
+8 -1
View File
@@ -1,6 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "sd-dhcp-server-lease.h"
#include "dhcp-client-id-internal.h"
#include "dhcp-protocol.h"
#include "ether-addr-util.h"
@@ -16,10 +18,11 @@ typedef struct DHCPRequest {
triple_timestamp timestamp;
/* options */
uint8_t type;
sd_dhcp_client_id client_id;
sd_dhcp_client_id client_id_by_header;
size_t max_optlen;
be32_t server_id;
be32_t server_address;
be32_t requested_ip;
usec_t lifetime;
const uint8_t *agent_info_option;
@@ -27,6 +30,10 @@ typedef struct DHCPRequest {
const uint8_t *parameter_request_list;
size_t parameter_request_list_len;
bool rapid_commit;
/* acquired data */
sd_dhcp_server_lease *static_lease;
be32_t address;
} DHCPRequest;
int dhcp_request_get_lifetime_timestamp(DHCPRequest *req, clockid_t clock, usec_t *ret);
+6 -9
View File
@@ -286,7 +286,6 @@ static int dhcp_server_append_static_hostname(
size_t *offset,
DHCPRequest *req) {
sd_dhcp_server_lease *static_lease;
int r;
assert(server);
@@ -294,11 +293,10 @@ static int dhcp_server_append_static_hostname(
assert(offset);
assert(req);
static_lease = dhcp_server_get_static_lease(server, req);
if (!static_lease || !static_lease->hostname)
if (!req->static_lease || !req->static_lease->hostname)
return 0;
if (dns_name_is_single_label(static_lease->hostname))
if (dns_name_is_single_label(req->static_lease->hostname))
/* Option 12 */
return dhcp_option_append(
&packet->dhcp,
@@ -306,8 +304,8 @@ static int dhcp_server_append_static_hostname(
offset,
/* overload= */ 0,
SD_DHCP_OPTION_HOST_NAME,
strlen(static_lease->hostname),
static_lease->hostname);
strlen(req->static_lease->hostname),
req->static_lease->hostname);
/* Option 81 */
@@ -322,7 +320,7 @@ static int dhcp_server_append_static_hostname(
buffer[1] = 255;
buffer[2] = 255;
r = dns_name_to_wire_format(static_lease->hostname, buffer + 3, sizeof(buffer) - 3, false);
r = dns_name_to_wire_format(req->static_lease->hostname, buffer + 3, sizeof(buffer) - 3, false);
if (r < 0)
return log_dhcp_server_errno(server, r, "Failed to encode FQDN for static lease: %m");
if (r > DHCP_MAX_FQDN_LENGTH)
@@ -350,7 +348,6 @@ static bool dhcp_request_contains(DHCPRequest *req, uint8_t option) {
int server_send_offer_or_ack(
sd_dhcp_server *server,
DHCPRequest *req,
be32_t address,
uint8_t type) {
static const uint8_t option_map[_SD_DHCP_LEASE_SERVER_TYPE_MAX] = {
@@ -375,7 +372,7 @@ int server_send_offer_or_ack(
if (r < 0)
return r;
packet->dhcp.yiaddr = address;
packet->dhcp.yiaddr = req->address;
packet->dhcp.siaddr = server->boot_server_address.s_addr;
lease_time = usec_to_be32_sec(req->lifetime);
@@ -8,7 +8,6 @@
int server_send_offer_or_ack(
sd_dhcp_server *server,
DHCPRequest *req,
be32_t address,
uint8_t type);
int server_send_nak_or_ignore(sd_dhcp_server *server, bool init_reboot, DHCPRequest *req);
+10 -6
View File
@@ -64,21 +64,25 @@ int dhcp_server_put_lease(sd_dhcp_server *server, sd_dhcp_server_lease *lease, b
return 0;
}
int dhcp_server_set_lease(sd_dhcp_server *server, be32_t address, DHCPRequest *req, usec_t expiration) {
int dhcp_server_set_lease(sd_dhcp_server *server, DHCPRequest *req) {
_cleanup_(sd_dhcp_server_lease_unrefp) sd_dhcp_server_lease *lease = NULL;
int r;
assert(server);
assert(address != 0);
assert(req);
assert(expiration != 0);
assert(req->address != INADDR_ANY);
usec_t expiration;
r = dhcp_request_get_lifetime_timestamp(req, CLOCK_BOOTTIME, &expiration);
if (r < 0)
return r;
/* If a lease for the host already exists, update it. */
lease = hashmap_get(server->bound_leases_by_client_id, &req->client_id);
if (lease) {
if (lease->address != address) {
if (lease->address != req->address) {
hashmap_remove_value(server->bound_leases_by_address, UINT32_TO_PTR(lease->address), lease);
lease->address = address;
lease->address = req->address;
r = hashmap_ensure_put(&server->bound_leases_by_address, NULL, UINT32_TO_PTR(lease->address), lease);
if (r < 0)
@@ -99,7 +103,7 @@ int dhcp_server_set_lease(sd_dhcp_server *server, be32_t address, DHCPRequest *r
*lease = (sd_dhcp_server_lease) {
.n_ref = 1,
.address = address,
.address = req->address,
.client_id = req->client_id,
.htype = req->message->htype,
.gateway = req->message->giaddr,