sd-dhcp-server: use struct hw_addr_data to manage client hardware address parsed from DHCP message
Then, this drops garbage in DHCP server lease in DBus and Varlink message. This also drops fallback to use client ID as hardware address when chaddr field is not set. In that case, we should broadcast reply.
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
#include "dhcp-client-id-internal.h"
|
||||
#include "dhcp-server-internal.h"
|
||||
#include "dhcp-server-request.h"
|
||||
#include "ether-addr-util.h"
|
||||
#include "sd-forward.h"
|
||||
|
||||
typedef struct sd_dhcp_server_lease {
|
||||
@@ -16,10 +17,9 @@ typedef struct sd_dhcp_server_lease {
|
||||
sd_dhcp_client_id client_id;
|
||||
|
||||
uint8_t htype; /* e.g. ARPHRD_ETHER */
|
||||
uint8_t hlen; /* e.g. ETH_ALEN */
|
||||
struct hw_addr_data hw_addr;
|
||||
be32_t address;
|
||||
be32_t gateway;
|
||||
uint8_t chaddr[16];
|
||||
usec_t expiration;
|
||||
char *hostname;
|
||||
} sd_dhcp_server_lease;
|
||||
|
||||
@@ -54,8 +54,6 @@ int dhcp_request_get_lifetime_timestamp(DHCPRequest *req, clockid_t clock, usec_
|
||||
}
|
||||
|
||||
static int ensure_sane_request(sd_dhcp_server *server, DHCPRequest *req, DHCPMessage *message) {
|
||||
int r;
|
||||
|
||||
assert(req);
|
||||
assert(message);
|
||||
|
||||
@@ -64,41 +62,26 @@ static int ensure_sane_request(sd_dhcp_server *server, DHCPRequest *req, DHCPMes
|
||||
if (message->hlen > sizeof(message->chaddr))
|
||||
return -EBADMSG;
|
||||
|
||||
/* set client id based on MAC address if client did not send an explicit one */
|
||||
if (!sd_dhcp_client_id_is_set(&req->client_id)) {
|
||||
if (!client_id_data_size_is_valid(message->hlen))
|
||||
return -EBADMSG;
|
||||
req->hw_addr.length = req->message->hlen;
|
||||
memcpy_safe(req->hw_addr.bytes, message->chaddr, message->hlen);
|
||||
|
||||
r = sd_dhcp_client_id_set(&req->client_id, /* type= */ 1, message->chaddr, message->hlen);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
/* Fake client ID generated from the DHCP header.
|
||||
* The client ID type 0 and 255 are special. So do not use if htype is 0 or 255.
|
||||
* Note, Some hardware type (e.g. Infiniband) may not set chaddr field. */
|
||||
if (!IN_SET(req->message->htype, 0, UINT8_MAX))
|
||||
(void) sd_dhcp_client_id_set(
|
||||
&req->client_id_by_header,
|
||||
req->message->htype,
|
||||
req->message->chaddr,
|
||||
req->message->hlen);
|
||||
|
||||
if (message->hlen == 0 || memeqzero(message->chaddr, message->hlen)) {
|
||||
uint8_t type;
|
||||
const void *data;
|
||||
size_t size;
|
||||
/* If Client Identifier option is unspecified, use the generated one. */
|
||||
if (!sd_dhcp_client_id_is_set(&req->client_id))
|
||||
req->client_id = req->client_id_by_header;
|
||||
|
||||
/* See RFC2131 section 4.1.1.
|
||||
* hlen and chaddr may not be set for non-ethernet interface.
|
||||
* Let's try to retrieve it from the client ID. */
|
||||
|
||||
if (!sd_dhcp_client_id_is_set(&req->client_id))
|
||||
return -EBADMSG;
|
||||
|
||||
r = sd_dhcp_client_id_get(&req->client_id, &type, &data, &size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (type != 1)
|
||||
return -EBADMSG;
|
||||
|
||||
if (size > sizeof(message->chaddr))
|
||||
return -EBADMSG;
|
||||
|
||||
memcpy(message->chaddr, data, size);
|
||||
message->hlen = size;
|
||||
}
|
||||
/* We manage bound leases by client ID. Hence, at least one of them is necessary. */
|
||||
if (!sd_dhcp_client_id_is_set(&req->client_id))
|
||||
return -EBADMSG;
|
||||
|
||||
if (req->max_optlen < DHCP_MIN_OPTIONS_SIZE)
|
||||
req->max_optlen = DHCP_MIN_OPTIONS_SIZE;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "dhcp-client-id-internal.h"
|
||||
#include "dhcp-protocol.h"
|
||||
#include "ether-addr-util.h"
|
||||
#include "sd-forward.h"
|
||||
#include "sparse-endian.h"
|
||||
#include "time-util.h"
|
||||
@@ -10,10 +11,13 @@
|
||||
typedef struct DHCPRequest {
|
||||
/* received message */
|
||||
DHCPMessage *message;
|
||||
/* sender hardware address, may not be set for non-ethernet interface */
|
||||
struct hw_addr_data hw_addr;
|
||||
triple_timestamp timestamp;
|
||||
|
||||
/* options */
|
||||
sd_dhcp_client_id client_id;
|
||||
sd_dhcp_client_id client_id_by_header;
|
||||
size_t max_optlen;
|
||||
be32_t server_id;
|
||||
be32_t requested_ip;
|
||||
|
||||
@@ -44,8 +44,7 @@ static int server_acquire_raw_socket(sd_dhcp_server *server) {
|
||||
|
||||
static int dhcp_server_send_unicast_raw(
|
||||
sd_dhcp_server *server,
|
||||
uint8_t hlen,
|
||||
const uint8_t *chaddr,
|
||||
const struct hw_addr_data *hw_addr,
|
||||
DHCPPacket *packet,
|
||||
size_t len) {
|
||||
|
||||
@@ -54,8 +53,7 @@ static int dhcp_server_send_unicast_raw(
|
||||
assert(server);
|
||||
assert(server->ifindex > 0);
|
||||
assert(server->address != 0);
|
||||
assert(hlen > 0);
|
||||
assert(chaddr);
|
||||
assert(hw_addr);
|
||||
assert(packet);
|
||||
assert(len > sizeof(DHCPPacket));
|
||||
|
||||
@@ -81,10 +79,10 @@ static int dhcp_server_send_unicast_raw(
|
||||
.ll.sll_family = AF_PACKET,
|
||||
.ll.sll_protocol = htobe16(ETH_P_IP),
|
||||
.ll.sll_ifindex = server->ifindex,
|
||||
.ll.sll_halen = hlen,
|
||||
.ll.sll_halen = hw_addr->length,
|
||||
};
|
||||
|
||||
memcpy(sa.ll.sll_addr, chaddr, hlen);
|
||||
memcpy_safe(sa.ll.sll_addr, hw_addr->bytes, hw_addr->length);
|
||||
|
||||
struct msghdr mh = {
|
||||
.msg_name = &sa.sa,
|
||||
@@ -192,7 +190,7 @@ static int dhcp_server_send_message(
|
||||
* InfiniBand. In that case, we cannot unicast in the below, so need to broadcast. Also, broadcast
|
||||
* the message if 'yiaddr' is zero.) */
|
||||
if (FLAGS_SET(be16toh(req->message->flags), 0x8000) ||
|
||||
req->message->hlen == 0 || memeqzero(req->message->chaddr, req->message->hlen) ||
|
||||
hw_addr_is_null(&req->hw_addr) ||
|
||||
packet->dhcp.yiaddr == INADDR_ANY)
|
||||
return dhcp_server_send_udp(
|
||||
server,
|
||||
@@ -205,8 +203,7 @@ static int dhcp_server_send_message(
|
||||
* unicasts DHCPOFFER and DHCPACK messages to the client’s hardware address and ’yiaddr’ address. */
|
||||
return dhcp_server_send_unicast_raw(
|
||||
server,
|
||||
req->message->hlen,
|
||||
req->message->chaddr,
|
||||
&req->hw_addr,
|
||||
packet,
|
||||
sizeof(DHCPPacket) + optoffset);
|
||||
}
|
||||
@@ -269,7 +266,7 @@ static int server_message_init(
|
||||
|
||||
r = dhcp_message_init(&packet->dhcp, BOOTREPLY,
|
||||
be32toh(req->message->xid),
|
||||
req->message->htype, req->message->hlen, req->message->chaddr,
|
||||
req->message->htype, req->hw_addr.length, req->hw_addr.bytes,
|
||||
type, req->max_optlen, &optoffset);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -534,28 +531,23 @@ int server_send_nak_or_ignore(sd_dhcp_server *server, bool init_reboot, DHCPRequ
|
||||
return DHCP_NAK;
|
||||
}
|
||||
|
||||
static int server_send_forcerenew(
|
||||
static int dhcp_server_send_forcerenew(
|
||||
sd_dhcp_server *server,
|
||||
be32_t address,
|
||||
be32_t gateway,
|
||||
uint8_t htype,
|
||||
uint8_t hlen,
|
||||
const uint8_t *chaddr) {
|
||||
sd_dhcp_server_lease *lease) {
|
||||
|
||||
_cleanup_free_ DHCPPacket *packet = NULL;
|
||||
size_t optoffset = 0;
|
||||
int r;
|
||||
|
||||
assert(server);
|
||||
assert(address != INADDR_ANY);
|
||||
assert(chaddr);
|
||||
assert(lease);
|
||||
|
||||
packet = malloc0(sizeof(DHCPPacket) + DHCP_MIN_OPTIONS_SIZE);
|
||||
if (!packet)
|
||||
return -ENOMEM;
|
||||
|
||||
r = dhcp_message_init(&packet->dhcp, BOOTREPLY, 0,
|
||||
htype, hlen, chaddr, DHCP_FORCERENEW,
|
||||
lease->htype, lease->hw_addr.length, lease->hw_addr.bytes, DHCP_FORCERENEW,
|
||||
DHCP_MIN_OPTIONS_SIZE, &optoffset);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -565,7 +557,7 @@ static int server_send_forcerenew(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return dhcp_server_send_udp(server, address, DHCP_PORT_CLIENT,
|
||||
return dhcp_server_send_udp(server, lease->address, DHCP_PORT_CLIENT,
|
||||
&packet->dhcp,
|
||||
sizeof(DHCPMessage) + optoffset);
|
||||
}
|
||||
@@ -579,8 +571,6 @@ int sd_dhcp_server_forcerenew(sd_dhcp_server *server) {
|
||||
log_dhcp_server(server, "FORCERENEW");
|
||||
|
||||
HASHMAP_FOREACH(lease, server->bound_leases_by_client_id)
|
||||
RET_GATHER(r,
|
||||
server_send_forcerenew(server, lease->address, lease->gateway,
|
||||
lease->htype, lease->hlen, lease->chaddr));
|
||||
RET_GATHER(r, dhcp_server_send_forcerenew(server, lease));
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -27,10 +27,10 @@ static int add_lease(sd_dhcp_server *server, const struct in_addr *server_addres
|
||||
*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 },
|
||||
.hw_addr.length = ETH_ALEN,
|
||||
.hw_addr.bytes = { 3, 3, 3, 3, 3, 3, },
|
||||
.expiration = usec_add(now(CLOCK_BOOTTIME), USEC_PER_DAY),
|
||||
.gateway = server_address->s_addr,
|
||||
.hlen = ETH_ALEN,
|
||||
.htype = ARPHRD_ETHER,
|
||||
|
||||
.client_id.size = 2,
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "iovec-util.h"
|
||||
#include "json-util.h"
|
||||
#include "mkdir.h"
|
||||
#include "string-util.h"
|
||||
#include "tmpfile-util.h"
|
||||
|
||||
static sd_dhcp_server_lease* dhcp_server_lease_free(sd_dhcp_server_lease *lease) {
|
||||
@@ -103,12 +102,11 @@ int dhcp_server_set_lease(sd_dhcp_server *server, be32_t address, DHCPRequest *r
|
||||
.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);
|
||||
lease->hw_addr = req->hw_addr;
|
||||
|
||||
if (req->hostname) {
|
||||
lease->hostname = strdup(req->hostname);
|
||||
@@ -146,27 +144,17 @@ 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) {
|
||||
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)
|
||||
goto verify;
|
||||
|
||||
/* 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;
|
||||
|
||||
static_lease = hashmap_get(server->static_leases_by_client_id, &client_id);
|
||||
if (!static_lease && sd_dhcp_client_id_is_set(&req->client_id_by_header))
|
||||
/* when no lease is found, fall back to use the fake client ID generated from the header. */
|
||||
static_lease = hashmap_get(server->static_leases_by_client_id, &req->client_id_by_header);
|
||||
if (!static_lease)
|
||||
return NULL;
|
||||
|
||||
verify:
|
||||
/* Check if the address is in the same subnet. */
|
||||
if ((static_lease->address & server->netmask) != server->subnet)
|
||||
return NULL;
|
||||
@@ -247,8 +235,8 @@ static int dhcp_server_lease_build_json(sd_dhcp_server_lease *lease, sd_json_var
|
||||
JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL("Address", &(struct in_addr) { .s_addr = lease->address }),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("Hostname", lease->hostname),
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("HardwareAddressType", lease->htype),
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("HardwareAddressLength", lease->hlen),
|
||||
SD_JSON_BUILD_PAIR_BYTE_ARRAY("HardwareAddress", lease->chaddr, sizeof(lease->chaddr)));
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("HardwareAddressLength", lease->hw_addr.length),
|
||||
SD_JSON_BUILD_PAIR_BYTE_ARRAY("HardwareAddress", lease->hw_addr.bytes, lease->hw_addr.length));
|
||||
}
|
||||
|
||||
int dhcp_server_bound_leases_append_json(sd_dhcp_server *server, sd_json_variant **v) {
|
||||
@@ -376,70 +364,67 @@ int dhcp_server_save_leases(sd_dhcp_server *server) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int json_dispatch_chaddr(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) {
|
||||
uint8_t* address = ASSERT_PTR(userdata);
|
||||
_cleanup_(iovec_done) struct iovec iov = {};
|
||||
int r;
|
||||
typedef struct LeaseParam {
|
||||
sd_dhcp_client_id client_id;
|
||||
uint8_t htype;
|
||||
uint8_t hlen;
|
||||
struct iovec hw_addr;
|
||||
struct in_addr address;
|
||||
usec_t exp_b;
|
||||
usec_t exp_r;
|
||||
char *hostname;
|
||||
} LeaseParam;
|
||||
|
||||
r = json_dispatch_byte_array_iovec(name, variant, flags, &iov);
|
||||
if (r < 0)
|
||||
return r;
|
||||
static void lease_param_done(LeaseParam *p) {
|
||||
assert(p);
|
||||
|
||||
if (iov.iov_len != 16)
|
||||
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is array of unexpected size.", strna(name));
|
||||
|
||||
memcpy(address, iov.iov_base, iov.iov_len);
|
||||
return 0;
|
||||
iovec_done(&p->hw_addr);
|
||||
free(p->hostname);
|
||||
}
|
||||
|
||||
static int json_dispatch_dhcp_lease(sd_dhcp_server *server, sd_json_variant *v, bool use_boottime) {
|
||||
static const sd_json_dispatch_field dispatch_table_boottime[] = {
|
||||
{ "ClientId", SD_JSON_VARIANT_ARRAY, json_dispatch_client_id, offsetof(sd_dhcp_server_lease, client_id), SD_JSON_MANDATORY },
|
||||
{ "Address", SD_JSON_VARIANT_ARRAY, json_dispatch_in_addr, offsetof(sd_dhcp_server_lease, address), SD_JSON_MANDATORY },
|
||||
{ "Hostname", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(sd_dhcp_server_lease, hostname), 0 },
|
||||
{ "HardwareAddressType", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint8, offsetof(sd_dhcp_server_lease, htype), 0 },
|
||||
{ "HardwareAddressLength", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint8, offsetof(sd_dhcp_server_lease, hlen), 0 },
|
||||
{ "HardwareAddress", SD_JSON_VARIANT_ARRAY, json_dispatch_chaddr, offsetof(sd_dhcp_server_lease, chaddr), 0 },
|
||||
{ "ExpirationUSec", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(sd_dhcp_server_lease, expiration), SD_JSON_MANDATORY },
|
||||
{ "ExpirationRealtimeUSec", _SD_JSON_VARIANT_TYPE_INVALID, NULL, 0, SD_JSON_MANDATORY },
|
||||
{}
|
||||
}, dispatch_table_realtime[] = {
|
||||
{ "ClientId", SD_JSON_VARIANT_ARRAY, json_dispatch_client_id, offsetof(sd_dhcp_server_lease, client_id), SD_JSON_MANDATORY },
|
||||
{ "Address", SD_JSON_VARIANT_ARRAY, json_dispatch_in_addr, offsetof(sd_dhcp_server_lease, address), SD_JSON_MANDATORY },
|
||||
{ "Hostname", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(sd_dhcp_server_lease, hostname), 0 },
|
||||
{ "HardwareAddressType", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint8, offsetof(sd_dhcp_server_lease, htype), 0 },
|
||||
{ "HardwareAddressLength", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint8, offsetof(sd_dhcp_server_lease, hlen), 0 },
|
||||
{ "HardwareAddress", SD_JSON_VARIANT_ARRAY, json_dispatch_chaddr, offsetof(sd_dhcp_server_lease, chaddr), 0 },
|
||||
{ "ExpirationUSec", _SD_JSON_VARIANT_TYPE_INVALID, NULL, 0, SD_JSON_MANDATORY },
|
||||
{ "ExpirationRealtimeUSec", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(sd_dhcp_server_lease, expiration), SD_JSON_MANDATORY },
|
||||
static const sd_json_dispatch_field dispatch_table[] = {
|
||||
{ "ClientId", SD_JSON_VARIANT_ARRAY, json_dispatch_client_id, offsetof(LeaseParam, client_id), SD_JSON_MANDATORY },
|
||||
{ "HardwareAddressType", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint8, offsetof(LeaseParam, htype), 0 },
|
||||
{ "HardwareAddressLength", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint8, offsetof(LeaseParam, hlen), 0 },
|
||||
{ "HardwareAddress", SD_JSON_VARIANT_ARRAY, json_dispatch_byte_array_iovec, offsetof(LeaseParam, hw_addr), 0 },
|
||||
{ "Address", SD_JSON_VARIANT_ARRAY, json_dispatch_in_addr, offsetof(LeaseParam, address), SD_JSON_MANDATORY },
|
||||
{ "AddressString", SD_JSON_VARIANT_STRING, NULL, 0, 0 },
|
||||
{ "ExpirationUSec", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(LeaseParam, exp_b), SD_JSON_MANDATORY },
|
||||
{ "ExpirationRealtimeUSec", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(LeaseParam, exp_r), SD_JSON_MANDATORY },
|
||||
{ "Hostname", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(LeaseParam, hostname), 0 },
|
||||
{}
|
||||
};
|
||||
|
||||
_cleanup_(sd_dhcp_server_lease_unrefp) sd_dhcp_server_lease *lease = NULL;
|
||||
usec_t now_b;
|
||||
int r;
|
||||
|
||||
assert(server);
|
||||
assert(v);
|
||||
|
||||
lease = new(sd_dhcp_server_lease, 1);
|
||||
if (!lease)
|
||||
return -ENOMEM;
|
||||
|
||||
*lease = (sd_dhcp_server_lease) {
|
||||
.n_ref = 1,
|
||||
};
|
||||
|
||||
r = sd_json_dispatch(v, use_boottime ? dispatch_table_boottime : dispatch_table_realtime, SD_JSON_ALLOW_EXTENSIONS, lease);
|
||||
_cleanup_(lease_param_done) LeaseParam p = {};
|
||||
r = sd_json_dispatch(v, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, &p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (p.hlen > HW_ADDR_MAX_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
if (p.hlen > p.hw_addr.iov_len)
|
||||
return -EINVAL;
|
||||
|
||||
if (!in4_addr_is_set(&p.address))
|
||||
return -EINVAL;
|
||||
|
||||
if (!sd_dhcp_client_id_is_set(&p.client_id))
|
||||
return -EINVAL;
|
||||
|
||||
usec_t now_b;
|
||||
r = sd_event_now(server->event, CLOCK_BOOTTIME, &now_b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (use_boottime) {
|
||||
if (lease->expiration < now_b)
|
||||
if (p.exp_b < now_b)
|
||||
return 0; /* already expired */
|
||||
} else {
|
||||
usec_t now_r;
|
||||
@@ -448,12 +433,29 @@ static int json_dispatch_dhcp_lease(sd_dhcp_server *server, sd_json_variant *v,
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (lease->expiration < now_r)
|
||||
if (p.exp_r < now_r)
|
||||
return 0; /* already expired */
|
||||
|
||||
lease->expiration = map_clock_usec_raw(lease->expiration, now_r, now_b);
|
||||
p.exp_b = map_clock_usec_raw(p.exp_r, now_r, now_b);
|
||||
}
|
||||
|
||||
_cleanup_(sd_dhcp_server_lease_unrefp) sd_dhcp_server_lease *lease = new(sd_dhcp_server_lease, 1);
|
||||
if (!lease)
|
||||
return -ENOMEM;
|
||||
|
||||
*lease = (sd_dhcp_server_lease) {
|
||||
.n_ref = 1,
|
||||
|
||||
.client_id = p.client_id,
|
||||
.htype = p.htype,
|
||||
.hw_addr.length = p.hlen,
|
||||
.address = p.address.s_addr,
|
||||
.expiration = p.exp_b,
|
||||
.hostname = TAKE_PTR(p.hostname),
|
||||
};
|
||||
|
||||
memcpy_safe(lease->hw_addr.bytes, p.hw_addr.iov_base, p.hlen);
|
||||
|
||||
r = dhcp_server_put_lease(server, lease, /* is_static= */ false);
|
||||
if (r == -EEXIST)
|
||||
return 0;
|
||||
|
||||
@@ -152,8 +152,9 @@ TEST(dhcp_server_handle_message) {
|
||||
test.header.op = BOOTREQUEST;
|
||||
ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_OFFER);
|
||||
|
||||
/* Neither client ID nor hardware type is set. There is no way to manage the bound lease for the request. */
|
||||
test.header.htype = 0;
|
||||
ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_OFFER);
|
||||
ASSERT_ERROR(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), EBADMSG);
|
||||
test.header.htype = ARPHRD_ETHER;
|
||||
ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_OFFER);
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ static int property_get_leases(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append_array(reply, 'y', &lease->chaddr, sizeof(lease->chaddr));
|
||||
r = sd_bus_message_append_array(reply, 'y', &lease->hw_addr.bytes, lease->hw_addr.length);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user