[Dnsmasq-discuss] [PATCH] dhcp_release6: the fixed part of an IA_NA is 12 bytes, not 24.
m.dmitrichenko222 at gmail.com
m.dmitrichenko222 at gmail.com
Mon Sep 21 10:56:12 UTC 2026
From: Mikhail Dmitrichenko <m.dmitrichenko222 at gmail.com>
parse_packet() enters the IA_NA sub-option parser 24 bytes into the
option, but the fixed part of an IA_NA is 12 bytes: IAID, T1, T2.
24 is the payload length of an IAADDR option, as the comment in
create_iaadr_option() notes; create_iana_option() in the same file
already uses 12 when it builds the option.
The parser therefore starts 12 bytes past the first sub-option header,
in the middle of the IPv6 address carried by the IAADDR, and walks the
remainder of the IA_NA as if it were a sub-option list. What it
returns depends on the bits of the address being released.
dnsmasq puts an IA_NA into a Reply to a Release only when it has no
binding for the address, and that IA_NA carries an IAADDR followed by
a Status Code of NoBinding. Feeding such a Reply to parse_packet()
gives, before this change:
2001:db8::1 -> 1 (UnspecFail)
fd00::dead:beef -> 1 (UnspecFail)
2001:db8:1:2:3:4:5:6 -> 3 (NoBinding)
fe80::a00:27ff:fe12:3456 -> 1 (UnspecFail)
2001:db8::d:2:0:1 -> 0 (Success)
Over 200000 random addresses, 199985 returned UnspecFail and only 11
returned the correct NoBinding. The "Error: no binding found" message
is lost in the same way. With the offset corrected every one of these
returns 3 and prints the message.
The bounds checks added in 0375e408 are preserved: option_len is still
validated against the remaining packet length, and the sub-option
parser still receives a length matching the buffer it is handed.
Signed-off-by: Mikhail Dmitrichenko <m.dmitrichenko222 at gmail.com>
---
contrib/lease-tools/dhcp_release6.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/contrib/lease-tools/dhcp_release6.c b/contrib/lease-tools/dhcp_release6.c
index bbdd412..a795a35 100644
--- a/contrib/lease-tools/dhcp_release6.c
+++ b/contrib/lease-tools/dhcp_release6.c
@@ -339,10 +339,10 @@ int16_t parse_packet(char* buf, size_t len)
if (option_type == IA_NA )
{
- if (option_len < 24)
+ if (option_len < 12)
return UNSPEC_FAIL;
- uint16_t result = parse_iana_suboption(buf + current_pos +24, option_len -24);
+ uint16_t result = parse_iana_suboption(buf + current_pos + 12, option_len - 12);
if (result)
return result;
}
--
2.25.1
More information about the Dnsmasq-discuss
mailing list