Skip to content

Commit

Permalink
networkd: fallback to chaddr for static lease lookup when not found
Browse files Browse the repository at this point in the history
DHCP static leases are looked up by the client identifier as send by
the client, while configured based on MAC. As RFC 2131 states the client
identifier is an opaque key and must not be interpreted by the server
this means that DHCP clients can (/will) also use a client identifier
which is not a MAC address. One of these clients actually is
systemd-networkd which uses an RFC 4361 by default to generate the
client identifier. For these kind of DHCP clients static leases thus
don't work because of this mismatch between configuring a MAC address
but the server matching based on client identifier. This adds a fallback
to try to look up a configured static lease based on the "chaddr" of the
DHCP message as this will always contain the MAC address of the client.

Fixes systemd#21368
  • Loading branch information
RobertMe committed Apr 19, 2023
1 parent 5739271 commit 2d498bb
Showing 1 changed file with 36 additions and 1 deletion.
37 changes: 36 additions & 1 deletion src/libsystemd-network/sd-dhcp-server.c
Original file line number Diff line number Diff line change
Expand Up @@ -1061,6 +1061,39 @@ static bool address_available(sd_dhcp_server *server, be32_t address) {
return true;
}

static int server_get_static_lease(sd_dhcp_server *server, const DHCPRequest *req, DHCPLease **ret) {
DHCPLease *static_lease;
_cleanup_free_ uint8_t *data = NULL;

static_lease = hashmap_get(server->static_leases_by_client_id, &req->client_id);
if (static_lease) {
*ret = TAKE_PTR(static_lease);
return 0;
}

/* when no lease is found based on the client id fall back to chaddr */
data = new(uint8_t, req->message->hlen + 1);
if (!data)
return -ENOMEM;

/* set client id type to 1: Ethernet Link-Layer (RFC 2132) */
data[0] = 0x01;
memcpy(data + 1, req->message->chaddr, req->message->hlen);

DHCPClientId c;

c = (DHCPClientId) {
.length = req->message->hlen + 1,
.data = data,
};

static_lease = hashmap_get(server->static_leases_by_client_id, &c);

*ret = TAKE_PTR(static_lease);

return 0;
}

#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) {
Expand Down Expand Up @@ -1092,7 +1125,9 @@ 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 = hashmap_get(server->static_leases_by_client_id, &req->client_id);
r = server_get_static_lease(server, req, &static_lease);
if (r < 0)
return r;

switch (type) {

Expand Down

0 comments on commit 2d498bb

Please sign in to comment.