Bug #15032
closedKea DHCP sends wrong bootloader file for UEFI
100%
Description
I already posted this problem in the pfSense forum and was asked to report this issue here. Here is the link of the discussion thread:
https://forum.netgate.com/topic/184301/kea-dhcp-uefi-pxe-boot-sends-wrong-boot-file
I'm using netboot.xyz for network booting and I just switched to Kea DHCP. After the migration I noticed that network booting from UEFI bios does not work anymore, but legacy bios boot still does work.
Here are the configuration values I set in pfSense:
TFTP Server: IP of my netboot server
Next Server: IP of my netboot server
Default BIOS File Name: netboot.xyz.kpxe
UEFI 32 bit File Name: netboot.xyz.efi
UEFI 64 bit File Name: netboot.xyz.efi
ARM 64 bit File Name: netboot.xyz-arm64.efi
The Kea DHCP server always offers the default netboot.xyz.kpxe file to UEFI machines.
Here are the logs from Kea DHCP for an UEFI bios:
Nov 23 12:23:55 kea-dhcp4 14098 INFO [kea-dhcp4.dhcp4.0x3e2f2f5b9300] EVAL_RESULT Expression ipxe_64_lan_pool_0 evaluated to 1 Nov 23 12:23:55 kea-dhcp4 14098 INFO [kea-dhcp4.dhcp4.0x3e2f2f5b9300] EVAL_RESULT Expression ipxe_legacy_lan_pool_0 evaluated to 1 Nov 23 12:23:55 kea-dhcp4 14098 INFO [kea-dhcp4.dhcp4.0x3e2f2f5b9300] EVAL_RESULT Expression ipxe_64_lan evaluated to 1 Nov 23 12:23:55 kea-dhcp4 14098 INFO [kea-dhcp4.dhcp4.0x3e2f2f5b9300] EVAL_RESULT Expression ipxe_legacy_lan evaluated to 1 Nov 23 12:23:55 kea-dhcp4 14098 INFO [kea-dhcp4.leases.0x3e2f2f5b9300] DHCP4_LEASE_ALLOC [hwtype=1 46:15:16:cd:59:84], cid=[no info], tid=0xaccc68dd: lease 172.17.128.2 has been allocated for 86400 seconds Nov 23 12:23:55 kea-dhcp4 14098 INFO [kea-dhcp4.dhcpsrv.0x3e2f2f5b9300] EVAL_RESULT Expression pool_opt1_0 evaluated to 1 Nov 23 12:23:55 kea-dhcp4 14098 INFO [kea-dhcp4.dhcpsrv.0x3e2f2f5b9300] EVAL_RESULT Expression pool_lan_0 evaluated to 1
And here is the generated kea-dhcp4.conf file. (I just removed the reservations)
{ "Dhcp4": { "interfaces-config": { "interfaces": [ "mlxen0", "mlxen0.2" ] }, "lease-database": { "type": "memfile", "persist": true, "name": "/var/lib/kea/dhcp4.leases" }, "loggers": [ { "name": "kea-dhcp4", "output_options": [ { "output": "syslog" } ], "severity": "INFO" } ], "valid-lifetime": 7200, "max-valid-lifetime": 86400, "ip-reservations-unique": false, "echo-client-id": false, "option-data": [ { "name": "domain-name", "data": "mydomain" } ], "option-def": [ { "space": "dhcp4", "name": "ldap-server", "code": 95, "type": "string" } ], "hooks-libraries": [ { "library": "/usr/local/lib/kea/hooks/libdhcp_lease_cmds.so" } ], "control-socket": { "socket-type": "unix", "socket-name": "/tmp/kea4-ctrl-socket" }, "authoritative": true, "client-classes": [ { "name": "ipxe_32_lan_pool_0", "test": "option[93].hex == 0x0006", "only-if-required": true, "option-data": [ { "name": "boot-file-name", "data": "netboot.xyz.efi" } ] }, { "name": "ipxe_64_lan_pool_0", "test": "option[93].hex == 0x0007 or option[93].hex == 0x0009", "only-if-required": true, "option-data": [ { "name": "boot-file-name", "data": "netboot.xyz.efi" } ] }, { "name": "ipxe_64arm_lan_pool_0", "test": "option[93].hex == 0x000b", "only-if-required": true, "option-data": [ { "name": "boot-file-name", "data": "netboot.xyz-arm64.efi" } ] }, { "name": "ipxe_legacy_lan_pool_0", "test": "not member('ipxe_32_lan_pool_0') and not member('ipxe_64_lan_pool_0') and not member('ipxe_64arm_lan_pool_0')", "only-if-required": true, "option-data": [ { "name": "boot-file-name", "data": "netboot.xyz.kpxe" } ] }, { "name": "pool_lan_0", "test": "member('ALL')" }, { "name": "ipxe_32_lan", "test": "option[93].hex == 0x0006", "only-if-required": true, "option-data": [ { "name": "boot-file-name", "data": "netboot.xyz.efi" } ] }, { "name": "ipxe_64_lan", "test": "option[93].hex == 0x0007 or option[93].hex == 0x0009", "only-if-required": true, "option-data": [ { "name": "boot-file-name", "data": "netboot.xyz.efi" } ] }, { "name": "ipxe_64arm_lan", "test": "option[93].hex == 0x000b", "only-if-required": true, "option-data": [ { "name": "boot-file-name", "data": "netboot.xyz-arm64.efi" } ] }, { "name": "ipxe_legacy_lan", "test": "not member('ipxe_32_lan') and not member('ipxe_64_lan') and not member('ipxe_64arm_lan')", "only-if-required": true, "option-data": [ { "name": "boot-file-name", "data": "netboot.xyz.kpxe" } ] }, { "name": "pool_opt1_0", "test": "member('ALL')" } ], "subnet4": [ { "id": 1, "subnet": "172.17.0.0/16", "option-data": [ { "name": "domain-name", "data": "mydomain" }, { "name": "domain-search", "data": "mydomain" }, { "name": "domain-name-servers", "data": "172.17.1.1" }, { "name": "routers", "data": "172.17.1.1" }, { "name": "netbios-name-servers", "data": "172.17.2.1" }, { "name": "netbios-node-type", "data": "8" } ], "pools": [ { "pool": "172.17.128.0 - 172.17.128.199", "client-class": "pool_lan_0", "option-data": [ { "name": "domain-name-servers", "data": "172.17.1.1" }, { "name": "tftp-server-name", "data": "172.17.2.17" } ], "require-client-classes": [ "ipxe_legacy_lan_pool_0", "ipxe_32_lan_pool_0", "ipxe_64_lan_pool_0", "ipxe_64arm_lan_pool_0" ] } ], "valid-lifetime": 86400, "next-server": "172.17.2.17", "require-client-classes": [ "ipxe_legacy_lan", "ipxe_32_lan", "ipxe_64_lan", "ipxe_64arm_lan" ], "reservations-in-subnet": true }, { "id": 2, "subnet": "172.20.0.0/16", "option-data": [ { "name": "domain-name-servers", "data": "172.20.1.1" }, { "name": "routers", "data": "172.20.1.1" } ], "pools": [ { "pool": "172.20.128.0 - 172.20.128.255", "client-class": "pool_opt1_0", "option-data": [ { "name": "domain-name-servers", "data": "172.20.1.1" } ] } ], "valid-lifetime": 86400, "reservations-in-subnet": true } ] }
I noticed that the legacy classes in the require-client-classes are on top of all the other classes. After i changed the order so that the legacy classes are at the bottom netboot worked for legacy and UEFI boot.
I also created a patch file that fixes the problem in the services.inc file:
--- /etc/inc/services.inc.save 2023-11-24 15:19:26.797541000 +0100
+++ /etc/inc/services.inc 2023-11-24 15:24:17.000000000 +0100
@@ -1548,7 +1548,7 @@
if (!is_array($keapool['require-client-classes'])) {
$keapool['require-client-classes'] = [];
}
- array_unshift($keapool['require-client-classes'], $name);
+ $keapool['require-client-classes'][] = $name;
}
if (!empty($poolconf['rootpath'])) {
@@ -1719,7 +1719,7 @@
if (!is_array($keasubnet['require-client-classes'])) {
$keasubnet['require-client-classes'] = [];
}
- array_unshift($keasubnet['require-client-classes'], $name);
+ $keasubnet['require-client-classes'][] = $name;
}
if (!empty($dhcpifconf['rootpath'])) {
Can you please take a look at this if this is the correct solution to this problem?