diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2004-02-23 19:19:13 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2004-02-23 19:19:13 +0000 |
commit | 4381c6e8a1553e1488c79150b156429d39169d4a (patch) | |
tree | d23be2ecafd68dad43130ec919ca850361aa0fc1 | |
parent | 3ded17d373374973a736f4ac489a185eca53518b (diff) |
remove allocation/storage/search code for subnets, shared networks, and
leases - it is server-only code.
-rw-r--r-- | sbin/dhclient/Makefile | 4 | ||||
-rw-r--r-- | sbin/dhclient/dhcpd.h | 33 | ||||
-rw-r--r-- | sbin/dhclient/dispatch.c | 60 | ||||
-rw-r--r-- | sbin/dhclient/memory.c | 914 |
4 files changed, 4 insertions, 1007 deletions
diff --git a/sbin/dhclient/Makefile b/sbin/dhclient/Makefile index 1f149bab1e3..a5f4e5a1903 100644 --- a/sbin/dhclient/Makefile +++ b/sbin/dhclient/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.4 2004/02/23 18:21:15 henning Exp $ +# $OpenBSD: Makefile,v 1.5 2004/02/23 19:19:12 henning Exp $ # # Copyright (c) 1996, 1997 The Internet Software Consortium. # All rights reserved. @@ -33,7 +33,7 @@ .include <bsd.own.mk> SRCS= dhclient.c clparse.c \ - alloc.c dispatch.c hash.c memory.c print.c bpf.c icmp.c options.c \ + alloc.c dispatch.c hash.c print.c bpf.c icmp.c options.c \ tree.c conflex.c errwarn.c inet.c packet.c convert.c \ ethernet.c tables.c parse.c diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h index cda2ef0380f..54e317b6345 100644 --- a/sbin/dhclient/dhcpd.h +++ b/sbin/dhclient/dhcpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dhcpd.h,v 1.6 2004/02/23 18:21:15 henning Exp $ */ +/* $OpenBSD: dhcpd.h,v 1.7 2004/02/23 19:19:12 henning Exp $ */ /* Definitions for dhcpd... */ @@ -538,36 +538,6 @@ struct lease *mockup_lease(struct packet *, struct shared_network *, /* bootp.c */ void bootp(struct packet *); -/* memory.c */ -void enter_host(struct host_decl *); -struct host_decl *find_hosts_by_haddr(int, unsigned char *, int); -struct host_decl *find_hosts_by_uid(unsigned char *, int); -struct subnet *find_host_for_network(struct host_decl **, struct iaddr *, - struct shared_network *); -void new_address_range(struct iaddr, struct iaddr, struct subnet *, int); -extern struct subnet *find_grouped_subnet(struct shared_network *, - struct iaddr); -extern struct subnet *find_subnet(struct iaddr); -void enter_shared_network(struct shared_network *); -int subnet_inner_than(struct subnet *, struct subnet *, int); -void enter_subnet(struct subnet *); -void enter_lease(struct lease *); -int supersede_lease(struct lease *, struct lease *, int); -void release_lease(struct lease *); -void abandon_lease(struct lease *, char *); -struct lease *find_lease_by_uid(unsigned char *, int); -struct lease *find_lease_by_hw_addr(unsigned char *, int); -struct lease *find_lease_by_ip_addr(struct iaddr); -void uid_hash_add(struct lease *); -void uid_hash_delete(struct lease *); -void hw_hash_add(struct lease *); -void hw_hash_delete(struct lease *); -struct class *add_class(int, char *); -struct class *find_class(int, unsigned char *, int); -struct group *clone_group(struct group *, char *); -void write_leases(void); -void dump_subnets(void); - /* alloc.c */ VOIDPTR dmalloc(int, char *); void dfree(VOIDPTR, char *); @@ -639,7 +609,6 @@ void discover_interfaces(int); struct interface_info *setup_fallback(void); void reinitialize_interfaces(void); void dispatch(void); -int locate_network(struct packet *); void got_one(struct protocol *); void add_timeout(TIME, void (*)(void *), void *); void cancel_timeout(void (*)(void *), void *); diff --git a/sbin/dhclient/dispatch.c b/sbin/dhclient/dispatch.c index 6b89055c3c4..8cd0b500029 100644 --- a/sbin/dhclient/dispatch.c +++ b/sbin/dhclient/dispatch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dispatch.c,v 1.9 2004/02/23 18:29:33 henning Exp $ */ +/* $OpenBSD: dispatch.c,v 1.10 2004/02/23 19:19:12 henning Exp $ */ /* Network input dispatcher... */ @@ -76,7 +76,6 @@ discover_interfaces(int state) struct interface_info *tmp; struct interface_info *last, *next; struct subnet *subnet; - struct shared_network *share; struct sockaddr_in foo; int ir; struct ifreq *tif; @@ -175,40 +174,6 @@ discover_interfaces(int state) /* Grab the address... */ addr.len = 4; memcpy(addr.iabuf, &foo.sin_addr.s_addr, addr.len); - - /* If there's a registered subnet for this address, - connect it together... */ - if ((subnet = find_subnet(addr))) { - /* If this interface has multiple aliases - on the same subnet, ignore all but the - first we encounter. */ - if (!subnet->interface) { - subnet->interface = tmp; - subnet->interface_address = addr; - } else if (subnet->interface != tmp) - warn("Multiple %s %s: %s %s", - "interfaces match the", - "same subnet", - subnet->interface->name, - tmp->name); - share = subnet->shared_network; - if (tmp->shared_network && - tmp->shared_network != share) - warn("Interface %s matches %s", - tmp->name, - "multiple shared networks"); - else - tmp->shared_network = share; - - if (!share->interface) - share->interface = tmp; - else if (share->interface != tmp) - warn("Multiple %s %s: %s %s", - "interfaces match the", - "same shared network", - share->interface->name, - tmp->name); - } } } @@ -534,29 +499,6 @@ active: return (1); } -int -locate_network(struct packet *packet) -{ - struct iaddr ia; - - /* If this came through a gateway, find the corresponding subnet... */ - if (packet->raw->giaddr.s_addr) { - struct subnet *subnet; - ia.len = 4; - memcpy(ia.iabuf, &packet->raw->giaddr, 4); - subnet = find_subnet(ia); - if (subnet) - packet->shared_network = subnet->shared_network; - else - packet->shared_network = NULL; - } else - packet->shared_network = packet->interface->shared_network; - - if (packet->shared_network) - return (1); - return (0); -} - void add_timeout(TIME when, void (*where)(void *), void *what) { diff --git a/sbin/dhclient/memory.c b/sbin/dhclient/memory.c deleted file mode 100644 index 6896c16274e..00000000000 --- a/sbin/dhclient/memory.c +++ /dev/null @@ -1,914 +0,0 @@ -/* $OpenBSD: memory.c,v 1.4 2004/02/14 23:52:48 henning Exp $ */ - -/* Memory-resident database... */ - -/* - * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. - * All rights reserved. - * - * 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''. - */ - -#include "dhcpd.h" - -static struct subnet *subnets; -static struct shared_network *shared_networks; -static struct hash_table *host_hw_addr_hash; -static struct hash_table *host_uid_hash; -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; - -static struct hash_table *vendor_class_hash; -static struct hash_table *user_class_hash; - -void -enter_host(struct host_decl *hd) -{ - struct host_decl *hp = NULL; - struct host_decl *np = NULL; - - hd->n_ipaddr = NULL; - - 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 there isn't already a host decl matching this - * address, add it to the hash table. - */ - if (!hp) - add_hash(host_hw_addr_hash, hd->interface.haddr, - hd->interface.hlen, (unsigned char *)hd); - } - - /* - * If there was already a host declaration for this hardware - * address, add this one to the end of the list. - */ - - if (hp) { - for (np = hp; np->n_ipaddr; np = np->n_ipaddr) - ; /* nothing */ - np->n_ipaddr = hd; - } - - if (hd->group->options[DHO_DHCP_CLIENT_IDENTIFIER]) { - if (!tree_evaluate(hd->group->options - [DHO_DHCP_CLIENT_IDENTIFIER])) - return; - /* - * 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) { - host_uid_hash = new_hash(); - hp = NULL; - } else - hp = (struct host_decl *)hash_lookup(host_uid_hash, - hd->group->options[DHO_DHCP_CLIENT_IDENTIFIER]->value, - hd->group->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) - ; /* nothing */ - np->n_ipaddr = hd; - } - } else { - add_hash(host_uid_hash, - hd->group->options[DHO_DHCP_CLIENT_IDENTIFIER]->value, - hd->group->options[DHO_DHCP_CLIENT_IDENTIFIER]->len, - (unsigned char *)hd); - } - } -} - -struct host_decl * -find_hosts_by_haddr(int htype, unsigned char *haddr, int hlen) -{ - struct host_decl *foo; - - foo = (struct host_decl *)hash_lookup(host_hw_addr_hash, - haddr, hlen); - return (foo); -} - -struct host_decl * -find_hosts_by_uid(unsigned char *data, int len) -{ - struct host_decl *foo; - - foo = (struct host_decl *)hash_lookup(host_uid_hash, data, len); - return (foo); -} - -/* - * 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(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(struct iaddr low, struct iaddr high, struct subnet *subnet, - int dynamic) -{ - struct lease *address_range, *lp, *plp; - struct iaddr net; - int min, max, i; - char lowbuf [16], highbuf [16], netbuf [16]; - struct shared_network *share = subnet->shared_network; - struct hostent *h; - struct in_addr ia; - - /* All subnets should have attached shared network structures. */ - if (!share) { - strlcpy(netbuf, piaddr (subnet->net), sizeof(netbuf)); - error("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) - 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. */ - net = subnet_number (low, subnet->netmask); - if (!addr_eq (net, subnet_number (high, subnet->netmask))) { - strlcpy(lowbuf, piaddr (low), sizeof(lowbuf)); - strlcpy(highbuf, piaddr (high), sizeof(highbuf)); - strlcpy(netbuf, piaddr (subnet->netmask), sizeof(netbuf)); - error("Address range %s to %s, netmask %s spans %s!", - lowbuf, highbuf, netbuf, "multiple subnets"); - } - - /* Make sure that the addresses are on the correct subnet. */ - if (!addr_eq (net, subnet->net)) { - strlcpy(lowbuf, piaddr (low), sizeof(lowbuf)); - strlcpy(highbuf, piaddr (high), sizeof(highbuf)); - strlcpy(netbuf, piaddr (subnet->netmask), sizeof(netbuf)); - error("Address range %s to %s not on net %s/%s!", - lowbuf, highbuf, piaddr (subnet->net), netbuf); - } - - /* 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); - } - - /* Get a lease structure for each address in the range. */ - address_range = new_leases(max - min + 1, "new_address_range"); - if (!address_range) { - strlcpy(lowbuf, piaddr(low), sizeof(lowbuf)); - strlcpy(highbuf, piaddr(high), sizeof(highbuf)); - error("No memory for address range %s-%s.", lowbuf, highbuf); - } - memset(address_range, 0, (sizeof *address_range) * (max - min + 1)); - - /* Fill in the last lease if it hasn't been already... */ - if (!share->last_lease) - share->last_lease = &address_range [0]; - - /* Fill out the lease structures with some minimal information. */ - for (i = 0; i < max - min + 1; i++) { - address_range[i].ip_addr = - ip_addr(subnet->net, subnet->netmask, i + min); - address_range[i].starts = - address_range[i].timestamp = MIN_TIME; - address_range[i].ends = MIN_TIME; - address_range[i].subnet = subnet; - address_range[i].shared_network = share; - address_range[i].flags = dynamic ? DYNAMIC_BOOTP_OK : 0; - - memcpy(&ia, address_range[i].ip_addr.iabuf, 4); - - if (subnet->group->get_lease_hostnames) { - h = gethostbyaddr((char *)&ia, sizeof ia, AF_INET); - if (!h) - warn("No hostname for %s", inet_ntoa (ia)); - else { - int len = strlen(h->h_name) + 1; - address_range[i].hostname = malloc(len); - if (!address_range [i].hostname) - error("no memory for hostname %s.", - h->h_name); - strlcpy(address_range [i].hostname, h->h_name, - len); - } - } - - /* Link this entry into the list. */ - address_range[i].next = share->leases; - address_range[i].prev = (struct lease *)0; - share->leases = &address_range [i]; - if (address_range[i].next) - address_range[i].next->prev = share->leases; - add_hash(lease_ip_addr_hash, address_range[i].ip_addr.iabuf, - address_range[i].ip_addr.len, - (unsigned char *)&address_range[i]); - } - - /* Find out if any dangling leases are in range... */ - plp = NULL; - for (lp = dangling_leases; lp; lp = lp->next) { - struct iaddr lnet; - int lhost; - - lnet = subnet_number(lp->ip_addr, subnet->netmask); - lhost = host_addr(lp->ip_addr, subnet->netmask); - - /* - * 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. - */ - if (addr_eq (lnet, subnet->net) && - lhost >= i && lhost <= max) { - if (plp) - plp->next = lp->next; - else - dangling_leases = lp->next; - lp->next = NULL; - address_range[lhost - i].hostname = lp->hostname; - address_range[lhost - i].client_hostname = - lp->client_hostname; - supersede_lease(&address_range[lhost - i], lp, 0); - free_lease(lp, "new_address_range"); - } else - plp = lp; - } -} - -struct subnet * -find_subnet(struct iaddr addr) -{ - struct subnet *rv; - - for (rv = subnets; rv; rv = rv->next_subnet) - if (addr_eq (subnet_number (addr, rv->netmask), rv->net)) - return rv; - - return (NULL); -} - -struct subnet * -find_grouped_subnet(struct shared_network *share, struct iaddr addr) -{ - struct subnet *rv; - - for (rv = share->subnets; rv; rv = rv->next_sibling) - if (addr_eq (subnet_number (addr, rv->netmask), rv->net)) - return rv; - - return (NULL); -} - -int -subnet_inner_than(struct subnet *subnet, struct subnet *scan, int warnp) -{ - if (addr_eq(subnet_number(subnet->net, scan->netmask), scan->net) || - addr_eq(subnet_number (scan->net, subnet->netmask), subnet->net)) { - char n1buf [16]; - int i, j; - - for (i = 0; i < 32; i++) - if (subnet->netmask.iabuf [3 - (i >> 3)] & - (1 << (i & 7))) - break; - for (j = 0; j < 32; j++) - if (scan->netmask.iabuf [3 - (j >> 3)] & - (1 << (j & 7))) - break; - strlcpy(n1buf, piaddr(subnet->net), sizeof(n1buf)); - if (warnp) - warn("%ssubnet %s/%d conflicts with subnet %s/%d", - "Warning: ", n1buf, 32 - i, - piaddr(scan->net), 32 - j); - if (i < j) - return 1; - } - return 0; -} - -/* Enter a new subnet into the subnet list. */ - -void -enter_subnet(struct subnet *subnet) -{ - struct subnet *scan, *prev = NULL; - - /* Check for duplicates... */ - for (scan = subnets; scan; scan = scan->next_subnet) { - /* - * 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) - prev->next_subnet = subnet; - else - subnets = subnet; - subnet->next_subnet = scan; - return; - } - prev = scan; - } - - /* XXX use the BSD radix tree code instead of a linked list. */ - subnet->next_subnet = subnets; - subnets = subnet; -} - -/* Enter a new shared network into the shared network list. */ - -void -enter_shared_network(struct shared_network *share) -{ - /* XXX Sort the nets into a balanced tree to make searching quicker. */ - share->next = shared_networks; - shared_networks = share; -} - -/* - * 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(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", - piaddr(lease->ip_addr)); - } - *comp = *lease; - comp->next = dangling_leases; - comp->prev = NULL; - dangling_leases = comp; - } else { - /* Record the hostname information in the lease. */ - comp->hostname = lease->hostname; - comp->client_hostname = lease->client_hostname; - supersede_lease(comp, lease, 0); - } -} - -/* - * 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. - */ -int -supersede_lease(struct lease *comp, struct lease *lease, int commit) -{ - int enter_uid = 0; - int enter_hwaddr = 0; - struct lease *lp; - - /* 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. - */ - - if (!(lease->flags & ABANDONED_LEASE) && - comp->ends > cur_time && - (((comp->uid && lease->uid) && (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", piaddr (comp->ip_addr)); - return 0; - } else { - /* If there's a Unique ID, dissociate it from the hash - table and free it if necessary. */ - if (comp->uid) { - uid_hash_delete(comp); - enter_uid = 1; - if (comp->uid != &comp->uid_buf[0]) { - free(comp->uid); - comp->uid_max = 0; - comp->uid_len = 0; - } - comp->uid = NULL; - } else - enter_uid = 1; - - if (comp->hardware_addr.htype && - ((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))) { - hw_hash_delete(comp); - enter_hwaddr = 1; - } else if (!comp->hardware_addr.htype) - enter_hwaddr = 1; - - /* Copy the data files, but not the linkages. */ - comp->starts = lease->starts; - if (lease->uid) { - if (lease->uid_len < sizeof(lease->uid_buf)) { - memcpy(comp->uid_buf, lease->uid, - lease->uid_len); - comp->uid = &comp->uid_buf[0]; - comp->uid_max = sizeof comp->uid_buf; - } else if (lease->uid != &lease->uid_buf[0]) { - comp->uid = lease->uid; - comp->uid_max = lease->uid_max; - lease->uid = NULL; - lease->uid_max = 0; - } else { - error("corrupt lease uid."); /* XXX */ - } - } else { - comp->uid = NULL; - comp->uid_max = 0; - } - comp->uid_len = lease->uid_len; - comp->host = lease->host; - comp->hardware_addr = lease->hardware_addr; - comp->flags = ((lease->flags & ~PERSISTENT_FLAGS) | - (comp->flags & ~EPHEMERAL_FLAGS)); - - /* Record the lease in the uid hash if necessary. */ - if (enter_uid && lease->uid) - uid_hash_add(comp); - - /* Record it in the hardware address hash if necessary. */ - if (enter_hwaddr && lease->hardware_addr.htype) - hw_hash_add(comp); - - /* - * Remove the lease from its current place in the - * timeout sequence. - */ - if (comp->prev) - comp->prev->next = comp->next; - else - comp->shared_network->leases = comp->next; - - if (comp->next) - comp->next->prev = comp->prev; - - if (comp->shared_network->last_lease == comp) - comp->shared_network->last_lease = comp->prev; - - /* Find the last insertion point... */ - if (comp == comp->shared_network->insertion_point || - !comp->shared_network->insertion_point) - lp = comp->shared_network->leases; - else - lp = comp->shared_network->insertion_point; - - - if (!lp) { - /* - * Nothing on the list yet? Just make comp the - * head of the list. - */ - comp->shared_network->leases = comp; - comp->shared_network->last_lease = comp; - } else if (lp->ends > lease->ends) { - /* - * Skip down the list until we run out of list - * or find a place for comp. - */ - while (lp->next && lp->ends > lease->ends) - lp = lp->next; - - if (lp->ends > lease->ends) { - /* - * If we ran out of list, put comp - * at the end. - */ - lp->next = comp; - comp->prev = lp; - comp->next = NULL; - comp->shared_network->last_lease = comp; - } else { - /* - * If we didn't, put it between lp and - * the previous item on the list. - */ - if ((comp->prev = lp->prev)) - comp->prev->next = comp; - comp->next = lp; - lp->prev = comp; - } - } else { - /* - * Skip up the list until we run out of list - * or find a place for comp. - */ - while (lp->prev && lp->ends < lease->ends) - lp = lp->prev; - - if (lp->ends < lease->ends) { - /* - * If we ran out of list, put comp - * at the beginning. - */ - lp->prev = comp; - comp->next = lp; - comp->prev = NULL; - comp->shared_network->leases = comp; - } else { - /* - * If we didn't, put it between lp and - * the next item on the list. - */ - if ((comp->next = lp->next)) - comp->next->prev = comp; - comp->prev = lp; - lp->next = comp; - } - } - comp->shared_network->insertion_point = comp; - comp->ends = lease->ends; - } - - /* - * Return zero if we didn't commit the lease to permanent storage; - * nonzero if we did. - */ - return (commit && write_lease(comp) && commit_leases()); -} - -/* Release the specified lease and re-hash it as appropriate. */ -void -release_lease(struct lease *lease) -{ - struct lease lt; - - lt = *lease; - if (lt.ends > cur_time) { - lt.ends = cur_time; - supersede_lease(lease, <, 1); - note("Released lease for IP address %s", - piaddr(lease->ip_addr)); - } -} - - -/* - * Abandon the specified lease for the specified time. sets it's - * particulars to zero, the end time apropriately and re-hash it as - * appropriate. abandons permanently if abtime is 0. - */ -void -abandon_lease(struct lease *lease, char *message) -{ - struct lease lt; - TIME abtime; - - abtime = lease->subnet->group->default_lease_time; - lease->flags |= ABANDONED_LEASE; - lt = *lease; - lt.ends = cur_time + abtime; - warn("Abandoning IP address %s for %d seconds: %s", - piaddr(lease->ip_addr), abtime, message); - lt.hardware_addr.htype = 0; - lt.hardware_addr.hlen = 0; - lt.uid = NULL; - lt.uid_len = 0; - supersede_lease(lease, <, 1); -} - -/* Locate the lease associated with a given IP address... */ - -struct lease * -find_lease_by_ip_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(unsigned char *uid, int len) -{ - struct lease *lease; - - lease = (struct lease *)hash_lookup(lease_uid_hash, uid, len); - return (lease); -} - -struct lease * -find_lease_by_hw_addr(unsigned char *hwaddr, int hwlen) -{ - struct lease *lease; - - lease = (struct lease *)hash_lookup(lease_hw_addr_hash, hwaddr, hwlen); - return (lease); -} - -/* Add the specified lease to the uid hash. */ - -void -uid_hash_add(struct lease *lease) -{ - struct lease *head = find_lease_by_uid(lease->uid, lease->uid_len); - struct lease *scan; - -#ifdef DEBUG - if (lease->n_uid) - abort(); -#endif - - /* If it's not in the hash, just add it. */ - if (!head) - add_hash(lease_uid_hash, lease->uid, - lease->uid_len, (unsigned char *)lease); - else { - /* Otherwise, attach it to the end of the list. */ - for (scan = head; scan->n_uid; scan = scan->n_uid) -#ifdef DEBUG - if (scan == lease) - abort() -#endif - ; - scan->n_uid = lease; - } -} - -/* Delete the specified lease from the uid hash. */ - -void -uid_hash_delete(struct lease *lease) -{ - struct lease *head = find_lease_by_uid (lease->uid, lease->uid_len); - struct lease *scan; - - /* If it's not in the hash, we have no work to do. */ - if (!head) { - lease->n_uid = NULL; - 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) { - delete_hash_entry(lease_uid_hash, lease->uid, lease->uid_len); - if (lease->n_uid) - add_hash(lease_uid_hash, lease->n_uid->uid, - lease->n_uid->uid_len, - (unsigned char *)(lease->n_uid)); - } 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) { - scan->n_uid = scan->n_uid->n_uid; - break; - } - } - lease->n_uid = (struct lease *)0; -} - -/* Add the specified lease to the hardware address hash. */ - -void hw_hash_add (struct lease *lease) -{ - struct lease *head = - find_lease_by_hw_addr(lease->hardware_addr.haddr, - lease->hardware_addr.hlen); - struct lease *scan; - - /* If it's not in the hash, just add it. */ - if (!head) - add_hash(lease_hw_addr_hash, lease->hardware_addr.haddr, - lease->hardware_addr.hlen, (unsigned char *)lease); - else { - /* Otherwise, attach it to the end of the list. */ - for (scan = head; scan->n_hw; scan = scan->n_hw) - ; /* nothing */ - scan->n_hw = lease; - } -} - -/* Delete the specified lease from the hardware address hash. */ - -void hw_hash_delete (struct lease *lease) -{ - struct lease *head = - find_lease_by_hw_addr(lease->hardware_addr.haddr, - lease->hardware_addr.hlen); - struct lease *scan; - - /* If it's not in the hash, we have no work to do. */ - if (!head) { - lease->n_hw = (struct lease *)0; - 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) { - delete_hash_entry(lease_hw_addr_hash, - lease->hardware_addr.haddr, lease->hardware_addr.hlen); - if (lease->n_hw) - add_hash(lease_hw_addr_hash, - lease->n_hw->hardware_addr.haddr, - lease->n_hw->hardware_addr.hlen, - (unsigned char *)(lease->n_hw)); - } 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_hw; scan = scan->n_hw) - if (scan->n_hw == lease) { - scan->n_hw = scan->n_hw->n_hw; - break; - } - } - lease->n_hw = NULL; -} - - -struct class *add_class (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 (NULL); - - memset(class, 0, sizeof *class); - strlcpy(tname, name, strlen(name) + 1); - class->name = tname; - - if (type) - add_hash(user_class_hash, (unsigned char *)tname, - strlen(tname), (unsigned char *)class); - else - add_hash(vendor_class_hash, (unsigned char *)tname, - strlen(tname), (unsigned char *)class); - return (class); -} - -struct class * -find_class(int type, unsigned char *name, int len) -{ - struct class *class = (struct class *)hash_lookup( - type ? user_class_hash : vendor_class_hash, name, len); - return (class); -} - -struct group *clone_group (struct group *group, char *caller) -{ - struct group *g = new_group (caller); - if (!g) - error("%s: can't allocate new group", caller); - *g = *group; - return g; -} - -/* Write all interesting leases to permanent storage. */ - -void -write_leases(void) -{ - struct lease *l; - struct shared_network *s; - - for (s = shared_networks; s; s = s->next) - for (l = s->leases; l; l = l->next) - if (l->hardware_addr.hlen || - l->uid_len || (l->flags & ABANDONED_LEASE)) - if (!write_lease (l)) - error("Can't rewrite lease database"); - - if (!commit_leases()) - error("Can't commit leases to new database: %m"); -} - -void -dump_subnets(void) -{ - struct lease *l; - struct shared_network *s; - struct subnet *n; - - note("Subnets:"); - for (n = subnets; n; n = n->next_subnet) { - debug(" Subnet %s", piaddr (n->net)); - debug(" netmask %s", piaddr (n->netmask)); - } - note("Shared networks:"); - for (s = shared_networks; s; s = s->next) { - note(" %s", s->name); - for (l = s->leases; l; l = l->next) - print_lease(l); - if (s->last_lease) { - debug(" Last Lease:"); - print_lease(s->last_lease); - } - } -} |