2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-09-04 16:25:21 +00:00

Keep a persistent database of leases

This commit is contained in:
Ted Lemon
1996-03-02 05:13:36 +00:00
parent 1a74d33bdc
commit 1358b87447
21 changed files with 1005 additions and 121 deletions

View File

@@ -1,6 +1,6 @@
SRCS = dhcpd.c options.c errwarn.c convert.c conflex.c confpars.c \ SRCS = dhcpd.c options.c errwarn.c convert.c conflex.c confpars.c \
tree.c memory.c bootp.c dhcp.c alloc.c print.c socket.c \ tree.c memory.c bootp.c dhcp.c alloc.c print.c socket.c \
hash.c tables.c inet.c hash.c tables.c inet.c db.c
PROG = dhcpd PROG = dhcpd
all: dhcpd dhclient all: dhcpd dhclient
@@ -12,7 +12,7 @@ CFLAGS += -DDEBUG -g -Wall -Wstrict-prototypes -Wno-unused \
dhclient: dhclient.o confpars.o alloc.o memory.o options.o \ dhclient: dhclient.o confpars.o alloc.o memory.o options.o \
hash.o tables.o inet.o convert.o conflex.o errwarn.o \ hash.o tables.o inet.o convert.o conflex.o errwarn.o \
tree.o print.o tree.o print.o db.o
cc -o dhclient dhclient.o confpars.o alloc.o memory.o options.o \ cc -o dhclient dhclient.o confpars.o alloc.o memory.o options.o \
hash.o tables.o inet.o convert.o conflex.o errwarn.o \ hash.o tables.o inet.o convert.o conflex.o errwarn.o \
print.o tree.o print.o tree.o db.o

View File

