DHCPv6 addresses sent with duplicate zero lifetimes
Describe the bug
Kea dhcpv6 will sometimes renew leases with a duplicate zero-lifetime address. My client interprets this as a valid lease without an IP address. The client-side symptom is that the IPv6 address isn't picked up.
To Reproduce
This is difficult to reproduce. I think it's related to load balancing: I've only seen it when load balancing is enabled. I have seen it with a debugger enabled and I know that Kea is failing to delete addresses with a 128-bit prefix because the hints are being stored with a 0-bit prefix. It's specific to the DHCPv6 address assignment.
Expected behavior
There should only be one address field with the correct lifetime.
Environment:
- Kea version: 2.0.3 from git
- OS: Custom linux with 4.14.266 kernel
- Which features were compiled in (in particular which backends) log4cplus, openssl, pgsql
- If/which hooks where loaded in lease_cmds, ha-hooks
Additional Information
Here's a patch that works for me. It's surely not the best way to fix the problem but it's the best I can manage. It ensures that the prefix length of the object to delete matches the prefix length of the stored object. In effect, the erase works only on the IP address.
diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc
index 1ca9a7c393..8c60f2eab8 100644
--- a/src/bin/dhcp6/dhcp6_srv.cc
+++ b/src/bin/dhcp6/dhcp6_srv.cc
@@ -2398,6 +2398,14 @@ Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query,
// Now remove this prefix from the hints list.
AllocEngine::Resource hint_type((*l)->addr_, (*l)->prefixlen_);
+ // Find the entry we want to match
+ for (AllocEngine::HintContainer::const_iterator hint = hints.begin();
+ hint != hints.end(); ++hint) {
+ if (hint->getAddress() == (*l)->addr_) {
+ hint_type = AllocEngine::Resource((*l)->addr_,
+ hint->getPrefixLength());
+ }
+ }
hints.erase(std::remove(hints.begin(), hints.end(), hint_type),
hints.end());
}
Here are some logs
2023-08-01 09:41:44.332 DEBUG [kea-dhcp6.packets/7977.140638832015232] DHCP6_BUFFER_RECEIVED received buffer from fe80::a00:27ff:fe9c:987d:546 to ff02::1:2:0 over interface eth1
2023-08-01 09:41:44.334 DEBUG [kea-dhcp6.packets/7977.140638832015232] DHCP6_PACKET_RECEIVED duid=[00:01:00:01:28:d2:6e:d5:08:00:27:84:e4:fc], tid=0xb1506a: RENEW (type 5) received from fe80::a00:27ff:fe9c:987d to ff02::1:2 on interface eth1
2023-08-01 09:41:44.334 DEBUG [kea-dhcp6.packets/7977.140638832015232] DHCP6_QUERY_DATA duid=[00:01:00:01:28:d2:6e:d5:08:00:27:84:e4:fc], tid=0xb1506a, packet details: localAddr=[ff02::1:2]:0 remoteAddr=[fe80::a00:27ff:fe9c:987d]:546 msgtype=5(RENEW), transid=0xb1506a type=00001, len=00014: 00:01:00:01:28:d2:6e:d5:08:00:27:84:e4:fc type=00002, len=00014: 00:01:00:01:2c:1e:f1:31:08:00:27:4f:6f:41 type=00003(IA_NA), len=00040: iaid=664574077, t1=3600, t2=5400, options: type=00005(IAADDR), len=00024: address=fd70:b66a:8bf6::1800, preferred-lft=7200, valid-lft=7500 type=00006, len=00010: 23(uint16) 24(uint16) 39(uint16) 31(uint16) 17(uint16) type=00008, len=00002: 0 (uint16) No relays traversed.
2023-08-01 09:41:44.334 DEBUG [kea-dhcp6.packets/7977.140638832015232] DHCP6_SUBNET_SELECTED duid=[00:01:00:01:28:d2:6e:d5:08:00:27:84:e4:fc], tid=0xb1506a: the subnet with ID 1 was selected for client assignments
2023-08-01 09:41:44.334 DEBUG [kea-dhcp6.packets/7977.140638832015232] DHCP6_SUBNET_DATA duid=[00:01:00:01:28:d2:6e:d5:08:00:27:84:e4:fc], tid=0xb1506a: the selected subnet details: fd70:b66a:8bf6::/64
2023-08-01 09:41:44.341 DEBUG [kea-dhcp6.leases/7977.140638832015232] DHCP6_PROCESS_IA_NA_EXTEND duid=[00:01:00:01:28:d2:6e:d5:08:00:27:84:e4:fc], tid=0xb1506a: extending lease lifetime for IA_NA option with iaid=664574077
2023-08-01 09:41:44.347 INFO [kea-dhcp6.leases/7977.140638832015232] DHCP6_LEASE_RENEW duid=[00:01:00:01:28:d2:6e:d5:08:00:27:84:e4:fc], tid=0xb1506a: lease for address fd70:b66a:8bf6::1800 and iaid=664574077 has been allocated
2023-08-01 09:41:44.371 DEBUG [kea-dhcp6.packets/7977.140638832015232] DHCP6_PACKET_SEND duid=[00:01:00:01:28:d2:6e:d5:08:00:27:84:e4:fc], tid=0xb1506a: trying to send packet REPLY (type 7) from [ff02::1:2]:547 to [fe80::a00:27ff:fe9c:987d]:546 on interface eth1
2023-08-01 09:41:44.374 DEBUG [kea-dhcp6.packets/7977.140638832015232] DHCP6_RESPONSE_DATA responding with packet type 7 data is localAddr=[ff02::1:2]:547 remoteAddr=[fe80::a00:27ff:fe9c:987d]:546 msgtype=7(REPLY), transid=0xb1506a type=00001, len=00014: 00:01:00:01:28:d2:6e:d5:08:00:27:84:e4:fc type=00002, len=00014: 00:01:00:01:2c:1e:f1:31:08:00:27:4f:6f:41 type=00003(IA_NA), len=00040: iaid=664574077, t1=720, t2=1152, options: type=00005(IAADDR), len=00024: address=fd70:b66a:8bf6::1800, preferred-lft=1440, valid-lft=1440 No relays traversed.
I also have a hint copied from gdb showing the zero prefix length and valid lifetime
$16 = {address_ = {asio_address_ = {type_ = boost::asio::ip::address::ipv6,
ipv4_address_ = {addr_ = {s_addr = 0}}, ipv6_address_ = {addr_ = {
__in6_u = {
__u6_addr8 = "\375\301p\213.o\000\000\000\000\000\000\000\000\031",
__u6_addr16 = {49661, 35696, 28462, 0, 0, 0, 0, 25}, __u6_addr32 = {
2339422717, 28462, 0, 1638400}}}, scope_id_ = 0}}},
prefix_len_ = 0 '\000', preferred_ = 0, valid_ = 0}
Contacting you
The github email will be fine