Server-specific in-memory database support. */
/*
- * Copyright (c) 2011-2015 by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 2004-2009 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2019 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1996-2003 by Internet Software Consortium
*
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
+ * 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/.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Internet Systems Consortium, Inc.
- * 950 Charter Street
- * Redwood City, CA 94063
+ * PO Box 360
+ * Newmarket, NH 03857 USA
* <info@isc.org>
* https://www.isc.org/
*
/*
* We allow users to specify any option as a host identifier.
*
- * Any host is uniquely identified by the combination of
+ * Any host is uniquely identified by the combination of
* option type & option data.
*
- * We expect people will only use a few types of options as host
+ * We expect people will only use a few types of options as host
* identifier. Because of this, we store a list with an entry for
- * each option type. Each of these has a hash table, which contains
+ * each option type. Each of these has a hash table, which contains
* hash of the option data.
*
* For v6 we also include a relay count - this specifies which
int numclasseswritten;
-omapi_object_type_t *dhcp_type_host;
+extern omapi_object_type_t *dhcp_type_host;
isc_result_t enter_class(cd, dynamicp, commit)
struct class *cd;
class_dereference(&c, MDL);
return ISC_R_EXISTS;
}
-
+
/* Find the tail. */
for (c = collections -> classes;
c -> nic; c = c -> nic)
}
}
- /*
+ /*
* Remove the old entry, if one exists.
*/
if (host->client_identifier.data != NULL) {
data_string_forget(&host->client_identifier, MDL);
}
- /*
+ /*
* Set our new value.
*/
memset(&host->client_identifier, 0, sizeof(host->client_identifier));
/*
* And add to hash.
*/
- host_hash_add(host_uid_hash, host->client_identifier.data,
+ host_hash_add(host_uid_hash, host->client_identifier.data,
host->client_identifier.len, host, MDL);
}
esp = NULL;
if (executable_statement_foreach (hd->group->statements,
find_uid_statement, &esp, 0)) {
- (void) evaluate_option_cache (&hd->client_identifier,
- NULL, NULL, NULL, NULL, NULL,
+ struct data_string cid;
+ memset(&cid, 0, sizeof(cid));
+ (void) evaluate_option_cache (&cid,
+ NULL, NULL, NULL, NULL, NULL,
&global_scope,
esp->data.option, MDL);
+
+ 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));
+ }
}
/* If we got a client identifier, hash this entry by
log_fatal("No memory for host-identifier "
"option information.");
}
- option_reference(&h_id_info->option,
+ option_reference(&h_id_info->option,
hd->host_id_option, MDL);
- if (!host_new_hash(&h_id_info->values_hash,
+ if (!host_new_hash(&h_id_info->values_hash,
HOST_HASH_SIZE, MDL)) {
log_fatal("No memory for host-identifier "
"option hash.");
host_id_info = h_id_info;
}
- if (host_hash_lookup(&hp, h_id_info->values_hash,
+ if (host_hash_lookup(&hp, h_id_info->values_hash,
hd->host_id.data, hd->host_id.len, MDL)) {
- /*
- * If this option is already present, then add
+ /*
+ * If this option is already present, then add
* 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
- * fully understand how these are used.
- * Shouldn't there be multiple lists, or
+ * fully understand how these are used.
+ * Shouldn't there be multiple lists, or
* maybe we should just forbid duplicates?
*/
if (np == NULL) {
}
host_dereference(&hp, MDL);
} else {
- host_hash_add(h_id_info->values_hash,
+ host_hash_add(h_id_info->values_hash,
hd->host_id.data,
hd->host_id.len,
hd, MDL);
/* do the write first as we won't be leaving it in any data
structures, unlike the host objects */
-
+
if (commit) {
write_named_billing_class ((unsigned char *)cp->name, 0, cp);
if (!commit_leases ())
return ISC_R_IOERROR;
}
-
+
/*
* If this is a subclass remove it from the class's hash table
*/
if (cp->superclass) {
- class_hash_delete(cp->superclass->hash,
+ class_hash_delete(cp->superclass->hash,
(const char *)cp->hash_string.data,
cp->hash_string.len,
MDL);
}
int
-find_hosts_by_option(struct host_decl **hp,
+find_hosts_by_option(struct host_decl **hp,
struct packet *packet,
struct option_state *opt_state,
const char *file, int line) {
int found;
struct packet *relay_packet;
struct option_state *relay_state;
-
+
+#if defined(LDAP_CONFIGURATION)
+ if ((found = find_client_in_ldap (hp, packet, opt_state, file, line)))
+ return found;
+#endif
+
for (p = host_id_info; p != NULL; p = p->next) {
- relay_packet = packet;
+ relay_packet = packet;
relay_state = opt_state;
/* If this option block is for a relay (relays != 0)
relay_state = relay_packet->options;
}
- oc = lookup_option(p->option->universe,
+ oc = lookup_option(p->option->universe,
relay_state, p->option->code);
if (oc != NULL) {
memset(&data, 0, sizeof(data));
if (!evaluate_option_cache(&data, relay_packet, NULL,
NULL, relay_state, NULL,
- &global_scope, oc,
+ &global_scope, oc,
MDL)) {
log_error("Error evaluating option cache");
return 0;
}
-
- found = host_hash_lookup(hp, p->values_hash,
+
+ found = host_hash_lookup(hp, p->values_hash,
data.data, data.len,
file, line);
{
#if defined(COMPACT_LEASES)
struct lease *address_range;
- unsigned n, s;
+ unsigned s;
#endif
- unsigned min, max, i;
+ unsigned min, max, i, num_addrs;
char lowbuf [16], highbuf [16], netbuf [16];
struct shared_network *share = subnet -> shared_network;
struct lease *lt = (struct lease *)0;
min = host_addr (high, subnet -> netmask);
}
+ /* 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
+
/* Get a lease structure for each address in the range. */
#if defined (COMPACT_LEASES)
- n = max - min + 1;
- s = (n + 1) * sizeof (struct lease);
+ s = (num_addrs + 1) * sizeof (struct lease);
/* 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) ||
- ((s / sizeof (struct lease)) != (n + 1))) {
+ ((s / sizeof (struct lease)) != (num_addrs + 1))) {
strcpy (lowbuf, piaddr (low));
strcpy (highbuf, piaddr (high));
- parse_warn (cfile, "%s-%s is a far too large address range.",
+ parse_warn (cfile, "%s-%s is an overly large address range.",
lowbuf, highbuf);
log_fatal ("Memory overflow.");
}
- address_range = new_leases (n, MDL);
+ address_range = new_leases (num_addrs, MDL);
if (!address_range) {
strcpy (lowbuf, piaddr (low));
strcpy (highbuf, piaddr (high));
#endif
/* Fill out the lease structures with some minimal information. */
- for (i = 0; i < max - min + 1; i++) {
+ for (i = 0; i < num_addrs; i++) {
struct lease *lp = (struct lease *)0;
#if defined (COMPACT_LEASES)
omapi_object_initialize ((omapi_object_t *)&address_range [i],
struct subnet *rv;
for (rv = subnets; rv; rv = rv -> next_subnet) {
+#if defined(DHCP4o6)
+ if (addr.len != rv->netmask.len)
+ continue;
+#endif
if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
if (subnet_reference (sp, rv,
file, line) != ISC_R_SUCCESS)
struct subnet *rv;
for (rv = share -> subnets; rv; rv = rv -> next_sibling) {
+#if defined(DHCP4o6)
+ if (addr.len != rv->netmask.len)
+ continue;
+#endif
if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
if (subnet_reference (sp, rv,
file, line) != ISC_R_SUCCESS)
}
/* XXX: could speed up if everyone had a prefix length */
-int
-subnet_inner_than(const struct subnet *subnet,
+int
+subnet_inner_than(const struct subnet *subnet,
const struct subnet *scan,
int warnp) {
+#if defined(DHCP4o6)
+ if (subnet->net.len != scan->net.len)
+ return 0;
+#endif
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")];
}
subnet_reference (&subnets, subnet, MDL);
}
-
+
/* Enter a new shared network into the shared network list. */
void enter_shared_network (share)
}
shared_network_reference (&shared_networks, share, MDL);
}
-
+
void new_shared_network_interface (cfile, share, name)
struct parse *cfile;
struct shared_network *share;
isc_result_t status;
if (share -> interface) {
- parse_warn (cfile,
+ parse_warn (cfile,
"A subnet or shared network can't be connected %s",
"to two interfaces.");
return;
}
-
+
for (ip = interfaces; ip; ip = ip -> next)
if (!strcmp (ip -> name, name))
break;
int pimmediate;
int from_pool;
{
- struct lease *lp, **lq, *prev;
+ LEASE_STRUCT_PTR lq;
struct timeval tv;
#if defined (FAILOVER_PROTOCOL)
int do_pool_check = 0;
if (pimmediate && !commit)
return 0;
#endif
-
/* If there is no sample lease, just do the move. */
if (!lease)
goto just_move_it;
/* If the lease has been billed to a class, remove the billing. */
if (comp -> billing_class != lease -> billing_class) {
- if (comp -> billing_class)
- unbill_class (comp, comp -> billing_class);
+ if (comp->billing_class)
+ unbill_class(comp);
if (lease -> billing_class)
bill_class (comp, lease -> billing_class);
}
host_dereference (&comp -> host, MDL);
host_reference (&comp -> host, lease -> host, MDL);
comp -> hardware_addr = lease -> hardware_addr;
- comp -> flags = ((lease -> flags & ~PERSISTENT_FLAGS) |
- (comp -> flags & ~EPHEMERAL_FLAGS));
if (comp -> scope)
binding_scope_dereference (&comp -> scope, MDL);
if (lease -> scope) {
/* Remove the lease from its current place in its current
timer sequence. */
- /* XXX this is horrid. */
- prev = (struct lease *)0;
- for (lp = *lq; lp; lp = lp -> next) {
- if (lp == comp)
- break;
- prev = lp;
- }
+ LEASE_REMOVEP(lq, comp);
- 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);
- }
+ /* 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));
}
/* Make the state transition. */
/* 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.
-
+
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
executable_statement_dereference
(&lease->on_star.on_expiry, MDL);
}
-
+
/* No sense releasing a lease after it's expired. */
if (lease->on_star.on_release)
executable_statement_dereference
(&lease->on_star.on_release, MDL);
/* Get rid of client-specific bindings that are only
correct when the lease is active. */
- if (lease -> billing_class)
- unbill_class (lease, lease -> billing_class);
+ if (lease->billing_class)
+ unbill_class(lease);
if (lease -> agent_options)
option_chain_head_dereference (&lease -> agent_options,
MDL);
executable_statement_dereference
(&lease->on_star.on_release, MDL);
}
-
+
/* A released lease can't expire. */
if (lease->on_star.on_expiry)
executable_statement_dereference
/* Get rid of client-specific bindings that are only
correct when the lease is active. */
- if (lease -> billing_class)
- unbill_class (lease, lease -> billing_class);
+ if (lease->billing_class)
+ unbill_class(lease);
if (lease -> agent_options)
option_chain_head_dereference (&lease -> agent_options,
MDL);
struct lease *lease;
const char *message;
{
- struct lease *lt = (struct lease *)0;
+ struct lease *lt = NULL;
#if defined (NSUPDATE)
(void) ddns_removals(lease, NULL, NULL, ISC_FALSE);
#endif
- if (!lease_copy (<, lease, MDL))
+ if (!lease_copy(<, lease, MDL)) {
return;
+ }
- if (lt->scope)
+ if (lt->scope) {
binding_scope_dereference(<->scope, MDL);
+ }
- lt -> ends = cur_time; /* XXX */
- lt -> next_binding_state = FTS_ABANDONED;
+ /* 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;
+ }
- 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 = (unsigned char *)0;
- lt -> uid_len = 0;
- lt -> uid_max = 0;
- supersede_lease (lease, lt, 1, 1, 1, 0);
- lease_dereference (<, MDL);
+ 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);
}
#if 0
struct pool *pool;
struct lease *next = NULL;
struct lease *lease = NULL;
+ struct lease *ltemp = NULL;
#define FREE_LEASES 0
#define ACTIVE_LEASES 1
#define EXPIRED_LEASES 2
#define ABANDONED_LEASES 3
#define BACKUP_LEASES 4
#define RESERVED_LEASES 5
- struct lease **lptr[RESERVED_LEASES+1];
+ LEASE_STRUCT_PTR lptr[RESERVED_LEASES+1];
TIME next_expiry = MAX_TIME;
int i;
struct timeval tv;
for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
/* If there's nothing on the queue, skip it. */
- if (!*(lptr [i]))
+ if (!(LEASE_NOT_EMPTYP(lptr[i])))
continue;
#if defined (FAILOVER_PROTOCOL)
if (i == EXPIRED_LEASES)
continue;
}
-#endif
- lease_reference(&lease, *(lptr [i]), MDL);
+#endif
+ lease_reference(&lease, LEASE_GET_FIRSTP(lptr[i]), MDL);
while (lease) {
/* Remember the next lease in the list. */
if (next)
lease_dereference(&next, MDL);
- if (lease -> next)
- lease_reference(&next, lease->next, MDL);
+ ltemp = LEASE_GET_NEXTP(lptr[i], lease);
+ if (ltemp)
+ lease_reference(&next, ltemp, MDL);
/* If we've run out of things to expire on this list,
stop. */
if ((lease->hardware_addr.hlen == 1) &&
(lease->hardware_addr.hbuf[0] == HTYPE_INFINIBAND))
return;
-
+
/* If it's not in the hash, just add it. */
if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
lease -> hardware_addr.hlen, MDL))
struct lease *l;
struct shared_network *s;
struct pool *p;
- struct lease **lptr[RESERVED_LEASES+1];
+ LEASE_STRUCT_PTR lptr[RESERVED_LEASES+1];
int num_written = 0, i;
/* Write all the leases. */
lptr[RESERVED_LEASES] = &p->reserved;
for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
- for (l = *(lptr[i]); l; l = l->next) {
+ for (l = LEASE_GET_FIRSTP(lptr[i]);
+ l != NULL;
+ l = LEASE_GET_NEXTP(lptr[i], l)) {
#if !defined (DEBUG_DUMP_ALL_LEASES)
if (l->hardware_addr.hlen != 0 || l->uid_len != 0 ||
l->tsfp != 0 || l->binding_state != FTS_FREE)
}
}
- /* XXXJAB this number doesn't include subclasses... */
+ /* XXXJAB this number doesn't include subclasses... */
log_info ("Wrote %d class decls to leases file.",
numclasseswritten);
}
-
-
+
+
/* Write all the dynamically-created group declarations. */
if (group_name_hash) {
num_written = 0;
return (1);
}
+#if !defined (BINARY_LEASES)
+/* Unlink all the leases in the queue. */
+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) &&
+ (comp != last_insert_point) &&
+ (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
+
/* 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.
*/
int lease_enqueue (struct lease *comp)
{
- struct lease **lq, *prev, *lp;
- static struct lease **last_lq = NULL;
- static struct lease *last_insert_point = NULL;
+ LEASE_STRUCT_PTR lq;
/* No queue to put it on? */
if (!comp -> pool)
return 0;
}
- /* 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) &&
- (comp != last_insert_point) &&
- (last_insert_point->sort_time <= comp->sort_time)) {
- prev = last_insert_point;
- lp = prev->next;
- } else {
- prev = NULL;
- lp = *lq;
- }
+ LEASE_INSERTP(lq, comp);
- /* Insertion sort the lease onto the appropriate queue. */
- for (; lp ; 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 1;
}
* 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. */
- if ((lease->binding_state == FTS_BACKUP) &&
+ if ((lease->binding_state == FTS_BACKUP) &&
(lease->pool->failover_peer == NULL)) {
#else
/* We aren't compiled for failover, so just move to FTS_FREE */
- if (lease->binding_state == FTS_BACKUP) {
+ if (lease->binding_state == FTS_BACKUP) {
#endif
lease->binding_state = FTS_FREE;
lease->next_binding_state = FTS_FREE;
lease->rewind_binding_state = FTS_FREE;
}
-
+
/* 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
struct pool *p;
int i;
struct lease *l;
- struct lease **lptr[RESERVED_LEASES+1];
+ LEASE_STRUCT_PTR lptr[RESERVED_LEASES+1];
/* Indicate that we are in the startup phase */
server_starting = SS_NOSYNC | SS_QFOLLOW;
+#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
+
/* First, go over the hash list and actually put all the leases
on the appropriate lists. */
lease_ip_hash_foreach(lease_ip_addr_hash, lease_instantiate);
lptr [RESERVED_LEASES] = &p->reserved;
for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
- for (l = *(lptr [i]); l; l = l -> next) {
+ for (l = LEASE_GET_FIRSTP(lptr[i]);
+ l != NULL;
+ l = LEASE_GET_NEXTP(lptr[i], l)) {
p -> lease_count++;
if (l -> ends <= cur_time) {
if (l->binding_state == FTS_FREE) {
struct shared_network *s;
struct subnet *n;
struct pool *p;
- struct lease **lptr[RESERVED_LEASES+1];
+ LEASE_STRUCT_PTR lptr[RESERVED_LEASES+1];
int i;
log_info ("Subnets:");
lptr [RESERVED_LEASES] = &p->reserved;
for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
- for (l = *(lptr [i]); l; l = l -> next) {
+ for (l = LEASE_GET_FIRSTP(lptr[i]);
+ l != NULL;
+ l = LEASE_GET_NEXTP(lptr[i], l)) {
print_lease (l);
}
}
struct shared_network *nc = (struct shared_network *)0,
*nn = (struct shared_network *)0;
struct pool *pc = (struct pool *)0, *pn = (struct pool *)0;
- struct lease *lc = (struct lease *)0, *ln = (struct lease *)0;
+ struct lease *lc = NULL, *ln = NULL, *ltemp = NULL;
struct interface_info *ic = (struct interface_info *)0,
*in = (struct interface_info *)0;
struct class *cc = (struct class *)0, *cn = (struct class *)0;
if (nc -> pools) {
pool_reference (&pn, nc -> pools, MDL);
do {
- struct lease **lptr[RESERVED_LEASES+1];
+ LEASE_STRUCT_PTR lptr[RESERVED_LEASES+1];
if (pn) {
pool_reference (&pc, pn, MDL);
/* As (sigh) are leases. */
for (i = FREE_LEASES ; i <= RESERVED_LEASES ; i++) {
- if (*lptr [i]) {
- lease_reference (&ln, *lptr [i], MDL);
+ if (LEASE_NOT_EMPTYP(lptr[i])) {
+ lease_reference(&ln, LEASE_GET_FIRSTP(lptr[i]), MDL);
do {
- if (ln) {
- lease_reference (&lc, ln, MDL);
- lease_dereference (&ln, MDL);
- }
- if (lc -> next) {
- lease_reference (&ln, lc -> next, MDL);
- lease_dereference (&lc -> next, MDL);
+ /* 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);
}
+
+ /* remove the current lease from the queue */
+ LEASE_REMOVEP(lptr[i], lc);
+
if (lc -> billing_class)
class_dereference (&lc -> billing_class,
MDL);
lease_dereference (&lc -> n_uid, MDL);
lease_dereference (&lc, MDL);
} while (ln);
- lease_dereference (lptr [i], MDL);
}
}
if (pc -> group)
cancel_all_timeouts ();
relinquish_timeouts ();
+#if defined(DELAYED_ACK)
relinquish_ackqueue();
+#endif
trace_free_all ();
group_dereference (&root_group, MDL);
executable_statement_dereference (&default_classification_rules, MDL);