sd-dhcp-server: rename DHCPLease -> sd_dhcp_server_lease

Then, move basic functions for the object to sd-dhcp-server-lease.[ch].

No effective funcional changes.
This commit is contained in:
Yu Watanabe
2024-01-03 15:20:31 +09:00
parent 95c48613f4
commit dd8ab4a206
10 changed files with 284 additions and 212 deletions
@@ -25,20 +25,6 @@ typedef enum DHCPRawOption {
_DHCP_RAW_OPTION_DATA_INVALID,
} DHCPRawOption;
typedef struct DHCPLease {
sd_dhcp_server *server;
sd_dhcp_client_id client_id;
uint8_t htype; /* e.g. ARPHRD_ETHER */
uint8_t hlen; /* e.g. ETH_ALEN */
be32_t address;
be32_t gateway;
uint8_t chaddr[16];
usec_t expiration;
char *hostname;
} DHCPLease;
struct sd_dhcp_server {
unsigned n_ref;
@@ -109,17 +95,12 @@ typedef struct DHCPRequest {
triple_timestamp timestamp;
} DHCPRequest;
extern const struct hash_ops dhcp_lease_hash_ops;
int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
size_t length, const triple_timestamp *timestamp);
int dhcp_server_send_packet(sd_dhcp_server *server,
DHCPRequest *req, DHCPPacket *packet,
int type, size_t optoffset);
DHCPLease *dhcp_lease_free(DHCPLease *lease);
DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPLease*, dhcp_lease_free);
#define log_dhcp_server_errno(server, error, fmt, ...) \
log_interface_prefix_full_errno( \
"DHCPv4 server: ", \
@@ -0,0 +1,33 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "sd-dhcp-server-lease.h"
#include "dhcp-client-id-internal.h"
#include "dhcp-server-internal.h"
#include "time-util.h"
typedef struct sd_dhcp_server_lease {
unsigned n_ref;
sd_dhcp_server *server;
sd_dhcp_client_id client_id;
uint8_t htype; /* e.g. ARPHRD_ETHER */
uint8_t hlen; /* e.g. ETH_ALEN */
be32_t address;
be32_t gateway;
uint8_t chaddr[16];
usec_t expiration;
char *hostname;
} sd_dhcp_server_lease;
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_cleanup_expired_leases(sd_dhcp_server *server);
sd_dhcp_server_lease* dhcp_server_get_static_lease(sd_dhcp_server *server, const DHCPRequest *req);
+5 -10
View File
@@ -18,16 +18,17 @@ ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) {
}
static int add_lease(sd_dhcp_server *server, const struct in_addr *server_address, uint8_t i) {
_cleanup_(dhcp_lease_freep) DHCPLease *lease = NULL;
_cleanup_(sd_dhcp_server_lease_unrefp) sd_dhcp_server_lease *lease = NULL;
int r;
assert(server);
lease = new(DHCPLease, 1);
lease = new(sd_dhcp_server_lease, 1);
if (!lease)
return -ENOMEM;
*lease = (DHCPLease) {
*lease = (sd_dhcp_server_lease) {
.n_ref = 1,
.address = htobe32(UINT32_C(10) << 24 | i),
.chaddr = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
.expiration = UINT64_MAX,
@@ -41,13 +42,7 @@ static int add_lease(sd_dhcp_server *server, const struct in_addr *server_addres
lease->client_id.raw[0] = 2;
lease->client_id.raw[1] = i;
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 r;
r = hashmap_ensure_put(&server->bound_leases_by_address, NULL, UINT32_TO_PTR(lease->address), lease);
r = dhcp_server_put_lease(server, lease, /* is_static = */ false);
if (r < 0)
return r;
+1
View File
@@ -19,6 +19,7 @@ sources = files(
'sd-dhcp-client.c',
'sd-dhcp-duid.c',
'sd-dhcp-lease.c',
'sd-dhcp-server-lease.c',
'sd-dhcp-server.c',
'sd-dhcp6-client.c',
'sd-dhcp6-lease.c',
@@ -0,0 +1,193 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "dhcp-server-lease-internal.h"
static sd_dhcp_server_lease* dhcp_server_lease_free(sd_dhcp_server_lease *lease) {
if (!lease)
return NULL;
if (lease->server) {
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->hostname);
return mfree(lease);
}
DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_server_lease, sd_dhcp_server_lease, dhcp_server_lease_free);
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
dhcp_server_lease_hash_ops,
sd_dhcp_client_id,
client_id_hash_func,
client_id_compare_func,
sd_dhcp_server_lease,
sd_dhcp_server_lease_unref);
int dhcp_server_put_lease(sd_dhcp_server *server, sd_dhcp_server_lease *lease, bool is_static) {
int r;
assert(server);
assert(lease);
lease->server = server; /* This must be set before hashmap_put(). */
r = hashmap_ensure_put(is_static ? &server->static_leases_by_client_id : &server->bound_leases_by_client_id,
&dhcp_server_lease_hash_ops, &lease->client_id, lease);
if (r < 0)
return r;
r = hashmap_ensure_put(is_static ? &server->static_leases_by_address : &server->bound_leases_by_address,
NULL, UINT32_TO_PTR(lease->address), lease);
if (r < 0)
return r;
return 0;
}
int dhcp_server_set_lease(sd_dhcp_server *server, be32_t address, DHCPRequest *req, usec_t expiration) {
_cleanup_(sd_dhcp_server_lease_unrefp) sd_dhcp_server_lease *lease = NULL;
int r;
assert(server);
assert(address != 0);
assert(req);
assert(expiration != 0);
/* 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) {
hashmap_remove_value(server->bound_leases_by_address, UINT32_TO_PTR(lease->address), lease);
lease->address = address;
r = hashmap_ensure_put(&server->bound_leases_by_address, NULL, UINT32_TO_PTR(lease->address), lease);
if (r < 0)
return r;
}
lease->expiration = expiration;
TAKE_PTR(lease);
return 0;
}
/* Otherwise, add a new lease. */
lease = new(sd_dhcp_server_lease, 1);
if (!lease)
return -ENOMEM;
*lease = (sd_dhcp_server_lease) {
.n_ref = 1,
.address = address,
.client_id = req->client_id,
.htype = req->message->htype,
.hlen = req->message->hlen,
.gateway = req->message->giaddr,
.expiration = expiration,
};
memcpy(lease->chaddr, req->message->chaddr, req->message->hlen);
if (req->hostname) {
lease->hostname = strdup(req->hostname);
if (!lease->hostname)
return -ENOMEM;
}
r = dhcp_server_put_lease(server, lease, /* is_static = */ false);
if (r < 0)
return r;
TAKE_PTR(lease);
return 0;
}
int dhcp_server_cleanup_expired_leases(sd_dhcp_server *server) {
sd_dhcp_server_lease *lease;
usec_t time_now;
int r;
assert(server);
r = sd_event_now(server->event, CLOCK_BOOTTIME, &time_now);
if (r < 0)
return r;
HASHMAP_FOREACH(lease, server->bound_leases_by_client_id)
if (lease->expiration < time_now) {
log_dhcp_server(server, "CLEAN (0x%x)", be32toh(lease->address));
sd_dhcp_server_lease_unref(lease);
}
return 0;
}
sd_dhcp_server_lease* dhcp_server_get_static_lease(sd_dhcp_server *server, const DHCPRequest *req) {
sd_dhcp_server_lease *static_lease;
sd_dhcp_client_id client_id;
assert(server);
assert(req);
static_lease = hashmap_get(server->static_leases_by_client_id, &req->client_id);
if (static_lease)
return static_lease;
/* when no lease is found based on the client id fall back to chaddr */
if (!client_id_data_size_is_valid(req->message->hlen))
return NULL;
if (sd_dhcp_client_id_set(&client_id, /* type = */ 1, req->message->chaddr, req->message->hlen) < 0)
return NULL;
return hashmap_get(server->static_leases_by_client_id, &client_id);
}
int sd_dhcp_server_set_static_lease(
sd_dhcp_server *server,
const struct in_addr *address,
uint8_t *client_id_raw,
size_t client_id_size) {
_cleanup_(sd_dhcp_server_lease_unrefp) sd_dhcp_server_lease *lease = NULL;
sd_dhcp_client_id client_id;
int r;
assert_return(server, -EINVAL);
assert_return(client_id_raw, -EINVAL);
assert_return(client_id_size_is_valid(client_id_size), -EINVAL);
assert_return(!sd_dhcp_server_is_running(server), -EBUSY);
r = sd_dhcp_client_id_set_raw(&client_id, client_id_raw, client_id_size);
if (r < 0)
return r;
/* Static lease with an empty or omitted address is a valid entry,
* the server removes any static lease with the specified mac address. */
if (!address || address->s_addr == 0) {
sd_dhcp_server_lease_unref(hashmap_get(server->static_leases_by_client_id, &client_id));
return 0;
}
lease = new(sd_dhcp_server_lease, 1);
if (!lease)
return -ENOMEM;
*lease = (sd_dhcp_server_lease) {
.n_ref = 1,
.address = address->s_addr,
.client_id = client_id,
};
r = dhcp_server_put_lease(server, lease, /* is_static = */ true);
if (r < 0)
return r;
TAKE_PTR(lease);
return 0;
}
+12 -178
View File
@@ -14,6 +14,7 @@
#include "dhcp-option.h"
#include "dhcp-packet.h"
#include "dhcp-server-internal.h"
#include "dhcp-server-lease-internal.h"
#include "dns-domain.h"
#include "fd-util.h"
#include "in-addr-util.h"
@@ -29,21 +30,6 @@
#define DHCP_DEFAULT_LEASE_TIME_USEC USEC_PER_HOUR
#define DHCP_MAX_LEASE_TIME_USEC (USEC_PER_HOUR*12)
DHCPLease *dhcp_lease_free(DHCPLease *lease) {
if (!lease)
return NULL;
if (lease->server) {
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->hostname);
return mfree(lease);
}
/* configures the server's address and subnet, and optionally the pool's size and offset into the subnet
* the whole pool must fit into the subnet, and may not contain the first (any) nor last (broadcast) address
* moreover, the server's own address may be in the pool, and is in that case reserved in order not to
@@ -126,14 +112,6 @@ int sd_dhcp_server_is_in_relay_mode(sd_dhcp_server *server) {
return in4_addr_is_set(&server->relay_target);
}
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
dhcp_lease_hash_ops,
sd_dhcp_client_id,
client_id_hash_func,
client_id_compare_func,
DHCPLease,
dhcp_lease_free);
static sd_dhcp_server *dhcp_server_free(sd_dhcp_server *server) {
assert(server);
@@ -986,41 +964,7 @@ static int dhcp_server_relay_message(sd_dhcp_server *server, DHCPMessage *messag
return -EBADMSG;
}
static int prepare_new_lease(DHCPLease **ret_lease, be32_t address, DHCPRequest *req, usec_t expiration) {
_cleanup_(dhcp_lease_freep) DHCPLease *lease = NULL;
assert(ret_lease);
assert(address != 0);
assert(req);
assert(expiration != 0);
lease = new(DHCPLease, 1);
if (!lease)
return -ENOMEM;
*lease = (DHCPLease) {
.address = address,
.client_id = req->client_id,
.htype = req->message->htype,
.hlen = req->message->hlen,
.gateway = req->message->giaddr,
.expiration = expiration,
};
memcpy(lease->chaddr, req->message->chaddr, req->message->hlen);
if (req->hostname) {
lease->hostname = strdup(req->hostname);
if (!lease->hostname)
return -ENOMEM;
}
*ret_lease = TAKE_PTR(lease);
return 0;
}
static int server_ack_request(sd_dhcp_server *server, DHCPRequest *req, DHCPLease *existing_lease, be32_t address) {
static int server_ack_request(sd_dhcp_server *server, DHCPRequest *req, be32_t address) {
usec_t expiration;
int r;
@@ -1032,30 +976,9 @@ static int server_ack_request(sd_dhcp_server *server, DHCPRequest *req, DHCPLeas
if (r < 0)
return r;
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, 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 = dhcp_server_set_lease(server, address, req, expiration);
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);
if (r < 0)
@@ -1069,26 +992,6 @@ static int server_ack_request(sd_dhcp_server *server, DHCPRequest *req, DHCPLeas
return DHCP_ACK;
}
static int dhcp_server_cleanup_expired_leases(sd_dhcp_server *server) {
DHCPLease *lease;
usec_t time_now;
int r;
assert(server);
r = sd_event_now(server->event, CLOCK_BOOTTIME, &time_now);
if (r < 0)
return r;
HASHMAP_FOREACH(lease, server->bound_leases_by_client_id)
if (lease->expiration < time_now) {
log_dhcp_server(server, "CLEAN (0x%x)", be32toh(lease->address));
dhcp_lease_free(lease);
}
return 0;
}
static bool address_available(sd_dhcp_server *server, be32_t address) {
assert(server);
@@ -1100,33 +1003,12 @@ static bool address_available(sd_dhcp_server *server, be32_t address) {
return true;
}
static DHCPLease* server_get_static_lease(sd_dhcp_server *server, const DHCPRequest *req) {
DHCPLease *static_lease;
sd_dhcp_client_id client_id;
assert(server);
assert(req);
static_lease = hashmap_get(server->static_leases_by_client_id, &req->client_id);
if (static_lease)
return static_lease;
/* when no lease is found based on the client id fall back to chaddr */
if (!client_id_data_size_is_valid(req->message->hlen))
return NULL;
if (sd_dhcp_client_id_set(&client_id, /* type = */ 1, req->message->chaddr, req->message->hlen) < 0)
return NULL;
return hashmap_get(server->static_leases_by_client_id, &client_id);
}
#define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30)
int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, size_t length, const triple_timestamp *timestamp) {
_cleanup_(dhcp_request_freep) DHCPRequest *req = NULL;
_cleanup_free_ char *error_message = NULL;
DHCPLease *existing_lease, *static_lease;
sd_dhcp_server_lease *existing_lease, *static_lease;
int type, r;
assert(server);
@@ -1154,7 +1036,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz
return r;
existing_lease = hashmap_get(server->bound_leases_by_client_id, &req->client_id);
static_lease = server_get_static_lease(server, req);
static_lease = dhcp_server_get_static_lease(server, req);
switch (type) {
@@ -1200,7 +1082,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz
return 0;
if (server->rapid_commit && req->rapid_commit)
return server_ack_request(server, req, existing_lease, address);
return server_ack_request(server, req, address);
r = server_send_offer_or_ack(server, req, address, DHCP_OFFER);
if (r < 0)
@@ -1280,7 +1162,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);
return server_ack_request(server, req, existing_lease, address);
return server_ack_request(server, req, address);
}
if (address_is_in_pool(server, address)) {
@@ -1290,7 +1172,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);
return server_ack_request(server, req, existing_lease, address);
return server_ack_request(server, req, address);
}
return server_send_nak_or_ignore(server, init_reboot, req);
@@ -1306,7 +1188,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz
if (existing_lease->address != req->message->ciaddr)
return 0;
dhcp_lease_free(existing_lease);
sd_dhcp_server_lease_unref(existing_lease);
if (server->callback)
server->callback(server, SD_DHCP_SERVER_EVENT_LEASE_CHANGED, server->callback_userdata);
@@ -1473,7 +1355,7 @@ on_error:
}
int sd_dhcp_server_forcerenew(sd_dhcp_server *server) {
DHCPLease *lease;
sd_dhcp_server_lease *lease;
int r = 0;
assert_return(server, -EINVAL);
@@ -1687,51 +1569,3 @@ int sd_dhcp_server_set_relay_agent_information(
free_and_replace(server->agent_remote_id, remote_id_dup);
return 0;
}
int sd_dhcp_server_set_static_lease(
sd_dhcp_server *server,
const struct in_addr *address,
uint8_t *client_id_raw,
size_t client_id_size) {
_cleanup_(dhcp_lease_freep) DHCPLease *lease = NULL;
sd_dhcp_client_id client_id;
int r;
assert_return(server, -EINVAL);
assert_return(client_id_raw, -EINVAL);
assert_return(client_id_size_is_valid(client_id_size), -EINVAL);
assert_return(!sd_dhcp_server_is_running(server), -EBUSY);
r = sd_dhcp_client_id_set_raw(&client_id, client_id_raw, client_id_size);
if (r < 0)
return r;
/* Static lease with an empty or omitted address is a valid entry,
* the server removes any static lease with the specified mac address. */
if (!address || address->s_addr == 0) {
dhcp_lease_free(hashmap_get(server->static_leases_by_client_id, &client_id));
return 0;
}
lease = new(DHCPLease, 1);
if (!lease)
return -ENOMEM;
*lease = (DHCPLease) {
.address = address->s_addr,
.client_id = client_id,
};
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;
r = hashmap_ensure_put(&server->static_leases_by_address, NULL, UINT32_TO_PTR(lease->address), lease);
if (r < 0)
return r;
TAKE_PTR(lease);
return 0;
}
+2 -2
View File
@@ -3,7 +3,7 @@
#include "alloc-util.h"
#include "bus-common-errors.h"
#include "bus-util.h"
#include "dhcp-server-internal.h"
#include "dhcp-server-lease-internal.h"
#include "networkd-dhcp-server-bus.h"
#include "networkd-link-bus.h"
#include "networkd-manager.h"
@@ -19,7 +19,7 @@ static int property_get_leases(
sd_bus_error *error) {
Link *l = ASSERT_PTR(userdata);
sd_dhcp_server *s;
DHCPLease *lease;
sd_dhcp_server_lease *lease;
int r;
assert(reply);
+3 -3
View File
@@ -2,7 +2,7 @@
#include <linux/nexthop.h>
#include "dhcp-server-internal.h"
#include "dhcp-server-lease-internal.h"
#include "dhcp6-internal.h"
#include "dhcp6-lease-internal.h"
#include "dns-domain.h"
@@ -892,7 +892,7 @@ static int pref64_append_json(Link *link, JsonVariant **v) {
static int dhcp_server_offered_leases_append_json(Link *link, JsonVariant **v) {
_cleanup_(json_variant_unrefp) JsonVariant *array = NULL;
DHCPLease *lease;
sd_dhcp_server_lease *lease;
int r;
assert(link);
@@ -924,7 +924,7 @@ static int dhcp_server_offered_leases_append_json(Link *link, JsonVariant **v) {
static int dhcp_server_static_leases_append_json(Link *link, JsonVariant **v) {
_cleanup_(json_variant_unrefp) JsonVariant *array = NULL;
DHCPLease *lease;
sd_dhcp_server_lease *lease;
int r;
assert(link);
+1
View File
@@ -26,6 +26,7 @@ _not_installed_headers = [
'sd-dhcp-lease.h',
'sd-dhcp-option.h',
'sd-dhcp-protocol.h',
'sd-dhcp-server-lease.h',
'sd-dhcp-server.h',
'sd-dhcp6-client.h',
'sd-dhcp6-lease.h',
+34
View File
@@ -0,0 +1,34 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#ifndef foosddhcpserverleasehfoo
#define foosddhcpserverleasehfoo
/***
Copyright © 2013 Intel Corporation. All rights reserved.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <https://www.gnu.org/licenses/>.
***/
#include "_sd-common.h"
_SD_BEGIN_DECLARATIONS;
typedef struct sd_dhcp_server_lease sd_dhcp_server_lease;
sd_dhcp_server_lease *sd_dhcp_server_lease_ref(sd_dhcp_server_lease *lease);
sd_dhcp_server_lease *sd_dhcp_server_lease_unref(sd_dhcp_server_lease *lease);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_server_lease, sd_dhcp_server_lease_unref);
_SD_END_DECLARATIONS;
#endif