From: Ted Lemon Date: Sat, 2 Mar 1996 05:13:36 +0000 (+0000) Subject: Keep a persistent database of leases X-Git-Tag: SS960301~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1358b874479b9f6989cdcfc6ef8369fc8efb21ac;p=thirdparty%2Fdhcp.git Keep a persistent database of leases --- diff --git a/Makefile b/Makefile index c90b3043b..373cc0192 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ 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 \ - hash.c tables.c inet.c + hash.c tables.c inet.c db.c PROG = dhcpd 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 \ 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 \ hash.o tables.o inet.o convert.o conflex.o errwarn.o \ - print.o tree.o \ No newline at end of file + print.o tree.o db.o \ No newline at end of file diff --git a/common/memory.c b/common/memory.c index ac33d50b7..b0e48cad5 100644 --- a/common/memory.c +++ b/common/memory.c @@ -42,7 +42,7 @@ #ifndef lint 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 */ #include "dhcpd.h" @@ -162,8 +162,8 @@ void new_address_range (low, high, subnet) if (address_range [i].next) address_range [i].next -> prev = subnet -> leases; add_hash (lease_ip_addr_hash, - (char *)&address_range [i].ip_addr, - sizeof address_range [i].ip_addr, + address_range [i].ip_addr.iabuf, + address_range [i].ip_addr.len, (unsigned char *)&address_range [i]); } @@ -187,7 +187,7 @@ void new_address_range (low, high, subnet) dangling_leases = lp -> next; } 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"); } else plp = lp; @@ -230,6 +230,7 @@ void enter_lease (lease) /* If we don't have a place for this lease yet, save it for later. */ if (!comp) { +printf ("didn't find the lease...\n"); comp = new_lease ("enter_lease"); if (!comp) { error ("No memory for lease %s\n", @@ -240,7 +241,8 @@ void enter_lease (lease) lease -> prev = (struct lease *)0; dangling_leases = lease; } 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 lease. */ -void supersede_lease (comp, lease) +int supersede_lease (comp, lease, commit) struct lease *comp, *lease; + int commit; { int enter_uid = 0; int enter_hwaddr = 0; @@ -402,6 +405,10 @@ void supersede_lease (comp, lease) comp -> contain -> 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. */ @@ -413,7 +420,7 @@ void release_lease (lease) lt = *lease; lt.ends = cur_time; - supersede_lease (lease, <); + supersede_lease (lease, <, 1); } /* 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.uid = (char *)0; lt.uid_len = 0; - supersede_lease (lease, <); + supersede_lease (lease, <, 1); } /* Locate the lease associated with a given IP address... */ @@ -504,6 +511,23 @@ struct class *find_class (type, name, len) 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 () { struct lease *l; diff --git a/common/options.c b/common/options.c index 7c860727e..a5ff795a9 100644 --- a/common/options.c +++ b/common/options.c @@ -3,7 +3,8 @@ 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 * modification, are permitted provided that the following conditions @@ -41,7 +42,7 @@ #ifndef lint 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 */ #define DHCP_OPTION_DATA diff --git a/common/tables.c b/common/tables.c index ada34a6a3..5b79b1458 100644 --- a/common/tables.c +++ b/common/tables.c @@ -389,6 +389,266 @@ int 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; void initialize_universes() diff --git a/confpars.c b/confpars.c index 6f850448e..f3cf4f30d 100644 --- a/confpars.c +++ b/confpars.c @@ -70,6 +70,38 @@ void readconf (void) break; parse_statement (cfile); } 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 */ diff --git a/db.c b/db.c new file mode 100644 index 000000000..e7f348d2d --- /dev/null +++ b/db.c @@ -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 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); +} diff --git a/dhcp.c b/dhcp.c index 29e49cf75..e418da6d2 100644 --- a/dhcp.c +++ b/dhcp.c @@ -379,8 +379,12 @@ void ack_lease (packet, lease, offer, when) /* Record the transaction id... */ lt.xid = packet -> raw -> xid; - /* Install the new information about this lease in the database. */ - supersede_lease (lease, <); + /* Install the new information about this lease in the database. + If this is a DHCPACK and we can't write the lease, don't + ACK it either. */ + if (!(supersede_lease (lease, <, offer == DHCPACK) + || offer != DHCPACK)) + return; /* Send a response to the client... */ diff --git a/dhcp.h b/dhcp.h index ac88e393d..8bee3732f 100644 --- a/dhcp.h +++ b/dhcp.h @@ -63,8 +63,8 @@ struct dhcp_packet { struct in_addr siaddr; /* IP address of next server to talk to */ struct in_addr giaddr; /* DHCP relay agent IP address */ char chaddr [16]; /* Client hardware address */ - char sname [64]; /* Server name */ - char file [128]; /* Boot filename */ + char sname [DHCP_SNAME_LEN]; /* Server name */ + char file [DHCP_FILE_LEN]; /* Boot filename */ unsigned char options [DHCP_OPTION_LEN]; /* Optional parameters (actual length dependent on MTU). */ diff --git a/dhcpd.c b/dhcpd.c index 85d0f5b17..f0452b498 100644 --- a/dhcpd.c +++ b/dhcpd.c @@ -132,6 +132,9 @@ int main (argc, argv, envp) /* Read the dhcpd.conf file... */ readconf (); + /* Start up the database... */ + db_startup (); + #if 0 /* If addresses were specified on the command line, resolve them; otherwise, just get a list of the addresses that are configured diff --git a/dhcpd.conf b/dhcpd.conf index 53c657f69..b14de2d4d 100644 --- a/dhcpd.conf +++ b/dhcpd.conf @@ -1,34 +1,7 @@ subnet 204.254.239.0 netmask 255.255.255.0 - range 204.254.239.11 204.254.239.17; - -subnet 204.254.240.0 netmask 255.255.255.0 - range 204.254.240.11 204.254.240.12; - -host minuet - 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; + range 204.254.239.10 204.254.239.20 + option subnet-mask 255.255.255.0 option broadcast-address 204.254.239.255 + default-lease-time 600 max-lease-time 7200 + option routers 204.254.239.1 + option domain-name-servers 204.254.239.2 + option domain-name "fugue.com"; diff --git a/dhcpd.h b/dhcpd.h index 4d1863e51..0ff116df3 100644 --- a/dhcpd.h +++ b/dhcpd.h @@ -154,8 +154,10 @@ typedef unsigned char option_mask [16]; #ifndef _PATH_DHCPD_CONF #ifdef DEBUG #define _PATH_DHCPD_CONF "dhcpd.conf" +#define _PATH_DHCPD_DB "dhcpd.leases" #else #define _PATH_DHCPD_CONF "/etc/dhcpd.conf" +#define _PATH_DHCPD_CONF "/etc/dhcpd.leases" #endif #endif @@ -170,12 +172,12 @@ void parse_options PROTO ((struct packet *)); void parse_option_buffer PROTO ((struct packet *, unsigned char *, int)); void cons_options PROTO ((struct packet *, struct packet *, struct tree_cache **, int)); -void new_cons_options PROTO ((struct packet *, struct packet *, - struct tree_cache **, int)); +/* void new_cons_options PROTO ((struct packet *, struct packet *, + struct tree_cache **, int)); */ int store_options PROTO ((unsigned char *, int, struct tree_cache **, - unsigned char *, int)); -int store_option PROTO ((struct tree_cache **, unsigned char, - unsigned char *, int, int *)); + unsigned char *, int, int, int)); +/* int store_option PROTO ((struct tree_cache **, unsigned char, + unsigned char *, int, int *)); */ char *pretty_print_option PROTO ((unsigned char, unsigned char *, int)); /* errwarn.c */ @@ -209,6 +211,7 @@ int peek_token PROTO ((char **, FILE *)); /* confpars.c */ void readconf PROTO ((void)); +void read_leases PROTO ((void)); void parse_statement PROTO ((FILE *)); void skip_to_semi PROTO ((FILE *)); 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); void enter_subnet (struct subnet *); 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 abandon_lease PROTO ((struct lease *)); 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 class *add_class PROTO ((int, char *)); struct class *find_class PROTO ((int, char *, int)); +void write_leases PROTO ((void)); void dump_subnets PROTO ((void)); /* alloc.c */ @@ -319,6 +323,7 @@ unsigned char *hash_lookup PROTO ((struct hash_table *, char *, int)); extern struct option dhcp_options [256]; extern unsigned char 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 universe dhcp_universe; void initialize_universes PROTO ((void)); @@ -334,12 +339,17 @@ void putUShort PROTO ((unsigned char *, unsigned short)); void putShort PROTO ((unsigned char *, short)); /* inet.c */ -struct iaddr subnet_number (struct iaddr, struct iaddr); -struct iaddr ip_addr (struct iaddr, struct iaddr, unsigned long); -unsigned long host_addr (struct iaddr, struct iaddr); -int addr_eq (struct iaddr, struct iaddr); -char *piaddr (struct iaddr); +struct iaddr subnet_number PROTO ((struct iaddr, struct iaddr)); +struct iaddr ip_addr PROTO ((struct iaddr, struct iaddr, unsigned long)); +unsigned long host_addr PROTO ((struct iaddr, struct iaddr)); +int addr_eq PROTO ((struct iaddr, struct iaddr)); +char *piaddr PROTO ((struct iaddr)); /* 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)); diff --git a/includes/dhcp.h b/includes/dhcp.h index ac88e393d..8bee3732f 100644 --- a/includes/dhcp.h +++ b/includes/dhcp.h @@ -63,8 +63,8 @@ struct dhcp_packet { struct in_addr siaddr; /* IP address of next server to talk to */ struct in_addr giaddr; /* DHCP relay agent IP address */ char chaddr [16]; /* Client hardware address */ - char sname [64]; /* Server name */ - char file [128]; /* Boot filename */ + char sname [DHCP_SNAME_LEN]; /* Server name */ + char file [DHCP_FILE_LEN]; /* Boot filename */ unsigned char options [DHCP_OPTION_LEN]; /* Optional parameters (actual length dependent on MTU). */ diff --git a/includes/dhcpd.h b/includes/dhcpd.h index 4d1863e51..0ff116df3 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -154,8 +154,10 @@ typedef unsigned char option_mask [16]; #ifndef _PATH_DHCPD_CONF #ifdef DEBUG #define _PATH_DHCPD_CONF "dhcpd.conf" +#define _PATH_DHCPD_DB "dhcpd.leases" #else #define _PATH_DHCPD_CONF "/etc/dhcpd.conf" +#define _PATH_DHCPD_CONF "/etc/dhcpd.leases" #endif #endif @@ -170,12 +172,12 @@ void parse_options PROTO ((struct packet *)); void parse_option_buffer PROTO ((struct packet *, unsigned char *, int)); void cons_options PROTO ((struct packet *, struct packet *, struct tree_cache **, int)); -void new_cons_options PROTO ((struct packet *, struct packet *, - struct tree_cache **, int)); +/* void new_cons_options PROTO ((struct packet *, struct packet *, + struct tree_cache **, int)); */ int store_options PROTO ((unsigned char *, int, struct tree_cache **, - unsigned char *, int)); -int store_option PROTO ((struct tree_cache **, unsigned char, - unsigned char *, int, int *)); + unsigned char *, int, int, int)); +/* int store_option PROTO ((struct tree_cache **, unsigned char, + unsigned char *, int, int *)); */ char *pretty_print_option PROTO ((unsigned char, unsigned char *, int)); /* errwarn.c */ @@ -209,6 +211,7 @@ int peek_token PROTO ((char **, FILE *)); /* confpars.c */ void readconf PROTO ((void)); +void read_leases PROTO ((void)); void parse_statement PROTO ((FILE *)); void skip_to_semi PROTO ((FILE *)); 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); void enter_subnet (struct subnet *); 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 abandon_lease PROTO ((struct lease *)); 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 class *add_class PROTO ((int, char *)); struct class *find_class PROTO ((int, char *, int)); +void write_leases PROTO ((void)); void dump_subnets PROTO ((void)); /* alloc.c */ @@ -319,6 +323,7 @@ unsigned char *hash_lookup PROTO ((struct hash_table *, char *, int)); extern struct option dhcp_options [256]; extern unsigned char 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 universe dhcp_universe; void initialize_universes PROTO ((void)); @@ -334,12 +339,17 @@ void putUShort PROTO ((unsigned char *, unsigned short)); void putShort PROTO ((unsigned char *, short)); /* inet.c */ -struct iaddr subnet_number (struct iaddr, struct iaddr); -struct iaddr ip_addr (struct iaddr, struct iaddr, unsigned long); -unsigned long host_addr (struct iaddr, struct iaddr); -int addr_eq (struct iaddr, struct iaddr); -char *piaddr (struct iaddr); +struct iaddr subnet_number PROTO ((struct iaddr, struct iaddr)); +struct iaddr ip_addr PROTO ((struct iaddr, struct iaddr, unsigned long)); +unsigned long host_addr PROTO ((struct iaddr, struct iaddr)); +int addr_eq PROTO ((struct iaddr, struct iaddr)); +char *piaddr PROTO ((struct iaddr)); /* 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)); diff --git a/memory.c b/memory.c index ac33d50b7..b0e48cad5 100644 --- a/memory.c +++ b/memory.c @@ -42,7 +42,7 @@ #ifndef lint 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 */ #include "dhcpd.h" @@ -162,8 +162,8 @@ void new_address_range (low, high, subnet) if (address_range [i].next) address_range [i].next -> prev = subnet -> leases; add_hash (lease_ip_addr_hash, - (char *)&address_range [i].ip_addr, - sizeof address_range [i].ip_addr, + address_range [i].ip_addr.iabuf, + address_range [i].ip_addr.len, (unsigned char *)&address_range [i]); } @@ -187,7 +187,7 @@ void new_address_range (low, high, subnet) dangling_leases = lp -> next; } 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"); } else plp = lp; @@ -230,6 +230,7 @@ void enter_lease (lease) /* If we don't have a place for this lease yet, save it for later. */ if (!comp) { +printf ("didn't find the lease...\n"); comp = new_lease ("enter_lease"); if (!comp) { error ("No memory for lease %s\n", @@ -240,7 +241,8 @@ void enter_lease (lease) lease -> prev = (struct lease *)0; dangling_leases = lease; } 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 lease. */ -void supersede_lease (comp, lease) +int supersede_lease (comp, lease, commit) struct lease *comp, *lease; + int commit; { int enter_uid = 0; int enter_hwaddr = 0; @@ -402,6 +405,10 @@ void supersede_lease (comp, lease) comp -> contain -> 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. */ @@ -413,7 +420,7 @@ void release_lease (lease) lt = *lease; lt.ends = cur_time; - supersede_lease (lease, <); + supersede_lease (lease, <, 1); } /* 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.uid = (char *)0; lt.uid_len = 0; - supersede_lease (lease, <); + supersede_lease (lease, <, 1); } /* Locate the lease associated with a given IP address... */ @@ -504,6 +511,23 @@ struct class *find_class (type, name, len) 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 () { struct lease *l; diff --git a/options.c b/options.c index 7c860727e..a5ff795a9 100644 --- a/options.c +++ b/options.c @@ -3,7 +3,8 @@ 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 * modification, are permitted provided that the following conditions @@ -41,7 +42,7 @@ #ifndef lint 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 */ #define DHCP_OPTION_DATA diff --git a/server/confpars.c b/server/confpars.c index 6f850448e..f3cf4f30d 100644 --- a/server/confpars.c +++ b/server/confpars.c @@ -70,6 +70,38 @@ void readconf (void) break; parse_statement (cfile); } 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 */ diff --git a/server/db.c b/server/db.c new file mode 100644 index 000000000..e7f348d2d --- /dev/null +++ b/server/db.c @@ -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 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); +} diff --git a/server/dhcp.c b/server/dhcp.c index 29e49cf75..e418da6d2 100644 --- a/server/dhcp.c +++ b/server/dhcp.c @@ -379,8 +379,12 @@ void ack_lease (packet, lease, offer, when) /* Record the transaction id... */ lt.xid = packet -> raw -> xid; - /* Install the new information about this lease in the database. */ - supersede_lease (lease, <); + /* Install the new information about this lease in the database. + If this is a DHCPACK and we can't write the lease, don't + ACK it either. */ + if (!(supersede_lease (lease, <, offer == DHCPACK) + || offer != DHCPACK)) + return; /* Send a response to the client... */ diff --git a/server/dhcpd.c b/server/dhcpd.c index 85d0f5b17..f0452b498 100644 --- a/server/dhcpd.c +++ b/server/dhcpd.c @@ -132,6 +132,9 @@ int main (argc, argv, envp) /* Read the dhcpd.conf file... */ readconf (); + /* Start up the database... */ + db_startup (); + #if 0 /* If addresses were specified on the command line, resolve them; otherwise, just get a list of the addresses that are configured diff --git a/server/dhcpd.conf b/server/dhcpd.conf index 53c657f69..b14de2d4d 100644 --- a/server/dhcpd.conf +++ b/server/dhcpd.conf @@ -1,34 +1,7 @@ subnet 204.254.239.0 netmask 255.255.255.0 - range 204.254.239.11 204.254.239.17; - -subnet 204.254.240.0 netmask 255.255.255.0 - range 204.254.240.11 204.254.240.12; - -host minuet - 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; + range 204.254.239.10 204.254.239.20 + option subnet-mask 255.255.255.0 option broadcast-address 204.254.239.255 + default-lease-time 600 max-lease-time 7200 + option routers 204.254.239.1 + option domain-name-servers 204.254.239.2 + option domain-name "fugue.com"; diff --git a/tables.c b/tables.c index ada34a6a3..5b79b1458 100644 --- a/tables.c +++ b/tables.c @@ -389,6 +389,266 @@ int 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; void initialize_universes()