From: Yu Watanabe Date: Thu, 7 May 2026 02:59:23 +0000 (+0900) Subject: sd-dhcp-server: store more information in DHCPRequest X-Git-Tag: v261-rc1~22^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e359c6df6589da33c0b7b0448355a95dcb70a8bd;p=thirdparty%2Fsystemd.git 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. --- diff --git a/src/libsystemd-network/dhcp-server-lease-internal.h b/src/libsystemd-network/dhcp-server-lease-internal.h index 024279ccbd3..f347837bd84 100644 --- a/src/libsystemd-network/dhcp-server-lease-internal.h +++ b/src/libsystemd-network/dhcp-server-lease-internal.h @@ -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); diff --git a/src/libsystemd-network/dhcp-server-request.c b/src/libsystemd-network/dhcp-server-request.c index 768677e65e5..202a8b888cd 100644 --- a/src/libsystemd-network/dhcp-server-request.c +++ b/src/libsystemd-network/dhcp-server-request.c @@ -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); - - r = dhcp_request_get_lifetime_timestamp(req, CLOCK_BOOTTIME, &expiration); - if (r < 0) - return r; + assert(req->address != INADDR_ANY); - 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: diff --git a/src/libsystemd-network/dhcp-server-request.h b/src/libsystemd-network/dhcp-server-request.h index c9ffe2aba8e..e5738978a2d 100644 --- a/src/libsystemd-network/dhcp-server-request.h +++ b/src/libsystemd-network/dhcp-server-request.h @@ -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); diff --git a/src/libsystemd-network/dhcp-server-send.c b/src/libsystemd-network/dhcp-server-send.c index 3fd548392da..9f52ff4cc8d 100644 --- a/src/libsystemd-network/dhcp-server-send.c +++ b/src/libsystemd-network/dhcp-server-send.c @@ -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); diff --git a/src/libsystemd-network/dhcp-server-send.h b/src/libsystemd-network/dhcp-server-send.h index 80fd9a6b94f..27801b64ec2 100644 --- a/src/libsystemd-network/dhcp-server-send.h +++ b/src/libsystemd-network/dhcp-server-send.h @@ -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); diff --git a/src/libsystemd-network/sd-dhcp-server-lease.c b/src/libsystemd-network/sd-dhcp-server-lease.c index 58b5831e441..4ab78972640 100644 --- a/src/libsystemd-network/sd-dhcp-server-lease.c +++ b/src/libsystemd-network/sd-dhcp-server-lease.c @@ -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,