[Dnsmasq-discuss] [PATCH] DHCPv6: NoBinding IA in a Release/Decline Reply also carries an IAADDR
Qingyang Zhou
qingyang.zhou at uwaterloo.ca
Sun Aug 9 16:52:14 UTC 2026
Hi,
RFC 8415 sections 18.3.7 and 18.3.8 both end with the same sentence about the
IA a server returns when it has no binding for one:
For each IA in the Release message for which the server has no binding
information, the server adds an IA option using the IAID from the
Release message and includes a Status Code option with the value
NoBinding in the IA option. No other options are included in the IA
option.
dnsmasq also puts an OPTION6_IAADDR in that IA, ahead of the status code.
Present in current master: 1f12252 ("Make configuration for DHCPv4 options and
DHCPv6 options consistent.", 2026-07-27), i.e. v2.93-16-g1f12252.
What I see, for a Release naming an address the server holds no lease for:
option 1 len 10 CLIENTID
option 2 len 10 SERVERID
option 3 len 62 IA_NA
sub-option 5 len 24 IAADDR <-- not permitted here
sub-option 13 len 18 STATUS_CODE = 3 (NoBinding)
option 13 len 18 STATUS_CODE = 0
Decline gives the same shape. Renew, which reaches NoBinding through
section 18.3.4 and has no equivalent sentence, emits the IA with the status
code alone:
option 3 len 34 IA_NA
sub-option 13 len 18 STATUS_CODE = 3 (NoBinding)
So the correct shape is already produced on a neighbouring path; it is the two
blocks below that add the extra option.
In src/rfc3315.c, in both the DHCP6RELEASE and DHCP6DECLINE cases, the inner
loop over the client's IAADDRs does this when no lease matches:
else
{
if (!made_ia)
{
o = new_opt6(state->ia_type);
...
made_ia = 1;
}
o1 = new_opt6(OPTION6_IAADDR);
put_opt6(&addr, IN6ADDRSZ);
put_opt6_long(0);
put_opt6_long(0);
end_opt6(o1);
}
Stated in words, in case the diff below does not survive the mail: the change
is to delete those five lines -- the `o1 = new_opt6(OPTION6_IAADDR);` call, the
three put_opt6* calls that follow it, and the matching `end_opt6(o1);` -- in
both the DHCP6RELEASE and the DHCP6DECLINE case. Nothing is added, no other
line moves, and `made_ia` keeps its current role of deciding whether the IA is
emitted at all.
It is in the branch taken when lease6_find() returned nothing; the
bound-address branch is lease_prune(lease, now) in the `if`, which is
untouched, so releasing or declining an address the server does have stays as
it was. The two other OPTION6_IAADDR sites in the file, around lines 1057 and
1670 on the assignment path, are also untouched.
I have a small standalone reproducer if it is useful: dnsmasq's own sources
plus a short driver that calls dhcp6_reply() directly, no root or network
needed, printing the options nested inside each IA. Happy to post it.
Found with a conformance checker that builds a reference model from RFC 8415
and compares the reply against the response class the RFC requires. Worth
noting this one is invisible to differential testing: every field in the reply
is individually legal, and only the rule about what may sit beside NoBinding
inside one IA makes it wrong.
Best regards,
Zhou Qingyang
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -1193,12 +1193,6 @@
}
made_ia = 1;
}
-
- o1 = new_opt6(OPTION6_IAADDR);
- put_opt6(&addr, IN6ADDRSZ);
- put_opt6_long(0);
- put_opt6_long(0);
- end_opt6(o1);
}
}
@@ -1274,12 +1268,6 @@
}
made_ia = 1;
}
-
- o1 = new_opt6(OPTION6_IAADDR);
- put_opt6(&addr, IN6ADDRSZ);
- put_opt6_long(0);
- put_opt6_long(0);
- end_opt6(o1);
}
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/attachments/20260809/81df0dac/attachment-0001.htm>
More information about the Dnsmasq-discuss
mailing list