@@ -42,7 +42,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"@(#) Copyright (c) 1995 The Internet Software Consortium. All rights reserved.\n"; "@(#) Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -162,8 +162,8 @@ void new_address_range (low, high, subnet)
if (address_range [i].next) if (address_range [i].next)
address_range [i].next -> prev = subnet -> leases; address_range [i].next -> prev = subnet -> leases;
add_hash (lease_ip_addr_hash, add_hash (lease_ip_addr_hash,
(char *)&address_range [i].ip_addr, address_range [i].ip_addr.iabuf,
sizeof address_range [i].ip_addr, address_range [i].ip_addr.len,
(unsigned char *)&address_range [i]); (unsigned char *)&address_range [i]);
} }
@@ -187,7 +187,7 @@ void new_address_range (low, high, subnet)
dangling_leases = lp -> next; dangling_leases = lp -> next;
} }
lp -> next = (struct lease *)0; lp -> next = (struct lease *)0;
supersede_lease (&address_range [lhost - i], lp); supersede_lease (&address_range [lhost - i], lp, 0);
free_lease (lp, "new_address_range"); free_lease (lp, "new_address_range");
} else } else
plp = lp; plp = lp;
@@ -230,6 +230,7 @@ void enter_lease (lease)
/* If we don't have a place for this lease yet, save it for /* If we don't have a place for this lease yet, save it for
later. */ later. */
if (!comp) { if (!comp) {
printf ("didn't find the lease...\n");
comp = new_lease ("enter_lease"); comp = new_lease ("enter_lease");
if (!comp) { if (!comp) {
error ("No memory for lease %s\n", error ("No memory for lease %s\n",
@@ -240,7 +241,8 @@ void enter_lease (lease)
lease -> prev = (struct lease *)0; lease -> prev = (struct lease *)0;
dangling_leases = lease; dangling_leases = lease;
} else { } else {
supersede_lease (comp, lease); printf ("superseding lease...\n");
supersede_lease (comp, lease, 0);
} }
} }
@@ -249,8 +251,9 @@ void enter_lease (lease)
list of leases by expiry time so that we can always find the oldest list of leases by expiry time so that we can always find the oldest
lease. */ lease. */
void supersede_lease (comp, lease) int supersede_lease (comp, lease, commit)
struct lease *comp, *lease; struct lease *comp, *lease;
int commit;
{ {
int enter_uid = 0; int enter_uid = 0;
int enter_hwaddr = 0; int enter_hwaddr = 0;
@@ -402,6 +405,10 @@ void supersede_lease (comp, lease)
comp -> contain -> insertion_point = comp; comp -> contain -> insertion_point = comp;
comp -> ends = lease -> ends; 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. */ /* Release the specified lease and re-hash it as appropriate. */
@@ -413,7 +420,7 @@ void release_lease (lease)
lt = *lease; lt = *lease;
lt.ends = cur_time; lt.ends = cur_time;
supersede_lease (lease, &lt); supersede_lease (lease, &lt, 1);
} }
/* Abandon the specified lease (set its timeout to infinity and its /* Abandon the specified lease (set its timeout to infinity and its
@@ -432,7 +439,7 @@ void abandon_lease (lease)
lt.hardware_addr.hlen = 0; lt.hardware_addr.hlen = 0;
lt.uid = (char *)0; lt.uid = (char *)0;
lt.uid_len = 0; lt.uid_len = 0;
supersede_lease (lease, &lt); supersede_lease (lease, &lt, 1);
} }
/* Locate the lease associated with a given IP address... */ /* Locate the lease associated with a given IP address... */
@@ -504,6 +511,23 @@ struct class *find_class (type, name, len)
return class; return class;
} }
/* Write all interesting leases to permanent storage. */
void write_leases ()
{
struct lease *l;
struct subnet *s;
int i;
for (s = subnets; s; s = s -> next) {
for (l = s -> leases; l; l = l -> next) {
if (l -> hardware_addr.hlen || l -> uid_len)
write_lease (l);
}
}
commit_leases ();
}
void dump_subnets () void dump_subnets ()
{ {
struct lease *l; struct lease *l;

View File

@@ -3,7 +3,8 @@
DHCP options parsing and reassembly. */ DHCP options parsing and reassembly. */
/* /*
* Copyright (c) 1995 The Internet Software Consortium. All rights reserved. * Copyright (c) 1995, 1996 The Internet Software Consortium.
* All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -41,7 +42,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"@(#) Copyright (c) 1995 The Internet Software Consortium. All rights reserved.\n"; "@(#) Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#define DHCP_OPTION_DATA #define DHCP_OPTION_DATA

View File

@@ -389,6 +389,266 @@ int sizeof_dhcp_option_default_priority_list =
sizeof dhcp_option_default_priority_list; sizeof dhcp_option_default_priority_list;
char *hardware_types [] = {
"unknown-0",
"ethernet",
"unknown-2",
"unknown-3",
"unknown-4",
"unknown-5",
"unknown-6",
"unknown-7",
"unknown-8",
"unknown-9",
"unknown-10",
"unknown-11",
"unknown-12",
"unknown-13",
"unknown-14",
"unknown-15",
"unknown-16",
"unknown-17",
"unknown-18",
"unknown-19",
"unknown-20",
"unknown-21",
"unknown-22",
"unknown-23",
"unknown-24",
"unknown-25",
"unknown-26",
"unknown-27",
"unknown-28",
"unknown-29",
"unknown-30",
"unknown-31",
"unknown-32",
"unknown-33",
"unknown-34",
"unknown-35",
"unknown-36",
"unknown-37",
"unknown-38",
"unknown-39",
"unknown-40",
"unknown-41",
"unknown-42",
"unknown-43",
"unknown-44",
"unknown-45",
"unknown-46",
"unknown-47",
"unknown-48",
"unknown-49",
"unknown-50",
"unknown-51",
"unknown-52",
"unknown-53",
"unknown-54",
"unknown-55",
"unknown-56",
"unknown-57",
"unknown-58",
"unknown-59",
"unknown-60",
"unknown-61",
"unknown-62",
"unknown-63",
"unknown-64",
"unknown-65",
"unknown-66",
"unknown-67",
"unknown-68",
"unknown-69",
"unknown-70",
"unknown-71",
"unknown-72",
"unknown-73",
"unknown-74",
"unknown-75",
"unknown-76",
"unknown-77",
"unknown-78",
"unknown-79",
"unknown-80",
"unknown-81",
"unknown-82",
"unknown-83",
"unknown-84",
"unknown-85",
"unknown-86",
"unknown-87",
"unknown-88",
"unknown-89",
"unknown-90",
"unknown-91",
"unknown-92",
"unknown-93",
"unknown-94",
"unknown-95",
"unknown-96",
"unknown-97",
"unknown-98",
"unknown-99",
"unknown-100",
"unknown-101",
"unknown-102",
"unknown-103",
"unknown-104",
"unknown-105",
"unknown-106",
"unknown-107",
"unknown-108",
"unknown-109",
"unknown-110",
"unknown-111",
"unknown-112",
"unknown-113",
"unknown-114",
"unknown-115",
"unknown-116",
"unknown-117",
"unknown-118",
"unknown-119",
"unknown-120",
"unknown-121",
"unknown-122",
"unknown-123",
"unknown-124",
"unknown-125",
"unknown-126",
"unknown-127",
"unknown-128",
"unknown-129",
"unknown-130",
"unknown-131",
"unknown-132",
"unknown-133",
"unknown-134",
"unknown-135",
"unknown-136",
"unknown-137",
"unknown-138",
"unknown-139",
"unknown-140",
"unknown-141",
"unknown-142",
"unknown-143",
"unknown-144",
"unknown-145",
"unknown-146",
"unknown-147",
"unknown-148",
"unknown-149",
"unknown-150",
"unknown-151",
"unknown-152",
"unknown-153",
"unknown-154",
"unknown-155",
"unknown-156",
"unknown-157",
"unknown-158",
"unknown-159",
"unknown-160",
"unknown-161",
"unknown-162",
"unknown-163",
"unknown-164",
"unknown-165",
"unknown-166",
"unknown-167",
"unknown-168",
"unknown-169",
"unknown-170",
"unknown-171",
"unknown-172",
"unknown-173",
"unknown-174",
"unknown-175",
"unknown-176",
"unknown-177",
"unknown-178",
"unknown-179",
"unknown-180",
"unknown-181",
"unknown-182",
"unknown-183",
"unknown-184",
"unknown-185",
"unknown-186",
"unknown-187",
"unknown-188",
"unknown-189",
"unknown-190",
"unknown-191",
"unknown-192",
"unknown-193",
"unknown-194",
"unknown-195",
"unknown-196",
"unknown-197",
"unknown-198",
"unknown-199",
"unknown-200",
"unknown-201",
"unknown-202",
"unknown-203",
"unknown-204",
"unknown-205",
"unknown-206",
"unknown-207",
"unknown-208",
"unknown-209",
"unknown-210",
"unknown-211",
"unknown-212",
"unknown-213",
"unknown-214",
"unknown-215",
"unknown-216",
"unknown-217",
"unknown-218",
"unknown-219",
"unknown-220",
"unknown-221",
"unknown-222",
"unknown-223",
"unknown-224",
"unknown-225",
"unknown-226",
"unknown-227",
"unknown-228",
"unknown-229",
"unknown-230",
"unknown-231",
"unknown-232",
"unknown-233",
"unknown-234",
"unknown-235",
"unknown-236",
"unknown-237",
"unknown-238",
"unknown-239",
"unknown-240",
"unknown-241",
"unknown-242",
"unknown-243",
"unknown-244",
"unknown-245",
"unknown-246",
"unknown-247",
"unknown-248",
"unknown-249",
"unknown-250",
"unknown-251",
"unknown-252",
"unknown-253",
"unknown-254",
"unknown-255" };
struct hash_table universe_hash; struct hash_table universe_hash;
void initialize_universes() void initialize_universes()

View File

@@ -70,6 +70,38 @@ void readconf (void)
break; break;
parse_statement (cfile); parse_statement (cfile);
} while (1); } while (1);
token = next_token (&val, cfile);
}
void read_leases (void)
{
FILE *cfile;
char *val;
int token;
jmp_buf bc;
/* Open the lease file... */
if ((cfile = fopen (_PATH_DHCPD_DB, "r")) == NULL)
warn ("Can't open lease database %s: %m", _PATH_DHCPD_DB);
do {
token = next_token (&val, cfile);
printf ("token = %d\n", token);
if (token == EOF)
break;
if (token != LEASE) {
warn ("Corrupt lease file - possible data loss!");
skip_to_semi (cfile);
} else {
if (!setjmp (bc)) {
struct lease *lease;
printf ("Parsing a lease...\n");
lease = parse_lease_statement (cfile, &bc);
enter_lease (lease);
print_lease (lease);
}
}
} while (1);
} }
/* statement :== host_statement */ /* statement :== host_statement */

