2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-08-22 01:49:35 +00:00

- A bug was fixed where the DHCPv6 server puts the NoAddrsAvail status

code in the IA_NA was fixed.  The status code now appears in the root
  level.  [ISC-Bugs #17316b]
This commit is contained in:
David Hankins 2007-12-06 00:08:44 +00:00
parent b9137d42af
commit 9f1d5a2f4c
2 changed files with 178 additions and 57 deletions

View File

@ -98,6 +98,10 @@ suggested fixes to <dhcp-users@isc.org>.
response to a SOLICIT but would not return the address in response
to a REQUEST.
- A bug was fixed where the DHCPv6 server puts the NoAddrsAvail status
code in the IA_NA was fixed. The status code now appears in the root
level.
Changes since 4.0.0b2
- Clarified error message when lease limit exceeded

View File

@ -50,6 +50,7 @@ struct reply_state {
/* IA level persistent state */
unsigned ia_count;
unsigned client_addresses;
isc_boolean_t ia_addrs_included;
isc_boolean_t static_lease;
struct ia_na *ia_na;
struct ia_na *old_ia;
@ -1031,6 +1032,7 @@ lease_to_client(struct data_string *reply_ret,
static struct reply_state reply;
struct option_cache *oc;
struct data_string packet_oro;
isc_boolean_t no_addrs_avail;
/* Locate the client. */
if (shared_network_from_packet6(&reply.shared,
@ -1082,10 +1084,30 @@ lease_to_client(struct data_string *reply_ret,
/* Process the client supplied IA_NA's onto the reply buffer. */
reply.ia_count = 0;
oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
no_addrs_avail = ISC_FALSE;
for (; oc != NULL ; oc = oc->next) {
if (reply_process_ia(&reply, oc) != ISC_R_SUCCESS) {
isc_result_t status;
/* Start counting addresses offered. */
reply.client_addresses = 0;
reply.ia_addrs_included = ISC_FALSE;
status = reply_process_ia(&reply, oc);
/*
* We continue to try other IA's whether we can address
* this one or not. Any other result is an immediate fail.
*/
if ((status != ISC_R_SUCCESS) &&
(status != ISC_R_NORESOURCES))
goto exit;
}
/*
* If any address can be given to any IA, then do not set the
* NoAddrsAvail status code.
*/
if (reply.client_addresses == 0)
no_addrs_avail = ISC_TRUE;
}
/*
@ -1094,16 +1116,94 @@ lease_to_client(struct data_string *reply_ret,
*/
if ((reply.ia_count == 0) &&
(packet->dhcpv6_msg_type != DHCPV6_INFORMATION_REQUEST))
goto exit;
goto exit;
/*
* Having stored the client's IA_NA's, store any options that will
* fit in the remaining space.
* RFC3315 section 17.2.2 (Solicit):
*
* 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.
*
* Section 18.2.1 (Request):
*
* 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.
*
* Section 18.2.3 (Renew):
*
* The server may choose to change the list of addresses and
* the lifetimes of addresses in IAs that are returned to the
* client.
*
* Section 18.2.4 (Rebind):
*
* Absolutely nothing.
*
* INTERPRETATION;
*
* Solicit and Request are fairly explicit; we send NoAddrsAvail.
* We handle SOLICIT here and REQUEST in the reply_process_ia()
* function (because SOLICIT only counts if we never get around to
* it).
*
* Renew and Rebind are totally undefined. If we send a reply with
* empty IA's, however, the client will stop renewing or rebinding,
* and this is a problem if they could have gotten addressed from
* another server. So we ignore client packets...they will eventually
* time out in the worst case.
*/
reply.cursor += store_options6((char *)reply.buf.data + reply.cursor,
sizeof(reply.buf) - reply.cursor,
reply.opt_state, reply.packet,
required_opts_solicit, &packet_oro);
if (no_addrs_avail &&
(reply.packet->dhcpv6_msg_type == DHCPV6_SOLICIT))
{
/* Set the NoAddrsAvail status code. */
if (!set_status_code(STATUS_NoAddrsAvail,
"No addresses available for this "
"interface.", reply.opt_state)) {
log_error("lease_to_client: Unable to set "
"NoAddrsAvail status code.");
goto exit;
}
/* Rewind the cursor to the start. */
reply.cursor = REPLY_OPTIONS_INDEX;
/*
* Produce a reply that includes;
*
* Status code.
* Server DUID.
* Client DUID.
*/
reply.cursor += store_options6((char *)reply.buf.data +
reply.cursor,
sizeof(reply.buf) -
reply.cursor,
reply.opt_state, reply.packet,
required_opts,
NULL);
} else if (no_addrs_avail &&
(reply.packet->dhcpv6_msg_type != DHCPV6_REQUEST))
{
goto exit;
} else {
/*
* Having stored the client's IA_NA's, store any options that
* will fit in the remaining space.
*/
reply.cursor += store_options6((char *)reply.buf.data +
reply.cursor,
sizeof(reply.buf) -
reply.cursor,
reply.opt_state, reply.packet,
required_opts_solicit,
&packet_oro);
}
/* Return our reply to the caller. */
reply_ret->len = reply.cursor;
@ -1250,7 +1350,6 @@ reply_process_ia(struct reply_state *reply, struct option_cache *ia) {
oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAADDR);
reply->valid = reply->prefer = 0xffffffff;
reply->client_valid = reply->client_prefer = 0;
reply->client_addresses = 0;
for (; oc != NULL ; oc = oc->next) {
status = reply_process_addr(reply, oc);
@ -1276,60 +1375,76 @@ reply_process_ia(struct reply_state *reply, struct option_cache *ia) {
if ((status != ISC_R_CANCELED) && (reply->client_addresses == 0)) {
status = find_client_address(reply);
/*
* RFC3315 section 17.2.2 (Solicit):
*
* 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.
*
* Section 18.2.1 (Request):
*
* 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.
*
* Section 18.2.3 (Renew):
*
* The server may choose to change the list of addresses and
* the lifetimes of addresses in IAs that are returned to the
* client.
*
* Section 18.2.4 (Rebind):
*
* Absolutely nothing. Interpretation: Only address the
* client if its old binding can be found.
*/
if ((status == ISC_R_NORESOURCES) &&
(reply->packet->dhcpv6_msg_type != DHCPV6_REBIND)) {
/* If this is not a Renew, clear all IAADDRs. */
if (reply->packet->dhcpv6_msg_type != DHCPV6_RENEW) {
if (status == ISC_R_NORESOURCES) {
switch (reply->packet->dhcpv6_msg_type) {
case DHCPV6_SOLICIT:
/*
* Solicit is handled by the caller, because
* it has to be the sum of all the IA's.
*/
goto cleanup;
case DHCPV6_REQUEST:
/* Section 18.2.1 (Request):
*
* 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.
*/
option_state_dereference(&reply->reply_ia, MDL);
if (!option_state_allocate(&reply->reply_ia,
MDL)) {
log_error("reply_process_ia: No memory "
"for option state wipe.");
MDL))
{
log_error("reply_process_ia: No "
"memory for option state "
"wipe.");
status = ISC_R_NOMEMORY;
goto cleanup;
}
}
/* Set the status code. */
if (!set_status_code(STATUS_NoAddrsAvail,
"No addresses available "
"for this interface.",
reply->reply_ia)) {
log_error("reply_process_ia: Unable to set "
"NoAddrsAvail status code.");
status = ISC_R_FAILURE;
goto cleanup;
}
if (!set_status_code(STATUS_NoAddrsAvail,
"No addresses available "
"for this interface.",
reply->reply_ia)) {
log_error("reply_process_ia: Unable "
"to set NoAddrsAvail status "
"code.");
status = ISC_R_FAILURE;
goto cleanup;
}
status = ISC_R_SUCCESS;
status = ISC_R_SUCCESS;
break;
default:
/*
* RFC 3315 does not tell us to emit a status
* code in this condition, or anything else.
*
* If we included non-allocated addresses
* (zeroed lifetimes) in an IA, then the client
* will deconfigure them.
*
* So we want to include the IA even if we
* can't give it a new address if it includes
* zeroed lifetime addresses.
*
* We don't want to include the IA if we
* provide zero addresses including zeroed
* lifetimes...if we did, the client would
* reset its renew/rebind behaviour. If we do
* not, the client may get a success off
* another server.
*/
if (reply->ia_addrs_included)
status = ISC_R_SUCCESS;
else
goto cleanup;
break;
}
}
if (status != ISC_R_SUCCESS)
@ -2091,6 +2206,8 @@ reply_process_send_addr(struct reply_state *reply, struct iaddr *addr) {
goto cleanup;
}
reply->ia_addrs_included = ISC_TRUE;
cleanup:
if (data.data != NULL)
data_string_forget(&data, MDL);