mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
Improve RFC-compliance when unable to supply addresses in DHCPv6
While testing https://github.com/sbyx/odhcp6c client I have noticed it permanently crashes after startup. The reason was it (odhcp6c) doesn't expect empty IA options in ADVERTISE message without any suboptions. Despite this validation bug of odhcp6c, dnsmasq should not generate ADVERTISE messages with IA if there's nothing to advert per RFC 3315 17.2.2: If the server will not assign any addresses to any IAs in a subsequent Request from the client, the server MUST send an Advertise message to the client that includes only a Status Code option with code NoAddrsAvail and a status message for the user, a Server Identifier option with the server's DUID, and a Client Identifier option with the client's DUID. Meanwhile it's need to add status code for every IA in REPLY message per RFC3315 18.2.1: If the server cannot assign any addresses to an IA in the message from the client, the server MUST include the IA in the Reply message with no addresses in the IA and a Status Code option in the IA containing status code NoAddrsAvail. So, I've changed the logic to skip IA completely from ADVERTISE messages and to add NoAddrsAvail subcode into IA of REPLY messages. As for overhead, yes, I believe it's ok to return NoAddrsAvail twice in IA and in global section for compatibility with all old and new clients.
This commit is contained in:
committed by
Simon Kelley
parent
3d9d2dd001
commit
b9ff5c8f43
@@ -691,6 +691,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
o = build_ia(state, &t1cntr);
|
o = build_ia(state, &t1cntr);
|
||||||
|
if (address_assigned)
|
||||||
|
address_assigned = 2;
|
||||||
|
|
||||||
for (ia_counter = 0; ia_option; ia_counter++, ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
for (ia_counter = 0; ia_option; ia_counter++, ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
||||||
{
|
{
|
||||||
@@ -781,6 +783,27 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
address_assigned = 1;
|
address_assigned = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (address_assigned != 1)
|
||||||
|
{
|
||||||
|
/* If the server will not assign any addresses to any IAs in a
|
||||||
|
subsequent Request from the client, the server MUST send an Advertise
|
||||||
|
message to the client that doesn't include any IA options. */
|
||||||
|
if (!state->lease_allocate)
|
||||||
|
{
|
||||||
|
save_counter(o);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the server cannot assign any addresses to an IA in the message
|
||||||
|
from the client, the server MUST include the IA in the Reply message
|
||||||
|
with no addresses in the IA and a Status Code option in the IA
|
||||||
|
containing status code NoAddrsAvail. */
|
||||||
|
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||||
|
put_opt6_short(DHCP6NOADDRS);
|
||||||
|
put_opt6_string(_("address unavailable"));
|
||||||
|
end_opt6(o1);
|
||||||
|
}
|
||||||
|
|
||||||
end_ia(t1cntr, min_time, 0);
|
end_ia(t1cntr, min_time, 0);
|
||||||
end_opt6(o);
|
end_opt6(o);
|
||||||
}
|
}
|
||||||
@@ -806,7 +829,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
put_opt6_short(DHCP6NOADDRS);
|
put_opt6_short(DHCP6NOADDRS);
|
||||||
put_opt6_string(_("no addresses available"));
|
put_opt6_string(_("no addresses available"));
|
||||||
end_opt6(o1);
|
end_opt6(o1);
|
||||||
log6_packet(state, "DHCPADVERTISE", NULL, _("no addresses available"));
|
log6_packet(state, state->lease_allocate ? "DHCPREPLY" : "DHCPADVERTISE", NULL, _("no addresses available"));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -862,7 +885,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
{
|
{
|
||||||
/* Static range, not configured. */
|
/* Static range, not configured. */
|
||||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||||
put_opt6_short(DHCP6UNSPEC);
|
put_opt6_short(DHCP6NOADDRS);
|
||||||
put_opt6_string(_("address unavailable"));
|
put_opt6_string(_("address unavailable"));
|
||||||
end_opt6(o1);
|
end_opt6(o1);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user