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:
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user