135
db.c Normal file
View File

@@ -0,0 +1,135 @@
/* db.c
Persistent database management routines for DHCPD... */
/*
* Copyright (c) 1995, 1996 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''.
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
FILE *db_file;
/* Write the specified lease to the current lease database file. */
int write_lease (lease)
struct lease *lease;
{
struct tm *t;
char tbuf [64];
errno = 0;
fprintf (db_file, "lease %s\n", piaddr (lease -> ip_addr));
t = gmtime (&lease -> starts);
strftime (tbuf, sizeof tbuf, "%w %Y/%m/%d %H:%M:%S", t);
fprintf (db_file, "\tstarts %s\n", tbuf);
t = gmtime (&lease -> ends);
strftime (tbuf, sizeof tbuf, "%w %Y/%m/%d %H:%M:%S", t);
fprintf (db_file, "\tends %s", tbuf);
if (lease -> hardware_addr.hlen) {
fprintf (db_file, "\n\thardware %s %s",
hardware_types [lease -> hardware_addr.htype],
print_hw_addr (lease -> hardware_addr.htype,
lease -> hardware_addr.hlen,
lease -> hardware_addr.haddr));
}
if (lease -> uid_len) {
int i;
fprintf (db_file, "\n\tuid %x", lease -> uid [0]);
for (i = 1; i < lease -> uid_len; i++)
fprintf (db_file, ":%x", lease -> uid [i]);
}
fputs (";\n", db_file);
return !errno;
}
/* Commit any leases that have been written out... */
int commit_leases ()
{
if (fflush (db_file) == EOF)
return 0;
if (fsync (fileno (db_file)) < 0)
return 0;
return 1;
}
void db_startup ()
{
/* Read in the existing lease file... */
read_leases ();
new_lease_file ();
}
void new_lease_file ()
{
char newfname [512];
char backfname [512];
TIME t;
/* If we already have an open database, close it. */
if (db_file) {
fclose (db_file);
}
/* Make a temporary lease file... */
time (&t);
sprintf (newfname, "%s.%d", _PATH_DHCPD_DB, t & 32767);
if ((db_file = fopen (newfname, "w")) == NULL) {
error ("Can't start new lease file: %m");
}
/* Write out all the leases that we know of... */
write_leases ();
/* Get the old database out of the way... */
sprintf (backfname, "%s~", _PATH_DHCPD_DB);
unlink (backfname);
link (_PATH_DHCPD_DB, backfname);
/* Move in the new file... */
rename (newfname, _PATH_DHCPD_DB);
}

8
dhcp.c
View File

@@ -379,8 +379,12 @@ void ack_lease (packet, lease, offer, when)
/* Record the transaction id... */ /* Record the transaction id... */
lt.xid = packet -> raw -> xid; lt.xid = packet -> raw -> xid;
/* Install the new information about this lease in the database. */ /* Install the new information about this lease in the database.
supersede_lease (lease, &lt); If this is a DHCPACK and we can't write the lease, don't
ACK it either. */
if (!(supersede_lease (lease, &lt, offer == DHCPACK)
|| offer != DHCPACK))
return;
/* Send a response to the client... */ /* Send a response to the client... */

4
dhcp.h
View File

