1999-09-28 22:49:31 +00:00
|
|
|
/* mdb.c
|
|
|
|
|
|
|
|
Server-specific in-memory database support. */
|
|
|
|
|
|
|
|
/*
|
2019-11-22 13:39:45 -05:00
|
|
|
* Copyright (c) 2004-2019 by Internet Systems Consortium, Inc. ("ISC")
|
2005-03-17 20:15:29 +00:00
|
|
|
* Copyright (c) 1996-2003 by Internet Software Consortium
|
1999-09-28 22:49:31 +00:00
|
|
|
*
|
2017-07-12 09:23:23 -04:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
1999-09-28 22:49:31 +00:00
|
|
|
*
|
2005-03-17 20:15:29 +00:00
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
|
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
|
|
|
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
1999-09-28 22:49:31 +00:00
|
|
|
*
|
2005-03-17 20:15:29 +00:00
|
|
|
* Internet Systems Consortium, Inc.
|
|
|
|
* 950 Charter Street
|
|
|
|
* Redwood City, CA 94063
|
|
|
|
* <info@isc.org>
|
2009-07-23 18:52:21 +00:00
|
|
|
* https://www.isc.org/
|
2000-03-17 04:00:32 +00:00
|
|
|
*
|
1999-09-28 22:49:31 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "dhcpd.h"
|
2005-03-17 20:15:29 +00:00
|
|
|
#include "omapip/hash.h"
|
1999-09-28 22:49:31 +00:00
|
|
|
|
2000-05-04 18:58:16 +00:00
|
|
|
struct subnet *subnets;
|
|
|
|
struct shared_network *shared_networks;
|
2005-03-17 20:15:29 +00:00
|
|
|
host_hash_t *host_hw_addr_hash;
|
|
|
|
host_hash_t *host_uid_hash;
|
|
|
|
host_hash_t *host_name_hash;
|
2006-10-27 22:54:13 +00:00
|
|
|
lease_id_hash_t *lease_uid_hash;
|
|
|
|
lease_ip_hash_t *lease_ip_addr_hash;
|
|
|
|
lease_id_hash_t *lease_hw_addr_hash;
|
1999-09-28 22:49:31 +00:00
|
|
|
|
2007-05-08 23:05:22 +00:00
|
|
|
/*
|
|
|
|
* We allow users to specify any option as a host identifier.
|
|
|
|
*
|
2019-11-22 13:39:45 -05:00
|
|
|
* Any host is uniquely identified by the combination of
|
2007-05-08 23:05:22 +00:00
|
|
|
* option type & option data.
|
|
|
|
*
|
2019-11-22 13:39:45 -05:00
|
|
|
* We expect people will only use a few types of options as host
|
2007-05-08 23:05:22 +00:00
|
|
|
* identifier. Because of this, we store a list with an entry for
|
2019-11-22 13:39:45 -05:00
|
|
|
* each option type. Each of these has a hash table, which contains
|
2007-05-08 23:05:22 +00:00
|
|
|
* hash of the option data.
|
2013-11-25 21:00:41 -08:00
|
|
|
*
|
|
|
|
* For v6 we also include a relay count - this specifies which
|
|
|
|
* relay to check for the requested option. As each different
|
|
|
|
* value of relays creates a new instance admins should use the
|
|
|
|
* same value across each option for all host-identifers.
|
|
|
|
* A value of 0 indicates that we aren't doing relay options
|
|
|
|
* and should simply look in the current option list.
|
2007-05-08 23:05:22 +00:00
|
|
|
*/
|
|
|
|
typedef struct host_id_info {
|
|
|
|
struct option *option;
|
|
|
|
host_hash_t *values_hash;
|
2013-11-25 21:00:41 -08:00
|
|
|
int relays;
|
2007-05-08 23:05:22 +00:00
|
|
|
struct host_id_info *next;
|
|
|
|
} host_id_info_t;
|
|
|
|
|
|
|
|
static host_id_info_t *host_id_info = NULL;
|
|
|
|
|
2001-07-10 20:36:06 +00:00
|
|
|
int numclasseswritten;
|
|
|
|
|
2020-07-30 10:01:36 -04:00
|
|
|
extern omapi_object_type_t *dhcp_type_host;
|
1999-09-28 22:49:31 +00:00
|
|
|
|
2001-06-22 16:47:20 +00:00
|
|
|
isc_result_t enter_class(cd, dynamicp, commit)
|
|
|
|
struct class *cd;
|
|
|
|
int dynamicp;
|
|
|
|
int commit;
|
|
|
|
{
|
|
|
|
if (!collections -> classes) {
|
2005-09-30 17:57:32 +00:00
|
|
|
/* A subclass with no parent is invalid. */
|
|
|
|
if (cd->name == NULL)
|
2009-10-28 04:12:30 +00:00
|
|
|
return DHCP_R_INVALIDARG;
|
2005-09-30 17:57:32 +00:00
|
|
|
|
2001-06-22 16:47:20 +00:00
|
|
|
class_reference (&collections -> classes, cd, MDL);
|
|
|
|
} else if (cd->name != NULL) { /* regular class */
|
|
|
|
struct class *c = 0;
|
|
|
|
|
|
|
|
if (find_class(&c, cd->name, MDL) != ISC_R_NOTFOUND) {
|
|
|
|
class_dereference(&c, MDL);
|
|
|
|
return ISC_R_EXISTS;
|
|
|
|
}
|
2019-11-22 13:39:45 -05:00
|
|
|
|
2005-09-30 17:57:32 +00:00
|
|
|
/* Find the tail. */
|
2001-06-22 16:47:20 +00:00
|
|
|
for (c = collections -> classes;
|
|
|
|
c -> nic; c = c -> nic)
|
|
|
|
/* nothing */ ;
|
|
|
|
class_reference (&c -> nic, cd, MDL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dynamicp && commit) {
|
|
|
|
const char *name = cd->name;
|
|
|
|
|
|
|
|
if (name == NULL) {
|
|
|
|
name = cd->superclass->name;
|
|
|
|
}
|
|
|
|
|
2006-03-02 19:02:56 +00:00
|
|
|
write_named_billing_class ((const unsigned char *)name, 0, cd);
|
2001-06-22 16:47:20 +00:00
|
|
|
if (!commit_leases ())
|
|
|
|
return ISC_R_IOERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ISC_R_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-09 15:51:02 +00:00
|
|
|
/* Variable to check if we're starting the server. The server will init as
|
|
|
|
* starting - but just to be safe start out as false to avoid triggering new
|
|
|
|
* special-case code
|
|
|
|
* XXX: There is actually a server_startup state...which is never entered...
|
|
|
|
*/
|
|
|
|
#define SS_NOSYNC 1
|
|
|
|
#define SS_QFOLLOW 2
|
|
|
|
static int server_starting = 0;
|
|
|
|
|
2001-06-27 00:31:20 +00:00
|
|
|
static int find_uid_statement (struct executable_statement *esp,
|
|
|
|
void *vp, int condp)
|
|
|
|
{
|
|
|
|
struct executable_statement **evp = vp;
|
|
|
|
|
|
|
|
if (esp -> op == supersede_option_statement &&
|
|
|
|
esp -> data.option &&
|
|
|
|
(esp -> data.option -> option -> universe ==
|
|
|
|
&dhcp_universe) &&
|
|
|
|
(esp -> data.option -> option -> code ==
|
|
|
|
DHO_DHCP_CLIENT_IDENTIFIER)) {
|
|
|
|
if (condp) {
|
|
|
|
log_error ("dhcp client identifier may not be %s",
|
|
|
|
"specified conditionally.");
|
|
|
|
} else if (!(*evp)) {
|
|
|
|
executable_statement_reference (evp, esp, MDL);
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
log_error ("only one dhcp client identifier may be %s",
|
|
|
|
"specified");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-05-08 23:05:22 +00:00
|
|
|
|
|
|
|
static host_id_info_t *
|
2013-11-25 21:00:41 -08:00
|
|
|
find_host_id_info(unsigned int option_code, int relays) {
|
2007-05-08 23:05:22 +00:00
|
|
|
host_id_info_t *p;
|
|
|
|
|
2013-11-25 21:00:41 -08:00
|
|
|
for (p = host_id_info; p != NULL; p = p->next) {
|
|
|
|
if ((p->option->code == option_code) &&
|
|
|
|
(p->relays == relays)) {
|
2007-05-08 23:05:22 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Debugging code */
|
|
|
|
#if 0
|
|
|
|
isc_result_t
|
|
|
|
print_host(const void *name, unsigned len, void *value) {
|
|
|
|
struct host_decl *h;
|
|
|
|
printf("--------------\n");
|
|
|
|
printf("name:'%s'\n", print_hex_1(len, name, 60));
|
|
|
|
printf("len:%d\n", len);
|
|
|
|
h = (struct host_decl *)value;
|
|
|
|
printf("host @%p is '%s'\n", h, h->name);
|
|
|
|
return ISC_R_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
hash_print_hosts(struct hash_table *h) {
|
|
|
|
hash_foreach(h, print_host);
|
|
|
|
printf("--------------\n");
|
|
|
|
}
|
|
|
|
#endif /* 0 */
|
|
|
|
|
|
|
|
void
|
|
|
|
change_host_uid(struct host_decl *host, const char *uid, int len) {
|
|
|
|
/* XXX: should consolidate this type of code throughout */
|
|
|
|
if (host_uid_hash == NULL) {
|
|
|
|
if (!host_new_hash(&host_uid_hash, HOST_HASH_SIZE, MDL)) {
|
|
|
|
log_fatal("Can't allocate host/uid hash");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-22 13:39:45 -05:00
|
|
|
/*
|
2007-05-08 23:05:22 +00:00
|
|
|
* Remove the old entry, if one exists.
|
|
|
|
*/
|
|
|
|
if (host->client_identifier.data != NULL) {
|
|
|
|
host_hash_delete(host_uid_hash,
|
|
|
|
host->client_identifier.data,
|
|
|
|
host->client_identifier.len,
|
|
|
|
MDL);
|
|
|
|
data_string_forget(&host->client_identifier, MDL);
|
|
|
|
}
|
|
|
|
|
2019-11-22 13:39:45 -05:00
|
|
|
/*
|
2007-05-08 23:05:22 +00:00
|
|
|
* Set our new value.
|
|
|
|
*/
|
|
|
|
memset(&host->client_identifier, 0, sizeof(host->client_identifier));
|
|
|
|
host->client_identifier.len = len;
|
|
|
|
if (!buffer_allocate(&host->client_identifier.buffer, len, MDL)) {
|
|
|
|
log_fatal("Can't allocate uid buffer");
|
|
|
|
}
|
|
|
|
host->client_identifier.data = host->client_identifier.buffer->data;
|
|
|
|
memcpy((char *)host->client_identifier.data, uid, len);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* And add to hash.
|
|
|
|
*/
|
2019-11-22 13:39:45 -05:00
|
|
|
host_hash_add(host_uid_hash, host->client_identifier.data,
|
2007-05-08 23:05:22 +00:00
|
|
|
host->client_identifier.len, host, MDL);
|
|
|
|
}
|
|
|
|
|
1999-09-28 22:49:31 +00:00
|
|
|
isc_result_t enter_host (hd, dynamicp, commit)
|
|
|
|
struct host_decl *hd;
|
|
|
|
int dynamicp;
|
|
|
|
int commit;
|
|
|
|
{
|
|
|
|
struct host_decl *hp = (struct host_decl *)0;
|
|
|
|
struct host_decl *np = (struct host_decl *)0;
|
|
|
|
struct executable_statement *esp;
|
2007-05-08 23:05:22 +00:00
|
|
|
host_id_info_t *h_id_info;
|
1999-09-28 22:49:31 +00:00
|
|
|
|
|
|
|
if (!host_name_hash) {
|
2006-06-01 20:23:18 +00:00
|
|
|
if (!host_new_hash(&host_name_hash, HOST_HASH_SIZE, MDL))
|
1999-09-28 22:49:31 +00:00
|
|
|
log_fatal ("Can't allocate host name hash");
|
2000-06-30 00:40:19 +00:00
|
|
|
host_hash_add (host_name_hash,
|
|
|
|
(unsigned char *)hd -> name,
|
|
|
|
strlen (hd -> name), hd, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
} else {
|
2000-05-16 23:03:49 +00:00
|
|
|
host_hash_lookup (&hp, host_name_hash,
|
|
|
|
(unsigned char *)hd -> name,
|
|
|
|
strlen (hd -> name), MDL);
|
1999-10-24 23:27:52 +00:00
|
|
|
|
|
|
|
/* If it's deleted, we can supersede it. */
|
|
|
|
if (hp && (hp -> flags & HOST_DECL_DELETED)) {
|
2000-05-16 23:03:49 +00:00
|
|
|
host_hash_delete (host_name_hash,
|
|
|
|
(unsigned char *)hd -> name,
|
|
|
|
strlen (hd -> name), MDL);
|
1999-10-24 23:27:52 +00:00
|
|
|
/* If the old entry wasn't dynamic, then we
|
|
|
|
always have to keep the deletion. */
|
2005-03-17 20:15:29 +00:00
|
|
|
if (hp -> flags & HOST_DECL_STATIC) {
|
1999-10-25 01:55:40 +00:00
|
|
|
hd -> flags |= HOST_DECL_STATIC;
|
2005-03-17 20:15:29 +00:00
|
|
|
}
|
|
|
|
host_dereference (&hp, MDL);
|
1999-10-24 23:27:52 +00:00
|
|
|
}
|
1999-09-28 22:49:31 +00:00
|
|
|
|
2001-06-27 00:31:20 +00:00
|
|
|
/* If we are updating an existing host declaration, we
|
|
|
|
can just delete it and add it again. */
|
|
|
|
if (hp && hp == hd) {
|
|
|
|
host_dereference (&hp, MDL);
|
|
|
|
delete_host (hd, 0);
|
|
|
|
if (!write_host (hd))
|
|
|
|
return ISC_R_IOERROR;
|
|
|
|
hd -> flags &= ~HOST_DECL_DELETED;
|
|
|
|
}
|
|
|
|
|
1999-09-28 22:49:31 +00:00
|
|
|
/* If there isn't already a host decl matching this
|
|
|
|
address, add it to the hash table. */
|
|
|
|
if (!hp) {
|
2000-05-16 23:03:49 +00:00
|
|
|
host_hash_add (host_name_hash,
|
|
|
|
(unsigned char *)hd -> name,
|
|
|
|
strlen (hd -> name), hd, MDL);
|
|
|
|
} else {
|
1999-09-28 22:49:31 +00:00
|
|
|
/* XXX actually, we have to delete the old one
|
|
|
|
XXX carefully and replace it. Not done yet. */
|
2000-05-16 23:03:49 +00:00
|
|
|
host_dereference (&hp, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
return ISC_R_EXISTS;
|
2000-05-16 23:03:49 +00:00
|
|
|
}
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
2000-05-16 23:03:49 +00:00
|
|
|
if (hd -> n_ipaddr)
|
|
|
|
host_dereference (&hd -> n_ipaddr, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
|
|
|
|
if (!hd -> type)
|
|
|
|
hd -> type = dhcp_type_host;
|
|
|
|
|
|
|
|
if (hd -> interface.hlen) {
|
|
|
|
if (!host_hw_addr_hash) {
|
2006-06-01 20:23:18 +00:00
|
|
|
if (!host_new_hash(&host_hw_addr_hash,
|
|
|
|
HOST_HASH_SIZE, MDL))
|
1999-09-28 22:49:31 +00:00
|
|
|
log_fatal ("Can't allocate host/hw hash");
|
2000-05-16 23:03:49 +00:00
|
|
|
} else {
|
|
|
|
/* If there isn't already a host decl matching this
|
|
|
|
address, add it to the hash table. */
|
2000-07-09 07:00:06 +00:00
|
|
|
host_hash_lookup (&hp, host_hw_addr_hash,
|
|
|
|
hd -> interface.hbuf,
|
|
|
|
hd -> interface.hlen, MDL);
|
|
|
|
}
|
|
|
|
if (!hp)
|
|
|
|
host_hash_add (host_hw_addr_hash, hd -> interface.hbuf,
|
|
|
|
hd -> interface.hlen, hd, MDL);
|
|
|
|
else {
|
|
|
|
/* If there was already a host declaration for
|
|
|
|
this hardware address, add this one to the
|
|
|
|
end of the list. */
|
|
|
|
for (np = hp; np -> n_ipaddr; np = np -> n_ipaddr)
|
|
|
|
;
|
|
|
|
host_reference (&np -> n_ipaddr, hd, MDL);
|
|
|
|
host_dereference (&hp, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* See if there's a statement that sets the client identifier.
|
|
|
|
This is a kludge - the client identifier really shouldn't be
|
|
|
|
set with an executable statement. */
|
2012-10-16 15:05:24 -07:00
|
|
|
esp = NULL;
|
|
|
|
if (executable_statement_foreach (hd->group->statements,
|
2001-06-27 00:31:20 +00:00
|
|
|
find_uid_statement, &esp, 0)) {
|
2019-11-22 13:39:45 -05:00
|
|
|
struct data_string cid;
|
|
|
|
memset(&cid, 0, sizeof(cid));
|
|
|
|
(void) evaluate_option_cache (&cid,
|
|
|
|
NULL, NULL, NULL, NULL, NULL,
|
2012-10-16 15:05:24 -07:00
|
|
|
&global_scope,
|
|
|
|
esp->data.option, MDL);
|
2019-11-22 13:39:45 -05:00
|
|
|
|
|
|
|
if (hd->client_identifier.len > 0 && cid.len > 0) {
|
|
|
|
char uid_buf[256];
|
|
|
|
char cid_buf[256];
|
|
|
|
print_hex_or_string(hd->client_identifier.len,
|
|
|
|
hd->client_identifier.data,
|
|
|
|
sizeof(uid_buf) - 1, uid_buf);
|
|
|
|
|
|
|
|
print_hex_or_string(cid.len, cid.data,
|
|
|
|
sizeof(cid_buf) - 1, cid_buf);
|
|
|
|
|
|
|
|
log_error ("Warning, host declaration '%s'"
|
|
|
|
" already has uid '%s',"
|
|
|
|
" ignoring dhcp-client-identifier '%s'",
|
|
|
|
hd->name, uid_buf, cid_buf);
|
|
|
|
|
|
|
|
data_string_forget(&cid, MDL);
|
|
|
|
} else {
|
|
|
|
memcpy(&hd->client_identifier, &cid, sizeof(cid));
|
|
|
|
}
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* If we got a client identifier, hash this entry by
|
|
|
|
client identifier. */
|
|
|
|
if (hd -> client_identifier.len) {
|
|
|
|
/* If there's no uid hash, make one; otherwise, see if
|
|
|
|
there's already an entry in the hash for this host. */
|
|
|
|
if (!host_uid_hash) {
|
2006-06-01 20:23:18 +00:00
|
|
|
if (!host_new_hash(&host_uid_hash,
|
|
|
|
HOST_HASH_SIZE, MDL))
|
1999-09-28 22:49:31 +00:00
|
|
|
log_fatal ("Can't allocate host/uid hash");
|
2000-06-30 00:40:19 +00:00
|
|
|
|
|
|
|
host_hash_add (host_uid_hash,
|
|
|
|
hd -> client_identifier.data,
|
|
|
|
hd -> client_identifier.len,
|
|
|
|
hd, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
} else {
|
2000-05-16 23:03:49 +00:00
|
|
|
/* If there's already a host declaration for this
|
|
|
|
client identifier, add this one to the end of the
|
|
|
|
list. Otherwise, add it to the hash table. */
|
|
|
|
if (host_hash_lookup (&hp, host_uid_hash,
|
|
|
|
hd -> client_identifier.data,
|
|
|
|
hd -> client_identifier.len,
|
|
|
|
MDL)) {
|
|
|
|
/* Don't link it in twice... */
|
|
|
|
if (!np) {
|
|
|
|
for (np = hp; np -> n_ipaddr;
|
2000-06-30 00:40:19 +00:00
|
|
|
np = np -> n_ipaddr) {
|
|
|
|
if (hd == np)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (hd != np)
|
|
|
|
host_reference (&np -> n_ipaddr,
|
|
|
|
hd, MDL);
|
2000-05-16 23:03:49 +00:00
|
|
|
}
|
|
|
|
host_dereference (&hp, MDL);
|
|
|
|
} else {
|
|
|
|
host_hash_add (host_uid_hash,
|
|
|
|
hd -> client_identifier.data,
|
|
|
|
hd -> client_identifier.len,
|
|
|
|
hd, MDL);
|
|
|
|
}
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-05-08 23:05:22 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If we use an option as our host identifier, record it here.
|
|
|
|
*/
|
|
|
|
if (hd->host_id_option != NULL) {
|
|
|
|
/*
|
|
|
|
* Look for the host identifier information for this option,
|
|
|
|
* and create a new entry if there is none.
|
|
|
|
*/
|
2013-11-25 21:00:41 -08:00
|
|
|
h_id_info = find_host_id_info(hd->host_id_option->code,
|
|
|
|
hd->relays);
|
2007-05-08 23:05:22 +00:00
|
|
|
if (h_id_info == NULL) {
|
|
|
|
h_id_info = dmalloc(sizeof(*h_id_info), MDL);
|
|
|
|
if (h_id_info == NULL) {
|
|
|
|
log_fatal("No memory for host-identifier "
|
|
|
|
"option information.");
|
|
|
|
}
|
2019-11-22 13:39:45 -05:00
|
|
|
option_reference(&h_id_info->option,
|
2007-05-08 23:05:22 +00:00
|
|
|
hd->host_id_option, MDL);
|
2019-11-22 13:39:45 -05:00
|
|
|
if (!host_new_hash(&h_id_info->values_hash,
|
2007-05-08 23:05:22 +00:00
|
|
|
HOST_HASH_SIZE, MDL)) {
|
2007-11-30 21:51:43 +00:00
|
|
|
log_fatal("No memory for host-identifier "
|
2007-05-08 23:05:22 +00:00
|
|
|
"option hash.");
|
|
|
|
}
|
2013-11-25 21:00:41 -08:00
|
|
|
h_id_info->relays = hd->relays;
|
2007-05-08 23:05:22 +00:00
|
|
|
h_id_info->next = host_id_info;
|
|
|
|
host_id_info = h_id_info;
|
|
|
|
}
|
|
|
|
|
2019-11-22 13:39:45 -05:00
|
|
|
if (host_hash_lookup(&hp, h_id_info->values_hash,
|
2007-05-08 23:05:22 +00:00
|
|
|
hd->host_id.data, hd->host_id.len, MDL)) {
|
2019-11-22 13:39:45 -05:00
|
|
|
/*
|
|
|
|
* If this option is already present, then add
|
2007-05-08 23:05:22 +00:00
|
|
|
* this host to the list in n_ipaddr, unless
|
|
|
|
* we have already done so previously.
|
|
|
|
*
|
|
|
|
* XXXSK: This seems scary to me, but I don't
|
2019-11-22 13:39:45 -05:00
|
|
|
* fully understand how these are used.
|
|
|
|
* Shouldn't there be multiple lists, or
|
2007-05-08 23:05:22 +00:00
|
|
|
* maybe we should just forbid duplicates?
|
|
|
|
*/
|
|
|
|
if (np == NULL) {
|
|
|
|
np = hp;
|
|
|
|
while (np->n_ipaddr != NULL) {
|
|
|
|
np = np->n_ipaddr;
|
|
|
|
}
|
|
|
|
if (hd != np) {
|
|
|
|
host_reference(&np->n_ipaddr, hd, MDL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
host_dereference(&hp, MDL);
|
|
|
|
} else {
|
2019-11-22 13:39:45 -05:00
|
|
|
host_hash_add(h_id_info->values_hash,
|
2007-05-08 23:05:22 +00:00
|
|
|
hd->host_id.data,
|
|
|
|
hd->host_id.len,
|
|
|
|
hd, MDL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-09-28 22:49:31 +00:00
|
|
|
if (dynamicp && commit) {
|
1999-10-01 03:26:45 +00:00
|
|
|
if (!write_host (hd))
|
|
|
|
return ISC_R_IOERROR;
|
|
|
|
if (!commit_leases ())
|
|
|
|
return ISC_R_IOERROR;
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ISC_R_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2001-06-22 16:47:20 +00:00
|
|
|
|
|
|
|
isc_result_t delete_class (cp, commit)
|
|
|
|
struct class *cp;
|
|
|
|
int commit;
|
|
|
|
{
|
|
|
|
cp->flags |= CLASS_DECL_DELETED;
|
|
|
|
|
|
|
|
/* do the write first as we won't be leaving it in any data
|
|
|
|
structures, unlike the host objects */
|
2019-11-22 13:39:45 -05:00
|
|
|
|
2001-06-22 16:47:20 +00:00
|
|
|
if (commit) {
|
2006-03-02 19:02:56 +00:00
|
|
|
write_named_billing_class ((unsigned char *)cp->name, 0, cp);
|
2001-06-22 16:47:20 +00:00
|
|
|
if (!commit_leases ())
|
|
|
|
return ISC_R_IOERROR;
|
|
|
|
}
|
2019-11-22 13:39:45 -05:00
|
|
|
|
2013-06-05 18:15:49 -07:00
|
|
|
/*
|
|
|
|
* If this is a subclass remove it from the class's hash table
|
|
|
|
*/
|
|
|
|
if (cp->superclass) {
|
2019-11-22 13:39:45 -05:00
|
|
|
class_hash_delete(cp->superclass->hash,
|
2013-06-05 18:15:49 -07:00
|
|
|
(const char *)cp->hash_string.data,
|
|
|
|
cp->hash_string.len,
|
|
|
|
MDL);
|
|
|
|
}
|
2001-06-22 16:47:20 +00:00
|
|
|
|
2013-06-05 18:15:49 -07:00
|
|
|
/* remove from collections */
|
|
|
|
unlink_class(&cp);
|
2001-06-22 16:47:20 +00:00
|
|
|
|
|
|
|
return ISC_R_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-10-01 03:26:45 +00:00
|
|
|
isc_result_t delete_host (hd, commit)
|
1999-09-28 22:49:31 +00:00
|
|
|
struct host_decl *hd;
|
|
|
|
int commit;
|
|
|
|
{
|
|
|
|
struct host_decl *hp = (struct host_decl *)0;
|
|
|
|
struct host_decl *np = (struct host_decl *)0;
|
2000-05-16 23:03:49 +00:00
|
|
|
struct host_decl *foo;
|
1999-09-28 22:49:31 +00:00
|
|
|
int hw_head = 0, uid_head = 1;
|
|
|
|
|
|
|
|
/* Don't need to do it twice. */
|
|
|
|
if (hd -> flags & HOST_DECL_DELETED)
|
1999-10-01 03:26:45 +00:00
|
|
|
return ISC_R_SUCCESS;
|
1999-09-28 22:49:31 +00:00
|
|
|
|
|
|
|
/* But we do need to do it once! :') */
|
|
|
|
hd -> flags |= HOST_DECL_DELETED;
|
|
|
|
|
|
|
|
if (hd -> interface.hlen) {
|
2000-05-16 23:03:49 +00:00
|
|
|
if (host_hw_addr_hash) {
|
|
|
|
if (host_hash_lookup (&hp, host_hw_addr_hash,
|
2001-06-27 00:31:20 +00:00
|
|
|
hd -> interface.hbuf,
|
|
|
|
hd -> interface.hlen, MDL)) {
|
2000-05-16 23:03:49 +00:00
|
|
|
if (hp == hd) {
|
|
|
|
host_hash_delete (host_hw_addr_hash,
|
|
|
|
hd -> interface.hbuf,
|
|
|
|
hd -> interface.hlen, MDL);
|
|
|
|
hw_head = 1;
|
|
|
|
} else {
|
2001-04-27 21:30:59 +00:00
|
|
|
np = (struct host_decl *)0;
|
|
|
|
foo = (struct host_decl *)0;
|
|
|
|
host_reference (&foo, hp, MDL);
|
|
|
|
while (foo) {
|
2000-05-16 23:03:49 +00:00
|
|
|
if (foo == hd)
|
|
|
|
break;
|
2005-03-17 20:15:29 +00:00
|
|
|
if (np)
|
|
|
|
host_dereference (&np, MDL);
|
2001-04-27 21:30:59 +00:00
|
|
|
host_reference (&np, foo, MDL);
|
|
|
|
host_dereference (&foo, MDL);
|
|
|
|
if (np -> n_ipaddr)
|
|
|
|
host_reference (&foo, np -> n_ipaddr, MDL);
|
2000-05-16 23:03:49 +00:00
|
|
|
}
|
2001-04-27 21:30:59 +00:00
|
|
|
|
2000-05-16 23:03:49 +00:00
|
|
|
if (foo) {
|
|
|
|
host_dereference (&np -> n_ipaddr, MDL);
|
|
|
|
if (hd -> n_ipaddr)
|
|
|
|
host_reference (&np -> n_ipaddr,
|
|
|
|
hd -> n_ipaddr, MDL);
|
2001-04-27 21:30:59 +00:00
|
|
|
host_dereference (&foo, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
2001-04-27 21:30:59 +00:00
|
|
|
if (np)
|
|
|
|
host_dereference (&np, MDL);
|
2000-05-16 23:03:49 +00:00
|
|
|
}
|
|
|
|
host_dereference (&hp, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
2000-05-16 23:03:49 +00:00
|
|
|
}
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* If we got a client identifier, hash this entry by
|
|
|
|
client identifier. */
|
|
|
|
if (hd -> client_identifier.len) {
|
2000-05-16 23:03:49 +00:00
|
|
|
if (host_uid_hash) {
|
|
|
|
if (host_hash_lookup (&hp, host_uid_hash,
|
|
|
|
hd -> client_identifier.data,
|
|
|
|
hd -> client_identifier.len, MDL)) {
|
|
|
|
if (hp == hd) {
|
|
|
|
host_hash_delete (host_uid_hash,
|
|
|
|
hd -> client_identifier.data,
|
|
|
|
hd -> client_identifier.len, MDL);
|
|
|
|
uid_head = 1;
|
|
|
|
} else {
|
2001-04-27 21:30:59 +00:00
|
|
|
np = (struct host_decl *)0;
|
|
|
|
foo = (struct host_decl *)0;
|
|
|
|
host_reference (&foo, hp, MDL);
|
|
|
|
while (foo) {
|
2000-05-16 23:03:49 +00:00
|
|
|
if (foo == hd)
|
2001-04-27 21:30:59 +00:00
|
|
|
break;
|
2005-03-17 20:15:29 +00:00
|
|
|
if (np)
|
|
|
|
host_dereference (&np, MDL);
|
2001-04-27 21:30:59 +00:00
|
|
|
host_reference (&np, foo, MDL);
|
|
|
|
host_dereference (&foo, MDL);
|
|
|
|
if (np -> n_ipaddr)
|
|
|
|
host_reference (&foo, np -> n_ipaddr, MDL);
|
2000-05-16 23:03:49 +00:00
|
|
|
}
|
2001-04-27 21:30:59 +00:00
|
|
|
|
2000-05-16 23:03:49 +00:00
|
|
|
if (foo) {
|
2001-04-27 21:30:59 +00:00
|
|
|
host_dereference (&np -> n_ipaddr, MDL);
|
|
|
|
if (hd -> n_ipaddr)
|
|
|
|
host_reference (&np -> n_ipaddr,
|
|
|
|
hd -> n_ipaddr, MDL);
|
|
|
|
host_dereference (&foo, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
2001-04-27 21:30:59 +00:00
|
|
|
if (np)
|
|
|
|
host_dereference (&np, MDL);
|
2000-05-16 23:03:49 +00:00
|
|
|
}
|
|
|
|
host_dereference (&hp, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
2000-05-16 23:03:49 +00:00
|
|
|
}
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
2007-05-08 23:05:22 +00:00
|
|
|
if (hd->host_id_option != NULL) {
|
|
|
|
option_dereference(&hd->host_id_option, MDL);
|
|
|
|
data_string_forget(&hd->host_id, MDL);
|
|
|
|
}
|
|
|
|
|
1999-09-28 22:49:31 +00:00
|
|
|
if (hd -> n_ipaddr) {
|
|
|
|
if (uid_head && hd -> n_ipaddr -> client_identifier.len) {
|
2000-05-16 23:03:49 +00:00
|
|
|
host_hash_add
|
|
|
|
(host_uid_hash,
|
|
|
|
hd -> n_ipaddr -> client_identifier.data,
|
|
|
|
hd -> n_ipaddr -> client_identifier.len,
|
|
|
|
hd -> n_ipaddr, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
if (hw_head && hd -> n_ipaddr -> interface.hlen) {
|
2000-05-16 23:03:49 +00:00
|
|
|
host_hash_add (host_hw_addr_hash,
|
|
|
|
hd -> n_ipaddr -> interface.hbuf,
|
|
|
|
hd -> n_ipaddr -> interface.hlen,
|
|
|
|
hd -> n_ipaddr, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
2000-05-16 23:03:49 +00:00
|
|
|
host_dereference (&hd -> n_ipaddr, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (host_name_hash) {
|
2000-05-16 23:03:49 +00:00
|
|
|
if (host_hash_lookup (&hp, host_name_hash,
|
|
|
|
(unsigned char *)hd -> name,
|
|
|
|
strlen (hd -> name), MDL)) {
|
1999-10-25 01:55:40 +00:00
|
|
|
if (hp == hd && !(hp -> flags & HOST_DECL_STATIC)) {
|
2000-05-16 23:03:49 +00:00
|
|
|
host_hash_delete (host_name_hash,
|
|
|
|
(unsigned char *)hd -> name,
|
|
|
|
strlen (hd -> name), MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
2000-05-16 23:03:49 +00:00
|
|
|
host_dereference (&hp, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (commit) {
|
1999-10-01 03:26:45 +00:00
|
|
|
if (!write_host (hd))
|
|
|
|
return ISC_R_IOERROR;
|
|
|
|
if (!commit_leases ())
|
|
|
|
return ISC_R_IOERROR;
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
1999-10-01 03:26:45 +00:00
|
|
|
return ISC_R_SUCCESS;
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
2000-05-16 23:03:49 +00:00
|
|
|
int find_hosts_by_haddr (struct host_decl **hp, int htype,
|
|
|
|
const unsigned char *haddr, unsigned hlen,
|
|
|
|
const char *file, int line)
|
1999-09-28 22:49:31 +00:00
|
|
|
{
|
2000-03-06 23:35:16 +00:00
|
|
|
struct hardware h;
|
2010-03-24 21:49:03 +00:00
|
|
|
#if defined(LDAP_CONFIGURATION)
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if ((ret = find_haddr_in_ldap (hp, htype, hlen, haddr, file, line)))
|
|
|
|
return ret;
|
|
|
|
#endif
|
2000-03-06 23:35:16 +00:00
|
|
|
|
|
|
|
h.hlen = hlen + 1;
|
|
|
|
h.hbuf [0] = htype;
|
|
|
|
memcpy (&h.hbuf [1], haddr, hlen);
|
1999-09-28 22:49:31 +00:00
|
|
|
|
2000-05-16 23:03:49 +00:00
|
|
|
return host_hash_lookup (hp, host_hw_addr_hash,
|
|
|
|
h.hbuf, h.hlen, file, line);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
2000-05-16 23:03:49 +00:00
|
|
|
int find_hosts_by_uid (struct host_decl **hp,
|
|
|
|
const unsigned char *data, unsigned len,
|
|
|
|
const char *file, int line)
|
1999-09-28 22:49:31 +00:00
|
|
|
{
|
2000-05-16 23:03:49 +00:00
|
|
|
return host_hash_lookup (hp, host_uid_hash, data, len, file, line);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
2007-05-08 23:05:22 +00:00
|
|
|
int
|
2019-11-22 13:39:45 -05:00
|
|
|
find_hosts_by_option(struct host_decl **hp,
|
2007-05-08 23:05:22 +00:00
|
|
|
struct packet *packet,
|
|
|
|
struct option_state *opt_state,
|
|
|
|
const char *file, int line) {
|
|
|
|
host_id_info_t *p;
|
|
|
|
struct option_cache *oc;
|
|
|
|
struct data_string data;
|
|
|
|
int found;
|
2013-11-25 21:00:41 -08:00
|
|
|
struct packet *relay_packet;
|
|
|
|
struct option_state *relay_state;
|
2015-07-29 13:32:16 -04:00
|
|
|
|
|
|
|
#if defined(LDAP_CONFIGURATION)
|
|
|
|
if ((found = find_client_in_ldap (hp, packet, opt_state, file, line)))
|
|
|
|
return found;
|
|
|
|
#endif
|
2019-11-22 13:39:45 -05:00
|
|
|
|
2007-05-08 23:05:22 +00:00
|
|
|
for (p = host_id_info; p != NULL; p = p->next) {
|
2019-11-22 13:39:45 -05:00
|
|
|
relay_packet = packet;
|
2013-11-25 21:00:41 -08:00
|
|
|
relay_state = opt_state;
|
|
|
|
|
|
|
|
/* If this option block is for a relay (relays != 0)
|
|
|
|
* and we are processing the main options and not
|
|
|
|
* options from the IA (packet->options == opt_state)
|
|
|
|
* try to find the proper relay
|
|
|
|
*/
|
|
|
|
if ((p->relays != 0) && (packet->options == opt_state)) {
|
|
|
|
int i = p->relays;
|
|
|
|
while ((i != 0) &&
|
|
|
|
(relay_packet->dhcpv6_container_packet != NULL)) {
|
|
|
|
relay_packet =
|
|
|
|
relay_packet->dhcpv6_container_packet;
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
/* We wanted a specific relay but were
|
|
|
|
* unable to find it */
|
|
|
|
if ((p->relays <= MAX_V6RELAY_HOPS) && (i != 0))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
relay_state = relay_packet->options;
|
|
|
|
}
|
|
|
|
|
2019-11-22 13:39:45 -05:00
|
|
|
oc = lookup_option(p->option->universe,
|
2013-11-25 21:00:41 -08:00
|
|
|
relay_state, p->option->code);
|
2007-05-08 23:05:22 +00:00
|
|
|
if (oc != NULL) {
|
|
|
|
memset(&data, 0, sizeof(data));
|
2013-11-25 21:00:41 -08:00
|
|
|
|
|
|
|
if (!evaluate_option_cache(&data, relay_packet, NULL,
|
|
|
|
NULL, relay_state, NULL,
|
2019-11-22 13:39:45 -05:00
|
|
|
&global_scope, oc,
|
2007-05-08 23:05:22 +00:00
|
|
|
MDL)) {
|
|
|
|
log_error("Error evaluating option cache");
|
|
|
|
return 0;
|
|
|
|
}
|
2019-11-22 13:39:45 -05:00
|
|
|
|
|
|
|
found = host_hash_lookup(hp, p->values_hash,
|
2007-05-08 23:05:22 +00:00
|
|
|
data.data, data.len,
|
|
|
|
file, line);
|
|
|
|
|
|
|
|
data_string_forget(&data, MDL);
|
|
|
|
|
|
|
|
if (found) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-09-28 22:49:31 +00:00
|
|
|
/* More than one host_decl can be returned by find_hosts_by_haddr or
|
|
|
|
find_hosts_by_uid, and each host_decl can have multiple addresses.
|
|
|
|
Loop through the list of hosts, and then for each host, through the
|
|
|
|
list of addresses, looking for an address that's in the same shared
|
|
|
|
network as the one specified. Store the matching address through
|
|
|
|
the addr pointer, update the host pointer to point at the host_decl
|
|
|
|
that matched, and return the subnet that matched. */
|
|
|
|
|
2000-05-16 23:03:49 +00:00
|
|
|
int find_host_for_network (struct subnet **sp, struct host_decl **host,
|
|
|
|
struct iaddr *addr, struct shared_network *share)
|
1999-09-28 22:49:31 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct iaddr ip_address;
|
|
|
|
struct host_decl *hp;
|
|
|
|
struct data_string fixed_addr;
|
|
|
|
|
|
|
|
memset (&fixed_addr, 0, sizeof fixed_addr);
|
|
|
|
|
|
|
|
for (hp = *host; hp; hp = hp -> n_ipaddr) {
|
|
|
|
if (!hp -> fixed_addr)
|
|
|
|
continue;
|
1999-10-13 16:28:00 +00:00
|
|
|
if (!evaluate_option_cache (&fixed_addr, (struct packet *)0,
|
|
|
|
(struct lease *)0,
|
2000-11-28 23:27:24 +00:00
|
|
|
(struct client_state *)0,
|
1999-10-13 16:28:00 +00:00
|
|
|
(struct option_state *)0,
|
|
|
|
(struct option_state *)0,
|
2000-01-26 14:56:18 +00:00
|
|
|
&global_scope,
|
|
|
|
hp -> fixed_addr, MDL))
|
1999-09-28 22:49:31 +00:00
|
|
|
continue;
|
|
|
|
for (i = 0; i < fixed_addr.len; i += 4) {
|
|
|
|
ip_address.len = 4;
|
|
|
|
memcpy (ip_address.iabuf,
|
|
|
|
fixed_addr.data + i, 4);
|
2000-05-16 23:03:49 +00:00
|
|
|
if (find_grouped_subnet (sp, share, ip_address, MDL)) {
|
|
|
|
struct host_decl *tmp = (struct host_decl *)0;
|
1999-09-28 22:49:31 +00:00
|
|
|
*addr = ip_address;
|
2000-05-16 23:03:49 +00:00
|
|
|
/* This is probably not necessary, but
|
|
|
|
just in case *host is the only reference
|
|
|
|
to that host declaration, make a temporary
|
|
|
|
reference so that dereferencing it doesn't
|
|
|
|
dereference hp out from under us. */
|
|
|
|
host_reference (&tmp, *host, MDL);
|
|
|
|
host_dereference (host, MDL);
|
|
|
|
host_reference (host, hp, MDL);
|
|
|
|
host_dereference (&tmp, MDL);
|
2000-01-26 14:56:18 +00:00
|
|
|
data_string_forget (&fixed_addr, MDL);
|
2000-05-16 23:03:49 +00:00
|
|
|
return 1;
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
}
|
2000-01-26 14:56:18 +00:00
|
|
|
data_string_forget (&fixed_addr, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
2000-05-16 23:03:49 +00:00
|
|
|
return 0;
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
2005-03-17 20:15:29 +00:00
|
|
|
void new_address_range (cfile, low, high, subnet, pool, lpchain)
|
|
|
|
struct parse *cfile;
|
1999-09-28 22:49:31 +00:00
|
|
|
struct iaddr low, high;
|
|
|
|
struct subnet *subnet;
|
|
|
|
struct pool *pool;
|
2005-03-17 20:15:29 +00:00
|
|
|
struct lease **lpchain;
|
1999-09-28 22:49:31 +00:00
|
|
|
{
|
2009-04-07 19:55:52 +00:00
|
|
|
#if defined(COMPACT_LEASES)
|
2007-07-13 06:43:43 +00:00
|
|
|
struct lease *address_range;
|
2015-05-27 13:17:46 -07:00
|
|
|
unsigned s;
|
2009-04-07 19:55:52 +00:00
|
|
|
#endif
|
2015-05-27 13:17:46 -07:00
|
|
|
unsigned min, max, i, num_addrs;
|
1999-09-28 22:49:31 +00:00
|
|
|
char lowbuf [16], highbuf [16], netbuf [16];
|
|
|
|
struct shared_network *share = subnet -> shared_network;
|
2000-06-07 00:15:53 +00:00
|
|
|
struct lease *lt = (struct lease *)0;
|
2007-07-13 06:43:43 +00:00
|
|
|
#if !defined(COMPACT_LEASES)
|
|
|
|
isc_result_t status;
|
|
|
|
#endif
|
1999-09-28 22:49:31 +00:00
|
|
|
|
|
|
|
/* All subnets should have attached shared network structures. */
|
|
|
|
if (!share) {
|
|
|
|
strcpy (netbuf, piaddr (subnet -> net));
|
|
|
|
log_fatal ("No shared network for network %s (%s)",
|
|
|
|
netbuf, piaddr (subnet -> netmask));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Initialize the hash table if it hasn't been done yet. */
|
|
|
|
if (!lease_uid_hash) {
|
2006-10-27 22:54:13 +00:00
|
|
|
if (!lease_id_new_hash(&lease_uid_hash, LEASE_HASH_SIZE, MDL))
|
1999-09-28 22:49:31 +00:00
|
|
|
log_fatal ("Can't allocate lease/uid hash");
|
|
|
|
}
|
|
|
|
if (!lease_ip_addr_hash) {
|
2006-10-27 22:54:13 +00:00
|
|
|
if (!lease_ip_new_hash(&lease_ip_addr_hash, LEASE_HASH_SIZE,
|
|
|
|
MDL))
|
1999-09-28 22:49:31 +00:00
|
|
|
log_fatal ("Can't allocate lease/ip hash");
|
|
|
|
}
|
|
|
|
if (!lease_hw_addr_hash) {
|
2006-10-27 22:54:13 +00:00
|
|
|
if (!lease_id_new_hash(&lease_hw_addr_hash, LEASE_HASH_SIZE,
|
|
|
|
MDL))
|
1999-09-28 22:49:31 +00:00
|
|
|
log_fatal ("Can't allocate lease/hw hash");
|
|
|
|
}
|
|
|
|
|
2007-12-13 16:50:17 +00:00
|
|
|
/* Make sure that high and low addresses are in this subnet. */
|
|
|
|
if (!addr_eq(subnet->net, subnet_number(low, subnet->netmask))) {
|
|
|
|
strcpy(lowbuf, piaddr(low));
|
|
|
|
strcpy(netbuf, piaddr(subnet->net));
|
|
|
|
log_fatal("bad range, address %s not in subnet %s netmask %s",
|
|
|
|
lowbuf, netbuf, piaddr(subnet->netmask));
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
2007-12-13 16:50:17 +00:00
|
|
|
if (!addr_eq(subnet->net, subnet_number(high, subnet->netmask))) {
|
|
|
|
strcpy(highbuf, piaddr(high));
|
|
|
|
strcpy(netbuf, piaddr(subnet->net));
|
|
|
|
log_fatal("bad range, address %s not in subnet %s netmask %s",
|
|
|
|
highbuf, netbuf, piaddr(subnet->netmask));
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the high and low host addresses... */
|
|
|
|
max = host_addr (high, subnet -> netmask);
|
|
|
|
min = host_addr (low, subnet -> netmask);
|
|
|
|
|
|
|
|
/* Allow range to be specified high-to-low as well as low-to-high. */
|
|
|
|
if (min > max) {
|
|
|
|
max = min;
|
|
|
|
min = host_addr (high, subnet -> netmask);
|
|
|
|
}
|
|
|
|
|
2015-05-27 13:17:46 -07:00
|
|
|
/* get the number of addresses we want, and add it to the pool info
|
|
|
|
* this value is only for use when setting up lease chains and will
|
|
|
|
* be overwritten when expire_all_pools is run
|
|
|
|
*/
|
|
|
|
num_addrs = max - min + 1;
|
|
|
|
#if defined (BINARY_LEASES)
|
|
|
|
pool->lease_count += num_addrs;
|
|
|
|
#endif
|
|
|
|
|
1999-09-28 22:49:31 +00:00
|
|
|
/* Get a lease structure for each address in the range. */
|
2000-05-16 23:03:49 +00:00
|
|
|
#if defined (COMPACT_LEASES)
|
2015-05-27 13:17:46 -07:00
|
|
|
s = (num_addrs + 1) * sizeof (struct lease);
|
2015-04-10 13:15:40 +02:00
|
|
|
/* Check unsigned overflow in new_leases().
|
|
|
|
With 304 byte lease structure (x64_86), this happens at
|
|
|
|
range 10.0.0.0 10.215.148.52; */
|
|
|
|
if (((s % sizeof (struct lease)) != 0) ||
|
2015-05-27 13:17:46 -07:00
|
|
|
((s / sizeof (struct lease)) != (num_addrs + 1))) {
|
2015-04-10 13:15:40 +02:00
|
|
|
strcpy (lowbuf, piaddr (low));
|
|
|
|
strcpy (highbuf, piaddr (high));
|
2015-05-27 13:17:46 -07:00
|
|
|
parse_warn (cfile, "%s-%s is an overly large address range.",
|
2015-04-10 13:15:40 +02:00
|
|
|
lowbuf, highbuf);
|
|
|
|
log_fatal ("Memory overflow.");
|
|
|
|
}
|
2015-05-27 13:17:46 -07:00
|
|
|
address_range = new_leases (num_addrs, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
if (!address_range) {
|
|
|
|
strcpy (lowbuf, piaddr (low));
|
|
|
|
strcpy (highbuf, piaddr (high));
|
|
|
|
log_fatal ("No memory for address range %s-%s.",
|
|
|
|
lowbuf, highbuf);
|
|
|
|
}
|
2000-05-16 23:03:49 +00:00
|
|
|
#endif
|
1999-09-28 22:49:31 +00:00
|
|
|
|
|
|
|
/* Fill out the lease structures with some minimal information. */
|
2015-05-27 13:17:46 -07:00
|
|
|
for (i = 0; i < num_addrs; i++) {
|
2000-05-16 23:03:49 +00:00
|
|
|
struct lease *lp = (struct lease *)0;
|
|
|
|
#if defined (COMPACT_LEASES)
|
|
|
|
omapi_object_initialize ((omapi_object_t *)&address_range [i],
|
|
|
|
dhcp_type_lease,
|
|
|
|
0, sizeof (struct lease), MDL);
|
|
|
|
lease_reference (&lp, &address_range [i], MDL);
|
|
|
|
#else
|
|
|
|
status = lease_allocate (&lp, MDL);
|
|
|
|
if (status != ISC_R_SUCCESS)
|
|
|
|
log_fatal ("No memory for lease %s: %s",
|
|
|
|
piaddr (ip_addr (subnet -> net,
|
|
|
|
subnet -> netmask,
|
|
|
|
i + min)),
|
|
|
|
isc_result_totext (status));
|
|
|
|
#endif
|
2010-02-03 23:25:25 +00:00
|
|
|
lp->ip_addr = ip_addr(subnet->net, subnet->netmask, i + min);
|
|
|
|
lp->starts = MIN_TIME;
|
|
|
|
lp->ends = MIN_TIME;
|
|
|
|
subnet_reference(&lp->subnet, subnet, MDL);
|
|
|
|
pool_reference(&lp->pool, pool, MDL);
|
|
|
|
lp->binding_state = FTS_FREE;
|
|
|
|
lp->next_binding_state = FTS_FREE;
|
|
|
|
lp->rewind_binding_state = FTS_FREE;
|
|
|
|
lp->flags = 0;
|
1999-09-28 22:49:31 +00:00
|
|
|
|
2000-06-07 00:15:53 +00:00
|
|
|
/* Remember the lease in the IP address hash. */
|
|
|
|
if (find_lease_by_ip_addr (<, lp -> ip_addr, MDL)) {
|
|
|
|
if (lt -> pool) {
|
2005-03-17 20:15:29 +00:00
|
|
|
parse_warn (cfile,
|
|
|
|
"lease %s is declared twice!",
|
|
|
|
piaddr (lp -> ip_addr));
|
2000-06-07 00:15:53 +00:00
|
|
|
} else
|
|
|
|
pool_reference (< -> pool, pool, MDL);
|
|
|
|
lease_dereference (<, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
} else
|
2006-10-27 22:54:13 +00:00
|
|
|
lease_ip_hash_add(lease_ip_addr_hash,
|
|
|
|
lp->ip_addr.iabuf, lp->ip_addr.len,
|
|
|
|
lp, MDL);
|
2005-03-17 20:15:29 +00:00
|
|
|
/* Put the lease on the chain for the caller. */
|
|
|
|
if (lpchain) {
|
|
|
|
if (*lpchain) {
|
|
|
|
lease_reference (&lp -> next, *lpchain, MDL);
|
|
|
|
lease_dereference (lpchain, MDL);
|
|
|
|
}
|
|
|
|
lease_reference (lpchain, lp, MDL);
|
|
|
|
}
|
2000-07-05 07:38:09 +00:00
|
|
|
lease_dereference (&lp, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-05-16 23:03:49 +00:00
|
|
|
int find_subnet (struct subnet **sp,
|
|
|
|
struct iaddr addr, const char *file, int line)
|
1999-09-28 22:49:31 +00:00
|
|
|
{
|
|
|
|
struct subnet *rv;
|
|
|
|
|
|
|
|
for (rv = subnets; rv; rv = rv -> next_subnet) {
|
2016-02-23 10:40:10 +01:00
|
|
|
#if defined(DHCP4o6)
|
|
|
|
if (addr.len != rv->netmask.len)
|
|
|
|
continue;
|
|
|
|
#endif
|
2000-05-16 23:03:49 +00:00
|
|
|
if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
|
|
|
|
if (subnet_reference (sp, rv,
|
|
|
|
file, line) != ISC_R_SUCCESS)
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
2000-05-16 23:03:49 +00:00
|
|
|
return 0;
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
2000-05-16 23:03:49 +00:00
|
|
|
int find_grouped_subnet (struct subnet **sp,
|
|
|
|
struct shared_network *share, struct iaddr addr,
|
|
|
|
const char *file, int line)
|
1999-09-28 22:49:31 +00:00
|
|
|
{
|
|
|
|
struct subnet *rv;
|
|
|
|
|
|
|
|
for (rv = share -> subnets; rv; rv = rv -> next_sibling) {
|
2016-02-23 10:40:10 +01:00
|
|
|
#if defined(DHCP4o6)
|
|
|
|
if (addr.len != rv->netmask.len)
|
|
|
|
continue;
|
|
|
|
#endif
|
2000-05-16 23:03:49 +00:00
|
|
|
if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
|
|
|
|
if (subnet_reference (sp, rv,
|
|
|
|
file, line) != ISC_R_SUCCESS)
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
2000-05-16 23:03:49 +00:00
|
|
|
return 0;
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
2007-05-08 23:05:22 +00:00
|
|
|
/* XXX: could speed up if everyone had a prefix length */
|
2019-11-22 13:39:45 -05:00
|
|
|
int
|
|
|
|
subnet_inner_than(const struct subnet *subnet,
|
2007-05-08 23:05:22 +00:00
|
|
|
const struct subnet *scan,
|
|
|
|
int warnp) {
|
2016-02-23 10:40:10 +01:00
|
|
|
#if defined(DHCP4o6)
|
|
|
|
if (subnet->net.len != scan->net.len)
|
|
|
|
return 0;
|
|
|
|
#endif
|
2007-05-08 23:05:22 +00:00
|
|
|
if (addr_eq(subnet_number(subnet->net, scan->netmask), scan->net) ||
|
|
|
|
addr_eq(subnet_number(scan->net, subnet->netmask), subnet->net)) {
|
|
|
|
char n1buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255")];
|
1999-09-28 22:49:31 +00:00
|
|
|
int i, j;
|
2007-05-08 23:05:22 +00:00
|
|
|
for (i = 0; i < 128; i++)
|
|
|
|
if (subnet->netmask.iabuf[3 - (i >> 3)]
|
1999-09-28 22:49:31 +00:00
|
|
|
& (1 << (i & 7)))
|
|
|
|
break;
|
2007-05-08 23:05:22 +00:00
|
|
|
for (j = 0; j < 128; j++)
|
|
|
|
if (scan->netmask.iabuf[3 - (j >> 3)] &
|
1999-09-28 22:49:31 +00:00
|
|
|
(1 << (j & 7)))
|
|
|
|
break;
|
2007-05-08 23:05:22 +00:00
|
|
|
if (warnp) {
|
|
|
|
strcpy(n1buf, piaddr(subnet->net));
|
|
|
|
log_error("Warning: subnet %s/%d overlaps subnet %s/%d",
|
|
|
|
n1buf, 32 - i,
|
|
|
|
piaddr(scan->net), 32 - j);
|
|
|
|
}
|
1999-09-28 22:49:31 +00:00
|
|
|
if (i < j)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Enter a new subnet into the subnet list. */
|
|
|
|
void enter_subnet (subnet)
|
|
|
|
struct subnet *subnet;
|
|
|
|
{
|
2001-06-27 00:31:20 +00:00
|
|
|
struct subnet *scan = (struct subnet *)0;
|
|
|
|
struct subnet *next = (struct subnet *)0;
|
|
|
|
struct subnet *prev = (struct subnet *)0;
|
1999-09-28 22:49:31 +00:00
|
|
|
|
|
|
|
/* Check for duplicates... */
|
2001-06-27 00:31:20 +00:00
|
|
|
if (subnets)
|
|
|
|
subnet_reference (&next, subnets, MDL);
|
|
|
|
while (next) {
|
|
|
|
subnet_reference (&scan, next, MDL);
|
|
|
|
subnet_dereference (&next, MDL);
|
|
|
|
|
|
|
|
/* When we find a conflict, make sure that the
|
|
|
|
subnet with the narrowest subnet mask comes
|
|
|
|
first. */
|
|
|
|
if (subnet_inner_than (subnet, scan, 1)) {
|
|
|
|
if (prev) {
|
|
|
|
if (prev -> next_subnet)
|
|
|
|
subnet_dereference (&prev -> next_subnet, MDL);
|
|
|
|
subnet_reference (&prev -> next_subnet, subnet, MDL);
|
|
|
|
subnet_dereference (&prev, MDL);
|
|
|
|
} else {
|
|
|
|
subnet_dereference (&subnets, MDL);
|
|
|
|
subnet_reference (&subnets, subnet, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
2001-06-27 00:31:20 +00:00
|
|
|
subnet_reference (&subnet -> next_subnet, scan, MDL);
|
|
|
|
subnet_dereference (&scan, MDL);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
subnet_reference (&prev, scan, MDL);
|
|
|
|
subnet_dereference (&scan, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
2001-06-27 00:31:20 +00:00
|
|
|
if (prev)
|
|
|
|
subnet_dereference (&prev, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
|
|
|
|
/* XXX use the BSD radix tree code instead of a linked list. */
|
2001-06-27 00:31:20 +00:00
|
|
|
if (subnets) {
|
|
|
|
subnet_reference (&subnet -> next_subnet, subnets, MDL);
|
|
|
|
subnet_dereference (&subnets, MDL);
|
|
|
|
}
|
|
|
|
subnet_reference (&subnets, subnet, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
2019-11-22 13:39:45 -05:00
|
|
|
|
1999-09-28 22:49:31 +00:00
|
|
|
/* Enter a new shared network into the shared network list. */
|
|
|
|
|
|
|
|
void enter_shared_network (share)
|
|
|
|
struct shared_network *share;
|
|
|
|
{
|
2000-05-16 23:03:49 +00:00
|
|
|
if (shared_networks) {
|
|
|
|
shared_network_reference (&share -> next,
|
|
|
|
shared_networks, MDL);
|
|
|
|
shared_network_dereference (&shared_networks, MDL);
|
|
|
|
}
|
|
|
|
shared_network_reference (&shared_networks, share, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
2019-11-22 13:39:45 -05:00
|
|
|
|
1999-10-24 17:19:46 +00:00
|
|
|
void new_shared_network_interface (cfile, share, name)
|
|
|
|
struct parse *cfile;
|
|
|
|
struct shared_network *share;
|
|
|
|
const char *name;
|
|
|
|
{
|
|
|
|
struct interface_info *ip;
|
2000-05-16 23:03:49 +00:00
|
|
|
isc_result_t status;
|
1999-10-24 17:19:46 +00:00
|
|
|
|
|
|
|
if (share -> interface) {
|
2019-11-22 13:39:45 -05:00
|
|
|
parse_warn (cfile,
|
1999-10-24 17:19:46 +00:00
|
|
|
"A subnet or shared network can't be connected %s",
|
|
|
|
"to two interfaces.");
|
|
|
|
return;
|
|
|
|
}
|
2019-11-22 13:39:45 -05:00
|
|
|
|
1999-10-24 17:19:46 +00:00
|
|
|
for (ip = interfaces; ip; ip = ip -> next)
|
|
|
|
if (!strcmp (ip -> name, name))
|
|
|
|
break;
|
|
|
|
if (!ip) {
|
2000-05-16 23:03:49 +00:00
|
|
|
status = interface_allocate (&ip, MDL);
|
|
|
|
if (status != ISC_R_SUCCESS)
|
|
|
|
log_fatal ("new_shared_network_interface %s: %s",
|
|
|
|
name, isc_result_totext (status));
|
1999-10-24 17:19:46 +00:00
|
|
|
if (strlen (name) > sizeof ip -> name) {
|
|
|
|
memcpy (ip -> name, name, (sizeof ip -> name) - 1);
|
|
|
|
ip -> name [(sizeof ip -> name) - 1] = 0;
|
|
|
|
} else
|
|
|
|
strcpy (ip -> name, name);
|
2000-05-16 23:03:49 +00:00
|
|
|
if (interfaces) {
|
|
|
|
interface_reference (&ip -> next, interfaces, MDL);
|
|
|
|
interface_dereference (&interfaces, MDL);
|
|
|
|
}
|
|
|
|
interface_reference (&interfaces, ip, MDL);
|
1999-10-24 17:19:46 +00:00
|
|
|
ip -> flags = INTERFACE_REQUESTED;
|
2000-05-16 23:03:49 +00:00
|
|
|
/* XXX this is a reference loop. */
|
|
|
|
shared_network_reference (&ip -> shared_network, share, MDL);
|
|
|
|
interface_reference (&share -> interface, ip, MDL);
|
1999-10-24 17:19:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-09-28 22:49:31 +00:00
|
|
|
/* Enter a lease into the system. This is called by the parser each
|
|
|
|
time it reads in a new lease. If the subnet for that lease has
|
|
|
|
already been read in (usually the case), just update that lease;
|
|
|
|
otherwise, allocate temporary storage for the lease and keep it around
|
|
|
|
until we're done reading in the config file. */
|
|
|
|
|
|
|
|
void enter_lease (lease)
|
|
|
|
struct lease *lease;
|
|
|
|
{
|
2000-05-16 23:03:49 +00:00
|
|
|
struct lease *comp = (struct lease *)0;
|
1999-09-28 22:49:31 +00:00
|
|
|
|
2000-06-07 00:15:53 +00:00
|
|
|
if (find_lease_by_ip_addr (&comp, lease -> ip_addr, MDL)) {
|
|
|
|
if (!comp -> pool) {
|
|
|
|
log_error ("undeclared lease found in database: %s",
|
|
|
|
piaddr (lease -> ip_addr));
|
|
|
|
} else
|
|
|
|
pool_reference (&lease -> pool, comp -> pool, MDL);
|
|
|
|
|
|
|
|
if (comp -> subnet)
|
|
|
|
subnet_reference (&lease -> subnet,
|
|
|
|
comp -> subnet, MDL);
|
2006-10-27 22:54:13 +00:00
|
|
|
lease_ip_hash_delete(lease_ip_addr_hash,
|
|
|
|
lease->ip_addr.iabuf, lease->ip_addr.len,
|
|
|
|
MDL);
|
2000-06-07 00:15:53 +00:00
|
|
|
lease_dereference (&comp, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
2000-09-29 18:21:33 +00:00
|
|
|
|
|
|
|
/* The only way a lease can get here without a subnet is if it's in
|
|
|
|
the lease file, but not in the dhcpd.conf file. In this case, we
|
|
|
|
*should* keep it around until it's expired, but never reallocate it
|
|
|
|
or renew it. Currently, to maintain consistency, we are not doing
|
|
|
|
this.
|
|
|
|
XXX fix this so that the lease is kept around until it expires.
|
|
|
|
XXX this will be important in IPv6 with addresses that become
|
|
|
|
XXX non-renewable as a result of a renumbering event. */
|
|
|
|
|
|
|
|
if (!lease -> subnet) {
|
|
|
|
log_error ("lease %s: no subnet.", piaddr (lease -> ip_addr));
|
|
|
|
return;
|
|
|
|
}
|
2006-10-27 22:54:13 +00:00
|
|
|
lease_ip_hash_add(lease_ip_addr_hash, lease->ip_addr.iabuf,
|
|
|
|
lease->ip_addr.len, lease, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Replace the data in an existing lease with the data in a new lease;
|
|
|
|
adjust hash tables to suit, and insertion sort the lease into the
|
|
|
|
list of leases by expiry time so that we can always find the oldest
|
|
|
|
lease. */
|
|
|
|
|
2014-12-10 19:08:05 -08:00
|
|
|
int supersede_lease (comp, lease, commit, propogate, pimmediate, from_pool)
|
1999-09-28 22:49:31 +00:00
|
|
|
struct lease *comp, *lease;
|
|
|
|
int commit;
|
2000-05-04 18:58:16 +00:00
|
|
|
int propogate;
|
2000-06-02 21:27:21 +00:00
|
|
|
int pimmediate;
|
2014-12-10 19:08:05 -08:00
|
|
|
int from_pool;
|
1999-09-28 22:49:31 +00:00
|
|
|
{
|
2015-05-27 13:17:46 -07:00
|
|
|
LEASE_STRUCT_PTR lq;
|
2008-01-08 17:51:01 +00:00
|
|
|
struct timeval tv;
|
2001-02-15 21:34:08 +00:00
|
|
|
#if defined (FAILOVER_PROTOCOL)
|
2006-06-16 19:26:45 +00:00
|
|
|
int do_pool_check = 0;
|
|
|
|
|
2001-02-15 21:34:08 +00:00
|
|
|
/* We must commit leases before sending updates regarding them
|
|
|
|
to failover peers. It is, therefore, an error to set pimmediate
|
|
|
|
and not commit. */
|
|
|
|
if (pimmediate && !commit)
|
|
|
|
return 0;
|
|
|
|
#endif
|
2000-06-02 21:27:21 +00:00
|
|
|
/* If there is no sample lease, just do the move. */
|
|
|
|
if (!lease)
|
|
|
|
goto just_move_it;
|
1999-09-28 22:49:31 +00:00
|
|
|
|
|
|
|
/* Static leases are not currently kept in the database... */
|
|
|
|
if (lease -> flags & STATIC_LEASE)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* If the existing lease hasn't expired and has a different
|
|
|
|
unique identifier or, if it doesn't have a unique
|
|
|
|
identifier, a different hardware address, then the two
|
|
|
|
leases are in conflict. If the existing lease has a uid
|
|
|
|
and the new one doesn't, but they both have the same
|
|
|
|
hardware address, and dynamic bootp is allowed on this
|
|
|
|
lease, then we allow that, in case a dynamic BOOTP lease is
|
|
|
|
requested *after* a DHCP lease has been assigned. */
|
|
|
|
|
2000-06-02 21:27:21 +00:00
|
|
|
if (lease -> binding_state != FTS_ABANDONED &&
|
2001-05-17 19:04:09 +00:00
|
|
|
lease -> next_binding_state != FTS_ABANDONED &&
|
2006-04-27 17:26:42 +00:00
|
|
|
comp -> binding_state == FTS_ACTIVE &&
|
1999-09-28 22:49:31 +00:00
|
|
|
(((comp -> uid && lease -> uid) &&
|
|
|
|
(comp -> uid_len != lease -> uid_len ||
|
|
|
|
memcmp (comp -> uid, lease -> uid, comp -> uid_len))) ||
|
|
|
|
(!comp -> uid &&
|
2000-01-05 18:22:07 +00:00
|
|
|
((comp -> hardware_addr.hlen !=
|
1999-09-28 22:49:31 +00:00
|
|
|
lease -> hardware_addr.hlen) ||
|
2000-01-05 18:22:07 +00:00
|
|
|
memcmp (comp -> hardware_addr.hbuf,
|
|
|
|
lease -> hardware_addr.hbuf,
|
1999-09-28 22:49:31 +00:00
|
|
|
comp -> hardware_addr.hlen))))) {
|
|
|
|
log_error ("Lease conflict at %s",
|
|
|
|
piaddr (comp -> ip_addr));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If there's a Unique ID, dissociate it from the hash
|
|
|
|
table and free it if necessary. */
|
2007-06-08 18:56:30 +00:00
|
|
|
if (comp->uid) {
|
|
|
|
uid_hash_delete(comp);
|
|
|
|
if (comp->uid != comp->uid_buf) {
|
|
|
|
dfree(comp->uid, MDL);
|
|
|
|
comp->uid_max = 0;
|
|
|
|
comp->uid_len = 0;
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
comp -> uid = (unsigned char *)0;
|
2007-06-08 18:56:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* If there's a hardware address, remove the lease from its
|
|
|
|
* old position in the hash bucket's ordered list.
|
|
|
|
*/
|
|
|
|
if (comp->hardware_addr.hlen)
|
|
|
|
hw_hash_delete(comp);
|
2006-02-24 23:16:32 +00:00
|
|
|
|
1999-09-28 22:49:31 +00:00
|
|
|
/* If the lease has been billed to a class, remove the billing. */
|
2000-07-05 07:38:09 +00:00
|
|
|
if (comp -> billing_class != lease -> billing_class) {
|
2015-07-29 08:32:50 -04:00
|
|
|
if (comp->billing_class)
|
|
|
|
unbill_class(comp);
|
2000-07-05 07:38:09 +00:00
|
|
|
if (lease -> billing_class)
|
|
|
|
bill_class (comp, lease -> billing_class);
|
|
|
|
}
|
1999-09-28 22:49:31 +00:00
|
|
|
|
|
|
|
/* Copy the data files, but not the linkages. */
|
|
|
|
comp -> starts = lease -> starts;
|
|
|
|
if (lease -> uid) {
|
1999-11-20 18:36:32 +00:00
|
|
|
if (lease -> uid_len <= sizeof (lease -> uid_buf)) {
|
1999-09-28 22:49:31 +00:00
|
|
|
memcpy (comp -> uid_buf,
|
|
|
|
lease -> uid, lease -> uid_len);
|
|
|
|
comp -> uid = &comp -> uid_buf [0];
|
|
|
|
comp -> uid_max = sizeof comp -> uid_buf;
|
2001-02-12 21:09:21 +00:00
|
|
|
comp -> uid_len = lease -> uid_len;
|
1999-09-28 22:49:31 +00:00
|
|
|
} else if (lease -> uid != &lease -> uid_buf [0]) {
|
|
|
|
comp -> uid = lease -> uid;
|
|
|
|
comp -> uid_max = lease -> uid_max;
|
|
|
|
lease -> uid = (unsigned char *)0;
|
|
|
|
lease -> uid_max = 0;
|
2001-02-12 21:09:21 +00:00
|
|
|
comp -> uid_len = lease -> uid_len;
|
|
|
|
lease -> uid_len = 0;
|
1999-09-28 22:49:31 +00:00
|
|
|
} else {
|
|
|
|
log_fatal ("corrupt lease uid."); /* XXX */
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
comp -> uid = (unsigned char *)0;
|
2001-02-12 21:09:21 +00:00
|
|
|
comp -> uid_len = comp -> uid_max = 0;
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
2000-05-16 23:03:49 +00:00
|
|
|
if (comp -> host)
|
|
|
|
host_dereference (&comp -> host, MDL);
|
|
|
|
host_reference (&comp -> host, lease -> host, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
comp -> hardware_addr = lease -> hardware_addr;
|
2000-07-27 09:03:08 +00:00
|
|
|
if (comp -> scope)
|
|
|
|
binding_scope_dereference (&comp -> scope, MDL);
|
|
|
|
if (lease -> scope) {
|
|
|
|
binding_scope_reference (&comp -> scope, lease -> scope, MDL);
|
|
|
|
binding_scope_dereference (&lease -> scope, MDL);
|
|
|
|
}
|
1999-09-28 22:49:31 +00:00
|
|
|
|
2000-11-28 23:27:24 +00:00
|
|
|
if (comp -> agent_options)
|
2001-01-25 08:36:36 +00:00
|
|
|
option_chain_head_dereference (&comp -> agent_options, MDL);
|
2000-11-28 23:27:24 +00:00
|
|
|
if (lease -> agent_options) {
|
|
|
|
/* Only retain the agent options if the lease is still
|
|
|
|
affirmatively associated with a client. */
|
2001-01-25 08:36:36 +00:00
|
|
|
if (lease -> next_binding_state == FTS_ACTIVE ||
|
2005-03-17 20:15:29 +00:00
|
|
|
lease -> next_binding_state == FTS_EXPIRED)
|
2001-01-25 08:36:36 +00:00
|
|
|
option_chain_head_reference (&comp -> agent_options,
|
|
|
|
lease -> agent_options,
|
|
|
|
MDL);
|
|
|
|
option_chain_head_dereference (&lease -> agent_options, MDL);
|
2000-11-28 23:27:24 +00:00
|
|
|
}
|
|
|
|
|
2000-05-16 23:03:49 +00:00
|
|
|
/* Record the hostname information in the lease. */
|
|
|
|
if (comp -> client_hostname)
|
|
|
|
dfree (comp -> client_hostname, MDL);
|
|
|
|
comp -> client_hostname = lease -> client_hostname;
|
|
|
|
lease -> client_hostname = (char *)0;
|
|
|
|
|
2013-08-27 13:40:47 -07:00
|
|
|
if (lease->on_star.on_expiry) {
|
|
|
|
if (comp->on_star.on_expiry)
|
|
|
|
executable_statement_dereference
|
|
|
|
(&comp->on_star.on_expiry, MDL);
|
|
|
|
executable_statement_reference (&comp->on_star.on_expiry,
|
|
|
|
lease->on_star.on_expiry,
|
2000-01-26 14:56:18 +00:00
|
|
|
MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
2013-08-27 13:40:47 -07:00
|
|
|
if (lease->on_star.on_commit) {
|
|
|
|
if (comp->on_star.on_commit)
|
|
|
|
executable_statement_dereference
|
|
|
|
(&comp->on_star.on_commit, MDL);
|
|
|
|
executable_statement_reference (&comp->on_star.on_commit,
|
|
|
|
lease->on_star.on_commit,
|
2000-01-26 14:56:18 +00:00
|
|
|
MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
2013-08-27 13:40:47 -07:00
|
|
|
if (lease->on_star.on_release) {
|
|
|
|
if (comp->on_star.on_release)
|
|
|
|
executable_statement_dereference
|
|
|
|
(&comp->on_star.on_release, MDL);
|
|
|
|
executable_statement_reference (&comp->on_star.on_release,
|
|
|
|
lease->on_star.on_release,
|
|
|
|
MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
2006-02-24 23:16:32 +00:00
|
|
|
|
1999-09-28 22:49:31 +00:00
|
|
|
/* Record the lease in the uid hash if necessary. */
|
2007-06-08 18:56:30 +00:00
|
|
|
if (comp->uid)
|
|
|
|
uid_hash_add(comp);
|
2006-02-24 23:16:32 +00:00
|
|
|
|
1999-09-28 22:49:31 +00:00
|
|
|
/* Record it in the hardware address hash if necessary. */
|
2007-06-08 18:56:30 +00:00
|
|
|
if (comp->hardware_addr.hlen)
|
|
|
|
hw_hash_add(comp);
|
2006-02-24 23:16:32 +00:00
|
|
|
|
|
|
|
comp->cltt = lease->cltt;
|
2006-07-25 13:26:00 +00:00
|
|
|
#if defined (FAILOVER_PROTOCOL)
|
2006-02-24 23:16:32 +00:00
|
|
|
comp->tstp = lease->tstp;
|
|
|
|
comp->tsfp = lease->tsfp;
|
|
|
|
comp->atsfp = lease->atsfp;
|
2000-06-02 21:27:21 +00:00
|
|
|
#endif /* FAILOVER_PROTOCOL */
|
2006-02-24 23:16:32 +00:00
|
|
|
comp->ends = lease->ends;
|
|
|
|
comp->next_binding_state = lease->next_binding_state;
|
2000-06-02 21:27:21 +00:00
|
|
|
|
2011-02-18 18:18:20 +00:00
|
|
|
/*
|
|
|
|
* If we have a control block pointer copy it in.
|
|
|
|
* We don't zero out an older ponter as it is still
|
|
|
|
* in use. We shouldn't need to overwrite an
|
|
|
|
* old pointer with a new one as the old transaction
|
|
|
|
* should have been cancelled before getting here.
|
|
|
|
*/
|
|
|
|
if (lease->ddns_cb != NULL)
|
|
|
|
comp->ddns_cb = lease->ddns_cb;
|
2009-10-28 04:12:30 +00:00
|
|
|
|
2000-06-02 21:27:21 +00:00
|
|
|
just_move_it:
|
2006-02-24 23:16:32 +00:00
|
|
|
#if defined (FAILOVER_PROTOCOL)
|
2010-02-03 23:25:25 +00:00
|
|
|
/*
|
|
|
|
* Atsfp should be cleared upon any state change that implies
|
2007-11-30 21:51:43 +00:00
|
|
|
* propagation whether supersede_lease was given a copy lease
|
2006-02-24 23:16:32 +00:00
|
|
|
* structure or not (often from the pool_timer()).
|
|
|
|
*/
|
|
|
|
if (propogate)
|
|
|
|
comp->atsfp = 0;
|
|
|
|
#endif /* FAILOVER_PROTOCOL */
|
|
|
|
|
2001-01-06 21:39:30 +00:00
|
|
|
if (!comp -> pool) {
|
|
|
|
log_error ("Supersede_lease: lease %s with no pool.",
|
2001-01-25 08:36:36 +00:00
|
|
|
piaddr (comp -> ip_addr));
|
2001-01-06 21:39:30 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2000-06-02 21:27:21 +00:00
|
|
|
/* Figure out which queue it's on. */
|
|
|
|
switch (comp -> binding_state) {
|
|
|
|
case FTS_FREE:
|
2009-01-30 22:31:22 +00:00
|
|
|
if (comp->flags & RESERVED_LEASE)
|
|
|
|
lq = &comp->pool->reserved;
|
|
|
|
else {
|
|
|
|
lq = &comp->pool->free;
|
2006-04-27 17:26:42 +00:00
|
|
|
comp->pool->free_leases--;
|
2009-01-30 22:31:22 +00:00
|
|
|
}
|
2006-06-16 19:26:45 +00:00
|
|
|
|
|
|
|
#if defined(FAILOVER_PROTOCOL)
|
|
|
|
do_pool_check = 1;
|
|
|
|
#endif
|
2000-06-02 21:27:21 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FTS_ACTIVE:
|
|
|
|
lq = &comp -> pool -> active;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FTS_EXPIRED:
|
|
|
|
case FTS_RELEASED:
|
|
|
|
case FTS_RESET:
|
|
|
|
lq = &comp -> pool -> expired;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FTS_ABANDONED:
|
|
|
|
lq = &comp -> pool -> abandoned;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FTS_BACKUP:
|
2009-01-30 22:31:22 +00:00
|
|
|
if (comp->flags & RESERVED_LEASE)
|
|
|
|
lq = &comp->pool->reserved;
|
|
|
|
else {
|
|
|
|
lq = &comp->pool->backup;
|
2006-04-27 17:26:42 +00:00
|
|
|
comp->pool->backup_leases--;
|
2009-01-30 22:31:22 +00:00
|
|
|
}
|
2006-06-16 19:26:45 +00:00
|
|
|
|
|
|
|
#if defined(FAILOVER_PROTOCOL)
|
|
|
|
do_pool_check = 1;
|
|
|
|
#endif
|
2000-06-02 21:27:21 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
log_error ("Lease with bogus binding state: %d",
|
|
|
|
comp -> binding_state);
|
2001-04-16 22:32:58 +00:00
|
|
|
#if defined (BINDING_STATE_DEBUG)
|
|
|
|
abort ();
|
|
|
|
#endif
|
2000-06-02 21:27:21 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Remove the lease from its current place in its current
|
|
|
|
timer sequence. */
|
2015-05-27 13:17:46 -07:00
|
|
|
LEASE_REMOVEP(lq, comp);
|
2000-05-16 23:03:49 +00:00
|
|
|
|
2016-02-05 09:03:51 -05:00
|
|
|
/* Now that we've done the flag-affected queue removal
|
|
|
|
* we can update the new lease's flags, if there's an
|
|
|
|
* existing lease */
|
|
|
|
if (lease) {
|
|
|
|
comp->flags = ((lease->flags & ~PERSISTENT_FLAGS) |
|
|
|
|
(comp->flags & ~EPHEMERAL_FLAGS));
|
|
|
|
}
|
|
|
|
|
2000-06-02 21:27:21 +00:00
|
|
|
/* Make the state transition. */
|
2001-04-06 01:03:39 +00:00
|
|
|
if (commit || !pimmediate)
|
2001-04-16 22:32:58 +00:00
|
|
|
make_binding_state_transition (comp);
|
2000-06-02 21:27:21 +00:00
|
|
|
|
2000-06-07 00:15:53 +00:00
|
|
|
/* Put the lease back on the appropriate queue. If the lease
|
|
|
|
is corrupt (as detected by lease_enqueue), don't go any farther. */
|
|
|
|
if (!lease_enqueue (comp))
|
2000-06-02 21:27:21 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* If this is the next lease that will timeout on the pool,
|
|
|
|
zap the old timeout and set the timeout on this pool to the
|
|
|
|
time that the lease's next event will happen.
|
2019-11-22 13:39:45 -05:00
|
|
|
|
2000-06-02 21:27:21 +00:00
|
|
|
We do not actually set the timeout unless commit is true -
|
|
|
|
we don't want to thrash the timer queue when reading the
|
|
|
|
lease database. Instead, the database code calls the
|
|
|
|
expiry event on each pool after reading in the lease file,
|
|
|
|
and the expiry code sets the timer if there's anything left
|
|
|
|
to expire after it's run any outstanding expiry events on
|
|
|
|
the pool. */
|
2001-05-17 19:04:09 +00:00
|
|
|
if ((commit || !pimmediate) &&
|
2000-06-02 21:27:21 +00:00
|
|
|
comp -> sort_time != MIN_TIME &&
|
2000-07-06 10:27:41 +00:00
|
|
|
comp -> sort_time > cur_time &&
|
|
|
|
(comp -> sort_time < comp -> pool -> next_event_time ||
|
|
|
|
comp -> pool -> next_event_time == MIN_TIME)) {
|
2000-06-02 21:27:21 +00:00
|
|
|
comp -> pool -> next_event_time = comp -> sort_time;
|
2008-01-03 00:30:14 +00:00
|
|
|
tv . tv_sec = comp -> pool -> next_event_time;
|
|
|
|
tv . tv_usec = 0;
|
|
|
|
add_timeout (&tv,
|
2000-06-02 21:27:21 +00:00
|
|
|
pool_timer, comp -> pool,
|
|
|
|
(tvref_t)pool_reference,
|
|
|
|
(tvunref_t)pool_dereference);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
2001-02-15 21:34:08 +00:00
|
|
|
if (commit) {
|
2010-02-03 23:25:25 +00:00
|
|
|
#if defined(FAILOVER_PROTOCOL)
|
|
|
|
/*
|
|
|
|
* If commit and propogate are set, then we can save a
|
|
|
|
* possible fsync later in BNDUPD socket transmission by
|
|
|
|
* stepping the rewind state forward to the new state, in
|
|
|
|
* case it has changed. This is only worth doing if the
|
|
|
|
* failover connection is currently connected, as in this
|
|
|
|
* case it is likely we will be transmitting to the peer very
|
|
|
|
* shortly.
|
|
|
|
*/
|
|
|
|
if (propogate && (comp->pool->failover_peer != NULL) &&
|
|
|
|
((comp->pool->failover_peer->service_state ==
|
|
|
|
cooperating) ||
|
|
|
|
(comp->pool->failover_peer->service_state ==
|
|
|
|
not_responding)))
|
|
|
|
comp->rewind_binding_state = comp->binding_state;
|
|
|
|
#endif
|
|
|
|
|
2001-02-15 21:34:08 +00:00
|
|
|
if (!write_lease (comp))
|
|
|
|
return 0;
|
2006-06-09 15:51:02 +00:00
|
|
|
if ((server_starting & SS_NOSYNC) == 0) {
|
|
|
|
if (!commit_leases ())
|
|
|
|
return 0;
|
|
|
|
}
|
2001-02-15 21:34:08 +00:00
|
|
|
}
|
|
|
|
|
2000-06-02 21:27:21 +00:00
|
|
|
#if defined (FAILOVER_PROTOCOL)
|
2001-02-15 21:34:08 +00:00
|
|
|
if (propogate) {
|
2005-03-17 20:15:29 +00:00
|
|
|
comp -> desired_binding_state = comp -> binding_state;
|
2001-02-15 21:34:08 +00:00
|
|
|
if (!dhcp_failover_queue_update (comp, pimmediate))
|
|
|
|
return 0;
|
|
|
|
}
|
2006-06-16 19:26:45 +00:00
|
|
|
if (do_pool_check && comp->pool->failover_peer)
|
|
|
|
dhcp_failover_pool_check(comp->pool);
|
2000-01-05 18:22:07 +00:00
|
|
|
#endif
|
2001-02-15 21:34:08 +00:00
|
|
|
|
2014-12-10 19:08:05 -08:00
|
|
|
/* If the current binding state has already expired and we haven't
|
|
|
|
* been called from pool_timer, do an expiry event right now.
|
|
|
|
*/
|
2005-03-17 20:15:29 +00:00
|
|
|
/* XXX At some point we should optimize this so that we don't
|
|
|
|
XXX write the lease twice, but this is a safe way to fix the
|
|
|
|
XXX problem for 3.0 (I hope!). */
|
2014-12-10 19:08:05 -08:00
|
|
|
if ((from_pool == 0) &&
|
|
|
|
(commit || !pimmediate) &&
|
|
|
|
(comp->sort_time < cur_time) &&
|
|
|
|
(comp->next_binding_state != comp->binding_state))
|
|
|
|
pool_timer(comp->pool);
|
2005-03-17 20:15:29 +00:00
|
|
|
|
2001-02-15 21:34:08 +00:00
|
|
|
return 1;
|
2000-06-02 21:27:21 +00:00
|
|
|
}
|
|
|
|
|
2001-04-16 22:32:58 +00:00
|
|
|
void make_binding_state_transition (struct lease *lease)
|
2000-06-02 21:27:21 +00:00
|
|
|
{
|
2012-10-16 15:05:24 -07:00
|
|
|
|
2001-01-19 11:10:32 +00:00
|
|
|
#if defined (FAILOVER_PROTOCOL)
|
|
|
|
dhcp_failover_state_t *peer;
|
|
|
|
|
2012-10-16 15:05:24 -07:00
|
|
|
if (lease -> pool && lease -> pool -> failover_peer)
|
2001-01-19 11:10:32 +00:00
|
|
|
peer = lease -> pool -> failover_peer;
|
|
|
|
else
|
|
|
|
peer = (dhcp_failover_state_t *)0;
|
|
|
|
#endif
|
|
|
|
|
2000-06-02 21:27:21 +00:00
|
|
|
/* If the lease was active and is now no longer active, but isn't
|
|
|
|
released, then it just expired, so do the expiry event. */
|
|
|
|
if (lease -> next_binding_state != lease -> binding_state &&
|
2001-01-19 11:10:32 +00:00
|
|
|
((
|
|
|
|
#if defined (FAILOVER_PROTOCOL)
|
|
|
|
peer &&
|
2010-02-03 23:25:25 +00:00
|
|
|
(lease->binding_state == FTS_EXPIRED ||
|
|
|
|
lease->binding_state == FTS_ACTIVE) &&
|
|
|
|
(lease->next_binding_state == FTS_FREE ||
|
|
|
|
lease->next_binding_state == FTS_BACKUP)) ||
|
2001-01-19 11:10:32 +00:00
|
|
|
(!peer &&
|
|
|
|
#endif
|
2005-03-17 20:15:29 +00:00
|
|
|
lease -> binding_state == FTS_ACTIVE &&
|
2001-01-19 11:10:32 +00:00
|
|
|
lease -> next_binding_state != FTS_RELEASED))) {
|
2001-04-09 01:18:15 +00:00
|
|
|
#if defined (NSUPDATE)
|
2012-03-19 22:29:06 +00:00
|
|
|
(void) ddns_removals(lease, NULL, NULL, ISC_TRUE);
|
2001-04-09 01:18:15 +00:00
|
|
|
#endif
|
2013-08-27 13:40:47 -07:00
|
|
|
if (lease->on_star.on_expiry) {
|
|
|
|
execute_statements(NULL, NULL, lease,
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
&lease->scope,
|
|
|
|
lease->on_star.on_expiry,
|
|
|
|
NULL);
|
|
|
|
if (lease->on_star.on_expiry)
|
2000-07-06 06:26:42 +00:00
|
|
|
executable_statement_dereference
|
2013-08-27 13:40:47 -07:00
|
|
|
(&lease->on_star.on_expiry, MDL);
|
2000-06-02 21:27:21 +00:00
|
|
|
}
|
2019-11-22 13:39:45 -05:00
|
|
|
|
2000-06-02 21:27:21 +00:00
|
|
|
/* No sense releasing a lease after it's expired. */
|
2013-08-27 13:40:47 -07:00
|
|
|
if (lease->on_star.on_release)
|
|
|
|
executable_statement_dereference
|
|
|
|
(&lease->on_star.on_release, MDL);
|
2005-03-17 20:15:29 +00:00
|
|
|
/* Get rid of client-specific bindings that are only
|
|
|
|
correct when the lease is active. */
|
2015-07-29 08:32:50 -04:00
|
|
|
if (lease->billing_class)
|
|
|
|
unbill_class(lease);
|
2005-03-17 20:15:29 +00:00
|
|
|
if (lease -> agent_options)
|
|
|
|
option_chain_head_dereference (&lease -> agent_options,
|
|
|
|
MDL);
|
|
|
|
if (lease -> client_hostname) {
|
|
|
|
dfree (lease -> client_hostname, MDL);
|
|
|
|
lease -> client_hostname = (char *)0;
|
|
|
|
}
|
|
|
|
if (lease -> host)
|
|
|
|
host_dereference (&lease -> host, MDL);
|
2001-04-20 20:39:54 +00:00
|
|
|
|
2000-06-02 21:27:21 +00:00
|
|
|
/* Send the expiry time to the peer. */
|
|
|
|
lease -> tstp = lease -> ends;
|
|
|
|
}
|
2000-05-03 06:34:13 +00:00
|
|
|
|
2000-06-02 21:27:21 +00:00
|
|
|
/* If the lease was active and is now released, do the release
|
|
|
|
event. */
|
2001-01-19 11:10:32 +00:00
|
|
|
if (lease -> next_binding_state != lease -> binding_state &&
|
|
|
|
((
|
|
|
|
#if defined (FAILOVER_PROTOCOL)
|
|
|
|
peer &&
|
|
|
|
lease -> binding_state == FTS_RELEASED &&
|
|
|
|
(lease -> next_binding_state == FTS_FREE ||
|
|
|
|
lease -> next_binding_state == FTS_BACKUP)) ||
|
|
|
|
(!peer &&
|
|
|
|
#endif
|
2005-03-17 20:15:29 +00:00
|
|
|
lease -> binding_state == FTS_ACTIVE &&
|
2001-01-19 11:10:32 +00:00
|
|
|
lease -> next_binding_state == FTS_RELEASED))) {
|
2001-04-09 01:18:15 +00:00
|
|
|
#if defined (NSUPDATE)
|
2009-07-22 17:00:01 +00:00
|
|
|
/*
|
|
|
|
* Note: ddns_removals() is also iterated when the lease
|
|
|
|
* enters state 'released' in 'release_lease()'. The below
|
|
|
|
* is caught when a peer receives a BNDUPD from a failover
|
|
|
|
* peer; it may not have received the client's release (it
|
|
|
|
* may have been offline).
|
|
|
|
*
|
|
|
|
* We could remove the call from release_lease() because
|
|
|
|
* it will also catch here on the originating server after the
|
|
|
|
* peer acknowledges the state change. However, there could
|
|
|
|
* be many hours inbetween, and in this case we /know/ the
|
|
|
|
* client is no longer using the lease when we receive the
|
|
|
|
* release message. This is not true of expiry, where the
|
|
|
|
* peer may have extended the lease.
|
|
|
|
*/
|
2012-03-19 22:29:06 +00:00
|
|
|
(void) ddns_removals(lease, NULL, NULL, ISC_TRUE);
|
2001-04-09 01:18:15 +00:00
|
|
|
#endif
|
2013-08-27 13:40:47 -07:00
|
|
|
if (lease->on_star.on_release) {
|
|
|
|
execute_statements(NULL, NULL, lease,
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
&lease->scope,
|
|
|
|
lease->on_star.on_release,
|
|
|
|
NULL);
|
|
|
|
executable_statement_dereference
|
|
|
|
(&lease->on_star.on_release, MDL);
|
1999-10-08 22:17:41 +00:00
|
|
|
}
|
2019-11-22 13:39:45 -05:00
|
|
|
|
2000-06-02 21:27:21 +00:00
|
|
|
/* A released lease can't expire. */
|
2013-08-27 13:40:47 -07:00
|
|
|
if (lease->on_star.on_expiry)
|
|
|
|
executable_statement_dereference
|
|
|
|
(&lease->on_star.on_expiry, MDL);
|
2000-06-02 21:27:21 +00:00
|
|
|
|
2005-03-17 20:15:29 +00:00
|
|
|
/* Get rid of client-specific bindings that are only
|
|
|
|
correct when the lease is active. */
|
2015-07-29 08:32:50 -04:00
|
|
|
if (lease->billing_class)
|
|
|
|
unbill_class(lease);
|
2005-03-17 20:15:29 +00:00
|
|
|
if (lease -> agent_options)
|
|
|
|
option_chain_head_dereference (&lease -> agent_options,
|
|
|
|
MDL);
|
|
|
|
if (lease -> client_hostname) {
|
|
|
|
dfree (lease -> client_hostname, MDL);
|
|
|
|
lease -> client_hostname = (char *)0;
|
|
|
|
}
|
|
|
|
if (lease -> host)
|
|
|
|
host_dereference (&lease -> host, MDL);
|
2001-04-20 20:39:54 +00:00
|
|
|
|
2000-06-02 21:27:21 +00:00
|
|
|
/* Send the release time (should be == cur_time) to the
|
|
|
|
peer. */
|
|
|
|
lease -> tstp = lease -> ends;
|
1999-10-08 22:17:41 +00:00
|
|
|
}
|
|
|
|
|
2001-04-16 22:32:58 +00:00
|
|
|
#if defined (DEBUG_LEASE_STATE_TRANSITIONS)
|
|
|
|
log_debug ("lease %s moves from %s to %s",
|
|
|
|
piaddr (lease -> ip_addr),
|
|
|
|
binding_state_print (lease -> binding_state),
|
|
|
|
binding_state_print (lease -> next_binding_state));
|
|
|
|
#endif
|
|
|
|
|
2000-06-02 21:27:21 +00:00
|
|
|
lease -> binding_state = lease -> next_binding_state;
|
2001-04-16 22:32:58 +00:00
|
|
|
switch (lease -> binding_state) {
|
|
|
|
case FTS_ACTIVE:
|
2000-07-06 10:27:41 +00:00
|
|
|
#if defined (FAILOVER_PROTOCOL)
|
|
|
|
if (lease -> pool && lease -> pool -> failover_peer)
|
|
|
|
lease -> next_binding_state = FTS_EXPIRED;
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
lease -> next_binding_state = FTS_FREE;
|
2001-04-16 22:32:58 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FTS_EXPIRED:
|
|
|
|
case FTS_RELEASED:
|
|
|
|
case FTS_ABANDONED:
|
|
|
|
case FTS_RESET:
|
2012-10-16 15:05:24 -07:00
|
|
|
lease->next_binding_state = FTS_FREE;
|
2008-02-28 21:21:56 +00:00
|
|
|
#if defined(FAILOVER_PROTOCOL)
|
2001-05-17 19:04:09 +00:00
|
|
|
/* If we are not in partner_down, leases don't go from
|
|
|
|
EXPIRED to FREE on a timeout - only on an update.
|
|
|
|
If we're in partner_down, they expire at mclt past
|
|
|
|
the time we entered partner_down. */
|
2012-10-16 15:05:24 -07:00
|
|
|
if ((lease->pool != NULL) &&
|
|
|
|
(lease->pool->failover_peer != NULL) &&
|
|
|
|
(lease->pool->failover_peer->me.state == partner_down))
|
|
|
|
lease->tsfp =
|
|
|
|
(lease->pool->failover_peer->me.stos +
|
|
|
|
lease->pool->failover_peer->mclt);
|
2008-02-28 21:21:56 +00:00
|
|
|
#endif /* FAILOVER_PROTOCOL */
|
2001-04-16 22:32:58 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FTS_FREE:
|
|
|
|
case FTS_BACKUP:
|
|
|
|
lease -> next_binding_state = lease -> binding_state;
|
|
|
|
break;
|
2000-07-06 10:27:41 +00:00
|
|
|
}
|
2001-04-16 22:32:58 +00:00
|
|
|
#if defined (DEBUG_LEASE_STATE_TRANSITIONS)
|
|
|
|
log_debug ("lease %s: next binding state %s",
|
|
|
|
piaddr (lease -> ip_addr),
|
|
|
|
binding_state_print (lease -> next_binding_state));
|
|
|
|
#endif
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
2000-05-16 23:03:49 +00:00
|
|
|
/* Copy the contents of one lease into another, correctly maintaining
|
|
|
|
reference counts. */
|
|
|
|
int lease_copy (struct lease **lp,
|
|
|
|
struct lease *lease, const char *file, int line)
|
|
|
|
{
|
|
|
|
struct lease *lt = (struct lease *)0;
|
|
|
|
isc_result_t status;
|
1999-09-28 22:49:31 +00:00
|
|
|
|
2000-05-16 23:03:49 +00:00
|
|
|
status = lease_allocate (<, MDL);
|
|
|
|
if (status != ISC_R_SUCCESS)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
lt -> ip_addr = lease -> ip_addr;
|
|
|
|
lt -> starts = lease -> starts;
|
|
|
|
lt -> ends = lease -> ends;
|
|
|
|
lt -> uid_len = lease -> uid_len;
|
|
|
|
lt -> uid_max = lease -> uid_max;
|
|
|
|
if (lease -> uid == lease -> uid_buf) {
|
|
|
|
lt -> uid = lt -> uid_buf;
|
|
|
|
memcpy (lt -> uid_buf, lease -> uid_buf, sizeof lt -> uid_buf);
|
2001-04-24 01:02:24 +00:00
|
|
|
} else if (!lease -> uid_max) {
|
|
|
|
lt -> uid = (unsigned char *)0;
|
2000-05-16 23:03:49 +00:00
|
|
|
} else {
|
|
|
|
lt -> uid = dmalloc (lt -> uid_max, MDL);
|
|
|
|
if (!lt -> uid) {
|
|
|
|
lease_dereference (<, MDL);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
memcpy (lt -> uid, lease -> uid, lease -> uid_max);
|
|
|
|
}
|
|
|
|
if (lease -> client_hostname) {
|
|
|
|
lt -> client_hostname =
|
|
|
|
dmalloc (strlen (lease -> client_hostname) + 1, MDL);
|
|
|
|
if (!lt -> client_hostname) {
|
|
|
|
lease_dereference (<, MDL);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
strcpy (lt -> client_hostname, lease -> client_hostname);
|
|
|
|
}
|
2000-07-27 09:03:08 +00:00
|
|
|
if (lease -> scope)
|
|
|
|
binding_scope_reference (< -> scope, lease -> scope, MDL);
|
2000-11-28 23:27:24 +00:00
|
|
|
if (lease -> agent_options)
|
2001-01-25 08:36:36 +00:00
|
|
|
option_chain_head_reference (< -> agent_options,
|
|
|
|
lease -> agent_options, MDL);
|
2000-05-16 23:03:49 +00:00
|
|
|
host_reference (< -> host, lease -> host, file, line);
|
|
|
|
subnet_reference (< -> subnet, lease -> subnet, file, line);
|
|
|
|
pool_reference (< -> pool, lease -> pool, file, line);
|
|
|
|
class_reference (< -> billing_class,
|
|
|
|
lease -> billing_class, file, line);
|
|
|
|
lt -> hardware_addr = lease -> hardware_addr;
|
2013-08-27 13:40:47 -07:00
|
|
|
if (lease->on_star.on_expiry)
|
|
|
|
executable_statement_reference (<->on_star.on_expiry,
|
|
|
|
lease->on_star.on_expiry,
|
2000-05-16 23:03:49 +00:00
|
|
|
file, line);
|
2013-08-27 13:40:47 -07:00
|
|
|
if (lease->on_star.on_commit)
|
|
|
|
executable_statement_reference (<->on_star.on_commit,
|
|
|
|
lease->on_star.on_commit,
|
2000-05-16 23:03:49 +00:00
|
|
|
file, line);
|
2013-08-27 13:40:47 -07:00
|
|
|
if (lease->on_star.on_release)
|
|
|
|
executable_statement_reference (<->on_star.on_release,
|
|
|
|
lease->on_star.on_release,
|
2000-05-16 23:03:49 +00:00
|
|
|
file, line);
|
2006-02-24 23:16:32 +00:00
|
|
|
lt->flags = lease->flags;
|
|
|
|
lt->tstp = lease->tstp;
|
|
|
|
lt->tsfp = lease->tsfp;
|
|
|
|
lt->atsfp = lease->atsfp;
|
|
|
|
lt->cltt = lease -> cltt;
|
|
|
|
lt->binding_state = lease->binding_state;
|
|
|
|
lt->next_binding_state = lease->next_binding_state;
|
2010-02-03 23:25:25 +00:00
|
|
|
lt->rewind_binding_state = lease->rewind_binding_state;
|
2006-02-24 23:16:32 +00:00
|
|
|
status = lease_reference(lp, lt, file, line);
|
|
|
|
lease_dereference(<, MDL);
|
2000-05-16 23:03:49 +00:00
|
|
|
return status == ISC_R_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Release the specified lease and re-hash it as appropriate. */
|
1999-10-05 02:47:12 +00:00
|
|
|
void release_lease (lease, packet)
|
1999-09-28 22:49:31 +00:00
|
|
|
struct lease *lease;
|
1999-10-05 02:47:12 +00:00
|
|
|
struct packet *packet;
|
1999-09-28 22:49:31 +00:00
|
|
|
{
|
1999-10-05 00:03:24 +00:00
|
|
|
/* If there are statements to execute when the lease is
|
1999-11-20 18:36:32 +00:00
|
|
|
released, execute them. */
|
2001-04-09 01:18:15 +00:00
|
|
|
#if defined (NSUPDATE)
|
2012-03-19 22:29:06 +00:00
|
|
|
(void) ddns_removals(lease, NULL, NULL, ISC_FALSE);
|
2001-04-09 01:18:15 +00:00
|
|
|
#endif
|
2013-08-27 13:40:47 -07:00
|
|
|
if (lease->on_star.on_release) {
|
|
|
|
execute_statements (NULL, packet, lease,
|
|
|
|
NULL, packet->options,
|
|
|
|
NULL, &lease->scope,
|
|
|
|
lease->on_star.on_release, NULL);
|
|
|
|
if (lease->on_star.on_release)
|
|
|
|
executable_statement_dereference
|
|
|
|
(&lease->on_star.on_release, MDL);
|
1999-10-05 00:03:24 +00:00
|
|
|
}
|
|
|
|
|
1999-11-12 17:21:28 +00:00
|
|
|
/* We do either the on_release or the on_expiry events, but
|
|
|
|
not both (it's possible that they could be the same,
|
|
|
|
in any case). */
|
2013-08-27 13:40:47 -07:00
|
|
|
if (lease->on_star.on_expiry)
|
|
|
|
executable_statement_dereference
|
|
|
|
(&lease->on_star.on_expiry, MDL);
|
1999-11-12 17:21:28 +00:00
|
|
|
|
2001-04-24 01:18:08 +00:00
|
|
|
if (lease -> binding_state != FTS_FREE &&
|
|
|
|
lease -> binding_state != FTS_BACKUP &&
|
|
|
|
lease -> binding_state != FTS_RELEASED &&
|
|
|
|
lease -> binding_state != FTS_EXPIRED &&
|
|
|
|
lease -> binding_state != FTS_RESET) {
|
2013-08-27 13:40:47 -07:00
|
|
|
if (lease->on_star.on_commit)
|
|
|
|
executable_statement_dereference
|
|
|
|
(&lease->on_star.on_commit, MDL);
|
1999-11-07 20:38:01 +00:00
|
|
|
|
2000-01-25 01:42:48 +00:00
|
|
|
/* Blow away any bindings. */
|
2000-07-27 09:03:08 +00:00
|
|
|
if (lease -> scope)
|
|
|
|
binding_scope_dereference (&lease -> scope, MDL);
|
2006-08-28 21:35:03 +00:00
|
|
|
|
|
|
|
/* Set sort times to the present. */
|
2000-06-02 21:27:21 +00:00
|
|
|
lease -> ends = cur_time;
|
2006-08-28 21:35:03 +00:00
|
|
|
/* Lower layers of muckery set tstp to ->ends. But we send
|
|
|
|
* protocol messages before this. So it is best to set
|
|
|
|
* tstp now anyway.
|
|
|
|
*/
|
|
|
|
lease->tstp = cur_time;
|
2000-06-02 21:27:21 +00:00
|
|
|
#if defined (FAILOVER_PROTOCOL)
|
|
|
|
if (lease -> pool && lease -> pool -> failover_peer) {
|
2010-02-03 23:25:25 +00:00
|
|
|
dhcp_failover_state_t *peer = NULL;
|
|
|
|
|
|
|
|
if (lease->pool != NULL)
|
|
|
|
peer = lease->pool->failover_peer;
|
|
|
|
|
|
|
|
if ((peer->service_state == not_cooperating) &&
|
|
|
|
(((peer->i_am == primary) &&
|
|
|
|
(lease->rewind_binding_state == FTS_FREE)) ||
|
|
|
|
((peer->i_am == secondary) &&
|
|
|
|
(lease->rewind_binding_state == FTS_BACKUP)))) {
|
|
|
|
lease->next_binding_state =
|
|
|
|
lease->rewind_binding_state;
|
|
|
|
} else
|
|
|
|
lease -> next_binding_state = FTS_RELEASED;
|
2000-06-02 21:27:21 +00:00
|
|
|
} else {
|
|
|
|
lease -> next_binding_state = FTS_FREE;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
lease -> next_binding_state = FTS_FREE;
|
|
|
|
#endif
|
2014-12-10 19:08:05 -08:00
|
|
|
supersede_lease(lease, NULL, 1, 1, 1, 0);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Abandon the specified lease (set its timeout to infinity and its
|
|
|
|
particulars to zero, and re-hash it as appropriate. */
|
|
|
|
|
|
|
|
void abandon_lease (lease, message)
|
|
|
|
struct lease *lease;
|
1999-10-07 06:36:35 +00:00
|
|
|
const char *message;
|
1999-09-28 22:49:31 +00:00
|
|
|
{
|
2016-07-07 14:11:26 -04:00
|
|
|
struct lease *lt = NULL;
|
2006-07-18 18:15:53 +00:00
|
|
|
#if defined (NSUPDATE)
|
2012-03-19 22:29:06 +00:00
|
|
|
(void) ddns_removals(lease, NULL, NULL, ISC_FALSE);
|
2006-07-18 18:15:53 +00:00
|
|
|
#endif
|
1999-09-28 22:49:31 +00:00
|
|
|
|
2016-07-07 14:11:26 -04:00
|
|
|
if (!lease_copy(<, lease, MDL)) {
|
2000-05-16 23:03:49 +00:00
|
|
|
return;
|
2016-07-07 14:11:26 -04:00
|
|
|
}
|
1999-11-07 20:38:01 +00:00
|
|
|
|
2016-07-07 14:11:26 -04:00
|
|
|
if (lt->scope) {
|
2005-03-17 20:15:29 +00:00
|
|
|
binding_scope_dereference(<->scope, MDL);
|
2016-07-07 14:11:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Calculate the abandone expiry time. If it wraps,
|
|
|
|
* use the maximum expiry time. */
|
|
|
|
lt->ends = cur_time + abandon_lease_time;
|
|
|
|
if (lt->ends < cur_time || lt->ends > MAX_TIME) {
|
|
|
|
lt->ends = MAX_TIME;
|
|
|
|
}
|
2005-03-17 20:15:29 +00:00
|
|
|
|
2016-07-07 14:11:26 -04:00
|
|
|
lt->next_binding_state = FTS_ABANDONED;
|
|
|
|
|
|
|
|
log_error ("Abandoning IP address %s: %s", piaddr(lease->ip_addr),
|
|
|
|
message);
|
|
|
|
lt->hardware_addr.hlen = 0;
|
|
|
|
if (lt->uid && lt->uid != lt->uid_buf) {
|
|
|
|
dfree(lt->uid, MDL);
|
|
|
|
}
|
|
|
|
|
|
|
|
lt->uid = NULL;
|
|
|
|
lt->uid_len = 0;
|
|
|
|
lt->uid_max = 0;
|
|
|
|
supersede_lease(lease, lt, 1, 1, 1, 0);
|
|
|
|
lease_dereference(<, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
2012-03-19 22:29:06 +00:00
|
|
|
#if 0
|
|
|
|
/*
|
|
|
|
* This doesn't appear to be in use for anything anymore.
|
|
|
|
* I'm ifdeffing it now and if there are no complaints in
|
|
|
|
* the future it will be removed.
|
|
|
|
* SAR
|
|
|
|
*/
|
|
|
|
|
1999-09-28 22:49:31 +00:00
|
|
|
/* Abandon the specified lease (set its timeout to infinity and its
|
|
|
|
particulars to zero, and re-hash it as appropriate. */
|
|
|
|
|
|
|
|
void dissociate_lease (lease)
|
|
|
|
struct lease *lease;
|
|
|
|
{
|
2000-05-16 23:03:49 +00:00
|
|
|
struct lease *lt = (struct lease *)0;
|
2006-07-18 18:15:53 +00:00
|
|
|
#if defined (NSUPDATE)
|
2012-03-19 22:29:06 +00:00
|
|
|
(void) ddns_removals(lease, NULL, NULL, ISC_FALSE);
|
2006-07-18 18:15:53 +00:00
|
|
|
#endif
|
1999-09-28 22:49:31 +00:00
|
|
|
|
2000-05-16 23:03:49 +00:00
|
|
|
if (!lease_copy (<, lease, MDL))
|
|
|
|
return;
|
|
|
|
|
2000-06-02 21:27:21 +00:00
|
|
|
#if defined (FAILOVER_PROTOCOL)
|
|
|
|
if (lease -> pool && lease -> pool -> failover_peer) {
|
|
|
|
lt -> next_binding_state = FTS_RESET;
|
|
|
|
} else {
|
|
|
|
lt -> next_binding_state = FTS_FREE;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
lt -> next_binding_state = FTS_FREE;
|
|
|
|
#endif
|
2000-05-16 23:03:49 +00:00
|
|
|
lt -> ends = cur_time; /* XXX */
|
|
|
|
lt -> hardware_addr.hlen = 0;
|
2001-05-02 07:09:36 +00:00
|
|
|
if (lt -> uid && lt -> uid != lt -> uid_buf)
|
2000-05-16 23:03:49 +00:00
|
|
|
dfree (lt -> uid, MDL);
|
|
|
|
lt -> uid = (unsigned char *)0;
|
|
|
|
lt -> uid_len = 0;
|
|
|
|
lt -> uid_max = 0;
|
2014-12-10 19:08:05 -08:00
|
|
|
supersede_lease (lease, lt, 1, 1, 1, 0);
|
2000-05-16 23:03:49 +00:00
|
|
|
lease_dereference (<, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
2012-03-19 22:29:06 +00:00
|
|
|
#endif
|
1999-09-28 22:49:31 +00:00
|
|
|
|
1999-10-08 22:17:41 +00:00
|
|
|
/* Timer called when a lease in a particular pool expires. */
|
|
|
|
void pool_timer (vpool)
|
|
|
|
void *vpool;
|
|
|
|
{
|
|
|
|
struct pool *pool;
|
2014-12-10 19:08:05 -08:00
|
|
|
struct lease *next = NULL;
|
|
|
|
struct lease *lease = NULL;
|
2015-05-27 13:17:46 -07:00
|
|
|
struct lease *ltemp = NULL;
|
2006-09-27 18:27:27 +00:00
|
|
|
#define FREE_LEASES 0
|
|
|
|
#define ACTIVE_LEASES 1
|
|
|
|
#define EXPIRED_LEASES 2
|
|
|
|
#define ABANDONED_LEASES 3
|
|
|
|
#define BACKUP_LEASES 4
|
|
|
|
#define RESERVED_LEASES 5
|
2015-05-27 13:17:46 -07:00
|
|
|
LEASE_STRUCT_PTR lptr[RESERVED_LEASES+1];
|
2000-06-02 21:27:21 +00:00
|
|
|
TIME next_expiry = MAX_TIME;
|
|
|
|
int i;
|
2008-01-03 00:30:14 +00:00
|
|
|
struct timeval tv;
|
1999-10-08 22:17:41 +00:00
|
|
|
|
|
|
|
pool = (struct pool *)vpool;
|
|
|
|
|
2014-12-10 19:08:05 -08:00
|
|
|
lptr[FREE_LEASES] = &pool->free;
|
|
|
|
lptr[ACTIVE_LEASES] = &pool->active;
|
|
|
|
lptr[EXPIRED_LEASES] = &pool->expired;
|
|
|
|
lptr[ABANDONED_LEASES] = &pool->abandoned;
|
|
|
|
lptr[BACKUP_LEASES] = &pool->backup;
|
2006-04-27 17:26:42 +00:00
|
|
|
lptr[RESERVED_LEASES] = &pool->reserved;
|
2000-06-02 21:27:21 +00:00
|
|
|
|
2006-04-27 17:26:42 +00:00
|
|
|
for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
|
2000-06-02 21:27:21 +00:00
|
|
|
/* If there's nothing on the queue, skip it. */
|
2015-05-27 13:17:46 -07:00
|
|
|
if (!(LEASE_NOT_EMPTYP(lptr[i])))
|
2000-06-02 21:27:21 +00:00
|
|
|
continue;
|
2001-05-17 19:04:09 +00:00
|
|
|
|
|
|
|
#if defined (FAILOVER_PROTOCOL)
|
2010-02-03 23:25:25 +00:00
|
|
|
if (pool->failover_peer &&
|
|
|
|
pool->failover_peer->me.state != partner_down) {
|
|
|
|
/*
|
|
|
|
* Normally the secondary doesn't initiate expiration
|
|
|
|
* events (unless in partner-down), but rather relies
|
|
|
|
* on the primary to expire the lease. However, when
|
|
|
|
* disconnected from its peer, the server is allowed to
|
|
|
|
* rewind a lease to the previous state that the peer
|
|
|
|
* would have recorded it. This means there may be
|
|
|
|
* opportunities for active->free or active->backup
|
|
|
|
* expirations while out of contact.
|
|
|
|
*
|
|
|
|
* Q: Should we limit this expiration to
|
|
|
|
* comms-interrupt rather than not-normal?
|
|
|
|
*/
|
|
|
|
if ((i == ACTIVE_LEASES) &&
|
|
|
|
(pool->failover_peer->i_am == secondary) &&
|
|
|
|
(pool->failover_peer->me.state == normal))
|
2001-05-17 19:04:09 +00:00
|
|
|
continue;
|
2010-02-03 23:25:25 +00:00
|
|
|
|
2001-05-17 19:04:09 +00:00
|
|
|
/* Leases in an expired state don't move to
|
|
|
|
free because of a timeout unless we're in
|
|
|
|
partner_down. */
|
|
|
|
if (i == EXPIRED_LEASES)
|
|
|
|
continue;
|
|
|
|
}
|
2019-11-22 13:39:45 -05:00
|
|
|
#endif
|
2015-05-27 13:17:46 -07:00
|
|
|
lease_reference(&lease, LEASE_GET_FIRSTP(lptr[i]), MDL);
|
2000-06-02 21:27:21 +00:00
|
|
|
|
|
|
|
while (lease) {
|
|
|
|
/* Remember the next lease in the list. */
|
|
|
|
if (next)
|
2014-12-10 19:08:05 -08:00
|
|
|
lease_dereference(&next, MDL);
|
2015-05-27 13:17:46 -07:00
|
|
|
ltemp = LEASE_GET_NEXTP(lptr[i], lease);
|
|
|
|
if (ltemp)
|
|
|
|
lease_reference(&next, ltemp, MDL);
|
2000-06-02 21:27:21 +00:00
|
|
|
|
|
|
|
/* If we've run out of things to expire on this list,
|
|
|
|
stop. */
|
2014-12-10 19:08:05 -08:00
|
|
|
if (lease->sort_time > cur_time) {
|
|
|
|
if (lease->sort_time < next_expiry)
|
|
|
|
next_expiry = lease->sort_time;
|
2000-06-02 21:27:21 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If there is a pending state change, and
|
|
|
|
this lease has gotten to the time when the
|
|
|
|
state change should happen, just call
|
|
|
|
supersede_lease on it to make the change
|
|
|
|
happen. */
|
2010-02-03 23:25:25 +00:00
|
|
|
if (lease->next_binding_state != lease->binding_state)
|
|
|
|
{
|
|
|
|
#if defined(FAILOVER_PROTOCOL)
|
|
|
|
dhcp_failover_state_t *peer = NULL;
|
|
|
|
|
|
|
|
if (lease->pool != NULL)
|
|
|
|
peer = lease->pool->failover_peer;
|
|
|
|
|
|
|
|
/* Can we rewind the lease to a free state? */
|
|
|
|
if (peer != NULL &&
|
|
|
|
peer->service_state == not_cooperating &&
|
|
|
|
lease->next_binding_state == FTS_EXPIRED &&
|
|
|
|
((peer->i_am == primary &&
|
|
|
|
lease->rewind_binding_state == FTS_FREE)
|
|
|
|
||
|
|
|
|
(peer->i_am == secondary &&
|
|
|
|
lease->rewind_binding_state ==
|
|
|
|
FTS_BACKUP)))
|
|
|
|
lease->next_binding_state =
|
|
|
|
lease->rewind_binding_state;
|
|
|
|
#endif
|
2014-12-10 19:08:05 -08:00
|
|
|
supersede_lease(lease, NULL, 1, 1, 1, 1);
|
2010-02-03 23:25:25 +00:00
|
|
|
}
|
2000-06-02 21:27:21 +00:00
|
|
|
|
2014-12-10 19:08:05 -08:00
|
|
|
lease_dereference(&lease, MDL);
|
2000-06-02 21:27:21 +00:00
|
|
|
if (next)
|
2014-12-10 19:08:05 -08:00
|
|
|
lease_reference(&lease, next, MDL);
|
1999-10-08 22:17:41 +00:00
|
|
|
}
|
2000-06-02 21:27:21 +00:00
|
|
|
if (next)
|
2014-12-10 19:08:05 -08:00
|
|
|
lease_dereference(&next, MDL);
|
2000-06-02 21:27:21 +00:00
|
|
|
if (lease)
|
2014-12-10 19:08:05 -08:00
|
|
|
lease_dereference(&lease, MDL);
|
2000-06-02 21:27:21 +00:00
|
|
|
}
|
2014-12-10 19:08:05 -08:00
|
|
|
|
|
|
|
/* If we found something to expire and its expiration time
|
|
|
|
* is either less than the current expiration time or the
|
|
|
|
* current expiration time is already expired update the
|
|
|
|
* timer.
|
|
|
|
*/
|
|
|
|
if ((next_expiry != MAX_TIME) &&
|
|
|
|
((pool->next_event_time > next_expiry) ||
|
|
|
|
(pool->next_event_time <= cur_time))) {
|
|
|
|
pool->next_event_time = next_expiry;
|
|
|
|
tv.tv_sec = pool->next_event_time;
|
|
|
|
tv.tv_usec = 0;
|
2008-01-03 00:30:14 +00:00
|
|
|
add_timeout (&tv, pool_timer, pool,
|
2000-05-16 23:03:49 +00:00
|
|
|
(tvref_t)pool_reference,
|
|
|
|
(tvunref_t)pool_dereference);
|
2000-06-02 21:27:21 +00:00
|
|
|
} else
|
2014-12-10 19:08:05 -08:00
|
|
|
pool->next_event_time = MIN_TIME;
|
2000-06-02 21:27:21 +00:00
|
|
|
|
1999-10-08 22:17:41 +00:00
|
|
|
}
|
|
|
|
|
1999-09-28 22:49:31 +00:00
|
|
|
/* Locate the lease associated with a given IP address... */
|
|
|
|
|
2000-05-16 23:03:49 +00:00
|
|
|
int find_lease_by_ip_addr (struct lease **lp, struct iaddr addr,
|
|
|
|
const char *file, int line)
|
1999-09-28 22:49:31 +00:00
|
|
|
{
|
2006-10-27 22:54:13 +00:00
|
|
|
return lease_ip_hash_lookup(lp, lease_ip_addr_hash, addr.iabuf,
|
|
|
|
addr.len, file, line);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
2000-05-16 23:03:49 +00:00
|
|
|
int find_lease_by_uid (struct lease **lp, const unsigned char *uid,
|
|
|
|
unsigned len, const char *file, int line)
|
1999-09-28 22:49:31 +00:00
|
|
|
{
|
2000-05-16 23:03:49 +00:00
|
|
|
if (len == 0)
|
|
|
|
return 0;
|
2006-10-27 22:54:13 +00:00
|
|
|
return lease_id_hash_lookup (lp, lease_uid_hash, uid, len, file, line);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
2000-05-16 23:03:49 +00:00
|
|
|
int find_lease_by_hw_addr (struct lease **lp,
|
|
|
|
const unsigned char *hwaddr, unsigned hwlen,
|
|
|
|
const char *file, int line)
|
1999-09-28 22:49:31 +00:00
|
|
|
{
|
2000-05-16 23:03:49 +00:00
|
|
|
if (hwlen == 0)
|
2012-02-16 21:05:28 +00:00
|
|
|
return (0);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If it's an infiniband address don't bother
|
|
|
|
* as we don't have a useful address to hash.
|
|
|
|
*/
|
|
|
|
if ((hwlen == 1) && (hwaddr[0] == HTYPE_INFINIBAND))
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
return (lease_id_hash_lookup(lp, lease_hw_addr_hash, hwaddr, hwlen,
|
|
|
|
file, line));
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
2007-04-26 20:06:25 +00:00
|
|
|
/* If the lease is preferred over the candidate, return truth. The
|
|
|
|
* 'cand' and 'lease' names are retained to read more clearly against
|
|
|
|
* the 'uid_hash_add' and 'hw_hash_add' functions (this is common logic
|
|
|
|
* to those two functions).
|
|
|
|
*
|
|
|
|
* 1) ACTIVE leases are preferred. The active lease with
|
|
|
|
* the longest lifetime is preferred over shortest.
|
|
|
|
* 2) "transitional states" are next, this time with the
|
|
|
|
* most recent CLTT.
|
|
|
|
* 3) free/backup/etc states are next, again with CLTT. In truth we
|
|
|
|
* should never see reset leases for this.
|
|
|
|
* 4) Abandoned leases are always dead last.
|
|
|
|
*/
|
|
|
|
static isc_boolean_t
|
|
|
|
client_lease_preferred(struct lease *cand, struct lease *lease)
|
1999-09-28 22:49:31 +00:00
|
|
|
{
|
2007-04-26 20:06:25 +00:00
|
|
|
if (cand->binding_state == FTS_ACTIVE) {
|
|
|
|
if (lease->binding_state == FTS_ACTIVE &&
|
|
|
|
lease->ends >= cand->ends)
|
|
|
|
return ISC_TRUE;
|
|
|
|
} else if (cand->binding_state == FTS_EXPIRED ||
|
|
|
|
cand->binding_state == FTS_RELEASED) {
|
|
|
|
if (lease->binding_state == FTS_ACTIVE)
|
|
|
|
return ISC_TRUE;
|
|
|
|
|
|
|
|
if ((lease->binding_state == FTS_EXPIRED ||
|
|
|
|
lease->binding_state == FTS_RELEASED) &&
|
|
|
|
lease->cltt >= cand->cltt)
|
|
|
|
return ISC_TRUE;
|
|
|
|
} else if (cand->binding_state != FTS_ABANDONED) {
|
|
|
|
if (lease->binding_state == FTS_ACTIVE ||
|
|
|
|
lease->binding_state == FTS_EXPIRED ||
|
|
|
|
lease->binding_state == FTS_RELEASED)
|
|
|
|
return ISC_TRUE;
|
|
|
|
|
|
|
|
if (lease->binding_state != FTS_ABANDONED &&
|
|
|
|
lease->cltt >= cand->cltt)
|
|
|
|
return ISC_TRUE;
|
|
|
|
} else /* (cand->binding_state == FTS_ABANDONED) */ {
|
|
|
|
if (lease->binding_state != FTS_ABANDONED ||
|
|
|
|
lease->cltt >= cand->cltt)
|
|
|
|
return ISC_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ISC_FALSE;
|
|
|
|
}
|
1999-09-28 22:49:31 +00:00
|
|
|
|
2007-04-26 20:06:25 +00:00
|
|
|
/* Add the specified lease to the uid hash. */
|
|
|
|
void
|
|
|
|
uid_hash_add(struct lease *lease)
|
|
|
|
{
|
|
|
|
struct lease *head = NULL;
|
|
|
|
struct lease *cand = NULL;
|
|
|
|
struct lease *prev = NULL;
|
|
|
|
struct lease *next = NULL;
|
2000-05-16 23:03:49 +00:00
|
|
|
|
1999-09-28 22:49:31 +00:00
|
|
|
/* If it's not in the hash, just add it. */
|
2000-05-16 23:03:49 +00:00
|
|
|
if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL))
|
2006-10-27 22:54:13 +00:00
|
|
|
lease_id_hash_add(lease_uid_hash, lease->uid, lease->uid_len,
|
|
|
|
lease, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
else {
|
2007-04-26 20:06:25 +00:00
|
|
|
/* Otherwise, insert it into the list in order of its
|
|
|
|
* preference for "resuming allocation to the client."
|
|
|
|
*
|
|
|
|
* Because we don't have control of the hash bucket index
|
|
|
|
* directly, we have to remove and re-insert the client
|
|
|
|
* id into the hash if we're inserting onto the head.
|
|
|
|
*/
|
|
|
|
lease_reference(&cand, head, MDL);
|
|
|
|
while (cand != NULL) {
|
|
|
|
if (client_lease_preferred(cand, lease))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (prev != NULL)
|
|
|
|
lease_dereference(&prev, MDL);
|
|
|
|
lease_reference(&prev, cand, MDL);
|
|
|
|
|
|
|
|
if (cand->n_uid != NULL)
|
|
|
|
lease_reference(&next, cand->n_uid, MDL);
|
|
|
|
|
|
|
|
lease_dereference(&cand, MDL);
|
|
|
|
|
|
|
|
if (next != NULL) {
|
|
|
|
lease_reference(&cand, next, MDL);
|
|
|
|
lease_dereference(&next, MDL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we want to insert 'before cand', and prev is NULL,
|
|
|
|
* then it was the head of the list. Assume that position.
|
|
|
|
*/
|
|
|
|
if (prev == NULL) {
|
|
|
|
lease_reference(&lease->n_uid, head, MDL);
|
|
|
|
lease_id_hash_delete(lease_uid_hash, lease->uid,
|
|
|
|
lease->uid_len, MDL);
|
|
|
|
lease_id_hash_add(lease_uid_hash, lease->uid,
|
|
|
|
lease->uid_len, lease, MDL);
|
|
|
|
} else /* (prev != NULL) */ {
|
|
|
|
if(prev->n_uid != NULL) {
|
|
|
|
lease_reference(&lease->n_uid, prev->n_uid,
|
|
|
|
MDL);
|
|
|
|
lease_dereference(&prev->n_uid, MDL);
|
|
|
|
}
|
|
|
|
lease_reference(&prev->n_uid, lease, MDL);
|
|
|
|
|
|
|
|
lease_dereference(&prev, MDL);
|
2001-03-15 23:22:33 +00:00
|
|
|
}
|
2007-04-26 20:06:25 +00:00
|
|
|
|
|
|
|
if (cand != NULL)
|
|
|
|
lease_dereference(&cand, MDL);
|
|
|
|
lease_dereference(&head, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Delete the specified lease from the uid hash. */
|
|
|
|
|
|
|
|
void uid_hash_delete (lease)
|
|
|
|
struct lease *lease;
|
|
|
|
{
|
2000-05-16 23:03:49 +00:00
|
|
|
struct lease *head = (struct lease *)0;
|
1999-09-28 22:49:31 +00:00
|
|
|
struct lease *scan;
|
|
|
|
|
|
|
|
/* If it's not in the hash, we have no work to do. */
|
2000-05-16 23:03:49 +00:00
|
|
|
if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL)) {
|
|
|
|
if (lease -> n_uid)
|
|
|
|
lease_dereference (&lease -> n_uid, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If the lease we're freeing is at the head of the list,
|
|
|
|
remove the hash table entry and add a new one with the
|
|
|
|
next lease on the list (if there is one). */
|
|
|
|
if (head == lease) {
|
2006-10-27 22:54:13 +00:00
|
|
|
lease_id_hash_delete(lease_uid_hash, lease->uid,
|
|
|
|
lease->uid_len, MDL);
|
2000-05-16 23:03:49 +00:00
|
|
|
if (lease -> n_uid) {
|
2006-10-27 22:54:13 +00:00
|
|
|
lease_id_hash_add(lease_uid_hash, lease->n_uid->uid,
|
|
|
|
lease->n_uid->uid_len, lease->n_uid,
|
|
|
|
MDL);
|
2000-05-16 23:03:49 +00:00
|
|
|
lease_dereference (&lease -> n_uid, MDL);
|
|
|
|
}
|
1999-09-28 22:49:31 +00:00
|
|
|
} else {
|
|
|
|
/* Otherwise, look for the lease in the list of leases
|
|
|
|
attached to the hash table entry, and remove it if
|
|
|
|
we find it. */
|
|
|
|
for (scan = head; scan -> n_uid; scan = scan -> n_uid) {
|
|
|
|
if (scan -> n_uid == lease) {
|
2000-05-16 23:03:49 +00:00
|
|
|
lease_dereference (&scan -> n_uid, MDL);
|
|
|
|
if (lease -> n_uid) {
|
|
|
|
lease_reference (&scan -> n_uid,
|
|
|
|
lease -> n_uid, MDL);
|
|
|
|
lease_dereference (&lease -> n_uid,
|
|
|
|
MDL);
|
|
|
|
}
|
1999-09-28 22:49:31 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2000-12-28 23:34:08 +00:00
|
|
|
lease_dereference (&head, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Add the specified lease to the hardware address hash. */
|
2012-02-16 21:05:28 +00:00
|
|
|
/* We don't add leases with infiniband addresses to the
|
|
|
|
* hash as there isn't any address to hash on. */
|
1999-09-28 22:49:31 +00:00
|
|
|
|
2007-04-26 20:06:25 +00:00
|
|
|
void
|
|
|
|
hw_hash_add(struct lease *lease)
|
1999-09-28 22:49:31 +00:00
|
|
|
{
|
2007-04-26 20:06:25 +00:00
|
|
|
struct lease *head = NULL;
|
|
|
|
struct lease *cand = NULL;
|
|
|
|
struct lease *prev = NULL;
|
|
|
|
struct lease *next = NULL;
|
1999-09-28 22:49:31 +00:00
|
|
|
|
2012-02-16 21:05:28 +00:00
|
|
|
/*
|
|
|
|
* If it's an infiniband address don't bother
|
|
|
|
* as we don't have a useful address to hash.
|
|
|
|
*/
|
|
|
|
if ((lease->hardware_addr.hlen == 1) &&
|
|
|
|
(lease->hardware_addr.hbuf[0] == HTYPE_INFINIBAND))
|
|
|
|
return;
|
2019-11-22 13:39:45 -05:00
|
|
|
|
1999-09-28 22:49:31 +00:00
|
|
|
/* If it's not in the hash, just add it. */
|
2000-05-16 23:03:49 +00:00
|
|
|
if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
|
|
|
|
lease -> hardware_addr.hlen, MDL))
|
2006-10-27 22:54:13 +00:00
|
|
|
lease_id_hash_add(lease_hw_addr_hash,
|
|
|
|
lease->hardware_addr.hbuf,
|
|
|
|
lease->hardware_addr.hlen, lease, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
else {
|
2007-04-26 20:06:25 +00:00
|
|
|
/* Otherwise, insert it into the list in order of its
|
|
|
|
* preference for "resuming allocation to the client."
|
|
|
|
*
|
|
|
|
* Because we don't have control of the hash bucket index
|
|
|
|
* directly, we have to remove and re-insert the client
|
|
|
|
* id into the hash if we're inserting onto the head.
|
|
|
|
*/
|
|
|
|
lease_reference(&cand, head, MDL);
|
|
|
|
while (cand != NULL) {
|
|
|
|
if (client_lease_preferred(cand, lease))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (prev != NULL)
|
|
|
|
lease_dereference(&prev, MDL);
|
|
|
|
lease_reference(&prev, cand, MDL);
|
|
|
|
|
|
|
|
if (cand->n_hw != NULL)
|
|
|
|
lease_reference(&next, cand->n_hw, MDL);
|
|
|
|
|
|
|
|
lease_dereference(&cand, MDL);
|
|
|
|
|
|
|
|
if (next != NULL) {
|
|
|
|
lease_reference(&cand, next, MDL);
|
|
|
|
lease_dereference(&next, MDL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we want to insert 'before cand', and prev is NULL,
|
|
|
|
* then it was the head of the list. Assume that position.
|
|
|
|
*/
|
|
|
|
if (prev == NULL) {
|
|
|
|
lease_reference(&lease->n_hw, head, MDL);
|
|
|
|
lease_id_hash_delete(lease_hw_addr_hash,
|
|
|
|
lease->hardware_addr.hbuf,
|
|
|
|
lease->hardware_addr.hlen, MDL);
|
|
|
|
lease_id_hash_add(lease_hw_addr_hash,
|
|
|
|
lease->hardware_addr.hbuf,
|
|
|
|
lease->hardware_addr.hlen,
|
|
|
|
lease, MDL);
|
|
|
|
} else /* (prev != NULL) */ {
|
|
|
|
if(prev->n_hw != NULL) {
|
2007-05-04 21:46:50 +00:00
|
|
|
lease_reference(&lease->n_hw, prev->n_hw,
|
2007-04-26 20:06:25 +00:00
|
|
|
MDL);
|
|
|
|
lease_dereference(&prev->n_hw, MDL);
|
|
|
|
}
|
|
|
|
lease_reference(&prev->n_hw, lease, MDL);
|
|
|
|
|
|
|
|
lease_dereference(&prev, MDL);
|
2001-03-15 23:22:33 +00:00
|
|
|
}
|
|
|
|
|
2007-04-26 20:06:25 +00:00
|
|
|
if (cand != NULL)
|
|
|
|
lease_dereference(&cand, MDL);
|
|
|
|
lease_dereference(&head, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Delete the specified lease from the hardware address hash. */
|
|
|
|
|
|
|
|
void hw_hash_delete (lease)
|
|
|
|
struct lease *lease;
|
|
|
|
{
|
2000-05-16 23:03:49 +00:00
|
|
|
struct lease *head = (struct lease *)0;
|
2001-03-16 01:57:00 +00:00
|
|
|
struct lease *next = (struct lease *)0;
|
1999-09-28 22:49:31 +00:00
|
|
|
|
2012-02-16 21:05:28 +00:00
|
|
|
/*
|
|
|
|
* If it's an infiniband address don't bother
|
|
|
|
* as we don't have a useful address to hash.
|
|
|
|
*/
|
|
|
|
if ((lease->hardware_addr.hlen == 1) &&
|
|
|
|
(lease->hardware_addr.hbuf[0] == HTYPE_INFINIBAND))
|
|
|
|
return;
|
|
|
|
|
1999-09-28 22:49:31 +00:00
|
|
|
/* If it's not in the hash, we have no work to do. */
|
2000-05-16 23:03:49 +00:00
|
|
|
if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
|
|
|
|
lease -> hardware_addr.hlen, MDL)) {
|
|
|
|
if (lease -> n_hw)
|
|
|
|
lease_dereference (&lease -> n_hw, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If the lease we're freeing is at the head of the list,
|
|
|
|
remove the hash table entry and add a new one with the
|
|
|
|
next lease on the list (if there is one). */
|
|
|
|
if (head == lease) {
|
2006-10-27 22:54:13 +00:00
|
|
|
lease_id_hash_delete(lease_hw_addr_hash,
|
|
|
|
lease->hardware_addr.hbuf,
|
|
|
|
lease->hardware_addr.hlen, MDL);
|
|
|
|
if (lease->n_hw) {
|
|
|
|
lease_id_hash_add(lease_hw_addr_hash,
|
|
|
|
lease->n_hw->hardware_addr.hbuf,
|
|
|
|
lease->n_hw->hardware_addr.hlen,
|
|
|
|
lease->n_hw, MDL);
|
|
|
|
lease_dereference(&lease->n_hw, MDL);
|
2000-05-16 23:03:49 +00:00
|
|
|
}
|
1999-09-28 22:49:31 +00:00
|
|
|
} else {
|
|
|
|
/* Otherwise, look for the lease in the list of leases
|
|
|
|
attached to the hash table entry, and remove it if
|
|
|
|
we find it. */
|
2001-03-15 23:22:33 +00:00
|
|
|
while (head -> n_hw) {
|
|
|
|
if (head -> n_hw == lease) {
|
|
|
|
lease_dereference (&head -> n_hw, MDL);
|
2000-05-16 23:03:49 +00:00
|
|
|
if (lease -> n_hw) {
|
2001-03-15 23:22:33 +00:00
|
|
|
lease_reference (&head -> n_hw,
|
2000-05-16 23:03:49 +00:00
|
|
|
lease -> n_hw, MDL);
|
|
|
|
lease_dereference (&lease -> n_hw,
|
|
|
|
MDL);
|
|
|
|
}
|
1999-09-28 22:49:31 +00:00
|
|
|
break;
|
|
|
|
}
|
2001-03-15 23:22:33 +00:00
|
|
|
lease_reference (&next, head -> n_hw, MDL);
|
|
|
|
lease_dereference (&head, MDL);
|
|
|
|
lease_reference (&head, next, MDL);
|
|
|
|
lease_dereference (&next, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
}
|
2001-03-15 23:22:33 +00:00
|
|
|
if (head)
|
|
|
|
lease_dereference (&head, MDL);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
2013-11-08 12:29:20 -08:00
|
|
|
/* Write v4 leases to permanent storage. */
|
|
|
|
int write_leases4(void) {
|
|
|
|
struct lease *l;
|
|
|
|
struct shared_network *s;
|
|
|
|
struct pool *p;
|
2015-05-27 13:17:46 -07:00
|
|
|
LEASE_STRUCT_PTR lptr[RESERVED_LEASES+1];
|
2013-11-08 12:29:20 -08:00
|
|
|
int num_written = 0, i;
|
|
|
|
|
|
|
|
/* Write all the leases. */
|
|
|
|
for (s = shared_networks; s; s = s->next) {
|
|
|
|
for (p = s->pools; p; p = p->next) {
|
|
|
|
lptr[FREE_LEASES] = &p->free;
|
|
|
|
lptr[ACTIVE_LEASES] = &p->active;
|
|
|
|
lptr[EXPIRED_LEASES] = &p->expired;
|
|
|
|
lptr[ABANDONED_LEASES] = &p->abandoned;
|
|
|
|
lptr[BACKUP_LEASES] = &p->backup;
|
|
|
|
lptr[RESERVED_LEASES] = &p->reserved;
|
|
|
|
|
|
|
|
for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
|
2015-05-27 13:17:46 -07:00
|
|
|
for (l = LEASE_GET_FIRSTP(lptr[i]);
|
|
|
|
l != NULL;
|
|
|
|
l = LEASE_GET_NEXTP(lptr[i], l)) {
|
2013-11-08 12:29:20 -08:00
|
|
|
#if !defined (DEBUG_DUMP_ALL_LEASES)
|
|
|
|
if (l->hardware_addr.hlen != 0 || l->uid_len != 0 ||
|
|
|
|
l->tsfp != 0 || l->binding_state != FTS_FREE)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
if (write_lease(l) == 0)
|
|
|
|
return (0);
|
|
|
|
num_written++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
log_info ("Wrote %d leases to leases file.", num_written);
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
1999-09-28 22:49:31 +00:00
|
|
|
/* Write all interesting leases to permanent storage. */
|
|
|
|
|
2001-06-27 00:31:20 +00:00
|
|
|
int write_leases ()
|
1999-09-28 22:49:31 +00:00
|
|
|
{
|
|
|
|
struct host_decl *hp;
|
|
|
|
struct group_object *gp;
|
1999-10-01 03:26:45 +00:00
|
|
|
struct hash_bucket *hb;
|
2001-06-22 16:47:20 +00:00
|
|
|
struct class *cp;
|
|
|
|
struct collection *colp;
|
1999-10-01 03:26:45 +00:00
|
|
|
int i;
|
1999-10-27 23:05:17 +00:00
|
|
|
int num_written;
|
1999-10-01 03:26:45 +00:00
|
|
|
|
2001-06-22 16:47:20 +00:00
|
|
|
/* write all the dynamically-created class declarations. */
|
|
|
|
if (collections->classes) {
|
2001-07-10 20:36:06 +00:00
|
|
|
numclasseswritten = 0;
|
2001-06-22 16:47:20 +00:00
|
|
|
for (colp = collections ; colp ; colp = colp->next) {
|
|
|
|
for (cp = colp->classes ; cp ; cp = cp->nic) {
|
2006-03-02 19:02:56 +00:00
|
|
|
write_named_billing_class(
|
|
|
|
(unsigned char *)cp->name,
|
2001-06-22 16:47:20 +00:00
|
|
|
0, cp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-22 13:39:45 -05:00
|
|
|
/* XXXJAB this number doesn't include subclasses... */
|
2001-07-10 20:36:06 +00:00
|
|
|
log_info ("Wrote %d class decls to leases file.",
|
|
|
|
numclasseswritten);
|
2001-06-22 16:47:20 +00:00
|
|
|
}
|
2019-11-22 13:39:45 -05:00
|
|
|
|
|
|
|
|
1999-10-01 03:26:45 +00:00
|
|
|
/* Write all the dynamically-created group declarations. */
|
1999-10-05 18:44:27 +00:00
|
|
|
if (group_name_hash) {
|
1999-10-27 23:05:17 +00:00
|
|
|
num_written = 0;
|
1999-10-05 18:44:27 +00:00
|
|
|
for (i = 0; i < group_name_hash -> hash_count; i++) {
|
1999-10-01 03:26:45 +00:00
|
|
|
for (hb = group_name_hash -> buckets [i];
|
|
|
|
hb; hb = hb -> next) {
|
|
|
|
gp = (struct group_object *)hb -> value;
|
|
|
|
if ((gp -> flags & GROUP_OBJECT_DYNAMIC) ||
|
|
|
|
((gp -> flags & GROUP_OBJECT_STATIC) &&
|
1999-10-27 23:05:17 +00:00
|
|
|
(gp -> flags & GROUP_OBJECT_DELETED))) {
|
2001-06-27 00:31:20 +00:00
|
|
|
if (!write_group (gp))
|
|
|
|
return 0;
|
1999-10-27 23:05:17 +00:00
|
|
|
++num_written;
|
|
|
|
}
|
1999-10-01 03:26:45 +00:00
|
|
|
}
|
1999-10-05 18:44:27 +00:00
|
|
|
}
|
1999-10-27 23:05:17 +00:00
|
|
|
log_info ("Wrote %d group decls to leases file.", num_written);
|
1999-10-01 03:26:45 +00:00
|
|
|
}
|
1999-09-28 22:49:31 +00:00
|
|
|
|
1999-10-25 01:55:40 +00:00
|
|
|
/* Write all the deleted host declarations. */
|
1999-10-24 23:27:52 +00:00
|
|
|
if (host_name_hash) {
|
1999-10-27 23:05:17 +00:00
|
|
|
num_written = 0;
|
1999-10-24 23:27:52 +00:00
|
|
|
for (i = 0; i < host_name_hash -> hash_count; i++) {
|
|
|
|
for (hb = host_name_hash -> buckets [i];
|
|
|
|
hb; hb = hb -> next) {
|
|
|
|
hp = (struct host_decl *)hb -> value;
|
1999-10-25 01:55:40 +00:00
|
|
|
if (((hp -> flags & HOST_DECL_STATIC) &&
|
1999-10-27 23:05:17 +00:00
|
|
|
(hp -> flags & HOST_DECL_DELETED))) {
|
2001-06-27 00:31:20 +00:00
|
|
|
if (!write_host (hp))
|
|
|
|
return 0;
|
1999-10-27 23:05:17 +00:00
|
|
|
++num_written;
|
|
|
|
}
|
1999-10-24 23:27:52 +00:00
|
|
|
}
|
|
|
|
}
|
1999-10-27 23:05:17 +00:00
|
|
|
log_info ("Wrote %d deleted host decls to leases file.",
|
|
|
|
num_written);
|
1999-10-24 23:27:52 +00:00
|
|
|
}
|
1999-09-28 22:49:31 +00:00
|
|
|
|
1999-10-25 01:55:40 +00:00
|
|
|
/* Write all the new, dynamic host declarations. */
|
|
|
|
if (host_name_hash) {
|
1999-10-27 23:05:17 +00:00
|
|
|
num_written = 0;
|
1999-10-25 01:55:40 +00:00
|
|
|
for (i = 0; i < host_name_hash -> hash_count; i++) {
|
|
|
|
for (hb = host_name_hash -> buckets [i];
|
|
|
|
hb; hb = hb -> next) {
|
|
|
|
hp = (struct host_decl *)hb -> value;
|
1999-10-27 23:05:17 +00:00
|
|
|
if ((hp -> flags & HOST_DECL_DYNAMIC)) {
|
2001-06-27 00:31:20 +00:00
|
|
|
if (!write_host (hp))
|
|
|
|
++num_written;
|
1999-10-27 23:05:17 +00:00
|
|
|
}
|
1999-10-25 01:55:40 +00:00
|
|
|
}
|
|
|
|
}
|
1999-10-27 23:05:17 +00:00
|
|
|
log_info ("Wrote %d new dynamic host decls to leases file.",
|
|
|
|
num_written);
|
1999-10-25 01:55:40 +00:00
|
|
|
}
|
|
|
|
|
2000-05-03 06:34:13 +00:00
|
|
|
#if defined (FAILOVER_PROTOCOL)
|
|
|
|
/* Write all the failover states. */
|
2001-06-27 00:31:20 +00:00
|
|
|
if (!dhcp_failover_write_all_states ())
|
|
|
|
return 0;
|
2000-05-03 06:34:13 +00:00
|
|
|
#endif
|
|
|
|
|
2013-11-08 12:29:20 -08:00
|
|
|
switch (local_family) {
|
|
|
|
case AF_INET:
|
|
|
|
if (write_leases4() == 0)
|
|
|
|
return (0);
|
|
|
|
break;
|
2007-05-19 18:47:15 +00:00
|
|
|
#ifdef DHCPv6
|
2013-11-08 12:29:20 -08:00
|
|
|
case AF_INET6:
|
|
|
|
if (write_leases6() == 0)
|
|
|
|
return (0);
|
|
|
|
break;
|
2007-05-19 18:47:15 +00:00
|
|
|
#endif /* DHCPv6 */
|
2013-11-08 12:29:20 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (commit_leases() == 0)
|
|
|
|
return (0);
|
|
|
|
return (1);
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
|
2015-05-27 13:17:46 -07:00
|
|
|
#if !defined (BINARY_LEASES)
|
2015-11-05 07:07:42 -05:00
|
|
|
/* Unlink all the leases in the queue. */
|
2015-05-27 13:17:46 -07:00
|
|
|
void lease_remove_all(struct lease **lq) {
|
|
|
|
struct lease *lp, *ln = NULL;
|
|
|
|
|
|
|
|
/* nothing to do */
|
|
|
|
if (*lq == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* We simply derefernce the first item in the list. When
|
|
|
|
* it's reference counter goes to zero it will be cleaned
|
|
|
|
* and the reference counter
|
|
|
|
*
|
|
|
|
* Get a pointer to the first item in the list and then
|
|
|
|
* drop the reference from the queue pointer
|
|
|
|
*/
|
|
|
|
lease_reference(&lp, *lq, MDL);
|
|
|
|
lease_dereference(lq, MDL);
|
|
|
|
|
|
|
|
do {
|
|
|
|
/* if we have a next save a pointer to it and unlink it */
|
|
|
|
if (lp->next) {
|
|
|
|
lease_reference(&ln, lp->next, MDL);
|
|
|
|
lease_dereference(&lp->next, MDL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get rid of what we currently have */
|
|
|
|
lease_dereference(&lp, MDL);
|
|
|
|
|
|
|
|
/* move the next to the current and loop */
|
|
|
|
lp = ln;
|
|
|
|
ln = NULL;
|
|
|
|
} while (lp != NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This routine walks through a given lease queue (lq) looking
|
|
|
|
* for comp. If it doesn't find the lease it is a fatal error
|
|
|
|
* as it should be on the given queue. Once we find the lease
|
|
|
|
* we can remove it from this list.
|
|
|
|
*/
|
|
|
|
void lease_remove(struct lease **lq, struct lease *comp)
|
|
|
|
{
|
|
|
|
struct lease *prev, *lp;
|
|
|
|
|
|
|
|
prev = NULL;
|
|
|
|
for (lp = *lq; lp != NULL; lp = lp->next) {
|
|
|
|
if (lp == comp)
|
|
|
|
break;
|
|
|
|
prev = lp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!lp) {
|
|
|
|
log_fatal("Lease with binding state %s not on its queue.",
|
|
|
|
(comp->binding_state < 1 ||
|
|
|
|
comp->binding_state > FTS_LAST)
|
|
|
|
? "unknown"
|
|
|
|
: binding_state_names[comp->binding_state - 1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prev) {
|
|
|
|
lease_dereference(&prev->next, MDL);
|
|
|
|
if (comp->next) {
|
|
|
|
lease_reference(&prev->next, comp->next, MDL);
|
|
|
|
lease_dereference (&comp->next, MDL);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
lease_dereference(lq, MDL);
|
|
|
|
if (comp->next) {
|
|
|
|
lease_reference(lq, comp->next, MDL);
|
|
|
|
lease_dereference(&comp->next, MDL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This routine inserts comp into lq in a sorted fashion.
|
|
|
|
* The sort key is comp->sort_time, smaller values are
|
|
|
|
* placed earlier in the list.
|
|
|
|
*/
|
|
|
|
void lease_insert(struct lease **lq, struct lease *comp)
|
|
|
|
{
|
|
|
|
struct lease *prev, *lp;
|
|
|
|
static struct lease **last_lq = NULL;
|
|
|
|
static struct lease *last_insert_point = NULL;
|
|
|
|
|
|
|
|
/* This only works during server startup: during runtime, the last
|
|
|
|
* lease may be dequeued in between calls. If the queue is the same
|
|
|
|
* as was used previously, and the lease structure isn't (this is not
|
|
|
|
* a re-queue), use that as a starting point for the insertion-sort.
|
|
|
|
*/
|
|
|
|
if ((server_starting & SS_QFOLLOW) && (lq == last_lq) &&
|
2019-11-22 13:39:45 -05:00
|
|
|
(comp != last_insert_point) &&
|
2015-05-27 13:17:46 -07:00
|
|
|
(last_insert_point->sort_time <= comp->sort_time)) {
|
|
|
|
prev = last_insert_point;
|
|
|
|
lp = prev->next;
|
|
|
|
} else {
|
|
|
|
prev = NULL;
|
|
|
|
lp = *lq;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Insertion sort the lease onto the appropriate queue. */
|
|
|
|
for (; lp != NULL ; lp = lp->next) {
|
|
|
|
if (lp->sort_time >= comp->sort_time)
|
|
|
|
break;
|
|
|
|
prev = lp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prev) {
|
|
|
|
if (prev->next) {
|
|
|
|
lease_reference(&comp->next, prev->next, MDL);
|
|
|
|
lease_dereference(&prev->next, MDL);
|
|
|
|
}
|
|
|
|
lease_reference(&prev->next, comp, MDL);
|
|
|
|
} else {
|
|
|
|
if (*lq) {
|
|
|
|
lease_reference (&comp->next, *lq, MDL);
|
|
|
|
lease_dereference(lq, MDL);
|
|
|
|
}
|
|
|
|
lease_reference(lq, comp, MDL);
|
|
|
|
}
|
|
|
|
last_insert_point = comp;
|
|
|
|
last_lq = lq;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-02-24 23:16:32 +00:00
|
|
|
/* In addition to placing this lease upon a lease queue depending on its
|
|
|
|
* state, it also keeps track of the number of FREE and BACKUP leases in
|
|
|
|
* existence, and sets the sort_time on the lease.
|
|
|
|
*
|
|
|
|
* Sort_time is used in pool_timer() to determine when the lease will
|
|
|
|
* bubble to the top of the list and be supersede_lease()'d into its next
|
|
|
|
* state (possibly, if all goes well). Example, ACTIVE leases move to
|
|
|
|
* EXPIRED state when the 'ends' value is reached, so that is its sort
|
|
|
|
* time. Most queues are sorted by 'ends', since it is generally best
|
|
|
|
* practice to re-use the oldest lease, to reduce address collision
|
|
|
|
* chances.
|
|
|
|
*/
|
2000-06-07 00:15:53 +00:00
|
|
|
int lease_enqueue (struct lease *comp)
|
|
|
|
{
|
2019-11-22 13:39:45 -05:00
|
|
|
LEASE_STRUCT_PTR lq;
|
2000-06-07 00:15:53 +00:00
|
|
|
|
|
|
|
/* No queue to put it on? */
|
|
|
|
if (!comp -> pool)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Figure out which queue it's going to. */
|
|
|
|
switch (comp -> binding_state) {
|
|
|
|
case FTS_FREE:
|
2006-04-27 17:26:42 +00:00
|
|
|
if (comp->flags & RESERVED_LEASE) {
|
|
|
|
lq = &comp->pool->reserved;
|
|
|
|
} else {
|
|
|
|
lq = &comp->pool->free;
|
|
|
|
comp->pool->free_leases++;
|
|
|
|
}
|
2000-06-07 00:15:53 +00:00
|
|
|
comp -> sort_time = comp -> ends;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FTS_ACTIVE:
|
|
|
|
lq = &comp -> pool -> active;
|
|
|
|
comp -> sort_time = comp -> ends;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FTS_EXPIRED:
|
|
|
|
case FTS_RELEASED:
|
|
|
|
case FTS_RESET:
|
|
|
|
lq = &comp -> pool -> expired;
|
2006-02-24 23:16:32 +00:00
|
|
|
#if defined(FAILOVER_PROTOCOL)
|
|
|
|
/* In partner_down, tsfp is the time at which the lease
|
|
|
|
* may be reallocated (stos+mclt). We can do that with
|
|
|
|
* lease_mine_to_reallocate() anywhere between tsfp and
|
|
|
|
* ends. But we prefer to wait until ends before doing it
|
|
|
|
* automatically (choose the greater of the two). Note
|
|
|
|
* that 'ends' is usually a historic timestamp in the
|
|
|
|
* case of expired leases, is really only in the future
|
|
|
|
* on released leases, and if we know a lease to be released
|
|
|
|
* the peer might still know it to be active...in which case
|
|
|
|
* it's possible the peer has renewed this lease, so avoid
|
|
|
|
* doing that.
|
|
|
|
*/
|
|
|
|
if (comp->pool->failover_peer &&
|
|
|
|
comp->pool->failover_peer->me.state == partner_down)
|
|
|
|
comp->sort_time = (comp->tsfp > comp->ends) ?
|
|
|
|
comp->tsfp : comp->ends;
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
comp->sort_time = comp->ends;
|
2000-06-07 00:15:53 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FTS_ABANDONED:
|
|
|
|
lq = &comp -> pool -> abandoned;
|
|
|
|
comp -> sort_time = comp -> ends;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FTS_BACKUP:
|
2006-04-27 17:26:42 +00:00
|
|
|
if (comp->flags & RESERVED_LEASE) {
|
|
|
|
lq = &comp->pool->reserved;
|
|
|
|
} else {
|
|
|
|
lq = &comp->pool->backup;
|
|
|
|
comp->pool->backup_leases++;
|
|
|
|
}
|
2000-06-07 00:15:53 +00:00
|
|
|
comp -> sort_time = comp -> ends;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
log_error ("Lease with bogus binding state: %d",
|
|
|
|
comp -> binding_state);
|
2001-04-16 22:32:58 +00:00
|
|
|
#if defined (BINDING_STATE_DEBUG)
|
|
|
|
abort ();
|
|
|
|
#endif
|
2000-06-07 00:15:53 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-05-27 13:17:46 -07:00
|
|
|
LEASE_INSERTP(lq, comp);
|
2006-06-09 15:51:02 +00:00
|
|
|
|
2000-06-07 00:15:53 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* For a given lease, sort it onto the right list in its pool and put it
|
|
|
|
in each appropriate hash, understanding that it's already by definition
|
|
|
|
in lease_ip_addr_hash. */
|
|
|
|
|
2005-09-30 17:57:32 +00:00
|
|
|
isc_result_t
|
2006-06-01 20:23:18 +00:00
|
|
|
lease_instantiate(const void *key, unsigned len, void *object)
|
2000-06-07 00:15:53 +00:00
|
|
|
{
|
2005-09-30 17:57:32 +00:00
|
|
|
struct lease *lease = object;
|
2001-04-30 22:38:34 +00:00
|
|
|
struct class *class;
|
2000-06-07 00:15:53 +00:00
|
|
|
/* XXX If the lease doesn't have a pool at this point, it's an
|
|
|
|
XXX orphan, which we *should* keep around until it expires,
|
|
|
|
XXX but which right now we just forget. */
|
|
|
|
if (!lease -> pool) {
|
2006-10-27 22:54:13 +00:00
|
|
|
lease_ip_hash_delete(lease_ip_addr_hash, lease->ip_addr.iabuf,
|
|
|
|
lease->ip_addr.len, MDL);
|
2005-09-30 17:57:32 +00:00
|
|
|
return ISC_R_SUCCESS;
|
2000-06-07 00:15:53 +00:00
|
|
|
}
|
2014-12-10 14:54:46 -05:00
|
|
|
|
|
|
|
#if defined (FAILOVER_PROTOCOL)
|
|
|
|
/* If the lease is in FTS_BACKUP but there is no peer, then the
|
|
|
|
* pool must have been formerly configured for failover and
|
|
|
|
* is now configured as standalone. This means we need to
|
|
|
|
* move the lease to FTS_FREE to make it available. */
|
2019-11-22 13:39:45 -05:00
|
|
|
if ((lease->binding_state == FTS_BACKUP) &&
|
2014-12-10 14:54:46 -05:00
|
|
|
(lease->pool->failover_peer == NULL)) {
|
|
|
|
#else
|
|
|
|
/* We aren't compiled for failover, so just move to FTS_FREE */
|
2019-11-22 13:39:45 -05:00
|
|
|
if (lease->binding_state == FTS_BACKUP) {
|
2014-12-10 14:54:46 -05:00
|
|
|
#endif
|
|
|
|
lease->binding_state = FTS_FREE;
|
|
|
|
lease->next_binding_state = FTS_FREE;
|
|
|
|
lease->rewind_binding_state = FTS_FREE;
|
|
|
|
}
|
2019-11-22 13:39:45 -05:00
|
|
|
|
2005-09-30 17:57:32 +00:00
|
|
|
/* Put the lease on the right queue. Failure to queue is probably
|
|
|
|
* due to a bogus binding state. In such a case, we claim success,
|
|
|
|
* so that later leases in a hash_foreach are processed, but we
|
|
|
|
* return early as we really don't want hw address hash entries or
|
|
|
|
* other cruft to surround such a bogus entry.
|
|
|
|
*/
|
|
|
|
if (!lease_enqueue(lease))
|
|
|
|
return ISC_R_SUCCESS;
|
2000-06-07 00:15:53 +00:00
|
|
|
|
|
|
|
/* Record the lease in the uid hash if possible. */
|
|
|
|
if (lease -> uid) {
|
|
|
|
uid_hash_add (lease);
|
|
|
|
}
|
2005-09-30 17:57:32 +00:00
|
|
|
|
2000-06-07 00:15:53 +00:00
|
|
|
/* Record it in the hardware address hash if possible. */
|
|
|
|
if (lease -> hardware_addr.hlen) {
|
|
|
|
hw_hash_add (lease);
|
|
|
|
}
|
2005-09-30 17:57:32 +00:00
|
|
|
|
2001-04-30 22:38:34 +00:00
|
|
|
/* If the lease has a billing class, set up the billing. */
|
|
|
|
if (lease -> billing_class) {
|
|
|
|
class = (struct class *)0;
|
|
|
|
class_reference (&class, lease -> billing_class, MDL);
|
|
|
|
class_dereference (&lease -> billing_class, MDL);
|
|
|
|
/* If the lease is available for allocation, the billing
|
|
|
|
is invalid, so we don't keep it. */
|
|
|
|
if (lease -> binding_state == FTS_ACTIVE ||
|
|
|
|
lease -> binding_state == FTS_EXPIRED ||
|
|
|
|
lease -> binding_state == FTS_RELEASED ||
|
2005-03-17 20:15:29 +00:00
|
|
|
lease -> binding_state == FTS_RESET)
|
2001-04-30 22:38:34 +00:00
|
|
|
bill_class (lease, class);
|
|
|
|
class_dereference (&class, MDL);
|
|
|
|
}
|
2005-09-30 17:57:32 +00:00
|
|
|
return ISC_R_SUCCESS;
|
2000-06-07 00:15:53 +00:00
|
|
|
}
|
|
|
|
|
2000-05-04 18:58:16 +00:00
|
|
|
/* Run expiry events on every pool. This is called on startup so that
|
|
|
|
any expiry events that occurred after the server stopped and before it
|
|
|
|
was restarted can be run. At the same time, if failover support is
|
|
|
|
compiled in, we compute the balance of leases for the pool. */
|
1999-10-08 22:17:41 +00:00
|
|
|
|
|
|
|
void expire_all_pools ()
|
|
|
|
{
|
|
|
|
struct shared_network *s;
|
|
|
|
struct pool *p;
|
|
|
|
int i;
|
2000-05-04 18:58:16 +00:00
|
|
|
struct lease *l;
|
2015-05-27 13:17:46 -07:00
|
|
|
LEASE_STRUCT_PTR lptr[RESERVED_LEASES+1];
|
1999-10-08 22:17:41 +00:00
|
|
|
|
2006-06-09 15:51:02 +00:00
|
|
|
/* Indicate that we are in the startup phase */
|
|
|
|
server_starting = SS_NOSYNC | SS_QFOLLOW;
|
|
|
|
|
2015-05-27 13:17:46 -07:00
|
|
|
#if defined (BINARY_LEASES)
|
|
|
|
/* set up the growth factors for the binary leases.
|
|
|
|
* We use 100% for free, 50% for active and backup
|
|
|
|
* 20% for expired, abandoned and reserved
|
|
|
|
* but no less than 100, 50, and 20.
|
|
|
|
*/
|
|
|
|
for (s = shared_networks; s; s = s -> next) {
|
|
|
|
for (p = s -> pools; p != NULL; p = p -> next) {
|
|
|
|
size_t num_f = 100, num_a = 50, num_e = 20;
|
|
|
|
if (p->lease_count > 100) {
|
|
|
|
num_f = p->lease_count;
|
|
|
|
num_a = num_f / 2;
|
|
|
|
num_e = num_f / 5;
|
|
|
|
}
|
|
|
|
lc_init_growth(&p->free, num_f);
|
|
|
|
lc_init_growth(&p->active, num_a);
|
|
|
|
lc_init_growth(&p->expired, num_a);
|
|
|
|
lc_init_growth(&p->abandoned, num_e);
|
|
|
|
lc_init_growth(&p->backup, num_e);
|
|
|
|
lc_init_growth(&p->reserved, num_e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2000-06-07 00:15:53 +00:00
|
|
|
/* First, go over the hash list and actually put all the leases
|
|
|
|
on the appropriate lists. */
|
2006-10-27 22:54:13 +00:00
|
|
|
lease_ip_hash_foreach(lease_ip_addr_hash, lease_instantiate);
|
2000-06-07 00:15:53 +00:00
|
|
|
|
1999-10-08 22:17:41 +00:00
|
|
|
/* Loop through each pool in each shared network and call the
|
2006-06-09 15:51:02 +00:00
|
|
|
* expiry routine on the pool. It is no longer safe to follow
|
|
|
|
* the queue insertion point, as expiration of a lease can move
|
|
|
|
* it between queues (and this may be the lease that function
|
|
|
|
* points at).
|
|
|
|
*/
|
|
|
|
server_starting &= ~SS_QFOLLOW;
|
2000-05-04 18:58:16 +00:00
|
|
|
for (s = shared_networks; s; s = s -> next) {
|
|
|
|
for (p = s -> pools; p; p = p -> next) {
|
|
|
|
pool_timer (p);
|
|
|
|
|
|
|
|
p -> lease_count = 0;
|
2000-06-02 21:27:21 +00:00
|
|
|
p -> free_leases = 0;
|
|
|
|
p -> backup_leases = 0;
|
2006-06-09 15:51:02 +00:00
|
|
|
|
2000-06-02 21:27:21 +00:00
|
|
|
lptr [FREE_LEASES] = &p -> free;
|
|
|
|
lptr [ACTIVE_LEASES] = &p -> active;
|
|
|
|
lptr [EXPIRED_LEASES] = &p -> expired;
|
|
|
|
lptr [ABANDONED_LEASES] = &p -> abandoned;
|
|
|
|
lptr [BACKUP_LEASES] = &p -> backup;
|
2006-04-27 17:26:42 +00:00
|
|
|
lptr [RESERVED_LEASES] = &p->reserved;
|
2000-06-02 21:27:21 +00:00
|
|
|
|
2006-04-27 17:26:42 +00:00
|
|
|
for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
|
2015-05-27 13:17:46 -07:00
|
|
|
for (l = LEASE_GET_FIRSTP(lptr[i]);
|
|
|
|
l != NULL;
|
|
|
|
l = LEASE_GET_NEXTP(lptr[i], l)) {
|
2000-05-04 18:58:16 +00:00
|
|
|
p -> lease_count++;
|
|
|
|
if (l -> ends <= cur_time) {
|
2006-05-05 20:32:31 +00:00
|
|
|
if (l->binding_state == FTS_FREE) {
|
|
|
|
if (i == FREE_LEASES)
|
|
|
|
p->free_leases++;
|
2007-10-01 15:12:19 +00:00
|
|
|
else if (i != RESERVED_LEASES)
|
2006-05-05 20:32:31 +00:00
|
|
|
log_fatal("Impossible case "
|
|
|
|
"at %s:%d.", MDL);
|
|
|
|
} else if (l->binding_state == FTS_BACKUP) {
|
|
|
|
if (i == BACKUP_LEASES)
|
|
|
|
p->backup_leases++;
|
2007-10-01 15:12:19 +00:00
|
|
|
else if (i != RESERVED_LEASES)
|
2006-05-05 20:32:31 +00:00
|
|
|
log_fatal("Impossible case "
|
|
|
|
"at %s:%d.", MDL);
|
|
|
|
}
|
2000-05-04 18:58:16 +00:00
|
|
|
}
|
2000-07-06 10:27:41 +00:00
|
|
|
#if defined (FAILOVER_PROTOCOL)
|
2000-05-04 18:58:16 +00:00
|
|
|
if (p -> failover_peer &&
|
2006-02-24 23:16:32 +00:00
|
|
|
l -> tstp > l -> atsfp &&
|
2005-03-17 20:15:29 +00:00
|
|
|
!(l -> flags & ON_UPDATE_QUEUE)) {
|
|
|
|
l -> desired_binding_state = l -> binding_state;
|
2000-06-02 21:27:21 +00:00
|
|
|
dhcp_failover_queue_update (l, 1);
|
2005-03-17 20:15:29 +00:00
|
|
|
}
|
2000-07-06 10:27:41 +00:00
|
|
|
#endif
|
2000-06-02 21:27:21 +00:00
|
|
|
}
|
2000-05-04 18:58:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-06-09 15:51:02 +00:00
|
|
|
|
|
|
|
/* turn off startup phase */
|
|
|
|
server_starting = 0;
|
1999-10-08 22:17:41 +00:00
|
|
|
}
|
|
|
|
|
1999-09-28 22:49:31 +00:00
|
|
|
void dump_subnets ()
|
|
|
|
{
|
|
|
|
struct lease *l;
|
|
|
|
struct shared_network *s;
|
|
|
|
struct subnet *n;
|
|
|
|
struct pool *p;
|
2015-05-27 13:17:46 -07:00
|
|
|
LEASE_STRUCT_PTR lptr[RESERVED_LEASES+1];
|
2000-06-02 21:27:21 +00:00
|
|
|
int i;
|
1999-09-28 22:49:31 +00:00
|
|
|
|
|
|
|
log_info ("Subnets:");
|
|
|
|
for (n = subnets; n; n = n -> next_subnet) {
|
|
|
|
log_debug (" Subnet %s", piaddr (n -> net));
|
|
|
|
log_debug (" netmask %s",
|
|
|
|
piaddr (n -> netmask));
|
|
|
|
}
|
|
|
|
log_info ("Shared networks:");
|
|
|
|
for (s = shared_networks; s; s = s -> next) {
|
2000-06-02 21:27:21 +00:00
|
|
|
log_info (" %s", s -> name);
|
|
|
|
for (p = s -> pools; p; p = p -> next) {
|
|
|
|
lptr [FREE_LEASES] = &p -> free;
|
|
|
|
lptr [ACTIVE_LEASES] = &p -> active;
|
|
|
|
lptr [EXPIRED_LEASES] = &p -> expired;
|
|
|
|
lptr [ABANDONED_LEASES] = &p -> abandoned;
|
|
|
|
lptr [BACKUP_LEASES] = &p -> backup;
|
2006-04-27 17:26:42 +00:00
|
|
|
lptr [RESERVED_LEASES] = &p->reserved;
|
2000-06-02 21:27:21 +00:00
|
|
|
|
2006-04-27 17:26:42 +00:00
|
|
|
for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
|
2015-05-27 13:17:46 -07:00
|
|
|
for (l = LEASE_GET_FIRSTP(lptr[i]);
|
|
|
|
l != NULL;
|
|
|
|
l = LEASE_GET_NEXTP(lptr[i], l)) {
|
2000-06-02 21:27:21 +00:00
|
|
|
print_lease (l);
|
|
|
|
}
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
2000-06-02 21:27:21 +00:00
|
|
|
}
|
1999-09-28 22:49:31 +00:00
|
|
|
}
|
|
|
|
}
|
2000-05-16 23:03:49 +00:00
|
|
|
|
2006-10-27 22:54:13 +00:00
|
|
|
HASH_FUNCTIONS(lease_ip, const unsigned char *, struct lease, lease_ip_hash_t,
|
|
|
|
lease_reference, lease_dereference, do_ip4_hash)
|
|
|
|
HASH_FUNCTIONS(lease_id, const unsigned char *, struct lease, lease_id_hash_t,
|
|
|
|
lease_reference, lease_dereference, do_id_hash)
|
2005-03-17 20:15:29 +00:00
|
|
|
HASH_FUNCTIONS (host, const unsigned char *, struct host_decl, host_hash_t,
|
2006-06-01 20:23:18 +00:00
|
|
|
host_reference, host_dereference, do_string_hash)
|
2005-03-17 20:15:29 +00:00
|
|
|
HASH_FUNCTIONS (class, const char *, struct class, class_hash_t,
|
2006-06-01 20:23:18 +00:00
|
|
|
class_reference, class_dereference, do_string_hash)
|
2001-06-27 00:31:20 +00:00
|
|
|
|
2005-03-17 20:15:29 +00:00
|
|
|
#if defined (DEBUG_MEMORY_LEAKAGE) && \
|
2001-06-27 00:31:20 +00:00
|
|
|
defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
|
|
|
|
extern struct hash_table *dns_zone_hash;
|
|
|
|
extern struct interface_info **interface_vector;
|
|
|
|
extern int interface_count;
|
|
|
|
dhcp_control_object_t *dhcp_control_object;
|
|
|
|
extern struct hash_table *auth_key_hash;
|
|
|
|
struct hash_table *universe_hash;
|
|
|
|
struct universe **universes;
|
|
|
|
int universe_count, universe_max;
|
2005-03-17 20:15:29 +00:00
|
|
|
#if 0
|
2001-06-27 00:31:20 +00:00
|
|
|
extern int end;
|
2005-03-17 20:15:29 +00:00
|
|
|
#endif
|
2001-06-27 00:31:20 +00:00
|
|
|
|
|
|
|
#if defined (COMPACT_LEASES)
|
|
|
|
extern struct lease *lease_hunks;
|
|
|
|
#endif
|
|
|
|
|
2009-04-07 19:55:52 +00:00
|
|
|
void free_everything(void)
|
2001-06-27 00:31:20 +00:00
|
|
|
{
|
|
|
|
struct subnet *sc = (struct subnet *)0, *sn = (struct subnet *)0;
|
|
|
|
struct shared_network *nc = (struct shared_network *)0,
|
|
|
|
*nn = (struct shared_network *)0;
|
|
|
|
struct pool *pc = (struct pool *)0, *pn = (struct pool *)0;
|
2015-05-27 13:17:46 -07:00
|
|
|
struct lease *lc = NULL, *ln = NULL, *ltemp = NULL;
|
2001-06-27 00:31:20 +00:00
|
|
|
struct interface_info *ic = (struct interface_info *)0,
|
|
|
|
*in = (struct interface_info *)0;
|
|
|
|
struct class *cc = (struct class *)0, *cn = (struct class *)0;
|
|
|
|
struct collection *lp;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Get rid of all the hash tables. */
|
|
|
|
if (host_hw_addr_hash)
|
2005-03-17 20:15:29 +00:00
|
|
|
host_free_hash_table (&host_hw_addr_hash, MDL);
|
2001-06-27 00:31:20 +00:00
|
|
|
host_hw_addr_hash = 0;
|
|
|
|
if (host_uid_hash)
|
2005-03-17 20:15:29 +00:00
|
|
|
host_free_hash_table (&host_uid_hash, MDL);
|
2001-06-27 00:31:20 +00:00
|
|
|
host_uid_hash = 0;
|
|
|
|
if (lease_uid_hash)
|
2009-04-07 19:55:52 +00:00
|
|
|
lease_id_free_hash_table (&lease_uid_hash, MDL);
|
2001-06-27 00:31:20 +00:00
|
|
|
lease_uid_hash = 0;
|
|
|
|
if (lease_ip_addr_hash)
|
2009-04-07 19:55:52 +00:00
|
|
|
lease_ip_free_hash_table (&lease_ip_addr_hash, MDL);
|
2001-06-27 00:31:20 +00:00
|
|
|
lease_ip_addr_hash = 0;
|
|
|
|
if (lease_hw_addr_hash)
|
2009-04-07 19:55:52 +00:00
|
|
|
lease_id_free_hash_table (&lease_hw_addr_hash, MDL);
|
2001-06-27 00:31:20 +00:00
|
|
|
lease_hw_addr_hash = 0;
|
|
|
|
if (host_name_hash)
|
2005-03-17 20:15:29 +00:00
|
|
|
host_free_hash_table (&host_name_hash, MDL);
|
2001-06-27 00:31:20 +00:00
|
|
|
host_name_hash = 0;
|
|
|
|
if (dns_zone_hash)
|
2005-03-17 20:15:29 +00:00
|
|
|
dns_zone_free_hash_table (&dns_zone_hash, MDL);
|
2001-06-27 00:31:20 +00:00
|
|
|
dns_zone_hash = 0;
|
2007-05-08 23:05:22 +00:00
|
|
|
|
|
|
|
while (host_id_info != NULL) {
|
|
|
|
host_id_info_t *tmp;
|
|
|
|
option_dereference(&host_id_info->option, MDL);
|
|
|
|
host_free_hash_table(&host_id_info->values_hash, MDL);
|
|
|
|
tmp = host_id_info->next;
|
|
|
|
dfree(host_id_info, MDL);
|
|
|
|
host_id_info = tmp;
|
|
|
|
}
|
2005-03-17 20:15:29 +00:00
|
|
|
#if 0
|
2001-06-27 00:31:20 +00:00
|
|
|
if (auth_key_hash)
|
2005-03-17 20:15:29 +00:00
|
|
|
auth_key_free_hash_table (&auth_key_hash, MDL);
|
|
|
|
#endif
|
2001-06-27 00:31:20 +00:00
|
|
|
auth_key_hash = 0;
|
|
|
|
|
|
|
|
omapi_object_dereference ((omapi_object_t **)&dhcp_control_object,
|
|
|
|
MDL);
|
|
|
|
|
|
|
|
for (lp = collections; lp; lp = lp -> next) {
|
|
|
|
if (lp -> classes) {
|
|
|
|
class_reference (&cn, lp -> classes, MDL);
|
|
|
|
do {
|
|
|
|
if (cn) {
|
|
|
|
class_reference (&cc, cn, MDL);
|
|
|
|
class_dereference (&cn, MDL);
|
|
|
|
}
|
|
|
|
if (cc -> nic) {
|
|
|
|
class_reference (&cn, cc -> nic, MDL);
|
|
|
|
class_dereference (&cc -> nic, MDL);
|
|
|
|
}
|
|
|
|
group_dereference (&cc -> group, MDL);
|
|
|
|
if (cc -> hash) {
|
2005-03-17 20:15:29 +00:00
|
|
|
class_free_hash_table (&cc -> hash, MDL);
|
2001-06-27 00:31:20 +00:00
|
|
|
cc -> hash = (struct hash_table *)0;
|
|
|
|
}
|
|
|
|
class_dereference (&cc, MDL);
|
|
|
|
} while (cn);
|
|
|
|
class_dereference (&lp -> classes, MDL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (interface_vector) {
|
|
|
|
for (i = 0; i < interface_count; i++) {
|
|
|
|
if (interface_vector [i])
|
|
|
|
interface_dereference (&interface_vector [i], MDL);
|
|
|
|
}
|
|
|
|
dfree (interface_vector, MDL);
|
|
|
|
interface_vector = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (interfaces) {
|
|
|
|
interface_reference (&in, interfaces, MDL);
|
|
|
|
do {
|
|
|
|
if (in) {
|
|
|
|
interface_reference (&ic, in, MDL);
|
|
|
|
interface_dereference (&in, MDL);
|
|
|
|
}
|
|
|
|
if (ic -> next) {
|
|
|
|
interface_reference (&in, ic -> next, MDL);
|
|
|
|
interface_dereference (&ic -> next, MDL);
|
|
|
|
}
|
|
|
|
omapi_unregister_io_object ((omapi_object_t *)ic);
|
|
|
|
if (ic -> shared_network) {
|
|
|
|
if (ic -> shared_network -> interface)
|
|
|
|
interface_dereference
|
|
|
|
(&ic -> shared_network -> interface, MDL);
|
|
|
|
shared_network_dereference (&ic -> shared_network, MDL);
|
|
|
|
}
|
|
|
|
interface_dereference (&ic, MDL);
|
|
|
|
} while (in);
|
|
|
|
interface_dereference (&interfaces, MDL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Subnets are complicated because of the extra links. */
|
|
|
|
if (subnets) {
|
|
|
|
subnet_reference (&sn, subnets, MDL);
|
|
|
|
do {
|
|
|
|
if (sn) {
|
|
|
|
subnet_reference (&sc, sn, MDL);
|
|
|
|
subnet_dereference (&sn, MDL);
|
|
|
|
}
|
|
|
|
if (sc -> next_subnet) {
|
|
|
|
subnet_reference (&sn, sc -> next_subnet, MDL);
|
|
|
|
subnet_dereference (&sc -> next_subnet, MDL);
|
|
|
|
}
|
|
|
|
if (sc -> next_sibling)
|
|
|
|
subnet_dereference (&sc -> next_sibling, MDL);
|
|
|
|
if (sc -> shared_network)
|
|
|
|
shared_network_dereference (&sc -> shared_network, MDL);
|
|
|
|
group_dereference (&sc -> group, MDL);
|
|
|
|
if (sc -> interface)
|
|
|
|
interface_dereference (&sc -> interface, MDL);
|
|
|
|
subnet_dereference (&sc, MDL);
|
|
|
|
} while (sn);
|
|
|
|
subnet_dereference (&subnets, MDL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* So are shared networks. */
|
2009-04-07 19:55:52 +00:00
|
|
|
/* XXX: this doesn't work presently, but i'm ok just filtering
|
|
|
|
* it out of the noise (you get a bigger spike on the real leaks).
|
|
|
|
* It would be good to fix this, but it is not a "real bug," so not
|
|
|
|
* today. This hack is incomplete, it doesn't trim out sub-values.
|
|
|
|
*/
|
2001-06-27 00:31:20 +00:00
|
|
|
if (shared_networks) {
|
2009-04-07 19:55:52 +00:00
|
|
|
shared_network_dereference (&shared_networks, MDL);
|
|
|
|
/* This is the old method (tries to free memory twice, broken) */
|
|
|
|
} else if (0) {
|
2001-06-27 00:31:20 +00:00
|
|
|
shared_network_reference (&nn, shared_networks, MDL);
|
|
|
|
do {
|
|
|
|
if (nn) {
|
|
|
|
shared_network_reference (&nc, nn, MDL);
|
|
|
|
shared_network_dereference (&nn, MDL);
|
|
|
|
}
|
|
|
|
if (nc -> next) {
|
|
|
|
shared_network_reference (&nn, nc -> next, MDL);
|
|
|
|
shared_network_dereference (&nc -> next, MDL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* As are pools. */
|
|
|
|
if (nc -> pools) {
|
|
|
|
pool_reference (&pn, nc -> pools, MDL);
|
|
|
|
do {
|
2015-05-27 13:17:46 -07:00
|
|
|
LEASE_STRUCT_PTR lptr[RESERVED_LEASES+1];
|
2007-10-01 15:12:19 +00:00
|
|
|
|
2001-06-27 00:31:20 +00:00
|
|
|
if (pn) {
|
|
|
|
pool_reference (&pc, pn, MDL);
|
|
|
|
pool_dereference (&pn, MDL);
|
|
|
|
}
|
|
|
|
if (pc -> next) {
|
|
|
|
pool_reference (&pn, pc -> next, MDL);
|
|
|
|
pool_dereference (&pc -> next, MDL);
|
|
|
|
}
|
2007-10-01 15:12:19 +00:00
|
|
|
|
2001-06-27 00:31:20 +00:00
|
|
|
lptr [FREE_LEASES] = &pc -> free;
|
|
|
|
lptr [ACTIVE_LEASES] = &pc -> active;
|
|
|
|
lptr [EXPIRED_LEASES] = &pc -> expired;
|
|
|
|
lptr [ABANDONED_LEASES] = &pc -> abandoned;
|
|
|
|
lptr [BACKUP_LEASES] = &pc -> backup;
|
2006-04-27 17:26:42 +00:00
|
|
|
lptr [RESERVED_LEASES] = &pc->reserved;
|
2001-06-27 00:31:20 +00:00
|
|
|
|
|
|
|
/* As (sigh) are leases. */
|
2006-04-27 17:26:42 +00:00
|
|
|
for (i = FREE_LEASES ; i <= RESERVED_LEASES ; i++) {
|
2015-05-27 13:17:46 -07:00
|
|
|
if (LEASE_NOT_EMPTYP(lptr[i])) {
|
|
|
|
lease_reference(&ln, LEASE_GET_FIRSTP(lptr[i]), MDL);
|
2001-06-27 00:31:20 +00:00
|
|
|
do {
|
2015-05-27 13:17:46 -07:00
|
|
|
/* save a pointer to the current lease */
|
|
|
|
lease_reference (&lc, ln, MDL);
|
|
|
|
lease_dereference (&ln, MDL);
|
|
|
|
|
|
|
|
/* get the next lease if there is one */
|
|
|
|
ltemp = LEASE_GET_NEXTP(lptr[i], lc);
|
|
|
|
if (ltemp != NULL) {
|
|
|
|
lease_reference(&ln, ltemp, MDL);
|
2001-06-27 00:31:20 +00:00
|
|
|
}
|
2015-05-27 13:17:46 -07:00
|
|
|
|
|
|
|
/* remove the current lease from the queue */
|
|
|
|
LEASE_REMOVEP(lptr[i], lc);
|
|
|
|
|
2001-06-27 00:31:20 +00:00
|
|
|
if (lc -> billing_class)
|
|
|
|
class_dereference (&lc -> billing_class,
|
|
|
|
MDL);
|
|
|
|
if (lc -> state)
|
|
|
|
free_lease_state (lc -> state, MDL);
|
|
|
|
lc -> state = (struct lease_state *)0;
|
|
|
|
if (lc -> n_hw)
|
|
|
|
lease_dereference (&lc -> n_hw, MDL);
|
|
|
|
if (lc -> n_uid)
|
|
|
|
lease_dereference (&lc -> n_uid, MDL);
|
|
|
|
lease_dereference (&lc, MDL);
|
|
|
|
} while (ln);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pc -> group)
|
|
|
|
group_dereference (&pc -> group, MDL);
|
|
|
|
if (pc -> shared_network)
|
|
|
|
shared_network_dereference (&pc -> shared_network,
|
|
|
|
MDL);
|
|
|
|
pool_dereference (&pc, MDL);
|
|
|
|
} while (pn);
|
|
|
|
pool_dereference (&nc -> pools, MDL);
|
|
|
|
}
|
|
|
|
/* Because of a circular reference, we need to nuke this
|
|
|
|
manually. */
|
|
|
|
group_dereference (&nc -> group, MDL);
|
|
|
|
shared_network_dereference (&nc, MDL);
|
|
|
|
} while (nn);
|
|
|
|
shared_network_dereference (&shared_networks, MDL);
|
|
|
|
}
|
|
|
|
|
|
|
|
cancel_all_timeouts ();
|
|
|
|
relinquish_timeouts ();
|
2015-11-05 07:07:42 -05:00
|
|
|
#if defined(DELAYED_ACK)
|
2008-01-21 19:53:21 +00:00
|
|
|
relinquish_ackqueue();
|
2015-11-05 07:07:42 -05:00
|
|
|
#endif
|
2001-06-27 00:31:20 +00:00
|
|
|
trace_free_all ();
|
|
|
|
group_dereference (&root_group, MDL);
|
|
|
|
executable_statement_dereference (&default_classification_rules, MDL);
|
|
|
|
|
|
|
|
shutdown_state = shutdown_drop_omapi_connections;
|
|
|
|
omapi_io_state_foreach (dhcp_io_shutdown, 0);
|
|
|
|
shutdown_state = shutdown_listeners;
|
|
|
|
omapi_io_state_foreach (dhcp_io_shutdown, 0);
|
|
|
|
shutdown_state = shutdown_dhcp;
|
|
|
|
omapi_io_state_foreach (dhcp_io_shutdown, 0);
|
|
|
|
|
|
|
|
omapi_object_dereference ((omapi_object_t **)&icmp_state, MDL);
|
|
|
|
|
2005-03-17 20:15:29 +00:00
|
|
|
universe_free_hash_table (&universe_hash, MDL);
|
2001-06-27 00:31:20 +00:00
|
|
|
for (i = 0; i < universe_count; i++) {
|
2009-04-07 19:55:52 +00:00
|
|
|
#if 0
|
2001-06-27 00:31:20 +00:00
|
|
|
union {
|
|
|
|
const char *c;
|
|
|
|
char *s;
|
|
|
|
} foo;
|
2009-04-07 19:55:52 +00:00
|
|
|
#endif
|
2001-06-27 00:31:20 +00:00
|
|
|
if (universes [i]) {
|
2009-04-07 19:55:52 +00:00
|
|
|
if (universes[i]->name_hash)
|
|
|
|
option_name_free_hash_table(
|
|
|
|
&universes[i]->name_hash,
|
|
|
|
MDL);
|
|
|
|
if (universes[i]->code_hash)
|
|
|
|
option_code_free_hash_table(
|
|
|
|
&universes[i]->code_hash,
|
|
|
|
MDL);
|
2005-03-17 20:15:29 +00:00
|
|
|
#if 0
|
2001-06-27 00:31:20 +00:00
|
|
|
if (universes [i] -> name > (char *)&end) {
|
|
|
|
foo.c = universes [i] -> name;
|
|
|
|
dfree (foo.s, MDL);
|
|
|
|
}
|
|
|
|
if (universes [i] > (struct universe *)&end)
|
|
|
|
dfree (universes [i], MDL);
|
2005-03-17 20:15:29 +00:00
|
|
|
#endif
|
2001-06-27 00:31:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
dfree (universes, MDL);
|
|
|
|
|
|
|
|
relinquish_free_lease_states ();
|
|
|
|
relinquish_free_pairs ();
|
|
|
|
relinquish_free_expressions ();
|
|
|
|
relinquish_free_binding_values ();
|
|
|
|
relinquish_free_option_caches ();
|
|
|
|
relinquish_free_packets ();
|
2009-04-07 19:55:52 +00:00
|
|
|
#if defined(COMPACT_LEASES)
|
2001-06-27 00:31:20 +00:00
|
|
|
relinquish_lease_hunks ();
|
2009-04-07 19:55:52 +00:00
|
|
|
#endif
|
2001-06-27 00:31:20 +00:00
|
|
|
relinquish_hash_bucket_hunks ();
|
|
|
|
omapi_type_relinquish ();
|
|
|
|
}
|
2005-03-17 20:15:29 +00:00
|
|
|
#endif /* DEBUG_MEMORY_LEAKAGE_ON_EXIT */
|