
(Kea lease allocation, client classification and option assignment)
Created: 2020-10-14 Wed 10:40


























VENDOR_CLASS_ and
the result is interpreted as a class
docsis3.0, so the packet belongs to class
VENDOR_CLASS_docsis3.0

"shared-networks": [
{
"name": "kea-net01",
"relay": { "ip-address": "192.0.2.1" },
"subnet4": [
{
"subnet": "192.0.2.0/24",
"client-class": "VENDOR_CLASS_windowsCE", # <-- Windows CE Clients will get
# an IP from this subnet
"option-data": [{
"name": "routers", "data": "192.0.2.1" }],
"pools": [{
"pool": "192.0.2.60 - 192.0.2.220" }]
},
{
"subnet": "10.0.0.0/24",
"client-class": "VENDOR_CLASS_fedoraLinux", # <-- Fedora-Linux Clients will
# get an IP from this subnet
"option-data": [
[...]


KNOWN classUNKNOWN class
{
"client-classes": [{
"name": "dependent-class",
"test": "member('KNOWN')",
"only-if-required": true
}]
}






"Dhcp4": {
"client-classes": [
{ "name": "windows",
"test": "substring(option[60].hex,0,3) == 'win'",
"option-data": [{
"name": "domain-name", "data": "win.example.com" }]
},
{ "name": "other",
"test": "not(substring(option[60].hex,0,3) == 'win')",
"option-data": [{
"name": "domain-name", "data": "other.example.com" }]
}
],
[...]


"shared-networks": [
{
"name": "kea-lab01",
"relay": { "ip-address": "192.0.2.1" },
"subnet4": [
{
"subnet": "192.0.2.0/24",
"client-class": "windows", # <-- all Windows Clients will
# get IP addresses from this subnet
"option-data": [{
"name": "routers", "data": "192.0.2.1" }],
"pools": [{
"pool": "192.0.2.60 - 192.0.2.250" }]
},
{
"subnet": "10.0.0.0/24",
"client-class": "other", # <-- non Windows Clients will
# get IP addresses from this subnet
"option-data": [
[...]




[kea-server]# systemctl stop kea-dhcp4 [kea-server]# kea-dhcp4 -d -c /etc/kea/kea-dhcp4.conf


kea-dhcp4.eval or
kea-dhcp6.eval debug logger in the Kea configuration file
"Logging": {
"loggers": [ {
"name": "kea-dhcp4.eval",
"output_options": [ {
"output": "/var/log/kea-dhcp4-eval.log"
} ],
"severity": "DEBUG",
"debuglevel": 55
} ]
}


[kea-server]# tail -f /var/log/kea-dhcp4-eval.log






"Dhcp4": {
"option-data": [{
"name": "domain-name-servers",
"code": 6,
"space": "dhcp4",
"csv-format": true,
"data": "192.0.2.1, 192.0.2.2"
},
...
]}


code, space and
csv-format can be obmitted
"Dhcp4": {
"option-data": [{
"name": "domain-name-servers",
"data": "192.0.2.1, 192.0.2.2"
},
...
]}


[...]
"subnet4": [ {
"subnet": "192.0.2.0/24",
"pools": [ { "pool": "192.0.2.100 - 192.0.2.200" } ],
"option-data": [{
"name": "routers",
"data": "192.0.2.1" },
{
"name": "domain-name",
"data": "a.example.com" }
]},
[...]


"client-classes": [{
"name": "Zimbutsio-Server",
"test": "option[vendor-class-identifier].text == 'Zimbutsio'",
"option-data": [ {
"name": "log-servers",
"data": "192.0.2.42"
}]
}],
[...]




{
"Dhcp4": {
"option-def": [{
"name": "my-message",
"code": 234,
"type": "string",
"array": false,
"record-types": "",
"space": "dhcp4",
"encapsulate": "" }],
"option-data": [{
"name": "my-message",
"space": "dhcp4",
"csv-format": true,
"data": "Hello World" }],
[...]














"Dhcp4:" {
# This specifies global reservations. They will apply to all subnets that
# have global reservations enabled.
"reservations": [
{ "hw-address": "aa:bb:cc:dd:ee:ff", "hostname": "hw-host-dynamic" },
{ "hw-address": "01:02:03:04:05:06", "hostname": "hw-host-fixed", "ip-address": "192.0.1.77" }, # risky!
{ "circuit-id": "'office042'", "hostname": "circuit-id-host" },
[...]








| Command | Description |
|---|---|
| reservation-add | add a new reservation to the Kea DB |
| reservation-get-all | get all reservation information (can be huge) |
| reservation-get | get information on a single reservation (by address or identifier) |
| reservation-get-page | get all reservation information from a subnet by pages (used for GUI display) |
| reservation-get-by-hostname | get the reservation information for one host by its hostname |
| reservation-get-by-id | get the reservation information for one host by its identifier (global, since 1.9.0) |
| reservation-del | delete a reservation from the database |


$ cat reservation-add.json
{
"command": "reservation-add",
"service": [ "dhcp6" ],
"arguments": {
"reservation": {
"duid": "01:02:03:04:05:06:07:08:09:0A",
"hostname": "foo.example.com",
"ip-addresses": [ "2001:db8:1::1" ],
"option-data": [{
"data": "4491",
"name": "vendor-opts"
},{
"data": "3000:1::234",
"name": "tftp-servers",
"space": "vendor-4491"
}],
"subnet-id": 1
}
}
}


curl command can be used to send the request towards the Kea
API
$ curl -s -X POST -H "Content-Type: application/json" \
-d @reservation-add.json http://127.0.0.1:8000/ | jq
[
{
"result": 0,
"text": "Host added."
}
]


$ cat reservation-get-all.json
{
"service": [
"dhcp6"
],
"command": "reservation-get-all",
"arguments": {
"subnet-id": 1
}
}
$ curl -s -X POST -H "Content-Type: application/json" \
-d @reservation-get-all.json http://127.0.0.1:8000/ | jq


[...]
"subnet4": [
{
"subnet": "10.0.0.0/24",
"pools": [ { "pool": "10.0.0.10-10.0.0.200" } ],
"reservations": [{
"hw-address": "01:02:03:04:05:06",
"client-classes": [ "windows", "staff" ]
}]
}],
[...]


reservation-mode configuration parameter
"Dhcp4": {
"subnet4": [{
"subnet": "192.0.2.0/24",
"reservation-mode": "disabled",
...
}]
}


| reservation-mode | description |
|---|---|
| all | reservations can be on global, subnet or inside pool scope, all checks enabled |
| out-of-pool | reservations in subnets are always outside the pool |
| global | only global reservations allowed, not subnet/pool reservations |
| disabled(*) | host reservation support is disabled, no checks for collisions |


hw-addressduidclient-idcircuit-idflex-id

host-reservation-identifiers takes a list of
identifier types that Kea will check
"host-reservation-identifiers": [ "circuit-id", "hw-address" ],
"subnet4": [{
"subnet": "192.0.2.0/24",
...
}]








[...]
"shared-networks": [
{
"name": "kea-lab01",
"relay": { "ip-address": "192.0.2.1" },
"subnet4": [{
"subnet": "192.0.2.0/24",
"option-data": [
{ "name": "routers", "data": "192.0.2.1" }],
"pools": [{ "pool": "192.0.2.20 - 192.0.2.190" }]
}, {
"subnet": "10.0.0.0/24",
"option-data": [
{ "name": "routers", "data": "10.0.0.1" }],
"pools": [{ "pool": "10.0.0.10 - 10.0.0.200" }]
}]
],
[...]










yq is a lightweight and portable command-line YAML processor:
https://mikefarah.gitbook.io/yqyq

yq tool can be used to convert if JSON file (or JSON coming
from STDIN via shell pipe) into YAML
$ yq r --prettyPrint add-reservation.json
service:
- dhcp6
command: reservation-add
arguments:
reservation:
subnet-id: 1
duid: 01:02:03:04:05:06:07:08:09:0A
ip-addresses:
- 2001:db8:1::1
hostname: foo.example.com
option-data:
- name: vendor-opts
data: "4491"
- name: tftp-servers
space: vendor-4491
data: 3000:1::234


yq also supports the reverse, converting YAML back to JSON
# yq r --prettyPrint -j add-reservation.yaml
{
"arguments": {
"reservation": {
"duid": "01:02:03:04:05:06:07:08:09:0A",
"hostname": "foo.example.com",
"ip-addresses": [
"2001:db8:1::1"
],
"option-data": [
{
"data": "4491",
"name": "vendor-opts"
},
{
"data": "3000:1::234",
"name": "tftp-servers",
"space": "vendor-4491"
}
],
"subnet-id": 1
}
},
"command": "reservation-add",
"service": [
"dhcp6"
]
}


kea-cmd can aid to convert YAML
command-files into JSON and send them to the DHCP server via the
Kea control channel
#!/bin/sh
curl -s -X POST -H "Content-Type: application/json" \
-d "$(yq r -j ${1})" http://127.0.0.1:8000/ | yq r -P -


successful command
# kea-cmd add-reservation.yaml - result: 0 text: Host added.
error case
# kea-cmd add-reservation.yaml - result: 1 text: specified reservation '2001:db8:1:cafe::1' is not matching the IPv6 subnet prefix '2001:db8:1::/64'


service:
- dhcp6
command: reservation-get-all
arguments:
subnet-id: 1
|
{
"service": [
"dhcp6"
],
"command": "reservation-get-all",
"arguments": {
"subnet-id": 1
}
}
|