@@ -63,8 +63,8 @@ struct dhcp_packet {
struct in_addr siaddr; /* IP address of next server to talk to */ struct in_addr siaddr; /* IP address of next server to talk to */
struct in_addr giaddr; /* DHCP relay agent IP address */ struct in_addr giaddr; /* DHCP relay agent IP address */
char chaddr [16]; /* Client hardware address */ char chaddr [16]; /* Client hardware address */
char sname [64]; /* Server name */ char sname [DHCP_SNAME_LEN]; /* Server name */
char file [128]; /* Boot filename */ char file [DHCP_FILE_LEN]; /* Boot filename */
unsigned char options [DHCP_OPTION_LEN]; unsigned char options [DHCP_OPTION_LEN];
/* Optional parameters /* Optional parameters
(actual length dependent on MTU). */ (actual length dependent on MTU). */

View File

@@ -132,6 +132,9 @@ int main (argc, argv, envp)
/* Read the dhcpd.conf file... */ /* Read the dhcpd.conf file... */
readconf (); readconf ();
/* Start up the database... */
db_startup ();
#if 0 #if 0
/* If addresses were specified on the command line, resolve them; /* If addresses were specified on the command line, resolve them;
otherwise, just get a list of the addresses that are configured otherwise, just get a list of the addresses that are configured

View File

@@ -1,34 +1,7 @@
subnet 204.254.239.0 netmask 255.255.255.0 subnet 204.254.239.0 netmask 255.255.255.0
range 204.254.239.11 204.254.239.17; range 204.254.239.10 204.254.239.20
option subnet-mask 255.255.255.0 option broadcast-address 204.254.239.255
subnet 204.254.240.0 netmask 255.255.255.0 default-lease-time 600 max-lease-time 7200
range 204.254.240.11 204.254.240.12; option routers 204.254.239.1
option domain-name-servers 204.254.239.2
host minuet option domain-name "fugue.com";
hardware ethernet 08:00:2b:35:0c:18
filename "/tftpboot/netbsd.minuet"
fixed-address minuet.fugue.com;
host allegro
hardware ethernet 08:00:2b:1c:07:b6
filename "/tftpboot/netbsd.allegro"
fixed-address allegro.fugue.com;
host fantasia
hardware ethernet 8:0:7:26:c0:a5
fixed-address fantasia.fugue.com
option routers prelude.fugue.com
option name-servers toccata.fugue.com, passacaglia.fugue.com
option domain-name "fugue.com";
host avogadro
hardware ethernet 08:00:2b:4c:39:12
option routers prelude.fugue.com
option name-servers toccata.fugue.com
option domain-name "fugue.com";
lease 204.254.239.11
starts 2 96/2/6 10:14:02
ends 2 96/2/6 11:15:02
hardware ethernet 08:00:2b:4c:39:12
host avogadro;

34
dhcpd.h
View File

@@ -154,8 +154,10 @@ typedef unsigned char option_mask [16];
#ifndef _PATH_DHCPD_CONF #ifndef _PATH_DHCPD_CONF
#ifdef DEBUG #ifdef DEBUG
#define _PATH_DHCPD_CONF "dhcpd.conf" #define _PATH_DHCPD_CONF "dhcpd.conf"
#define _PATH_DHCPD_DB "dhcpd.leases"
#else #else
#define _PATH_DHCPD_CONF "/etc/dhcpd.conf" #define _PATH_DHCPD_CONF "/etc/dhcpd.conf"
#define _PATH_DHCPD_CONF "/etc/dhcpd.leases"
#endif #endif
#endif #endif
@@ -170,12 +172,12 @@ void parse_options PROTO ((struct packet *));
void parse_option_buffer PROTO ((struct packet *, unsigned char *, int)); void parse_option_buffer PROTO ((struct packet *, unsigned char *, int));
void cons_options PROTO ((struct packet *, struct packet *, void cons_options PROTO ((struct packet *, struct packet *,
struct tree_cache **, int)); struct tree_cache **, int));
void new_cons_options PROTO ((struct packet *, struct packet *, /* void new_cons_options PROTO ((struct packet *, struct packet *,
struct tree_cache **, int)); struct tree_cache **, int)); */
int store_options PROTO ((unsigned char *, int, struct tree_cache **, int store_options PROTO ((unsigned char *, int, struct tree_cache **,
unsigned char *, int)); unsigned char *, int, int, int));
int store_option PROTO ((struct tree_cache **, unsigned char, /* int store_option PROTO ((struct tree_cache **, unsigned char,
unsigned char *, int, int *)); unsigned char *, int, int *)); */
char *pretty_print_option PROTO ((unsigned char, unsigned char *, int)); char *pretty_print_option PROTO ((unsigned char, unsigned char *, int));
/* errwarn.c */ /* errwarn.c */
@@ -209,6 +211,7 @@ int peek_token PROTO ((char **, FILE *));
/* confpars.c */ /* confpars.c */
void readconf PROTO ((void)); void readconf PROTO ((void));
void read_leases PROTO ((void));
void parse_statement PROTO ((FILE *)); void parse_statement PROTO ((FILE *));
void skip_to_semi PROTO ((FILE *)); void skip_to_semi PROTO ((FILE *));
struct host_decl *parse_host_statement PROTO ((FILE *, jmp_buf *)); struct host_decl *parse_host_statement PROTO ((FILE *, jmp_buf *));
@@ -266,7 +269,7 @@ void new_address_range PROTO ((struct iaddr, struct iaddr,
extern struct subnet *find_subnet (struct iaddr); extern struct subnet *find_subnet (struct iaddr);
void enter_subnet (struct subnet *); void enter_subnet (struct subnet *);
void enter_lease PROTO ((struct lease *)); void enter_lease PROTO ((struct lease *));
void supersede_lease PROTO ((struct lease *, struct lease *)); int supersede_lease PROTO ((struct lease *, struct lease *, int));
void release_lease PROTO ((struct lease *)); void release_lease PROTO ((struct lease *));
void abandon_lease PROTO ((struct lease *)); void abandon_lease PROTO ((struct lease *));
struct lease *find_lease_by_uid PROTO ((unsigned char *, int)); struct lease *find_lease_by_uid PROTO ((unsigned char *, int));
@@ -274,6 +277,7 @@ struct lease *find_lease_by_hw_addr PROTO ((unsigned char *, int));
struct lease *find_lease_by_ip_addr PROTO ((struct iaddr)); struct lease *find_lease_by_ip_addr PROTO ((struct iaddr));
struct class *add_class PROTO ((int, char *)); struct class *add_class PROTO ((int, char *));
struct class *find_class PROTO ((int, char *, int)); struct class *find_class PROTO ((int, char *, int));
void write_leases PROTO ((void));
void dump_subnets PROTO ((void)); void dump_subnets PROTO ((void));
/* alloc.c */ /* alloc.c */
@@ -319,6 +323,7 @@ unsigned char *hash_lookup PROTO ((struct hash_table *, char *, int));
extern struct option dhcp_options [256]; extern struct option dhcp_options [256];
extern unsigned char dhcp_option_default_priority_list []; extern unsigned char dhcp_option_default_priority_list [];
extern int sizeof_dhcp_option_default_priority_list; extern int sizeof_dhcp_option_default_priority_list;
extern char *hardware_types [256];
extern struct hash_table universe_hash; extern struct hash_table universe_hash;
extern struct universe dhcp_universe; extern struct universe dhcp_universe;
void initialize_universes PROTO ((void)); void initialize_universes PROTO ((void));
@@ -334,12 +339,17 @@ void putUShort PROTO ((unsigned char *, unsigned short));
void putShort PROTO ((unsigned char *, short)); void putShort PROTO ((unsigned char *, short));
/* inet.c */ /* inet.c */
struct iaddr subnet_number (struct iaddr, struct iaddr); struct iaddr subnet_number PROTO ((struct iaddr, struct iaddr));
struct iaddr ip_addr (struct iaddr, struct iaddr, unsigned long); struct iaddr ip_addr PROTO ((struct iaddr, struct iaddr, unsigned long));
unsigned long host_addr (struct iaddr, struct iaddr); unsigned long host_addr PROTO ((struct iaddr, struct iaddr));
int addr_eq (struct iaddr, struct iaddr); int addr_eq PROTO ((struct iaddr, struct iaddr));
char *piaddr (struct iaddr); char *piaddr PROTO ((struct iaddr));
/* dhclient.c */ /* dhclient.c */
void parse_client_statement (FILE *, struct host_decl *); void parse_client_statement PROTO ((FILE *, struct host_decl *));
/* db.c */
int write_lease PROTO ((struct lease *));
int commit_leases PROTO ((void));
void db_startup PROTO ((void));
void new_lease_file PROTO ((void));

View File

@@ -63,8 +63,8 @@ struct dhcp_packet {
struct in_addr siaddr; /* IP address of next server to talk to */ struct in_addr siaddr; /* IP address of next server to talk to */
struct in_addr giaddr; /* DHCP relay agent IP address */ struct in_addr giaddr; /* DHCP relay agent IP address */
char chaddr [16]; /* Client hardware address */ char chaddr [16]; /* Client hardware address */
char sname [64]; /* Server name */ char sname [DHCP_SNAME_LEN]; /* Server name */
char file [128]; /* Boot filename */ char file [DHCP_FILE_LEN]; /* Boot filename */
unsigned char options [DHCP_OPTION_LEN]; unsigned char options [DHCP_OPTION_LEN];
/* Optional parameters /* Optional parameters
(actual length dependent on MTU). */ (actual length dependent on MTU). */

View File

@@ -154,8 +154,10 @@ typedef unsigned char option_mask [16];
#ifndef _PATH_DHCPD_CONF #ifndef _PATH_DHCPD_CONF
#ifdef DEBUG #ifdef DEBUG
#define _PATH_DHCPD_CONF "dhcpd.conf" #define _PATH_DHCPD_CONF "dhcpd.conf"
#define _PATH_DHCPD_DB "dhcpd.leases"
#else #else
#define _PATH_DHCPD_CONF "/etc/dhcpd.conf" #define _PATH_DHCPD_CONF "/etc/dhcpd.conf"
#define _PATH_DHCPD_CONF "/etc/dhcpd.leases"
#endif #endif
#endif #endif
@@ -170,12 +172,12 @@ void parse_options PROTO ((struct packet *));
void parse_option_buffer PROTO ((struct packet *, unsigned char *, int)); void parse_option_buffer PROTO ((struct packet *, unsigned char *, int));
void cons_options PROTO ((struct packet *, struct packet *, void cons_options PROTO ((struct packet *, struct packet *,
struct tree_cache **, int)); struct tree_cache **, int));
void new_cons_options PROTO ((struct packet *, struct packet *, /* void new_cons_options PROTO ((struct packet *, struct packet *,
struct tree_cache **, int)); struct tree_cache **, int)); */
int store_options PROTO ((unsigned char *, int, struct tree_cache **, int store_options PROTO ((unsigned char *, int, struct tree_cache **,
unsigned char *, int)); unsigned char *, int, int, int));
int store_option PROTO ((struct tree_cache **, unsigned char, /* int store_option PROTO ((struct tree_cache **, unsigned char,
unsigned char *, int, int *)); unsigned char *, int, int *)); */
char *pretty_print_option PROTO ((unsigned char, unsigned char *, int)); char *pretty_print_option PROTO ((unsigned char, unsigned char *, int));
/* errwarn.c */ /* errwarn.c */
@@ -209,6 +211,7 @@ int peek_token PROTO ((char **, FILE *));
/* confpars.c */ /* confpars.c */
void readconf PROTO ((void)); void readconf PROTO ((void));
void read_leases PROTO ((void));
void parse_statement PROTO ((FILE *)); void parse_statement PROTO ((FILE *));
void skip_to_semi PROTO ((FILE *)); void skip_to_semi PROTO ((FILE *));
struct host_decl *parse_host_statement PROTO ((FILE *, jmp_buf *)); struct host_decl *parse_host_statement PROTO ((FILE *, jmp_buf *));
@@ -266,7 +269,7 @@ void new_address_range PROTO ((struct iaddr, struct iaddr,
extern struct subnet *find_subnet (struct iaddr); extern struct subnet *find_subnet (struct iaddr);
void enter_subnet (struct subnet *); void enter_subnet (struct subnet *);
void enter_lease PROTO ((struct lease *)); void enter_lease PROTO ((struct lease *));
void supersede_lease PROTO ((struct lease *, struct lease *)); int supersede_lease PROTO ((struct lease *, struct lease *, int));
void release_lease PROTO ((struct lease *)); void release_lease PROTO ((struct lease *));
void abandon_lease PROTO ((struct lease *)); void abandon_lease PROTO ((struct lease *));
struct lease *find_lease_by_uid PROTO ((unsigned char *, int)); struct lease *find_lease_by_uid PROTO ((unsigned char *, int));
@@ -274,6 +277,7 @@ struct lease *find_lease_by_hw_addr PROTO ((unsigned char *, int));
struct lease *find_lease_by_ip_addr PROTO ((struct iaddr)); struct lease *find_lease_by_ip_addr PROTO ((struct iaddr));
struct class *add_class PROTO ((int, char *)); struct class *add_class PROTO ((int, char *));
struct class *find_class PROTO ((int, char *, int)); struct class *find_class PROTO ((int, char *, int));
void write_leases PROTO ((void));
void dump_subnets PROTO ((void)); void dump_subnets PROTO ((void));
/* alloc.c */ /* alloc.c */
@@ -319,6 +323,7 @@ unsigned char *hash_lookup PROTO ((struct hash_table *, char *, int));
extern struct option dhcp_options [256]; extern struct option dhcp_options [256];
extern unsigned char dhcp_option_default_priority_list []; extern unsigned char dhcp_option_default_priority_list [];
extern int sizeof_dhcp_option_default_priority_list; extern int sizeof_dhcp_option_default_priority_list;
extern char *hardware_types [256];
extern struct hash_table universe_hash; extern struct hash_table universe_hash;
extern struct universe dhcp_universe; extern struct universe dhcp_universe;
void initialize_universes PROTO ((void)); void initialize_universes PROTO ((void));
@@ -334,12 +339,17 @@ void putUShort PROTO ((unsigned char *, unsigned short));
void putShort PROTO ((unsigned char *, short)); void putShort PROTO ((unsigned char *, short));
/* inet.c */ /* inet.c */
struct iaddr subnet_number (struct iaddr, struct iaddr); struct iaddr subnet_number PROTO ((struct iaddr, struct iaddr));
struct iaddr ip_addr (struct iaddr, struct iaddr, unsigned long); struct iaddr ip_addr PROTO ((struct iaddr, struct iaddr, unsigned long));
unsigned long host_addr (struct iaddr, struct iaddr); unsigned long host_addr PROTO ((struct iaddr, struct iaddr));
int addr_eq (struct iaddr, struct iaddr); int addr_eq PROTO ((struct iaddr, struct iaddr));
char *piaddr (struct iaddr); char *piaddr PROTO ((struct iaddr));
/* dhclient.c */ /* dhclient.c */
void parse_client_statement (FILE *, struct host_decl *); void parse_client_statement PROTO ((FILE *, struct host_decl *));
/* db.c */
int write_lease PROTO ((struct lease *));
int commit_leases PROTO ((void));
void db_startup PROTO ((void));
void new_lease_file PROTO ((void));

View File

@@ -42,7 +42,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"@(#) Copyright (c) 1995 The Internet Software Consortium. All rights reserved.\n"; "@(#) Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -162,8 +162,8 @@ void new_address_range (low, high, subnet)
if (address_range [i].next) if (address_range [i].next)
address_range [i].next -> prev = subnet -> leases; address_range [i].next -> prev = subnet -> leases;
add_hash (lease_ip_addr_hash, add_hash (lease_ip_addr_hash,
(char *)&address_range [i].ip_addr, address_range [i].ip_addr.iabuf,
sizeof address_range [i].ip_addr, address_range [i].ip_addr.len,
(unsigned char *)&address_range [i]); (unsigned char *)&address_range [i]);
} }
@@ -187,7 +187,7 @@ void new_address_range (low, high, subnet)
dangling_leases = lp -> next; dangling_leases = lp -> next;
} }
lp -> next = (struct lease *)0; lp -> next = (struct lease *)0;
supersede_lease (&address_range [lhost - i], lp); supersede_lease (&address_range [lhost - i], lp, 0);
free_lease (lp, "new_address_range"); free_lease (lp, "new_address_range");
} else } else
plp = lp; plp = lp;
@@ -230,6 +230,7 @@ void enter_lease (lease)
/* If we don't have a place for this lease yet, save it for /* If we don't have a place for this lease yet, save it for
later. */ later. */
if (!comp) { if (!comp) {
printf ("didn't find the lease...\n");
comp = new_lease ("enter_lease"); comp = new_lease ("enter_lease");
if (!comp) { if (!comp) {
error ("No memory for lease %s\n", error ("No memory for lease %s\n",
@@ -240,7 +241,8 @@ void enter_lease (lease)
lease -> prev = (struct lease *)0; lease -> prev = (struct lease *)0;
dangling_leases = lease; dangling_leases = lease;
} else { } else {
supersede_lease (comp, lease); printf ("superseding lease...\n");
supersede_lease (comp, lease, 0);
} }
} }
@@ -249,8 +251,9 @@ void enter_lease (lease)
list of leases by expiry time so that we can always find the oldest list of leases by expiry time so that we can always find the oldest
lease. */ lease. */
void supersede_lease (comp, lease) int supersede_lease (comp, lease, commit)
struct lease *comp, *lease; struct lease *comp, *lease;
int commit;
{ {
int enter_uid = 0; int enter_uid = 0;
int enter_hwaddr = 0; int enter_hwaddr = 0;
@@ -402,6 +405,10 @@ void supersede_lease (comp, lease)
comp -> contain -> insertion_point = comp; comp -> contain -> insertion_point = comp;
comp -> ends = lease -> ends; 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. */ /* Release the specified lease and re-hash it as appropriate. */
@@ -413,7 +420,7 @@ void release_lease (lease)
lt = *lease; lt = *lease;
lt.ends = cur_time; lt.ends = cur_time;
supersede_lease (lease, &lt); supersede_lease (lease, &lt, 1);
} }
/* Abandon the specified lease (set its timeout to infinity and its /* Abandon the specified lease (set its timeout to infinity and its
@@ -432,7 +439,7 @@ void abandon_lease (lease)
lt.hardware_addr.hlen = 0; lt.hardware_addr.hlen = 0;
lt.uid = (char *)0; lt.uid = (char *)0;
lt.uid_len = 0; lt.uid_len = 0;
supersede_lease (lease, &lt); supersede_lease (lease, &lt, 1);
} }
/* Locate the lease associated with a given IP address... */ /* Locate the lease associated with a given IP address... */
@@ -504,6 +511,23 @@ struct class *find_class (type, name, len)
return class; return class;
} }
/* Write all interesting leases to permanent storage. */
void write_leases ()
{
struct lease *l;
struct subnet *s;
int i;
for (s = subnets; s; s = s -> next) {
for (l = s -> leases; l; l = l -> next) {
if (l -> hardware_addr.hlen || l -> uid_len)
write_lease (l);
}
}
commit_leases ();
}
void dump_subnets () void dump_subnets ()
{ {
struct lease *l; struct lease *l;

View File

@@ -3,7 +3,8 @@
DHCP options parsing and reassembly. */ DHCP options parsing and reassembly. */
/* /*
* Copyright (c) 1995 The Internet Software Consortium. All rights reserved. * Copyright (c) 1995, 1996 The Internet Software Consortium.
* All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -41,7 +42,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"@(#) Copyright (c) 1995 The Internet Software Consortium. All rights reserved.\n"; "@(#) Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#define DHCP_OPTION_DATA #define DHCP_OPTION_DATA

View File

@@ -70,6 +70,38 @@ void readconf (void)
break; break;
parse_statement (cfile); parse_statement (cfile);
} while (1); } while (1);
token = next_token (&val, cfile);
}
void read_leases (void)
{
FILE *cfile;
char *val;
int token;
jmp_buf bc;
/* Open the lease file... */
if ((cfile = fopen (_PATH_DHCPD_DB, "r")) == NULL)
warn ("Can't open lease database %s: %m", _PATH_DHCPD_DB);
do {
token = next_token (&val, cfile);
printf ("token = %d\n", token);
if (token == EOF)
break;
if (token != LEASE) {
warn ("Corrupt lease file - possible data loss!");
skip_to_semi (cfile);
} else {
if (!setjmp (bc)) {
struct lease *lease;
printf ("Parsing a lease...\n");
lease = parse_lease_statement (cfile, &bc);
enter_lease (lease);
print_lease (lease);
}
}
} while (1);
} }
/* statement :== host_statement */ /* statement :== host_statement */

135
server/db.c Normal file
View File

@@ -0,0 +1,135 @@
/* db.c
Persistent database management routines for DHCPD... */
/*
* Copyright (c) 1995, 1996 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''.
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
FILE *db_file;
/* Write the specified lease to the current lease database file. */
int write_lease (lease)
struct lease *lease;
{
struct tm *t;
char tbuf [64];
errno = 0;
fprintf (db_file, "lease %s\n", piaddr (lease -> ip_addr));
t = gmtime (&lease -> starts);
strftime (tbuf, sizeof tbuf, "%w %Y/%m/%d %H:%M:%S", t);
fprintf (db_file, "\tstarts %s\n", tbuf);
t = gmtime (&lease -> ends);
strftime (tbuf, sizeof tbuf, "%w %Y/%m/%d %H:%M:%S", t);
fprintf (db_file, "\tends %s", tbuf);
if (lease -> hardware_addr.hlen) {
fprintf (db_file, "\n\thardware %s %s",
hardware_types [lease -> hardware_addr.htype],
print_hw_addr (lease -> hardware_addr.htype,
lease -> hardware_addr.hlen,
lease -> hardware_addr.haddr));
}
if (lease -> uid_len) {
int i;
fprintf (db_file, "\n\tuid %x", lease -> uid [0]);
for (i = 1; i < lease -> uid_len; i++)
fprintf (db_file, ":%x", lease -> uid [i]);
}
fputs (";\n", db_file);
return !errno;
}
/* Commit any leases that have been written out... */
int commit_leases ()
{
if (fflush (db_file) == EOF)
return 0;
if (fsync (fileno (db_file)) < 0)
return 0;
return 1;
}
void db_startup ()
{
/* Read in the existing lease file... */
read_leases ();
new_lease_file ();
}
void new_lease_file ()
{
char newfname [512];
char backfname [512];
TIME t;
/* If we already have an open database, close it. */
if (db_file) {
fclose (db_file);
}
/* Make a temporary lease file... */
time (&t);
sprintf (newfname, "%s.%d", _PATH_DHCPD_DB, t & 32767);
if ((db_file = fopen (newfname, "w")) == NULL) {
error ("Can't start new lease file: %m");
}
/* Write out all the leases that we know of... */
write_leases ();
/* Get the old database out of the way... */
sprintf (backfname, "%s~", _PATH_DHCPD_DB);
unlink (backfname);
link (_PATH_DHCPD_DB, backfname);
/* Move in the new file... */
rename (newfname, _PATH_DHCPD_DB);
}

View File

@@ -379,8 +379,12 @@ void ack_lease (packet, lease, offer, when)
/* Record the transaction id... */ /* Record the transaction id... */
lt.xid = packet -> raw -> xid; lt.xid = packet -> raw -> xid;
/* Install the new information about this lease in the database. */ /* Install the new information about this lease in the database.
supersede_lease (lease, &lt); If this is a DHCPACK and we can't write the lease, don't
ACK it either. */
if (!(supersede_lease (lease, &lt, offer == DHCPACK)
|| offer != DHCPACK))
return;
/* Send a response to the client... */ /* Send a response to the client... */

View File

@@ -132,6 +132,9 @@ int main (argc, argv, envp)
/* Read the dhcpd.conf file... */ /* Read the dhcpd.conf file... */
readconf (); readconf ();
/* Start up the database... */
db_startup ();
#if 0 #if 0
/* If addresses were specified on the command line, resolve them; /* If addresses were specified on the command line, resolve them;
otherwise, just get a list of the addresses that are configured otherwise, just get a list of the addresses that are configured

View File

@@ -1,34 +1,7 @@
subnet 204.254.239.0 netmask 255.255.255.0 subnet 204.254.239.0 netmask 255.255.255.0
range 204.254.239.11 204.254.239.17; range 204.254.239.10 204.254.239.20
option subnet-mask 255.255.255.0 option broadcast-address 204.254.239.255
subnet 204.254.240.0 netmask 255.255.255.0 default-lease-time 600 max-lease-time 7200
range 204.254.240.11 204.254.240.12; option routers 204.254.239.1
option domain-name-servers 204.254.239.2
host minuet option domain-name "fugue.com";
hardware ethernet 08:00:2b:35:0c:18
filename "/tftpboot/netbsd.minuet"
fixed-address minuet.fugue.com;
host allegro
hardware ethernet 08:00:2b:1c:07:b6
filename "/tftpboot/netbsd.allegro"
fixed-address allegro.fugue.com;
host fantasia
hardware ethernet 8:0:7:26:c0:a5
fixed-address fantasia.fugue.com
option routers prelude.fugue.com
option name-servers toccata.fugue.com, passacaglia.fugue.com
option domain-name "fugue.com";
host avogadro
hardware ethernet 08:00:2b:4c:39:12
option routers prelude.fugue.com
option name-servers toccata.fugue.com
option domain-name "fugue.com";
lease 204.254.239.11
starts 2 96/2/6 10:14:02
ends 2 96/2/6 11:15:02
hardware ethernet 08:00:2b:4c:39:12
host avogadro;

260
tables.c
View File

@@ -389,6 +389,266 @@ int sizeof_dhcp_option_default_priority_list =
sizeof dhcp_option_default_priority_list; sizeof dhcp_option_default_priority_list;
char *hardware_types [] = {
"unknown-0",
"ethernet",
"unknown-2",
"unknown-3",
"unknown-4",
"unknown-5",
"unknown-6",
"unknown-7",
"unknown-8",
"unknown-9",
"unknown-10",
"unknown-11",
"unknown-12",
"unknown-13",
"unknown-14",
"unknown-15",
"unknown-16",
"unknown-17",
"unknown-18",
"unknown-19",
"unknown-20",
"unknown-21",
"unknown-22",
"unknown-23",
"unknown-24",
"unknown-25",
"unknown-26",
"unknown-27",
"unknown-28",
"unknown-29",
"unknown-30",
"unknown-31",
"unknown-32",
"unknown-33",
"unknown-34",
"unknown-35",
"unknown-36",
"unknown-37",
"unknown-38",
"unknown-39",
"unknown-40",
"unknown-41",
"unknown-42",
"unknown-43",
"unknown-44",
"unknown-45",
"unknown-46",
"unknown-47",
"unknown-48",
"unknown-49",
"unknown-50",
"unknown-51",
"unknown-52",
"unknown-53",
"unknown-54",
"unknown-55",
"unknown-56",
"unknown-57",
"unknown-58",
"unknown-59",
"unknown-60",
"unknown-61",
"unknown-62",
"unknown-63",
"unknown-64",
"unknown-65",
"unknown-66",
"unknown-67",
"unknown-68",
"unknown-69",
"unknown-70",
"unknown-71",
"unknown-72",
"unknown-73",
"unknown-74",
"unknown-75",
"unknown-76",
"unknown-77",
"unknown-78",
"unknown-79",
"unknown-80",
"unknown-81",
"unknown-82",
"unknown-83",
"unknown-84",
"unknown-85",
"unknown-86",
"unknown-87",
"unknown-88",
"unknown-89",
"unknown-90",
"unknown-91",
"unknown-92",
"unknown-93",
"unknown-94",
"unknown-95",
"unknown-96",
"unknown-97",
"unknown-98",
"unknown-99",
"unknown-100",
"unknown-101",
"unknown-102",
"unknown-103",
"unknown-104",
"unknown-105",
"unknown-106",
"unknown-107",
"unknown-108",
"unknown-109",
"unknown-110",
"unknown-111",
"unknown-112",
"unknown-113",
"unknown-114",
"unknown-115",
"unknown-116",
"unknown-117",
"unknown-118",
"unknown-119",
"unknown-120",
"unknown-121",
"unknown-122",
"unknown-123",
"unknown-124",
"unknown-125",
"unknown-126",
"unknown-127",
"unknown-128",
"unknown-129",
"unknown-130",
"unknown-131",
"unknown-132",
"unknown-133",
"unknown-134",
"unknown-135",
"unknown-136",
"unknown-137",
"unknown-138",
"unknown-139",
"unknown-140",
"unknown-141",
"unknown-142",
"unknown-143",
"unknown-144",
"unknown-145",
"unknown-146",
"unknown-147",
"unknown-148",
"unknown-149",
"unknown-150",
"unknown-151",
"unknown-152",
"unknown-153",
"unknown-154",
"unknown-155",
"unknown-156",
"unknown-157",
"unknown-158",
"unknown-159",
"unknown-160",
"unknown-161",
"unknown-162",
"unknown-163",
"unknown-164",
"unknown-165",
"unknown-166",
"unknown-167",
"unknown-168",
"unknown-169",
"unknown-170",
"unknown-171",
"unknown-172",
"unknown-173",
"unknown-174",
"unknown-175",
"unknown-176",
"unknown-177",
"unknown-178",
"unknown-179",
"unknown-180",
"unknown-181",
"unknown-182",
"unknown-183",
"unknown-184",
"unknown-185",
"unknown-186",
"unknown-187",
"unknown-188",
"unknown-189",
"unknown-190",
"unknown-191",
"unknown-192",
"unknown-193",
"unknown-194",
"unknown-195",
"unknown-196",
"unknown-197",
"unknown-198",
"unknown-199",
"unknown-200",
"unknown-201",
"unknown-202",
"unknown-203",
"unknown-204",
"unknown-205",
"unknown-206",
"unknown-207",
"unknown-208",
"unknown-209",
"unknown-210",
"unknown-211",
"unknown-212",
"unknown-213",
"unknown-214",
"unknown-215",
"unknown-216",
"unknown-217",
"unknown-218",
"unknown-219",
"unknown-220",
"unknown-221",
"unknown-222",
"unknown-223",
"unknown-224",
"unknown-225",
"unknown-226",
"unknown-227",
"unknown-228",
"unknown-229",
"unknown-230",
"unknown-231",
"unknown-232",
"unknown-233",
"unknown-234",
"unknown-235",
"unknown-236",
"unknown-237",
"unknown-238",
"unknown-239",
"unknown-240",
"unknown-241",
"unknown-242",
"unknown-243",
"unknown-244",
"unknown-245",
"unknown-246",
"unknown-247",
"unknown-248",
"unknown-249",
"unknown-250",
"unknown-251",
"unknown-252",
"unknown-253",
"unknown-254",
"unknown-255" };
struct hash_table universe_hash; struct hash_table universe_hash;
void initialize_universes() void initialize_universes()