1995-11-29 07:40:04 +00:00
|
|
|
/* memory.c
|
|
|
|
|
|
|
|
Memory-resident database... */
|
|
|
|
|
|
|
|
/*
|
1996-02-07 22:43:54 +00:00
|
|
|
* Copyright (c) 1995, 1996 The Internet Software Consortium.
|
|
|
|
* All rights reserved.
|
1995-11-29 07:40:04 +00:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
*
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. Neither the name of The Internet Software Consortium nor the names
|
|
|
|
* of its contributors may be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
|
|
|
|
* CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
|
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
* DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
|
|
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
|
|
|
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
|
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
|
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
* This software has been written for the Internet Software Consortium
|
|
|
|
* by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
|
|
|
|
* Enterprises. To learn more about the Internet Software Consortium,
|
|
|
|
* see ``http://www.vix.com/isc''. To learn more about Vixie
|
|
|
|
* Enterprises, see ``http://www.vix.com''.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef lint
|
|
|
|
static char copyright[] =
|
1996-03-02 05:13:36 +00:00
|
|
|
"@(#) Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
|
1995-11-29 07:40:04 +00:00
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
#include "dhcpd.h"
|
|
|
|
|
1996-02-21 12:11:09 +00:00
|
|
|
static struct subnet *subnets;
|
1996-05-22 07:40:52 +00:00
|
|
|
static struct shared_network *shared_networks;
|
|
|
|
static struct hash_table *host_hw_addr_hash;
|
|
|
|
static struct hash_table *host_uid_hash;
|
1995-11-29 07:40:04 +00:00
|
|
|
static struct hash_table *lease_uid_hash;
|
|
|
|
static struct hash_table *lease_ip_addr_hash;
|
|
|
|
static struct hash_table *lease_hw_addr_hash;
|
|
|
|
static struct lease *dangling_leases;
|
|
|
|
|
1996-02-29 18:28:43 +00:00
|
|
|
static struct hash_table *vendor_class_hash;
|
|
|
|
static struct hash_table *user_class_hash;
|
|
|
|
|
1995-11-29 07:40:04 +00:00
|
|
|
void enter_host (hd)
|
|
|
|
struct host_decl *hd;
|
|
|
|
{
|
1996-05-22 07:40:52 +00:00
|
|
|
struct host_decl *hp = (struct host_decl *)0;
|
|
|
|
struct host_decl *np = (struct host_decl *)0;
|
|
|
|
|
|
|
|
hd -> n_ipaddr = (struct host_decl *)0;
|
|
|
|
|
|
|
|
if (hd -> interface.hlen) {
|
|
|
|
if (!host_hw_addr_hash)
|
|
|
|
host_hw_addr_hash = new_hash ();
|
|
|
|
else
|
|
|
|
hp = (struct host_decl *)
|
|
|
|
hash_lookup (host_hw_addr_hash,
|
|
|
|
hd -> interface.haddr,
|
|
|
|
hd -> interface.hlen);
|
|
|
|
|
|
|
|
if (!hp)
|
|
|
|
add_hash (host_hw_addr_hash,
|
|
|
|
hd -> interface.haddr, hd -> interface.hlen,
|
|
|
|
(unsigned char *)hd);
|
|
|
|
}
|
|
|
|
/* If there's already a host declaration for this hardware
|
|
|
|
address, add this one to the end of the list. Otherwise,
|
|
|
|
add it to the hash table. */
|
|
|
|
|
|
|
|
if (hp) {
|
|
|
|
for (np = hp; np -> n_ipaddr; np = np -> n_ipaddr)
|
|
|
|
;
|
|
|
|
np -> n_ipaddr = hd;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hd -> options [DHO_DHCP_CLIENT_IDENTIFIER]) {
|
|
|
|
if (!tree_evaluate (hd -> options
|
|
|
|
[DHO_DHCP_CLIENT_IDENTIFIER]))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!host_uid_hash)
|
|
|
|
host_uid_hash = new_hash ();
|
|
|
|
else
|
|
|
|
hp = (struct host_decl *) hash_lookup
|
|
|
|
(host_uid_hash,
|
|
|
|
hd -> options
|
|
|
|
[DHO_DHCP_CLIENT_IDENTIFIER] -> value,
|
|
|
|
hd -> options
|
|
|
|
[DHO_DHCP_CLIENT_IDENTIFIER] -> len);
|
|
|
|
|
|
|
|
/* 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 (hp) {
|
|
|
|
/* Don't link it in twice... */
|
|
|
|
if (!np) {
|
|
|
|
for (np = hp; np -> n_ipaddr;
|
|
|
|
np = np -> n_ipaddr)
|
|
|
|
;
|
|
|
|
np -> n_ipaddr = hd;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
add_hash (host_uid_hash,
|
|
|
|
hd -> options
|
|
|
|
[DHO_DHCP_CLIENT_IDENTIFIER] -> value,
|
|
|
|
hd -> options
|
|
|
|
[DHO_DHCP_CLIENT_IDENTIFIER] -> len,
|
|
|
|
(unsigned char *)hd);
|
|
|
|
}
|
|
|
|
}
|
1995-11-29 07:40:04 +00:00
|
|
|
}
|
|
|
|
|
1996-05-22 07:40:52 +00:00
|
|
|
struct host_decl *find_hosts_by_haddr (htype, haddr, hlen)
|
|
|
|
int htype;
|
|
|
|
unsigned char *haddr;
|
|
|
|
int hlen;
|
1995-11-29 07:40:04 +00:00
|
|
|
{
|
|
|
|
struct host_decl *foo;
|
|
|
|
|
1996-05-22 07:40:52 +00:00
|
|
|
foo = (struct host_decl *)hash_lookup (host_hw_addr_hash,
|
|
|
|
haddr, hlen);
|
|
|
|
return foo;
|
1995-11-29 07:40:04 +00:00
|
|
|
}
|
|
|
|
|
1996-05-22 07:40:52 +00:00
|
|
|
struct host_decl *find_hosts_by_uid (data, len)
|
|
|
|
unsigned char *data;
|
|
|
|
int len;
|
1995-11-29 07:40:04 +00:00
|
|
|
{
|
|
|
|
struct host_decl *foo;
|
|
|
|
|
1996-05-22 07:40:52 +00:00
|
|
|
foo = (struct host_decl *)hash_lookup (host_uid_hash, data, len);
|
|
|
|
return foo;
|
1995-11-29 07:40:04 +00:00
|
|
|
}
|
|
|
|
|
1996-05-22 07:40:52 +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. */
|
|
|
|
|
|
|
|
struct subnet *find_host_for_network (host, addr, share)
|
|
|
|
struct host_decl **host;
|
|
|
|
struct iaddr *addr;
|
|
|
|
struct shared_network *share;
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct subnet *subnet;
|
|
|
|
struct iaddr ip_address;
|
|
|
|
struct host_decl *hp;
|
|
|
|
|
|
|
|
for (hp = *host; hp; hp = hp -> n_ipaddr) {
|
|
|
|
if (!hp -> fixed_addr || !tree_evaluate (hp -> fixed_addr))
|
|
|
|
continue;
|
|
|
|
for (i = 0; i < hp -> fixed_addr -> len; i += 4) {
|
|
|
|
ip_address.len = 4;
|
|
|
|
memcpy (ip_address.iabuf,
|
|
|
|
hp -> fixed_addr -> value + i, 4);
|
|
|
|
subnet = find_grouped_subnet (share, ip_address);
|
|
|
|
if (subnet) {
|
|
|
|
*addr = ip_address;
|
|
|
|
*host = hp;
|
|
|
|
return subnet;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (struct subnet *)0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void new_address_range (low, high, subnet, dynamic)
|
1996-02-21 15:16:18 +00:00
|
|
|
struct iaddr low, high;
|
|
|
|
struct subnet *subnet;
|
1996-05-22 07:40:52 +00:00
|
|
|
int dynamic;
|
1995-11-29 07:40:04 +00:00
|
|
|
{
|
|
|
|
struct lease *address_range, *lp, *plp;
|
1996-02-06 20:25:56 +00:00
|
|
|
struct iaddr net;
|
1996-02-21 12:11:09 +00:00
|
|
|
int min, max, i;
|
1995-11-29 07:40:04 +00:00
|
|
|
char lowbuf [16], highbuf [16], netbuf [16];
|
1996-05-22 07:40:52 +00:00
|
|
|
struct shared_network *share = subnet -> shared_network;
|
|
|
|
|
|
|
|
/* All subnets should have attached shared network structures. */
|
|
|
|
if (!share) {
|
|
|
|
strcpy (netbuf, piaddr (subnet -> net));
|
|
|
|
error ("No shared network for network %s (%s)",
|
|
|
|
netbuf, piaddr (subnet -> netmask));
|
|
|
|
}
|
1995-11-29 07:40:04 +00:00
|
|
|
|
|
|
|
/* Initialize the hash table if it hasn't been done yet. */
|
|
|
|
if (!lease_uid_hash)
|
|
|
|
lease_uid_hash = new_hash ();
|
|
|
|
if (!lease_ip_addr_hash)
|
|
|
|
lease_ip_addr_hash = new_hash ();
|
|
|
|
if (!lease_hw_addr_hash)
|
|
|
|
lease_hw_addr_hash = new_hash ();
|
|
|
|
|
|
|
|
/* Make sure that high and low addresses are in same subnet. */
|
1996-02-21 15:16:18 +00:00
|
|
|
net = subnet_number (low, subnet -> netmask);
|
|
|
|
if (!addr_eq (net, subnet_number (high, subnet -> netmask))) {
|
1996-02-06 20:25:56 +00:00
|
|
|
strcpy (lowbuf, piaddr (low));
|
|
|
|
strcpy (highbuf, piaddr (high));
|
1996-02-21 15:16:18 +00:00
|
|
|
strcpy (netbuf, piaddr (subnet -> netmask));
|
1995-11-29 07:40:04 +00:00
|
|
|
error ("Address range %s to %s, netmask %s spans %s!",
|
|
|
|
lowbuf, highbuf, netbuf, "multiple subnets");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the high and low host addresses... */
|
1996-02-21 15:16:18 +00:00
|
|
|
max = host_addr (high, subnet -> netmask);
|
|
|
|
min = host_addr (low, subnet -> netmask);
|
1995-11-29 07:40:04 +00:00
|
|
|
|
|
|
|
/* Allow range to be specified high-to-low as well as low-to-high. */
|
1996-02-21 12:11:09 +00:00
|
|
|
if (min > max) {
|
|
|
|
max = min;
|
1996-02-21 15:16:18 +00:00
|
|
|
min = host_addr (high, subnet -> netmask);
|
1995-11-29 07:40:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Get a lease structure for each address in the range. */
|
1996-02-21 12:11:09 +00:00
|
|
|
address_range = new_leases (max - min + 1, "new_address_range");
|
1995-11-29 07:40:04 +00:00
|
|
|
if (!address_range) {
|
1996-02-06 20:25:56 +00:00
|
|
|
strcpy (lowbuf, piaddr (low));
|
|
|
|
strcpy (highbuf, piaddr (high));
|
1995-11-29 07:40:04 +00:00
|
|
|
error ("No memory for address range %s-%s.", lowbuf, highbuf);
|
|
|
|
}
|
1996-02-21 12:11:09 +00:00
|
|
|
memset (address_range, 0, (sizeof *address_range) * (max - min + 1));
|
|
|
|
|
|
|
|
/* Fill in the last lease if it hasn't been already... */
|
1996-05-22 07:40:52 +00:00
|
|
|
if (!share -> last_lease) {
|
|
|
|
share -> last_lease = &address_range [0];
|
1996-02-21 15:16:18 +00:00
|
|
|
}
|
1995-11-29 07:40:04 +00:00
|
|
|
|
|
|
|
/* Fill out the lease structures with some minimal information. */
|
1996-02-21 12:11:09 +00:00
|
|
|
for (i = 0; i < max - min + 1; i++) {
|
1996-02-06 20:25:56 +00:00
|
|
|
address_range [i].ip_addr =
|
1996-02-21 12:11:09 +00:00
|
|
|
ip_addr (subnet -> net, subnet -> netmask, i + min);
|
1995-11-29 07:40:04 +00:00
|
|
|
address_range [i].starts =
|
|
|
|
address_range [i].timestamp = MIN_TIME;
|
|
|
|
address_range [i].ends = MIN_TIME;
|
1996-05-22 07:40:52 +00:00
|
|
|
address_range [i].subnet = subnet;
|
|
|
|
address_range [i].shared_network = share;
|
|
|
|
address_range [i].flags = dynamic ? DYNAMIC_BOOTP_OK : 0;
|
1995-11-29 07:40:04 +00:00
|
|
|
|
|
|
|
/* Link this entry into the list. */
|
1996-05-22 07:40:52 +00:00
|
|
|
address_range [i].next = share -> leases;
|
1995-11-29 07:40:04 +00:00
|
|
|
address_range [i].prev = (struct lease *)0;
|
1996-05-22 07:40:52 +00:00
|
|
|
share -> leases = &address_range [i];
|
1996-02-06 20:25:56 +00:00
|
|
|
if (address_range [i].next)
|
1996-05-22 07:40:52 +00:00
|
|
|
address_range [i].next -> prev = share -> leases;
|
1995-11-29 07:40:04 +00:00
|
|
|
add_hash (lease_ip_addr_hash,
|
1996-03-02 05:13:36 +00:00
|
|
|
address_range [i].ip_addr.iabuf,
|
|
|
|
address_range [i].ip_addr.len,
|
1995-11-29 07:40:04 +00:00
|
|
|
(unsigned char *)&address_range [i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Find out if any dangling leases are in range... */
|
|
|
|
plp = (struct lease *)0;
|
|
|
|
for (lp = dangling_leases; lp; lp = lp -> next) {
|
1996-02-06 20:25:56 +00:00
|
|
|
struct iaddr lnet;
|
1995-11-29 07:40:04 +00:00
|
|
|
int lhost;
|
|
|
|
|
1996-02-06 20:25:56 +00:00
|
|
|
lnet = subnet_number (lp -> ip_addr, subnet -> netmask);
|
|
|
|
lhost = host_addr (lp -> ip_addr, subnet -> netmask);
|
1995-11-29 07:40:04 +00:00
|
|
|
|
|
|
|
/* If it's in range, fill in the real lease structure with
|
|
|
|
the dangling lease's values, and remove the lease from
|
|
|
|
the list of dangling leases. */
|
1996-02-06 20:25:56 +00:00
|
|
|
if (addr_eq (lnet, subnet -> net) &&
|
1995-11-29 07:40:04 +00:00
|
|
|
lhost >= i && lhost <= max) {
|
|
|
|
if (plp) {
|
|
|
|
plp -> next = lp -> next;
|
|
|
|
} else {
|
|
|
|
dangling_leases = lp -> next;
|
|
|
|
}
|
|
|
|
lp -> next = (struct lease *)0;
|
1996-03-02 05:13:36 +00:00
|
|
|
supersede_lease (&address_range [lhost - i], lp, 0);
|
1995-11-29 07:40:04 +00:00
|
|
|
free_lease (lp, "new_address_range");
|
|
|
|
} else
|
|
|
|
plp = lp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-02-21 12:11:09 +00:00
|
|
|
struct subnet *find_subnet (addr)
|
|
|
|
struct iaddr addr;
|
1995-11-29 07:40:04 +00:00
|
|
|
{
|
|
|
|
struct subnet *rv;
|
|
|
|
|
1996-05-22 07:40:52 +00:00
|
|
|
for (rv = subnets; rv; rv = rv -> next_subnet) {
|
|
|
|
if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net))
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
return (struct subnet *)0;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct subnet *find_grouped_subnet (share, addr)
|
|
|
|
struct shared_network *share;
|
|
|
|
struct iaddr addr;
|
|
|
|
{
|
|
|
|
struct subnet *rv;
|
|
|
|
|
|
|
|
for (rv = share -> subnets; rv; rv = rv -> next_sibling) {
|
1996-02-21 12:11:09 +00:00
|
|
|
if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net))
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
return (struct subnet *)0;
|
1995-11-29 07:40:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Enter a new subnet into the subnet hash. */
|
|
|
|
|
|
|
|
void enter_subnet (subnet)
|
|
|
|
struct subnet *subnet;
|
|
|
|
{
|
1996-02-21 12:11:09 +00:00
|
|
|
/* XXX Sort the nets into a balanced tree to make searching quicker. */
|
1996-05-22 07:40:52 +00:00
|
|
|
subnet -> next_subnet = subnets;
|
1996-02-21 12:11:09 +00:00
|
|
|
subnets = subnet;
|
1995-11-29 07:40:04 +00:00
|
|
|
}
|
|
|
|
|
1996-05-22 07:40:52 +00:00
|
|
|
/* Enter a new subnet into the subnet hash. */
|
|
|
|
|
|
|
|
void enter_shared_network (share)
|
|
|
|
struct shared_network *share;
|
|
|
|
{
|
|
|
|
/* XXX Sort the nets into a balanced tree to make searching quicker. */
|
|
|
|
share -> next = shared_networks;
|
|
|
|
shared_networks = share;
|
|
|
|
}
|
|
|
|
|
1995-11-29 07:40:04 +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;
|
|
|
|
{
|
|
|
|
struct lease *comp = find_lease_by_ip_addr (lease -> ip_addr);
|
|
|
|
|
|
|
|
/* If we don't have a place for this lease yet, save it for
|
|
|
|
later. */
|
|
|
|
if (!comp) {
|
|
|
|
comp = new_lease ("enter_lease");
|
|
|
|
if (!comp) {
|
|
|
|
error ("No memory for lease %s\n",
|
1996-02-06 20:25:56 +00:00
|
|
|
piaddr (lease -> ip_addr));
|
1995-11-29 07:40:04 +00:00
|
|
|
}
|
|
|
|
*comp = *lease;
|
|
|
|
lease -> next = dangling_leases;
|
|
|
|
lease -> prev = (struct lease *)0;
|
|
|
|
dangling_leases = lease;
|
|
|
|
} else {
|
1996-03-02 05:13:36 +00:00
|
|
|
supersede_lease (comp, lease, 0);
|
1995-11-29 07:40:04 +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. */
|
|
|
|
|
1996-03-02 05:13:36 +00:00
|
|
|
int supersede_lease (comp, lease, commit)
|
1995-11-29 07:40:04 +00:00
|
|
|
struct lease *comp, *lease;
|
1996-03-02 05:13:36 +00:00
|
|
|
int commit;
|
1995-11-29 07:40:04 +00:00
|
|
|
{
|
|
|
|
int enter_uid = 0;
|
|
|
|
int enter_hwaddr = 0;
|
|
|
|
struct lease *lp;
|
|
|
|
|
|
|
|
/* 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
|
1996-06-27 19:09:51 +00:00
|
|
|
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. */
|
|
|
|
|
1995-11-29 07:40:04 +00:00
|
|
|
if (comp -> ends > cur_time &&
|
1996-06-27 19:09:51 +00:00
|
|
|
((comp -> uid && (lease -> uid ||
|
|
|
|
!(lease -> flags & DYNAMIC_BOOTP_OK)) &&
|
1995-11-29 07:40:04 +00:00
|
|
|
(comp -> uid_len != lease -> uid_len ||
|
|
|
|
memcmp (comp -> uid, lease -> uid, comp -> uid_len))) ||
|
|
|
|
(!comp -> uid &&
|
|
|
|
((comp -> hardware_addr.htype !=
|
|
|
|
lease -> hardware_addr.htype) ||
|
|
|
|
(comp -> hardware_addr.hlen !=
|
|
|
|
lease -> hardware_addr.hlen) ||
|
|
|
|
memcmp (comp -> hardware_addr.haddr,
|
|
|
|
lease -> hardware_addr.haddr,
|
|
|
|
comp -> hardware_addr.hlen))))) {
|
|
|
|
warn ("Lease conflict at %s",
|
1996-02-06 20:25:56 +00:00
|
|
|
piaddr (comp -> ip_addr));
|
1996-06-11 08:14:28 +00:00
|
|
|
return 0;
|
1995-11-29 07:40:04 +00:00
|
|
|
} else {
|
|
|
|
/* If there's a Unique ID, dissociate it from the hash
|
|
|
|
table if necessary, and always free it. */
|
|
|
|
if (comp -> uid) {
|
1996-06-12 04:05:23 +00:00
|
|
|
if (comp -> uid != lease -> uid) {
|
|
|
|
if (comp -> uid_len != lease -> uid_len ||
|
|
|
|
memcmp (comp -> uid, lease -> uid,
|
|
|
|
comp -> uid_len)) {
|
|
|
|
delete_hash_entry (lease_uid_hash,
|
|
|
|
comp -> uid,
|
|
|
|
comp -> uid_len);
|
|
|
|
enter_uid = 1;
|
|
|
|
}
|
|
|
|
free (comp -> uid);
|
1995-11-29 07:40:04 +00:00
|
|
|
}
|
1996-02-21 12:11:09 +00:00
|
|
|
} else
|
|
|
|
enter_uid = 1;
|
|
|
|
|
1995-11-29 07:40:04 +00:00
|
|
|
if (comp -> hardware_addr.htype &&
|
1996-02-06 20:25:56 +00:00
|
|
|
((comp -> hardware_addr.hlen !=
|
|
|
|
lease -> hardware_addr.hlen) ||
|
|
|
|
(comp -> hardware_addr.htype !=
|
|
|
|
lease -> hardware_addr.htype) ||
|
|
|
|
memcmp (comp -> hardware_addr.haddr,
|
|
|
|
lease -> hardware_addr.haddr,
|
|
|
|
comp -> hardware_addr.hlen))) {
|
1995-11-29 07:40:04 +00:00
|
|
|
delete_hash_entry (lease_hw_addr_hash,
|
|
|
|
comp -> hardware_addr.haddr,
|
|
|
|
comp -> hardware_addr.hlen);
|
|
|
|
enter_hwaddr = 1;
|
1996-02-21 12:11:09 +00:00
|
|
|
} else if (!comp -> hardware_addr.htype)
|
|
|
|
enter_hwaddr = 1;
|
1995-11-29 07:40:04 +00:00
|
|
|
|
|
|
|
/* Copy the data files, but not the linkages. */
|
|
|
|
comp -> starts = lease -> starts;
|
1996-02-26 09:30:23 +00:00
|
|
|
comp -> offered_expiry = lease -> offered_expiry;
|
1995-11-29 07:40:04 +00:00
|
|
|
comp -> timestamp = lease -> timestamp;
|
|
|
|
comp -> uid = lease -> uid;
|
|
|
|
comp -> uid_len = lease -> uid_len;
|
|
|
|
comp -> host = lease -> host;
|
|
|
|
comp -> hardware_addr = lease -> hardware_addr;
|
|
|
|
comp -> state = lease -> state;
|
1996-05-22 07:40:52 +00:00
|
|
|
comp -> flags = ((lease -> flags & ~PERSISTENT_FLAGS) |
|
|
|
|
(comp -> flags & ~EPHEMERAL_FLAGS));
|
1995-11-29 07:40:04 +00:00
|
|
|
|
|
|
|
/* Record the lease in the uid hash if necessary. */
|
|
|
|
if (enter_uid && lease -> uid) {
|
1996-02-21 12:11:09 +00:00
|
|
|
add_hash (lease_uid_hash, comp -> uid,
|
|
|
|
comp -> uid_len, (unsigned char *)comp);
|
1995-11-29 07:40:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Record it in the hardware address hash if necessary. */
|
|
|
|
if (enter_hwaddr && lease -> hardware_addr.htype) {
|
|
|
|
add_hash (lease_hw_addr_hash,
|
1996-02-21 12:11:09 +00:00
|
|
|
comp -> hardware_addr.haddr,
|
|
|
|
comp -> hardware_addr.hlen,
|
|
|
|
(unsigned char *)comp);
|
1995-11-29 07:40:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Remove the lease from its current place in the list. */
|
|
|
|
if (comp -> prev) {
|
|
|
|
comp -> prev -> next = comp -> next;
|
|
|
|
} else {
|
1996-05-22 07:40:52 +00:00
|
|
|
comp -> shared_network -> leases = comp -> next;
|
1995-11-29 07:40:04 +00:00
|
|
|
}
|
|
|
|
if (comp -> next) {
|
|
|
|
comp -> next -> prev = comp -> prev;
|
|
|
|
}
|
1996-05-22 07:40:52 +00:00
|
|
|
if (comp -> shared_network -> last_lease == comp) {
|
|
|
|
comp -> shared_network -> last_lease = comp -> prev;
|
1996-02-21 12:11:09 +00:00
|
|
|
}
|
1995-11-29 07:40:04 +00:00
|
|
|
|
|
|
|
/* Find the last insertion point... */
|
1996-05-22 07:40:52 +00:00
|
|
|
if (comp == comp -> shared_network -> insertion_point ||
|
|
|
|
!comp -> shared_network -> insertion_point) {
|
|
|
|
lp = comp -> shared_network -> leases;
|
1995-11-29 07:40:04 +00:00
|
|
|
} else {
|
1996-05-22 07:40:52 +00:00
|
|
|
lp = comp -> shared_network -> insertion_point;
|
1995-11-29 07:40:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!lp) {
|
|
|
|
/* Nothing on the list yet? Just make comp the
|
|
|
|
head of the list. */
|
1996-05-22 07:40:52 +00:00
|
|
|
comp -> shared_network -> leases = comp;
|
|
|
|
comp -> shared_network -> last_lease = comp;
|
1996-02-21 15:16:18 +00:00
|
|
|
} else if (lp -> ends > lease -> ends) {
|
1995-11-29 07:40:04 +00:00
|
|
|
/* Skip down the list until we run out of list
|
|
|
|
or find a place for comp. */
|
1996-02-21 15:16:18 +00:00
|
|
|
while (lp -> next && lp -> ends > lease -> ends) {
|
1995-11-29 07:40:04 +00:00
|
|
|
lp = lp -> next;
|
|
|
|
}
|
1996-02-21 15:16:18 +00:00
|
|
|
if (lp -> ends > lease -> ends) {
|
1995-11-29 07:40:04 +00:00
|
|
|
/* If we ran out of list, put comp
|
|
|
|
at the end. */
|
|
|
|
lp -> next = comp;
|
|
|
|
comp -> prev = lp;
|
|
|
|
comp -> next = (struct lease *)0;
|
1996-05-22 07:40:52 +00:00
|
|
|
comp -> shared_network -> last_lease = comp;
|
1995-11-29 07:40:04 +00:00
|
|
|
} else {
|
|
|
|
/* If we didn't, put it between lp and
|
|
|
|
the previous item on the list. */
|
1996-02-21 15:16:18 +00:00
|
|
|
if ((comp -> prev = lp -> prev))
|
|
|
|
comp -> prev -> next = comp;
|
1995-11-29 07:40:04 +00:00
|
|
|
comp -> next = lp;
|
|
|
|
lp -> prev = comp;
|
|
|
|
}
|
|
|
|
} else {
|
1996-02-21 12:11:09 +00:00
|
|
|
/* Skip up the list until we run out of list
|
1995-11-29 07:40:04 +00:00
|
|
|
or find a place for comp. */
|
1996-02-21 15:16:18 +00:00
|
|
|
while (lp -> prev && lp -> ends < lease -> ends) {
|
1995-11-29 07:40:04 +00:00
|
|
|
lp = lp -> prev;
|
|
|
|
}
|
1996-02-21 15:16:18 +00:00
|
|
|
if (lp -> ends < lease -> ends) {
|
1995-11-29 07:40:04 +00:00
|
|
|
/* If we ran out of list, put comp
|
|
|
|
at the beginning. */
|
|
|
|
lp -> prev = comp;
|
|
|
|
comp -> next = lp;
|
|
|
|
comp -> prev = (struct lease *)0;
|
1996-05-22 07:40:52 +00:00
|
|
|
comp -> shared_network -> leases = comp;
|
1995-11-29 07:40:04 +00:00
|
|
|
} else {
|
|
|
|
/* If we didn't, put it between lp and
|
|
|
|
the next item on the list. */
|
1996-02-21 15:16:18 +00:00
|
|
|
if ((comp -> next = lp -> next))
|
|
|
|
comp -> next -> prev = comp;
|
1995-11-29 07:40:04 +00:00
|
|
|
comp -> prev = lp;
|
|
|
|
lp -> next = comp;
|
|
|
|
}
|
|
|
|
}
|
1996-05-22 07:40:52 +00:00
|
|
|
comp -> shared_network -> insertion_point = comp;
|
1996-02-21 15:16:18 +00:00
|
|
|
comp -> ends = lease -> ends;
|
1995-11-29 07:40:04 +00:00
|
|
|
}
|
1996-03-02 05:13:36 +00:00
|
|
|
|
|
|
|
/* Return zero if we didn't commit the lease to permanent storage;
|
|
|
|
nonzero if we did. */
|
|
|
|
return commit && write_lease (comp) && commit_leases ();
|
1995-11-29 07:40:04 +00:00
|
|
|
}
|
1996-02-06 20:25:56 +00:00
|
|
|
|
1996-02-21 12:11:09 +00:00
|
|
|
/* Release the specified lease and re-hash it as appropriate. */
|
|
|
|
|
|
|
|
void release_lease (lease)
|
|
|
|
struct lease *lease;
|
|
|
|
{
|
|
|
|
struct lease lt;
|
|
|
|
|
|
|
|
lt = *lease;
|
1996-02-21 15:16:18 +00:00
|
|
|
lt.ends = cur_time;
|
1996-03-02 05:13:36 +00:00
|
|
|
supersede_lease (lease, <, 1);
|
1996-02-21 12:11:09 +00:00
|
|
|
}
|
|
|
|
|
1996-02-29 18:28:43 +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)
|
|
|
|
struct lease *lease;
|
|
|
|
{
|
|
|
|
struct lease lt;
|
|
|
|
|
|
|
|
lt = *lease;
|
|
|
|
lt.ends = 0xFFFFFFFF;
|
|
|
|
warn ("Abandoning IP address %s\n",
|
|
|
|
piaddr (lease -> ip_addr));
|
|
|
|
lt.hardware_addr.htype = -1;
|
|
|
|
lt.hardware_addr.hlen = 0;
|
1996-05-16 07:22:00 +00:00
|
|
|
lt.uid = (unsigned char *)0;
|
1996-02-29 18:28:43 +00:00
|
|
|
lt.uid_len = 0;
|
1996-03-02 05:13:36 +00:00
|
|
|
supersede_lease (lease, <, 1);
|
1996-02-29 18:28:43 +00:00
|
|
|
}
|
|
|
|
|
1996-02-06 20:25:56 +00:00
|
|
|
/* Locate the lease associated with a given IP address... */
|
|
|
|
|
|
|
|
struct lease *find_lease_by_ip_addr (addr)
|
|
|
|
struct iaddr addr;
|
|
|
|
{
|
|
|
|
struct lease *lease = (struct lease *)hash_lookup (lease_ip_addr_hash,
|
|
|
|
addr.iabuf,
|
|
|
|
addr.len);
|
|
|
|
return lease;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct lease *find_lease_by_uid (uid, len)
|
|
|
|
unsigned char *uid;
|
|
|
|
int len;
|
|
|
|
{
|
|
|
|
struct lease *lease = (struct lease *)hash_lookup (lease_uid_hash,
|
|
|
|
uid, len);
|
|
|
|
return lease;
|
|
|
|
}
|
|
|
|
|
1996-02-21 12:11:09 +00:00
|
|
|
struct lease *find_lease_by_hw_addr (hwaddr, hwlen)
|
|
|
|
unsigned char *hwaddr;
|
|
|
|
int hwlen;
|
|
|
|
{
|
|
|
|
struct lease *lease = (struct lease *)hash_lookup (lease_hw_addr_hash,
|
|
|
|
hwaddr, hwlen);
|
|
|
|
return lease;
|
|
|
|
}
|
|
|
|
|
1996-02-29 18:28:43 +00:00
|
|
|
struct class *add_class (type, name)
|
|
|
|
int type;
|
|
|
|
char *name;
|
|
|
|
{
|
|
|
|
struct class *class = new_class ("add_class");
|
|
|
|
char *tname = (char *)malloc (strlen (name) + 1);
|
|
|
|
|
|
|
|
if (!vendor_class_hash)
|
|
|
|
vendor_class_hash = new_hash ();
|
|
|
|
if (!user_class_hash)
|
|
|
|
user_class_hash = new_hash ();
|
|
|
|
|
|
|
|
if (!tname || !class || !vendor_class_hash || !user_class_hash)
|
|
|
|
return (struct class *)0;
|
|
|
|
|
|
|
|
memset (class, 0, sizeof *class);
|
|
|
|
strcpy (tname, name);
|
|
|
|
class -> name = tname;
|
1996-05-17 23:20:23 +00:00
|
|
|
memset (class -> options, 0, sizeof class -> options);
|
|
|
|
class -> max_lease_time = class -> default_lease_time = 0;
|
1996-02-29 18:28:43 +00:00
|
|
|
|
|
|
|
if (type)
|
|
|
|
add_hash (user_class_hash,
|
|
|
|
tname, strlen (tname), (unsigned char *)class);
|
|
|
|
else
|
|
|
|
add_hash (user_class_hash,
|
|
|
|
tname, strlen (tname), (unsigned char *)class);
|
|
|
|
return class;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct class *find_class (type, name, len)
|
|
|
|
int type;
|
|
|
|
char *name;
|
|
|
|
int len;
|
|
|
|
{
|
|
|
|
struct class *class =
|
|
|
|
(struct class *)hash_lookup (type
|
|
|
|
? user_class_hash
|
|
|
|
: vendor_class_hash, name, len);
|
|
|
|
return class;
|
|
|
|
}
|
|
|
|
|
1996-03-02 05:13:36 +00:00
|
|
|
/* Write all interesting leases to permanent storage. */
|
|
|
|
|
|
|
|
void write_leases ()
|
|
|
|
{
|
|
|
|
struct lease *l;
|
1996-05-22 07:40:52 +00:00
|
|
|
struct shared_network *s;
|
1996-03-02 05:13:36 +00:00
|
|
|
|
1996-05-22 07:40:52 +00:00
|
|
|
for (s = shared_networks; s; s = s -> next) {
|
1996-03-02 05:13:36 +00:00
|
|
|
for (l = s -> leases; l; l = l -> next) {
|
|
|
|
if (l -> hardware_addr.hlen || l -> uid_len)
|
|
|
|
write_lease (l);
|
|
|
|
}
|
|
|
|
}
|
1996-06-11 08:14:28 +00:00
|
|
|
if (!commit_leases ())
|
|
|
|
error ("Can't commit leases to new database: %m");
|
1996-03-02 05:13:36 +00:00
|
|
|
}
|
|
|
|
|
1996-02-21 12:11:09 +00:00
|
|
|
void dump_subnets ()
|
|
|
|
{
|
|
|
|
struct lease *l;
|
1996-05-22 07:40:52 +00:00
|
|
|
struct shared_network *s;
|
|
|
|
struct subnet *n;
|
1996-02-21 12:11:09 +00:00
|
|
|
|
1996-05-25 18:38:02 +00:00
|
|
|
for (s = shared_networks; s; s = s -> next) {
|
|
|
|
for (n = subnets; n; n = n -> next_sibling) {
|
|
|
|
debug ("Subnet %s", piaddr (n -> net));
|
|
|
|
debug (" netmask %s",
|
|
|
|
piaddr (n -> netmask));
|
|
|
|
}
|
|
|
|
for (l = s -> leases; l; l = l -> next) {
|
|
|
|
print_lease (l);
|
|
|
|
}
|
|
|
|
debug ("Last Lease:");
|
|
|
|
print_lease (s -> last_lease);
|
1996-02-21 12:11:09 +00:00
|
|
|
}
|
|
|
|
}
|