summaryrefslogtreecommitdiff
path: root/src/libsystemd-network
diff options
context:
space:
mode:
authorRobert Meijers <systemd@robert.meijers.dev>2023-04-17 22:16:05 +0200
committerYu Watanabe <watanabe.yu+github@gmail.com>2023-04-20 19:18:50 +0900
commit4646cdaa378fa2aab7334a80228d8a94b316763b (patch)
tree11cb85089d02f9a7505be73f715cba056b77d688 /src/libsystemd-network
parent114e85d28e9543e39d25414475c3f7e70a6fcbbb (diff)
downloadsystemd-4646cdaa378fa2aab7334a80228d8a94b316763b.tar.gz
networkd: fallback to chaddr for static lease lookup when not found
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 #21368
Diffstat (limited to 'src/libsystemd-network')
-rw-r--r--src/libsystemd-network/sd-dhcp-server.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
index 05c0cddfd0..55290ee0f1 100644
--- a/src/libsystemd-network/sd-dhcp-server.c
+++ b/src/libsystemd-network/sd-dhcp-server.c
@@ -1061,6 +1061,40 @@ 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;
+
+ assert(server);
+ assert(req);
+ assert(ret);
+
+ static_lease = hashmap_get(server->static_leases_by_client_id, &req->client_id);
+ if (static_lease) {
+ *ret = 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);
+
+ static_lease = hashmap_get(server->static_leases_by_client_id,
+ &(DHCPClientId) {
+ .length = req->message->hlen + 1,
+ .data = data,
+ });
+
+ *ret = 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) {
@@ -1092,7 +1126,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) {