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

Insure we let people Request addresses that we suggested in Advertise.

See RT ticket #17302 for more.
This commit is contained in:
Shane Kerr 2007-12-06 00:07:12 +00:00
parent 8d7ba39e22
commit b9137d42af
5 changed files with 98 additions and 4 deletions

View File

@ -94,6 +94,10 @@ suggested fixes to <dhcp-users@isc.org>.
to put dhcpd.leases and dhclient.leases in /usr/local/var/db, which no
one ever has.
- Regression fix for bug where server advertised a IPv6 address in
response to a SOLICIT but would not return the address in response
to a REQUEST.
Changes since 4.0.0b2
- Clarified error message when lease limit exceeded

View File

@ -3184,6 +3184,7 @@ isc_result_t ia_na_add_iaaddr(struct ia_na *ia_na, struct iaaddr *iaaddr,
const char *file, int line);
void ia_na_remove_iaaddr(struct ia_na *ia_na, struct iaaddr *iaaddr,
const char *file, int line);
isc_boolean_t ia_na_equal(const struct ia_na *a, const struct ia_na *b);
isc_result_t ipv6_pool_allocate(struct ipv6_pool **pool,
const struct in6_addr *start_addr, int bits,

View File

@ -75,6 +75,8 @@ struct buffer {
XXX ephemeral by default and be made a persistent reference explicitly. */
/* XXX on the other hand, it seems to work pretty nicely, so maybe the
XXX above comment is meshuggenah. */
/* XXX I think the above comment tries to say this:
XXX http://tinyurl.com/2tjqre */
/* A string of data bytes, possibly accompanied by a larger buffer. */
struct data_string {

View File

@ -1130,7 +1130,7 @@ lease_to_client(struct data_string *reply_ret,
reply.cursor = 0;
}
/* Process a client-supplied IA_NA. This may append options ot the tail of
/* Process a client-supplied IA_NA. This may append options to the tail of
* the reply packet being built in the reply_state structure.
*/
static isc_result_t
@ -1141,12 +1141,16 @@ reply_process_ia(struct reply_state *reply, struct option_cache *ia) {
struct option_state *packet_ia;
struct option_cache *oc;
struct data_string ia_data, data;
isc_boolean_t lease_in_database;
/* Initialize values that will get cleaned up on return. */
packet_ia = NULL;
memset(&ia_data, 0, sizeof(ia_data));
memset(&data, 0, sizeof(data));
/* Note that find_client_address() may set reply->lease. */
lease_in_database = ISC_FALSE;
/*
* Note that find_client_address() may set reply->lease.
*/
/* Make sure there is at least room for the header. */
if ((reply->cursor + IA_NA_OFFSET + 4) > sizeof(reply->buf)) {
@ -1395,7 +1399,7 @@ reply_process_ia(struct reply_state *reply, struct option_cache *ia) {
* pool timers for each (if any).
*/
if ((status != ISC_R_CANCELED) && !reply->static_lease &&
(reply->packet->dhcpv6_msg_type != DHCPV6_SOLICIT) &&
(reply->buf.reply.msg_type == DHCPV6_REPLY) &&
(reply->ia_na->num_iaaddr != 0)) {
struct iaaddr *tmp;
struct data_string *ia_id;
@ -1443,6 +1447,23 @@ reply_process_ia(struct reply_state *reply, struct option_cache *ia) {
ia_id->len, reply->ia_na, MDL);
write_ia_na(reply->ia_na);
/*
* Note that we wrote the lease into the database,
* so that we know not to release it when we're done
* with this function.
*/
lease_in_database = ISC_TRUE;
/*
* If this is a soft binding, we will check to see if we are
* suggesting the existing database entry to the client.
*/
} else if ((status != ISC_R_CANCELED) && !reply->static_lease &&
(reply->old_ia != NULL)) {
if (ia_na_equal(reply->old_ia, reply->ia_na)) {
lease_in_database = ISC_TRUE;
}
}
cleanup:
@ -1458,8 +1479,12 @@ reply_process_ia(struct reply_state *reply, struct option_cache *ia) {
ia_na_dereference(&reply->ia_na, MDL);
if (reply->old_ia != NULL)
ia_na_dereference(&reply->old_ia, MDL);
if (reply->lease != NULL)
if (reply->lease != NULL) {
if (!lease_in_database) {
release_lease6(reply->lease->ipv6_pool, reply->lease);
}
iaaddr_dereference(&reply->lease, MDL);
}
if (reply->fixed.data != NULL)
data_string_forget(&reply->fixed, MDL);

View File

@ -343,6 +343,68 @@ ia_na_remove_all_iaaddr(struct ia_na *ia_na, const char *file, int line) {
ia_na->num_iaaddr = 0;
}
/*
* Compare two IA_NA.
*/
isc_boolean_t
ia_na_equal(const struct ia_na *a, const struct ia_na *b)
{
isc_boolean_t found;
int i, j;
/*
* Handle cases where one or both of the inputs is NULL.
*/
if (a == NULL) {
if (b == NULL) {
return ISC_TRUE;
} else {
return ISC_FALSE;
}
}
/*
* Check the DUID is the same.
*/
if (a->iaid_duid.len != b->iaid_duid.len) {
return ISC_FALSE;
}
if (memcmp(a->iaid_duid.data,
b->iaid_duid.data, a->iaid_duid.len) != 0) {
return ISC_FALSE;
}
/*
* Make sure we have the same number of addresses in each.
*/
if (a->num_iaaddr != b->num_iaaddr) {
return ISC_FALSE;
}
/*
* Check that each address is present in both.
*/
for (i=0; i<a->num_iaaddr; i++) {
found = ISC_FALSE;
for (j=0; j<a->num_iaaddr; j++) {
if (memcmp(&(a->iaaddr[i]->addr),
&(b->iaaddr[j]->addr),
sizeof(struct in6_addr) == 0)) {
found = ISC_TRUE;
break;
}
}
if (!found) {
return ISC_FALSE;
}
}
/*
* These are the same in every way we care about.
*/
return ISC_TRUE;
}
/*
* Helper function for lease heaps.
* Makes the top of the heap the oldest lease.