[kea-dev] Issues with static reservations using Client Id in DHCPv4
marcin at isc.org
Wed Dec 9 13:24:06 UTC 2015
Earlier this year we were implementing host reservations for Kea. The
basic work was completed but some major pieces were never implemented
because of time constraints, shift of priorities and schedule updates.
One of those features that are still outstanding is client-id based
reservation in DHCPv4. The framework was largely prepared for it (given
the similarity with DUID based reservations in v6), but it doesn't work
end to end. New tickets #4230 and #4229 are just a manifestation of this
deficiency and misunderstanding of the current state of host reservation
During the design phase of the host reservation features we made an
assumption that reservations can be made based on DUID or MAC address.
Moreover, the DUID was considered to be more suitable for reservations
in v6, because of the unavailability of the MAC address in many (most?)
cases. The MAC address based reservations seemed to be more frequently
used in v4 space, because of MAC address availability in DHCP messages
and many clients not adhering to RFC4361.
The advantage of using DUID based reservations in both cases (v4 and v6)
was an ability of a server's administrator to correlate v4 and v6 leases
acquired by a particular host. This seems to be common desire in dual
In DHCPv4, DUID is just one of the possible client identifiers conveyed
in the client identifier option, having the following format:
- code (1 byte)
- len (1 byte)
- type (1 byte)
- client-id (variable length)
RFC4361 specifies that clients construct client identifier in the
- code (1 byte)
- len (1 byte)
- type (1 byte) = 255
- IAID per interface (4 bytes)
- DUID (same as RFC3315)
The last two constitute 'client-id' within the client identifier option
format provided above.
In the light of this, current Kea code has major issues.
Kea uses entire client identifier option to compare against the DUID
specified in the reservation.
Let's assume that a client adheres to RFC4361 and constructs the client
- code = 61
- len = 16
- type = 255
- IAID = 0x01020304
- DUID-LL = 0x0003 0x0001 0x13234353637383
Let's also assume that server administrator has created static
reservation for this client using its DUID:
Currently, when the server receives client identifier option, it will
remove the code and length fields and use the rest of the contents to
compare with a DUID in the reservation:
This is clearly wrong (you can see the difference between the two),
unless we assume that the administrator must specify the entire contents
of the client-id option when it makes a reservation. But, should this
still be called reservation by DUID?
One way to address this issue is to modify the server / allocation
engine code to detect that the client identifier received holds a DUID,
rather than anything else. This can be easily done for the valid client
idenitifier, with Type set to 255. The server should only use the
portion of the client identifier past IAID to search for the reservation
in the reservations database. This should be a simple change and it
wouldn't require any changes to the Host class in libdhcpsrv to hold any
other type of client identification information than DUID. Note that the
Host object, representing static reservation, holds the DuidPtr which is
by definition capable of holding a DUID, rather than full client identifier.
There is a down side, though. Some deployments may (and probably will)
want to make reservations based on other types of client identifiers. In
addition, even if someone wants to do DUID based reservation he may also
want to explicitly specify IAID, being a part of the client identifier
and that IAID may vary by client's interface. In that case it seems
useful to (also) have ability to make reservation by full client
identifier. In our case:
But, this brings additional complexity. First, configuration parser for
host reservations doesn't support "client-id" parameter (only "duid"
parameter). But, this is easy to fix. Second, the host reservation data
structure and API are not really prepared to store full client id.
One, sort of hackish, way to do it would be to use the current data
structures in Host object (use DuidPtr as storage for client id or
DUID), and the following logic on the server side to find a reservation:
- Server checks if the client identifier option holds a DUID (check if
Type 255) and if it does, extract the DUID from this option and use it
as an input to obtain reservation
- If the above returns no results, use the whole client identifier
option as an input to obtain reservations.
- If second step returns no results too, assume that there is no
client-id or DUID based reservation.
The glaring part of this solution is that it makes use of DUID object to
potentially store the full client identifier, which is not really a
DUID, right? In fact, the DUID is just a part of client identifier. On
the other hand, if you take a look at our libdhcp++ implementation the
ClientId object (probably not rightly) already derives from DUID, so we
have crossed the line long time ago.
Alternative solution is to reorganize the Host class to make "full
client identifier" a separate identifier type and possible extend the
Host object API to accommodate queries by "client-id" apart from those
Now, I expect tomatoes flying over my head, but this is something that
has to be resolved nevertheless.
DHCP Software Engineer
More information about the kea-dev