]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
DHCP Server Daemon
authorTed Lemon <source@isc.org>
Wed, 29 Nov 1995 07:40:04 +0000 (07:40 +0000)
committerTed Lemon <source@isc.org>
Wed, 29 Nov 1995 07:40:04 +0000 (07:40 +0000)
64 files changed:
Design [new file with mode: 0644]
Makefile [new file with mode: 0644]
alloc.c [new file with mode: 0644]
bootp.c [new file with mode: 0644]
cdefs.h [new file with mode: 0644]
cf/bsdos.h [new file with mode: 0644]
cf/netbsd.h [new file with mode: 0644]
cf/sunos4.h [new file with mode: 0644]
common/alloc.c [new file with mode: 0644]
common/conflex.c [new file with mode: 0644]
common/convert.c [new file with mode: 0644]
common/errwarn.c [new file with mode: 0644]
common/hash.c [new file with mode: 0644]
common/memory.c [new file with mode: 0644]
common/options.c [new file with mode: 0644]
common/print.c [new file with mode: 0644]
common/socket.c [new file with mode: 0644]
common/tables.c [new file with mode: 0644]
common/tree.c [new file with mode: 0644]
conf.y [new file with mode: 0644]
conflex.c [new file with mode: 0644]
confpars.c [new file with mode: 0644]
convert.c [new file with mode: 0644]
db.c [new file with mode: 0644]
dhcp.c [new file with mode: 0644]
dhcp.h [new file with mode: 0644]
dhcpd.c [new file with mode: 0644]
dhcpd.conf [new file with mode: 0644]
dhcpd.h [new file with mode: 0644]
dhctoken.h [new file with mode: 0644]
doc/dhc-minutes-94dec.txt [new file with mode: 0644]
doc/dns-minutes-93nov.txt [new file with mode: 0644]
doc/draft-ietf-dhc-dhcp-03.txt [new file with mode: 0644]
doc/draft-ietf-dhc-options-1533update-01.txt [new file with mode: 0644]
doc/draft-ietf-dnsind-dynDNS-00.txt [new file with mode: 0644]
doc/draft-ohta-dynamic-dns-00.txt [new file with mode: 0644]
doc/rfc1533.txt [new file with mode: 0644]
errwarn.c [new file with mode: 0644]
hash.c [new file with mode: 0644]
hash.h [new file with mode: 0644]
includes/cdefs.h [new file with mode: 0644]
includes/cf/bsdos.h [new file with mode: 0644]
includes/cf/netbsd.h [new file with mode: 0644]
includes/cf/sunos4.h [new file with mode: 0644]
includes/dhcp.h [new file with mode: 0644]
includes/dhcpd.h [new file with mode: 0644]
includes/dhctoken.h [new file with mode: 0644]
includes/hash.h [new file with mode: 0644]
includes/osdep.h [new file with mode: 0644]
includes/tree.h [new file with mode: 0644]
memory.c [new file with mode: 0644]
options.c [new file with mode: 0644]
osdep.h [new file with mode: 0644]
print.c [new file with mode: 0644]
server/bootp.c [new file with mode: 0644]
server/confpars.c [new file with mode: 0644]
server/db.c [new file with mode: 0644]
server/dhcp.c [new file with mode: 0644]
server/dhcpd.c [new file with mode: 0644]
server/dhcpd.conf [new file with mode: 0644]
socket.c [new file with mode: 0644]
tables.c [new file with mode: 0644]
tree.c [new file with mode: 0644]
tree.h [new file with mode: 0644]

diff --git a/Design b/Design
new file mode 100644 (file)
index 0000000..59be2fd
--- /dev/null
+++ b/Design
@@ -0,0 +1,78 @@
+Objects that need to be tracked:
+
+Node Names
+       - A node name is the name of a node attached to a network.
+       - Nodes can be any type of hardware that is attached to a
+         network and requires one or more addresses.
+       - Node names may be associated with a specific hardware
+         address or set of hardware addresses.
+       - Node names may also be associated with a specific IP address
+         or set of IP addresses.
+
+Interfaces
+       - An interface is known by its hardware address, which must be
+         unique.   This works for Ethernet, but may be complicated by
+         PPP (?).   What about IBM token ring and FDDI?
+       - An interface may be associated with a specific node name,
+         a specific address, or both.
+
+IP Addresses
+       - An interface may be associated with a single IP address.
+         4.4BSD supports IP aliasing so that a single interface can
+         have multiple addresses, but this probably isn't worth
+         supporting explicitly.
+
+Transitions
+       - A machine may be moved to a different net
+         - If the machine's personality hasn't changed, we may want
+           to assign it a new IP address but keep the same node name.
+         - If the machine's personality *has* changed, we need to
+           assign it both a new node name and a new IP address.
+       - A machine's hardware may be upgraded.
+         - The new machine should get the old IP Address and Node Name.
+         - The old machine may need a new IP address and Node Name.
+
+Static Configuration File
+       - Addresses which server may assign to arbitrary hosts
+       - Addresses which are statically assigned to particular
+         hardware, but which server may need to provide
+       - Allowable lease length for a given address
+
+Dynamic Server Database
+       - Addresses which have been dynamically assigned
+       - The hardware addresses to which they have been assigned
+       - The lease expiry time on each assigned address
+
+Sample static configuration file:
+
+# One 12-bit subnet, may assign addresses 240 through 4190.
+network 16.3.16.0 netmask 255.255.240.0
+       address-range 240 through 4190;
+# One 4-bit subnet, may assign addresses 2 through 6.
+network 192.5.5.16 netmask 255.255.255.240
+       address-range 192.5.5.2 through 192.5.5.6;
+# 16 12-bit subnets, may assign addresses 128 through 4190 of each network.
+# Address ranges are shared with listed servers [TBI].
+networks 16.1.0.0 through 16.1.240.0 netmask 255.255.240.0
+       address-range 0.128 through 31.240
+       shared-with dhcp-1.pa.dec.com, dhcp-2.pa.dec.com, dhcp-3.pa.dec.com;
+
+
+
+Sample database file:
+
+# January 12, 1996, 16:42:37
+timestamp 1049897235;
+lease 204.254.239.7 starts 1049897235 ends 1049957235
+       hardware ethernet 08:00:2b:4c:29:35
+       uid 08:00:2b:4c:29:35 host minuet class decstations;
+lease 204.254.239.8 starts 1049897235 ends 1049957235
+       hardware ethernet 08:00:2b:22:09:27 
+       uid 08:00:2b:22:09:27 class decstations;
+lease 204.254.239.9 starts 1049897235 ends 1049957235
+       hardware ethernet 08:00:42:29:09:42
+       uid 08:00:42:29:09:42;
+lease 204.254.239.240 starts 1049897235 ends 1049957235
+       uid 50:50:50:3a:6b:69:6d:62:61 host kimba-ppp;
+
+
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..e4a4add
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,8 @@
+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
+PROG = dhcpd
+
+.include <bsd.prog.mk>
+
+CFLAGS += -DDEBUG -g
diff --git a/alloc.c b/alloc.c
new file mode 100644 (file)
index 0000000..9dbeadb
--- /dev/null
+++ b/alloc.c
@@ -0,0 +1,197 @@
+/* alloc.c
+
+   Memory allocation...
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+struct dhcp_packet *dhcp_free_list;
+struct packet *packet_free_list;
+
+VOIDPTR dmalloc (size, name)
+       int size;
+       char *name;
+{
+       VOIDPTR foo = (VOIDPTR)malloc (size);
+       if (!foo)
+               warn ("No memory for %s.\n");
+       return foo;
+}
+
+void dfree (ptr, name)
+       VOIDPTR ptr;
+       char *name;
+{
+       free (ptr);
+}
+
+struct packet *new_packet (name)
+       char *name;
+{
+       struct packet *rval;
+       rval = (struct packet *)dmalloc (sizeof (struct packet), name);
+       return rval;
+}
+
+struct dhcp_packet *new_dhcp_packet (name)
+       char *name;
+{
+       struct dhcp_packet *rval;
+       rval = (struct dhcp_packet *)dmalloc (sizeof (struct dhcp_packet),
+                                             name);
+       return rval;
+}
+
+struct tree *new_tree (name)
+       char *name;
+{
+       struct tree *rval = dmalloc (sizeof (struct tree), name);
+       return rval;
+}
+
+struct tree_cache *new_tree_cache (name)
+       char *name;
+{
+       struct tree_cache *rval = dmalloc (sizeof (struct tree_cache), name);
+       return rval;
+}
+
+struct hash_table *new_hash_table (count, name)
+       int count;
+       char *name;
+{
+       struct hash_table *rval = dmalloc (sizeof (struct hash_table)
+                                          - (DEFAULT_HASH_SIZE
+                                             * sizeof (struct hash_bucket *))
+                                          + (count
+                                             * sizeof (struct hash_bucket *)),
+                                          name);
+       rval -> hash_count = count;
+       return rval;
+}
+
+struct hash_bucket *new_hash_bucket (name)
+       char *name;
+{
+       struct hash_bucket *rval = dmalloc (sizeof (struct hash_bucket), name);
+       return rval;
+}
+
+struct lease *new_leases (n, name)
+       int n;
+       char *name;
+{
+       struct lease *rval = dmalloc (n * sizeof (struct lease), name);
+       return rval;
+}
+
+struct lease *new_lease (name)
+       char *name;
+{
+       struct lease *rval = dmalloc (sizeof (struct lease), name);
+       return rval;
+}
+
+struct subnet *new_subnet (name)
+       char *name;
+{
+       struct subnet *rval = dmalloc (sizeof (struct subnet), name);
+       return rval;
+}
+
+void free_subnet (ptr, name)
+       struct subnet *ptr;
+       char *name;
+{
+       dfree ((VOIDPTR)ptr, name);
+}
+
+void free_lease (ptr, name)
+       struct lease *ptr;
+       char *name;
+{
+       dfree ((VOIDPTR)ptr, name);
+}
+
+void free_hash_bucket (ptr, name)
+       struct hash_bucket *ptr;
+       char *name;
+{
+       dfree ((VOIDPTR)ptr, name);
+}
+
+void free_hash_table (ptr, name)
+       struct hash_table *ptr;
+       char *name;
+{
+       dfree ((VOIDPTR)ptr, name);
+}
+
+void free_tree_cache (ptr, name)
+       struct tree_cache *ptr;
+       char *name;
+{
+       dfree ((VOIDPTR)ptr, name);
+}
+
+void free_packet (ptr, name)
+       struct packet *ptr;
+       char *name;
+{
+       dfree ((VOIDPTR)ptr, name);
+}
+
+void free_dhcp_packet (ptr, name)
+       struct dhcp_packet *ptr;
+       char *name;
+{
+       dfree ((VOIDPTR)ptr, name);
+}
+
+void free_tree (ptr, name)
+       struct tree *ptr;
+       char *name;
+{
+       dfree ((VOIDPTR)ptr, name);
+}
diff --git a/bootp.c b/bootp.c
new file mode 100644 (file)
index 0000000..6f5d1a5
--- /dev/null
+++ b/bootp.c
@@ -0,0 +1,147 @@
+/* bootp.c
+
+   BOOTP Protocol support. */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+void bootp (packet)
+       struct packet *packet;
+{
+       int result;
+       struct host_decl *hp = find_host_by_addr (packet -> raw -> htype,
+                                                 packet -> raw -> chaddr,
+                                                 packet -> raw -> hlen);
+       struct dhcp_packet *reply;
+       struct sockaddr_in to;
+
+       /* If the packet is from a host we don't know, drop it on
+          the floor. XXX */
+       if (!hp) {
+               note ("Can't find record for BOOTP host %s",
+                     print_hw_addr (packet -> raw -> htype,
+                                    packet -> raw -> hlen,
+                                    packet -> raw -> chaddr));
+               return;
+       }
+       /* If we don't have a fixed address for it, drop it on the floor.
+          XXX */
+       if (!hp -> fixed_addr || !tree_evaluate (hp -> fixed_addr)) {
+               note ("No fixed address for BOOTP host %s (%s)",
+                     print_hw_addr (packet -> raw -> htype,
+                                    packet -> raw -> hlen,
+                                    packet -> raw -> chaddr),
+                     hp -> name);
+               return;
+       }
+       reply = new_dhcp_packet ("bootp");
+       if (!reply) {
+               free_dhcp_packet (packet -> raw, "bootp");
+               free_packet (packet, "bootp");
+               return;
+       }
+       /* Take the fields that we care about... */
+       reply -> op = BOOTREPLY;
+       reply -> htype = packet -> raw -> htype;
+       reply -> hlen = packet -> raw -> hlen;
+       memcpy (reply -> chaddr, packet -> raw -> chaddr, reply -> hlen);
+       memset (&reply -> chaddr [reply -> hlen], 0,
+               (sizeof reply -> chaddr) - reply -> hlen);
+       reply -> hops = packet -> raw -> hops;
+       reply -> xid = packet -> raw -> xid;
+       reply -> secs = packet -> raw -> secs;
+       reply -> flags = 0;
+       reply -> ciaddr = packet -> raw -> ciaddr;
+       if (!tree_evaluate (hp -> fixed_addr))
+               warn ("tree_evaluate failed.");
+       debug ("fixed_addr: %x %d %d %d %d %x",
+              *(int *)(hp -> fixed_addr -> value), hp -> fixed_addr -> len,
+              hp -> fixed_addr -> buf_size, hp -> fixed_addr -> timeout,
+              hp -> fixed_addr -> tree);
+       memcpy (&reply -> yiaddr, hp -> fixed_addr -> value,
+               sizeof reply -> yiaddr);
+       reply -> siaddr.s_addr = pick_interface (packet);
+       reply -> giaddr = packet -> raw -> giaddr;
+       if (hp -> server_name) {
+               strncpy (reply -> sname, hp -> server_name,
+                        (sizeof reply -> sname) - 1);
+               reply -> sname [(sizeof reply -> sname) - 1] = 0;
+       }
+       if (hp -> filename) {
+               strncpy (reply -> file, hp -> filename,
+                        (sizeof reply -> file) - 1);
+               reply -> file [(sizeof reply -> file) - 1] = 0;
+       }
+       reply -> options [0] = 0;
+       /* XXX gateways? */
+       to.sin_port = server_port;
+
+#if 0
+       if (packet -> raw -> flags & BOOTP_BROADCAST)
+#endif
+               to.sin_addr.s_addr = INADDR_BROADCAST;
+#if 0
+       else
+               to.sin_addr.s_addr = INADDR_ANY;
+#endif
+
+       memset (reply -> options, 0, sizeof (reply -> options));
+       /* If we got the magic cookie, send it back. */
+       if (packet -> options_valid)
+               memcpy (reply -> options, packet -> raw -> options, 4);
+       to.sin_port = packet -> client.sin_port;
+       to.sin_family = AF_INET;
+       to.sin_len = sizeof to;
+       memset (to.sin_zero, 0, sizeof to.sin_zero);
+
+       note ("Sending bootp reply to %s, port %d",
+             inet_ntoa (to.sin_addr), htons (to.sin_port));
+
+       errno = 0;
+       result = sendto (packet -> client_sock, reply,
+                        ((char *)(&reply -> options) - (char *)reply) + 64,
+                        0, (struct sockaddr *)&to, sizeof to);
+       if (result < 0)
+               warn ("sendto: %m");
+}
diff --git a/cdefs.h b/cdefs.h
new file mode 100644 (file)
index 0000000..4b94c99
--- /dev/null
+++ b/cdefs.h
@@ -0,0 +1,49 @@
+/* cdefs.h
+
+   Standard C definitions... */
+
+/*
+ * Copyright (c) 1995 RadioMail Corporation.  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 RadioMail Corporation 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 RADIOMAIL CORPORATION 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
+ * RADIOMAIL CORPORATION 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 was written for RadioMail Corporation by Ted Lemon
+ * under a contract with Vixie Enterprises, and is based on an earlier
+ * design by Paul Vixie.
+ */
+
+#if defined (__GNUC__) || defined (__STDC__)
+#define PROTO(x)       x
+#define KandR(x)
+#define ANSI_DECL(x)   x
+#define INLINE         inline
+#else
+#define PROTO(x)       ()
+#define KandR(x)       x
+#define ANSI_DECL(x)
+#define INLINE
+#endif
diff --git a/cf/bsdos.h b/cf/bsdos.h
new file mode 100644 (file)
index 0000000..bdac405
--- /dev/null
@@ -0,0 +1,106 @@
+/* bsdos.h
+
+   System dependencies for BSD/os... */
+
+/*
+ * Copyright (c) 1995 RadioMail Corporation.  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 RadioMail Corporation 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 RADIOMAIL CORPORATION 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
+ * RADIOMAIL CORPORATION 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 was written for RadioMail Corporation by Ted Lemon
+ * under a contract with Vixie Enterprises, and is based on an earlier
+ * design by Paul Vixie.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <paths.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <limits.h>
+
+#include <netdb.h>
+extern int h_errno;
+
+#include <net/if.h>
+
+/* Time stuff... */
+#include <sys/time.h>
+#define TIME struct timeval
+#define GET_TIME(x)    gettimeofday ((x), (struct timezone *)0)
+#define TIME_DIFF_US(high, low)                                        \
+  (((high) -> tv_sec - (low) -> tv_sec) * 1000000                      \
+   + ((high) -> tv_usec - (low) -> tv_usec))
+#define SET_TIME(x, y) (((x) -> tv_sec = ((y) / 1000000)),             \
+                        ((x) -> tv_usec = ((y) % 1000000)))
+#define DELAY() usleep (2000)
+#define DELAY_ONE_SECOND() usleep (1000000)
+
+/* Login stuff... */
+#include <utmp.h>
+#include <sys/syslimits.h>
+#define _PATH_LOGIN    "/usr/bin/login"
+#define SETLOGIN(x) setlogin (x)
+#define SETUID(x)      setuid (x)
+#define SETGID(x)      (setgroups (0, &x), setgid (x))
+#define USER_MAX       UT_NAMESIZE
+
+/* Varargs stuff... */
+#include <stdarg.h>
+#define VA_DOTDOTDOT ...
+#define va_dcl
+#define VA_start(list, last) va_start (list, last)
+
+#define _PATH_MPOOL_PID        "/var/run/mpoold.pid"
+
+#define EOL    '\n'
+#define VOIDPTR        void *
+
+/* Time stuff... */
+#include <sys/time.h>
+#define TIME struct timeval
+#define GET_TIME(x)    gettimeofday ((x), (struct timezone *)0)
+#define TIME_DIFF(high, low)                                           \
+  (((high) -> tv_sec == (low) -> tv_sec)                               \
+   ? ((high) -> tv_usec > (low) -> tv_usec                             \
+      ? 1 : (((high) -> tv_usec == (low) -> tv_usec) ? 0 : -1))                \
+   : (high) -> tv_sec - (low) -> tv_sec)
+#define SET_TIME(x, y) (((x) -> tv_sec = ((y))), ((x) -> tv_usec = 0))
+#define ADD_TIME(d, s1, s2) {                                          \
+                (d) -> tv_usec = (s1) -> tv_usec + (s2) -> tv_usec;    \
+                if ((d) -> tv_usec > 1000000 || (d) -> tv_usec < -1000000) { \
+                        (d) -> tv_sec = (d) -> tv_usec / 1000000;      \
+                        (d) -> tv_usec %= 1000000;                     \
+                } else                                                 \
+                        (d) -> tv_sec = 0;                             \
+                (d) -> tv_sec += (s1) -> tv_sec + (s2) -> tv_sec;      \
+       }
+#define SET_MAX_TIME(x)        (((x) -> tv_sec = INT_MAX),                     \
+                        ((x) -> tv_usec = 999999))
diff --git a/cf/netbsd.h b/cf/netbsd.h
new file mode 100644 (file)
index 0000000..d69ff1b
--- /dev/null
@@ -0,0 +1,73 @@
+/* netbsd.h
+
+   System dependencies for NetBSD... */
+
+/*
+ * Copyright (c) 1995 RadioMail Corporation.  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 RadioMail Corporation 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 RADIOMAIL CORPORATION 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
+ * RADIOMAIL CORPORATION 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 was written for RadioMail Corporation by Ted Lemon
+ * under a contract with Vixie Enterprises, and is based on an earlier
+ * design by Paul Vixie.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <paths.h>
+#include <errno.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <limits.h>
+
+#include <sys/wait.h>
+#include <signal.h>
+
+#include <netdb.h>
+extern int h_errno;
+
+#include <net/if.h>
+
+/* Varargs stuff... */
+#include <stdarg.h>
+#define VA_DOTDOTDOT ...
+#define va_dcl
+#define VA_start(list, last) va_start (list, last)
+
+#define _PATH_DHCPD_PID        "/var/run/dhcpd.pid"
+
+#define EOL    '\n'
+#define VOIDPTR void *
+
+/* Time stuff... */
+#include <sys/time.h>
+#define TIME time_t
+#define GET_TIME(x)    time ((x))
+#define TIME_DIFF(high, low)           (*(high) - *(low))
+#define SET_TIME(x, y) (*(x) = (y))
+#define ADD_TIME(d, s1, s2) (*(d) = *(s1) + *(s2))
+#define SET_MAX_TIME(x)        (*(x) = INT_MAX)
diff --git a/cf/sunos4.h b/cf/sunos4.h
new file mode 100644 (file)
index 0000000..fa97687
--- /dev/null
@@ -0,0 +1,83 @@
+/* sunos4.h
+
+   System dependencies for SunOS 4 (tested on 4.1.4)... */
+
+/*
+ * Copyright (c) 1995 RadioMail Corporation.  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 RadioMail Corporation 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 RADIOMAIL CORPORATION 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
+ * RADIOMAIL CORPORATION 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 was written for RadioMail Corporation by Ted Lemon
+ * under a contract with Vixie Enterprises, and is based on an earlier
+ * design by Paul Vixie.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <limits.h>
+
+#include <netdb.h>
+extern int h_errno;
+
+#include <net/if.h>
+
+/* Varargs stuff... */
+#include <varargs.h>
+#define VA_DOTDOTDOT va_alist
+#define VA_start(list, last) va_start (list)
+
+#define vsnprintf(buf, size, fmt, list) vsprintf (buf, fmt, list)
+
+#define EOL    '\n'
+#define VOIDPTR        void *
+
+/* Time stuff... */
+#include <sys/time.h>
+#define TIME struct timeval
+#define GET_TIME(x)    gettimeofday ((x), (struct timezone *)0)
+#define TIME_DIFF(high, low)                                           \
+  (((high) -> tv_sec == (low) -> tv_sec)                               \
+   ? ((high) -> tv_usec > (low) -> tv_usec                             \
+      ? 1 : (((high) -> tv_usec == (low) -> tv_usec) ? 0 : -1))                \
+   : (high) -> tv_sec - (low) -> tv_sec)
+#define SET_TIME(x, y) (((x) -> tv_sec = ((y))), ((x) -> tv_usec = 0))
+#define ADD_TIME(d, s1, s2) {                                          \
+                (d) -> tv_usec = (s1) -> tv_usec + (s2) -> tv_usec;    \
+                if ((d) -> tv_usec > 1000000 || (d) -> tv_usec < -1000000) { \
+                        (d) -> tv_sec = (d) -> tv_usec / 1000000;      \
+                        (d) -> tv_usec %= 1000000;                     \
+                } else                                                 \
+                        (d) -> tv_sec = 0;                             \
+                (d) -> tv_sec += (s1) -> tv_sec + (s2) -> tv_sec;      \
+       }
+#define SET_MAX_TIME(x)        (((x) -> tv_sec = INT_MAX),                     \
+                        ((x) -> tv_usec = 999999))
diff --git a/common/alloc.c b/common/alloc.c
new file mode 100644 (file)
index 0000000..9dbeadb
--- /dev/null
@@ -0,0 +1,197 @@
+/* alloc.c
+
+   Memory allocation...
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+struct dhcp_packet *dhcp_free_list;
+struct packet *packet_free_list;
+
+VOIDPTR dmalloc (size, name)
+       int size;
+       char *name;
+{
+       VOIDPTR foo = (VOIDPTR)malloc (size);
+       if (!foo)
+               warn ("No memory for %s.\n");
+       return foo;
+}
+
+void dfree (ptr, name)
+       VOIDPTR ptr;
+       char *name;
+{
+       free (ptr);
+}
+
+struct packet *new_packet (name)
+       char *name;
+{
+       struct packet *rval;
+       rval = (struct packet *)dmalloc (sizeof (struct packet), name);
+       return rval;
+}
+
+struct dhcp_packet *new_dhcp_packet (name)
+       char *name;
+{
+       struct dhcp_packet *rval;
+       rval = (struct dhcp_packet *)dmalloc (sizeof (struct dhcp_packet),
+                                             name);
+       return rval;
+}
+
+struct tree *new_tree (name)
+       char *name;
+{
+       struct tree *rval = dmalloc (sizeof (struct tree), name);
+       return rval;
+}
+
+struct tree_cache *new_tree_cache (name)
+       char *name;
+{
+       struct tree_cache *rval = dmalloc (sizeof (struct tree_cache), name);
+       return rval;
+}
+
+struct hash_table *new_hash_table (count, name)
+       int count;
+       char *name;
+{
+       struct hash_table *rval = dmalloc (sizeof (struct hash_table)
+                                          - (DEFAULT_HASH_SIZE
+                                             * sizeof (struct hash_bucket *))
+                                          + (count
+                                             * sizeof (struct hash_bucket *)),
+                                          name);
+       rval -> hash_count = count;
+       return rval;
+}
+
+struct hash_bucket *new_hash_bucket (name)
+       char *name;
+{
+       struct hash_bucket *rval = dmalloc (sizeof (struct hash_bucket), name);
+       return rval;
+}
+
+struct lease *new_leases (n, name)
+       int n;
+       char *name;
+{
+       struct lease *rval = dmalloc (n * sizeof (struct lease), name);
+       return rval;
+}
+
+struct lease *new_lease (name)
+       char *name;
+{
+       struct lease *rval = dmalloc (sizeof (struct lease), name);
+       return rval;
+}
+
+struct subnet *new_subnet (name)
+       char *name;
+{
+       struct subnet *rval = dmalloc (sizeof (struct subnet), name);
+       return rval;
+}
+
+void free_subnet (ptr, name)
+       struct subnet *ptr;
+       char *name;
+{
+       dfree ((VOIDPTR)ptr, name);
+}
+
+void free_lease (ptr, name)
+       struct lease *ptr;
+       char *name;
+{
+       dfree ((VOIDPTR)ptr, name);
+}
+
+void free_hash_bucket (ptr, name)
+       struct hash_bucket *ptr;
+       char *name;
+{
+       dfree ((VOIDPTR)ptr, name);
+}
+
+void free_hash_table (ptr, name)
+       struct hash_table *ptr;
+       char *name;
+{
+       dfree ((VOIDPTR)ptr, name);
+}
+
+void free_tree_cache (ptr, name)
+       struct tree_cache *ptr;
+       char *name;
+{
+       dfree ((VOIDPTR)ptr, name);
+}
+
+void free_packet (ptr, name)
+       struct packet *ptr;
+       char *name;
+{
+       dfree ((VOIDPTR)ptr, name);
+}
+
+void free_dhcp_packet (ptr, name)
+       struct dhcp_packet *ptr;
+       char *name;
+{
+       dfree ((VOIDPTR)ptr, name);
+}
+
+void free_tree (ptr, name)
+       struct tree *ptr;
+       char *name;
+{
+       dfree ((VOIDPTR)ptr, name);
+}
diff --git a/common/conflex.c b/common/conflex.c
new file mode 100644 (file)
index 0000000..a7b56dd
--- /dev/null
@@ -0,0 +1,280 @@
+/* conflex.c
+
+   Lexical scanner for dhcpd config file... */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+#include "dhctoken.h"
+#include <ctype.h>
+
+static int line;
+static int lpos;
+int tlpos;
+int tline;
+static int token;
+static int ugflag;
+static char *tval;
+static char tokbuf [1500];
+
+static int get_char PROTO ((FILE *));
+static int get_token PROTO ((FILE *));
+static void skip_to_eol PROTO ((FILE *));
+static int read_string PROTO ((FILE *));
+static int read_number PROTO ((int, FILE *));
+static int read_num_or_atom PROTO ((int, FILE *));
+static int intern PROTO ((char *, int));
+
+static int get_char (cfile)
+       FILE *cfile;
+{
+       char c = getc (cfile);
+       if (!ugflag) {
+               if (c == EOL) {
+                       line++;
+                       lpos = 1;
+               } else {
+                       lpos++;
+               }
+       } else
+               ugflag = 0;
+       return c;               
+}
+
+static int get_token (cfile)
+       FILE *cfile;
+{
+       int c;
+       int i;
+       int ttok;
+
+       do {
+               c = get_char (cfile);
+               if (isascii (c) && isspace (c))
+                       continue;
+               if (c == '#') {
+                       skip_to_eol (cfile);
+                       continue;
+               }
+               tlpos = lpos;
+               tline = line;
+               if (c == '"') {
+                       ttok = read_string (cfile);
+                       break;
+               }
+               if (isascii (c) && isdigit (c)) {
+                       ttok = read_number (c, cfile);
+                       break;
+               } else if (isascii (c) && isalpha (c)) {
+                       ttok = read_num_or_atom (c, cfile);
+                       break;
+               } else {
+                       tval = 0;
+                       ttok = c;
+                       break;
+               }
+       } while (1);
+       return ttok;
+}
+
+int next_token (rval, cfile)
+       char **rval;
+       FILE *cfile;
+{
+       int rv;
+
+       if (token) {
+               rv = token;
+               token = 0;
+       } else {
+               rv = get_token (cfile);
+       }
+       if (rval)
+               *rval = tval;
+       return rv;
+}
+
+int peek_token (rval, cfile)
+       char **rval;
+       FILE *cfile;
+{
+       if (!token)
+               token = get_token (cfile);
+       if (rval)
+               *rval = tval;
+       return token;
+}
+
+static void skip_to_eol (cfile)
+       FILE *cfile;
+{
+       int c;
+       do {
+               c = get_char (cfile);
+               if (c == EOF)
+                       return;
+               if (c == EOL) {
+                       ungetc (c, cfile);
+                       ugflag = 1;
+                       return;
+               }
+       } while (1);
+}
+
+static int read_string (cfile)
+       FILE *cfile;
+{
+       int i;
+       int bs = 0;
+       int c;
+
+       for (i = 0; i < sizeof tokbuf; i++) {
+               c = get_char (cfile);
+               if (c == EOF) {
+                       parse_warn ("eof in string constant");
+                       break;
+               }
+               if (bs) {
+                       bs = 0;
+                       tokbuf [i] = c;
+               } else if (c == '\\')
+                       bs = 1;
+               else if (c == '"')
+                       break;
+               else
+                       tokbuf [i] = c;
+       }
+       /* Normally, I'd feel guilty about this, but we're talking about
+          strings that'll fit in a DHCP packet here... */
+       if (i == sizeof tokbuf) {
+               parse_warn ("string constant larger than internal buffer");
+               --i;
+       }
+       tokbuf [i] = 0;
+       tval = tokbuf;
+       return STRING;
+}
+
+static int read_number (c, cfile)
+       int c;
+       FILE *cfile;
+{
+       int seenx = 0;
+       int i = 0;
+       tokbuf [i++] = c;
+       for (; i < sizeof tokbuf; i++) {
+               c = get_char (cfile);
+               if (!seenx && c == 'x')
+                       seenx = 1;
+               else if (!isascii (c) || !isxdigit (c)) {
+                       ungetc (c, cfile);
+                       ugflag = 1;
+                       break;
+               }
+               tokbuf [i] = c;
+       }
+       if (i == sizeof tokbuf) {
+               parse_warn ("numeric token larger than internal buffer");
+               --i;
+       }
+       tokbuf [i] = 0;
+       tval = tokbuf;
+       return NUMBER;
+}
+
+static int read_num_or_atom (c, cfile)
+       int c;
+       FILE *cfile;
+{
+       int i = 0;
+       int rv = NUMBER_OR_ATOM;
+       tokbuf [i++] = c;
+       for (; i < sizeof tokbuf; i++) {
+               c = get_char (cfile);
+               if (!isascii (c) ||
+                   (c != '-' && c != '_' && !isalnum (c))) {
+                       ungetc (c, cfile);
+                       ugflag = 1;
+                       break;
+               }
+               if (!isxdigit (c))
+                       rv = ATOM;
+               tokbuf [i] = c;
+       }
+       if (i == sizeof tokbuf) {
+               parse_warn ("token larger than internal buffer");
+               --i;
+       }
+       tokbuf [i] = 0;
+       tval = tokbuf;
+       return intern (tval, rv);
+}
+
+static int intern (atom, dfv)
+       char *atom;
+       int dfv;
+{
+       switch (atom [0]) {
+             case 'h':
+               if (!strcasecmp (atom + 1, "ost"))
+                       return HOST;
+               if (!strcasecmp (atom + 1, "ardware"))
+                       return HARDWARE;
+               break;
+             case 'f':
+               if (!strcasecmp (atom + 1, "ilename"))
+                       return FILENAME;
+               if (!strcasecmp (atom + 1, "ixed-address"))
+                       return FIXED_ADDR;
+               break;
+             case 'e':
+               if (!strcasecmp (atom + 1, "thernet"))
+                       return ETHERNET;
+               break;
+             case 'o':
+               if (!strcasecmp (atom + 1, "ption"))
+                       return OPTION;
+               break;
+       }
+       return dfv;
+}
diff --git a/common/convert.c b/common/convert.c
new file mode 100644 (file)
index 0000000..bd423a0
--- /dev/null
@@ -0,0 +1,117 @@
+/* convert.c
+
+   Safe copying of option values into and out of the option buffer, which
+   can't be assumed to be aligned. */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+unsigned long getULong (buf)
+       unsigned char *buf;
+{
+       unsigned long ibuf;
+
+       memcpy (&ibuf, buf, sizeof (unsigned long));
+       return ntohl (ibuf);
+}
+
+long getLong (buf)
+       unsigned char *buf;
+{
+       long ibuf;
+
+       memcpy (&ibuf, buf, sizeof (long));
+       return ntohl (ibuf);
+}
+
+unsigned short getUShort (buf)
+       unsigned char *buf;
+{
+       unsigned short ibuf;
+
+       memcpy (&ibuf, buf, sizeof (unsigned short));
+       return ntohs (ibuf);
+}
+
+short getShort (buf)
+       unsigned char *buf;
+{
+       short ibuf;
+
+       memcpy (&ibuf, buf, sizeof (short));
+       return ntohs (ibuf);
+}
+
+void putULong (obuf, val)
+       unsigned char *obuf;
+       unsigned long val;
+{
+       unsigned long tmp = htonl (val);
+       memcpy (obuf, &tmp, sizeof tmp);
+}
+
+void putLong (obuf, val)
+       unsigned char *obuf;
+       long val;
+{
+       long tmp = htonl (val);
+       memcpy (obuf, &tmp, sizeof tmp);
+}
+
+void putUShort (obuf, val)
+       unsigned char *obuf;
+       unsigned short val;
+{
+       unsigned short tmp = htonl (val);
+       memcpy (obuf, &tmp, sizeof tmp);
+}
+
+void putShort (obuf, val)
+       unsigned char *obuf;
+       short val;
+{
+       short tmp = htonl (val);
+       memcpy (obuf, &tmp, sizeof tmp);
+}
+
diff --git a/common/errwarn.c b/common/errwarn.c
new file mode 100644 (file)
index 0000000..d3c25c4
--- /dev/null
@@ -0,0 +1,200 @@
+/* errwarn.c
+
+   Errors and warnings... */
+
+/*
+ * Copyright (c) 1995 RadioMail Corporation.  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 RadioMail Corporation 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 RADIOMAIL CORPORATION 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
+ * RADIOMAIL CORPORATION 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 was written for RadioMail Corporation by Ted Lemon
+ * under a contract with Vixie Enterprises, and is based on an earlier
+ * design by Paul Vixie.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1995 RadioMail Corporation.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+#include <syslog.h>
+#include <errno.h>
+
+static void do_percentm PROTO ((char *obuf, char *ibuf));
+
+static char mbuf [1024];
+static char fbuf [1024];
+
+/* Log an error message, then exit... */
+
+int error (ANSI_DECL(char *) fmt, VA_DOTDOTDOT)
+     KandR (char *fmt;)
+     va_dcl
+{
+  va_list list;
+  extern int logged_in;
+
+  do_percentm (fbuf, fmt);
+
+  VA_start (list, fmt);
+  vsnprintf (mbuf, sizeof mbuf, fbuf, list);
+  va_end (list);
+#ifndef DEBUG
+  syslog (LOG_ERR, mbuf);
+#else
+  write (1, mbuf, strlen (mbuf));
+  write (1, "\n", 1);
+#endif
+
+  cleanup ();
+  exit (1);
+}
+
+/* Log a warning message... */
+
+int warn (ANSI_DECL (char *) fmt, VA_DOTDOTDOT)
+     KandR (char *fmt;)
+     va_dcl
+{
+  va_list list;
+
+  do_percentm (fbuf, fmt);
+
+  VA_start (list, fmt);
+  vsnprintf (mbuf, sizeof mbuf, fbuf, list);
+  va_end (list);
+#ifndef DEBUG
+  syslog (LOG_ERR, mbuf);
+#else
+  write (1, mbuf, strlen (mbuf));
+  write (1, "\n", 1);
+#endif
+  return 0;
+}
+
+/* Log a note... */
+
+int note (ANSI_DECL (char *) fmt, VA_DOTDOTDOT)
+     KandR (char *fmt;)
+     va_dcl
+{
+  va_list list;
+
+  do_percentm (fbuf, fmt);
+
+  VA_start (list, fmt);
+  vsnprintf (mbuf, sizeof mbuf, fbuf, list);
+  va_end (list);
+#ifndef DEBUG
+  syslog (LOG_INFO, mbuf);
+#else
+  write (1, mbuf, strlen (mbuf));
+  write (1, "\n", 1);
+#endif
+  return 0;
+}
+
+/* Log a debug message... */
+
+int debug (ANSI_DECL (char *) fmt, VA_DOTDOTDOT)
+     KandR (char *fmt;)
+     va_dcl
+{
+  va_list list;
+
+  do_percentm (fbuf, fmt);
+
+  VA_start (list, fmt);
+  vsnprintf (mbuf, sizeof mbuf, fbuf, list);
+  va_end (list);
+#ifndef DEBUG
+  syslog (LOG_DEBUG, mbuf);
+#else
+  write (1, mbuf, strlen (mbuf));
+  write (1, "\n", 1);
+#endif
+  return 0;
+}
+
+/* Find %m in the input string and substitute an error message string. */
+
+static void do_percentm (obuf, ibuf)
+     char *obuf;
+     char *ibuf;
+{
+  char *s = ibuf;
+  char *p = obuf;
+  int infmt = 0;
+
+  while (*s)
+    {
+      if (infmt)
+       {
+         if (*s == 'm')
+           {
+             strcpy (p - 1, strerror (errno));
+             p += strlen (p);
+             ++s;
+           }
+         else
+           *p++ = *s++;
+         infmt = 0;
+       }
+      else
+       {
+         if (*s == '%')
+           infmt = 1;
+         *p++ = *s++;
+       }
+    }
+  *p = 0;
+}
+
+
+int parse_warn (ANSI_DECL (char *) fmt, VA_DOTDOTDOT)
+       KandR (char *fmt;)
+       va_dcl
+{
+       extern int tline, tlpos;
+       va_list list;
+       
+       do_percentm (mbuf, fmt);
+       snprintf (fbuf, sizeof fbuf, "dhcpd.conf line %d char %d: %s",
+                 tline, tlpos, mbuf);
+       
+       VA_start (list, fmt);
+       vsnprintf (mbuf, sizeof mbuf, fbuf, list);
+       va_end (list);
+#ifndef DEBUG
+       syslog (LOG_ERROR, mbuf);
+#else
+       write (1, mbuf, strlen (mbuf));
+       write (1, "\n", 1);
+#endif
+       return 0;
+}
diff --git a/common/hash.c b/common/hash.c
new file mode 100644 (file)
index 0000000..9b2d5f9
--- /dev/null
@@ -0,0 +1,152 @@
+/* hash.c
+
+   Routines for manipulating hash tables... */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+struct hash_table *new_hash ()
+{
+       struct hash_table *rv = new_hash_table (DEFAULT_HASH_SIZE, "new_hash");
+       if (!rv)
+               return rv;
+       memset (&rv -> buckets, 0,
+               DEFAULT_HASH_SIZE * sizeof (struct hash_bucket *));
+       return rv;
+}
+
+static INLINE do_hash (name, len, size)
+       char *name;
+       int len;
+       int size;
+{
+       register int accum = 0;
+       register unsigned char *s = (unsigned char *)name;
+       int i = len;
+       if (i) {
+               while (i--) {
+                       /* Add the character in... */
+                       accum += *s++;
+                       /* Add carry back in... */
+                       while (accum > 255) {
+                               accum = (accum & 255) + (accum >> 8);
+                       }
+               }
+       } else {
+               while (*s) {
+                       /* Add the character in... */
+                       accum += *s++;
+                       /* Add carry back in... */
+                       while (accum > 255) {
+                               accum = (accum & 255) + (accum >> 8);
+                       }
+               }
+       }
+       return accum % size;
+}
+
+void add_hash (table, name, len, pointer)
+       struct hash_table *table;
+       int len;
+       char *name;
+       unsigned char *pointer;
+{
+       int hashno = do_hash (name, len, table -> hash_count);
+       struct hash_bucket *bp = new_hash_bucket ("add_hash");
+       if (!bp) {
+               warn ("Can't add %s to hash table.", name);
+               return;
+       }
+       bp -> name = name;
+       bp -> value = pointer;
+       bp -> next = table -> buckets [hashno];
+       table -> buckets [hashno] = bp;
+}
+
+void delete_hash_entry (table, name, len)
+       struct hash_table *table;
+       int len;
+       char *name;
+{
+       int hashno = do_hash (name, len, table -> hash_count);
+       struct hash_bucket *bp, *pbp = (struct hash_bucket *)0;
+
+       /* Go through the list looking for an entry that matches;
+          if we find it, delete it. */
+       for (bp = table -> buckets [hashno]; bp; bp = bp -> next) {
+               if ((!bp -> len && !strcmp (bp -> name, name)) ||
+                   (bp -> len == len &&
+                    !memcmp (bp -> name, name, len))) {
+                       if (pbp) {
+                               pbp -> next = bp -> next;
+                       } else {
+                               table -> buckets [hashno] = bp -> next;
+                       }
+                       free_hash_bucket (bp, "delete_hash_entry");
+                       break;
+               }
+       }
+}
+
+unsigned char *hash_lookup (table, name, len)
+       struct hash_table *table;
+       char *name;
+       int len;
+{
+       int hashno = do_hash (name, len, table -> hash_count);
+       struct hash_bucket *bp;
+
+       if (len) {
+               for (bp = table -> buckets [hashno]; bp; bp = bp -> next)
+                       if (len == bp -> len
+                           && !memcmp (bp -> name, name, len))
+                               return bp -> value;
+       } else {
+               for (bp = table -> buckets [hashno]; bp; bp = bp -> next)
+                       if (!strcmp (bp -> name, name))
+                               return bp -> value;
+       }
+       return (unsigned char *)0;
+}
+
diff --git a/common/memory.c b/common/memory.c
new file mode 100644 (file)
index 0000000..c3e1abd
--- /dev/null
@@ -0,0 +1,395 @@
+/* memory.c
+
+   Memory-resident database... */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+static struct host_decl *hosts;
+static struct hash_table *subnet_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;
+
+void enter_host (hd)
+       struct host_decl *hd;
+{
+       hd -> n_name = hosts;
+       hd -> n_haddr = hosts;
+       hd -> n_cid = hosts;
+       
+       hosts = hd;
+}
+
+struct host_decl *find_host_by_name (name)
+       char *name;
+{
+       struct host_decl *foo;
+
+       for (foo = hosts; foo; foo = foo -> n_name)
+               if (!strcmp (name, foo -> name))
+                       return foo;
+       return (struct host_decl *)0;
+}
+
+struct host_decl *find_host_by_addr (htype, haddr, hlen)
+       int htype;
+       unsigned char *haddr;
+       int hlen;
+{
+       struct host_decl *foo;
+       int i;
+
+       for (foo = hosts; foo; foo = foo -> n_haddr)
+               for (i = 0; i < foo -> interface_count; i++)
+                       if (foo -> interfaces [i].htype == htype &&
+                           foo -> interfaces [i].hlen == hlen &&
+                           !memcmp (foo -> interfaces [i].haddr, haddr, hlen))
+                               return foo;
+       return (struct host_decl *)0;
+}
+
+void new_address_range (low, high, netmask)
+       struct in_addr low, high, netmask;
+{
+       struct lease *address_range, *lp, *plp;
+       struct subnet *subnet;
+       struct in_addr net;
+       int i, max;
+       char lowbuf [16], highbuf [16], netbuf [16];
+
+       /* Initialize the hash table if it hasn't been done yet. */
+       if (!subnet_hash)
+               subnet_hash = new_hash ();
+       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.s_addr = SUBNET (low, netmask);
+       if (net.s_addr != SUBNET (high, netmask)) {
+               strcpy (lowbuf, inet_ntoa (low));
+               strcpy (highbuf, inet_ntoa (high));
+               strcpy (netbuf, inet_ntoa (netmask));
+               error ("Address range %s to %s, netmask %s spans %s!",
+                      lowbuf, highbuf, netbuf, "multiple subnets");
+       }
+
+       /* See if this subnet is already known - if not, make a new one. */
+       subnet = find_subnet (net);
+       if (!subnet) {
+               subnet = new_subnet ("new_address_range");
+               if (!subnet)
+                       error ("No memory for new subnet");
+               subnet -> net = net;
+               subnet -> netmask = netmask;
+               subnet -> leases = (struct lease *)0;
+               enter_subnet (subnet);
+       }
+
+       /* Get the high and low host addresses... */
+       max = HOST_ADDR (high, netmask);
+       i = HOST_ADDR (low, netmask);
+
+       /* Allow range to be specified high-to-low as well as low-to-high. */
+       if (i > max) {
+               max = i;
+               i = HOST_ADDR (high, netmask);
+       }
+
+       /* Get a lease structure for each address in the range. */
+       address_range = new_leases (max - i + 1, "new_address_range");
+       if (!address_range) {
+               strcpy (lowbuf, inet_ntoa (low));
+               strcpy (highbuf, inet_ntoa (high));
+               error ("No memory for address range %s-%s.", lowbuf, highbuf);
+       }
+       memset (address_range, 0, (sizeof *address_range) * (max - i + 1));
+
+       /* Fill out the lease structures with some minimal information. */
+       for (; i <= max; i++) {
+               address_range [i].ip_addr.s_addr = IP_ADDR (subnet -> net, i);
+               address_range [i].starts =
+                       address_range [i].timestamp = MIN_TIME;
+               address_range [i].ends = MIN_TIME;
+               address_range [i].contain = subnet;
+
+               /* Link this entry into the list. */
+               address_range [i].next = subnet -> leases;
+               address_range [i].prev = (struct lease *)0;
+               subnet -> leases = &address_range [i];
+               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,
+                         (unsigned char *)&address_range [i]);
+       }
+
+       /* Find out if any dangling leases are in range... */
+       plp = (struct lease *)0;
+       for (lp = dangling_leases; lp; lp = lp -> next) {
+               struct in_addr lnet;
+               int lhost;
+
+               lnet.s_addr = SUBNET (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 (lnet.s_addr == subnet -> net.s_addr &&
+                   lhost >= i && lhost <= max) {
+                       if (plp) {
+                               plp -> next = lp -> next;
+                       } else {
+                               dangling_leases = lp -> next;
+                       }
+                       lp -> next = (struct lease *)0;
+                       supersede_lease (&address_range [lhost - i], lp);
+                       free_lease (lp, "new_address_range");
+               } else
+                       plp = lp;
+       }
+}
+
+struct subnet *find_subnet (subnet)
+       struct in_addr subnet;
+{
+       struct subnet *rv;
+
+       return (struct subnet *)hash_lookup (subnet_hash,
+                                            (char *)&subnet, sizeof subnet);
+}
+
+/* Enter a new subnet into the subnet hash. */
+
+void enter_subnet (subnet)
+       struct subnet *subnet;
+{
+       add_hash (subnet_hash, (char *)&subnet -> net,
+                 sizeof subnet -> net, (unsigned char *)subnet);
+}
+       
+/* Enter a lease into the system.   This is called by the parser each
+   time it reads in a new lease.   If the subnet for that lease has
+   already been read in (usually the case), just update that lease;
+   otherwise, allocate temporary storage for the lease and keep it around
+   until we're done reading in the config file. */
+
+void enter_lease (lease)
+       struct lease *lease;
+{
+       struct lease *comp = find_lease_by_ip_addr (lease -> ip_addr);
+
+       /* If we don't have a place for this lease yet, save it for
+          later. */
+       if (!comp) {
+               comp = new_lease ("enter_lease");
+               if (!comp) {
+                       error ("No memory for lease %s\n",
+                              inet_ntoa (lease -> ip_addr));
+               }
+               *comp = *lease;
+               lease -> next = dangling_leases;
+               lease -> prev = (struct lease *)0;
+               dangling_leases = lease;
+       } else {
+               supersede_lease (comp, lease);
+       }
+}
+
+/* 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. */
+
+void supersede_lease (comp, lease)
+       struct lease *comp, *lease;
+{
+       int enter_uid = 0;
+       int enter_hwaddr = 0;
+       struct subnet *parent;
+       struct lease *lp;
+
+       /* If the existing lease hasn't expired and has a different
+          unique identifier or, if it doesn't have a unique
+          identifier, a different hardware address, then the two
+          leases are in conflict. */
+       if (comp -> ends > cur_time &&
+           ((comp -> 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",
+                     inet_ntoa (comp -> ip_addr));
+       } else {
+               /* If there's a Unique ID, dissociate it from the hash
+                  table if necessary, and always free it. */
+               if (comp -> uid) {
+                       if (comp -> uid_len != lease -> uid_len ||
+                           memcmp (comp -> uid, lease -> uid,
+                                   comp -> uid_len)) {
+                               delete_hash_entry (lease_uid_hash,
+                                                  comp -> uid,
+                                                  comp -> uid_len);
+                               enter_uid = 1;
+                       }
+                       free (comp -> uid);
+               }
+               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)) {
+                       delete_hash_entry (lease_hw_addr_hash,
+                                          comp -> hardware_addr.haddr,
+                                          comp -> hardware_addr.hlen);
+                       enter_hwaddr = 1;
+               }
+
+               /* Copy the data files, but not the linkages. */
+               comp -> starts = lease -> starts;
+               comp -> ends = lease -> ends;
+               comp -> timestamp = lease -> timestamp;
+               comp -> uid = lease -> uid;
+               comp -> uid_len = lease -> uid_len;
+               comp -> host = lease -> host;
+               comp -> hardware_addr = lease -> hardware_addr;
+               comp -> state = lease -> state;
+
+               /* Record the lease in the uid hash if necessary. */
+               if (enter_uid && lease -> uid) {
+                       add_hash (lease_uid_hash, lease -> uid,
+                                 lease -> uid_len, (unsigned char *)lease);
+               }
+
+               /* Record it in the hardware address hash if necessary. */
+               if (enter_hwaddr && lease -> hardware_addr.htype) {
+                       add_hash (lease_hw_addr_hash,
+                                 lease -> hardware_addr.haddr,
+                                 lease -> hardware_addr.hlen,
+                                 (unsigned char *)lease);
+               }
+
+               /* Remove the lease from its current place in the list. */
+               if (comp -> prev) {
+                       comp -> prev -> next = comp -> next;
+               } else {
+                       comp -> contain -> leases = comp -> next;
+               }
+               if (comp -> next) {
+                       comp -> next -> prev = comp -> prev;
+               }
+
+               /* Find the last insertion point... */
+               if (comp == comp -> contain -> insertion_point ||
+                   !comp -> contain -> insertion_point) {
+                       lp = comp -> contain -> leases;
+               } else {
+                       lp = comp -> contain -> insertion_point;
+               }
+
+               if (!lp) {
+                       /* Nothing on the list yet?    Just make comp the
+                          head of the list. */
+                       comp -> contain -> leases = comp;
+               } else if (lp -> ends <= comp -> ends) {
+                       /* Skip down the list until we run out of list
+                          or find a place for comp. */
+                       while (lp -> next && lp -> ends < comp -> ends) {
+                               lp = lp -> next;
+                       }
+                       if (lp -> ends < comp -> ends) {
+                               /* If we ran out of list, put comp
+                                  at the end. */
+                               lp -> next = comp;
+                               comp -> prev = lp;
+                               comp -> next = (struct lease *)0;
+                       } else {
+                               /* If we didn't, put it between lp and
+                                  the previous item on the list. */
+                               comp -> prev = lp -> prev;
+                               comp -> prev -> next = comp;
+                               comp -> next = lp;
+                               lp -> prev = comp;
+                       }
+               } else {
+                       /* Skip ip the list until we run out of list
+                          or find a place for comp. */
+                       while (lp -> prev && lp -> ends > comp -> ends) {
+                               lp = lp -> prev;
+                       }
+                       if (lp -> ends > comp -> ends) {
+                               /* If we ran out of list, put comp
+                                  at the beginning. */
+                               lp -> prev = comp;
+                               comp -> next = lp;
+                               comp -> prev = (struct lease *)0;
+                               comp -> contain -> leases = comp;
+                       } else {
+                               /* If we didn't, put it between lp and
+                                  the next item on the list. */
+                               comp -> next = lp -> next;
+                               comp -> next -> prev = comp;
+                               comp -> prev = lp;
+                               lp -> next = comp;
+                       }
+               }
+               comp -> contain -> insertion_point = comp;
+       }
+}
diff --git a/common/options.c b/common/options.c
new file mode 100644 (file)
index 0000000..2a63279
--- /dev/null
@@ -0,0 +1,556 @@
+/* options.c
+
+   DHCP options parsing and reassembly. */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#define DHCP_OPTION_DATA
+#include "dhcpd.h"
+
+/* Parse all available options out of the specified packet. */
+
+void parse_options (packet)
+       struct packet *packet;
+{
+       /* Initially, zero all option pointers. */
+       memset (packet -> options, 0, sizeof (packet -> options));
+
+       /* If we don't see the magic cookie, there's nothing to parse. */
+       if (memcmp (packet -> raw -> options, DHCP_OPTIONS_COOKIE, 4)) {
+               packet -> options_valid = 0;
+               return;
+       }
+
+       /* Go through the options field, up to the end of the packet
+          or the End field. */
+       parse_option_buffer (packet, &packet -> raw -> options [4],
+                            packet -> packet_length - DHCP_FIXED_LEN);
+       /* If we parsed a DHCP Option Overload option, parse more
+          options out of the buffer(s) containing them. */
+       if (packet -> options_valid
+           && packet -> options [DHO_DHCP_OPTION_OVERLOAD].data) {
+               if (packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 1)
+                       parse_option_buffer (packet,
+                                            packet -> raw -> file,
+                                            sizeof packet -> raw -> file);
+               if (packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 2)
+                       parse_option_buffer (packet,
+                                            packet -> raw -> sname,
+                                            sizeof packet -> raw -> sname);
+       }
+}
+
+/* Parse options out of the specified buffer, storing addresses of option
+   values in packet -> options and setting packet -> options_valid if no
+   errors are encountered. */
+
+void parse_option_buffer (packet, buffer, length)
+       struct packet *packet;
+       unsigned char *buffer;
+       int length;
+{
+       unsigned char *s, *t;
+       unsigned char *end = buffer + length;
+       int len;
+       int code;
+
+       for (s = buffer; *s != DHO_END && s < end; ) {
+               code = s [0];
+               /* Pad options don't have a length - just skip them. */
+               if (code == DHO_PAD) {
+                       ++s;
+                       continue;
+               }
+               /* All other fields (except end, see above) have a
+                  one-byte length. */
+               len = s [1];
+               /* If the length is outrageous, the options are bad. */
+               if (s + len + 2 > end) {
+                       warn ("Option %s length %d overflows input buffer.",
+                             dhcp_options [code].name,
+                             len);
+                       packet -> options_valid = 0;
+                       return;
+               }
+               /* If we haven't seen this option before, just make
+                  space for it and copy it there. */
+               if (!packet -> options [code].data) {
+                       if (!(t = (unsigned char *)malloc (len + 1)))
+                               error ("Can't allocate storage for option %s.",
+                                      dhcp_options [code].name);
+                       /* Copy and NUL-terminate the option (in case it's an
+                          ASCII string. */
+                       memcpy (t, &s [2], len);
+                       t [len] = 0;
+                       packet -> options [code].len = len;
+                       packet -> options [code].data = t;
+               } else {
+                       /* If it's a repeat, concatenate it to whatever
+                          we last saw.   This is really only required
+                          for clients, but what the heck... */
+                       t = (unsigned char *)
+                               malloc (len + packet -> options [code].len);
+                       if (!t)
+                               error ("Can't expand storage for option %s.",
+                                      dhcp_options [code].name);
+                       memcpy (t, packet -> options [code].data,
+                               packet -> options [code].len);
+                       memcpy (t + packet -> options [code].len,
+                               &s [2], len);
+                       packet -> options [code].len += len;
+                       t [packet -> options [code].len] = 0;
+                       free (packet -> options [code].data);
+                       packet -> options [code].data = t;
+               }
+               s += len + 2;
+       }
+       packet -> options_valid = 1;
+}
+
+/* Cons up options based on client-supplied desired option list (if any)
+   and selected server option list. */
+
+void cons_options (inpacket, outpacket, hp, overload)
+       struct packet *inpacket;
+       struct dhcp_packet *outpacket;
+       struct host_decl *hp;
+       int overload;   /* Overload flags that may be set. */
+{
+       option_mask options_have;       /* Options we can send. */
+       option_mask options_want;       /* Options client wants. */
+       option_mask options_done;       /* Options we've already encoded. */
+       option_mask temp;               /* Working option mask. */
+       unsigned char *priority_list;
+       int priority_len;
+       unsigned char *buffer = inpacket -> raw -> options;
+       int buflen, bufix;
+       int reserved = 3;               /* Reserved space for overload. */
+       unsigned char *overload_ptr = (unsigned char *)0;
+       int stored_length [256];
+       int missed = 0;
+       int missed_code;
+       int missed_length;
+       int result;
+       int i;
+
+       /* If there's no place to overload with options, don't save space
+          for an overload option. */
+       if (!overload)
+               reserved = 0;
+
+       /* Zero out the stored-lengths array. */
+       memset (stored_length, 0, sizeof stored_length);
+
+       /* If the client has provided a maximum DHCP message size,
+          use that.   Otherwise, we use the default MTU size (576 bytes). */
+       /* XXX Maybe it would be safe to assume that we can send a packet
+          to the client that's as big as the one it sent us, even if it
+          didn't specify a large MTU. */
+       if (inpacket -> options [DHO_DHCP_MAX_MESSAGE_SIZE].data)
+               buflen = (getUShort (inpacket -> options
+                                    [DHO_DHCP_MAX_MESSAGE_SIZE].data)
+                         - DHCP_FIXED_LEN);
+       else
+               buflen = 576 - DHCP_FIXED_LEN;
+
+       /* If the client has provided a list of options that it wishes
+          returned, use it to prioritize. */
+       if (inpacket -> options [DHO_DHCP_PARAMETER_REQUEST_LIST].data) {
+               priority_list =
+                       inpacket -> options
+                               [DHO_DHCP_PARAMETER_REQUEST_LIST].data;
+               priority_len =
+                       inpacket -> options
+                               [DHO_DHCP_PARAMETER_REQUEST_LIST].len;
+       } else {
+       /* Otherwise, prioritize based on the default priority list. */
+               priority_list = dhcp_option_default_priority_list;
+               priority_len = sizeof_dhcp_option_default_priority_list;
+       }
+
+       /* Make a bitmask of all the options the client wants. */
+       OPTION_ZERO (options_want);
+       for (i = 0; i < priority_len; i++)
+               OPTION_SET (options_want, priority_list [i]);
+
+       /* Make a bitmask of all the options we have available. */
+       OPTION_ZERO (options_have);
+       for (i = 0; i < 256; i++)
+               if (hp -> options [i])
+                       OPTION_SET (options_have, i);
+       
+      again:
+       /* Try copying out options that fit easily. */
+       for (i = 0; i < priority_len; i++) {
+               /* Code for next option to try to store. */
+               int code = priority_list [i];
+
+               /* Number of bytes left to store (some may already
+                  have been stored by a previous pass). */
+               int length;
+
+               /* If no data is available for this option, skip it. */
+               if (!hp -> options [code])
+                       continue;
+
+               /* Don't look at options that have already been stored. */
+               if (OPTION_ISSET (options_done, code))
+                       continue;
+
+               /* Find the value of the option... */
+               if (!tree_evaluate (hp -> options [code]))
+                       continue;
+
+               /* We should now have a constant length for the option. */
+               length = (hp -> options [code] -> len - stored_length [code]);
+
+               /* If there's no space for this option, skip it. */
+               if ((bufix + OPTION_SPACE (length) + reserved) > buflen) {
+                       /* If this is the first missed option, remember it. */
+                       if (++missed == 1) {
+                               missed_code = code;
+                               missed_length = length;
+                       }
+                       continue;
+               }
+               
+               /* Otherwise, store the option. */
+               result = store_option (outpacket, code,
+                                      buffer + bufix,
+                                      buflen - bufix - reserved,
+                                      stored_length);
+               bufix += result;
+
+               /* The following test should always succeed because of
+                  preconditioning above. */
+               if (stored_length [code] == hp -> options [code] -> len)
+                       OPTION_SET (options_done, code);
+               else {
+                       warn ("%s: Only stored %d out of %d bytes.",
+                             dhcp_options [code].name,
+                             stored_length [code],
+                             hp -> options [code] -> len);
+                       if (++missed == 1) {
+                               missed_code = code;
+                               missed_length = hp -> options [code] -> len
+                                       - stored_length [code];
+                       }
+               }
+       }
+
+       /* If we didn't miss any options, we're done. */
+       /* XXX Maybe we want to try to encode options the client didn't
+          request but that we have available? */
+       if (!missed)
+               return;
+
+       /* If we did miss one or more options, they must not have fit.
+          It's possible, though, that there's only one option left to
+          store, and that it would fit if we weren't reserving space
+          for the overload option.   In that case, we want to avoid
+          overloading. */
+       if (reserved && missed == 1
+           && (bufix + OPTION_SPACE (missed_length) <= buflen)) {
+               result = store_option (outpacket, missed_code,
+                                      buffer + bufix, buflen - bufix,
+                                      stored_length);
+               bufix += result;
+               /* This test should always fail -- we'll send bad
+                  data if it doesn't. */
+               if (stored_length [missed_code]
+                   == hp -> options [missed_code] -> len) {
+                       OPTION_SET (options_done, missed_code);
+               } else {
+                       warn ("%s (last): Only stored %d out of %d bytes.",
+                             dhcp_options [missed_code].name,
+                             stored_length [missed_code],
+                             hp -> options [missed_code] -> len);
+               }
+               return;
+       }
+
+       /* We've crammed in all the options that completely fit in
+          the current buffer, but maybe we can fit part of the next
+          option into the current buffer and part into the next. */
+       if (bufix + OPTION_SPACE (missed_length) + reserved
+           < buflen + (overload & 1 ? 128 : 0) + (overload & 2 ? 64 : 0)) {
+               result = store_option (outpacket, missed_code,
+                                      buffer + bufix,
+                                      buflen - bufix - reserved,
+                                      stored_length);
+               bufix += result;
+
+               /* This test should never fail. */
+               if (stored_length [missed_code]
+                   == hp -> options [missed_code] -> len) {
+                       OPTION_SET (options_done, missed_code);
+                       warn ("%s: Unexpected completed store.",
+                             dhcp_options [missed_code].name);
+               }
+       }
+
+       /* Okay, nothing else is going to fit in the current buffer
+          except possibly the override option.   Store that. */
+       if (reserved) {
+               buffer [bufix++] = DHO_DHCP_OPTION_OVERLOAD;
+               buffer [bufix++] = 1;
+               overload_ptr = buffer + bufix;
+               buffer [bufix++] = 0;
+               /* If there's space, store an End option code. */
+               if (bufix < buflen)
+                       buffer [bufix++] = DHO_END;
+               /* If there's still space, pad it. */
+               while (bufix < buflen)
+                       buffer [bufix++] = DHO_PAD;
+       }
+           
+       /* If we've fallen through to here, we still have options to
+          store, and may be able to overload options into the file
+          and server name fields of the DHCP packet. */
+
+       /* We should have stored an overload option by now if we're
+          going to need it, so if this test fails, there's a programming
+          error somewhere above. */
+       if (overload && !overload_ptr) {
+               warn ("Need to overload, but didn't store overload option!");
+               return;
+       }
+
+       /* Can we use the file buffer? */
+       if (overload & 1) {
+               buffer = inpacket -> raw -> file;
+               buflen = sizeof inpacket -> raw -> file;
+               bufix = 0;
+               overload &= ~1;
+               goto again;
+       }
+       /* Can we use the sname buffer? */
+       if (overload & 2) {
+               buffer = inpacket -> raw -> sname;
+               buflen = sizeof inpacket -> raw -> sname;
+               bufix = 0;
+               overload &= ~2;
+               goto again;
+       }
+
+       warn ("Insufficient packet space for all options.");
+}
+
+/* Copy the option data specified by code from the packet structure's
+   option array into an option buffer specified by buf and buflen,
+   updating stored_length[code] to reflect the amount of code's option
+   data that has been stored so far.   Return 1 if all the option data
+   has been stored. */
+   
+int store_option (packet, code, buffer, buflen, stored_length)
+       struct packet *packet;
+       unsigned char code;
+       unsigned char *buffer;
+       int buflen;
+       int *stored_length;
+{
+       int length = packet -> options [code].len - stored_length [code];
+       int bufix = 0;
+       int rv = 1;
+       if (length > buflen) {
+               rv = 0;
+               length = buflen;
+       }
+
+       /* If the option's length is more than 255, we must store it
+          in multiple hunks.   Store 255-byte hunks first. */
+       /* XXX Might a client lose its cookies if options aren't
+          chunked out so that each chunk is aligned to the size
+          of the data being represented? */
+       while (length) {
+               unsigned char incr = length > 255 ? 255 : length;
+               buffer [bufix] = code;
+               buffer [bufix + 1] = incr;
+               memcpy (buffer + bufix + 2, (packet -> options [code].data
+                                            + stored_length [code]), incr);
+               length -= incr;
+               stored_length [code] += incr;
+               bufix += 2 + incr;
+       }
+       return rv;
+}
+
+/* Format the specified option so that a human can easily read it. */
+
+char *pretty_print_option (code, data, len)
+       unsigned char code;
+       unsigned char *data;
+       int len;
+{
+       static char optbuf [32768]; /* XXX */
+       int hunksize = 0;
+       int numhunk = -1;
+       int numelem = 0;
+       char fmtbuf [32];
+       int i, j;
+       char *op = optbuf;
+       unsigned char *dp = data;
+       struct in_addr foo;
+
+       /* Figure out the size of the data. */
+       for (i = 0; dhcp_options [code].format [i]; i++) {
+               if (!numhunk) {
+                       warn ("%s: Excess information in format string: %s\n",
+                             dhcp_options [code].name,
+                             &(dhcp_options [code].format [i]));
+                       break;
+               }
+               numelem++;
+               fmtbuf [i] = dhcp_options [code].format [i];
+               switch (dhcp_options [code].format [i]) {
+                     case 'A':
+                       --numelem;
+                       fmtbuf [i] = 0;
+                       numhunk = 0;
+                       break;
+                     case 't':
+                       fmtbuf [i] = 't';
+                       fmtbuf [i + 1] = 0;
+                       numhunk = -2;
+                       break;
+                     case 'I':
+                     case 'l':
+                     case 'L':
+                       hunksize += 4;
+                       break;
+                     case 's':
+                     case 'S':
+                       hunksize += 2;
+                       break;
+                     case 'b':
+                     case 'B':
+                     case 'f':
+                       hunksize++;
+                       break;
+                     case 'e':
+                       break;
+                     default:
+                       warn ("%s: garbage in format string: %s\n",
+                             dhcp_options [code].name,
+                             &(dhcp_options [code].format [i]));
+                       break;
+               } 
+       }
+
+       /* Check for too few bytes... */
+       if (hunksize > len) {
+               warn ("%s: expecting at least %d bytes; got %d",
+                     dhcp_options [code].name,
+                     hunksize, len);
+               return "<error>";
+       }
+       /* Check for too many bytes... */
+       if (numhunk == -1 && hunksize < len)
+               warn ("%s: %d extra bytes",
+                     dhcp_options [code].name,
+                     len - hunksize);
+
+       /* If this is an array, compute its size. */
+       if (!numhunk)
+               numhunk = len / hunksize;
+       /* See if we got an exact number of hunks. */
+       if (numhunk > 0 && numhunk * hunksize < len)
+               warn ("%s: %d extra bytes at end of array\n",
+                     dhcp_options [code].name,
+                     len - numhunk * hunksize);
+
+       /* A one-hunk array prints the same as a single hunk. */
+       if (numhunk < 0)
+               numhunk = 1;
+
+printf ("numhunk = %d  numelem = %d\n", numhunk, numelem);
+       /* Cycle through the array (or hunk) printing the data. */
+       for (i = 0; i < numhunk; i++) {
+               for (j = 0; j < numelem; j++) {
+                       switch (fmtbuf [j]) {
+                             case 't':
+                               strcpy (op, dp);
+                               break;
+                             case 'I':
+                               foo.s_addr = htonl (getULong (dp));
+                               strcpy (op, inet_ntoa (foo));
+                               dp += 4;
+                               break;
+                             case 'l':
+                               sprintf (op, "%ld", getLong (dp));
+                               dp += 4;
+                               break;
+                             case 'L':
+                               sprintf (op, "%ld", getULong (dp));
+                               dp += 4;
+                               break;
+                             case 's':
+                               sprintf (op, "%d", getShort (dp));
+                               dp += 2;
+                               break;
+                             case 'S':
+                               sprintf (op, "%d", getUShort (dp));
+                               dp += 2;
+                               break;
+                             case 'b':
+                               sprintf (op, "%d", *(char *)dp++);
+                               break;
+                             case 'B':
+                               sprintf (op, "%d", *dp++);
+                               break;
+                             case 'f':
+                               strcpy (op, *dp++ ? "true" : "false");
+                               break;
+                             default:
+                               warn ("Unexpected format code %c", fmtbuf [j]);
+                       }
+                       op += strlen (op);
+                       *op++ = ' ';
+               }
+       }
+       *--op = 0;
+       return optbuf;
+}
+
+                       
+               
diff --git a/common/print.c b/common/print.c
new file mode 100644 (file)
index 0000000..85e79fc
--- /dev/null
@@ -0,0 +1,65 @@
+/* print.c
+
+   Turn data structures into printable text. */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+char *print_hw_addr (htype, hlen, data)
+       int htype;
+       int hlen;
+       unsigned char *data;
+{
+       static char habuf [49];
+       char *s;
+       int i;
+
+       s = habuf;
+       for (i = 0; i < hlen; i++) {
+               sprintf (s, "%x", data [i]);
+               s += strlen (s);
+               *s++ = ':';
+       }
+       *--s = 0;
+       return habuf;
+}
+
diff --git a/common/socket.c b/common/socket.c
new file mode 100644 (file)
index 0000000..1ee6eb7
--- /dev/null
@@ -0,0 +1,208 @@
+/* socket.c
+
+   BSD socket interface code... */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+#include <sys/ioctl.h>
+
+/* List of sockets we're accepting packets on... */
+struct socklist {
+       struct socklist *next;
+       struct sockaddr_in addr;
+       int sock;
+} *sockets;
+
+/* Return the list of IP addresses associated with each network interface. */
+
+u_int32_t *get_interface_list (count)
+       int *count;
+{
+       u_int32_t *intbuf = (u_int32_t *)0;
+       static char buf [8192];
+       struct ifconf ic;
+       int i;
+       int sock;
+       int ifcount = 0;
+       int ifix = 0;
+
+       /* Create an unbound datagram socket to do the SIOCGIFADDR ioctl on. */
+       if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+               error ("Can't create addrlist socket");
+
+       /* Get the interface configuration information... */
+       ic.ifc_len = sizeof buf;
+       ic.ifc_ifcu.ifcu_buf = (caddr_t)buf;
+       i = ioctl(sock, SIOCGIFCONF, &ic);
+       close (sock);
+       if (i < 0)
+               error ("ioctl: SIOCGIFCONF: %m");
+
+      again:
+       /* Cycle through the list of interfaces looking for IP addresses.
+          Go through twice; once to count the number if addresses, and a
+          second time to copy them into an array of addresses. */
+       for (i = 0; i < ic.ifc_len;) {
+               struct ifreq *ifp = (struct ifreq *)((caddr_t)ic.ifc_req + i);
+               i += (sizeof ifp -> ifr_name) + ifp -> ifr_addr.sa_len;
+               if (ifp -> ifr_addr.sa_family == AF_INET) {
+                       struct sockaddr_in *foo =
+                               (struct sockaddr_in *)(&ifp -> ifr_addr);
+                       /* We don't want the loopback interface. */
+                       if (foo -> sin_addr.s_addr == INADDR_LOOPBACK)
+                               continue;
+                       if (intbuf)
+                               intbuf [ifix++] = foo -> sin_addr.s_addr;
+                       else
+                               ++ifcount;
+               }
+       }
+       /* If we haven't already filled our array, allocate it and go
+          again. */
+       if (!intbuf) {
+               intbuf = (u_int32_t *)dmalloc ((ifcount + 1)
+                                              * sizeof (u_int32_t),
+                                              "get_interface_list");
+               if (!intbuf)
+                       return intbuf;
+               goto again;
+       }
+       *count = ifcount;
+       return intbuf;
+}
+
+void listen_on (port, address)
+       u_int16_t port;
+       u_int32_t address;
+{
+       struct sockaddr_in name;
+       int sock;
+       struct socklist *tmp;
+       int flag;
+
+       name.sin_family = AF_INET;
+       name.sin_port = port;
+       name.sin_addr.s_addr = address;
+       memset (name.sin_zero, 0, sizeof (name.sin_zero));
+
+       /* List addresses on which we're listening. */
+       note ("Receiving on %s, port %d",
+             inet_ntoa (name.sin_addr), htons (name.sin_port));
+       if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+               error ("Can't create dhcp socket: %m");
+
+       flag = 1;
+       if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
+                       &flag, sizeof flag) < 0)
+               error ("Can't set SO_REUSEADDR option on dhcp socket: %m");
+
+       if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST,
+                       &flag, sizeof flag) < 0)
+               error ("Can't set SO_BROADCAST option on dhcp socket: %m");
+
+       if (bind (sock, (struct sockaddr *)&name, sizeof name) < 0)
+               error ("Can't bind to dhcp address: %m");
+
+       tmp = (struct socklist *)dmalloc (sizeof (struct socklist),
+                                         "listen_on");
+       if (!tmp)
+               error ("Can't allocate memory for socket list.");
+       tmp -> addr = name;
+       tmp -> sock = sock;
+       tmp -> next = sockets;
+       sockets = tmp;
+}
+
+unsigned char packbuf [65536]; /* Should cover the gnarliest MTU... */
+
+void dispatch ()
+{
+       struct sockaddr_in from;
+       int fromlen = sizeof from;
+       fd_set r, w, x;
+       struct socklist *l;
+       int max = 0;
+       int count;
+       int result;
+
+       FD_ZERO (&r);
+       FD_ZERO (&w);
+       FD_ZERO (&x);
+
+       do {
+               /* Set up the read mask. */
+               for (l = sockets; l; l = l -> next) {
+                       FD_SET (l -> sock, &r);
+                       FD_SET (l -> sock, &x);
+                       if (l -> sock > max)
+                               max = l -> sock;
+               }
+
+               /* Wait for a packet or a timeout... XXX */
+               count = select (max + 1, &r, &w, &x, (struct timeval *)0);
+
+               /* Not likely to be transitory... */
+               if (count < 0)
+                       error ("select: %m");
+
+               for (l = sockets; l; l = l -> next) {
+                       if (!FD_ISSET (l -> sock, &r))
+                               continue;
+                       if ((result =
+                            recvfrom (l -> sock, packbuf, sizeof packbuf, 0,
+                                      (struct sockaddr *)&from, &fromlen))
+                           < 0) {
+                               warn ("recvfrom failed on %s: %m",
+                                     inet_ntoa (l -> addr.sin_addr));
+                               sleep (5);
+                               continue;
+                       }
+                       note ("request from %s, port %d",
+                             inet_ntoa (from.sin_addr),
+                             htons (from.sin_port));
+                       do_packet (packbuf, result, &from, fromlen, l -> sock);
+               }
+       } while (1);
+}
+
diff --git a/common/tables.c b/common/tables.c
new file mode 100644 (file)
index 0000000..30b1ebd
--- /dev/null
@@ -0,0 +1,414 @@
+/* tables.c
+
+   Tables of information... */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+/* DHCP Option names, formats and codes, from RFC1533.
+
+   Format codes:
+
+   e - end of data
+   I - IP address
+   l - 32-bit signed integer
+   L - 32-bit unsigned integer
+   s - 16-bit signed integer
+   S - 16-bit unsigned integer
+   b - 8-bit signed integer
+   B - 8-bit unsigned integer
+   t - ASCII text
+   f - flag (true or false)
+   A - array of whatever precedes (e.g., IA means array of IP addresses)
+*/
+
+struct universe dhcp_universe;
+struct option dhcp_options [256] = {
+       "pad", "",                                      &dhcp_universe, 0,
+       "subnet-mask", "I",                             &dhcp_universe, 1,
+       "time-offset", "l",                             &dhcp_universe, 2,
+       "routers", "IA",                                &dhcp_universe, 3,
+       "time-servers", "IA",                           &dhcp_universe, 4,
+       "name-servers", "IA",                           &dhcp_universe, 5,
+       "domain-name-servers", "IA",                    &dhcp_universe, 6,
+       "log-servers", "IA",                            &dhcp_universe, 7,
+       "cookie-servers", "IA",                         &dhcp_universe, 8,
+       "lpr-servers", "IA",                            &dhcp_universe, 9,
+       "impress-servers", "IA",                        &dhcp_universe, 10,
+       "resource-location-servers", "IA",              &dhcp_universe, 11,
+       "host-name", "t",                               &dhcp_universe, 12,
+       "boot-size", "S",                               &dhcp_universe, 13,
+       "merit-dump", "t",                              &dhcp_universe, 14,
+       "domain-name", "t",                             &dhcp_universe, 15,
+       "swap-server", "I",                             &dhcp_universe, 16,
+       "root-path", "t",                               &dhcp_universe, 17,
+       "extensions-path", "t",                         &dhcp_universe, 18,
+       "ip-forwarding", "f",                           &dhcp_universe, 19,
+       "non-local-source-routing", "f",                &dhcp_universe, 20,
+       "policy-filter", "IIA",                         &dhcp_universe, 21,
+       "max-dgram-reassembly", "S",                    &dhcp_universe, 22,
+       "default-ip-ttl", "B",                          &dhcp_universe, 23,
+       "path-mtu-aging-timeout", "L",                  &dhcp_universe, 24,
+       "path-mtu-plateau-table", "SA",                 &dhcp_universe, 25,
+       "interface-mtu", "S",                           &dhcp_universe, 26,
+       "all-subnets-local", "f",                       &dhcp_universe, 27,
+       "broadcast-address", "I",                       &dhcp_universe, 28,
+       "perform-mask-discovery", "f",                  &dhcp_universe, 29,
+       "mask-supplier", "f",                           &dhcp_universe, 30,
+       "router-discovery", "f",                        &dhcp_universe, 31,
+       "router-solicitation-address", "I",             &dhcp_universe, 32,
+       "static-routes", "IIA",                         &dhcp_universe, 33,
+       "trailer-encapsulation", "f",                   &dhcp_universe, 34,
+       "arp-cache-timeout", "L",                       &dhcp_universe, 35,
+       "ieee802.3-encapsulation", "f",                 &dhcp_universe, 36,
+       "default-tcp-ttl", "B",                         &dhcp_universe, 37,
+       "tcp-keepalive-interval", "L",                  &dhcp_universe, 38,
+       "tcp-keepalive-garbage", "f",                   &dhcp_universe, 39,
+       "nis-domain", "t",                              &dhcp_universe, 40,
+       "nis-servers", "IA",                            &dhcp_universe, 41,
+       "ntp-servers", "IA",                            &dhcp_universe, 42,
+       "vendor-encapsulated-options", "t",             &dhcp_universe, 43,
+       "netbios-name-servers", "IA",                   &dhcp_universe, 44,
+       "netbios-dd-server", "IA",                      &dhcp_universe, 45,
+       "netbios-node-type", "B",                       &dhcp_universe, 46,
+       "netbios-scope", "t",                           &dhcp_universe, 47,
+       "font-servers", "IA",                           &dhcp_universe, 48,
+       "x-display-manager", "IA",                      &dhcp_universe, 49,
+       "dhcp-requested-address", "I",                  &dhcp_universe, 50,
+       "dhcp-lease-time", "L",                         &dhcp_universe, 51,
+       "dhcp-option-overload", "B",                    &dhcp_universe, 52,
+       "dhcp-message-type", "B",                       &dhcp_universe, 53,
+       "dhcp-server-identifier", "I",                  &dhcp_universe, 54,
+       "dhcp-parameter-request-list", "BA",            &dhcp_universe, 55,
+       "dhcp-message", "t",                            &dhcp_universe, 56,
+       "dhcp-max-message-size", "S",                   &dhcp_universe, 57,
+       "dhcp-renewal-time", "L",                       &dhcp_universe, 58,
+       "dhcp-rebinding-time", "L",                     &dhcp_universe, 59,
+       "dhcp-class-identifier", "t",                   &dhcp_universe, 60,
+       "dhcp-client-identifier", "t",                  &dhcp_universe, 61,
+       "option-62", "",                                &dhcp_universe, 62,
+       "option-63", "",                                &dhcp_universe, 63,
+       "option-64", "",                                &dhcp_universe, 64,
+       "option-65", "",                                &dhcp_universe, 65,
+       "option-66", "",                                &dhcp_universe, 66,
+       "option-67", "",                                &dhcp_universe, 67,
+       "option-68", "",                                &dhcp_universe, 68,
+       "option-69", "",                                &dhcp_universe, 69,
+       "option-70", "",                                &dhcp_universe, 70,
+       "option-71", "",                                &dhcp_universe, 71,
+       "option-72", "",                                &dhcp_universe, 72,
+       "option-73", "",                                &dhcp_universe, 73,
+       "option-74", "",                                &dhcp_universe, 74,
+       "option-75", "",                                &dhcp_universe, 75,
+       "option-76", "",                                &dhcp_universe, 76,
+       "option-77", "",                                &dhcp_universe, 77,
+       "option-78", "",                                &dhcp_universe, 78,
+       "option-79", "",                                &dhcp_universe, 79,
+       "option-80", "",                                &dhcp_universe, 80,
+       "option-81", "",                                &dhcp_universe, 81,
+       "option-82", "",                                &dhcp_universe, 82,
+       "option-83", "",                                &dhcp_universe, 83,
+       "option-84", "",                                &dhcp_universe, 84,
+       "option-85", "",                                &dhcp_universe, 85,
+       "option-86", "",                                &dhcp_universe, 86,
+       "option-87", "",                                &dhcp_universe, 87,
+       "option-88", "",                                &dhcp_universe, 88,
+       "option-89", "",                                &dhcp_universe, 89,
+       "option-90", "",                                &dhcp_universe, 90,
+       "option-91", "",                                &dhcp_universe, 91,
+       "option-92", "",                                &dhcp_universe, 92,
+       "option-93", "",                                &dhcp_universe, 93,
+       "option-94", "",                                &dhcp_universe, 94,
+       "option-95", "",                                &dhcp_universe, 95,
+       "option-96", "",                                &dhcp_universe, 96,
+       "option-97", "",                                &dhcp_universe, 97,
+       "option-98", "",                                &dhcp_universe, 98,
+       "option-99", "",                                &dhcp_universe, 99,
+       "option-100", "",                               &dhcp_universe, 100,
+       "option-101", "",                               &dhcp_universe, 101,
+       "option-102", "",                               &dhcp_universe, 102,
+       "option-103", "",                               &dhcp_universe, 103,
+       "option-104", "",                               &dhcp_universe, 104,
+       "option-105", "",                               &dhcp_universe, 105,
+       "option-106", "",                               &dhcp_universe, 106,
+       "option-107", "",                               &dhcp_universe, 107,
+       "option-108", "",                               &dhcp_universe, 108,
+       "option-109", "",                               &dhcp_universe, 109,
+       "option-110", "",                               &dhcp_universe, 110,
+       "option-111", "",                               &dhcp_universe, 111,
+       "option-112", "",                               &dhcp_universe, 112,
+       "option-113", "",                               &dhcp_universe, 113,
+       "option-114", "",                               &dhcp_universe, 114,
+       "option-115", "",                               &dhcp_universe, 115,
+       "option-116", "",                               &dhcp_universe, 116,
+       "option-117", "",                               &dhcp_universe, 117,
+       "option-118", "",                               &dhcp_universe, 118,
+       "option-119", "",                               &dhcp_universe, 119,
+       "option-120", "",                               &dhcp_universe, 120,
+       "option-121", "",                               &dhcp_universe, 121,
+       "option-122", "",                               &dhcp_universe, 122,
+       "option-123", "",                               &dhcp_universe, 123,
+       "option-124", "",                               &dhcp_universe, 124,
+       "option-125", "",                               &dhcp_universe, 125,
+       "option-126", "",                               &dhcp_universe, 126,
+       "option-127", "",                               &dhcp_universe, 127,
+       "option-128", "",                               &dhcp_universe, 128,
+       "option-129", "",                               &dhcp_universe, 129,
+       "option-130", "",                               &dhcp_universe, 130,
+       "option-131", "",                               &dhcp_universe, 131,
+       "option-132", "",                               &dhcp_universe, 132,
+       "option-133", "",                               &dhcp_universe, 133,
+       "option-134", "",                               &dhcp_universe, 134,
+       "option-135", "",                               &dhcp_universe, 135,
+       "option-136", "",                               &dhcp_universe, 136,
+       "option-137", "",                               &dhcp_universe, 137,
+       "option-138", "",                               &dhcp_universe, 138,
+       "option-139", "",                               &dhcp_universe, 139,
+       "option-140", "",                               &dhcp_universe, 140,
+       "option-141", "",                               &dhcp_universe, 141,
+       "option-142", "",                               &dhcp_universe, 142,
+       "option-143", "",                               &dhcp_universe, 143,
+       "option-144", "",                               &dhcp_universe, 144,
+       "option-145", "",                               &dhcp_universe, 145,
+       "option-146", "",                               &dhcp_universe, 146,
+       "option-147", "",                               &dhcp_universe, 147,
+       "option-148", "",                               &dhcp_universe, 148,
+       "option-149", "",                               &dhcp_universe, 149,
+       "option-150", "",                               &dhcp_universe, 150,
+       "option-151", "",                               &dhcp_universe, 151,
+       "option-152", "",                               &dhcp_universe, 152,
+       "option-153", "",                               &dhcp_universe, 153,
+       "option-154", "",                               &dhcp_universe, 154,
+       "option-155", "",                               &dhcp_universe, 155,
+       "option-156", "",                               &dhcp_universe, 156,
+       "option-157", "",                               &dhcp_universe, 157,
+       "option-158", "",                               &dhcp_universe, 158,
+       "option-159", "",                               &dhcp_universe, 159,
+       "option-160", "",                               &dhcp_universe, 160,
+       "option-161", "",                               &dhcp_universe, 161,
+       "option-162", "",                               &dhcp_universe, 162,
+       "option-163", "",                               &dhcp_universe, 163,
+       "option-164", "",                               &dhcp_universe, 164,
+       "option-165", "",                               &dhcp_universe, 165,
+       "option-166", "",                               &dhcp_universe, 166,
+       "option-167", "",                               &dhcp_universe, 167,
+       "option-168", "",                               &dhcp_universe, 168,
+       "option-169", "",                               &dhcp_universe, 169,
+       "option-170", "",                               &dhcp_universe, 170,
+       "option-171", "",                               &dhcp_universe, 171,
+       "option-172", "",                               &dhcp_universe, 172,
+       "option-173", "",                               &dhcp_universe, 173,
+       "option-174", "",                               &dhcp_universe, 174,
+       "option-175", "",                               &dhcp_universe, 175,
+       "option-176", "",                               &dhcp_universe, 176,
+       "option-177", "",                               &dhcp_universe, 177,
+       "option-178", "",                               &dhcp_universe, 178,
+       "option-179", "",                               &dhcp_universe, 179,
+       "option-180", "",                               &dhcp_universe, 180,
+       "option-181", "",                               &dhcp_universe, 181,
+       "option-182", "",                               &dhcp_universe, 182,
+       "option-183", "",                               &dhcp_universe, 183,
+       "option-184", "",                               &dhcp_universe, 184,
+       "option-185", "",                               &dhcp_universe, 185,
+       "option-186", "",                               &dhcp_universe, 186,
+       "option-187", "",                               &dhcp_universe, 187,
+       "option-188", "",                               &dhcp_universe, 188,
+       "option-189", "",                               &dhcp_universe, 189,
+       "option-190", "",                               &dhcp_universe, 190,
+       "option-191", "",                               &dhcp_universe, 191,
+       "option-192", "",                               &dhcp_universe, 192,
+       "option-193", "",                               &dhcp_universe, 193,
+       "option-194", "",                               &dhcp_universe, 194,
+       "option-195", "",                               &dhcp_universe, 195,
+       "option-196", "",                               &dhcp_universe, 196,
+       "option-197", "",                               &dhcp_universe, 197,
+       "option-198", "",                               &dhcp_universe, 198,
+       "option-199", "",                               &dhcp_universe, 199,
+       "option-200", "",                               &dhcp_universe, 200,
+       "option-201", "",                               &dhcp_universe, 201,
+       "option-202", "",                               &dhcp_universe, 202,
+       "option-203", "",                               &dhcp_universe, 203,
+       "option-204", "",                               &dhcp_universe, 204,
+       "option-205", "",                               &dhcp_universe, 205,
+       "option-206", "",                               &dhcp_universe, 206,
+       "option-207", "",                               &dhcp_universe, 207,
+       "option-208", "",                               &dhcp_universe, 208,
+       "option-209", "",                               &dhcp_universe, 209,
+       "option-210", "",                               &dhcp_universe, 210,
+       "option-211", "",                               &dhcp_universe, 211,
+       "option-212", "",                               &dhcp_universe, 212,
+       "option-213", "",                               &dhcp_universe, 213,
+       "option-214", "",                               &dhcp_universe, 214,
+       "option-215", "",                               &dhcp_universe, 215,
+       "option-216", "",                               &dhcp_universe, 216,
+       "option-217", "",                               &dhcp_universe, 217,
+       "option-218", "",                               &dhcp_universe, 218,
+       "option-219", "",                               &dhcp_universe, 219,
+       "option-220", "",                               &dhcp_universe, 220,
+       "option-221", "",                               &dhcp_universe, 221,
+       "option-222", "",                               &dhcp_universe, 222,
+       "option-223", "",                               &dhcp_universe, 223,
+       "option-224", "",                               &dhcp_universe, 224,
+       "option-225", "",                               &dhcp_universe, 225,
+       "option-226", "",                               &dhcp_universe, 226,
+       "option-227", "",                               &dhcp_universe, 227,
+       "option-228", "",                               &dhcp_universe, 228,
+       "option-229", "",                               &dhcp_universe, 229,
+       "option-230", "",                               &dhcp_universe, 230,
+       "option-231", "",                               &dhcp_universe, 231,
+       "option-232", "",                               &dhcp_universe, 232,
+       "option-233", "",                               &dhcp_universe, 233,
+       "option-234", "",                               &dhcp_universe, 234,
+       "option-235", "",                               &dhcp_universe, 235,
+       "option-236", "",                               &dhcp_universe, 236,
+       "option-237", "",                               &dhcp_universe, 237,
+       "option-238", "",                               &dhcp_universe, 238,
+       "option-239", "",                               &dhcp_universe, 239,
+       "option-240", "",                               &dhcp_universe, 240,
+       "option-241", "",                               &dhcp_universe, 241,
+       "option-242", "",                               &dhcp_universe, 242,
+       "option-243", "",                               &dhcp_universe, 243,
+       "option-244", "",                               &dhcp_universe, 244,
+       "option-245", "",                               &dhcp_universe, 245,
+       "option-246", "",                               &dhcp_universe, 246,
+       "option-247", "",                               &dhcp_universe, 247,
+       "option-248", "",                               &dhcp_universe, 248,
+       "option-249", "",                               &dhcp_universe, 249,
+       "option-250", "",                               &dhcp_universe, 250,
+       "option-251", "",                               &dhcp_universe, 251,
+       "option-252", "",                               &dhcp_universe, 252,
+       "option-253", "",                               &dhcp_universe, 253,
+       "option-254", "",                               &dhcp_universe, 254,
+       "option-end", "e",                              &dhcp_universe, 255,
+};
+
+/* Default dhcp option priority list (this is ad hoc and should not be
+   mistaken for a carefully crafted and optimized list). */
+unsigned char dhcp_option_default_priority_list [] = {
+       DHO_SUBNET_MASK,
+       DHO_TIME_OFFSET,
+       DHO_ROUTERS,
+       DHO_TIME_SERVERS,
+       DHO_NAME_SERVERS,
+       DHO_DOMAIN_NAME_SERVERS,
+       DHO_LOG_SERVERS,
+       DHO_COOKIE_SERVERS,
+       DHO_LPR_SERVERS,
+       DHO_IMPRESS_SERVERS,
+       DHO_RESOURCE_LOCATION_SERVERS,
+       DHO_HOST_NAME,
+       DHO_BOOT_SIZE,
+       DHO_MERIT_DUMP,
+       DHO_DOMAIN_NAME,
+       DHO_SWAP_SERVER,
+       DHO_ROOT_PATH,
+       DHO_EXTENSIONS_PATH,
+       DHO_IP_FORWARDING,
+       DHO_NON_LOCAL_SOURCE_ROUTING,
+       DHO_POLICY_FILTER,
+       DHO_MAX_DGRAM_REASSEMBLY,
+       DHO_DEFAULT_IP_TTL,
+       DHO_PATH_MTU_AGING_TIMEOUT,
+       DHO_PATH_MTU_PLATEAU_TABLE,
+       DHO_INTERFACE_MTU,
+       DHO_ALL_SUBNETS_LOCAL,
+       DHO_BROADCAST_ADDRESS,
+       DHO_PERFORM_MASK_DISCOVERY,
+       DHO_MASK_SUPPLIER,
+       DHO_ROUTER_DISCOVERY,
+       DHO_ROUTER_SOLICITATION_ADDRESS,
+       DHO_STATIC_ROUTES,
+       DHO_TRAILER_ENCAPSULATION,
+       DHO_ARP_CACHE_TIMEOUT,
+       DHO_IEEE802_3_ENCAPSULATION,
+       DHO_DEFAULT_TCP_TTL,
+       DHO_TCP_KEEPALIVE_INTERVAL,
+       DHO_TCP_KEEPALIVE_GARBAGE,
+       DHO_NIS_DOMAIN,
+       DHO_NIS_SERVERS,
+       DHO_NTP_SERVERS,
+       DHO_VENDOR_ENCAPSULATED_OPTIONS,
+       DHO_NETBIOS_NAME_SERVERS,
+       DHO_NETBIOS_DD_SERVER,
+       DHO_NETBIOS_NODE_TYPE,
+       DHO_NETBIOS_SCOPE,
+       DHO_FONT_SERVERS,
+       DHO_X_DISPLAY_MANAGER,
+       DHO_DHCP_REQUESTED_ADDRESS,
+       DHO_DHCP_LEASE_TIME,
+       DHO_DHCP_OPTION_OVERLOAD,
+       DHO_DHCP_MESSAGE_TYPE,
+       DHO_DHCP_SERVER_IDENTIFIER,
+       DHO_DHCP_PARAMETER_REQUEST_LIST,
+       DHO_DHCP_MESSAGE,
+       DHO_DHCP_MAX_MESSAGE_SIZE,
+       DHO_DHCP_RENEWAL_TIME,
+       DHO_DHCP_REBINDING_TIME,
+       DHO_DHCP_CLASS_IDENTIFIER,
+       DHO_DHCP_CLIENT_IDENTIFIER,
+};
+
+int sizeof_dhcp_option_default_priority_list =
+       sizeof dhcp_option_default_priority_list;
+
+
+struct hash_table universe_hash;
+
+void initialize_universes()
+{
+       int i;
+
+       dhcp_universe.name = "dhcp";
+       dhcp_universe.hash = new_hash ();
+       if (!dhcp_universe.hash)
+               error ("Can't allocate dhcp option hash table.");
+       for (i = 0; i < 256; i++) {
+               dhcp_universe.options [i] = &dhcp_options [i];
+               add_hash (dhcp_universe.hash, dhcp_options [i].name, 0,
+                         (unsigned char *)&dhcp_options [i]);
+       }
+       universe_hash.hash_count = DEFAULT_HASH_SIZE;
+       add_hash (&universe_hash, dhcp_universe.name, 0,
+                 (unsigned char *)&dhcp_universe);
+}
diff --git a/common/tree.c b/common/tree.c
new file mode 100644 (file)
index 0000000..3b3e894
--- /dev/null
@@ -0,0 +1,391 @@
+/* tree.c
+
+   Routines for manipulating parse trees... */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+static TIME tree_evaluate_recurse PROTO ((int *, unsigned char **, int *,
+                                         struct tree *));
+static TIME do_host_lookup PROTO ((int *, unsigned char **, int *,
+                                         struct dns_host_entry *));
+static void do_data_copy PROTO ((int *, unsigned char **, int *,
+                                unsigned char *, int));
+
+pair cons (car, cdr)
+       caddr_t car;
+       pair cdr;
+{
+       pair foo = (pair)dmalloc (sizeof *foo, "cons");
+       if (!foo)
+               error ("no memory for cons.");
+       foo -> car = car;
+       foo -> cdr = cdr;
+       return foo;
+}
+
+struct tree_cache *tree_cache (tree)
+       struct tree *tree;
+{
+       struct tree_cache *tc;
+
+       tc = new_tree_cache ("tree_cache");
+       if (!tc)
+               return 0;
+       tc -> value = (char *)0;
+       tc -> len = tc -> buf_size = 0;
+       tc -> timeout = 0;
+       tc -> tree = tree;
+       return tc;
+}
+
+struct tree *tree_host_lookup (name)
+       char *name;
+{
+       struct tree *nt;
+       nt = new_tree ("tree_host_lookup");
+       if (!nt)
+               error ("No memory for host lookup tree node.");
+       nt -> op = TREE_HOST_LOOKUP;
+       nt -> data.host_lookup.host = enter_dns_host (name);
+       return nt;
+}
+
+struct dns_host_entry *enter_dns_host (name)
+       char *name;
+{
+       struct dns_host_entry *dh;
+
+       if (!(dh = (struct dns_host_entry *)dmalloc
+             (sizeof (struct dns_host_entry), "enter_dns_host"))
+           || !(dh -> hostname = dmalloc (strlen (name) + 1,
+                                          "enter_dns_host")))
+               error ("Can't allocate space for new host.");
+       strcpy (dh -> hostname, name);
+       dh -> data = (unsigned char *)0;
+       dh -> data_len = 0;
+       dh -> timeout = 0;
+       return dh;
+}
+
+struct tree *tree_const (data, len)
+       unsigned char *data;
+       int len;
+{
+       struct tree *nt;
+       if (!(nt = new_tree ("tree_const"))
+           || !(nt -> data.const_val.data =
+                (unsigned char *)dmalloc (len, "tree_const")))
+               error ("No memory for constant data tree node.");
+       nt -> op = TREE_CONST;
+       memcpy (nt -> data.const_val.data, data, len);
+       nt -> data.const_val.len = len;
+       return nt;
+}
+
+struct tree *tree_concat (left, right)
+       struct tree *left, *right;
+{
+       struct tree *nt;
+
+       /* If we're concatenating a null tree to a non-null tree, just
+          return the non-null tree; if both trees are null, return
+          a null tree. */
+       if (!left)
+               return right;
+       if (!right)
+               return left;
+
+       /* If both trees are constant, combine them. */
+       if (left -> op = TREE_CONST && right -> op == TREE_CONST) {
+               unsigned char *buf = dmalloc (left -> data.const_val.len
+                                             + right -> data.const_val.len,
+                                             "tree_concat");
+               if (!buf)
+                       error ("No memory to concatenate constants.");
+               memcpy (buf, left -> data.const_val.data,
+                       left -> data.const_val.len);
+               memcpy (buf + left -> data.const_val.len,
+                       right -> data.const_val.data,
+                       right -> data.const_val.len);
+               dfree (left -> data.const_val.data, "tree_concat");
+               dfree (right -> data.const_val.data, "tree_concat");
+               left -> data.const_val.data = buf;
+               left -> data.const_val.len += right -> data.const_val.len;
+               free_tree (right, "tree_concat");
+               return left;
+       }
+                       
+       /* Otherwise, allocate a new node to concatenate the two. */
+       if (!(nt = new_tree ("tree_concat")))
+               error ("No memory for data tree concatenation node.");
+       nt -> op = TREE_CONCAT;
+       nt -> data.concat.left = left;
+       nt -> data.concat.right = right;
+       return nt;
+}
+
+struct tree *tree_limit (tree, limit)
+       struct tree *tree;
+       int limit;
+{
+       struct tree *rv;
+
+       /* If the tree we're limiting is constant, limit it now. */
+       if (tree -> op == TREE_CONST) {
+               if (tree -> data.const_val.len > limit)
+                       tree -> data.const_val.len = limit;
+               return tree;
+       }
+
+       /* Otherwise, put in a node which enforces the limit on evaluation. */
+       rv = new_tree ("tree_limit");
+       if (!rv)
+               return (struct tree *)0;
+       rv -> op = TREE_LIMIT;
+       rv -> data.limit.tree = tree;
+       rv -> data.limit.limit = limit;
+       return rv;
+}
+
+int tree_evaluate (tree_cache)
+       struct tree_cache *tree_cache;
+{
+       unsigned char *bp = tree_cache -> value;
+       int bc = tree_cache -> buf_size;
+       int bufix = 0;
+
+       /* If there's no tree associated with this cache, it evaluates
+          to a constant and that was detected at startup. */
+       if (!tree_cache -> tree)
+               return 1;
+
+       /* Try to evaluate the tree without allocating more memory... */
+       tree_cache -> timeout = tree_evaluate_recurse (&bufix, &bp, &bc,
+                                                      tree_cache -> tree);
+
+       /* No additional allocation needed? */
+       if (bufix <= bc) {
+               tree_cache -> len = bufix;
+               return 1;
+       }
+
+       /* If we can't allocate more memory, return with what we
+          have (maybe nothing). */
+       if (!(bp = (unsigned char *)dmalloc (bufix, "tree_evaluate")))
+               return 0;
+
+       /* Record the change in conditions... */
+       bc = bufix;
+       bufix = 0;
+
+       /* Note that the size of the result shouldn't change on the
+          second call to tree_evaluate_recurse, since we haven't
+          changed the ``current'' time. */
+       tree_evaluate_recurse (&bufix, &bp, &bc, tree_cache -> tree);
+
+       /* Free the old buffer if needed, then store the new buffer
+          location and size and return. */
+       if (tree_cache -> value)
+               dfree (tree_cache -> value, "tree_evaluate");
+       tree_cache -> value = bp;
+       tree_cache -> len = bufix;
+       tree_cache -> buf_size = bc;
+       return 1;
+}
+
+static TIME tree_evaluate_recurse (bufix, bufp, bufcount, tree)
+       int *bufix;
+       unsigned char **bufp;
+       int *bufcount;
+       struct tree *tree;
+{
+       int limit;
+       TIME t1, t2;
+
+       switch (tree -> op) {
+             case TREE_CONCAT:
+               t1 = tree_evaluate_recurse (bufix, bufp, bufcount,
+                                          tree -> data.concat.left);
+               t2 = tree_evaluate_recurse (bufix, bufp, bufcount,
+                                          tree -> data.concat.right);
+               if (t1 > t2)
+                       return t2;
+               return t1;
+
+             case TREE_HOST_LOOKUP:
+               return do_host_lookup (bufix, bufp, bufcount,
+                                      tree -> data.host_lookup.host);
+
+             case TREE_CONST:
+               do_data_copy (bufix, bufp, bufcount,
+                             tree -> data.const_val.data,
+                             tree -> data.const_val.len);
+               t1 = MAX_TIME;
+               return t1;
+
+             case TREE_LIMIT:
+               limit = *bufix + tree -> data.limit.limit;
+               t1 = tree_evaluate_recurse (bufix, bufp, bufcount,
+                                           tree -> data.limit.tree);
+               *bufix = limit;
+               return t1;
+
+             default:
+               warn ("Bad node id in tree: %d.");
+               t1 = MAX_TIME;
+               return t1;
+       }
+}
+
+static TIME do_host_lookup (bufix, bufp, bufcount, dns)
+       int *bufix;
+       unsigned char **bufp;
+       int *bufcount;
+       struct dns_host_entry *dns;
+{
+       struct hostent *h;
+       int i;
+       int new_len;
+
+       debug ("time: now = %d  dns = %d %d  diff = %d",
+              cur_time, dns -> timeout, cur_time - dns -> timeout);
+
+       /* If the record hasn't timed out, just copy the data and return. */
+       if (cur_time <= dns -> timeout) {
+               debug ("easy copy: %x %d %x",
+                      dns -> data, dns -> data_len, *(int *)(dns -> data));
+               do_data_copy (bufix, bufp, bufcount,
+                             dns -> data, dns -> data_len);
+               return dns -> timeout;
+       }
+       debug ("Looking up %s", dns -> hostname);
+
+       /* Otherwise, look it up... */
+       h = gethostbyname (dns -> hostname);
+       if (!h) {
+               switch (h_errno) {
+                     case HOST_NOT_FOUND:
+                       warn ("%s: host unknown.", dns -> hostname);
+                       break;
+                     case TRY_AGAIN:
+                       warn ("%s: temporary name server failure",
+                             dns -> hostname);
+                       break;
+                     case NO_RECOVERY:
+                       warn ("%s: name server failed", dns -> hostname);
+                       break;
+                     case NO_DATA:
+                       warn ("%s: no A record associated with address",
+                             dns -> hostname);
+               }
+
+               /* Okay to try again after a minute. */
+               return cur_time + 60;
+       }
+
+       debug ("Lookup succeeded; first address is %x",
+              h -> h_addr_list [0]);
+
+       /* Count the number of addresses we got... */
+       for (i = 0; h -> h_addr_list [i]; i++)
+               ;
+       
+       /* Do we need to allocate more memory? */
+       new_len = i * h -> h_length;
+       if (dns -> buf_len < i) {
+               unsigned char *buf =
+                       (unsigned char *)dmalloc (new_len, "do_host_lookup");
+               /* If we didn't get more memory, use what we have. */
+               if (!buf) {
+                       new_len = dns -> buf_len;
+                       if (!dns -> buf_len) {
+                               dns -> timeout = cur_time + 60;
+                               return dns -> timeout;
+                       }
+               } else {
+                       dfree (dns -> data, "do_host_lookup");
+                       dns -> data = buf;
+                       dns -> buf_len = new_len;
+               }
+       }
+
+       /* Addresses are conveniently stored one to the buffer, so we
+          have to copy them out one at a time... :'( */
+       for (i = 0; i < new_len / h -> h_length; i++)
+               memcpy (dns -> data + h -> h_length * i,
+                       h -> h_addr_list [i], h -> h_length);
+       debug ("dns -> data: %x  h -> h_addr_list [0]: %x",
+              *(int *)(dns -> data), h -> h_addr_list [0]);
+       dns -> data_len = new_len;
+
+       /* Set the timeout for an hour from now.
+          XXX This should really use the time on the DNS reply. */
+       dns -> timeout = cur_time + 3600;
+
+       debug ("hard copy: %x %d %x",
+              dns -> data, dns -> data_len, *(int *)(dns -> data));
+       do_data_copy (bufix, bufp, bufcount, dns -> data, dns -> data_len);
+       return dns -> timeout;
+}
+
+static void do_data_copy (bufix, bufp, bufcount, data, len)
+       int *bufix;
+       unsigned char **bufp;
+       int *bufcount;
+       unsigned char *data;
+       int len;
+{
+       int space = *bufcount - *bufix;
+
+       /* If there's more space than we need, use only what we need. */
+       if (space > len)
+               space = len;
+
+       /* Copy as much data as will fit, then increment the buffer index
+          by the amount we actually had to copy, which could be more. */
+       if (space > 0)
+               memcpy (*bufp + *bufix, data, space);
+       *bufix += len;
+}
diff --git a/conf.y b/conf.y
new file mode 100644 (file)
index 0000000..28ce4f4
--- /dev/null
+++ b/conf.y
@@ -0,0 +1,114 @@
+/* conf.y
+
+   Dhcpd configuration file grammar... */
+
+/*
+ * Copyright (c) 1995 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"
+%}
+
+%token HOST HARDWARE ETHERNET FILENAME FIXED_ADDRESS STRING
+%token OCTET COLON DOT SEMI TOKEN OPTION
+
+%start config
+
+%%
+config :       config_items
+       ;
+
+
+config_items:  /* blank */
+       |       config_item
+       |       config_items config_item
+       ;
+
+config_item:   host_decl
+       ;
+
+host_decl:     HOST hostname packet_decls SEMI
+       ;
+
+hostname:      token
+       |       token DOT hostname
+       ;
+
+packet_decls:  /* empty */
+       |       packet_decl
+       |       packet_decls packet_decl
+       ;
+
+packet_decl:   hardware_decl
+       |       filename_decl
+       |       fixed_addr_decl
+       |       option_decl
+       ;
+
+hardware_decl: HARDWARE ETHERNET OCTET COLON OCTET COLON OCTET
+                                       COLON OCTET COLON OCTET COLON OCTET
+       ;
+
+filename_decl: FILENAME STRING
+       ;
+
+fixed_addr_decl: FIXED_ADDRESS host_address
+       ;
+
+host_address:  hostname
+       |       ip_address
+       ;
+
+ip_address:    OCTET DOT OCTET
+       |       OCTET DOT OCTET DOT OCTET DOT OCTET
+       ;
+
+option_decl:   OPTION token STRING
+       ;
+
+token:         reserved_word
+       |       TOKEN
+       ;
+
+reserved_word: HOST
+       |       HARDWARE
+       |       ETHERNET
+       |       FILENAME
+       |       FIXED_ADDRESS
+       |       OPTION
+       ;
+
diff --git a/conflex.c b/conflex.c
new file mode 100644 (file)
index 0000000..a7b56dd
--- /dev/null
+++ b/conflex.c
@@ -0,0 +1,280 @@
+/* conflex.c
+
+   Lexical scanner for dhcpd config file... */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+#include "dhctoken.h"
+#include <ctype.h>
+
+static int line;
+static int lpos;
+int tlpos;
+int tline;
+static int token;
+static int ugflag;
+static char *tval;
+static char tokbuf [1500];
+
+static int get_char PROTO ((FILE *));
+static int get_token PROTO ((FILE *));
+static void skip_to_eol PROTO ((FILE *));
+static int read_string PROTO ((FILE *));
+static int read_number PROTO ((int, FILE *));
+static int read_num_or_atom PROTO ((int, FILE *));
+static int intern PROTO ((char *, int));
+
+static int get_char (cfile)
+       FILE *cfile;
+{
+       char c = getc (cfile);
+       if (!ugflag) {
+               if (c == EOL) {
+                       line++;
+                       lpos = 1;
+               } else {
+                       lpos++;
+               }
+       } else
+               ugflag = 0;
+       return c;               
+}
+
+static int get_token (cfile)
+       FILE *cfile;
+{
+       int c;
+       int i;
+       int ttok;
+
+       do {
+               c = get_char (cfile);
+               if (isascii (c) && isspace (c))
+                       continue;
+               if (c == '#') {
+                       skip_to_eol (cfile);
+                       continue;
+               }
+               tlpos = lpos;
+               tline = line;
+               if (c == '"') {
+                       ttok = read_string (cfile);
+                       break;
+               }
+               if (isascii (c) && isdigit (c)) {
+                       ttok = read_number (c, cfile);
+                       break;
+               } else if (isascii (c) && isalpha (c)) {
+                       ttok = read_num_or_atom (c, cfile);
+                       break;
+               } else {
+                       tval = 0;
+                       ttok = c;
+                       break;
+               }
+       } while (1);
+       return ttok;
+}
+
+int next_token (rval, cfile)
+       char **rval;
+       FILE *cfile;
+{
+       int rv;
+
+       if (token) {
+               rv = token;
+               token = 0;
+       } else {
+               rv = get_token (cfile);
+       }
+       if (rval)
+               *rval = tval;
+       return rv;
+}
+
+int peek_token (rval, cfile)
+       char **rval;
+       FILE *cfile;
+{
+       if (!token)
+               token = get_token (cfile);
+       if (rval)
+               *rval = tval;
+       return token;
+}
+
+static void skip_to_eol (cfile)
+       FILE *cfile;
+{
+       int c;
+       do {
+               c = get_char (cfile);
+               if (c == EOF)
+                       return;
+               if (c == EOL) {
+                       ungetc (c, cfile);
+                       ugflag = 1;
+                       return;
+               }
+       } while (1);
+}
+
+static int read_string (cfile)
+       FILE *cfile;
+{
+       int i;
+       int bs = 0;
+       int c;
+
+       for (i = 0; i < sizeof tokbuf; i++) {
+               c = get_char (cfile);
+               if (c == EOF) {
+                       parse_warn ("eof in string constant");
+                       break;
+               }
+               if (bs) {
+                       bs = 0;
+                       tokbuf [i] = c;
+               } else if (c == '\\')
+                       bs = 1;
+               else if (c == '"')
+                       break;
+               else
+                       tokbuf [i] = c;
+       }
+       /* Normally, I'd feel guilty about this, but we're talking about
+          strings that'll fit in a DHCP packet here... */
+       if (i == sizeof tokbuf) {
+               parse_warn ("string constant larger than internal buffer");
+               --i;
+       }
+       tokbuf [i] = 0;
+       tval = tokbuf;
+       return STRING;
+}
+
+static int read_number (c, cfile)
+       int c;
+       FILE *cfile;
+{
+       int seenx = 0;
+       int i = 0;
+       tokbuf [i++] = c;
+       for (; i < sizeof tokbuf; i++) {
+               c = get_char (cfile);
+               if (!seenx && c == 'x')
+                       seenx = 1;
+               else if (!isascii (c) || !isxdigit (c)) {
+                       ungetc (c, cfile);
+                       ugflag = 1;
+                       break;
+               }
+               tokbuf [i] = c;
+       }
+       if (i == sizeof tokbuf) {
+               parse_warn ("numeric token larger than internal buffer");
+               --i;
+       }
+       tokbuf [i] = 0;
+       tval = tokbuf;
+       return NUMBER;
+}
+
+static int read_num_or_atom (c, cfile)
+       int c;
+       FILE *cfile;
+{
+       int i = 0;
+       int rv = NUMBER_OR_ATOM;
+       tokbuf [i++] = c;
+       for (; i < sizeof tokbuf; i++) {
+               c = get_char (cfile);
+               if (!isascii (c) ||
+                   (c != '-' && c != '_' && !isalnum (c))) {
+                       ungetc (c, cfile);
+                       ugflag = 1;
+                       break;
+               }
+               if (!isxdigit (c))
+                       rv = ATOM;
+               tokbuf [i] = c;
+       }
+       if (i == sizeof tokbuf) {
+               parse_warn ("token larger than internal buffer");
+               --i;
+       }
+       tokbuf [i] = 0;
+       tval = tokbuf;
+       return intern (tval, rv);
+}
+
+static int intern (atom, dfv)
+       char *atom;
+       int dfv;
+{
+       switch (atom [0]) {
+             case 'h':
+               if (!strcasecmp (atom + 1, "ost"))
+                       return HOST;
+               if (!strcasecmp (atom + 1, "ardware"))
+                       return HARDWARE;
+               break;
+             case 'f':
+               if (!strcasecmp (atom + 1, "ilename"))
+                       return FILENAME;
+               if (!strcasecmp (atom + 1, "ixed-address"))
+                       return FIXED_ADDR;
+               break;
+             case 'e':
+               if (!strcasecmp (atom + 1, "thernet"))
+                       return ETHERNET;
+               break;
+             case 'o':
+               if (!strcasecmp (atom + 1, "ption"))
+                       return OPTION;
+               break;
+       }
+       return dfv;
+}
diff --git a/confpars.c b/confpars.c
new file mode 100644 (file)
index 0000000..05de625
--- /dev/null
@@ -0,0 +1,1048 @@
+/* confpars.c
+
+   Parser for dhcpd config file... */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+#include "dhctoken.h"
+
+static TIME parsed_time;
+
+/* conf-file :== statements
+   declarations :== <nil> | declaration | declarations declaration */
+
+void readconf (void)
+{
+       FILE *cfile;
+       char *val;
+       int token;
+
+       /* Set up the initial dhcp option universe. */
+       initialize_universes ();
+
+       if ((cfile = fopen (_PATH_DHCPD_CONF, "r")) == NULL)
+               error ("Can't open %s: %m", _PATH_DHCPD_CONF);
+       do {
+               token = peek_token (&val, cfile);
+               if (token == EOF)
+                       break;
+               parse_statement (cfile);
+       } while (1);
+}
+
+/* statement :== host_statement */
+
+void parse_statement (cfile)
+       FILE *cfile;
+{
+       char *val;
+       jmp_buf bc;
+
+       switch (next_token (&val, cfile)) {
+             case HOST:
+               if (!setjmp (bc)) {
+                       struct host_decl *hd =
+                               parse_host_statement (cfile, &bc);
+                       if (hd) {
+                               enter_host (hd);
+                       }
+               }
+               break;
+             case LEASE:
+               if (!setjmp (bc)) {
+                       struct lease *lease =
+                               parse_lease_statement (cfile, &bc);
+                       enter_lease (lease);
+               }
+               break;
+             case TIMESTAMP:
+               if (!setjmp (bc)) {
+                       parsed_time = parse_timestamp (cfile, &bc);
+               }
+               break;
+             case RANGE:
+               if (!setjmp (bc)) {
+                       parse_address_range (cfile, &bc);
+               }
+               break;
+             default:
+               parse_warn ("expecting a declaration.");
+               skip_to_semi (cfile);
+               break;
+       }
+}
+
+void skip_to_semi (cfile)
+       FILE *cfile;
+{
+       int token;
+       char *val;
+
+       do {
+               token = next_token (&val, cfile);
+       } while (token != SEMI && token != EOF);
+}
+
+/* host_statement :== HOST hostname declarations SEMI
+   host_declarations :== <nil> | host_declaration
+                              | host_declarations host_declaration */
+
+struct host_decl *parse_host_statement (cfile, bc)
+       FILE *cfile;
+       jmp_buf *bc;
+{
+       char *val;
+       int token;
+       struct host_decl tmp, *perm;
+
+       memset (&tmp, 0, sizeof tmp);
+       tmp.name = parse_host_name (cfile, bc);
+       do {
+               token = peek_token (&val, cfile);
+               if (token == SEMI) {
+                       token = next_token (&val, cfile);
+                       break;
+               }
+               parse_host_decl (cfile, bc, &tmp);
+       } while (1);
+       perm = (struct host_decl *)malloc (sizeof (struct host_decl));
+       if (!perm)
+               error ("can't allocate host decl struct for %s.", tmp.name);
+       *perm = tmp;
+       return perm;
+}
+
+/* host_name :== identifier | host_name DOT identifier */
+
+char *parse_host_name (cfile, bc)
+       FILE *cfile;
+       jmp_buf *bc;
+{
+       char *val;
+       int token;
+       int len = 0;
+       char *s;
+       char *t;
+       pair c = (pair)0;
+       
+       /* Read a dotted hostname... */
+       do {
+               /* Read a token, which should be an identifier. */
+               token = next_token (&val, cfile);
+               if (!is_identifier (token)) {
+                       parse_warn ("expecting an identified in hostname");
+                       skip_to_semi (cfile);
+                       longjmp (*bc, 1);
+               }
+               /* Store this identifier... */
+               if (!(s = (char *)malloc (strlen (val) + 1)))
+                       error ("can't allocate temp space for hostname.");
+               strcpy (s, val);
+               c = cons ((caddr_t)s, c);
+               len += strlen (s) + 1;
+               /* Look for a dot; if it's there, keep going, otherwise
+                  we're done. */
+               token = peek_token (&val, cfile);
+               if (token == DOT)
+                       token = next_token (&val, cfile);
+       } while (token == DOT);
+
+       /* Assemble the hostname together into a string. */
+       if (!(s = (char *)malloc (len)))
+               error ("can't allocate space for hostname.");
+       t = s + len;
+       *--t = 0;
+       while (c) {
+               pair cdr = c -> cdr;
+               int l = strlen ((char *)(c -> car));
+               t -= l;
+               memcpy (t, (char *)(c -> car), l);
+               /* Free up temp space. */
+               free (c -> car);
+               free (c);
+               c = cdr;
+               if (t != s)
+                       *--t = '.';
+       }
+       return s;
+}
+
+/* host_declaration :== hardware_declaration | filename_declaration
+                     | fixed_addr_declaration | option_declaration */
+
+void parse_host_decl (cfile, bc, decl)
+       FILE *cfile;
+       jmp_buf *bc;
+       struct host_decl *decl;
+{
+       char *val;
+       int token;
+
+       token = next_token (&val, cfile);
+       switch (token) {
+             case HARDWARE:
+               parse_hardware_decl (cfile, bc, decl);
+               break;
+             case FILENAME:
+               parse_filename_decl (cfile, bc, decl);
+               break;
+             case FIXED_ADDR:
+               parse_fixed_addr_decl (cfile, bc, decl);
+               break;
+             case OPTION:
+               parse_option_decl (cfile, bc, decl);
+               break;
+             default:
+               parse_warn ("expecting a dhcp option declaration.");
+               skip_to_semi (cfile);
+               longjmp (*bc, 1);
+               break;
+       }
+}
+
+/* hardware_decl :== HARDWARE ETHERNET NUMBER COLON NUMBER COLON NUMBER COLON
+                                      NUMBER COLON NUMBER COLON NUMBER */
+
+void parse_hardware_decl (cfile, bc, decl)
+       FILE *cfile;
+       jmp_buf *bc;
+       struct host_decl *decl;
+{
+       char *val;
+       int token;
+       struct hardware hw;
+
+       hw = parse_hardware_addr (cfile, bc);
+
+       /* Find space for the new interface... */
+       if (decl -> interfaces) {
+               decl -> interfaces =
+                       (struct hardware *)realloc (decl -> interfaces,
+                                                   ++decl -> interface_count *
+                                                   sizeof (struct hardware));
+       } else {
+               decl -> interfaces =
+                       (struct hardware *)malloc (sizeof (struct hardware));
+               decl -> interface_count = 1;
+       }
+       if (!decl -> interfaces)
+               error ("no memory for hardware interface info.");
+
+       /* Copy out the information... */
+       decl -> interfaces [decl -> interface_count - 1].htype = hw.htype;
+       decl -> interfaces [decl -> interface_count - 1].hlen = hw.hlen;
+       memcpy (decl -> interfaces [decl -> interface_count - 1].haddr,
+               &hw.haddr, hw.hlen);
+}
+
+struct hardware parse_hardware_addr (cfile, bc)
+       FILE *cfile;
+       jmp_buf *bc;
+{
+       char *val;
+       int token;
+       int hlen;
+       struct hardware rv;
+
+       token = next_token (&val, cfile);
+       switch (token) {
+             case ETHERNET:
+               rv.htype = ARPHRD_ETHER;
+               hlen = 6;
+               parse_numeric_aggregate (cfile, bc,
+                                        (unsigned char *)&rv.haddr, &hlen,
+                                        COLON, 16, 8);
+               rv.hlen = hlen;
+               break;
+             default:
+               parse_warn ("expecting a network hardware type");
+               skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       return rv;
+}
+
+/* filename_decl :== FILENAME STRING */
+
+void parse_filename_decl (cfile, bc, decl)
+       FILE *cfile;
+       jmp_buf *bc;
+       struct host_decl *decl;
+{
+       char *val;
+       int token;
+       char *s;
+
+       token = next_token (&val, cfile);
+       if (token != STRING) {
+               parse_warn ("filename must be a string");
+               skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       s = (char *)malloc (strlen (val));
+       if (!s)
+               error ("no memory for filename.");
+       strcpy (s, val);
+       decl -> filename = s;
+}
+
+/* ip_addr_or_hostname :== ip_address | hostname
+   ip_address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
+   
+   Parse an ip address or a hostname.   If uniform is zero, put in
+   a TREE_LIMIT node to catch hostnames that evaluate to more than
+   one IP address. */
+
+struct tree *parse_ip_addr_or_hostname (cfile, bc, uniform)
+       FILE *cfile;
+       jmp_buf *bc;
+       int uniform;
+{
+       char *val;
+       int token;
+       unsigned char addr [4];
+       int len = sizeof addr;
+       char *name;
+       struct tree *rv;
+
+       token = peek_token (&val, cfile);
+       if (is_identifier (token)) {
+               name = parse_host_name (cfile, bc);
+               rv = tree_host_lookup (name);
+               if (!uniform)
+                       rv = tree_limit (rv, 4);
+       } else if (token == NUMBER) {
+               parse_numeric_aggregate (cfile, bc, addr, &len, DOT, 10, 8);
+               rv = tree_const (addr, len);
+       } else {
+               parse_warn ("%s (%d): expecting IP address or hostname",
+                           val, token);
+               skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       return rv;
+}      
+       
+
+/* fixed_addr_declaration :== FIXED_ADDR ip_addr_or_hostname */
+
+void parse_fixed_addr_decl (cfile, bc, decl)
+       FILE *cfile;
+       jmp_buf *bc;
+       struct host_decl *decl;
+{
+       decl -> fixed_addr =
+               tree_cache (parse_ip_addr_or_hostname (cfile, bc, 0));
+}
+
+/* option_declaration :== OPTION identifier DOT identifier <syntax> |
+                         OPTION identifier <syntax>
+
+   Option syntax is handled specially through format strings, so it
+   would be painful to come up with BNF for it.   However, it always
+   starts as above. */
+
+void parse_option_decl (cfile, bc, decl)
+       FILE *cfile;
+       jmp_buf *bc;
+       struct host_decl *decl;
+{
+       char *val;
+       int token;
+       unsigned char buf [4];
+       char *vendor;
+       char *fmt;
+       struct universe *universe;
+       struct option *option;
+       struct tree *tree = (struct tree *)0;
+
+       token = next_token (&val, cfile);
+       if (!is_identifier (token)) {
+               parse_warn ("expecting identifier after option keyword.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       vendor = dmalloc (strlen (val) + 1, "parse_option_decl");
+       strcpy (vendor, val);
+       token = peek_token (&val, cfile);
+       if (token == DOT) {
+               /* Go ahead and take the DOT token... */
+               token = next_token (&val, cfile);
+
+               /* The next token should be an identifier... */
+               token = next_token (&val, cfile);
+               if (!is_identifier (token)) {
+                       parse_warn ("expecting identifier after '.'");
+                       if (token != SEMI)
+                               skip_to_semi (cfile);
+                       longjmp (*bc, 1);
+               }
+
+               /* Look up the option name hash table for the specified
+                  vendor. */
+               universe = (struct universe *)hash_lookup (&universe_hash,
+                                                          vendor, 0);
+               /* If it's not there, we can't parse the rest of the
+                  statement. */
+               if (!universe) {
+                       parse_warn ("no vendor named %s.", vendor);
+                       skip_to_semi (cfile);
+                       longjmp (*bc, 1);
+               }
+       } else {
+               /* Use the default hash table, which contains all the
+                  standard dhcp option names. */
+               val = vendor;
+               universe = &dhcp_universe;
+       }
+
+       /* Look up the actual option info... */
+       option = (struct option *)hash_lookup (universe -> hash, val, 0);
+
+       /* If we didn't get an option structure, it's an undefined option. */
+       if (!option) {
+               if (val == vendor)
+                       parse_warn ("no option named %s", val);
+               else
+                       parse_warn ("no option named %s for vendor %s",
+                                   val, vendor);
+               skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+
+       /* Free the initial identifier token. */
+       free (vendor);
+
+       /* Parse the option data... */
+       do {
+               /* Set a flag if this is an array of a simple type (i.e.,
+                  not an array of pairs of IP addresses, or something
+                  like that. */
+               int uniform = option -> format [1] == 'A';
+
+               for (fmt = option -> format; *fmt; fmt++) {
+                       if (*fmt == 'A')
+                               break;
+                       switch (*fmt) {
+                             case 't': /* Text string... */
+                               token = next_token (&val, cfile);
+                               if (token != STRING
+                                   && !is_identifier (token)) {
+                                       parse_warn ("expecting string.");
+                                       if (token != SEMI)
+                                               skip_to_semi (cfile);
+                                       longjmp (*bc, 1);
+                               }
+                               tree = tree_concat (tree,
+                                                   tree_const (val,
+                                                               strlen (val)));
+                               break;
+
+                             case 'I': /* IP address or hostname. */
+                               tree = tree_concat (tree,
+                                                   parse_ip_addr_or_hostname
+                                                   (cfile, bc, uniform));
+                               break;
+
+                             case 'L': /* Unsigned 32-bit integer... */
+                             case 'l': /* Signed 32-bit integer... */
+                               token = next_token (&val, cfile);
+                               if (token != NUMBER) {
+                                     need_number:
+                                       parse_warn ("expecting number.");
+                                       if (token != SEMI)
+                                               skip_to_semi (cfile);
+                                       longjmp (*bc, 1);
+                               }
+                               convert_num (buf, val, 0, 32);
+                               tree = tree_concat (tree, tree_const (buf, 4));
+                               break;
+                             case 's': /* Signed 16-bit integer. */
+                             case 'S': /* Unsigned 16-bit integer. */
+                               token = next_token (&val, cfile);
+                               if (token != NUMBER)
+                                       goto need_number;
+                               convert_num (buf, val, 0, 16);
+                               tree = tree_concat (tree, tree_const (buf, 2));
+                               break;
+                             case 'b': /* Signed 8-bit integer. */
+                             case 'B': /* Unsigned 8-bit integer. */
+                               token = next_token (&val, cfile);
+                               if (token != NUMBER)
+                                       goto need_number;
+                               convert_num (buf, val, 0, 8);
+                               tree = tree_concat (tree, tree_const (buf, 1));
+                               break;
+                             case 'f': /* Boolean flag. */
+                               token = next_token (&val, cfile);
+                               if (!is_identifier (token)) {
+                                       parse_warn ("expecting identifier.");
+                                     bad_flag:
+                                       if (token != SEMI)
+                                               skip_to_semi (cfile);
+                                       longjmp (*bc, 1);
+                               }
+                               if (!strcasecmp (val, "true")
+                                   || !strcasecmp (val, "on"))
+                                       buf [0] = 1;
+                               else if (!strcasecmp (val, "false")
+                                        || !strcasecmp (val, "off"))
+                                       buf [0] = 0;
+                               else {
+                                       parse_warn ("expecting boolean.");
+                                       goto bad_flag;
+                               }
+                               tree = tree_concat (tree, tree_const (buf, 1));
+                               break;
+                             default:
+                               warn ("Bad format %c in parse_option_decl.",
+                                     *fmt);
+                               skip_to_semi (cfile);
+                               longjmp (*bc, 1);
+                       }
+               }
+               if (*fmt == 'A') {
+                       token = peek_token (&val, cfile);
+                       if (token == COMMA) {
+                               token = next_token (&val, cfile);
+                               continue;
+                       }
+                       break;
+               }
+       } while (*fmt == 'A');
+
+       if (decl -> options [option -> code]) {
+               parse_warn ("duplicate option code %d (%s).",
+                           option -> code, option -> name);
+       }
+       decl -> options [option -> code] = tree_cache (tree);
+}
+
+/* timestamp :== TIMESTAMP date
+
+   Timestamps are actually not used in dhcpd.conf, which is a static file,
+   but rather in the database file and the journal file. */
+
+TIME parse_timestamp (cfile, bc)
+       FILE *cfile;
+       jmp_buf *bc;
+{
+       return parse_date (cfile, bc);
+}
+               
+/* lease_decl :== LEASE ip_address lease_modifiers
+   lease_modifiers :== <nil>
+               |       lease_modifier
+               |       lease_modifier lease_modifiers
+   lease_modifier :==  STARTS date
+               |       ENDS date
+               |       UID hex_numbers
+               |       HOST identifier
+               |       CLASS identifier
+               |       TIMESTAMP number */
+
+struct lease *parse_lease_statement (cfile, bc)
+       FILE *cfile;
+       jmp_buf *bc;
+{
+       char *val;
+       int token;
+       unsigned char addr [4];
+       int len = sizeof addr;
+       char *name;
+       unsigned char *uid;
+       int seenmask = 0;
+       int seenbit;
+       char tbuf [32];
+       char ubuf [1024];
+       static struct lease lease;
+
+       /* Get the address for which the lease has been issued. */
+       parse_numeric_aggregate (cfile, bc, addr, &len, DOT, 10, 8);
+       memcpy (&lease.ip_addr, addr, len);
+
+       do {
+               token = next_token (&val, cfile);
+               if (token == SEMI)
+                       break;
+               strncpy (val, tbuf, sizeof tbuf);
+               tbuf [(sizeof tbuf) - 1] = 0;
+
+               /* Parse any of the times associated with the lease. */
+               if (token == STARTS || token == ENDS || token == TIMESTAMP) {
+                       TIME t;
+                       t = parse_date (cfile, bc);
+                       switch (token) {
+                             case STARTS:
+                               seenbit = 1;
+                               lease.starts = t;
+                               break;
+                       
+                             case ENDS:
+                               seenbit = 2;
+                               lease.ends = t;
+                               break;
+                               
+                             case TIMESTAMP:
+                               seenbit = 4;
+                               lease.timestamp = t;
+                               break;
+                       }
+               } else {
+                       switch (token) {
+                               /* Colon-seperated hexadecimal octets... */
+                             case UID:
+                               seenbit = 8;
+                               lease.uid_len = 0;
+                               parse_numeric_aggregate (cfile, bc, ubuf,
+                                                        &lease.uid_len,
+                                                        ':', 16, 8);
+                               lease.uid = (unsigned char *)
+                                       malloc (lease.uid_len);
+                               if (!lease.uid) {
+                                       error ("No memory for lease uid");
+                               }
+                               memcpy (lease.uid, ubuf, lease.uid_len);
+                               break;
+
+                             case HOST:
+                               seenbit = 16;
+                               token = next_token (&val, cfile);
+                               if (!is_identifier (token)) {
+                                       if (token != SEMI)
+                                               skip_to_semi (cfile);
+                                       longjmp (*bc, 1);
+                               }
+                               lease.host =
+                                       find_host_by_name (val);
+                               if (!lease.host)
+                                       parse_warn ("lease host ``%s'' is %s",
+                                                   lease.host,
+                                                   "no longer known.");
+                               break;
+                                       
+                             case CLASS:
+                               seenbit = 32;
+                               token = next_token (&val, cfile);
+                               if (!is_identifier (token)) {
+                                       if (token != SEMI)
+                                               skip_to_semi (cfile);
+                                       longjmp (*bc, 1);
+                               }
+                               /* for now, we aren't using this. */
+                               break;
+
+                             case HARDWARE:
+                               seenbit = 64;
+                               lease.hardware_addr
+                                       = parse_hardware_addr (cfile, bc);
+                               break;
+
+                             default:
+                               if (token != SEMI)
+                                       skip_to_semi (cfile);
+                               longjmp (*bc, 1);
+                       }
+               }
+               if (seenmask & seenbit) {
+                       parse_warn ("Too many %s declarations in lease %s\n",
+                                   tbuf, inet_ntoa (lease.ip_addr));
+               } else
+                       seenmask |= seenbit;
+       } while (1);
+       return &lease;
+}
+
+/* address_range :== RANGE ip_address ip_address ip_address */
+
+void parse_address_range (cfile, bc)
+       FILE *cfile;
+       jmp_buf *bc;
+{
+       struct in_addr low, high, mask;
+       unsigned char addr [4];
+       int len = sizeof addr;
+
+       /* Get the bottom address in the range... */
+       parse_numeric_aggregate (cfile, bc, addr, &len, DOT, 10, 8);
+       memcpy (&low, addr, len);
+
+       /* Get the top address in the range... */
+       parse_numeric_aggregate (cfile, bc, addr, &len, DOT, 10, 8);
+       memcpy (&high, addr, len);
+
+       /* Get the netmask of the subnet containing the range... */
+       parse_numeric_aggregate (cfile, bc, addr, &len, DOT, 10, 8);
+       memcpy (&mask, addr, len);
+
+       /* Create the new address range... */
+       new_address_range (low, high, mask);
+}
+
+/* date :== NUMBER NUMBER/NUMBER/NUMBER NUMBER:NUMBER:NUMBER
+
+   Dates are always in GMT; first number is day of week; next is
+   year/month/day; next is hours:minutes:seconds on a 24-hour
+   clock. */
+
+TIME parse_date (cfile, bc)
+       FILE *cfile;
+       jmp_buf *bc;
+{
+       TIME t;
+       struct tm tm;
+       char *val;
+       int token;
+
+       /* Day of week... */
+       token = next_token (&val, cfile);
+       if (token != NUMBER) {
+               parse_warn ("numeric day of week expected.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       tm.tm_wday = atoi (token);
+
+       /* Year... */
+       token = next_token (&val, cfile);
+       if (token != NUMBER) {
+               parse_warn ("numeric year expected.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       tm.tm_year = atoi (token);
+       if (tm.tm_year > 1900)
+               tm.tm_year -= 1900;
+
+       /* Slash seperating year from month... */
+       token = next_token (&val, cfile);
+       if (token != SLASH) {
+               parse_warn ("expected slash seperating year from month.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+
+       /* Month... */
+       token = next_token (&val, cfile);
+       if (token != NUMBER) {
+               parse_warn ("numeric month expected.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       tm.tm_mon = atoi (token);
+
+       /* Slash seperating month from day... */
+       token = next_token (&val, cfile);
+       if (token != SLASH) {
+               parse_warn ("expected slash seperating month from day.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+
+       /* Month... */
+       token = next_token (&val, cfile);
+       if (token != NUMBER) {
+               parse_warn ("numeric day of month expected.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       tm.tm_mday = atoi (token);
+
+       /* Hour... */
+       token = next_token (&val, cfile);
+       if (token != NUMBER) {
+               parse_warn ("numeric hour expected.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       tm.tm_hour = atoi (token);
+
+       /* Colon seperating hour from minute... */
+       token = next_token (&val, cfile);
+       if (token != COLON) {
+               parse_warn ("expected colon seperating hour from minute.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+
+       /* Minute... */
+       token = next_token (&val, cfile);
+       if (token != NUMBER) {
+               parse_warn ("numeric minute expected.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       tm.tm_min = atoi (token);
+
+       /* Colon seperating minute from second... */
+       token = next_token (&val, cfile);
+       if (token != COLON) {
+               parse_warn ("expected colon seperating hour from minute.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+
+       /* Minute... */
+       token = next_token (&val, cfile);
+       if (token != NUMBER) {
+               parse_warn ("numeric minute expected.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       tm.tm_sec = atoi (token);
+
+       tm.tm_zone = "GMT";
+       tm.tm_isdst = 0;
+       tm.tm_gmtoff = 0;
+
+       /* XXX */ /* We assume that mktime does not use tm_yday. */
+       tm.tm_yday = 0;
+
+       return mktime (&tm);
+}
+
+/* No BNF for numeric aggregates - that's defined by the caller.  What
+   this function does is to parse a sequence of numbers seperated by
+   the token specified in seperator.  If max is zero, any number of
+   numbers will be parsed; otherwise, exactly max numbers are
+   expected.  Base and size tell us how to internalize the numbers
+   once they've been tokenized. */
+
+unsigned char *parse_numeric_aggregate (cfile, bc, buf,
+                                       max, seperator, base, size)
+       FILE *cfile;
+       jmp_buf *bc;
+       unsigned char *buf;
+       int *max;
+       int seperator;
+       int base;
+       int size;
+{
+       char *val;
+       int token;
+       unsigned char *bufp = buf, *s, *t;
+       int count = 0;
+       pair c = (pair)0;
+
+       if (!bufp && *max) {
+               bufp = (unsigned char *)malloc (*max * size / 8);
+               if (!bufp)
+                       error ("can't allocate space for numeric aggregate");
+       } else
+               s = bufp;
+
+       do {
+               if (count) {
+                       token = peek_token (&val, cfile);
+                       if (token != seperator) {
+                               if (!*max)
+                                       break;
+                               parse_warn ("too few numbers.");
+                               skip_to_semi (cfile);
+                               longjmp (*bc, 1);
+                       }
+                       token = next_token (&val, cfile);
+               }
+               token = next_token (&val, cfile);
+               /* Allow NUMBER_OR_ATOM if base is 16. */
+               if (token != NUMBER &&
+                   (base != 16 || token != NUMBER_OR_ATOM)) {
+                       parse_warn ("expecting numeric value.");
+                       skip_to_semi (cfile);
+                       longjmp (*bc, 1);
+               }
+               /* If we can, convert the number now; otherwise, build
+                  a linked list of all the numbers. */
+               if (s) {
+                       convert_num (s, val, base, size);
+                       s += size / 8;
+               } else {
+                       t = (char *)malloc (strlen (val) + 1);
+                       if (!t)
+                               error ("no temp space for number.");
+                       strcpy (t, val);
+                       c = cons (t, c);
+               }
+       } while (++count != *max);
+
+       /* If we had to cons up a list, convert it now. */
+       if (c) {
+               bufp = (unsigned char *)malloc (count * size / 8);
+               if (!bufp)
+                       error ("can't allocate space for numeric aggregate.");
+               s = bufp;
+               *max = count;
+       }
+       while (c) {
+               pair cdr = c -> cdr;
+               convert_num (s, (char *)(c -> car), base, size);
+               s += size / 8;
+               /* Free up temp space. */
+               free (c -> car);
+               free (c);
+               c = cdr;
+       }
+       return bufp;
+}
+
+void convert_num (buf, str, base, size)
+       unsigned char *buf;
+       char *str;
+       int base;
+       int size;
+{
+       char *ptr = str;
+       int negative = 0;
+       u_int32_t val = 0;
+       int tval;
+       int max;
+
+       if (*ptr == '-') {
+               negative = 1;
+               ++ptr;
+       }
+
+       /* If base wasn't specified, figure it out from the data. */
+       if (!base) {
+               if (ptr [0] == '0') {
+                       if (ptr [1] == 'x') {
+                               base = 16;
+                               ptr += 2;
+                       } else if (isascii (ptr [1]) && isdigit (ptr [1])) {
+                               base = 8;
+                               ptr += 1;
+                       } else {
+                               base = 10;
+                       }
+               } else {
+                       base = 10;
+               }
+       }
+
+       do {
+               tval = *ptr++;
+               /* XXX assumes ASCII... */
+               if (tval >= 'a')
+                       tval = tval - 'a' + 10;
+               else if (tval >= 'A')
+                       tval = tval - 'A' + 10;
+               else if (tval >= '0')
+                       tval -= '0';
+               else {
+                       warn ("Bogus number: %s.", str);
+                       break;
+               }
+               if (tval >= base) {
+                       warn ("Bogus number: %s: digit %d not in base %d\n",
+                             str, tval, base);
+                       break;
+               }
+               val = val * base + tval;
+       } while (*ptr);
+
+       if (negative)
+               max = (1 << (size - 1));
+       else
+               max = (1 << size) - 1;
+       if (val > max) {
+               switch (base) {
+                     case 8:
+                       warn ("value %s%lo exceeds max (%d) for precision.",
+                             negative ? "-" : "", val, max);
+                       break;
+                     case 16:
+                       warn ("value %s%lx exceeds max (%d) for precision.",
+                             negative ? "-" : "", val, max);
+                       break;
+                     default:
+                       warn ("value %s%ld exceeds max (%d) for precision.",
+                             negative ? "-" : "", val, max);
+                       break;
+               }
+       }
+
+       if (negative) {
+               switch (size) {
+                     case 8:
+                       *buf = -(unsigned long)val;
+                       break;
+                     case 16:
+                       putShort (buf, -(unsigned long)val);
+                       break;
+                     case 32:
+                       putLong (buf, -(unsigned long)val);
+                       break;
+                     default:
+                       warn ("Unexpected integer size: %d\n");
+                       break;
+               }
+       } else {
+               switch (size) {
+                     case 8:
+                       *buf = (u_int8_t)val;
+                       break;
+                     case 16:
+                       putUShort (buf, (u_int16_t)val);
+                       break;
+                     case 32:
+                       putULong (buf, val);
+                       break;
+                     default:
+                       warn ("Unexpected integer size: %d\n");
+                       break;
+               }
+       }
+}
diff --git a/convert.c b/convert.c
new file mode 100644 (file)
index 0000000..bd423a0
--- /dev/null
+++ b/convert.c
@@ -0,0 +1,117 @@
+/* convert.c
+
+   Safe copying of option values into and out of the option buffer, which
+   can't be assumed to be aligned. */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+unsigned long getULong (buf)
+       unsigned char *buf;
+{
+       unsigned long ibuf;
+
+       memcpy (&ibuf, buf, sizeof (unsigned long));
+       return ntohl (ibuf);
+}
+
+long getLong (buf)
+       unsigned char *buf;
+{
+       long ibuf;
+
+       memcpy (&ibuf, buf, sizeof (long));
+       return ntohl (ibuf);
+}
+
+unsigned short getUShort (buf)
+       unsigned char *buf;
+{
+       unsigned short ibuf;
+
+       memcpy (&ibuf, buf, sizeof (unsigned short));
+       return ntohs (ibuf);
+}
+
+short getShort (buf)
+       unsigned char *buf;
+{
+       short ibuf;
+
+       memcpy (&ibuf, buf, sizeof (short));
+       return ntohs (ibuf);
+}
+
+void putULong (obuf, val)
+       unsigned char *obuf;
+       unsigned long val;
+{
+       unsigned long tmp = htonl (val);
+       memcpy (obuf, &tmp, sizeof tmp);
+}
+
+void putLong (obuf, val)
+       unsigned char *obuf;
+       long val;
+{
+       long tmp = htonl (val);
+       memcpy (obuf, &tmp, sizeof tmp);
+}
+
+void putUShort (obuf, val)
+       unsigned char *obuf;
+       unsigned short val;
+{
+       unsigned short tmp = htonl (val);
+       memcpy (obuf, &tmp, sizeof tmp);
+}
+
+void putShort (obuf, val)
+       unsigned char *obuf;
+       short val;
+{
+       short tmp = htonl (val);
+       memcpy (obuf, &tmp, sizeof tmp);
+}
+
diff --git a/db.c b/db.c
new file mode 100644 (file)
index 0000000..66f47b3
--- /dev/null
+++ b/db.c
@@ -0,0 +1,142 @@
+/* db.c
+
+   IP Address Allocation database... */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+/*
+   The IP Address Allocation Database tracks addresses that have been
+   allocated from the free pool as specified in dhcpd.conf.   The
+   database is maintained in two parts to maintain integrity: the
+   journal file and the data file.
+
+   Both files are free-form flat files similar to dhcpd.conf, but with
+   a more limited syntax - all that can be specified are leases and
+   who they belong to.
+
+   When dhcpd starts up, it reads the entire data file into memory.
+   It then reads the journal file into memory and makes corrections to
+   the data based on journal entries.
+
+   While dhcpd is running, it periodically records the current time,
+   forks (if possible) and dumps the recorded time and its internal
+   database of temporarily assigned addresses into a temporary file.
+   It then removes any existing backup file, renames the existing file
+   with the backup filename, and then renames the new temporary file
+   with the real data file name.  The link syscall is not present on
+   most systems, so a synchronous ``rename'' that guarantees that
+   exactly one file will be the master database may not be possible.
+   Therefore the recovery routine needs to know what to do if it finds
+   a backup and a temporary file, but no database file.
+
+   Whenever a client requests that an address be allocated to it, or
+   requests a lease renewal, and the server is able to satisfy the
+   request, it writes a record into the journal file indicating what
+   has been requested and waits for that information to reach the
+   disk.  Once the file's dirty buffers have been flushed, the server
+   responds to the request, and logs another record in the journal
+   indicating that it has done so.
+
+   Entries in the journal file are logged along with the time at which
+   the logging occurred.  When the server forks to dump the database,
+   it records the current time before forking.  The copy of the server
+   that writes out the database records the time read prior to forking
+   in the new data file.  The copy of the server that continues to
+   serve DHCP requests ensures that any journal entries subsequent to
+   the fork have time stamps that are greater than the time read
+   before forking.  When recovering from a crash, the server discards
+   any entries in the journal which have time stamps earlier than the
+   time stamp on the data file.
+
+   When recovering from a crash, dhcpd may find a journal entry for a
+   request, but no entry indicating that it was satisfied.  There is
+   no automatic way to recover from this, since the server may have
+   sent out a response, so in this case the server must notify
+   sysadmin of the problem and leave it to them to solve it.
+
+   In addition to the actual data files, we also keep a running log of
+   ``interesting'' events, which we mail to the dhcp-admin alias every
+   morning at 7:00 AM.  This log can be tailed by paranoid sysadmins
+   or in times of network trouble. */
+
+/* Initialize the internal database, perform crash recovery as needed. */
+
+void dbinit ()
+{
+       FILE *dbfile;
+
+       /* We are assuming that on entry, there is no other dhcpd
+          running on this machine.  If there were, there would be the
+          potential for serious database corruption.  The main code
+          currently assures that there is only one server running by
+          listening on the bootps port with INADDR_ANY.  Unices that
+          I'm familiar with will only allow one process to do this,
+          even if the SO_REUSEADDR option is set.   'twouldn't surprise
+          me terribly, though, if this didn't work for some other
+          operating system.   Beware.   XXX */
+
+       /* Look for a file under the official database name.
+          Failing that, look for a file under the backup name.
+          If we find neither, we assume that the database is empty. */
+
+       if ((dbfile = fopen (_PATH_DHCP_DB, "r")) != NULL
+           (dbfile = fopen (_PATH_DHCP_DB_BACKUP, "r") != NULL)) {
+
+               /* Read in the data file, making a list of assigned
+                  addresses that have been removed from dhcpd.conf. */
+
+       }
+
+       /* Open the journal file and read through any entries which
+           are out of date. */
+
+       /* Now read entries that postdate the last database sync,
+          keeping track of incomplete entries (when we're done, there
+          should never be more than one such entry. */
+
+       /* Now expire any leases that have lapsed since we last ran. */
+
+       /* ...and we're done... */
+}
diff --git a/dhcp.c b/dhcp.c
new file mode 100644 (file)
index 0000000..9f8946d
--- /dev/null
+++ b/dhcp.c
@@ -0,0 +1,52 @@
+/* dhcp.c
+
+   DHCP Protocol support. */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+void dhcp (packet)
+       struct packet *packet;
+{
+}
diff --git a/dhcp.h b/dhcp.h
new file mode 100644 (file)
index 0000000..f06571d
--- /dev/null
+++ b/dhcp.h
@@ -0,0 +1,155 @@
+/* dhcp.h
+
+   Protocol structures... */
+
+/*
+ * Copyright (c) 1995 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''.
+ */
+
+#define DHCP_UDP_OVERHEAD      (14 + /* Ethernet header */             \
+                                20 + /* IP header */                   \
+                                8)   /* UDP header */
+#define DHCP_SNAME_LEN         64
+#define DHCP_FILE_LEN          128
+#define DHCP_FIXED_LEN         (236 + DHCP_UDP_OVERHEAD) /* Everything but
+                                                            options. */
+#define DHCP_MTU_MAX           1500
+#define DHCP_OPTION_LEN                (DHCP_MTU_MAX - DHCP_FIXED_LEN)
+
+struct dhcp_packet {
+       u_int8_t  op;           /* Message opcode/type */
+       u_int8_t  htype;        /* Hardware addr type (see net/if_types.h) */
+       u_int8_t  hlen;         /* Hardware addr length */
+       u_int8_t  hops;         /* Number of relay agent hops from client */
+       u_int32_t xid;          /* Transaction ID */
+       u_int16_t secs;         /* Seconds since client started looking */
+       u_int16_t flags;        /* Flag bits */
+       struct in_addr ciaddr;  /* Client IP address (if already in use) */
+       struct in_addr yiaddr;  /* Client IP address */
+       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 options [DHCP_OPTION_LEN]; /* Optional parameters
+                                          (actual length dependent on MTU). */
+};
+
+/* BOOTP (rfc951) message types */
+#define        BOOTREQUEST     1
+#define BOOTREPLY      2
+
+/* Possible values for flags field... */
+#define BOOTP_BROADCAST 32768L
+
+/* Magic cookie validating dhcp options field (and bootp vendor
+   extensions field). */
+#define DHCP_OPTIONS_COOKIE    "\143\202\123\143"
+
+/* DHCP Option codes: */
+
+#define DHO_PAD                                0
+#define DHO_SUBNET_MASK                        1
+#define DHO_TIME_OFFSET                        2
+#define DHO_ROUTERS                    3
+#define DHO_TIME_SERVERS               4
+#define DHO_NAME_SERVERS               5
+#define DHO_DOMAIN_NAME_SERVERS                6
+#define DHO_LOG_SERVERS                        7
+#define DHO_COOKIE_SERVERS             8
+#define DHO_LPR_SERVERS                        9
+#define DHO_IMPRESS_SERVERS            10
+#define DHO_RESOURCE_LOCATION_SERVERS  11
+#define DHO_HOST_NAME                  12
+#define DHO_BOOT_SIZE                  13
+#define DHO_MERIT_DUMP                 14
+#define DHO_DOMAIN_NAME                        15
+#define DHO_SWAP_SERVER                        16
+#define DHO_ROOT_PATH                  17
+#define DHO_EXTENSIONS_PATH            18
+#define DHO_IP_FORWARDING              19
+#define DHO_NON_LOCAL_SOURCE_ROUTING   20
+#define DHO_POLICY_FILTER              21
+#define DHO_MAX_DGRAM_REASSEMBLY       22
+#define DHO_DEFAULT_IP_TTL             23
+#define DHO_PATH_MTU_AGING_TIMEOUT     24
+#define DHO_PATH_MTU_PLATEAU_TABLE     25
+#define DHO_INTERFACE_MTU              26
+#define DHO_ALL_SUBNETS_LOCAL          27
+#define DHO_BROADCAST_ADDRESS          28
+#define DHO_PERFORM_MASK_DISCOVERY     29
+#define DHO_MASK_SUPPLIER              30
+#define DHO_ROUTER_DISCOVERY           31
+#define DHO_ROUTER_SOLICITATION_ADDRESS        32
+#define DHO_STATIC_ROUTES              33
+#define DHO_TRAILER_ENCAPSULATION      34
+#define DHO_ARP_CACHE_TIMEOUT          35
+#define DHO_IEEE802_3_ENCAPSULATION    36
+#define DHO_DEFAULT_TCP_TTL            37
+#define DHO_TCP_KEEPALIVE_INTERVAL     38
+#define DHO_TCP_KEEPALIVE_GARBAGE      39
+#define DHO_NIS_DOMAIN                 40
+#define DHO_NIS_SERVERS                        41
+#define DHO_NTP_SERVERS                        42
+#define DHO_VENDOR_ENCAPSULATED_OPTIONS        43
+#define DHO_NETBIOS_NAME_SERVERS       44
+#define DHO_NETBIOS_DD_SERVER          45
+#define DHO_NETBIOS_NODE_TYPE          46
+#define DHO_NETBIOS_SCOPE              47
+#define DHO_FONT_SERVERS               48
+#define DHO_X_DISPLAY_MANAGER          49
+#define DHO_DHCP_REQUESTED_ADDRESS     50
+#define DHO_DHCP_LEASE_TIME            51
+#define DHO_DHCP_OPTION_OVERLOAD       52
+#define DHO_DHCP_MESSAGE_TYPE          53
+#define DHO_DHCP_SERVER_IDENTIFIER     54
+#define DHO_DHCP_PARAMETER_REQUEST_LIST        55
+#define DHO_DHCP_MESSAGE               56
+#define DHO_DHCP_MAX_MESSAGE_SIZE      57
+#define DHO_DHCP_RENEWAL_TIME          58
+#define DHO_DHCP_REBINDING_TIME                59
+#define DHO_DHCP_CLASS_IDENTIFIER      60
+#define DHO_DHCP_CLIENT_IDENTIFIER     61
+#define DHO_END                                255
+
+/* DHCP message types. */
+#define DHCPDISCOVER   1
+#define DHCPOFFER      2
+#define DHCPREQUEST    3
+#define DHCPDECLINE    4
+#define DHCPACK                5
+#define DHCPNAK                6
+#define DHCPRELEASE    7
diff --git a/dhcpd.c b/dhcpd.c
new file mode 100644 (file)
index 0000000..b2687e6
--- /dev/null
+++ b/dhcpd.c
@@ -0,0 +1,256 @@
+/* dhcpd.c
+
+   DHCP Server Daemon. */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+static void usage PROTO ((void));
+
+TIME cur_time;
+
+u_int32_t *server_addrlist;
+int server_addrcount;
+u_int16_t server_port;
+
+int main (argc, argv, envp)
+       int argc;
+       char **argv, **envp;
+{
+       struct in_addr addr;
+       int port = 0;
+       int i;
+       struct sockaddr_in name;
+       u_int32_t *addrlist = (u_int32_t *)0;
+       int addrcount = 0;
+       struct tree *addrtree = (struct tree *)0;
+       struct servent *ent;
+       int sock;
+       int pid;
+       int result;
+       int flag;
+
+       openlog ("dhcpd", LOG_NDELAY, LOG_DAEMON);
+#ifndef DEBUG
+       setlogmask (LOG_UPTO (LOG_INFO));
+
+       /* Become a daemon... */
+       if ((pid = fork ()) < 0)
+               error ("Can't fork daemon: %m");
+       else if (pid)
+               exit (0);
+       /* Become session leader and get pid... */
+       pid = setsid ();
+#endif 
+       for (i = 1; i < argc; i++) {
+               if (!strcmp (argv [i], "-p")) {
+                       if (++i == argc)
+                               usage ();
+                       server_port = htons (atoi (argv [i]));
+                       debug ("binding to user-specified port %d\n",
+                              ntohs (server_port));
+#if 0
+               } else if (!strcmp (argv [i], "-a")) {
+                       if (++i == argc)
+                               usage ();
+                       if (inet_aton (argv [i], &addr)) {
+                               addrtree =
+                                       tree_concat (addrtree,
+                                                    tree_const
+                                                    ((unsigned char *)&addr,
+                                                     sizeof addr));
+                       } else {
+                               addrtree = tree_concat (addrtree,
+                                                       tree_host_lookup
+                                                       (argv [i]));
+                       }
+#endif
+               } else
+                       usage ();
+       }
+
+       /* Default to the DHCP/BOOTP port. */
+       if (!server_port)
+       {
+               ent = getservbyname ("dhcp", "udp");
+               if (!ent)
+                       server_port = htons (67);
+               else
+                       server_port = ent -> s_port;
+               endservent ();
+       }
+  
+       /* Get the current time... */
+       GET_TIME (&cur_time);
+
+       /* Read the dhcpd.conf file... */
+       readconf ();
+
+#if 0
+       /* If addresses were specified on the command line, resolve them;
+          otherwise, just get a list of the addresses that are configured
+          on this host and listen on all of them. */
+       if (addrtree) {
+               tree_evaluate ((unsigned char **)&addrlist,
+                              &addrcount, addrtree);
+               addrcount /= 4;
+               if (!addrcount)
+                       error ("Server addresses resolve to nothing.");
+       } else {
+/*             addrlist = get_interface_list (&addrcount); */
+#endif
+               addr.s_addr = 0;
+               addrlist = (u_int32_t *)&(addr.s_addr);
+               addrcount = 1;
+#if 0
+       }
+#endif
+
+       server_addrlist = get_interface_list (&server_addrcount);
+
+       /* Listen on the specified (or default) port on each specified
+          (or default) IP address. */
+       for (i = 0; i < addrcount; i++) {
+               listen_on (server_port, addrlist [i]);
+       }
+
+       /* Write a pid file. */
+       if ((i = open (_PATH_DHCPD_PID, O_WRONLY | O_CREAT)) >= 0) {
+               char obuf [20];
+               sprintf (obuf, "%d\n", getpid ());
+               write (i, obuf, strlen (obuf));
+               close (i);
+       }
+
+       /* Receive packets and dispatch them... */
+       dispatch ();
+}
+
+/* Print usage message. */
+
+static void usage ()
+{
+       error ("Usage: dhcpd [-p <port>] [-a <ip-addr>]");
+}
+
+void cleanup ()
+{
+}
+
+void do_packet (packbuf, len, from, fromlen, sock)
+       unsigned char *packbuf;
+       int len;
+       struct sockaddr_in *from;
+       int fromlen;
+       int sock;
+{
+       struct packet *tp;
+       struct dhcp_packet *tdp;
+
+       if (!(tp = new_packet ("do_packet")))
+               return;
+       if (!(tdp = new_dhcp_packet ("do_packet"))) {
+               free_packet (tp, "do_packet");
+               return;
+       }
+       memcpy (tdp, packbuf, len);
+       memset (tp, 0, sizeof *tp);
+       tp -> raw = tdp;
+       tp -> packet_length = len;
+       tp -> client = *from;
+       tp -> client_len = fromlen;
+       tp -> client_sock = sock;
+       parse_options (tp);
+       if (tp -> options_valid &&
+           tp -> options [DHO_DHCP_MESSAGE_TYPE].data)
+               dhcp (tp);
+       else
+               bootp (tp);
+}
+
+dump_packet (tp)
+       struct packet *tp;
+{
+       struct dhcp_packet *tdp = tp -> raw;
+
+       debug ("op = %d  htype = %d  hlen = %d  hops = %d",
+              tdp -> op, tdp -> htype, tdp -> hlen, tdp -> hops);
+       debug ("xid = %x  secs = %d  flags = %x",
+              tdp -> xid, tdp -> secs, tdp -> flags);
+       debug ("ciaddr = %s  yiaddr = %s",
+              inet_ntoa (tdp -> ciaddr), inet_ntoa (tdp -> yiaddr));
+       debug ("siaddr = %s  giaddr = %s",
+              inet_ntoa (tdp -> siaddr), inet_ntoa (tdp -> giaddr));
+       debug ("chaddr = %02.2x:%02.2x:%02.2x:%02.2x:%02.2x:%02.2x",
+              ((unsigned char *)(tdp -> chaddr)) [0],
+              ((unsigned char *)(tdp -> chaddr)) [1],
+              ((unsigned char *)(tdp -> chaddr)) [2],
+              ((unsigned char *)(tdp -> chaddr)) [3],
+              ((unsigned char *)(tdp -> chaddr)) [4],
+              ((unsigned char *)(tdp -> chaddr)) [5]);
+       if (tp -> options_valid) {
+               int i;
+
+               for (i = 0; i < 256; i++) {
+                       if (tp -> options [i].data)
+                               printf ("  %s = %s\n",
+                                       dhcp_options [i].name,
+                                       pretty_print_option
+                                       (i, tp -> options [i].data,
+                                        tp -> options [i].len));
+               }
+       }
+}
+
+/* Based on the contents of packet, figure out which interface address
+   to use from server_addrlist.   Currently just picks the first
+   interface. */
+
+u_int32_t pick_interface (packet)
+       struct packet *packet;
+{
+       if (server_addrlist)
+               return server_addrlist [0];
+       return 0;
+}
diff --git a/dhcpd.conf b/dhcpd.conf
new file mode 100644 (file)
index 0000000..36d8f0e
--- /dev/null
@@ -0,0 +1,17 @@
+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";
+
diff --git a/dhcpd.h b/dhcpd.h
new file mode 100644 (file)
index 0000000..ac1367c
--- /dev/null
+++ b/dhcpd.h
@@ -0,0 +1,263 @@
+/* dhcpd.h
+
+   Definitions for dhcpd... */
+
+/*
+ * Copyright (c) 1995 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 <sys/types.h>
+#include <syslog.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include "dhcp.h"
+#include "cdefs.h"
+#include "osdep.h"
+#include "tree.h"
+#include "hash.h"
+
+/* A dhcp packet and the pointers to its option values. */
+struct packet {
+       struct dhcp_packet *raw;
+       int packet_length;
+       int packet_type;
+       int options_valid;
+       struct sockaddr_in client;
+       int client_len;
+       int client_sock;
+       struct {
+               int len;
+               unsigned char *data;
+       } options [256];
+};
+
+struct hardware {
+       u_int8_t htype;
+       u_int8_t hlen;
+       u_int8_t haddr [16];
+};
+
+/* A dhcp host declaration structure. */
+struct host_decl {
+       struct host_decl *n_name, *n_haddr, *n_cid;
+       char *name;
+       struct hardware *interfaces;
+       int interface_count;
+       char *filename;
+       char *server_name;      
+       struct tree_cache *fixed_addr;
+       struct tree_cache *options [256];
+};
+
+/* A dhcp lease declaration structure. */
+struct lease {
+       struct lease *next;
+       struct lease *prev;
+       struct in_addr ip_addr;
+       TIME starts, ends, timestamp;
+       unsigned char *uid;
+       int uid_len;
+       struct host_decl *host;
+       struct subnet *contain;
+       struct hardware hardware_addr;
+       int state;
+};
+
+struct subnet {
+       struct in_addr net;
+       struct in_addr netmask;
+       struct lease *leases;
+       struct lease *insertion_point;
+};
+
+/* Bitmask of dhcp option codes. */
+typedef unsigned char option_mask [16];
+
+/* DHCP Option mask manipulation macros... */
+#define OPTION_ZERO(mask)      (memset (mask, 0, 16))
+#define OPTION_SET(mask, bit)  (mask [bit >> 8] |= (1 << (bit & 7)))
+#define OPTION_CLR(mask, bit)  (mask [bit >> 8] &= ~(1 << (bit & 7)))
+#define OPTION_ISSET(mask, bit)        (mask [bit >> 8] & (1 << (bit & 7)))
+#define OPTION_ISCLR(mask, bit)        (!OPTION_ISSET (mask, bit))
+
+/* An option occupies its length plus two header bytes (code and
+    length) for every 255 bytes that must be stored. */
+#define OPTION_SPACE(x)                ((x) + 2 * ((x) / 255 + 1))
+
+/* Default path to dhcpd config file. */
+#ifndef _PATH_DHCPD_CONF
+#ifdef DEBUG
+#define _PATH_DHCPD_CONF       "dhcpd.conf"
+#else
+#define _PATH_DHCPD_CONF       "/etc/dhcpd.conf"
+#endif
+#endif
+
+/* Subnet macros... */
+#define SUBNET(addr, mask) ((addr).s_addr & (netmask).s_addr)
+#define IP_ADDR(net, host) ((net).s_addr | i)
+#define HOST_ADDR(addr, mask)  ((addr).s_addr & ~(netmask).s_addr)
+#define MAX_TIME 0x7fffffff
+#define MIN_TIME 0
+
+/* External definitions... */
+
+/* options.c */
+
+void parse_options PROTO ((struct packet *));
+void parse_option_buffer PROTO ((struct packet *, unsigned char *, int));
+void cons_options PROTO ((struct packet *, struct dhcp_packet *,
+                         struct host_decl *, int));
+char *pretty_print_option PROTO ((unsigned char, unsigned char *, int));
+
+/* errwarn.c */
+int error PROTO ((char *, ...));
+int warn PROTO ((char *, ...));
+int note PROTO ((char *, ...));
+int debug PROTO ((char *, ...));
+int parse_warn PROTO ((char *, ...));
+
+/* dhcpd.c */
+TIME cur_time;
+extern u_int32_t *server_addrlist;
+extern int server_addrcount;
+extern u_int16_t server_port;
+int main PROTO ((int, char **, char **));
+void cleanup PROTO ((void));
+void do_packet PROTO ((unsigned char *, int, struct sockaddr_in *, int, int));
+u_int32_t pick_interface PROTO ((struct packet *));
+
+
+/* conflex.c */
+int next_token PROTO ((char **, FILE *));
+int peek_token PROTO ((char **, FILE *));
+
+/* confpars.c */
+void readconf PROTO ((void));
+void parse_statement PROTO ((FILE *));
+void skip_to_semi PROTO ((FILE *));
+struct host_decl *parse_host_statement PROTO ((FILE *, jmp_buf *));
+char *parse_host_name PROTO ((FILE *, jmp_buf *));
+void parse_host_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
+void parse_hardware_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
+struct hardware parse_hardware_addr PROTO ((FILE *, jmp_buf *));
+void parse_filename_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
+void parse_fixed_addr_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
+void parse_option_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
+TIME parse_timestamp PROTO ((FILE *, jmp_buf *));
+TIME parse_date PROTO ((FILE *, jmp_buf *));
+struct lease *parse_lease_statement PROTO ((FILE *, jmp_buf *));
+void parse_address_range PROTO ((FILE *, jmp_buf *));
+unsigned char *parse_numeric_aggregate PROTO ((FILE *, jmp_buf *,
+                                              unsigned char *, int *,
+                                              int, int, int));
+void convert_num PROTO ((unsigned char *, char *, int, int));
+
+/* tree.c */
+pair cons PROTO ((caddr_t, pair));
+struct tree_cache *tree_cache PROTO ((struct tree *));
+struct tree *tree_host_lookup PROTO ((char *));
+struct dns_host_entry *enter_dns_host PROTO ((char *));
+struct tree *tree_const PROTO ((unsigned char *, int));
+struct tree *tree_concat PROTO ((struct tree *, struct tree *));
+struct tree *tree_limit PROTO ((struct tree *, int));
+int tree_evaluate PROTO ((struct tree_cache *));
+
+/* dhcp.c */
+void dhcp PROTO ((struct packet *));
+
+/* bootp.c */
+void bootp PROTO ((struct packet *));
+
+/* memory.c */
+void enter_host PROTO ((struct host_decl *));
+struct host_decl *find_host_by_name PROTO ((char *name));
+struct host_decl *find_host_by_addr PROTO ((int, unsigned char *, int));
+extern struct subnet *find_subnet (struct in_addr);
+void enter_subnet (struct subnet *);
+void enter_lease PROTO ((struct lease *));
+void supersede_lease PROTO ((struct lease *, struct lease *));
+struct lease *find_lease_by_uid PROTO ((unsigned char *, int));
+struct lease *find_lease_by_ip_addr PROTO ((struct in_addr));
+struct lease *find_next_expiring_lease PROTO ((void));
+
+/* alloc.c */
+VOIDPTR dmalloc PROTO ((int, char *));
+void dfree PROTO ((VOIDPTR, char *));
+struct packet *new_packet PROTO ((char *));
+struct dhcp_packet *new_dhcp_packet PROTO ((char *));
+struct tree *new_tree PROTO ((char *));
+struct tree_cache *new_tree_cache PROTO ((char *));
+struct hash_table *new_hash_table PROTO ((int, char *));
+struct hash_bucket *new_hash_bucket PROTO ((char *));
+struct lease *new_lease PROTO ((char *));
+struct lease *new_leases (int, char *);
+struct subnet *new_subnet PROTO ((char *));
+void free_subnet PROTO ((struct subnet *, char *));
+void free_lease PROTO ((struct lease *, char *));
+void free_hash_bucket PROTO ((struct hash_bucket *, char *));
+void free_hash_table PROTO ((struct hash_table *, char *));
+void free_tree_cache PROTO ((struct tree_cache *, char *));
+void free_packet PROTO ((struct packet *, char *));
+void free_dhcp_packet PROTO ((struct dhcp_packet *, char *));
+void free_tree PROTO ((struct tree *, char *));
+
+/* print.c */
+char *print_hw_addr PROTO ((int, int, unsigned char *));
+
+/* socket.c */
+u_int32_t *get_interface_list PROTO ((int *));
+void listen_on PROTO ((u_int16_t, u_int32_t));
+void dispatch PROTO ((void));
+
+/* hash.c */
+struct hash_table *new_hash PROTO ((void));
+void add_hash PROTO ((struct hash_table *, char *, int, unsigned char *));
+void delete_hash_entry PROTO ((struct hash_table *, char *, int));
+unsigned char *hash_lookup PROTO ((struct hash_table *, char *, int));
+
+/* tables.c */
+extern struct option dhcp_options [256];
+extern unsigned char dhcp_option_default_priority_list [];
+extern int sizeof_dhcp_option_default_priority_list;
+extern struct hash_table universe_hash;
+extern struct universe dhcp_universe;
+void initialize_universes PROTO ((void));
+
diff --git a/dhctoken.h b/dhctoken.h
new file mode 100644 (file)
index 0000000..04f057e
--- /dev/null
@@ -0,0 +1,71 @@
+/* dhctoken.h
+
+   Tokens for config file lexer and parser. */
+
+/*
+ * Copyright (c) 1995 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''.
+ */
+
+#define SEMI ';'
+#define DOT '.'
+#define COLON ':'
+#define COMMA ','
+#define SLASH '/'
+
+#define FIRST_TOKEN    HOST
+#define HOST           256
+#define HARDWARE       257
+#define FILENAME       258
+#define FIXED_ADDR     259
+#define OPTION         260
+#define ETHERNET       261
+#define STRING         262
+#define NUMBER         263
+#define NUMBER_OR_ATOM 264
+#define ATOM           265
+#define TIMESTAMP      266
+#define STARTS         267
+#define ENDS           268
+#define UID            269
+#define CLASS          270
+#define LEASE          271
+#define RANGE          272
+#define LAST_TOKEN     RANGE
+
+#define is_identifier(x)       ((x) >= FIRST_TOKEN &&  \
+                                (x) <= FIRST_TOKEN &&  \
+                                (x) != STRING &&       \
+                                (x) != NUMBER)
diff --git a/doc/dhc-minutes-94dec.txt b/doc/dhc-minutes-94dec.txt
new file mode 100644 (file)
index 0000000..a1beb76
--- /dev/null
@@ -0,0 +1,188 @@
+
+CURRENT_MEETING_REPORT_
+
+Reported by Walt Wimer/CMU
+
+Minutes of the Dynamic Host Configuration Working Group (DHC)
+
+The DHC Working Group met on 7 December and 9 December at the 31st IETF.
+
+
+Document Status
+
+The most recent Internet-Draft of the DHCP specification includes
+several changes based on the results of the latest interoperability
+testing.  Based on the results of that testing, and a review of the
+Standards process RFC, the working group decided it would be appropriate
+to ask that DHCP be considered for ``Draft Standard'' status.  As soon
+as a revision of the current Internet-Draft is completed, the
+specification for DHCP will be submitted for review.
+
+A few, minor changes have been made to RFC 1541 based on questions
+raised during the latest interoperability testing.  Two new options have
+been defined since RFC 1533:  62, NetWare/IP domain and 63, NetWare/IP
+option.
+
+The working group agreed that the minimum lease requirement (one hour)
+should be made advisory rather than mandatory.
+
+
+Implementations
+
+The following list of implementations was compiled from information
+given by working group attendees.
+
+ _____________________________________________________________________
+ ||                   |                   |               |             ||
+ || Vendor            |Client             |Server         |Relay agent  ||
+ ||___________________|___________________|_______________|_____________||
+ || FTP Software      |DOS/Windows        |Windows        |             ||
+ ||___________________|___________________|NT_(beta)______|_____________||
+ || SunSoft           |DOS/Windows        |Solaris 2.0    |in server    ||
+ ||___________________|Solaris_(beta?)____|_______________|_____________||
+ || Microsoft         |DOS/Windows        |NT             |in server    ||
+ ||                   |NT                 |               |             ||
+ ||___________________|Windows95_beta_____|_______________|_____________||
+ || Competitive       |???                |Solaris        |             ||
+ ||_Automation________|___________________|_______________|_____________||
+ || Apple             |Newton             |               |             ||
+ ||___________________|Mac_(beta)_________|_______________|_____________||
+ || WIDE project      |Unix, BSD386       |Unix, BSD386   |Unix, BSD386 ||
+ ||_(free,_avail_2/95)|News,_SunOS________|News,_SunOS____|News,_SunOS_ ||
+ ||_Silicon_Graphics__|IRIX_(soon)________|IRIX___________|_____________||
+ || Hewlett Packard   |X-terminal         |HP/UX (June 95)|in server    ||
+ ||___________________|___________________|_______________|HP_router____||
+ || IBM               |OS/2 (soon)        |OS/2 (soon)    |             ||
+ ||                   |AIX (soon)         |AIX (soon)     |             ||
+ ||___________________|___________________|AS/400_(soon)__|_____________||
+ || cisco Systems     |Terminal server?   |               |routers      ||
+ ||                   |(proxy for         |               |             ||
+ ||___________________|terminal_clients?)_|_______________|_____________||
+ || Novell            |NetWare/IP         |NetWare/IP     |             ||
+ ||___________________|(spring)___________|(later)________|_____________||
+ || Shiva             |Proxy for          |               |             ||
+ ||___________________|dial-in_clients____|_______________|_____________||
+
+
+Future Interoperability Test
+
+There was some discussion of a future interoperability test.  Suggested
+venues include Bucknell University (summer '95), CMU (no specific time),
+next IETF (March '95) and remote via the Internet (?!?!).  The working
+group will hold a discussion about the next interoperability testing via
+electronic mail.
+
+
+Outstanding Issues
+
+The working group discussed some outstanding issues and generated some
+solutions:
+
+
+   o New options:  TFTP server address, bootfile name, to be registered
+     with IANA.
+
+   o Some clients will already have an IP address, not otherwise
+     registered or managed by DHCP. Those clients will only want local
+     configuration parameters, not an address.  A new DHCP message,
+     DHCPINFORM, will be defined for parameter requests.
+
+   o There was some question about the definition and interpretation of
+     ``client identifiers.''  The working group confirmed that a
+     ``client identifier'' is an opaque, unique identifier.  Text will
+     be added to the protocol specification to clarify this issue and to
+     advise that ``client identifiers'' must be unique.  ``Client
+     identifier'' type 0 will indicate ``an opaque string of
+     characters.''
+
+
+The issue of security was discussed.  The primary concern is to detect
+and avoid spoof/unauthorized servers.  Some sites are also concerned
+about unauthorized clients.  The consensus was that a public key
+identification and authorization mechanism should be developed as an
+optional DHCP service.
+
+Ralph Droms presented a preliminary proposal for a server-server
+protocol to allow automatic management of DHCP bindings by multiple DHCP
+servers at a single site.  The goals are to increase availability and
+reliability through redundancy of address allocation and binding
+servers, and through load sharing.  The basic model, based on a proposal
+by Jeff Mogul, is to assign each allocatable address and allocated
+binding to a specific ``owner'' server.  That owner has modification
+privileges, while all other servers have read-only privileges.  Servers
+use TCP connections and a simple protocol to replicate copies of new
+bindings and transfer ownership of addresses to balance the pool of
+available addresses.
+
+The hard part is bindings that are released early, prior to expiration.
+Those released bindings must be reported to all other servers, so those
+servers do not respond with stale data in the future.  However, servers
+may be inaccessible.  The proposed solution was to add an ``owner''
+option; clients would select responses from the ``owner'' in favor of
+all other responses.
+
+The suggestion was made that multiple DHCP servers might be able to use
+an underlying distributed database like DNS, NIS+ or Oracle.  Questions
+were raised about the scalability of the proposed scheme -- suppose many
+clients send simultaneous update requests, how often should updates be
+replicated, what about combinatoric explosion with the number of
+servers?
+
+
+IPv6 Issues
+
+The second meeting began with a discussion of several IPv6 issues.  IPv6
+address configuration has three basic forms:
+
+
+  1. Intra-link scope address (client forms address all on its own)
+
+  2. ``Stateless'' servers (e.g., in routers using some simple
+     assignment algorithm)
+  3. Stateful servers (`a la IPv4 DHCP)
+
+
+Regardless of how addresses are managed, IPv6 will need some other
+mechanism(s) to obtain other configuration parameters.  Some members of
+the IPv6 design team claim there will be no other parameters.
+
+The following action items were identified:
+
+
+   o Someone to enumerate all IPv6 network layer parameters.
+     Mike Carney volunteered.
+
+   o Extensions/changes to DHCP protocol format for IPv6.
+     Walt Wimer volunteered.
+
+
+Dynamic Addressing
+
+Next, the working group discussed the problem of dynamic updates to DNS
+from DHCP information (dynamic addressing).  For simple registration of
+DNS hostnames for individual DHCP clients, what should we do?  Should
+client be responsible for contacting DNS server directly, or should DHCP
+server contact DNS on behalf of client?  It will be necessary to clarify
+DNS configuration/update mechanism with DNS Working Group.  One solution
+to the question of who does the update would be to define a DHCP option
+for client to say whether it will do the registration with DNS directly
+or whether client wants DHCP server to take care of it.  DHCP server may
+need a way to veto the client's preference.  This permits a simple
+client (such as an embedded hub, probe, etc.)  to let the DHCP server do
+everything (DHCP server probably has necessary credentials to update DNS
+while client probably does not).  Or, a more sophisticated client can
+update its ``home'' DNS directly (for example, a mobile notebook
+computer belonging to XYZ, Inc.  can be taken to an IETF get a local IP
+address from the IETF DHCP server, but then directly update XYZ.COM's
+DNS server in order to maintain an XYZ.COM name).  The problem of name
+collisions was unresolved - should the client or the server be
+responsible?  Masataka Ohta volunteered to do a DHCP-to-DNS interaction
+proposal
+
+
+DHCP and SNMP
+
+Finally, the working group considered DHCP and SNMP. The working group
+chair asked if there were any MIB writers in the audience.  The scribe
+thought there was a volunteer but did not catch the name.
+
diff --git a/doc/dns-minutes-93nov.txt b/doc/dns-minutes-93nov.txt
new file mode 100644 (file)
index 0000000..aa02802
--- /dev/null
@@ -0,0 +1,267 @@
+
+CURRENT_MEETING_REPORT_
+
+Reported by Rob Austein/Epilogue Technology
+
+Minutes of the Domain Name System Working Group (DNS)
+
+
+Documents
+
+Three new DNS-related Informational RFCs have come out recently.
+RFC 1535 (also known as ``the EDU.COM emergency RFC'') details problems
+with a widely-used but ill-advised DNS search heuristic, and proposes a
+solution.  RFC 1536 details common DNS implementation errors, with
+proposed solutions; this document was accepted as a DNS Working Group
+project at the 27th IETF (Amsterdam), completed, and accepted on the
+mailing list.  RFC 1537 details common DNS configuration errors; while
+it was never formally accepted as a DNS Working Group document, it was
+reviewed by the working group members.  These three RFCs are closely
+related and cross-reference each other, so, on advice of the RFC Editor,
+the DNS Working Group Chair approved ``fast track'' publication of these
+documents on behalf of the Working Group.  If anybody has serious
+problems with these documents, blame it on the Chair.
+
+Dave Perkins reported on the current status of the DNS MIB documents on
+behalf of the Network Management Area Directorate (NMDIR). Basically,
+there are no remaining hard problems, just some remaining detail work.
+One of the authors, Rob Austein, has received a detailed list of
+remaining concerns, none of which appear to be show-stoppers.  It should
+be possible to get these documents out the door before the 29th IETF in
+Seattle.  Dave pointed out two design issues that are not objections but
+of which he thinks the DNS Working Group should be aware:
+
+
+  1. Due to SNMP protocol limitations, the length limits on DNS names
+     used as indices to ``conceptual tables'' in the MIBs will be
+     shorter than the DNS name length limit of 255 octets.  Based on
+     analysis of current usage, this should not be a problem, so we'll
+     flag it with a warning statement in the document but otherwise
+     leave it alone.
+  2. The most recent versions of the documents (not yet released as
+     Internet-Drafts) use the SNMPv2 SMI rather than the SNMPv1 SMI, in
+     order to clear up some problems with unsigned 32-bit integers.
+     NMDIR wants to be sure that the DNS Working Group realizes that
+     this means only SNMPv2-capable implementations will be able to use
+     these MIBs.
+
+
+DNS Security Sub-Group
+
+James Galvin gave a report on the meeting held by the DNS Security
+``sub-group'' (a spin off from the DNS Working Group at the 26th IETF in
+Columbus).
+
+
+     The DNS Security design team of the DNS Working Group met for
+     one morning at the Houston IETF. The discussion began with a
+     call for threats that the members of the group were most
+     concerned about.  The list included the following:
+
+       o disclosure of the data - some expressed a desire to be
+         able to encrypt the data in responses
+
+       o modification of the data
+
+       o masquerade of the origin of the data
+
+       o masquerade of a secondary - some expressed a desire to be
+         able to reliably identify both peers in a zone transfer;
+         this would provide the basis for controlling access to
+         zone transfers
+
+     During the discussion of these threats it was agreed to accept
+     the following assumptions:
+
+      1. DNS data is ``public''
+      2. backward/co-existence compatibility is required
+
+     With respect to the first, accepting it set aside any further
+     discussion of the threat of disclosure of the data.  The second
+     assumption is included explicitly to remind everyone that we do
+     not want parallel DNS systems in the Internet.
+     In addition, it was explicitly agreed that we would not address
+     authentication of secondaries or access control issues.  Thus,
+     the current list of desired security services is:
+
+       o data integrity
+       o data origin authentication
+
+     It was noted that a digital signature mechanism would support
+     the desired services.
+     The meeting continued with a brainstorming period during which
+     the desired functional requirements of a secure DNS were
+     collected.  This list does not represent mandatory
+     functionality but, rather, it is desired functionality.  It was
+     agreed that this list was subject to discussion on the mailing
+     list for a period of time that would conclude on November 30.
+     The requirements are listed here in no particular order.
+
+       o sites must be able to support at least their internal
+         users in the presence of external network failures
+
+       o it should be possible for a site to pre-configure other
+         authoritative servers without having to query the
+         ``system'' to find the server
+
+       o it should be possible to request services only from
+         security enhanced servers, only from non-security enhanced
+         servers, or to indicate that either is acceptable
+
+       o it should be possible to recognize security enhanced
+         responses
+
+       o it should be possible to assign cryptographic keys (make
+         use of the security services) to leaf nodes in the DNS
+         tree, i.e., fully qualified domain names
+
+       o it should be possible to not trust secondary servers
+
+       o a mechanism must exist for revoking cryptographic keys
+         that works within the DNS time-to-live framework
+
+       o security services should be supported with no additional
+         DNS queries beyond what would be required if security was
+         not supported
+
+       o it must be possible to ensure that cached data expires
+         according to its TTL
+
+     The meeting concluded with agreement on the following three
+     milestones.
+
+      1. The desired functional requirements are to be reviewed and
+         agreed upon by November 30.
+
+      2. Strawman proposals that meet as many of the desired
+         requirements as possible are due by January 31, 1994.
+
+      3. The group would produce a single, draft proposal at the
+         next IETF meeting, March 1994.
+
+
+
+The DNS Security effort will be spun off as a separate working group in
+the Service Applications Area (SAP), as soon as James can get the
+charter approved.  The DNS Security mailing list is
+dns-security@tis.com; requests to subscribe should be sent to
+dns-security-request@tis.com.
+
+Discussion of the incremental zone transfer protocol
+(draft-ietf-dns-ixfr-00.txt) was deferred because none of the authors
+were present at the meeting.  Comments on this draft should be sent to
+the authors and/or the Namedroppers mailing list.
+
+
+
+DNS Efforts to Support SIPP
+
+Sue Thomson gave a brief report on current DNS efforts to support SIPP
+(the merger of the SIP and PIP proposals).  See the latest version of
+the Internet-Draft, draft-ietf-sip-sippdns-nn.txt, for details.
+
+
+DNS Reliability Issues - Boeing
+
+Ed King gave a presentation on DNS reliability issues in Boeing's
+production environment.  Ed has to support DNS on a corporate network
+with thousands of subnets and DNS software from many vendors in a
+production environment that never shuts down and where an interruption
+to DNS services due to a power hit can leave hundreds of engineers
+sitting idle waiting for their workstations to finish booting.  Much of
+the problem is that each vendor has their own slightly different (and
+often more than slightly broken) interface between DNS, local host
+tables, and the vendor's own pet name resolution mechanism.  Replacing
+or repairing all the DNS software in an environment isn't economically
+feasible, so the most constructive approach seems to be to write a ``DNS
+Requirements'' document to use as a reference when pressuring vendors to
+fix their DNS implementations.  The DNS portion of the Host Requirements
+documents (RFC 1123 section 6.1) and the newly published DNS ``Common
+Errors'' Informational RFCs are good starting points, but companies like
+Boeing need a document that has the force of a standard and that goes
+into more detail on interface design issues than Host Requirements does.
+
+No definite decision was reached as a result of Ed's presentation, but
+watch Namedroppers for further discussion and probably a call to form a
+working group.
+
+
+DNS Support for DHC and Mobile Hosts
+
+Masataka Ohta gave a presentation on a possible way to implement some of
+the DNS support needed for dynamic host configuration and mobile hosts.
+The presentation went into more detail than there is room for in these
+minutes, so expect to see a summary of this on the Namedroppers list.
+
+
+The Future of the DNS Working Group
+
+Dave Crocker spoke about the future of the DNS Working Group.  As has
+been discussed at previous meetings, the DNS Working Group as currently
+organized doesn't really fit well into the current IETF organizational
+framework.  Accordingly, Dave asks that DNS reorganize itself more along
+the current IETF pattern.  The proposal is to move the ``permanent''
+functions of the DNS Working Group (DNS oversight within the IETF,
+mostly) into the SAP Area Directorate, that Dave will be forming ``Real
+Soon Now,'' while reincarnating specific closed-ended tasks as separate
+working groups within the SAP Area.  The SAP Area Directorate will hold
+open meetings at regular intervals, so that there will still be a forum
+for overall DNS design work.  For formal purposes, the current DNS
+Working Group will probably be retroactively construed as having been
+the DNS MIB Working Group, and will be closed down as soon as the DNS
+MIB documents hit the streets.  As a practical matter, and in the
+Chair's opinion, the current DNS Working Group will effectively
+reconstitute itself as the attendees of the DNS portion of the SAP Area
+Directorate open meetings.  Dave expects to have the reorganization
+completed by the 29th IETF in Seattle.
+
+The discussion that followed Dave's statement made it clear that there
+are people with strong feelings on both sides of this issue (keep the
+DNS Working Group as it is versus reorganize per Dave's plan).  Unless
+somebody feels strongly enough about this to make a formal appeal, the
+reorganization will probably go through.
+
+
+Attendees
+
+Steve Alexander          stevea@lachman.com
+Garrett Alexander        gda@tycho.ncsc.mil
+Robert Austein           sra@epilogue.com
+Anders Baardsgaad        anders@cc.uit.no
+Alireza Bahreman         bahreman@bellcore.com
+William Barns            barns@gateway.mitre.org
+Stephen Crocker          crocker@tis.com
+Donald Eastlake          dee@skidrow.lkg.dec.com
+Havard Eidnes            havard.eidnes@runit.sintef.no
+Erik Fair                fair@apple.com
+Roger Fajman             raf@cu.nih.gov
+Patrik Faltstrom         paf@nada.kth.se
+Antonio Fernandez        afa@thumper.bellcore.com
+James Fielding           jamesf@arl.army.mil
+James Galvin             galvin@tis.com
+Chris Gorsuch            chrisg@lobby.ti.com
+Ronald Jacoby            rj@sgi.com
+Rick Jones               raj@cup.hp.com
+Charlie Kaufman          kaufman@zk3.dec.com
+Elizabeth Kaufman        kaufman@biomded.med.yale.edu
+Stephen Kent             kent@bbn.com
+Edwin King               eek@atc.boeing.com
+Paul Lambert             paul_lambert@email.mot.com
+Walter Lazear            lazear@gateway.mitre.org
+Lars-Johan Liman         liman@ebone.net
+John Linn                linn@security.ov.com
+Jun Matsukata            jm@eng.isas.ac.jp
+Paul Mockapetris         pvm@darpa.mil
+Sath Nelakonda           sath@lachman.com
+Masataka Ohta            mohta@cc.titech.ac.jp
+Michael Patton           map@bbn.com
+Jon Postel               postel@isi.edu
+Jeffrey Schiller         jis@mit.edu
+Richard Schmalgemeier    rgs@merit.edu
+Michael St.  Johns       stjohns@arpa.mil
+John Stewart             jstewart@cnri.reston.va.us
+Theodore Ts'o            tytso@mit.edu
+Walter Wimer             walter.wimer@andrew.cmu.edu
+David Woodgate           David.Woodgate@its.csiro.au
+Weiping Zhao             zhao@nacsis.ac.jp
+
diff --git a/doc/draft-ietf-dhc-dhcp-03.txt b/doc/draft-ietf-dhc-dhcp-03.txt
new file mode 100644 (file)
index 0000000..08ac212
--- /dev/null
@@ -0,0 +1,2043 @@
+
+Network Working Group                                           R. Droms
+INTERNET DRAFT                                       Bucknell University
+Obsoletes: draft-ietf-dhc-dhcp-02.txt                     September 1995
+                                                      Expires March 1996
+
+
+                  Dynamic Host Configuration Protocol
+                      <draft-ietf-dhc-dhcp-03.txt>
+
+Status of this memo
+
+   This document is an Internet-Draft. Internet-Drafts are working
+   documents of the Internet Engineering Task Force (IETF), its areas,
+   and its working groups. Note that other groups may also distribute
+   working documents as Internet-Drafts.
+
+   Internet-Drafts are draft documents valid for a maximum of six months
+   and may be updated, replaced, or obsoleted by other documents at any
+   time. It is inappropriate to use Internet-Drafts as reference
+   material or to cite them other than as ``work in progress.''
+
+   To learn the current status of any Internet-Draft, please check the
+   ``1id-abstracts.txt'' listing contained in the Internet-Drafts Shadow
+   Directories on ftp.is.co.za (Africa), nic.nordu.net (Europe),
+   munnari.oz.au (Pacific Rim), ds.internic.net (US East Coast), or
+   ftp.isi.edu (US West Coast).
+
+Abstract
+
+   The Dynamic Host Configuration Protocol (DHCP) provides a framework
+   for passing configuration information to hosts on a TCP/IP network.
+   DHCP is based on the Bootstrap Protocol (BOOTP) [7], adding the
+   capability of automatic allocation of reusable network addresses and
+   additional configuration options [19].  DHCP captures the behavior of
+   BOOTP relay agents [7, 21], and DHCP participants can interoperate
+   with BOOTP participants [9].
+
+
+Table of Contents
+
+   1.  Introduction. . . . . . . . . . . . . . . . . . . . . . . . .  2
+   1.1 Related Work. . . . . . . . . . . . . . . . . . . . . . . . .  4
+   1.2 Problem definition and issues . . . . . . . . . . . . . . . .  4
+   1.3 Requirements. . . . . . . . . . . . . . . . . . . . . . . . .  5
+   1.4 Terminology . . . . . . . . . . . . . . . . . . . . . . . . .  6
+   1.5 Design goals. . . . . . . . . . . . . . . . . . . . . . . . .  6
+   2.  Protocol Summary. . . . . . . . . . . . . . . . . . . . . . .  8
+   2.1 Configuration parameters repository . . . . . . . . . . . . . 10
+   2.2 Dynamic allocation of network addresses . . . . . . . . . . . 11
+   3.  The Client-Server Protocol. . . . . . . . . . . . . . . . . . 12
+   3.1 Client-server interaction - allocating a network address. . . 13
+   3.2 Client-server interaction - reusing a  previously allocated
+       network address . . . . . . . . . . . . . . . . . . . . . . . 17
+   3.3 Interpretation and representation of time values. . . . . . . 20
+   3.4 Obtaining parameters with externally configured network
+       address . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
+   3.5 Client parameters in DHCP . . . . . . . . . . . . . . . . . . 20
+   3.6 Use of DHCP in clients with multiple interfaces . . . . . . . 21
+   3.7 When clients should use DHCP. . . . . . . . . . . . . . . . . 22
+   4.  Specification of the DHCP client-server protocol. . . . . . . 22
+   4.1 Constructing and sending DHCP messages. . . . . . . . . . . . 22
+   4.2 DHCP server administrative controls . . . . . . . . . . . . . 24
+   4.3 DHCP server behavior. . . . . . . . . . . . . . . . . . . . . 25
+   4.4 DHCP client behavior. . . . . . . . . . . . . . . . . . . . . 33
+   5.  References . . . . . . . . . . . . . . . . . . . . . . . . . .40
+   6.  Security Considerations. . . . . . . . . . . . . . . . . . . .42
+   7.  Author's Address . . . . . . . . . . . . . . . . . . . . . . .42
+   A.  Host Configuration Parameters  . . . . . . . . . . . . . . . .43
+   B.  Changes to draft-ietf-dhc-dhcp-02.txt. . . . . . . . . . . . .44
+
+List of Figures
+
+   1. Format of a DHCP message . . . . . . . . . . . . . . . . . . .  9
+   2. Format of the 'flags' field. . . . . . . . . . . . . . . . . . 10
+   3. Timeline diagram of messages exchanged between DHCP client and
+      servers when allocating a new network address. . . . . . . . . 15
+   4. Timeline diagram of messages exchanged between DHCP client and
+      servers when reusing a previously allocated network address. . 18
+   5. State-transition diagram for DHCP clients. . . . . . . . . . . 34
+
+List of Tables
+
+   1. Description of fields in a DHCP message. . . . . . . . . . . . 12
+   2. DHCP messages. . . . . . . . . . . . . . . . . . . . . . . . . 14
+   3. Fields and options used by DHCP servers. . . . . . . . . . . . 27
+   4. Client messages from various states. . . . . . . . . . . . . . 33
+   5. Fields and options used by DHCP clients. . . . . . . . . . . . 37
+
+1. Introduction
+
+   The Dynamic Host Configuration Protocol (DHCP) provides configuration
+   parameters to Internet hosts.  DHCP consists of two components: a
+   protocol for delivering host-specific configuration parameters from a
+   DHCP server to a host and a mechanism for allocation of network
+   addresses to hosts.
+
+   DHCP is built on a client-server model, where designated DHCP server
+   hosts allocate network addresses and deliver configuration parameters
+   to dynamically configured hosts.  Throughout the remainder of this
+   document, the term "server" refers to a host providing initialization
+   parameters through DHCP, and the term "client" refers to a host
+   requesting initialization parameters from a DHCP server.
+
+   A host should not act as a DHCP server unless explicitly configured
+   to do so by a system administrator.  The diversity of hardware and
+   protocol implementations in the Internet would preclude reliable
+   operation if random hosts were allowed to respond to DHCP requests.
+   For example, IP requires the setting of many parameters within the
+   protocol implementation software.  Because IP can be used on many
+   dissimilar kinds of network hardware, values for those parameters
+   cannot be guessed or assumed to have correct defaults.  Also,
+   distributed address allocation schemes depend on a polling/defense
+   mechanism for discovery of addresses that are already in use.  IP
+   hosts may not always be able to defend their network addresses, so
+   that such a distributed address allocation scheme cannot be
+   guaranteed to avoid allocation of duplicate network addresses.
+
+   DHCP supports three mechanisms for IP address allocation.  In
+   "automatic allocation", DHCP assigns a permanent IP address to a
+   client.  In "dynamic allocation", DHCP assigns an IP address to a
+   client for a limited period of time (or until the client explicitly
+   relinquishes the address).  In "manual allocation", a client's IP
+   address is assigned by the network administrator, and DHCP is used
+   simply to convey the assigned address to the client.  A particular
+   network will use one or more of these mechanisms, depending on the
+   policies of the network administrator.
+
+   Dynamic allocation is the only one of the three mechanisms that
+   allows automatic reuse of an address that is no longer needed by the
+   client to which it was assigned.  Thus, dynamic allocation is
+   particularly useful for assigning an address to a client that will be
+   connected to the network only temporarily or for sharing a limited
+   pool of IP addresses among a group of clients that do not need
+   permanent IP addresses.  Dynamic allocation may also be a good choice
+   for assigning an IP address to a new client being permanently
+   connected to a network where IP addresses are sufficiently scarce
+   that it is important to reclaim them when old clients are retired.
+   Manual allocation allows DHCP to be used to eliminate the error-prone
+   process of manually configuring hosts with IP addresses in
+   environments where (for whatever reasons) it is desirable to manage
+   IP address assignment outside of the DHCP mechanisms.
+
+   The format of DHCP messages is based on the format of BOOTP messages,
+   to capture the BOOTP relay agent behavior described as part of the
+   BOOTP specification [7, 21] and to allow interoperability of existing
+   BOOTP clients with DHCP servers.  Using BOOTP relay agents eliminates
+   the necessity of having a DHCP server on each physical network
+   segment.
+
+1.1 Related Work
+
+   There are several Internet protocols and related mechanisms that
+   address some parts of the dynamic host configuration problem.  The
+
+   Reverse Address Resolution Protocol (RARP) [10] (through the
+   extensions defined in the Dynamic RARP (DRARP) [5]) explicitly
+   addresses the problem of network address discovery, and includes an
+   automatic IP address assignment mechanism.  The Trivial File Transfer
+   Protocol (TFTP) [20] provides for transport of a boot image from a
+   boot server.  The Internet Control Message Protocol (ICMP) [16]
+   provides for informing hosts of additional routers via "ICMP
+   redirect" messages.  ICMP also can provide subnet mask information
+   through the "ICMP mask request" message and other information through
+   the (obsolete) "ICMP information request" message.  Hosts can locate
+   routers through the ICMP router discovery mechanism [8].
+
+   BOOTP is a transport mechanism for a collection of configuration
+   information.  BOOTP is also extensible, and official extensions [17]
+   have been defined for several configuration parameters.  Morgan has
+   proposed extensions to BOOTP for dynamic IP address assignment [15].
+   The Network Information Protocol (NIP), used by the Athena project at
+   MIT, is a distributed mechanism for dynamic IP address assignment
+   [19].  The Resource Location Protocol RLP [1] provides for location
+   of higher level services.  Sun Microsystems diskless workstations use
+   a boot procedure that employs RARP, TFTP and an RPC mechanism called
+   "bootparams" to deliver configuration information and operating
+   system code to diskless hosts.  (Sun Microsystems, Sun Workstation
+   and SunOS are trademarks of Sun Microsystems, Inc.)  Some Sun
+   networks also use DRARP and an auto-installation mechanism to
+   automate the configuration of new hosts in an existing network.
+
+   In other related work, the path minimum transmission unit (MTU)
+   discovery algorithm can determine the MTU of an arbitrary internet
+   path [14].  The Address Resolution Protocol (ARP) has been proposed
+   as a transport protocol for resource location and selection [6].
+   Finally, the Host Requirements RFCs [3, 4] mention specific
+   requirements for host reconfiguration and suggest a scenario for
+   initial configuration of diskless hosts.
+
+1.2 Problem definition and issues
+
+   DHCP is designed to supply DHCP clients with the configuration
+   parameters defined in the Host Requirements RFCs.  After obtaining
+   parameters via DHCP, a DHCP client should be able to exchange packets
+   with any other host in the Internet.  The TCP/IP stack parameters
+   supplied by DHCP are listed in Appendix A.
+
+   Not all of these parameters are required for a newly initialized
+   client.  A client and server may negotiate for the transmission of
+   only those parameters required by the client or specific to a
+   particular subnet.
+
+   DHCP allows but does not require the configuration of client
+   parameters not directly related to the IP protocol.  DHCP also does
+   not address registration of newly configured clients with the Domain
+   Name System (DNS) [12, 13].
+
+   DHCP is not intended for use in configuring routers.
+
+1.3 Requirements
+
+   Throughout this document, the words that are used to define the
+   significance of particular requirements are capitalized.  These words
+   are:
+
+      o "MUST"
+
+        This word or the adjective "REQUIRED" means that the
+        item is an absolute requirement of this specification.
+
+      o "MUST NOT"
+
+        This phrase means that the item is an absolute prohibition
+        of this specification.
+
+      o "SHOULD"
+
+        This word or the adjective "RECOMMENDED" means that there
+        may exist valid reasons in particular circumstances to ignore
+        this item, but the full implications should be understood and
+        the case carefully weighed before choosing a different course.
+
+      o "SHOULD NOT"
+
+        This phrase means that there may exist valid reasons in
+        particular circumstances when the listed behavior is acceptable
+        or even useful, but the full implications should be understood
+        and the case carefully weighed before implementing any behavior
+        described with this label.
+
+      o "MAY"
+
+        This word or the adjective "OPTIONAL" means that this item is
+        truly optional.  One vendor may choose to include the item
+        because a particular marketplace requires it or because it
+        enhances the product, for example; another vendor may omit the
+        same item.
+
+1.4 Terminology
+
+   This document uses the following terms:
+
+      o "DHCP client"
+
+        A DHCP client is an Internet host using DHCP to obtain
+        configuration parameters such as a network address.
+
+      o "DHCP server"
+
+        A DHCP server is an Internet host that returns configuration
+        parameters to DHCP clients.
+
+      o "BOOTP relay agent"
+
+        A BOOTP relay agent or relay agent is an Internet host or router that
+        passes DHCP messages between DHCP clients and DHCP servers.  DHCP is
+        designed to use the same relay agent behavior as specified in
+        the BOOTP protocol specification.
+
+      o "binding"
+
+        A binding is a collection of configuration parameters, including
+        at least an IP address, associated with or "bound to" a DHCP
+        client.  Bindings are managed by DHCP servers.
+
+1.5 Design goals
+
+   The following list gives general design goals for DHCP.
+
+      o DHCP should be a mechanism rather than a policy.  DHCP must
+        allow local system administrators control over configuration
+        parameters where desired; e.g., local system administrators
+        should be able to enforce local policies concerning allocation
+        and access to local resources where desired.
+
+      o Clients should require no manual configuration.  Each client should
+        be able to discover appropriate local configuration parameters
+        without user intervention and incorporate those parameters into
+        its own configuration.
+
+      o Networks should require no manual configuration for individual
+        clients.  Under normal circumstances, the network manager should
+        not have to enter any per-client configuration parameters.
+
+      o DHCP should not require a server on each subnet.  To allow for
+        scale and economy, DHCP must work across routers or through the
+        intervention of BOOTP relay agents.
+
+      o A DHCP client must be prepared to receive multiple responses to a
+        request for configuration parameters.  Some installations may
+        include multiple, overlapping DHCP servers to enhance
+        reliability and increase performance.
+
+      o DHCP must coexist with statically configured, non-participating
+        hosts and with existing network protocol implementations.
+
+      o DHCP must interoperate with the BOOTP relay agent behavior as
+        described by RFC 951 and by RFC 1542 [21].
+
+      o DHCP must provide service to existing BOOTP clients.
+
+   The following list gives design goals specific to the transmission of
+   the network layer parameters.  DHCP must:
+
+      o Guarantee that any specific network address will not be in
+        use by more than one DHCP client at a time,
+
+      o Retain DHCP client configuration across DHCP client reboot.  A DHCP
+        client should, whenever possible, be assigned the same configuration
+        parameters (e.g., network address) in response to each request,
+
+      o Retain DHCP client configuration across server reboots, and, whenever
+        possible, a DHCP client should be assigned the same configuration
+        parameters despite restarts of the DHCP mechanism,
+
+      o Allow automatic assignment of configuration parameters to new
+        clients to avoid hand configuration for new clients,
+
+      o Support fixed or permanent allocation of configuration
+        parameters to specific clients.
+
+2. Protocol Summary
+
+   From the client's point of view, DHCP is an extension of the BOOTP
+   mechanism.  This behavior allows existing BOOTP clients to
+   interoperate with DHCP servers without requiring any change to the
+   clients' initialization software.  RFC 1533 [2] details the
+   interactions between BOOTP and DHCP clients and servers [9].  There
+   are some new, optional transactions that optimize the interaction
+   between DHCP clients and servers that are described in sections 3 and
+   4.
+
+   Figure 1 gives the format of a DHCP message and table 1 describes
+   each of the fields in the DHCP message.  The numbers in parentheses
+   indicate the size of each field in octets.  The names for the fields
+   given in the figure will be used throughout this document to refer to
+   the fields in DHCP messages.
+
+   There are two primary differences between DHCP and BOOTP.  First,
+   DHCP defines mechanisms through which clients can be assigned a
+   network address for a finite lease, allowing for serial reassignment
+   of network addresses to different clients.  Second, DHCP provides the
+   mechanism for a client to acquire all of the IP configuration
+   parameters that it needs in order to operate.
+
+   DHCP introduces a small change in terminology intended to clarify the
+   meaning of one of the fields.  What was the "vendor extensions" field
+   in BOOTP has been re-named the "options" field in DHCP. Similarly,
+   the tagged data items that were used inside the BOOTP "vendor
+   extensions" field, which were formerly referred to as "vendor
+   extensions," are now termed simply "options."
+
+   DHCP defines a new 'client identifier' option that is used to pass an
+   explicit client identifier to a DHCP server.  This change eliminates
+   the overloading of the 'chaddr' field in BOOTP messages, where
+   'chaddr' is used both as a hardware address for transmission of BOOTP
+   reply messages and as a client identifier.  The 'client identifier'
+   is an opaque key, not to be interpreted by the server; for example,
+   the 'client identifier' may contain a hardware address, identical to
+   the contents of the 'chaddr' field, or it may contain another type of
+   identifier, such as a DNS name.  If the client uses a 'client
+   identifier' in one message, it MUST use that same identifier in all
+   subsequent messages, to ensure that all servers correctly identify
+   the client.
+
+   0                   1                   2                   3
+   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |     op (1)    |   htype (1)   |   hlen (1)    |   hops (1)    |
+   +---------------+---------------+---------------+---------------+
+   |                            xid (4)                            |
+   +-------------------------------+-------------------------------+
+   |           secs (2)            |           flags (2)           |
+   +-------------------------------+-------------------------------+
+   |                          ciaddr  (4)                          |
+   +---------------------------------------------------------------+
+   |                          yiaddr  (4)                          |
+   +---------------------------------------------------------------+
+   |                          siaddr  (4)                          |
+   +---------------------------------------------------------------+
+   |                          giaddr  (4)                          |
+   +---------------------------------------------------------------+
+   |                                                               |
+   |                          chaddr  (16)                         |
+   |                                                               |
+   |                                                               |
+   +---------------------------------------------------------------+
+   |                                                               |
+   |                          sname   (64)                         |
+   +---------------------------------------------------------------+
+   |                                                               |
+   |                          file    (128)                        |
+   +---------------------------------------------------------------+
+   |                                                               |
+   |                          options (variable)                   |
+   +---------------------------------------------------------------+
+
+                  Figure 1:  Format of a DHCP message
+
+   DHCP clarifies the interpretation of the 'siaddr' field as the
+   address of the server to use in the next step of the client's
+   bootstrap process.  A DHCP server may return its own address in the
+   'siaddr' field, if the server is prepared to supply the next
+   bootstrap service (e.g., delivery of an operating system executable
+   image).  A DHCP server always returns its own address in the 'server
+   identifier' option.
+
+   The 'options' field is now variable length. A DHCP client must be
+   prepared to receive DHCP messages with an 'options' field of at least
+   length 312 octets.  This requirement implies that a DHCP client must
+   be prepared to receive a message of up to 576 octets, the minimum IP
+   datagram size an IP host must be prepared to accept [3].  DHCP
+   clients may negotiate the use of larger DHCP messages through the
+
+   'maximum DHCP message size' option.  The options field may be further
+   extended into the 'file' and 'sname' fields.
+
+   In the case of a client using DHCP for initial configuration (before
+   the client's TCP/IP software has been completely configured), DHCP
+   requires creative use of the client's TCP/IP software and liberal
+   interpretation of RFC 1122.  The TCP/IP software SHOULD accept and
+   forward to the IP layer any IP packets delivered to the client's
+   hardware address before the IP address is configured; DHCP servers
+   and BOOTP relay agents may not be able to deliver DHCP messages to
+   clients that cannot accept hardware unicast datagrams before the
+   TCP/IP software is configured.
+
+   To work around some clients that cannot accept IP unicast datagrams
+   before the TCP/IP software is configured as discussed in the previous
+   paragraph, DHCP uses the 'flags' field [21].  The leftmost bit is
+   defined as the BROADCAST (B) flag.  The semantics of this flag are
+   discussed in section 4.1 of this document.  The remaining bits of the
+   flags field are reserved for future use.  They MUST be set to zero by
+   clients and ignored by servers and relay agents.  Figure 2 gives the
+   format of the 'flags' field.
+
+                                    1 1 1 1 1 1
+                0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+                +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+                |B|             MBZ             |
+                +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+                B:  BROADCAST flag
+
+                MBZ:  MUST BE ZERO (reserved for future use)
+
+                Figure 2:  Format of the 'flags' field
+
+
+2.1 Configuration parameters repository
+
+   The first service provided by DHCP is to provide persistent storage
+   of network parameters for network clients.  The model of DHCP
+   persistent storage is that the DHCP service stores a key-value entry
+   for each client, where the key is some unique identifier (for
+   example, an IP subnet number and a unique identifier within the
+   subnet) and the value contains the configuration parameters for the
+   client.
+
+   For example, the key might be the pair (IP-subnet-number, hardware-
+   address) (note that the "hardware-address" should be typed by the
+   type of hardware to accommodate possible duplication of hardware
+   addresses resulting from bit-ordering problems in a mixed-media,
+   bridged network) allowing for serial or concurrent reuse of a
+   hardware address on different subnets, and for hardware addresses
+   that may not be globally unique.  Alternately, the key might be the
+   pair (IP-subnet-number, hostname), allowing the server to assign
+   parameters intelligently to a DHCP client that has been moved to a
+   different subnet or has changed hardware addresses (perhaps because
+   the network interface failed and was replaced). The protocol defines
+   that the key will be (IP-subnet-number, hardware-address) unless the
+   client explicitly supplies an identifier.
+
+   A client can query the DHCP service to retrieve its configuration
+   parameters.  The client interface to the configuration parameters
+   repository consists of protocol messages to request configuration
+   parameters and responses from the server carrying the configuration
+   parameters.
+
+2.2 Dynamic allocation of network addresses
+
+   The second service provided by DHCP is the allocation of temporary or
+   permanent network (IP) addresses to clients.  The basic mechanism for
+   the dynamic allocation of network addresses is simple: a client
+   requests the use of an address for some period of time.  The
+   allocation mechanism (the collection of DHCP servers) guarantees not
+   to reallocate that address within the requested time and attempts to
+   return the same network address each time the client requests an
+   address.  In this document, the period over which a network address
+   is allocated to a client is referred to as a "lease" [11].  The
+   client may extend its lease with subsequent requests.  The client may
+   issue a message to release the address back to the server when the
+   client no longer needs the address.  The client may ask for a
+   permanent assignment by asking for an infinite lease.  Even when
+   assigning "permanent" addresses, a server may choose to give out
+   lengthy but non-infinite leases to allow detection of the fact that
+   the client has been retired.
+
+   In some environments it will be necessary to reassign network
+   addresses due to exhaustion of available addresses.  In such
+   environments, the allocation mechanism will reuse addresses whose
+   lease has expired.  The server should use whatever information is
+   available in the configuration information repository to choose an
+   address to reuse.  For example, the server may choose the least
+   recently assigned address.  As a consistency check, the allocating
+   server SHOULD probe the reused address before allocating the address,
+   e.g., with an ICMP echo request, and the client SHOULD probe the
+   newly received address, e.g., with ARP.
+
+   FIELD      OCTETS       DESCRIPTION
+   -----      ------       -----------
+
+   op            1  Message op code / message type.
+                    1 = BOOTREQUEST, 2 = BOOTREPLY
+   htype         1  Hardware address type, see ARP section in "Assigned
+                    Numbers" RFC; e.g., '1' = 10mb ethernet.
+   hlen          1  Hardware address length (e.g.  '6' for 10mb
+                    ethernet).
+   hops          1  Client sets to zero, optionally used by relay agents
+                    when booting via a relay agent.
+   xid           4  Transaction ID, a random number chosen by the
+                    client, used by the client and server to associate
+                    messages and responses between a client and a
+                    server.
+   secs          2  Filled in by client, seconds elapsed since client
+                    began address acquisition or renewal process.
+   flags         2  Flags (see figure 2).
+   ciaddr        4  Client IP address; only filled in if client is in
+                    BOUND, RENEW or REBINDING state and can respond to ARP
+                    requests.
+   yiaddr        4  'your' (client) IP address.
+   siaddr        4  IP address of next server to use in bootstrap;
+                    returned in DHCPOFFER, DHCPACK by server.
+   giaddr        4  Relay agent IP address, used in booting via a
+                    relay agent.
+   chaddr       16  Client hardware address.
+   sname        64  Optional server host name, null terminated string.
+   file        128  Boot file name, null terminated string; "generic"
+                    name or null in DHCPDISCOVER, fully qualified
+                    directory-path name in DHCPOFFER.
+   options     var  Optional parameters field.  See the options
+                    documents for a list of defined options.
+
+             Table 1:  Description of fields in a DHCP message
+
+3. The Client-Server Protocol
+
+   DHCP uses the BOOTP message format defined in RFC 951 and given in
+   table 1 and figure 1.  The 'op' field of each DHCP message sent from
+   a client to a server contains BOOTREQUEST. BOOTREPLY is used in the
+   'op' field of each DHCP message sent from a server to a client.
+
+   The first four octets of the 'options' field of the DHCP message
+   contain the (decimal) values 99, 130, 83 and 99, respectively (this
+   is the same magic cookie as is defined in RFC 1497 [17]).  The
+   remainder of the 'options' field consists a list of tagged parameters
+   that are called "options".  All of the "vendor extensions" listed in
+   RFC 1497 are also DHCP options.  RFC 1533 gives the complete set of
+   options defined for use with DHCP.
+
+   Several options have been defined so far.  One particular option -
+   the "DHCP message type" option - must be included in every DHCP
+   message.  This option defines the "type" of the DHCP message.
+   Additional options may be allowed, required, or not allowed,
+   depending on the DHCP message type.
+
+   Throughout this document, DHCP messages that include a 'DHCP message
+   type' option will be referred to by the type of the message; e.g., a
+   DHCP message with 'DHCP message type' option type 1 will be referred
+   to as a "DHCPDISCOVER" message.
+
+3.1 Client-server interaction - allocating a network address
+
+   The following summary of the protocol exchanges between clients and
+   servers refers to the DHCP messages described in table 2.  The
+   timeline diagram in figure 3 shows the timing relationships in a
+   typical client-server interaction.  If the client already knows its
+   address, some steps may be omitted; this abbreviated interaction is
+   described in section 3.2.
+
+   1. The client broadcasts a DHCPDISCOVER message on its local physical
+      subnet.  The DHCPDISCOVER message MAY include options that suggest
+      values for the network address and lease duration.  BOOTP relay
+      agents may pass the message on to DHCP servers not on the same
+      physical subnet.
+
+   2. Each server may respond with a DHCPOFFER message that includes an
+      available network address in the 'yiaddr' field (and other
+      configuration parameters in DHCP options).  Servers need not
+      reserve the offered network address, although the protocol will
+      work more efficiently if the server avoids allocating the offered
+      network address to another client.  When allocating a new address
+      (i.e., 'ciaddr' == 0), servers SHOULD check that the offered
+      network address is not already in use; e.g., the server may probe
+      the offered address with an ICMP Echo Request.  Servers SHOULD be
+      implemented so that network administrators MAY choose to disable
+      probes of newly allocated addresses.  The server transmits the
+      DHCPOFFER message to the client, using the BOOTP relay agent if
+      necessary.
+
+   3. The client receives one or more DHCPOFFER messages from one or
+      more servers.  The client may choose to wait for multiple
+      responses.  The client chooses one server from which to request
+      configuration parameters, based on the configuration parameters
+      offered in the DHCPOFFER messages.  The client broadcasts a
+      DHCPREQUEST message that MUST include the 'server identifier'
+      option to indicate which server it has selected, and that MAY
+      include other options specifying desired configuration values.
+      The 'requested IP address' option MUST be set to the value of
+      'yiaddr' in the DHCPOFFER message from the server.  This
+      DHCPREQUEST message is broadcast and relayed through DHCP/BOOTP
+      relay agents.  To help ensure that any BOOTP relay agents forward
+      the DHCPREQUEST message to the same set of DHCP servers that
+      received the original DHCPDISCOVER message, the DHCPREQUEST
+      message MUST use the same value in the DHCP message header's
+      'secs' field and be sent to the same IP broadcast address as the
+      original DHCPDISCOVER message.  The client times out and
+      retransmits the DHCPDISCOVER message if the client receives no
+      DHCPOFFER messages.
+
+   Message         Use
+   -------         ---
+
+   DHCPDISCOVER -  Client broadcast to locate available servers.
+
+   DHCPOFFER    -  Server to client in response to DHCPDISCOVER with
+                   offer of configuration parameters.
+
+   DHCPREQUEST  -  Client message to servers either (a) requesting
+                   offered parameters from one server and implicitly
+                   declining offers from all others, (b) confirming
+                   correctness of previously allocated address after,
+                   e.g., system reboot, or (c) extending the lease on a
+                   particular network address.
+
+   DHCPACK      -  Server to client with configuration parameters,
+                   including committed network address.
+
+   DHCPNAK      -  Server to client indicating client's notion of network
+                   address is incorrect (e.g., client has moved to new
+                   subnet) or client's lease as expired
+
+   DHCPDECLINE  -  Client to server indicating network address is already
+                   in use.
+
+   DHCPRELEASE  -  Client to server relinquishing network address and
+                   cancelling remaining lease.
+
+   DHCPINFORM   -  Client to server, asking only for local configuration
+                   parameters; client already has externally configured
+                   network address.
+
+                          Table 2:  DHCP messages
+                Server          Client          Server
+            (not selected)                    (selected)
+
+                  v               v               v
+                  |               |               |
+                  |     Begins initialization     |
+                  |               |               |
+                  | _____________/|\_____________ |
+                  |/ DHCPDISCOVER | DHCPDISCOVER \|
+                  |               |               |
+              Determines          |          Determines
+             configuration        |         configuration
+                  |               |               |
+                  |\              |  ____________/|
+                  | \_________    | /DHCPOFFER    |
+                  |  DHCPOFFER\   |/              |
+                  |            \  |               |
+                  |       Collects replies        |
+                  |              \|               |
+                  |     Selects configuration     |
+                  |               |               |
+                  | _____________/|\_____________ |
+                  |/ DHCPREQUEST  |  DHCPREQUEST \|
+                  |               |               |
+                  |               |     Commits configuration
+                  |               |               |
+                  |               | _____________/|
+                  |               |/ DHCPACK      |
+                  |               |               |
+                  |    Initialization complete    |
+                  |               |               |
+                  .               .               .
+                  .               .               .
+                  |               |               |
+                  |      Graceful shutdown        |
+                  |               |               |
+                  |               |\_____________ |
+                  |               |  DHCPRELEASE \|
+                  |               |               |
+                  |               |        Discards lease
+                  |               |               |
+                  v               v               v
+     Figure 3: Timeline diagram of messages exchanged between DHCP
+               client and servers when allocating a new network address
+
+  4. The servers receive the DHCPREQUEST broadcast from the client.
+     Those servers not selected by the DHCPREQUEST message use the
+     message as notification that the client has declined that server's
+     offer.  The server selected in the DHCPREQUEST message commits the
+     binding for the client to persistent storage and responds with a
+     DHCPACK message containing the configuration parameters for the
+     requesting client.  The combination of 'client identifier' or
+     'chaddr' and assigned network address constitute a unique
+     identifier for the client's lease and are used by both the client
+     and server to identify a lease referred to in any DHCP messages.
+     Any configuration parameters in the DHCPACK message SHOULD NOT
+     conflict with those in the earlier DHCPOFFER message to which the
+     client is responding.  The server SHOULD NOT check the offered
+     network address at this point. The 'yiaddr' field in the DHCPACK
+     messages is filled in with the selected network address.
+
+     If the selected server is unable to satisfy the DHCPREQUEST message
+     (e.g., the requested network address has been allocated), the
+     server SHOULD respond with a DHCPNAK message.
+
+     A server MAY choose to mark addresses offered to clients in
+     DHCPOFFER messages as unavailable.  The server SHOULD mark an
+     address offered to a client in a DHCPOFFER message as available if
+     the server receives no DHCPREQUEST message from that client.
+
+  5. The client receives the DHCPACK message with configuration
+     parameters.  The client SHOULD perform a final check on the
+     parameters (e.g., ARP for allocated network address), and notes the
+     duration of the lease specified in the DHCPACK message.  At this
+     point, the client is configured.  If the client detects that the
+     address is already in use (e.g., through the use of ARP), the
+     client MUST send a DHCPDECLINE message to the server and restarts
+     the configuration process.  The client SHOULD wait a minimum of ten
+     seconds before restarting the configuration process to avoid
+     excessive network traffic in case of looping.
+
+     If the client receives a DHCPNAK message, the client restarts the
+     configuration process.
+
+     The client times out and retransmits the DHCPREQUEST message if the
+     client receives neither a DHCPACK or a DHCPNAK message.  The client
+     retransmits the DHCPREQUEST according to the retransmission
+     algorithm in section 4.1.  The client should choose to retransmit
+     the DHCPREQUEST enough times to give adequate probability of
+     contacting the server without causing the client (and the user of
+     that client) to wait overly long before giving up; e.g., a client
+     retransmitting as described in section 4.1 might retransmit the
+     DHCPREQUEST message four times, for a total delay of 60 seconds,
+     before restarting the initialization procedure.  If the client
+     receives neither a DHCPACK or a DHCPNAK message after employing the
+     retransmission algorithm, the client reverts to INIT state and
+     restarts the initialization process.  The client SHOULD notify the
+     user that the initialization process has failed and is restarting.
+
+  6. The client may choose to relinquish its lease on a network address
+     by sending a DHCPRELEASE message to the server.  The client
+     identifies the lease to be released with its 'client identifier',
+     or 'chaddr' and network address in the DHCPRELEASE message. If the
+     client used a 'client identifier' when it obtained the lease, it
+     MUST use the same 'client identifier' in the DHCPRELEASE message.
+
+3.2 Client-server interaction - reusing a previously allocated network
+    address
+
+   If a client remembers and wishes to reuse a previously allocated
+   network address, a client may choose to omit some of the steps
+   described in the previous section.  The timeline diagram in figure 4
+   shows the timing relationships in a typical client-server interaction
+   for a client reusing a previously allocated network address.
+
+   1. The client broadcasts a DHCPREQUEST message on its local subnet.
+      The message includes the client's network address in the
+      'requested IP address' option. As the client has not received its
+      network address, it MUST NOT fill in the 'ciaddr' field. BOOTP
+      relay agents pass the message on to DHCP servers not on the same
+      subnet.  If the client used a 'client identifier' to obtain its
+      address, the client MUST use the same 'client identifier' in the
+      DHCPREQUEST message.
+
+   2. Servers with knowledge of the client's configuration parameters
+      respond with a DHCPACK message to the client.  Servers SHOULD NOT
+      check that the client's network address is already in use; the
+      client may respond to ICMP Echo Request messages at this point.
+
+      If the client's request is invalid (e.g., the client has moved to
+      a new subnet), servers SHOULD respond with a DHCPNAK message to
+      the client. Servers SHOULD NOT respond if their information is not
+      guaranteed to be accurate.  For example, a server that identifies
+      a request for an expired binding that is owned by another server
+      SHOULD NOT respond with a DHCPNAK unless the servers are using an
+      explicit mechanism to maintain coherency among the servers.
+
+                Server          Client          Server
+
+                  v               v               v
+                  |               |               |
+                  |             Begins            |
+                  |         initialization        |
+                  |               |               |
+                  |              /|\              |
+                  |  ___________/ | \___________  |
+                  | /DHCPREQUEST  |  DHCPREQUEST\ |
+                  |/              |              \|
+                  |               |                |
+               Locates            |            Locates
+            configuration         |         configuration
+                  |               |               |
+                  |\              |              /|
+                  | \             |  ___________/ |
+                  |  \            | /  DHCPACK    |
+                  |   \_______    |/              |
+                  |    DHCPACK\   |               |
+                  |         Initialization        |
+                  |            complete           |
+                  |              \|               |
+                  |               |               |
+                  |          (Subsequent          |
+                  |            DHCPACKS           |
+                  |            ignored)           |
+                  |               |               |
+                  |               |               |
+                  v               v               v
+
+     Figure 4: Timeline diagram of messages exchanged between DHCP
+               client and servers when reusing a previously allocated
+               network address
+
+
+     If 'giaddr' in the DHCPREQUEST message contains 0x0, the server sends
+     the DHCPNAK message directly to the client, as the client is on the
+     same subnet.  Otherwise, the server send the DHCPNAK message to the IP
+     address of the BOOTP relay agent, as recorded in 'giaddr'.  The
+     relay agent will, in turn, forward the message directly to the
+     client's hardware address, so that the DHCPNAK can be delivered even
+     if the client has moved to a new network.
+
+  3. The client receives the DHCPACK message with configuration
+     parameters.  The client performs a final check on the parameters
+     (as in section 3.1), and notes the duration of the lease specified
+     in the DHCPACK message.  The specific lease is implicitly identified
+     by the 'client identifier' or 'chaddr' and the network address.  At
+     this point, the client is configured.
+
+     If the client detects that the IP address in the DHCPACK message
+     is already in use, the client MUST send a DHCPDECLINE message to the
+     server and restarts the configuration process by requesting a
+     new network address.  This action corresponds to the client
+     moving to the INIT state in the DHCP state diagram, which is
+     described in section 4.4.
+
+     If the client receives a DHCPNAK message, it cannot reuse its
+     remembered network address.  It must instead request a new
+     address by restarting the configuration process, this time
+     using the (non-abbreviated) procedure described in section
+     3.1.  This action also corresponds to the client moving to
+     the INIT state in the DHCP state diagram.
+
+     The client times out and retransmits the DHCPREQUEST message if
+     the client receives neither a DHCPACK nor a DHCPNAK message.  The
+     client retransmits the DHCPREQUEST according to the retransmission
+     algorithm in section 4.1.  The client should choose to retransmit
+     the DHCPREQUEST enough times to give adequate probability of
+     contacting the server without causing the client (and the user of
+     that client) to wait overly long before giving up; e.g., a client
+     retransmitting as described in section 4.1 might retransmit the
+     DHCPREQUEST message four times, for a total delay of 60 seconds,
+     before restarting the initialization procedure.  If the client
+     receives neither a DHCPACK or a DHCPNAK message after employing
+     the retransmission algorithm, the client MAY choose to use the
+     previously allocated network address and configuration parameters
+     for the remainder of the unexpired lease.  This corresponds to
+     moving to BOUND state in the client state transition diagram shown
+     in figure 5.
+
+  4. The client may choose to relinquish its lease on a network
+     address by sending a DHCPRELEASE message to the server.  The
+     client identifies the lease to be released with its
+     'client identifier', or 'chaddr' and network address in the
+     DHCPRELEASE message.
+
+     Note that in this case, where the client retains its network
+     address locally, the client will not normally relinquish its
+     lease during a graceful shutdown.  Only in the case where the
+     client explicitly needs to relinquish its lease, e.g., the client
+     is about to be moved to a different subnet, will the client send
+     a DHCPRELEASE message.
+
+3.3 Interpretation and representation of time values
+
+   A client acquires a lease for a network address for a fixed period of
+   time (which may be infinite).  Throughout the protocol, times are to
+   be represented in units of seconds.  The time value of 0xffffffff is
+   reserved to represent "infinity".
+
+   As clients and servers may not have synchronized clocks, times are
+   represented in DHCP messages as relative times, to be interpreted
+   with respect to the client's local clock.  Representing relative
+   times in units of seconds in an unsigned 32 bit word gives a range of
+   relative times from 0 to approximately 100 years, which is sufficient
+   for the relative times to be measured using DHCP.
+
+   The algorithm for lease duration interpretation given in the previous
+   paragraph assumes that client and server clocks are stable relative
+   to each other.  If there is drift between the two clocks, the server
+   may consider the lease expired before the client does.  To
+   compensate, the server may return a shorter lease duration to the
+   client than the server commits to its local database of client
+   information.
+
+3.4 Obtaining parameters with externally configured network address
+
+   If a client has obtained a network address through some other means
+   (e.g., manual configuration), it may use a DHCPINFORM request message
+   to obtain other local configuration parameters.  Servers receiving a
+   DHCPINFORM message construct a DHCPACK message with any local
+   configuration parameters appropriate for the client without:
+   allocating a new address, checking for an existing binding, filling
+   in 'yiaddr' or including lease time parameters.  The servers SHOULD
+   unicast the DHCPACK reply to the address given in the 'ciaddr' field
+   of the DHCPINFORM message.
+
+   The server SHOULD check the network address in a DHCPINFORM message
+   for consistency, but MUST NOT check for an existing lease.  The
+   server forms a DHCPACK message containing the configuration
+   parameters for the requesting client and sends the DHCPACK message
+   directly to the client.
+
+3.5 Client parameters in DHCP
+
+   Not all clients require initialization of all parameters listed in
+   Appendix A.  Two techniques are used to reduce the number of
+   parameters transmitted from the server to the client.  First, most of
+   the parameters have defaults defined in the Host Requirements RFCs;
+   if the client receives no parameters from the server that override
+   the defaults, a client uses those default values.  Second, in its
+   initial DHCPDISCOVER or DHCPREQUEST message, a client may provide the
+   server with a list of specific parameters the client is interested
+   in.  If the client includes a list of parameters in a DHCPDISCOVER
+   message, it MUST include that list in any subsequent DHCPREQUEST
+   messages.
+
+   The client SHOULD include the 'maximum DHCP message size' option to
+   let the server know how large the server may make its DHCP messages.
+   The parameters returned to a client may still exceed the space
+   allocated to options in a DHCP message.  In this case, two additional
+   options flags (which must appear in the 'options' field of the
+   message) indicate that the 'file' and 'sname' fields are to be used
+   for options.
+
+   The client can inform the server which configuration parameters the
+   client is interested in by including the 'parameter request list'
+   option.  The data portion of this option explicitly lists the options
+   requested by tag number.
+
+   In addition, the client may suggest values for the network address
+   and lease time in the DHCPDISCOVER message.  The client may include
+   the 'requested IP address' option to suggest that a particular IP
+   address be assigned, and may include the 'IP address lease time'
+   option to suggest the lease time it would like.  Other options
+   representing "hints" at configuration parameters are allowed in a
+   DHCPDISCOVER or DHCPREQUEST message.  However, additional options may
+   be ignored by servers, and multiple servers may, therefore, not
+   return identical values for some options.  The 'requested IP address'
+   option is to be filled in only in a DHCPREQUEST message when the
+   client is verifying network parameters obtained previously. The
+   client fills in the 'ciaddr' field only when correctly configured
+   with an IP address in BOUND, RENEWING or REBINDING state.
+
+   If a server receives a DHCPREQUEST message with an invalid 'requested
+   IP address', the server SHOULD respond to the client with a DHCPNAK
+   message and may choose to report the problem to the system
+   administrator.  The server may include an error message in the
+   'message' option.
+
+3.6 Use of DHCP in clients with multiple interfaces
+
+   A client with multiple network interfaces must use DHCP through each
+   interface independently to obtain configuration information
+   parameters for those separate interfaces.
+
+3.7 When clients should use DHCP
+
+   A client SHOULD use DHCP to reacquire or verify its IP address and
+   network parameters whenever the local network parameters may have
+   changed; e.g., at system boot time or after a disconnection from the
+   local network, as the local network configuration may change without
+   the client's or user's knowledge.
+
+   If a client has knowledge of a previous network address and is unable
+   to contact a local DHCP server, the client may continue to use the
+   previous network address until the lease for that address expires.
+   If the lease expires before the client can contact a DHCP server, the
+   client must immediately discontinue use of the previous network
+   address and may inform local users of the problem.
+
+4. Specification of the DHCP client-server protocol
+
+   In this section, we assume that a DHCP server has a block of network
+   addresses from which it can satisfy requests for new addresses.  Each
+   server also maintains a database of allocated addresses and leases in
+   local permanent storage.
+
+4.1 Constructing and sending DHCP messages
+
+   DHCP clients and servers both construct DHCP messages by filling in
+   fields in the fixed format section of the message and appending
+   tagged data items in the variable length option area.  The options
+   area includes first a four-octet 'magic cookie' (which was described
+   in section 3), followed by the options.  The last option must always
+   be the 'end' option.
+
+   DHCP uses UDP as its transport protocol.  DHCP messages from a client
+   to a server are sent to the 'DHCP server' port (67), and DHCP
+   messages from a server to a client are sent to the 'DHCP client' port
+   (68). A server with multiple network address (e.g., a multi-homed
+   host) MAY use any of its network addresses in outgoing DHCP messages.
+
+   DHCP messages broadcast by a client prior to that client obtaining
+   its IP address must have the source address field in the IP header
+   set to 0.
+
+   If the 'giaddr' field in a DHCP message from a client is non-zero,
+   the server sends any return messages to the 'DHCP server' port on the
+   DHCP relaying agent whose address appears in 'giaddr'. If the
+   'giaddr' field is zero and the 'ciaddr' field is nonzero, then the
+   server should unicast the packet to the address in 'ciaddr'.  If
+   'giaddr' is zero and 'ciaddr' is zero, and the broadcast bit is set,
+   then the server should broadcast the packet to 255.255.255.255.    If
+   the broadcast bit is not set and 'giaddr' is zero and 'ciaddr' is
+   zero, then the server should unicast the packet to the client's
+   hardware address and 'yiaddr' address.
+
+   If the options in a DHCP message extend into the 'sname' and 'file'
+   fields, the 'option overload' option MUST appear in the 'options'
+   field, with value 1, 2 or 3, as specified in RFC 1533.  If the
+   'option overload' option is present in the 'options' field, the
+   options in the 'options' field MUST be terminated by an 'end' option,
+   and MAY contain one or more 'pad' options to fill the options field.
+   The options in the 'sname' and 'file' fields (if in use as indicated
+   by the 'options overload' option) MUST begin with the first octet of
+   the field, MUST be terminated by an 'end' option, and MUST be
+   followed by 'pad' options to fill the remainder of the field.  Any
+   individual option in the 'options', 'sname' and 'file' fields MUST be
+   entirely contained in that field.  The options in the 'options' field
+   MUST be interpreted first, so that any 'option overload' options may
+   be interpreted.  The 'file' field MUST be interpreted next (if the
+   'option overload' option indicates that the 'file' field contains
+   DHCP options), followed by the 'sname' field.
+
+   The values to be passed in an 'option' tag may be too long to fit in
+   the 255 octets available to a single option (e.g., a list of routers
+   in a 'router' option [21]).  Options may appear only once, unless
+   otherwise specified in the options document.  The client concatenates
+   the values of multiple instances of the same option into a single
+   parameter list for configuration.
+
+   DHCP clients are responsible for all message retransmission.  The
+   client MUST adopt a retransmission strategy that incorporates a
+   randomized exponential backoff algorithm to determine the delay
+   between retransmissions.  The delay between retransmissions SHOULD be
+   chosen to allow sufficient time for replies from the server to be
+   delivered based on the characteristics of the internetwork between
+   the client and the server.  For example, in a 10Mb/sec Ethernet
+   internetwork, the delay before the first retransmission SHOULD be 4
+   seconds randomized by the value of a uniform random number chosen
+   from the range -1 to +1.  Clients with clocks that provide resolution
+   granularity of less than one second may choose a non-integer
+   randomization value.  The delay before the next retransmission SHOULD
+   be 8 seconds randomized by the value of a uniform number chosen from
+   the range -1 to +1.  The retransmission delay SHOULD be doubled with
+   subsequent retransmissions up to a maximum of 64 seconds.  The client
+   MAY provide an indication of retransmission attempts to the user as
+   an indication of the progress of the configuration process.
+
+   The 'xid' field is used by the client to match incoming DHCP messages
+   with pending requests.  A DHCP client MUST choose 'xid's in such a
+   way as to minimize the chance of using an 'xid' identical to one used
+   by another client. For example, a client may choose a different,
+   random initial 'xid' each time the client is rebooted, and
+   subsequently use sequential 'xid's until the next reboot.  Selecting
+   a new 'xid' for each retransmission is an implementation decision.  A
+   client may choose to reuse the same 'xid' or select a new 'xid' for
+   each retransmitted message.
+
+   Normally, DHCP servers and BOOTP relay agents attempt to deliver
+   DHCPOFFER, DHCPACK and DHCPNAK messages directly to the client using
+   unicast delivery.  The IP destination address (in the IP header) is
+   set to the DHCP 'yiaddr' address and the link-layer destination
+   address is set to the DHCP 'chaddr' address.  Unfortunately, some
+   client implementations are unable to receive such unicast IP
+   datagrams until the implementation has been configured with a valid
+   IP address (leading to a deadlock in which the client's IP address
+   cannot be delivered until the client has been configured with an IP
+   address).
+
+   A client that cannot receive unicast IP datagrams until its protocol
+   software has been configured with an IP address SHOULD set the
+   BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
+   DHCPREQUEST messages that client sends.  The BROADCAST bit will
+   provide a hint to the DHCP server and BOOTP relay agent to broadcast
+   any messages to the client on the client's subnet.  A client that can
+   receive unicast IP datagrams before its protocol software has been
+   configured SHOULD clear the BROADCAST bit to 0.  The BOOTP
+   clarifications document discusses the ramifications of the use of the
+   BROADCAST bit [21].
+
+   A server or relay agent sending or relaying a DHCP message directly
+   to a DHCP client (i.e., not to a relay agent specified in the
+   'giaddr' field) SHOULD examine the BROADCAST bit in the 'flags'
+   field.  If this bit is set to 1, the DHCP message SHOULD be sent as
+   an IP broadcast using an IP broadcast address (preferably
+   255.255.255.255) as the IP destination address and the link-layer
+   broadcast address as the link-layer destination address.  If the
+   BROADCAST bit is cleared to 0, the message SHOULD be sent as an IP
+   unicast to the IP address specified in the 'yiaddr' field and the
+   link-layer address specified in the 'chaddr' field.  If unicasting is
+   not possible, the message MAY be sent as an IP broadcast using an IP
+   broadcast address (preferably 255.255.255.255) as the IP destination
+   address and the link-layer broadcast address as the link-layer
+   destination address.
+
+4.2 DHCP server administrative controls
+
+   DHCP servers are not required to respond to every DHCPDISCOVER and
+   DHCPREQUEST message they receive.  For example, a network
+   administrator, to retain stringent control over the clients attached
+   to the network, may choose to configure DHCP servers to respond only
+   to clients that have been previously registered through some external
+   mechanism.  The DHCP specification describes only the interactions
+   between clients and servers when the clients and servers choose to
+   interact; it is beyond the scope of the DHCP specification to
+   describe all of the administrative controls that system
+   administrators might want to use.  Specific DHCP server
+   implementations may incorporate any controls or policies desired by a
+   network administrator.
+
+   In some environments, a DHCP server will have to consider the values
+   of the vendor and user class options included in DHCPDISCOVER or
+   DHCPREQUEST messages when determining the correct parameters for a
+   particular client.  For example, an organization might have a
+   separate printer server for each type of end-user, requiring the DHCP
+   server to examine the 'user class identifier' to determine which
+   printer server address to return in a DHCPOFFER or DHCPACK message.
+
+   A DHCP server needs to use some unique identifier to associate a
+   client with its lease.  The client MAY choose to explicitly provide
+   the identifier through the 'client identifier' option.  If the client
+   supplies a 'client identifier', the client MUST use the same 'client
+   identifier' in all subsequent messages, and the server MUST use that
+   identifier to identify the client.  If the client does not provide a
+   'client identifier' option, the server MUST use the contents of the
+   'chaddr' field to identify the client. It is crucial for DHCP clients
+   to use unique identifiers in the 'client identifier' option.  Use of
+   'chaddr' as the client's unique identifier may cause unexpected
+   results, as that identifier may be associated with a hardware
+   interface that could be moved to a new client.  Some sites may choose
+   to use a manufacturer's serial number as the 'client identifier', to
+   avoid unexpected changes in a clients network address due to transfer
+   of hardware interfaces among computers.  Sites may also choose to use
+   a DNS name as the 'client identifier', causing address leases to be
+   associated with the DNS name rather than a specific hardware box.
+
+   DHCP clients are free to use any strategy in selecting a DHCP server
+   among those from which the client receives a DHCPOFFER message.  The
+   client implementation of DHCP SHOULD provide a mechanism for the user
+   to select directly the 'vendor class identifier' and 'user class
+   identifier' values.
+
+4.3 DHCP server behavior
+
+   A DHCP server processes incoming DHCP messages from a client based on
+   the current state of the binding for that client.  A DHCP server can
+   receive the following messages from a client:
+
+      o DHCPDISCOVER
+
+      o DHCPREQUEST
+
+      o DHCPDECLINE
+
+      o DHCPRELEASE
+
+      o DHCPINFORM
+
+   Table 3 gives the use of the fields and options in a DHCP message by
+   a server.  The remainder of this section describes the action of the
+   DHCP server for each possible incoming message.
+
+4.3.1 DHCPDISCOVER message
+
+   When a server receives a DHCPDISCOVER message from a client, the
+   server chooses a network address for the requesting client.  If no
+   address is available, the server may choose to report the problem to
+   the system administrator. If an address is available, the new address
+   SHOULD be chosen as follows:
+
+   o The client's current address as recorded in the client's current
+     binding, ELSE
+
+   o The client's previous address as recorded in the client's (now
+     expired or released) binding, if that address is in the server's
+     pool of available addresses and not already allocated, ELSE
+
+   o The address requested in the 'Requested IP Address' option, if that
+     address is valid and not already allocated, ELSE
+
+   o A new address allocated from the server's pool of available
+     addresses; the address is selected based on the subnet from which
+     the message was received (if 'giaddr' is 0) or on the address of
+     the relay agent that forwarded the message ('giaddr' when not 0).
+
+   As described in section 4.2, a server MAY, for administrative
+   reasons, assign an address other than the one requested, or may
+   refuse to allocate an address to a particular client even though free
+   addresses are available.
+
+   While not required for correct operation of DHCP, the server SHOULD
+   not reuse the selected network address before the client responds to
+   the server's DHCPOFFER message.  The server may choose to record the
+   address as offered to the client.
+
+  Field      DHCPOFFER            DHCPACK             DHCPNAK
+  -----      ---------            -------             -------
+  'op'       BOOTREPLY            BOOTREPLY           BOOTREPLY
+  'htype'    (From "Assigned Numbers" RFC)
+  'hlen'     (Hardware address length in octets)
+  'hops'     0                    0                   0
+  'xid'      'xid' from client    'xid' from client   'xid' from client
+             DHCPDISCOVER         DHCPREQUEST         DHCPREQUEST
+             message              message             message
+  'secs'     0                    0                   0
+  'ciaddr'   0                    'ciaddr' from       0
+                                  DHCPREQUEST or 0
+  'yiaddr'   IP address offered   IP address          0
+             to client            assigned to client
+  'siaddr'   IP address of next   IP address of next  0
+             bootstrap server     bootstrap server
+  'flags'    'flags' from         'flags' from        'flags' from
+             client DHCPDISCOVER  client DHCPREQUEST  client DHCPREQUEST
+             message              message             message
+  'giaddr'   'giaddr' from        'giaddr' from       'giaddr' from
+             client DHCPDISCOVER  client DHCPREQUEST  client DHCPREQUEST
+             message              message             message
+  'chaddr'   'chaddr' from        'chaddr' from       'chaddr' from
+             client DHCPDISCOVER  client DHCPREQUEST  client DHCPREQUEST
+             message              message             message
+  'sname'    Server host name     Server host name    (unused)
+             or options           or options
+  'file'     Client boot file     Client boot file    (unused)
+             name or options      name or options
+  'options'  options              options
+
+  Option                    DHCPOFFER    DHCPACK            DHCPNAK
+  ------                    ---------    -------            -------
+  Requested IP address      MUST NOT     MUST NOT           MUST NOT
+  IP address lease time     MUST         MUST (DHCPREQUEST) MUST NOT
+                                         MUST NOT (DHCPINFORM)
+  Use 'file'/'sname' fields MAY          MAY                MUST NOT
+  DHCP message type         DHCPOFFER    DHCPACK            DHCPNAK
+  Parameter request list    MUST NOT     MUST NOT           MUST NOT
+  Message                   SHOULD       SHOULD             SHOULD
+  Client identifier         MUST NOT     MUST NOT           MAY
+  Vendor class identifier   MAY          MAY                MAY
+  User class identifier     MUST         MUST               MAY
+  Server identifier         MUST         MUST               MUST
+  Maximum message size      MUST NOT     MUST NOT           MUST NOT
+  All others                MAY          MAY                MUST NOT
+
+           Table 3:  Fields and options used by DHCP servers
+
+   The server must also choose an expiration time for the lease, as
+   follows:
+
+   o IF the client has not requested a specific lease in the
+     DHCPDISCOVER message and the client already has an assigned network
+     address, the server returns the lease expiration time previously
+     assigned to that address (note that the client must explicitly
+     request a specific lease to extend the expiration time on a
+     previously assigned address), ELSE
+
+   o IF the client has not requested a specific lease in the
+     DHCPDISCOVER message and the client does not have an assigned
+     network address, the server assigns a locally configured default
+     lease time, ELSE
+
+   o IF the client has requested a specific lease in the DHCPDISCOVER
+     message (regardless of whether the client has an assigned network
+     address), the server may choose either to return the requested
+     lease (if the lease is acceptable to local policy) or select
+     another lease.
+
+   Once the network address and lease have been determined, the server
+   constructs a DHCPOFFER message with the offered configuration
+   parameters.  It is important for all DHCP servers to return the same
+   parameters (with the possible exception of a newly allocated network
+   address) to ensure predictable client behavior regardless of which
+   server the client selects.  The configuration parameters MUST be
+   selected by applying the following rules in the order given below.
+   The network administrator is responsible for configuring multiple
+   DHCP servers to ensure uniform responses from those servers.  The
+   server MUST return to the client:
+
+   o The client's network address, as determined by the rules given
+     earlier in this section,
+
+   o The expiration time for the client's lease, as determined by the
+     rules given earlier in this section,
+
+   o Parameters requested by the client, according to the following
+     rules:
+
+        -- IF the server has been explicitly configured with a default
+           value for the parameter, the server MUST include that value
+           in an appropriate option in the 'option' field, ELSE
+
+        -- IF the server recognizes the parameter as a parameter
+           defined in the Host Requirements Document, the server MUST
+           include the default value for that parameter as given in the
+           Host Requirements Document in an appropriate option in the
+           'option' field, ELSE
+
+        -- The server MUST NOT return a value for that parameter,
+
+     The server MUST supply as many of the requested parameters as
+     possible and MUST omit any parameters it cannot provide.  The
+     server MUST include each requested parameter only once unless
+     explicitly allowed in the DHCP Options and BOOTP Vendor
+     Extensions document.
+
+   o Any parameters from the existing binding that differ from the Host
+     Requirements Document defaults,
+
+   o Any parameters specific to this client (as identified by
+     the contents of 'chaddr' or 'client identifier' in the DHCPDISCOVER
+     or DHCPREQUEST message), e.g., as configured by the network
+     administrator,
+
+   o Any parameters specific to this client's class (as identified
+     by the contents of the 'vendor class identifier' or 'user class
+     identifier' options in the DHCPDISCOVER or DHCPREQUEST message),
+     e.g., as configured by the network administrator; the parameters
+     MUST be identified by an exact match between the client's vendor and
+     user class identifiers and the client's classes identified in the
+     server,
+
+   o Parameters with non-default values on the client's subnet.
+
+   The server MAY choose to return the 'vendor class identifier' and
+   MUST return the 'user class identifier' used to determine the
+   parameters in the DHCPOFFER message to assist the client in selecting
+   which DHCPOFFER to accept.  The server inserts the 'xid' field from
+   the DHCPDISCOVER message into the 'xid' field of the DHCPOFFER
+   message and sends the DHCPOFFER message to the requesting client.
+
+4.3.2 DHCPREQUEST message
+
+   A DHCPREQUEST message may come from a client responding to a
+   DHCPOFFER message from a server, from a client verifying a previously
+   allocated IP address or from a client extending the lease on a
+   network address.  If the DHCPREQUEST message contains a 'server
+   identifier' option, the message is in response to a DHCPOFFER
+   message.  Otherwise, the message is a request to verify or extend an
+   existing lease.  If the client uses a 'client identifier' in a
+   DHCPREQUEST message, it MUST use that same 'client identifier' in all
+   subsequent messages. If the client included a list of requested
+   parameters in a DHCPDISCOVER message, it MUST include that list in
+   all subsequent messages.
+
+   Any configuration parameters in the DHCPACK message SHOULD NOT
+   conflict with those in the earlier DHCPOFFER message to which the
+   client is responding.  The client SHOULD use the parameters in the
+   DHCPACK message for configuration.
+
+   Clients send DHCPREQUEST messages as follows:
+
+   o DHCPREQUEST generated during SELECTING state:
+
+     Client inserts the address of the selected server in 'server
+     identifier', 'ciaddr' MUST be zero, 'requested IP address' MUST be
+     filled in with the yiaddr value from the chosen DHCPOFFER.
+
+     Note that the client may choose to collect several DHCPOFFER
+     messages and select the "best" offer.  The client indicates its
+     selection by identifying the offering server in the DHCPREQUEST
+     message.  If the client receives no acceptable offers, the client
+     may choose to try another DHCPDISCOVER message.  Therefore, the
+     servers may not receive a specific DHCPREQUEST from which they can
+     decide whether or not the client has accepted the offer.  Because
+     the servers have not committed any network address assignments on
+     the basis of a DHCPOFFER, servers are free to reuse offered network
+     addresses in response to subsequent requests.  As an implementation
+     detail, servers SHOULD NOT reuse offered addresses and may use an
+     implementation-specific timeout mechanism to decide when to reuse
+     an offered address.
+
+   o DHCPREQUEST generated during INIT-REBOOT state:
+
+     'server identifier' MUST NOT be filled in, 'requested IP address'
+     option MUST be filled in with client's notion of its previously
+     assigned address. ciaddr MUST be zero. The client is seeking to
+     verify a previously allocated, cached configuration. Server SHOULD
+     send a DHCPNAK message to the client if the 'requested IP address'
+     is incorrect, or is on the wrong network.
+
+     Determining whether a client in the INIT-REBOOT state is on the
+     correct network is done by examining the contents of 'giaddr', the
+     'requested IP address' option, and a database lookup. If the DHCP
+     server detects that the client is on the wrong net (i.e., the
+     result of applying the local subnet mask or remote subnet mask (if
+     'giaddr' is not zero) to 'requested IP address' option value
+     doesn't match reality), then the server SHOULD send a DHCPNAK
+     message to the client.
+
+     If the network is correct, then the DHCP server should check if the
+     client's notion of its IP address is correct. If not, then the
+     server SHOULD send a DHCPNAK message to the client. If the DHCP
+     server has no record of this client, then it MUST remain silent,
+     and MAY output a warning to the network administrator. This
+     behavior is necessary for peaceful coexistence of non-communicating
+     DHCP servers on the same wire.
+
+     If 'ciaddr' is not set in the DHCPREQUEST message, the server
+     SHOULD set the broadcast bit in the DHCPNAK message.  DHCPNAK is
+     broadcast to ensure that clients that may have an incorrect notion
+     of subnet mask or have not yet configured a network address (in
+     INIT-REBOOT state) will receive the DHCPNAK.
+
+     If 'ciaddr' is set in the DHCPREQUEST message, then the client is
+     configured to use the address and can respond to ARP requests
+     messages, so the DHCPNAK should be unicast (since it may be on a
+     remote subnet).  Typically, this case occurs when the client's
+     clock is much slower than the server's clock and the client
+     believes it still has a valid lease even though the lease has
+     actually expired.
+
+     If 'ciaddr' is not set in the DHCPREQUEST message, the server
+     SHOULD set the broadcast bit in the DHCPNAK message.  DHCPNAK is
+     broadcast to ensure that clients that may have an incorrect notion
+     of subnet mask or have not yet configured a network address (in
+     INIT-REBOOT state) will receive the DHCPNAK.
+
+     If 'ciaddr' is set in the DHCPREQUEST message, then the client is
+     configured to use the address and can respond to ARP requests
+     messages, so the DHCPNAK should be unicast (since it may be on a
+     remote subnet).  Typically, this case occurs when the client's
+     clock is much slower than the server's clock and the client
+     believes it still has a valid lease even though the lease has
+     actually expired.
+
+   o DHCPREQUEST generated during RENEWING state:
+
+     'server identifier' MUST NOT be filled in, 'requested IP address'
+     option MUST NOT be filled in, 'ciaddr' MUST be filled in with
+     client's IP address. In this situation, the client is completely
+     configured, and is trying to extend its lease. This message will be
+     unicast, so no relay agents will be involved in its transmission.
+     Because 'giaddr' is therefore not filled in, the DHCP server will
+     trust the value in 'ciaddr', and use it when replying to the
+     client.
+
+     A client MAY choose to renew or extend its lease prior to T1.  The
+     server may choose not to extend the lease (as a policy decision by
+     the network administrator), but should return a DHCPACK message
+     regardless.
+
+   o DHCPREQUEST generated during REBINDING state:
+
+     'server identifier' MUST NOT be filled in, 'requested IP address'
+     option MUST NOT be filled in, 'ciaddr' MUST be filled in with
+     client's IP address. In this situation, the client is completely
+     configured, and is trying to extend its lease. This message MUST be
+     broadcast to the 0xffffffff IP broadcast address.  The DHCP server
+     SHOULD check 'ciaddr' for correctness before replying to the
+     DHCPREQUEST.
+
+     The DHCPREQUEST from a REBINDING client is intended to accommodate
+     sites that have multiple DHCP servers and a mechanism for
+     maintaining consistency among leases managed by multiple servers.
+     A DHCP server MAY extend a client's lease only if it has local
+     administrative authority to do so.
+
+4.3.3 DHCPDECLINE message
+
+     If the server receives a DHCPDECLINE message, the client has
+     discovered through some other means that the suggested network
+     address is already in use.  The server MUST mark the network
+     address as not available and SHOULD notify the local system
+     administrator of a possible configuration problem.
+
+4.3.4 DHCPRELEASE message
+
+     Upon receipt of a DHCPRELEASE message, the server marks the network
+     address as not allocated.  The server SHOULD retain a record of the
+     client's initialization parameters for possible reuse in response
+     to subsequent requests from the client.
+
+4.3.5 DHCPINFORM message
+
+     The server responds to a DHCPINFORM message by sending a DHCPACK
+     message directly to the address given in the 'ciaddr' field of the
+     DHCPINFORM message.  The server SHOULD NOT send a lease expiration
+     time to the client and SHOULD NOT fill in 'yiaddr'.  The server
+     includes other parameters in the DHCPACK message as defined in
+     section 4.3.1.
+
+4.3.6 Client messages
+
+     Table 4 details the differences between messages from clients in
+     various states.
+
+     ---------------------------------------------------------------------
+     |              |INIT-REBOOT  |SELECTING    |RENEWING     |REBINDING |
+     ---------------------------------------------------------------------
+     |broad/unicast |broadcast    |broadcast    |unicast      |broadcast |
+     |server-ip     |MUST NOT     |MUST         |MUST NOT     |MUST NOT  |
+     |requested-ip  |MUST         |MUST         |MUST NOT     |MUST NOT  |
+     |ciaddr        |zero         |zero         |IP address   |IP address|
+     ---------------------------------------------------------------------
+
+               Table 4: Client messages from different states
+
+4.4 DHCP client behavior
+
+   Figure 5 gives a state-transition diagram for a DHCP client.  A
+   client can receive the following messages from a server:
+
+      o DHCPOFFER
+
+      o DHCPACK
+
+      o DHCPNAK
+
+   The DHCPINFORM message is not shown in figure 5.  A client simply
+   sends the DHCPINFORM and waits for DHCPACK messages.  Once the client
+   has selected its parameters, it has completed the configuration
+   process.
+
+   Table 5 gives the use of the fields and options in a DHCP message by
+   a client.  The remainder of this section describes the action of the
+   DHCP client for each possible incoming message.  The description in
+   the following section corresponds to the full configuration procedure
+   previously described in section 3.1, and the text in the subsequent
+   section corresponds to the abbreviated configuration procedure
+   described in section 3.2.
+
+ --------                               -------
+|        | +-------------------------->|       |<-------------------+
+| INIT-  | |     +-------------------->| INIT  |                    |
+| REBOOT |DHCPNAK/         +---------->|       |<---+               |
+|        |Restart|         |            -------     |               |
+ --------  |  DHCPNAK/     |               |                        |
+    |      Discard offer   |      -/Send DHCPDISCOVER               |
+-/Send DHCPREQUEST         |               |                        |
+    |      |     |      DHCPACK            v        |               |
+ -----------     |   (not accept.)/   -----------   |               |
+|           |    |  Send DHCPDECLINE |           |                  |
+| REBOOTING |    |         |         | SELECTING |<----+            |
+|           |    |        /          |           |     |DHCPOFFER/  |
+ -----------     |       /            -----------   |  |Collect     |
+    |            |      /                  |   |       |  replies   |
+DHCPACK/         |     /  +----------------+   +-------+            |
+Record lease, set|    |   v   Select offer/                         |
+timers T1, T2   ------------  send DHCPREQUEST      |               |
+    |   +----->|            |             DHCPNAK, Lease expired/   |
+    |   |      | REQUESTING |                  Halt network         |
+    DHCPOFFER/ |            |                       |               |
+    Discard     ------------                        |               |
+    |   |        |        |                   -----------           |
+    |   +--------+     DHCPACK/              |           |          |
+    |              Record lease, set    -----| REBINDING |          |
+    |                timers T1, T2     /     |           |          |
+    |                     |        DHCPACK/   -----------           |
+    |                     v     Record lease, set   ^               |
+    +----------------> -------      /timers T1,T2   |               |
+               +----->|       |<---+                |               |
+               |      | BOUND |<---+                |               |
+  DHCPOFFER, DHCPACK, |       |    |            T2 expires/   DHCPNAK/
+   DHCPNAK/Discard     -------     |             Broadcast  Halt network
+               |       | |         |            DHCPREQUEST         |
+               +-------+ |        DHCPACK/          |               |
+                    T1 expires/   Record lease, set |               |
+                 Send DHCPREQUEST timers T1, T2     |               |
+                 to leasing server |                |               |
+                         |   ----------             |               |
+                         |  |          |------------+               |
+                         +->| RENEWING |                            |
+                            |          |----------------------------+
+                             ----------
+          Figure 5:  State-transition diagram for DHCP clients
+
+4.4.1 Initialization and allocation of network address
+
+   The client begins in INIT state and forms a DHCPDISCOVER message.
+   The client SHOULD wait a random time between one and ten seconds to
+   desynchronize the use of DHCP at startup.  The client sets 'ciaddr'
+   to 0x00000000.  The client MAY request specific parameters by
+   including the 'parameter request list' option.  The client MAY
+   suggest a network address and/or lease time by including the
+   'requested IP address' and 'IP address lease time' options.  The
+   client MUST include its hardware address in the 'chaddr' field, if
+   necessary for delivery of DHCP reply messages.  The client MAY
+   include a different unique identifier in the 'client identifier'
+   option, as discussed in section 4.2.  If the client included a list
+   of requested parameters in a DHCPDISCOVER message, it MUST include
+   that list in all subsequent messages.
+
+   The client generates and records a random transaction identifier and
+   inserts that identifier into the 'xid' field.  The client records its
+   own local time for later use in computing the lease expiration.  The
+   client then broadcasts the DHCPDISCOVER on the local hardware
+   broadcast address to the 0xffffffff IP broadcast address and 'DHCP
+   server' UDP port.
+
+   If the 'xid' of an arriving DHCPOFFER message does not match the
+   'xid' of the most recent DHCPDISCOVER message, the DHCPOFFER message
+   must be silently discarded.  Any arriving DHCPACK messages must be
+   silently discarded.
+
+   The client collects DHCPOFFER messages over a period of time, selects
+   one DHCPOFFER message from the (possibly many) incoming DHCPOFFER
+   messages (e.g., the first DHCPOFFER message or the DHCPOFFER message
+   from the previously used server) and extracts the server address from
+   the 'server identifier' option in the DHCPOFFER message.  The time
+   over which the client collects messages and the mechanism used to
+   select one DHCPOFFER are implementation dependent.
+
+     Field      DHCPDISCOVER          DHCPREQUEST           DHCPDECLINE,
+                DHCPINFORM                                  DHCPRELEASE
+     -----      ------------          -----------           -----------
+     'op'       BOOTREQUEST           BOOTREQUEST           BOOTREQUEST
+     'htype'    (From "Assigned Numbers" RFC)
+     'hlen'     (Hardware address length in octets)
+     'hops'     0                     0                     0
+     'xid'      selected by client    'xid' from server     selected by
+                                      DHCPOFFER message     client
+     'secs'     (opt.)                (opt.)                0
+     'flags'    Set 'BROADCAST'       Set 'BROADCAST'       0
+                flag if client        flag if client
+                requires broadcast    requires broadcast
+                reply                 reply
+     'ciaddr'   DHCPDISCOVER:         0 or client's         client's network
+                0 or client's         network address       address
+                netwrk address        (BOUND/RENEW/REBIND)  (DHCPRELEASE only)
+                (BOUND/RENEW/REBIND)
+                DHCPINFORM: client's
+                network address
+     'yiaddr'   0                     0                     0
+     'siaddr'   0                     0                     0
+     'giaddr'   0                     0                     0
+     'chaddr'   client's hardware     client's hardware     client's hardware
+                address               address               address
+     'sname'    options, if           options, if           (unused)
+                indicated in          indicated in
+                'sname/file'          'sname/file'
+                option; otherwise     option; otherwise
+                unused                unused
+     'file'     options, if           options, if           (unused)
+                indicated in          indicated in
+                'sname/file'          'sname/file'
+                option; otherwise     option; otherwise
+                unused                unused
+     'options'  options               options               (unused)
+
+     Option                     DHCPDISCOVER  DHCPREQUEST      DHCPDECLINE,
+                                DHCPINFORM                     DHCPRELEASE
+     ------                     ------------  -----------      -----------
+     Requested IP address       MAY           MUST (in         MUST
+                                (DISCOVER)    SELECTING or     (DHCPDECLINE),
+                                MUST NOT      INIT-REBOOT)     MUST NOT
+                                (INFORM)      MUST NOT (in     (DHCPRELEASE)
+                                              BOUND or
+                                              RENEWING)
+     IP address lease time      MAY           MAY              MUST NOT
+                                (DISCOVER)
+                                MUST NOT
+                                (INFORM)
+     Use 'file'/'sname' fields  MAY           MAY              MAY
+     DHCP message type          DHCPDISCOVER/ DHCPREQUEST      DHCPDECLINE/
+                                DHCPINFORM                     DHCPRELEASE
+     Client identifier          MAY           MAY              MAY
+     Vendor class identifier    MAY           MAY              MUST NOT
+     User class identifier      MAY           MAY              MUST NOT
+     Server identifier          MUST NOT      MUST (after      MUST
+                                              SELECTING)
+                                              MUST NOT (after
+                                              INIT-REBOOT,
+                                              BOUND, RENEWING
+                                              or REBINDING)
+     Parameter request list     MAY           MAY              MUST NOT
+     Maximum message size       MAY           MAY              MUST NOT
+     Message                    SHOULD NOT    SHOULD NOT       SHOULD
+     Site-specific              MAY           MAY              MUST NOT
+     All others                 MAY           MAY              MUST NOT
+
+             Table 5:  Fields and options used by DHCP clients
+
+   If the parameters are acceptable, the client records the address of
+   the server that supplied the parameters from the 'server identifier'
+   field and sends that address in the 'server identifier' field of a
+   DHCPREQUEST broadcast message.  Once the DHCPACK message from the
+   server arrives, the client is initialized and moves to BOUND state.
+   The DHCPREQUEST message contains the same 'xid' as the DHCPOFFER
+   message.  The client records the lease expiration time as the sum of
+   the time at which the original request was sent and the duration of
+   the lease from the DHCPOFFER message.    The client SHOULD perform a
+   check on the suggested address to ensure that the address is not
+   already in use.  For example, if the client is on a network that
+   supports ARP, the client may issue an ARP request for the suggested
+   request.  When broadcasting an ARP request for the suggested address,
+   the client must fill in its own hardware address as the sender's
+   hardware address, and 0 as the sender's IP address, to avoid
+   confusing ARP caches in other hosts on the same subnet.  If the
+   network address appears to be in use, the client MUST send a
+   DHCPDECLINE message to the server. The client SHOULD broadcast an ARP
+   reply to announce the client's new IP address and clear any outdated
+   ARP cache entries in hosts on the client's subnet.
+
+4.4.2 Initialization with known network address
+
+   The client begins in INIT-REBOOT state and sends a DHCPREQUEST
+   message.  The client may request specific configuration parameters by
+   including the 'parameter request list' option.  The client generates
+   and records a random transaction identifier and inserts that
+   identifier into the 'xid' field.  The client records its own local
+   time for later use in computing the lease expiration.  The client
+   MUST NOT include a 'server identifier' in the DHCPREQUEST message.
+   The client then broadcasts the DHCPREQUEST on the local hardware
+   broadcast address to the 'DHCP server' UDP port.
+
+   Once a DHCPACK message with an 'xid' field matching that in the
+   client's DHCPREQUEST message arrives from any server, the client is
+   initialized and moves to BOUND state.  The client records the lease
+   expiration time as the sum of the time at which the DHCPREQUEST
+   message was sent and the duration of the lease from the DHCPACK
+   message.
+
+4.4.3 Initialization with an externally assigned network address
+
+   The client sends a DHCPINFORM message. The client may request
+   specific configuration parameters by including the 'parameter request
+   list' option. The client generates and records a random transaction
+   identifier and inserts that identifier into the 'xid' field. The
+   client places its own network address in the 'ciaddr' field. The
+   client SHOULD NOT request lease time parameters.
+
+   The client then unicasts the DHCPINFORM to the DHCP server if it
+   knows the server's address, otherwise it broadcasts the message to
+   the limited (all 1s) broadcast address.  DHCPINFORM messages MUST be
+   directed to the 'DHCP server' UDP port.
+
+   Once a DHCPACK message with an 'xid' field matching that in the
+   client's DHCPINFORM message arrives from any server, the client is
+   initialized.
+
+   If the client does not receive a DHCPACK within a reasonable period
+   of time (60 seconds or 4 tries if using timeout suggested in section
+   4.1), then it SHOULD display a message informing the user of the
+   problem, and then SHOULD begin network processing using suitable
+   defaults as per Appendix A.
+
+4.4.4 Use of broadcast and unicast
+
+   The DHCP client broadcasts DHCPDISCOVER, DHCPREQUEST and DHCPINFORM
+   messages, unless the client knows the address of a DHCP server.  The
+   client unicasts DHCPDECLINE and DHCPRELEASE messages to the server.
+   When the DHCP client knows the address of a DHCP server, in either
+   INIT or REBOOTING state, the client may use that address in the
+   DHCPDISCOVER or DHCPREQUEST rather than the IP broadcast address.
+   The client may also use unicast to send DHCPINFORM messages to a
+   known DHCP server.  If the client receives no response to DHCP
+   messages sent to the IP address of a known DHCP server, the DHCP
+   client reverts to using the IP broadcast address.
+
+4.4.5 Reacquisition and expiration
+
+   The client maintains two times, T1 and T2, that specify the times at
+   which the client tries to extend its lease on its network address.
+   T1 is the time at which the client enters the RENEWING state and
+   attempts to contact the server that originally issued the client's
+   network address.  T2 is the time at which the client enters the
+   REBINDING state and attempts to contact any server. T1 MUST be
+   earlier than T2, which, in turn, MUST be earlier than the time at
+   which the client's lease will expire.
+
+   To avoid the need for synchronized clocks, T1 and T2 are expressed in
+   options as relative times [2].
+
+   At time T1 the client moves to RENEWING state and sends (via unicast)
+   a DHCPREQUEST message to the server to extend its lease.  The client
+   sets the 'ciaddr' field in the DHCPREQUEST to its current network
+   address. The client records the local time at which the DHCPREQUEST
+   message is sent for computation of the lease expiration time.  The
+   client MUST NOT include a 'server identifier' in the DHCPREQUEST
+   message.
+
+   Any DHCPACK messages that arrive with an 'xid' that does not match
+   the 'xid' of the client's DHCPREQUEST message are silently discarded.
+   When the client receives a DHCPACK from the server, the client
+   computes the lease expiration time as the sum of the time at which
+   the client sent the DHCPREQUEST message and the duration of the lease
+   in the DHCPACK message.  The client has successfully reacquired its
+   network address, returns to BOUND state and may continue network
+   processing.
+
+   If no DHCPACK arrives before time T2, the client moves to REBINDING
+   state and sends (via broadcast) a DHCPREQUEST message to extend its
+   lease.  The client sets the 'ciaddr' field in the DHCPREQUEST to its
+   current network address.  The client MUST NOT include a 'server
+   identifier' in the DHCPREQUEST message.
+
+   Times T1 and T2 are configurable by the server through options.  T1
+   defaults to (0.5 * duration_of_lease).  T2 defaults to (0.875 *
+   duration_of_lease).  Times T1 and T2 SHOULD be chosen with some
+   random "fuzz" around a fixed value, to avoid synchronization of
+   client reacquisition.
+
+   A client MAY choose to renew or extend its lease prior to T1.  The
+   server MAY choose to extend the client's lease according to policy
+   set by the network administrator.  The server SHOULD return T1 and
+   T2, and their values SHOULD be adjusted from their original values to
+   take account of the time remaining on the lease.
+
+   In both RENEWING and REBINDING state, if the client receives no
+   response to its DHCPREQUEST message, the client SHOULD wait one-half
+   of the remaining time until T2 (in RENEWING state) and one-half of
+   the remaining lease time (in REBINDING state), down to a minimum of
+   60 seconds, before retransmitting the DHCPREQUEST message.
+
+   If the lease expires before the client receives a DHCPACK, the client
+   moves to INIT state, MUST immediately stop any other network
+   processing and requests network initialization parameters as if the
+   client were uninitialized.  If the client then receives a DHCPACK
+   allocating that client its previous network address, the client
+   SHOULD continue network processing.  If the client is given a new
+   network address, it MUST NOT continue using the previous network
+   address and SHOULD notify the local users of the problem.
+
+4.4.6 DHCPRELEASE
+
+   If the client no longer requires use of its assigned network address
+   (e.g., the client is gracefully shut down), the client sends a
+   DHCPRELEASE message to the server.  Note that the correct operation
+   of DHCP does not depend on the transmission of DHCPRELEASE messages.
+
+5. References
+
+   [1] Acetta, M., "Resource Location Protocol", RFC 887, CMU, December
+       1983.
+
+   [2] Alexander, S., and R. Droms, "DHCP Options and BOOTP Vendor
+       Extensions", RFC 1533, Lachman Technology, Inc., Bucknell
+       University, October 1993.
+
+   [3] Braden, R., Editor, "Requirements for Internet Hosts --
+       Communication Layers", STD 3, RFC 1122, USC/Information Sciences
+       Institute, October 1989.
+
+   [4] Braden, R., Editor, "Requirements for Internet Hosts --
+       Application and Support, STD 3, RFC 1123, USC/Information
+       Sciences Institute, October 1989.
+
+   [5] Brownell, D, "Dynamic Reverse Address Resolution Protocol
+       (DRARP)", Work in Progress.
+
+   [6] Comer, D., and R. Droms, "Uniform Access to Internet Directory
+       Services", Proc. of ACM SIGCOMM '90 (Special issue of Computer
+       Communications Review), 20(4):50--59, 1990.
+
+   [7] Croft, B., and J. Gilmore, "Bootstrap Protocol (BOOTP)", RFC 951,
+       Stanford and SUN Microsystems, September 1985.
+
+   [8] Deering, S., "ICMP Router Discovery Messages", RFC 1256, Xerox
+       PARC, September 1991.
+
+   [9] Droms, D., "Interoperation between DHCP and BOOTP", RFC 1534,
+       Bucknell University, October 1993.
+
+  [10] Finlayson, R., Mann, T., Mogul, J., and M. Theimer, "A Reverse
+       Address Resolution Protocol", RFC 903, Stanford, June 1984.
+
+  [11] Gray C., and D. Cheriton, "Leases: An Efficient Fault-Tolerant
+       Mechanism for Distributed File Cache Consistency", In Proc. of
+       the Twelfth ACM Symposium on Operating Systems Design, 1989.
+
+  [12] Mockapetris, P., "Domain Names -- Concepts and Facilities", STD
+       13, RFC 1034, USC/Information Sciences Institute, November 1987.
+
+  [13] Mockapetris, P., "Domain Names -- Implementation and
+       Specification", STD 13, RFC 1035, USC/Information Sciences
+       Institute, November 1987.
+
+  [14] Mogul J., and S. Deering, "Path MTU Discovery", RFC 1191,
+       November 1990.
+
+  [15] Morgan, R., "Dynamic IP Address Assignment for Ethernet Attached
+       Hosts", Work in Progress.
+
+  [16] Postel, J., "Internet Control Message Protocol", STD 5, RFC 792,
+       USC/Information Sciences Institute, September 1981.
+
+  [17] Reynolds, J., "BOOTP Vendor Information Extensions", RFC 1497,
+       USC/Information Sciences Institute, August 1993.
+
+  [18] Reynolds, J., and J. Postel, "Assigned Numbers", STD 2, RFC 1340,
+       USC/Information Sciences Institute, July 1992.
+
+  [19] Jeffrey Schiller and Mark Rosenstein. A Protocol for the Dynamic
+       Assignment of IP Addresses for use on an Ethernet. (Available
+       from the Athena Project, MIT), 1989.
+
+  [20] Sollins, K., "The TFTP Protocol (Revision 2)",  RFC 783, NIC,
+       June 1981.
+
+  [21] Wimer, W., "Clarifications and Extensions for the Bootstrap
+       Protocol", RFC 1542, Carnegie Mellon University, October 1993.
+
+6. Security Considerations
+
+   DHCP is built directly on UDP and IP which are as yet inherently
+   insecure.  Furthermore, DHCP is generally intended to make
+   maintenance of remote and/or diskless hosts easier.  While perhaps
+   not impossible, configuring such hosts with passwords or keys may be
+   difficult and inconvenient.  Therefore, DHCP in its current form is
+   quite insecure.
+
+   Unauthorized DHCP servers may be easily set up.  Such servers can
+   then send false and potentially disruptive information to clients
+   such as incorrect or duplicate IP addresses, incorrect routing
+   information (including spoof routers, etc.), incorrect domain
+   nameserver addresses (such as spoof nameservers), and so on.
+   Clearly, once this seed information is in place, an attacker can
+   further compromise affected systems.
+
+   Malicious DHCP clients could masquerade as legitimate clients and
+   retrieve information intended for those legitimate clients.  Where
+   dynamic allocation of resources is used, a malicious client could
+   claim all resources for itself, thereby denying resources to
+   legitimate clients.
+
+7. Author's Address
+
+   Ralph Droms
+   Computer Science Department
+   323 Dana Engineering
+   Bucknell University
+   Lewisburg, PA 17837
+
+   Phone: (717) 524-1145
+   EMail: droms@bucknell.edu
+
+   This document will expire on March 31, 1996.
+
+A. Host Configuration Parameters
+
+   IP-layer_parameters,_per_host:_
+
+   Be a router                     on/off                 HRC 3.1
+   Non-local source routing        on/off                 HRC 3.3.5
+   Policy filters for
+   non-local source routing        (list)                 HRC 3.3.5
+   Maximum reassembly size         integer                HRC 3.3.2
+   Default TTL                     integer                HRC 3.2.1.7
+   PMTU aging timeout              integer                MTU 6.6
+   MTU plateau table               (list)                 MTU 7
+   IP-layer_parameters,_per_interface:_
+   IP address                      (address)              HRC 3.3.1.6
+   Subnet mask                     (address mask)         HRC 3.3.1.6
+   MTU                             integer                HRC 3.3.3
+   All-subnets-MTU                 on/off                 HRC 3.3.3
+   Broadcast address flavor        0x00000000/0xffffffff  HRC 3.3.6
+   Perform mask discovery          on/off                 HRC 3.2.2.9
+   Be a mask supplier              on/off                 HRC 3.2.2.9
+   Perform router discovery        on/off                 RD 5.1
+   Router solicitation address     (address)              RD 5.1
+   Default routers, list of:
+           router address          (address)              HRC 3.3.1.6
+           preference level        integer                HRC 3.3.1.6
+   Static routes, list of:
+           destination             (host/subnet/net)      HRC 3.3.1.2
+           destination mask        (address mask)         HRC 3.3.1.2
+           type-of-service         integer                HRC 3.3.1.2
+           first-hop router        (address)              HRC 3.3.1.2
+           ignore redirects        on/off                 HRC 3.3.1.2
+           PMTU                    integer                MTU 6.6
+           perform PMTU discovery  on/off                 MTU 6.6
+
+   Link-layer_parameters,_per_interface:_
+   Trailers                       on/off                 HRC 2.3.1
+   ARP cache timeout              integer                HRC 2.3.2.1
+   Ethernet encapsulation         (RFC 894/RFC 1042)     HRC 2.3.3
+
+   TCP_parameters,_per_host:_
+   TTL                            integer                HRC 4.2.2.19
+   Keep-alive interval            integer                HRC 4.2.3.6
+   Keep-alive data size           0/1                    HRC 4.2.3.6
+
+Key:
+
+   MTU = Path MTU Discovery (RFC 1191, Proposed Standard)
+   RD = Router Discovery (RFC 1256, Proposed Standard)
+
+B. Changes to draft-ietf-dhc-dhcp-02.txt:
+
+* Changed 'host' to 'client' throughout when explicitly referencing a
+  DHCP client.
+
+* Section 3.1, numbered paragraph 5: changed "client performs" to
+  "client SHOULD perform"
+
+* Clarified text in section 3.1, numbered paragraph 6 and section 3.2,
+  numbered paragraph 4 describing use of DHCPRELEASE.
+
+* Clarified text in the second paragraph of section 2.2, describing
+  how the server probes a reused address before allocating it to a DHCP
+  client.
+
+* Changed and added text as suggested by Glenn Stump for separate
+  'vendor class' and 'user class' options:
+
+  - Section 4.2, changed second paragraph to discuss vendor and user
+    class identifiers.
+
+  - Section 4.2, changed last sentence of third paragraph to include
+    both vendor and user class identifiers.
+
+  - Modified table 3 to include both vendor and user class identifiers.
+
+  - Section 4.3.1, changed 6th bulleted rule for selection of parameters
+    by server to include vendor and user class identifiers.
+
+  - Section 4.3.1, changed last paragraph to include vendor and user
+    class identifiers.
+
+  - Modified table 5 to include both vendor and uesr class identifiers.
diff --git a/doc/draft-ietf-dhc-options-1533update-01.txt b/doc/draft-ietf-dhc-options-1533update-01.txt
new file mode 100644 (file)
index 0000000..e171eb0
--- /dev/null
@@ -0,0 +1,1516 @@
+
+Network Working Group                                       S. Alexander
+INTERNET DRAFT                                  Lachman Technology, Inc.
+Obsoletes: draft-ietf-dhc-options-1533update-00.txt             R. Droms
+                                                     Bucknell University
+                                                          September 1995
+                                                      Expires March 1996
+
+
+               DHCP Options and BOOTP Vendor Extensions
+               <draft-ietf-dhc-options-1533update-01.txt>
+
+Status of this memo
+
+   This document is an Internet-Draft. Internet-Drafts are working
+   documents of the Internet Engineering Task Force (IETF), its areas,
+   and its working groups. Note that other groups may also distribute
+   working documents as Internet-Drafts.
+
+   Internet-Drafts are draft documents valid for a maximum of six months
+   and may be updated, replaced, or obsoleted by other documents at any
+   time. It is inappropriate to use Internet-Drafts as reference
+   material or to cite them other than as ``work in progress.''
+
+   To learn the current status of any Internet-Draft, please check the
+   ``1id-abstracts.txt'' listing contained in the Internet-Drafts Shadow
+   Directories on ftp.is.co.za (Africa), nic.nordu.net (Europe),
+   munnari.oz.au (Pacific Rim), ds.internic.net (US East Coast), or
+   ftp.isi.edu (US West Coast).
+
+Abstract
+
+   The Dynamic Host Configuration Protocol (DHCP) [1] provides a
+   framework for passing configuration information to hosts on a TCP/IP
+   network.  Configuration parameters and other control information are
+   carried in tagged data items that are stored in the 'options' field
+   of the DHCP message.  The data items themselves are also called
+   "options."
+
+   This document specifies the current set of DHCP options.  This
+   document will be periodically updated as new options are defined.
+    Each superseding document will include the entire current list of
+   valid options.  The current list of valid options is also available
+   in ftp://ftp.isi.edu/in-notes/iana/assignments [22].
+
+   All of the vendor information extensions defined in RFC 1497 [2] may
+   be used as DHCP options.  The definitions given in RFC 1497 are
+   included in this document, which supersedes RFC 1497.  All of the
+   DHCP options defined in this document, except for those specific to
+   DHCP as defined in section 9, may be used as BOOTP vendor information
+   extensions.
+
+Table of Contents
+
+    1.  Introduction ..............................................  2
+    2.  BOOTP Extension/DHCP Option Field Format ..................  2
+    3.  RFC 1497 Vendor Extensions ................................  3
+    4.  IP Layer Parameters per Host .............................. 10
+    5.  IP Layer Parameters per Interface ........................  13
+    6.  Link Layer Parameters per Interface ....................... 16
+    7.  TCP Parameters ............................................ 17
+    8.  Application and Service Parameters ........................ 18
+    9.  DHCP Extensions ........................................... 26
+   10.  Extensions ................................................ 33
+   11.  Acknowledgements .......................................... 33
+   12.  References ................................................ 33
+   13.  Security Considerations ................................... 35
+   14.  Authors' Addresses ........................................ 35
+   A.   Changes to draft-ietf-dhc-options-1533update-00.txt........ 36
+
+1. Introduction
+
+   This document specifies options for use with both the Dynamic Host
+   Configuration Protocol and the Bootstrap Protocol.
+
+   The full description of DHCP packet formats may be found in the DHCP
+   specification document [1], and the full description of BOOTP packet
+   formats may be found in the BOOTP specification document [3].  This
+   document defines the format of information in the last field of DHCP
+   packets ('options') and of BOOTP packets ('vend').  The remainder of
+   this section defines a generalized use of this area for giving
+   information useful to a wide class of machines, operating systems and
+   configurations. Sites with a single DHCP or BOOTP server that is
+   shared among heterogeneous clients may choose to define other, site-
+   specific formats for the use of the 'options' field.
+
+   Section 2 of this memo describes the formats of DHCP options and
+   BOOTP vendor extensions.  Section 3 describes options defined in
+   previous documents for use with BOOTP (all may also be used with
+   DHCP).  Sections 4-8 define new options intended for use with both
+   DHCP and BOOTP. Section 9 defines options used only in DHCP.
+
+   References further describing most of the options defined in sections
+   2-6 can be found in section 12.  The use of the options defined in
+   section 9 is described in the DHCP specification [1].
+
+   Information on registering new options is contained in section 10.
+
+2. BOOTP Extension/DHCP Option Field Format
+
+   DHCP options have the same format as the BOOTP 'vendor extensions'
+   defined in RFC 1497 [2].  Options may be fixed length or variable
+   length.  All options begin with a tag octet, which uniquely
+   identifies the option.  Fixed-length options without data consist of
+   only a tag octet.  Only options 0 and 255 are fixed length.  All
+   other options are variable-length with a length octet following the
+   tag octet.  The value of the length octet does not include the two
+   octets specifying the tag and length.  The length octet is followed
+   by "length" octets of data.  Options containing NVT ASCII data SHOULD
+   NOT include a trailing NULL; however, the receiver of such options
+   MUST be prepared to delete trailing nulls if they exist.  The
+   receiver MUST NOT require that a trailing null be included in the
+   data.  In the case of some variable-length options the length field
+   is a constant but must still be specified.
+
+   Any options defined subsequent to this document should contain a
+   length octet even if the length is fixed or zero.
+
+   All multi-octet quantities are in network byte-order.
+
+   When used with BOOTP, the first four octets of the vendor information
+   field have been assigned to the "magic cookie" (as suggested in RFC
+   951).  This field identifies the mode in which the succeeding data is
+   to be interpreted.  The value of the magic cookie is the 4 octet
+   dotted decimal 99.130.83.99 (or hexadecimal number 63.82.53.63) in
+   network byte order.
+
+   All of the "vendor extensions" defined in RFC 1497 are also DHCP
+   options.
+
+   Option codes 128 to 254 (decimal) are reserved for site-specific
+   options.
+
+   Except for the options in section 9, all options may be used with
+   either DHCP or BOOTP.
+
+   Many of these options have their default values specified in other
+   documents.  In particular, RFC 1122 [4] specifies default values for
+   most IP and TCP configuration parameters.
+
+3. RFC 1497 Vendor Extensions
+
+   This section lists the vendor extensions as defined in RFC 1497.
+   They are defined here for completeness.
+
+3.1. Pad Option
+
+   The pad option can be used to cause subsequent fields to align on
+   word boundaries.
+
+   The code for the pad option is 0, and its length is 1 octet.
+
+    Code
+   +-----+
+   |  0  |
+   +-----+
+
+3.2. End Option
+
+   The end option marks the end of valid information in the vendor
+   field.  Subsequent octets should be filled with pad options.
+
+   The code for the end option is 255, and its length is 1 octet.
+
+    Code
+   +-----+
+   | 255 |
+   +-----+
+
+3.3. Subnet Mask
+
+   The subnet mask option specifies the client's subnet mask as per RFC
+   950 [5].
+
+   If both the subnet mask and the router option are specified in a DHCP
+   reply, the subnet mask option MUST be first.
+
+   The code for the subnet mask option is 1, and its length is 4 octets.
+
+    Code   Len        Subnet Mask
+   +-----+-----+-----+-----+-----+-----+
+   |  1  |  4  |  m1 |  m2 |  m3 |  m4 |
+   +-----+-----+-----+-----+-----+-----+
+
+3.4. Time Offset
+
+   The time offset field specifies the offset of the client's subnet in
+   seconds from Coordinated Universal Time (UTC).  The offset is
+   expressed as a signed 32-bit integer.
+
+   The code for the time offset option is 2, and its length is 4 octets.
+
+    Code   Len        Time Offset
+   +-----+-----+-----+-----+-----+-----+
+   |  2  |  4  |  n1 |  n2 |  n3 |  n4 |
+   +-----+-----+-----+-----+-----+-----+
+
+3.5. Router Option
+
+   The router option specifies a list of IP addresses for routers on the
+   client's subnet.  Routers SHOULD be listed in order of preference.
+
+   The code for the router option is 3.  The minimum length for the
+   router option is 4 octets, and the length MUST always be a multiple
+   of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  3  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+3.6. Time Server Option
+
+   The time server option specifies a list of RFC 868 [6] time servers
+   available to the client.  Servers SHOULD be listed in order of
+   preference.
+
+   The code for the time server option is 4.  The minimum length for
+   this option is 4 octets, and the length MUST always be a multiple of
+   4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  4  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+3.7. Name Server Option
+
+   The name server option specifies a list of IEN 116 [7] name servers
+   available to the client.  Servers SHOULD be listed in order of
+   preference.
+
+   The code for the name server option is 5.  The minimum length for
+   this option is 4 octets, and the length MUST always be a multiple of
+   4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  5  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+3.8. Domain Name Server Option
+
+   The domain name server option specifies a list of Domain Name System
+   (STD 13, RFC 1035 [8]) name servers available to the client.  Servers
+   SHOULD be listed in order of preference.
+
+   The code for the domain name server option is 6.  The minimum length
+   for this option is 4 octets, and the length MUST always be a multiple
+   of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  6  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+3.9. Log Server Option
+
+   The log server option specifies a list of MIT-LCS UDP log servers
+   available to the client.  Servers SHOULD be listed in order of
+   preference.
+
+   The code for the log server option is 7.  The minimum length for this
+   option is 4 octets, and the length MUST always be a multiple of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  7  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+3.10. Cookie Server Option
+
+   The cookie server option specifies a list of RFC 865 [9] cookie
+   servers available to the client.  Servers SHOULD be listed in order
+   of preference.
+
+   The code for the log server option is 8.  The minimum length for this
+   option is 4 octets, and the length MUST always be a multiple of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  8  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+3.11. LPR Server Option
+
+   The LPR server option specifies a list of RFC 1179 [10] line printer
+   servers available to the client.  Servers SHOULD be listed in order
+   of preference.
+
+   The code for the LPR server option is 9.  The minimum length for this
+   option is 4 octets, and the length MUST always be a multiple of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  9  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+3.12. Impress Server Option
+
+   The Impress server option specifies a list of Imagen Impress servers
+   available to the client.  Servers SHOULD be listed in order of
+   preference.
+
+   The code for the Impress server option is 10.  The minimum length for
+   this option is 4 octets, and the length MUST always be a multiple of
+   4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  10 |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+3.13. Resource Location Server Option
+
+   This option specifies a list of RFC 887 [11] Resource Location
+   servers available to the client.  Servers SHOULD be listed in order
+   of preference.
+
+   The code for this option is 11.  The minimum length for this option
+   is 4 octets, and the length MUST always be a multiple of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  11 |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+3.14. Host Name Option
+
+   This option specifies the name of the client.  The name may or may
+   not be qualified with the local domain name (see section 3.17 for the
+   preferred way to retrieve the domain name).  See RFC 1035 for
+   character set restrictions.
+
+   The code for this option is 12, and its minimum length is 1.
+
+    Code   Len                 Host Name
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  12 |  n  |  h1 |  h2 |  h3 |  h4 |  h5 |  h6 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+3.15. Boot File Size Option
+
+   This option specifies the length in 512-octet blocks of the default
+   boot image for the client.  The file length is specified as an
+   unsigned 16-bit integer.
+
+   The code for this option is 13, and its length is 2.
+
+    Code   Len   File Size
+   +-----+-----+-----+-----+
+   |  13 |  2  |  l1 |  l2 |
+   +-----+-----+-----+-----+
+
+3.16. Merit Dump File
+
+   This option specifies the path-name of a file to which the client's
+   core image should be dumped in the event the client crashes.  The
+   path is formatted as a character string consisting of characters from
+   the NVT ASCII character set.
+
+   The code for this option is 14.  Its minimum length is 1.
+
+    Code   Len      Dump File Pathname
+   +-----+-----+-----+-----+-----+-----+---
+   |  14 |  n  |  n1 |  n2 |  n3 |  n4 | ...
+   +-----+-----+-----+-----+-----+-----+---
+
+3.17. Domain Name
+
+   This option specifies the domain name that client should use when
+   resolving hostnames via the Domain Name System.
+
+   The code for this option is 15.  Its minimum length is 1.
+
+    Code   Len        Domain Name
+   +-----+-----+-----+-----+-----+-----+--
+   |  15 |  n  |  d1 |  d2 |  d3 |  d4 |  ...
+   +-----+-----+-----+-----+-----+-----+--
+
+3.18. Swap Server
+
+   This specifies the IP address of the client's swap server.
+
+   The code for this option is 16 and its length is 4.
+
+    Code   Len    Swap Server Address
+   +-----+-----+-----+-----+-----+-----+
+   |  16 |  n  |  a1 |  a2 |  a3 |  a4 |
+   +-----+-----+-----+-----+-----+-----+
+
+3.19. Root Path
+
+   This option specifies the path-name that contains the client's root
+   disk.  The path is formatted as a character string consisting of
+   characters from the NVT ASCII character set.
+
+   The code for this option is 17.  Its minimum length is 1.
+
+    Code   Len      Root Disk Pathname
+   +-----+-----+-----+-----+-----+-----+---
+   |  17 |  n  |  n1 |  n2 |  n3 |  n4 | ...
+   +-----+-----+-----+-----+-----+-----+---
+
+3.20. Extensions Path
+
+   A string to specify a file, retrievable via TFTP, which contains
+   information which can be interpreted in the same way as the 64-octet
+   vendor-extension field within the BOOTP response, with the following
+   exceptions:
+
+          - the length of the file is unconstrained;
+          - all references to Tag 18 (i.e., instances of the
+            BOOTP Extensions Path field) within the file are
+            ignored.
+
+   The code for this option is 18.  Its minimum length is 1.
+
+    Code   Len      Extensions Pathname
+   +-----+-----+-----+-----+-----+-----+---
+   |  18 |  n  |  n1 |  n2 |  n3 |  n4 | ...
+   +-----+-----+-----+-----+-----+-----+---
+
+4. IP Layer Parameters per Host
+
+   This section details the options that affect the operation of the IP
+   layer on a per-host basis.
+
+4.1. IP Forwarding Enable/Disable Option
+
+   This option specifies whether the client should configure its IP
+   layer for packet forwarding.  A value of 0 means disable IP
+   forwarding, and a value of 1 means enable IP forwarding.
+
+   The code for this option is 19, and its length is 1.
+
+    Code   Len  Value
+   +-----+-----+-----+
+   |  19 |  1  | 0/1 |
+   +-----+-----+-----+
+
+4.2. Non-Local Source Routing Enable/Disable Option
+
+   This option specifies whether the client should configure its IP
+   layer to allow forwarding of datagrams with non-local source routes
+   (see Section 3.3.5 of [4] for a discussion of this topic).  A value
+   of 0 means disallow forwarding of such datagrams, and a value of 1
+   means allow forwarding.
+
+   The code for this option is 20, and its length is 1.
+
+    Code   Len  Value
+   +-----+-----+-----+
+   |  20 |  1  | 0/1 |
+   +-----+-----+-----+
+
+4.3. Policy Filter Option
+
+   This option specifies policy filters for non-local source routing.
+   The filters consist of a list of IP addresses and masks which specify
+   destination/mask pairs with which to filter incoming source routes.
+
+   Any source routed datagram whose next-hop address does not match one
+   of the filters should be discarded by the client.
+
+   See [4] for further information.
+
+   The code for this option is 21.  The minimum length of this option is
+   8, and the length MUST be a multiple of 8.
+
+    Code   Len         Address 1                  Mask 1
+   +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+   |  21 |  n  |  a1 |  a2 |  a3 |  a4 |  m1 |  m2 |  m3 |  m4 |
+   +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+           Address 2                  Mask 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+---
+   |  a1 |  a2 |  a3 |  a4 |  m1 |  m2 |  m3 |  m4 | ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+---
+
+4.4. Maximum Datagram Reassembly Size
+
+   This option specifies the maximum size datagram that the client
+   should be prepared to reassemble.  The size is specified as a 16-bit
+   unsigned integer.  The minimum value legal value is 576.
+
+   The code for this option is 22, and its length is 2.
+
+    Code   Len      Size
+   +-----+-----+-----+-----+
+   |  22 |  2  |  s1 |  s2 |
+   +-----+-----+-----+-----+
+
+4.5. Default IP Time-to-live
+
+   This option specifies the default time-to-live that the client should
+   use on outgoing datagrams.  The TTL is specified as an octet with a
+   value between 1 and 255.
+
+   The code for this option is 23, and its length is 1.
+
+    Code   Len   TTL
+   +-----+-----+-----+
+   |  23 |  1  | ttl |
+   +-----+-----+-----+
+
+4.6. Path MTU Aging Timeout Option
+
+   This option specifies the timeout (in seconds) to use when aging Path
+   MTU values discovered by the mechanism defined in RFC 1191 [12].  The
+   timeout is specified as a 32-bit unsigned integer.
+
+   The code for this option is 24, and its length is 4.
+
+    Code   Len           Timeout
+   +-----+-----+-----+-----+-----+-----+
+   |  24 |  4  |  t1 |  t2 |  t3 |  t4 |
+   +-----+-----+-----+-----+-----+-----+
+
+4.7. Path MTU Plateau Table Option
+
+   This option specifies a table of MTU sizes to use when performing
+   Path MTU Discovery as defined in RFC 1191.  The table is formatted as
+   a list of 16-bit unsigned integers, ordered from smallest to largest.
+   The minimum MTU value cannot be smaller than 68.
+
+   The code for this option is 25.  Its minimum length is 2, and the
+   length MUST be a multiple of 2.
+
+    Code   Len     Size 1      Size 2
+   +-----+-----+-----+-----+-----+-----+---
+   |  25 |  n  |  s1 |  s2 |  s1 |  s2 | ...
+   +-----+-----+-----+-----+-----+-----+---
+
+5. IP Layer Parameters per Interface
+
+   This section details the options that affect the operation of the IP
+   layer on a per-interface basis.  It is expected that a client can
+   issue multiple requests, one per interface, in order to configure
+   interfaces with their specific parameters.
+
+5.1. Interface MTU Option
+
+   This option specifies the MTU to use on this interface.  The MTU is
+   specified as a 16-bit unsigned integer.  The minimum legal value for
+   the MTU is 68.
+
+   The code for this option is 26, and its length is 2.
+
+    Code   Len      MTU
+   +-----+-----+-----+-----+
+   |  26 |  2  |  m1 |  m2 |
+   +-----+-----+-----+-----+
+
+5.2. All Subnets are Local Option
+
+   This option specifies whether or not the client may assume that all
+   subnets of the IP network to which the client is connected use the
+   same MTU as the subnet of that network to which the client is
+   directly connected.  A value of 1 indicates that all subnets share
+   the same MTU.  A value of 0 means that the client should assume that
+   some subnets of the directly connected network may have smaller MTUs.
+
+   The code for this option is 27, and its length is 1.
+
+    Code   Len  Value
+   +-----+-----+-----+
+   |  27 |  1  | 0/1 |
+   +-----+-----+-----+
+
+5.3. Broadcast Address Option
+
+   This option specifies the broadcast address in use on the client's
+   subnet.  Legal values for broadcast addresses are specified in
+   section 3.2.1.3 of [4].
+
+   The code for this option is 28, and its length is 4.
+
+    Code   Len     Broadcast Address
+   +-----+-----+-----+-----+-----+-----+
+   |  28 |  4  |  b1 |  b2 |  b3 |  b4 |
+   +-----+-----+-----+-----+-----+-----+
+
+5.4. Perform Mask Discovery Option
+
+   This option specifies whether or not the client should perform subnet
+   mask discovery using ICMP.  A value of 0 indicates that the client
+   should not perform mask discovery.  A value of 1 means that the
+   client should perform mask discovery.
+
+   The code for this option is 29, and its length is 1.
+
+    Code   Len  Value
+   +-----+-----+-----+
+   |  29 |  1  | 0/1 |
+   +-----+-----+-----+
+
+5.5. Mask Supplier Option
+
+   This option specifies whether or not the client should respond to
+   subnet mask requests using ICMP.  A value of 0 indicates that the
+   client should not respond.  A value of 1 means that the client should
+   respond.
+
+   The code for this option is 30, and its length is 1.
+
+    Code   Len  Value
+   +-----+-----+-----+
+   |  30 |  1  | 0/1 |
+   +-----+-----+-----+
+
+5.6. Perform Router Discovery Option
+
+   This option specifies whether or not the client should solicit
+   routers using the Router Discovery mechanism defined in RFC 1256
+   [13].  A value of 0 indicates that the client should not perform
+   router discovery.  A value of 1 means that the client should perform
+   router discovery.
+
+   The code for this option is 31, and its length is 1.
+
+    Code   Len  Value
+   +-----+-----+-----+
+   |  31 |  1  | 0/1 |
+   +-----+-----+-----+
+
+5.7. Router Solicitation Address Option
+
+   This option specifies the address to which the client should transmit
+   router solicitation requests.
+
+   The code for this option is 32, and its length is 4.
+
+    Code   Len            Address
+   +-----+-----+-----+-----+-----+-----+
+   |  32 |  4  |  a1 |  a2 |  a3 |  a4 |
+   +-----+-----+-----+-----+-----+-----+
+
+5.8. Static Route Option
+
+   This option specifies a list of static routes that the client should
+   install in its routing cache.  If multiple routes to the same
+   destination are specified, they are listed in descending order of
+   priority.
+
+   The routes consist of a list of IP address pairs.  The first address
+   is the destination address, and the second address is the router for
+   the destination.
+
+   The default route (0.0.0.0) is an illegal destination for a static
+   route.  See section 3.5 for information about the router option.
+
+   The code for this option is 33.  The minimum length of this option is
+   8, and the length MUST be a multiple of 8.
+
+    Code   Len         Destination 1           Router 1
+   +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+   |  33 |  n  |  d1 |  d2 |  d3 |  d4 |  r1 |  r2 |  r3 |  r4 |
+   +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+           Destination 2           Router 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+---
+   |  d1 |  d2 |  d3 |  d4 |  r1 |  r2 |  r3 |  r4 | ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+---
+
+6. Link Layer Parameters per Interface
+
+   This section lists the options that affect the operation of the data
+   link layer on a per-interface basis.
+
+6.1. Trailer Encapsulation Option
+
+   This option specifies whether or not the client should negotiate the
+   use of trailers (RFC 893 [14]) when using the ARP protocol.  A value
+   of 0 indicates that the client should not attempt to use trailers.  A
+   value of 1 means that the client should attempt to use trailers.
+
+   The code for this option is 34, and its length is 1.
+
+    Code   Len  Value
+   +-----+-----+-----+
+   |  34 |  1  | 0/1 |
+   +-----+-----+-----+
+
+6.2. ARP Cache Timeout Option
+
+   This option specifies the timeout in seconds for ARP cache entries.
+   The time is specified as a 32-bit unsigned integer.
+
+   The code for this option is 35, and its length is 4.
+
+    Code   Len           Time
+   +-----+-----+-----+-----+-----+-----+
+   |  35 |  4  |  t1 |  t2 |  t3 |  t4 |
+   +-----+-----+-----+-----+-----+-----+
+
+6.3. Ethernet Encapsulation Option
+
+   This option specifies whether or not the client should use Ethernet
+   Version 2 (RFC 894 [15]) or IEEE 802.3 (RFC 1042 [16]) encapsulation
+   if the interface is an Ethernet.  A value of 0 indicates that the
+   client should use RFC 894 encapsulation.  A value of 1 means that the
+   client should use RFC 1042 encapsulation.
+
+   The code for this option is 36, and its length is 1.
+
+    Code   Len  Value
+   +-----+-----+-----+
+   |  36 |  1  | 0/1 |
+   +-----+-----+-----+
+
+7. TCP Parameters
+
+   This section lists the options that affect the operation of the TCP
+   layer on a per-interface basis.
+
+7.1. TCP Default TTL Option
+
+   This option specifies the default TTL that the client should use when
+   sending TCP segments.  The value is represented as an 8-bit unsigned
+   integer.  The minimum value is 1.
+
+   The code for this option is 37, and its length is 1.
+
+    Code   Len   TTL
+   +-----+-----+-----+
+   |  37 |  1  |  n  |
+   +-----+-----+-----+
+
+7.2. TCP Keepalive Interval Option
+
+   This option specifies the interval (in seconds) that the client TCP
+   should wait before sending a keepalive message on a TCP connection.
+   The time is specified as a 32-bit unsigned integer.  A value of zero
+   indicates that the client should not generate keepalive messages on
+   connections unless specifically requested by an application.
+
+   The code for this option is 38, and its length is 4.
+
+    Code   Len           Time
+   +-----+-----+-----+-----+-----+-----+
+   |  38 |  4  |  t1 |  t2 |  t3 |  t4 |
+   +-----+-----+-----+-----+-----+-----+
+
+7.3. TCP Keepalive Garbage Option
+
+   This option specifies the whether or not the client should send TCP
+   keepalive messages with a octet of garbage for compatibility with
+   older implementations.  A value of 0 indicates that a garbage octet
+   should not be sent. A value of 1 indicates that a garbage octet
+   should be sent.
+
+   The code for this option is 39, and its length is 1.
+
+    Code   Len  Value
+   +-----+-----+-----+
+   |  39 |  1  | 0/1 |
+   +-----+-----+-----+
+
+8. Application and Service Parameters
+
+   This section details some miscellaneous options used to configure
+   miscellaneous applications and services.
+
+8.1. Network Information Service Domain Option
+
+   This option specifies the name of the client's NIS [17] domain.  The
+   domain is formatted as a character string consisting of characters
+   from the NVT ASCII character set.
+
+   The code for this option is 40.  Its minimum length is 1.
+
+    Code   Len      NIS Domain Name
+   +-----+-----+-----+-----+-----+-----+---
+   |  40 |  n  |  n1 |  n2 |  n3 |  n4 | ...
+   +-----+-----+-----+-----+-----+-----+---
+
+8.2. Network Information Servers Option
+
+   This option specifies a list of IP addresses indicating NIS servers
+   available to the client.  Servers SHOULD be listed in order of
+   preference.
+
+   The code for this option is 41.  Its minimum length is 4, and the
+   length MUST be a multiple of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  41 |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+8.3. Network Time Protocol Servers Option
+
+   This option specifies a list of IP addresses indicating NTP [18]
+   servers available to the client.  Servers SHOULD be listed in order
+   of preference.
+
+   The code for this option is 42.  Its minimum length is 4, and the
+   length MUST be a multiple of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  42 |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+8.4. Vendor Specific Information
+
+   This option is used by clients and servers to exchange vendor-
+   specific information.  The information is an opaque object of n
+   octets, presumably interpreted by vendor-specific code on the clients
+   and servers.  The definition of this information is vendor specific.
+   The vendor is indicated in the vendor class identifier option.
+   Servers not equipped to interpret the vendor-specific information
+   sent by a client MUST ignore it (although it may be reported).
+   Clients which do not receive desired vendor-specific information
+   SHOULD make an attempt to operate without it, although they may do so
+   (and announce they are doing so) in a degraded mode.
+
+   If a vendor potentially encodes more than one item of information in
+   this option, then the vendor SHOULD encode the option using
+   "Encapsulated vendor-specific options" as described below:
+
+   The Encapsulated vendor-specific options field SHOULD be encoded as a
+   sequence of code/length/value fields of identical syntax to the DHCP
+   options field with the following exceptions:
+
+      1) There SHOULD NOT be a "magic cookie" field in the encapsulated
+         vendor-specific extensions field.
+
+      2) Codes other than 0 or 255 MAY be redefined by the vendor within
+         the encapsulated vendor-specific extensions field, but SHOULD
+         conform to the tag-length-value syntax defined in section 2.
+
+      3) Code 255 (END), if present, signifies the end of the
+         encapsulated vendor extensions, not the end of the vendor
+         extensions field. If no code 255 is present, then the end of
+         the enclosing vendor-specific information field is taken as the
+         end of the encapsulated vendor-specific extensions field.
+
+   The code for this option is 43 and its minimum length is 1.
+
+   Code   Len   Vendor-specific information
+   +-----+-----+-----+-----+---
+   |  43 |  n  |  i1 |  i2 | ...
+   +-----+-----+-----+-----+---
+
+   When encapsulated vendor-specific extensions are used, the
+   information bytes 1-n have the following format:
+
+    Code   Len   Data item        Code   Len   Data item       Code
+   +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+   |  T1 |  n  |  d1 |  d2 | ... |  T2 |  n  |  D1 |  D2 | ... | ... |
+   +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+
+8.5. NetBIOS over TCP/IP Name Server Option
+
+   The NetBIOS name server (NBNS) option specifies a list of RFC
+   1001/1002 [19] [20] NBNS name servers listed in order of preference.
+
+   The code for this option is 44.  The minimum length of the option is
+   4 octets, and the length must always be a multiple of 4.
+
+    Code   Len           Address 1              Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----
+   |  44 |  n  |  a1 |  a2 |  a3 |  a4 |  b1 |  b2 |  b3 |  b4 | ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----
+
+8.6. NetBIOS over TCP/IP Datagram Distribution Server Option
+
+   The NetBIOS datagram distribution server (NBDD) option specifies a
+   list of RFC 1001/1002 NBDD servers listed in order of preference. The
+   code for this option is 45.  The minimum length of the option is 4
+   octets, and the length must always be a multiple of 4.
+
+    Code   Len           Address 1              Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----
+   |  45 |  n  |  a1 |  a2 |  a3 |  a4 |  b1 |  b2 |  b3 |  b4 | ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----
+
+8.7. NetBIOS over TCP/IP Node Type Option
+
+   The NetBIOS node type option allows NetBIOS over TCP/IP clients which
+   are configurable to be configured as described in RFC 1001/1002.  The
+   value is specified as a single octet which identifies the client type
+   as follows:
+
+      Value         Node Type
+      -----         ---------
+      0x1           B-node
+      0x2           P-node
+      0x4           M-node
+      0x8           H-node
+
+   In the above chart, the notation '0x' indicates a number in base-16
+   (hexadecimal).
+
+   The code for this option is 46.  The length of this option is always
+   1.
+
+    Code   Len  Node Type
+   +-----+-----+-----------+
+   |  46 |  1  | see above |
+   +-----+-----+-----------+
+
+8.8. NetBIOS over TCP/IP Scope Option
+
+   The NetBIOS scope option specifies the NetBIOS over TCP/IP scope
+   parameter for the client as specified in RFC 1001/1002. See [19],
+   [20], and [8] for character-set restrictions.
+
+   The code for this option is 47.  The minimum length of this option is
+   1.
+
+    Code   Len       NetBIOS Scope
+   +-----+-----+-----+-----+-----+-----+----
+   |  47 |  n  |  s1 |  s2 |  s3 |  s4 | ...
+   +-----+-----+-----+-----+-----+-----+----
+
+8.9. X Window System Font Server Option
+
+   This option specifies a list of X Window System [21] Font servers
+   available to the client. Servers SHOULD be listed in order of
+   preference.
+
+   The code for this option is 48.  The minimum length of this option is
+   4 octets, and the length MUST be a multiple of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+---
+   |  48 |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |   ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+---
+
+8.10. X Window System Display Manager Option
+
+   This option specifies a list of IP addresses of systems that are
+   running the X Window System Display Manager and are available to the
+   client.
+
+   Addresses SHOULD be listed in order of preference.
+
+   The code for the this option is 49. The minimum length of this option
+   is 4, and the length MUST be a multiple of 4.
+
+    Code   Len         Address 1               Address 2
+
+   +-----+-----+-----+-----+-----+-----+-----+-----+---
+   |  49 |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |   ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+---
+
+8.11. Network Information Service+ Domain Option
+
+This option specifies the name of the client's NIS+ [17] domain.  The
+domain is formatted as a character string consisting of characters
+from the NVT ASCII character set.
+
+The code for this option is 64.  Its minimum length is 1.
+
+    Code   Len      NIS Client Domain Name
+   +-----+-----+-----+-----+-----+-----+---
+   |  64 |  n  |  n1 |  n2 |  n3 |  n4 | ...
+   +-----+-----+-----+-----+-----+-----+---
+
+8.12. Network Information Service+ Servers Option
+
+   This option specifies a list of IP addresses indicating NIS+ servers
+   available to the client.  Servers SHOULD be listed in order of
+   preference.
+
+   The code for this option is 65.  Its minimum length is 4, and the
+   length MUST be a multiple of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  65 |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+8.13. Mobile IP Home Agent option
+
+   This option specifies a list of IP addresses indicating mobile IP
+   home agents available to the client.  Agents SHOULD be listed in
+   order of preference.
+
+   The code for this option is 68.  Its minimum length is 0 (indicating
+   no home agents are available) and the length MUST be a multiple of 4.
+   It is expected that the usual length will be four octets, containing
+   a single home agent's address.
+
+    Code Len    Home Agent Addresses (zero or more)
+   +-----+-----+-----+-----+-----+-----+--
+   | 68  |  n  | a1  | a2  | a3  | a4  | ...
+   +-----+-----+-----+-----+-----+-----+--
+
+8.14. Simple Mail Transport Protocol (SMTP) Server Option
+
+   The SMTP server option specifies a list of SMTP servers available to
+   the client.  Servers SHOULD be listed in order of preference.
+
+   The code for the SMTP server option is 69.  The minimum length for
+   this option is 4 octets, and the length MUST always be a multiple of
+   4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   | 69  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+8.15. Post Office Protocol (POP3) Server Option
+
+   The POP3 server option specifies a list of POP3 available to the
+   client.  Servers SHOULD be listed in order of preference.
+
+   The code for the POP3 server option is 70.  The minimum length for
+   this option is 4 octets, and the length MUST always be a multiple of
+   4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   | 70  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+8.16. Network News Transport Protocol (NNTP) Server Option
+
+   The NNTP server option specifies a list of NNTP available to the
+   client.  Servers SHOULD be listed in order of preference.
+
+   The code for the NNTP server option is 71. The minimum length for
+   this option is 4 octets, and the length MUST always be a multiple of
+   4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   | 71  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+8.17. Default World Wide Web (WWW) Server Option
+
+   The WWW server option specifies a list of WWW available to the
+   client.  Servers SHOULD be listed in order of preference.
+
+   The code for the WWW server option is 72.  The minimum length for
+   this option is 4 octets, and the length MUST always be a multiple of
+   4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   | 72  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+8.18. Default Finger Server Option
+
+   The Finger server option specifies a list of Finger available to the
+   client.  Servers SHOULD be listed in order of preference.
+
+   The code for the Finger server option is 73.  The minimum length for
+   this option is 4 octets, and the length MUST always be a multiple of
+   4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   | 73  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+8.19. Default Internet Relay Chat (IRC) Server Option
+
+   The IRC server option specifies a list of IRC available to the
+   client.  Servers SHOULD be listed in order of preference.
+
+   The code for the IRC server option is 74.  The minimum length for
+   this option is 4 octets, and the length MUST always be a multiple of
+   4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   | 74  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+8.20. StreetTalk Server Option
+
+   The StreetTalk server option specifies a list of StreetTalk servers
+   available to the client.  Servers SHOULD be listed in order of
+   preference.
+
+   The code for the StreetTalk server option is 75.  The minimum length
+   for this option is 4 octets, and the length MUST always be a multiple
+   of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   | 75  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+8.21. StreetTalk Directory Assistance (STDA) Server Option
+
+   The StreetTalk Directory Assistance (STDA) server option specifies a
+   list of STDA servers available to the client.  Servers SHOULD be
+   listed in order of preference.
+
+   The code for the StreetTalk Directory Assistance server option is 76.
+   The minimum length for this option is 4 octets, and the length MUST
+   always be a multiple of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   | 76  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+9. DHCP Extensions
+
+   This section details the options that are specific to DHCP.
+
+9.1. Requested IP Address
+
+   This option is used in a client request (DHCPDISCOVER) to allow the
+   client to request that a particular IP address be assigned.
+
+   The code for this option is 50, and its length is 4.
+
+    Code   Len          Address
+   +-----+-----+-----+-----+-----+-----+
+   |  50 |  4  |  a1 |  a2 |  a3 |  a4 |
+   +-----+-----+-----+-----+-----+-----+
+
+9.2. IP Address Lease Time
+
+   This option is used in a client request (DHCPDISCOVER or DHCPREQUEST)
+   to allow the client to request a lease time for the IP address.  In a
+   server reply (DHCPOFFER), a DHCP server uses this option to specify
+   the lease time it is willing to offer.
+
+   The time is in units of seconds, and is specified as a 32-bit
+   unsigned integer.
+
+   The code for this option is 51, and its length is 4.
+
+    Code   Len         Lease Time
+   +-----+-----+-----+-----+-----+-----+
+   |  51 |  4  |  t1 |  t2 |  t3 |  t4 |
+   +-----+-----+-----+-----+-----+-----+
+
+9.3. Option Overload
+
+   This option is used to indicate that the DHCP 'sname' or 'file'
+   fields are being overloaded by using them to carry DHCP options. A
+   DHCP server inserts this option if the returned parameters will
+   exceed the usual space allotted for options.
+
+   If this option is present, the client interprets the specified
+   additional fields after it concludes interpretation of the standard
+   option fields.
+
+   The code for this option is 52, and its length is 1.  Legal values
+   for this option are:
+
+           Value   Meaning
+           -----   --------
+             1     the 'file' field is used to hold options
+             2     the 'sname' field is used to hold options
+             3     both fields are used to hold options
+
+    Code   Len  Value
+   +-----+-----+-----+
+   |  52 |  1  |1/2/3|
+   +-----+-----+-----+
+
+9.4 TFTP server name
+
+This option is used to identify a TFTP server when the 'sname'
+field in the DHCP header has been used for DHCP options.
+
+The code for this option is 66, and its minimum length is 1.
+
+    Code  Len   TFTP server
+   +-----+-----+-----+-----+-----+---
+   | 66  |  n  |  c1 |  c2 |  c3 | ...
+   +-----+-----+-----+-----+-----+---
+
+9.5 Bootfile name
+
+This option is used to identify a bootfile when the 'file' field in the
+DHCP header has been used for DHCP options.
+
+The code for this option is 67, and its minimum length is 1.
+
+    Code  Len   Bootfile name
+   +-----+-----+-----+-----+-----+---
+   | 67  |  n  |  c1 |  c2 |  c3 | ...
+   +-----+-----+-----+-----+-----+---
+
+9.6. DHCP Message Type
+
+   This option is used to convey the type of the DHCP message.  The code
+   for this option is 53, and its length is 1.  Legal values for this
+   option are:
+
+           Value   Message Type
+           -----   ------------
+             1     DHCPDISCOVER
+             2     DHCPOFFER
+             3     DHCPREQUEST
+             4     DHCPDECLINE
+             5     DHCPACK
+             6     DHCPNAK
+             7     DHCPRELEASE
+             8     DHCPINFORM
+
+    Code   Len  Type
+   +-----+-----+-----+
+   |  53 |  1  | 1-9 |
+   +-----+-----+-----+
+
+9.7. Server Identifier
+
+   This option is used in DHCPOFFER and DHCPREQUEST messages, and may
+   optionally be included in the DHCPACK and DHCPNAK messages.  DHCP
+   servers include this option in the DHCPOFFER in order to allow the
+   client to distinguish between lease offers.  DHCP clients indicate
+   which of several lease offers is being accepted by including this
+   option in a DHCPREQUEST message.
+
+   The identifier is the IP address of the selected server.
+
+   The code for this option is 54, and its length is 4.
+
+    Code   Len            Address
+   +-----+-----+-----+-----+-----+-----+
+   |  54 |  4  |  a1 |  a2 |  a3 |  a4 |
+   +-----+-----+-----+-----+-----+-----+
+
+9.8. Parameter Request List
+
+   This option is used by a DHCP client to request values for specified
+   configuration parameters.  The list of requested parameters is
+   specified as n octets, where each octet is a valid DHCP option code
+   as defined in this document.
+
+   The client MAY list the options in order of preference.  The DHCP
+   server is not required to return the options in the requested order,
+   but MUST try to insert the requested options in the order requested
+   by the client.
+
+   The code for this option is 55.  Its minimum length is 1.
+
+    Code   Len   Option Codes
+   +-----+-----+-----+-----+---
+   |  55 |  n  |  c1 |  c2 | ...
+   +-----+-----+-----+-----+---
+
+9.9. Message
+
+   This option is used by a DHCP server to provide an error message to a
+   DHCP client in a DHCPNAK message in the event of a failure. A client
+   may use this option in a DHCPDECLINE message to indicate the why the
+   client declined the offered parameters.  The message consists of n
+   octets of NVT ASCII text, which the client may display on an
+   available output device.
+
+   The code for this option is 56 and its minimum length is 1.
+
+    Code   Len     Text
+   +-----+-----+-----+-----+---
+   |  56 |  n  |  c1 |  c2 | ...
+   +-----+-----+-----+-----+---
+
+9.10. Maximum DHCP Message Size
+
+   This option specifies the maximum length DHCP message that it is
+   willing to accept.  The length is specified as an unsigned 16-bit
+   integer.  A client may use the maximum DHCP message size option in
+   DHCPDISCOVER or DHCPREQUEST messages, but should not use the option
+   in DHCPDECLINE messages.
+
+   The code for this option is 57, and its length is 2.  The minimum
+   legal value is 576 octets.
+
+    Code   Len     Length
+   +-----+-----+-----+-----+
+   |  57 |  2  |  l1 |  l2 |
+   +-----+-----+-----+-----+
+
+9.11. Renewal (T1) Time Value
+
+   This option specifies the time interval from address assignment until
+   the client transitions to the RENEWING state.
+
+   The value is in units of seconds, and is specified as a 32-bit
+   unsigned integer.
+
+   The code for this option is 58, and its length is 4.
+
+    Code   Len         T1 Interval
+   +-----+-----+-----+-----+-----+-----+
+   |  58 |  4  |  t1 |  t2 |  t3 |  t4 |
+   +-----+-----+-----+-----+-----+-----+
+
+9.12. Rebinding (T2) Time Value
+
+   This option specifies the time interval from address assignment until
+   the client transitions to the REBINDING state.
+
+   The value is in units of seconds, and is specified as a 32-bit
+   unsigned integer.
+
+   The code for this option is 59, and its length is 4.
+
+    Code   Len         T2 Interval
+   +-----+-----+-----+-----+-----+-----+
+   |  59 |  4  |  t1 |  t2 |  t3 |  t4 |
+   +-----+-----+-----+-----+-----+-----+
+
+9.13. Vendor class identifier
+
+   This option is used by DHCP clients to optionally identify the vendor
+   type and configuration of a DHCP client.  The information is a string
+   of n octets, interpreted by servers.  Vendors may choose to define
+   specific vendor class identifiers to convey particular configuration
+   or other identification information about a client.  For example, the
+   identifier may encode the client's hardware configuration.  Servers
+   not equipped to interpret the class-specific information sent by a
+   client MUST ignore it (although it may be reported). Servers that
+   respond SHOULD only use option 43 to return the vendor-specific
+   information to the client.
+
+   The code for this option is 60, and its minimum length is 1.
+
+   Code   Len   Vendor class Identifier
+   +-----+-----+-----+-----+---
+   |  60 |  n  |  i1 |  i2 | ...
+   +-----+-----+-----+-----+---
+
+9.14. Client-identifier
+
+   This option is used by DHCP clients to specify their unique
+   identifier.  DHCP servers use this value to index their database of
+   address bindings.  This value is expected to be unique for all
+   clients in an administrative domain.
+
+   Identifiers SHOULD be treated as opaque objects by DHCP servers.
+
+   The client identifier MAY consist of type-value pairs similar to the
+   'htype'/'chaddr' fields defined in [3]. For instance, it MAY consist
+   of a hardware type and hardware address. In this case the type field
+   SHOULD be one of the ARP hardware types defined in STD2 [22].  A
+   hardware type of 0 (zero) should be used when the value field
+   contains an identifier other than a hardware address (e.g. a fully
+   qualified domain name).
+
+   The code for this option is 61, and its minimum length is 2.
+
+   Code   Len   Type  Client-Identifier
+   +-----+-----+-----+-----+-----+---
+   |  61 |  n  |  t1 |  i1 |  i2 | ...
+   +-----+-----+-----+-----+-----+---
+
+9.15. User Class Information
+
+   This option is used by a DHCP client to optionally identify the type
+   or category of user or applications it represents.  The information
+   contained in this option is an NVT ASCII text object that represents
+   the user class of which the client is a member.
+
+   DHCP administrators may define specific user class identifiers to
+   convey information about a client's software configuration or about
+   its user's preferences.  For example, an identifier may specify that
+   a particular DHCP client is a member of the class "accounting
+   auditors", which have special service needs such as a particular
+   database server.
+
+   Servers not equipped to interpret any of user classes specified by a
+   client MUST ignore it (although it may be reported).  Otherwise,
+   servers SHOULD respond with the set of options corresponding to the
+   user class specified by the client.  Further, if the server responds,
+   it MUST return this option to the client.
+
+   Clients which do not receive information for the user class requested
+   SHOULD make an attempt to operate without it, although they may do so
+   (and may announce they are doing so) in a degraded mode.
+   The code for this option is 77.  The minimum length for this option
+   is two.
+
+   Code   Len     text1
+  +-----+-----+-----+-----+-----
+  | 77  |  N  |  c1 |  c2 | ...
+  +-----+-----+-----+-----+-----
+
+
+10. Extensions
+
+   Additional generic data fields may be registered by contacting:
+
+      Internet Assigned Numbers Authority (IANA)
+      USC/Information Sciences Institute
+      4676 Admiralty Way
+      Marina del Rey, California  90292-6695
+
+      or by email as: iana@isi.edu
+
+   Implementation specific use of undefined generic types (those in the
+   range 61-127) may conflict with other implementations, and
+   registration is required.
+
+11. Acknowledgements
+
+   The authors would like to thank Philip Almquist for his feedback on
+   this document.  The comments of the DHCP Working Group are also
+   gratefully acknowledged.  In particular, Mike Carney and Jon Dreyer
+   from SunSelect suggested the current format of the Vendor-specific
+   Information option.
+
+   RFC 1497 is based on earlier work by Philip Prindeville, with help
+   from Drew Perkins, Bill Croft, and Steve Deering.
+
+12. References
+
+   [1] Droms, R., "Dynamic Host Configuration Protocol", RFC 1531,
+       Bucknell University, October 1993.
+
+   [2] Reynolds, J., "BOOTP Vendor Information Extensions", RFC 1497,
+       USC/Information Sciences Institute, August 1993.
+
+   [3] Croft, W., and J. Gilmore, "Bootstrap Protocol", RFC 951,
+       Stanford University and Sun Microsystems, September 1985.
+
+   [4] Braden, R., Editor, "Requirements for Internet Hosts -
+       Communication Layers", STD 3, RFC 1122, USC/Information Sciences
+       Institute, October 1989.
+
+   [5] Mogul, J., and J. Postel, "Internet Standard Subnetting
+       Procedure", STD 5, RFC 950, USC/Information Sciences Institute,
+       August 1985.
+
+   [6] Postel, J., and K. Harrenstien, "Time Protocol", STD 26, RFC
+       868, USC/Information Sciences Institute, SRI, May 1983.
+
+   [7] Postel, J., "Name Server", IEN 116, USC/Information Sciences
+       Institute, August 1979.
+
+   [8] Mockapetris, P., "Domain Names - Implementation and
+       Specification", STD 13, RFC 1035, USC/Information Sciences
+       Institute, November 1987.
+
+   [9] Postel, J., "Quote of the Day Protocol", STD 23, RFC 865,
+       USC/Information Sciences Institute, May 1983.
+
+   [10] McLaughlin, L., "Line Printer Daemon Protocol", RFC 1179, The
+        Wollongong Group, August 1990.
+
+   [11] Accetta, M., "Resource Location Protocol", RFC 887, CMU,
+        December 1983.
+
+   [12] Mogul, J. and S. Deering, "Path MTU Discovery", RFC 1191,
+        DECWRL,  Stanford University, November 1990.
+
+   [13] Deering, S., "ICMP Router Discovery Messages", RFC 1256,
+        Xerox PARC, September 1991.
+
+   [14] Leffler, S. and M. Karels, "Trailer Encapsulations", RFC 893,
+        U. C. Berkeley, April 1984.
+
+   [15] Hornig, C., "Standard for the Transmission of IP Datagrams over
+        Ethernet Networks", RFC 894, Symbolics, April 1984.
+
+   [16] Postel, J. and J. Reynolds, "Standard for the Transmission of
+        IP Datagrams Over IEEE 802 Networks", RFC 1042,  USC/Information
+        Sciences Institute, February 1988.
+
+   [17] Sun Microsystems, "System and Network Administration", March
+        1990.
+
+   [18] Mills, D., "Internet Time Synchronization: The Network Time
+        Protocol", RFC 1305, UDEL, March 1992.
+
+   [19] NetBIOS Working Group, "Protocol Standard for a NetBIOS Service
+        on a TCP/UDP transport: Concepts and Methods", STD 19, RFC 1001,
+        March 1987.
+
+   [20] NetBIOS Working Group, "Protocol Standard for a NetBIOS Service
+        on a TCP/UDP transport: Detailed Specifications", STD 19, RFC
+        1002, March 1987.
+
+   [21] Scheifler, R., "FYI On the X Window System", FYI 6, RFC 1198,
+        MIT Laboratory for Computer Science, January 1991.
+
+   [22] Reynolds, J., and J. Postel, "Assigned Numbers", STD 2, RFC 1700,
+        USC/Information Sciences Institute, July 1992.
+
+13. Security Considerations
+
+   Security issues are not discussed in this memo.
+
+14. Authors' Addresses
+
+   Steve Alexander
+   Lachman Technology, Inc.
+   1901 North Naper Boulevard
+   Naperville, IL 60563-8895
+
+   Phone: (708) 505-9555 x256
+   EMail: stevea@lachman.com
+
+
+   Ralph Droms
+   Computer Science Department
+   323 Dana Engineering
+   Bucknell University
+   Lewisburg, PA 17837
+
+   Phone: (717) 524-1145
+   EMail: droms@bucknell.edu
+
+A. Changes to draft-ietf-dhc-options-1533update-00.txt:
+
+* Section 8.4 - changed to indicate vendor-specific information is
+  interpreted based on vendor class identifier.
+
+* Section 9.13 - changed "Class-identifier" to "Vendor class
+  identifier"
+
+* Added section 9.15 describing "User class identifier"
diff --git a/doc/draft-ietf-dnsind-dynDNS-00.txt b/doc/draft-ietf-dnsind-dynDNS-00.txt
new file mode 100644 (file)
index 0000000..1bbfdad
--- /dev/null
@@ -0,0 +1,1254 @@
+
+
+
+
+
+
+DNSIND Working Group                         Susan Thomson (Bellcore)
+INTERNET-DRAFT                                    Yakov Rekhter (IBM)
+<draft-ietf-dnsind-dynDNS-00.txt>                     Jim Bound (DEC)
+                                                     January 31, 1995
+
+
+   Extending the Domain Name System (DNS) to Perform Dynamic Updates
+
+
+Status of this Memo
+
+   This document is an Internet Draft.  Internet Drafts are working
+   documents of the Internet Engineering Task Force (IETF), its Areas,
+   and its Working Groups. Note that other groups may also distribute
+   working documents as Internet Drafts.
+
+   Internet Drafts are draft documents valid for a maximum of six
+   months. Internet Drafts may be updated, replaced, or obsoleted by
+   other documents at any time.  It is not appropriate to use Internet
+   Drafts as reference material or to cite them other than as a "working
+   draft" or "work in progress."
+
+   To learn the current status of any Internet Draft.  please check the
+   1id-abstracts.txt listing contained in the Internet Drafts Shadow
+   Directories on ds.internic.net, nic.nordu.net, ftp.nisc.sri.com or
+   munnari.oz.au.
+
+
+Abstract
+
+   The Domain Name System currently only supports queries on a
+   statically configured database. This document describes extensions to
+   the Domain Name System to enable name servers to accept requests to
+   update the database dynamically. Extensions include support for
+   adding and deleting a set of names and associated resource records
+   within a zone atomically and the definition of a new resource record
+   that enables update requests  to be serialized.
+
+
+
+
+
+
+
+
+
+
+
+Expires July 31, 1995                                           [Page 1]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+1.  INTRODUCTION
+
+
+   The Domain Name System currently only supports queries on a stati-
+   cally configured database. This document describes extensions to the
+   Domain Name System to enable name servers to accept requests to
+   update the database dynamically.
+
+   Section 2 provides an overview of the update function. Section 3
+   describes the update message format and Sections 4 and 5 describe
+   name server and resolver behavior when processing dynamic updates in
+   more detail. Examples of usage are described in Section 6. A new
+   resource record useful for serializing update requests is defined in
+   Section 7 and security considerations are discussed in Section 8.
+
+
+
+2.  OVERVIEW
+
+   A domain name identifies a node within the domain name space tree
+   structure. Each node has a set of Resource Records (RRs).
+
+   The extensions to the DNS protocol enable name servers to accept
+   requests to update the names space and RRs associated with nodes in
+   the name space dynamically. An update request is an atomic transac-
+   tion consisting of a set of operations on names and RRs in a zone.
+   The operations may be one of four types:
+
+   1.   Add new name and associated with it a set of records to zone
+        (ADDNEW)
+
+        This operation is only successful if the name of the records
+        does not already exist in the zone. The effect of the operation
+        is to create a new node in the name space and add records to
+        this node.
+
+   2.   Add records associated with an existing name to zone (ADDEXIST)
+
+        This operation is only successful if the name the records are
+        associated with exists in the zone. The effect of the operation
+        is to update records that belong to an existing node in the name
+        space.
+
+   3.   Add name and associated with it a set of records to zone,
+        whether name exists or not (ADD)
+
+
+
+Expires July 31, 1995                                           [Page 2]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+        If the name already exists, then the semantics of this operation
+        is the same as ADDEXIST. If the name doesn't exist, then the
+        semantics of this operation is the same as ADDNEW.
+
+   4.   Delete records from zone (DELETE)
+
+        This operation is only successful if the specified records
+        exist. However, it is possible to specify that all resource
+        records associated with a name, class and type must be deleted
+        without explicitly deleting each and every one of them. This is
+        done using a wildcard data field in the resource record.
+
+
+   The update protocol allows several operations to be performed on sets
+   of records with different owner names and record types, provided all
+   names are contained within a single zone.  The effect of an update
+   transaction is to perform all of the operations in the transaction,
+   if all can be performed successfully, or none at all. If the zone
+   serial number in the SOA RR is not explicitly updated in an update
+   request, a side-effect of a successful update transaction may be to
+   update the zone serial number.  A successful update is applied syn-
+   chronously to the database by the primary name server for the zone,
+   and the updates are transferred to secondary name servers asynchro-
+   nously.
+
+   Some of the operations depend on comparing an existing record with a
+   record specified in an update.  Two records are considered to be the
+   same if their name, class, type, data length and value are the same.
+   The time-to-live field is specifically excluded from comparison. The
+   effect of wildcard names and data fields are discussed in Section 3.
+
+   The message format used to implement an atomic transaction has a
+   similar structure to that of a query, but the contents of some of the
+   fields differ. An entity that initiates an update indicates in an
+   update message the update operations to  be performed along with the
+   records to be updated.  A name server responds to an update request
+   by (a) indicating that the update has been successfully applied to
+   the database at the primary name server, (b) indicating that the name
+   server is not authoritative for the records specified, or (c) indi-
+   cating an error.
+
+   An update may be carried in a UDP datagram or a TCP connection.
+
+
+
+
+
+
+Expires July 31, 1995                                           [Page 3]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+3.  UPDATE MESSAGE FORMAT
+
+
+   The message format has the following structure: the message header,
+   which is similar to that of the query, and the message body, which
+   consists of four sections, one per operation type. The four sections
+   are in the order listed: the delete section, the add new record sec-
+   tion, the add existing record section and the plain add secion.  Each
+   section contains the records that need to have the associated opera-
+   tion applied.
+
+
+
+3.1.  Header Section
+
+
+
+
+          0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+       |                      ID                       |
+       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+       |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
+       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+       |                    DELCOUNT                   |
+       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+       |                    ANCOUNT                    |
+       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+       |                    AECOUNT                    |
+       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+       |                    ACOUNT                     |
+       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+
+
+   The differences between the query header and the update header are in
+   the values that certain fields can assume, and in the semantics of
+   certain fields.
+
+   There is a new operation code (value to be defined) to specify an
+   update request in the Opcode field.
+
+
+       UPDATE          TBD
+
+
+
+
+Expires July 31, 1995                                           [Page 4]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+   This Opcode distinguishes the update header from the query header.
+   This document specifies the semantics of the fields in the update
+   header only.
+
+   Besides a new operation code, there are also new return codes.  The
+   four count fields have different semantics: they contain the number
+   of records in the DELETE section, the number of records in the ADDNEW
+   section, the number of records in the ADDEXIST section and the number
+   of records in the ADD section, respectively.
+
+   The other fields remain the same, except that they apply to update
+   requests rather than queries. Note the AA bit is set in a response if
+   and only if a server is authoritative for ALL nodes specified in the
+   request. Also, the TC bit is not applicable to updates.
+
+   The fields are set as follows in update requests and responses:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Expires July 31, 1995                                           [Page 5]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+   ID        A 16 bit identifier assigned by the entity that
+             generates any kind of request.  This identifier is
+             copied in the corresponding reply and can be used by the
+             requestor to match up replies to outstanding requests.
+
+   QR        A one bit field that specifies whether this message is a
+             request (0), or a response (1).
+
+   OPCODE    A four bit field that specifies the kind of request in
+             this message.  This value is set by the originator of a
+             request and copied into the response.  In addition to
+             the values defined in RFC1034, this document defines the
+             following value:
+
+                   TBD             an update request (UPDATE)
+
+
+   AA        Authoritative Answer - this bit is valid in responses,
+             and specifies that the responding name server is an
+             authority for all domain names in the message body.
+
+   TC        Bit is set to zero in an update request and copied into
+             the response. The TC bit is ignored on receipt of a
+             request or response.
+
+
+   RD        Recursion Desired - this bit may be set in a request and
+             is copied into the response.  If RD is set, it directs
+             the name server to pursue the request recursively.
+             Recursive update support is optional.
+
+   RA        Recursion Available - this be is set or cleared in a
+             response, and denotes whether recursive update support is
+             available in the name server.
+
+   Z         Reserved for future use.  Must be zero in all requests
+             and responses.
+
+   RCODE     Response code - this 4 bit field is set as part of
+             responses.  The values and semantics of update responses
+             are as follows:
+
+             0               No error condition
+
+             1               Format error - The name server was
+
+
+
+Expires July 31, 1995                                           [Page 6]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+                             unable to interpret the request.
+
+             2               Server failure - The name server was
+                             unable to process this request due to a
+                             problem with the name server.
+
+             3               Name Error - Meaningful only for
+                             responses from an authoritative name
+                             server, this code signifies that one or
+                             more of the domain names referenced in
+                             the update request does not exist.
+
+             4               Not Implemented - The name server does
+                             not support the specified operation.
+
+             5               Refused - The name server refuses to
+                             perform the specified operation for
+                             policy reasons.
+
+             6               Alias Error - This code indicates that the
+                             domain name specified in an update is an
+                             alias.
+
+             7               Name Exists Error - This code indicates
+                             the name already exists. This return code
+                             is only meaningful from a server
+                             in response to an ADDNEW operation.
+
+             8               Record Not Exist Error - This code
+                             indicates that the resource record does
+                             not exist.
+                             This return code is only meaningful from a
+                             server in response to a DELETE operation.
+
+             9               Too many Zones Error - This code
+                             indicates that the records to be
+                             updated exist in more than one zone.
+
+             10              SERIAL RR Error - This code
+                             indicates that an operation on the
+                             SERIAL record is in error.
+
+             11              Permission Denied - This code indicates
+                             that the client has insufficient authority
+                             to perform the update.
+
+
+
+Expires July 31, 1995                                           [Page 7]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+   DELCOUNT  an unsigned 16 bit integer specifying the number of
+             resource records in the DELETE section. Always zero in a
+             response.
+
+   ANCOUNT   an unsigned 16 bit integer specifying the number of
+             resource records in the ADDNEW section. Always zero
+             in a response.
+
+   AECOUNT   an unsigned 16 bit integer specifying the number of
+             resource records in the ADDEXIST section.
+             Always zero in a response.
+
+   ACOUNT    an unsigned 16 bit integer specifying the number of
+             resource records in the ADD section.
+             Always zero in a response.
+
+
+
+3.2.  Testing for Resource Record Equality
+
+
+   The update operations require that records be compared. In  particu-
+   lar, the DELETE operation requires that the records to be deleted
+   must exist. It has already been stated that records are tested for
+   equality by comparing their name, class, type, data length and data
+   values. The time-to-live value is excluded from the comparison.
+
+   The comparison of character strings in names and in data fields is
+   case-insensitive. For two names to match, they must match label by
+   label. A non-wildcard label never matches the '*' label, i.e. names
+   must exist explicitly in a zone to be matched by a record specified
+   in an update; the use of a wildcard name in a zone does not imply
+   existence for updates.
+
+   In a DELETE operation, it is sometimes convenient to specify that all
+   records associated with a certain name that are of a given class and
+   type be deleted without specifying all existing records explicitly. A
+   record with a data field containing the '*' character and a data
+   length field of one is defined to match data in any other record.
+
+   DISCUSSION: I believe the '*' data value does not match existing
+   legal data values, expect for the NULL record, which is experimental
+   and not supported by BIND.
+
+
+
+
+
+Expires July 31, 1995                                           [Page 8]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+4.  NAME SERVER BEHAVIOR
+
+
+   From a client's perspective, any authoritative server can process an
+   update request. Non-authoritative name servers forward the request to
+   an authoritative name server if recursive service is specified or
+   indicate to the client that the server is not authoritative for the
+   records to be updated.
+
+   From a server's perspective, only the primary authoritative name
+   server actually performs the update request. A secondary name server
+   is responsible for forwarding the request to the primary name server
+   for the zone. As mentioned above, a non-authoritative name server is
+   also responsible for forwarding the update request to the primary, if
+   recursive service is desired by the client and it is available.
+   Unlike a secondary, however, a non-authoritative name server will
+   need to determine the name servers authoritative for the domain names
+   to be updated by asking other names servers for referrals if the
+   information is not cached locally. A secondary name server will have
+   this information preconfigured. Note that the forwarding of an update
+   message is done synchronously on an update request, whether it is
+   performed by a secondary name server or a non-authoritative server
+   that provides recursive service.  That is, a name server will wait
+   for a response to a forwarded update request before returning the
+   response to the client.
+
+
+
+4.1.  Maintaining Internal Consistency
+
+
+   Zone consistency between primary and secondaries is achieved through
+   asynchronous zone transfer. Either full zone transfer as currently
+   defined can be used, or incremental zone transfer when it becomes
+   available[IXFR]. The proposed Notify mechanism[NOTIFY] may also be
+   used to  cause zone transfers to happen earlier than would otherwise
+   be determined by the zone refresh time.
+
+
+
+4.2.  Algorithm
+
+
+   On receiving an update request, the server's behavior will depend on
+   whether recursive service is requested and available. If recursive
+
+
+
+Expires July 31, 1995                                           [Page 9]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+   service is requested and available, the server determines the set of
+   authoritative name servers for the nodes specified in the transac-
+   tion.  The server sends the update to the set of name servers, waits
+   for the response, and returns the response to the resolver.
+
+   If recursive service is not requested or is not available, then the
+   name server checks to see whether the update is in a zone for which
+   it is authoritative. If so, the server attempts to perform the update
+   if the name server is primary for the zone.  If the name server is
+   secondary for the zone, the server forwards the update to  the pri-
+   mary name server, waits for the response and returns the response to
+   the resolver.  Otherwise, if the name server is not authoritative for
+   the zone to be updated, an error is returned.
+
+   The algorithm for name server behavior is explained in more detail
+   below (adapted from [RFC1034]):
+
+   1.   Indicate in the response whether update recursion is available
+        or not. If recursive service is available and requested, then
+        the server uses the local resolver or a copy of its algorithm
+        (Section 4) to perform the update operation. Otherwise, go to
+        step 2.
+
+   2    Determine the names (RRNAMEs) associated with all records to be
+        updated in the transaction.  For each RRNAME, search the avail-
+        able zones for the zone which is the nearest to RRNAME.
+
+        a)   If no zone is found, return a non-authoritative response
+             indicating no error. Exit.
+
+        b)   If more than one zone is found, return a response indicat-
+             ing that the update request is not restricted to a single
+             zone. Exit.
+
+        Otherwise, go to step 3.
+
+   3.   If this is a secondary name server for the zone, forward the
+        request to the primary and wait for the response. Send the
+        response to the resolver.  Exit. (A secondary may do further
+        checking of the update request before sending to the primary for
+        processing, if desired.) Otherwise, go to step 4.
+
+   4.   Start the transaction
+
+   5.   For each RRNAME in the update request, start matching down,
+
+
+
+Expires July 31, 1995                                          [Page 10]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+        label by label, in the zone (found in step 2). For each label,
+        test for the following cases:
+
+        a)   If the whole RRNAME is matched, we have found the node to
+             be updated.
+
+             If the record at the node is a CNAME, and RRTYPE does not
+             match CNAME, abort the transaction and return an authorita-
+             tive response indicating an alias error.
+
+             If the operation is ADDNEW, abort the transaction and
+             return an authoritative response indicating that the name
+             already exists.
+
+             If the operation is ADDEXIST or ADD, check if the specified
+             record already exists. If so, ignore.
+
+             If the operation is DELETE, check if the specified record
+             exists in the zone. If not, abort the transaction and
+             return an authoritative response indicating that the record
+             does not exist.
+
+             Otherwise, perform the update operation tentatively.
+
+        b)   If we have a referral, abort the transaction. Return a
+             non-authoritative response indicating no error. Exit.
+
+        c)   If at some label, a match is impossible (i.e. the label
+             does not exist), and the operation is ADDEXIST or DELETE,
+             abort the transaction and return an authoritative response
+             indicating that the name does not exist.
+
+             Otherwise, perform the update operation tentatively.
+
+   6    Commit the transaction. If the zone serial number has not been
+        explicitly updated as part of  the transaction, the zone serial
+        number may or may not be incremented at this time.  Indicate in
+        the response that the server is authoritative and return a suc-
+        cessful response. Exit.
+
+   At the start of a transaction, the zone must be locked to prevent
+   concurrent interleaving of concurrent update requests. The zone is
+   unlocked at the end of a (successful or unsuccessful) transaction.
+   Aborting a transaction requires that any changes made so far must be
+   rolled back.  Committing a transaction means that the changes are
+
+
+
+Expires July 31, 1995                                          [Page 11]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+   applied to the zone and are visible to subsequent queries to the pri-
+   mary. (It is an implementation matter whether the master file is
+   updated at this time or later. The point is that the changes are made
+   persistent, e.g. in a log on stable storage, and are added to the
+   cached copy of the zone.) If the zone serial number is not explicitly
+   updated in a request, a primary name server may update the zone
+   serial number when committing each transaction, or periodically,
+   after some number of transactions or time has passed, depending on
+   policy. The effect of incrementing the serial number periodically
+   rather than on each transaction means that a secondary may not detect
+   that a zone has been updated as quickly as it otherwise would do. On
+   the other hand, updating the serial number periodically makes it pos-
+   sible to slow incrementing of the serial number in situations where
+   many updates occur close together in time.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Expires July 31, 1995                                          [Page 12]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+5.  RESOLVER BEHAVIOR
+
+
+   A resolver provides the application interface to name servers. A
+   resolver must enable applications to perform both standard queries
+   and updates.
+
+   A stub resolver performs no resolution function itself, but must
+   either be configured with a list of name servers that provide recur-
+   sive service, i.e. name servers that can perform requests on the
+   resolver's behalf, or be configured with the names of authoritative
+   servers of zones that this resolver is known to be responsible for
+   updating.
+
+   A full-service resolver traverses the domain name space itself, pos-
+   sibly querying several name servers to find the name servers authori-
+   tative for the zone to be updated.  A full-service resolver performs
+   an update operation as follows (adapted from [RFC1034]):
+
+   1.   If a resolver has direct access to a name server's authoritative
+        data, determine the names (RRNAMEs) associated with all records
+        to be updated in the transaction.  For each RRNAME, search the
+        available zones for the zone which is authoritative for RRNAME.
+
+        a)   If more than one zone is found, return a response indicat-
+             ing that the update request is not restricted to a single
+             zone. Exit.
+
+        b)   If a single authoritative zone is found, perform the update
+             transaction in the relevant zone as outlined in Section
+             4.2. Exit.
+
+   2.   If the zone is non-local, find the best servers to ask for any
+        or all RRNAMEs. If the resolver finds that the RRNAMEs cannot be
+        in the same zone, it returns a response indicating that the
+        update is not constrained to a single zone and exits.
+
+   3.   Send a query to one of the servers for any RRNAME, RRCLASS and
+        RRTYPE to be updated in the zone.
+
+   4.   Analyze the response:
+
+        a)   If the response is authoritative, go to step 5
+
+        b)   If the response contains better delegation information,
+
+
+
+Expires July 31, 1995                                          [Page 13]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+             cache the delegation information and go to step 2.
+
+        c)   If the response shows a server failure or other bizarre
+             contents, delete the server from the list of servers and go
+             back to step 3.
+
+   5.   Send an update to an authoritative name server.
+
+   6.   Analyze the response:
+
+        a)   If the response shows a server failure or other bizarre
+             contents, delete the server from the list of servers and go
+             back to step 5.
+
+        b)   Otherwise, return the response to the client.
+
+   The data structures used to represent the state of a query in pro-
+   gress in the resolver are the same as that specified in RFC1034,
+   except that the list that represents the resolver's best guess about
+   which name servers to ask may include additional information per-
+   tinent to updates, e.g.  which in a set of authoritative name servers
+   accept update requests for a given zone (some name servers may refuse
+   to accept update requests) and the relative performance of the name
+   servers (primary may provide better performance than secondaries).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Expires July 31, 1995                                          [Page 14]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+6.  EXAMPLES
+
+   A wide range of update functions can be achieved using a combination
+   of the four update operations. To illustrate this, we use a simple
+   zone consisting of the following records:
+
+
+             xyz.com.          SOA     ns.xyz.com sysadm.xyz.com
+                                      ( ... )
+                               NS      ns.xyz.com.
+
+             ns.xyz.com.       A       128.96.33.22
+
+             foo.xyz.com.      A       128.96.33.33
+                               A       128.96.34.34
+
+
+   For example, one of the A records belonging to foo.xyz.com can be
+   modified by first deleting it and adding the new.
+
+
+   DELETE    foo.xyz.com      A       128.96.33.33
+
+   ADD       foo.xyz.com      A       128.96.44.44
+
+
+   Both ADD or ADDEXIST would work in the above example to add the
+   replacement record.
+
+   The canonical name of a host can be changed from "foo" to "bar" and
+   the old name "foo" made an alias, by sending an update  transaction
+   consisting of the following three operations:
+
+
+   DELETE    foo.xyz.com      A       128.96.33.33
+             foo.xyz.com      A       128.96.34.34
+
+   ADDEXIST  foo.xyz.com      CNAME   bar.xyz.com
+
+   ADDNEW    bar.xyz.com      A       128.61.44.33
+
+
+
+   Alternatively, the A records belonging to "foo" need not be individu-
+   ally deleted. The wildcard data field can be used to delete all
+
+
+
+Expires July 31, 1995                                          [Page 15]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+   records associated with "foo" as follows:
+
+
+   DELETE    foo.xyz.com      A       *
+
+
+   Also, both of the above add operations could be replaced by ADD.
+   However, the existence checks would not then be applied.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Expires July 31, 1995                                          [Page 16]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+7.  SERIAL RESOURCE RECORD
+
+
+   A new resource record is defined that can be used to serialize update
+   requests. Serialization is needed if updates can be concurrent or the
+   update is dependent on the database being in a certain state.  In
+   particular, serialisation may be necessary to protect against dupli-
+   cate messages. Duplicate messages arise when the transport protocol
+   used does not guarantee otherwise, or when resolvers retransmit mes-
+   sages because the transport protocol is unreliable. Also, malicious
+   clients may deliberately replay old update requests.
+
+   In general, to serialize requests, a token needs to be associated
+   with the set of records to be updated. This token must be set to a
+   different value on each update. The SERIAL resource record is defined
+   to hold this token and to indicate the set of records associated with
+   the token.  The SERIAL record has the same name, class, and TTL
+   values as the records to be protected. The name may contain the wild-
+   card label in which case the SERIAL record covers all records in the
+   zone (of the type specified in the data field), and can be used to
+   serialize updates at the granularity of a zone.  The data field of
+   the record contains the type of the records protected and the token
+   itself. The type may be any valid record type, or it may contain type
+   ANY which means that the token covers all records associated with the
+   name specified. The token is a 64-bit number (the exact definition of
+   which is to be discussed below).
+
+   The data field of the record is as follows:
+
+
+
+             0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+          |                RR type covered                |
+          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+          |                                               |
+          |                   token                       |
+          |                                               |
+          |                                               |
+          +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+
+
+   To update the SERIAL record, a client MUST delete the current record
+   explicitly and then add the new record with the new token value. The
+
+
+
+Expires July 31, 1995                                          [Page 17]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+   SERIAL record is the only record where the use of the wildcard data
+   field when deleting records is invalid. This restriction  ensures
+   that the update of the token is itself serialized, by making sure
+   that the change from the current token value to the new token value
+   is done in a mutually exclusive manner.
+
+   For example, given a zone containing a SERIAL RR as follows:
+
+
+             xyz.com.          SOA     ns.xyz.com sysadm.xyz.com
+                                      ( ... )
+                               NS      ns.xyz.com.
+
+             ns.xyz.com.       A       128.96.33.22
+
+             foo.xyz.com.      SERIAL  A  2157449756503
+                               A       128.96.33.33
+                               A       128.96.34.34
+
+
+   Updates to the A records would be serialized by using the following
+   operations:
+
+
+   DELETE    foo.xyz.com      SERIAL   A  2157449756503
+             foo.xyz.com      A        *
+
+   ADD       foo.xyz.com      SERIAL   A  7575470909833451
+             foo.xyz.com      A        128.96.44.44
+             foo.xyz.com      A        128.96.55.55
+
+
+   FOR DISCUSSION: One approach would be to define the token as a random
+   number.  However, update serialization is only as good as the random
+   numbers generated.  If clients cannot be trusted to generate unique
+   random numbers or it is too expensive to do so, an alternative
+   approach is to define the token as a sequence number. This approach
+   is cheap to implement, but does require that the name server inter-
+   pret the value of the data field of the SERIAL RR added to determine
+   that it is appropriately set.  Another approach is to have the server
+   responsible for generating the next token (in any way it liked). This
+   also requires the server to interpret the data field of the SERIAL
+   RR.
+
+
+
+
+
+Expires July 31, 1995                                          [Page 18]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+8.  SECURITY CONSIDERATIONS
+
+
+   DNS updates must be able to be made secure. The security mechanism
+   must provide data origin authentication, data integrity and protec-
+   tion against replay. Data confidentiality is not required.
+
+   The signature records defined in [DNSSEC] can be used to ensure that
+   each set of records of a particular name, type and class are updated
+   by an entity that has the appropriate authority.  The signature
+   record is updated along with the associated records in an update
+   transaction. The SIG RR must sign all records associated with a name,
+   class and type, not only those updated in the request.  The "time
+   signed" timestamp in the SIG record may be used to protect against
+   replay if it is defined that, when updated, it must have a value
+   greater than the current value and be set to a time not too far in
+   the future.
+
+   Note that a signature record only covers records of a particular
+   name, class and type. Thus, while the integrity of each set of
+   records of the same name, class and type updated in a transaction can
+   be assured, the integrity of a set of updates records with different
+   names or types is not.  To ensure integrity of the entire message, a
+   network layer security protocol should be used if available. Alterna-
+   tively, a SIG RR signing the entire message can be placed at the end
+   of the last section of a message as explained in [DNSSEC]. If SIG
+   records are not used to authenticate individual updates, the SERIAL
+   record will need to be used to ensure against replay.
+
+   Note that a SIG RR is not only used to authenticate an update
+   request, but is stored along with the authenticated data in DNS to
+   authenticate subsequent queries for the data.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Expires July 31, 1995                                          [Page 19]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+9.  OPEN ISSUES
+
+
+
+   1.   Should non-recursive updates perform referrals when an update is
+        sent to a non-authoritative server?
+
+
+        This is a bit less clean for updates than for queries, since
+        multiple nodes can be specified in an atomic transaction. (A
+        referral need only be to one of the nodes specified - any one
+        will do.
+
+        On the other hand, using queries to locate authoritative servers
+        before sending an update is likely to be less efficient than
+        using updates only. However, caching of queries should alleviate
+        this.
+
+        The usefulness of having updates perform referrals is not clear:
+
+        a)   While updates need to be reliable and hence might be car-
+             ried using TCP, the recommended approach to get referrals
+             is UDP.
+
+        b)   As a practical matter, it cannot be required that all name
+             servers in DNS support dynamic updates.  Thus, queries will
+             always have to be used as the fallback mechanism for locat-
+             ing the authoritative name servers for a dynamic zone.
+
+        This document as it stands does not specify referrals.
+
+
+
+10.  ACKNOWLEDGEMENTS
+
+
+   We would like to thank the DNSIND working group for their valuable
+   input, in particular, Donald Eastlake.
+
+
+
+11.  REFERENCES
+
+
+
+
+
+
+Expires July 31, 1995                                          [Page 20]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+   [RFC1034]
+        P. Mockapetris, "Domain Names - Concepts and Facilities", RFC
+        1034, USC/Information Sciences Institute, November 1987.
+
+   [RFC1035]
+        P. Mockapetris, "Domain Names - Implementation and Specifica-
+        tion", RFC 1035, USC/Information Sciences Institute, November
+        1987.
+
+   [DNSSEC]
+        Donald E. Eastlake and Charles W. Kaufman, "Domain Name System
+        Protocol Security Extensions", Internet Draft, March 1994,
+        <draft-ietf-dnssec-secext-03.txt>.
+
+   [IXFR]M. Ohta, "Incremental Zone Transfer", Internet Draft, November
+        1994.
+
+   [NOTIFY]
+        P. Vixie, "Notify: a mechanism for prompt notification of
+        authority zone changes", Internet Draft, November 1994, <draft-
+        ietf-dnsind-notify-00.txt>.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Expires July 31, 1995                                          [Page 21]
+
+
+
+
+
+\fINTERNET-DRAFT           Dynamic DNS Updates               January 1995
+
+
+Authors' Addresses
+
+
+   Susan Thomson
+   Bellcore
+   445 South Street
+   Morristown, NJ 07960
+   Phone: (201) 829-4514
+   email: set@thumper.bellcore.com
+
+   Yakov Rekhter
+   T.J. Watson Research Center IBM Corporation
+   P.O. Box 740, H3-D40,
+   Yorktown Heights, NY 10598
+   Phone:  (914) 784-7361
+   email:  yakov@watson.ibm.com
+
+   Jim Bound
+   Digital Equipment Corporation
+   110 Spitbrook Road ZK3-3/U14
+   Nashua, NH 03062-2698
+   Phone: (603) 881-0400
+   email: bound@zk3.dec.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Expires July 31, 1995                                          [Page 22]
+
+
diff --git a/doc/draft-ohta-dynamic-dns-00.txt b/doc/draft-ohta-dynamic-dns-00.txt
new file mode 100644 (file)
index 0000000..f361d77
--- /dev/null
@@ -0,0 +1,5 @@
+
+This Internet-Draft was deleted.  For more information, send a message to
+
+       Internet-Drafts@cnri.reston.va.us
+
diff --git a/doc/rfc1533.txt b/doc/rfc1533.txt
new file mode 100644 (file)
index 0000000..3967778
--- /dev/null
@@ -0,0 +1,1683 @@
+
+
+
+
+
+
+Network Working Group                                       S. Alexander
+Request for Comments: 1533                      Lachman Technology, Inc.
+Obsoletes: 1497, 1395, 1084, 1048                               R. Droms
+Category: Standards Track                            Bucknell University
+                                                            October 1993
+
+
+               DHCP Options and BOOTP Vendor Extensions
+
+Status of this Memo
+
+   This RFC specifies an Internet standards track protocol for the
+   Internet community, and requests discussion and suggestions for
+   improvements.  Please refer to the current edition of the "Internet
+   Official Protocol Standards" for the standardization state and status
+   of this protocol.  Distribution of this memo is unlimited.
+
+Abstract
+
+   The Dynamic Host Configuration Protocol (DHCP) [1] provides a
+   framework for passing configuration information to hosts on a TCP/IP
+   network.  Configuration parameters and other control information are
+   carried in tagged data items that are stored in the "options" field
+   of the DHCP message.  The data items themselves are also called
+   "options."
+
+   This document specifies the current set of DHCP options.  This
+   document will be periodically updated as new options are defined.
+    Each superseding document will include the entire current list of
+   valid options.
+
+   All of the vendor information extensions defined in RFC 1497 [2] may
+   be used as DHCP options.  The definitions given in RFC 1497 are
+   included in this document, which supersedes RFC 1497.  All of the
+   DHCP options defined in this document, except for those specific to
+   DHCP as defined in section 9, may be used as BOOTP vendor information
+   extensions.
+
+Table of Contents
+
+    1.  Introduction ..............................................  2
+    2.  BOOTP Extension/DHCP Option Field Format ..................  2
+    3.  RFC 1497 Vendor Extensions ................................  3
+    4.  IP Layer Parameters per Host .............................. 10
+    5.  IP Layer Parameters per Interface ........................  13
+    6.  Link Layer Parameters per Interface ....................... 16
+    7.  TCP Parameters ............................................ 17
+    8.  Application and Service Parameters ........................ 18
+
+
+
+Alexander & Droms                                               [Page 1]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+    9.  DHCP Extensions ........................................... 23
+   10.  Extensions ................................................ 27
+   11.  Acknowledgements .......................................... 28
+   12.  References ................................................ 28
+   13.  Security Considerations ................................... 19
+   14.  Authors' Addresses ........................................ 30
+
+1. Introduction
+
+   This document specifies options for use with both the Dynamic Host
+   Configuration Protocol and the Bootstrap Protocol.
+
+   The full description of DHCP packet formats may be found in the DHCP
+   specification document [1], and the full description of BOOTP packet
+   formats may be found in the BOOTP specification document [3].  This
+   document defines the format of information in the last field of DHCP
+   packets ('options') and of BOOTP packets ('vend').  The remainder of
+   this section defines a generalized use of this area for giving
+   information useful to a wide class of machines, operating systems and
+   configurations. Sites with a single DHCP or BOOTP server that is
+   shared among heterogeneous clients may choose to define other, site-
+   specific formats for the use of the 'options' field.
+
+   Section 2 of this memo describes the formats of DHCP options and
+   BOOTP vendor extensions.  Section 3 describes options defined in
+   previous documents for use with BOOTP (all may also be used with
+   DHCP).  Sections 4-8 define new options intended for use with both
+   DHCP and BOOTP. Section 9 defines options used only in DHCP.
+
+   References further describing most of the options defined in sections
+   2-6 can be found in section 12.  The use of the options defined in
+   section 9 is described in the DHCP specification [1].
+
+   Information on registering new options is contained in section 10.
+
+2. BOOTP Extension/DHCP Option Field Format
+
+   DHCP options have the same format as the BOOTP "vendor extensions"
+   defined in RFC 1497 [2].  Options may be fixed length or variable
+   length.  All options begin with a tag octet, which uniquely
+   identifies the option.  Fixed-length options without data consist of
+   only a tag octet.  Only options 0 and 255 are fixed length.  All
+   other options are variable-length with a length octet following the
+   tag octet.  The value of the length octet does not include the two
+   octets specifying the tag and length.  The length octet is followed
+   by "length" octets of data.  In the case of some variable-length
+   options the length field is a constant but must still be specified.
+
+
+
+
+Alexander & Droms                                               [Page 2]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+   Any options defined subsequent to this document should contain a
+   length octet even if the length is fixed or zero.
+
+   All multi-octet quantities are in network byte-order.
+
+   When used with BOOTP, the first four octets of the vendor information
+   field have been assigned to the "magic cookie" (as suggested in RFC
+   951).  This field identifies the mode in which the succeeding data is
+   to be interpreted.  The value of the magic cookie is the 4 octet
+   dotted decimal 99.130.83.99 (or hexadecimal number 63.82.53.63) in
+   network byte order.
+
+   All of the "vendor extensions" defined in RFC 1497 are also DHCP
+   options.
+
+   Option codes 128 to 254 (decimal) are reserved for site-specific
+   options.
+
+   Except for the options in section 9, all options may be used with
+   either DHCP or BOOTP.
+
+   Many of these options have their default values specified in other
+   documents.  In particular, RFC 1122 [4] specifies default values for
+   most IP and TCP configuration parameters.
+
+3. RFC 1497 Vendor Extensions
+
+   This section lists the vendor extensions as defined in RFC 1497.
+   They are defined here for completeness.
+
+3.1. Pad Option
+
+   The pad option can be used to cause subsequent fields to align on
+   word boundaries.
+
+   The code for the pad option is 0, and its length is 1 octet.
+
+    Code
+   +-----+
+   |  0  |
+   +-----+
+
+
+
+
+
+
+
+
+
+
+Alexander & Droms                                               [Page 3]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+3.2. End Option
+
+   The end option marks the end of valid information in the vendor
+   field.  Subsequent octets should be filled with pad options.
+
+   The code for the end option is 255, and its length is 1 octet.
+
+    Code
+   +-----+
+   | 255 |
+   +-----+
+
+3.3. Subnet Mask
+
+   The subnet mask option specifies the client's subnet mask as per RFC
+   950 [5].
+
+   If both the subnet mask and the router option are specified in a DHCP
+   reply, the subnet mask option MUST be first.
+
+   The code for the subnet mask option is 1, and its length is 4 octets.
+
+    Code   Len        Subnet Mask
+   +-----+-----+-----+-----+-----+-----+
+   |  1  |  4  |  m1 |  m2 |  m3 |  m4 |
+   +-----+-----+-----+-----+-----+-----+
+
+3.4. Time Offset
+
+   The time offset field specifies the offset of the client's subnet in
+   seconds from Coordinated Universal Time (UTC).  The offset is
+   expressed as a signed 32-bit integer.
+
+   The code for the time offset option is 2, and its length is 4 octets.
+
+    Code   Len        Time Offset
+   +-----+-----+-----+-----+-----+-----+
+   |  2  |  4  |  n1 |  n2 |  n3 |  n4 |
+   +-----+-----+-----+-----+-----+-----+
+
+
+
+
+
+
+
+
+
+
+
+
+Alexander & Droms                                               [Page 4]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+3.5. Router Option
+
+   The router option specifies a list of IP addresses for routers on the
+   client's subnet.  Routers SHOULD be listed in order of preference.
+
+   The code for the router option is 3.  The minimum length for the
+   router option is 4 octets, and the length MUST always be a multiple
+   of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  3  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+3.6. Time Server Option
+
+   The time server option specifies a list of RFC 868 [6] time servers
+   available to the client.  Servers SHOULD be listed in order of
+   preference.
+
+   The code for the time server option is 4.  The minimum length for
+   this option is 4 octets, and the length MUST always be a multiple of
+   4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  4  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+3.7. Name Server Option
+
+   The name server option specifies a list of IEN 116 [7] name servers
+   available to the client.  Servers SHOULD be listed in order of
+   preference.
+
+   The code for the name server option is 5.  The minimum length for
+   this option is 4 octets, and the length MUST always be a multiple of
+   4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  5  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+
+
+
+
+
+
+
+Alexander & Droms                                               [Page 5]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+3.8. Domain Name Server Option
+
+   The domain name server option specifies a list of Domain Name System
+   (STD 13, RFC 1035 [8]) name servers available to the client.  Servers
+   SHOULD be listed in order of preference.
+
+   The code for the domain name server option is 6.  The minimum length
+   for this option is 4 octets, and the length MUST always be a multiple
+   of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  6  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+3.9. Log Server Option
+
+   The log server option specifies a list of MIT-LCS UDP log servers
+   available to the client.  Servers SHOULD be listed in order of
+   preference.
+
+   The code for the log server option is 7.  The minimum length for this
+   option is 4 octets, and the length MUST always be a multiple of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  7  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+3.10. Cookie Server Option
+
+   The cookie server option specifies a list of RFC 865 [9] cookie
+   servers available to the client.  Servers SHOULD be listed in order
+   of preference.
+
+   The code for the log server option is 8.  The minimum length for this
+   option is 4 octets, and the length MUST always be a multiple of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  8  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+
+
+
+
+
+
+
+
+Alexander & Droms                                               [Page 6]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+3.11. LPR Server Option
+
+   The LPR server option specifies a list of RFC 1179 [10] line printer
+   servers available to the client.  Servers SHOULD be listed in order
+   of preference.
+
+   The code for the LPR server option is 9.  The minimum length for this
+   option is 4 octets, and the length MUST always be a multiple of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  9  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+3.12. Impress Server Option
+
+   The Impress server option specifies a list of Imagen Impress servers
+   available to the client.  Servers SHOULD be listed in order of
+   preference.
+
+   The code for the Impress server option is 10.  The minimum length for
+   this option is 4 octets, and the length MUST always be a multiple of
+   4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  10 |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+3.13. Resource Location Server Option
+
+   This option specifies a list of RFC 887 [11] Resource Location
+   servers available to the client.  Servers SHOULD be listed in order
+   of preference.
+
+   The code for this option is 11.  The minimum length for this option
+   is 4 octets, and the length MUST always be a multiple of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  11 |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+
+
+
+
+
+
+
+
+Alexander & Droms                                               [Page 7]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+3.14. Host Name Option
+
+   This option specifies the name of the client.  The name may or may
+   not be qualified with the local domain name (see section 3.17 for the
+   preferred way to retrieve the domain name).  See RFC 1035 for
+   character set restrictions.
+
+   The code for this option is 12, and its minimum length is 1.
+
+    Code   Len                 Host Name
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  12 |  n  |  h1 |  h2 |  h3 |  h4 |  h5 |  h6 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+3.15. Boot File Size Option
+
+   This option specifies the length in 512-octet blocks of the default
+   boot image for the client.  The file length is specified as an
+   unsigned 16-bit integer.
+
+   The code for this option is 13, and its length is 2.
+
+    Code   Len   File Size
+   +-----+-----+-----+-----+
+   |  13 |  2  |  l1 |  l2 |
+   +-----+-----+-----+-----+
+
+3.16. Merit Dump File
+
+   This option specifies the path-name of a file to which the client's
+   core image should be dumped in the event the client crashes.  The
+   path is formatted as a character string consisting of characters from
+   the NVT ASCII character set.
+
+   The code for this option is 14.  Its minimum length is 1.
+
+    Code   Len      Dump File Pathname
+   +-----+-----+-----+-----+-----+-----+---
+   |  14 |  n  |  n1 |  n2 |  n3 |  n4 | ...
+   +-----+-----+-----+-----+-----+-----+---
+
+
+
+
+
+
+
+
+
+
+
+Alexander & Droms                                               [Page 8]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+3.17. Domain Name
+
+   This option specifies the domain name that client should use when
+   resolving hostnames via the Domain Name System.
+
+   The code for this option is 15.  Its minimum length is 1.
+
+    Code   Len        Domain Name
+   +-----+-----+-----+-----+-----+-----+--
+   |  15 |  n  |  d1 |  d2 |  d3 |  d4 |  ...
+   +-----+-----+-----+-----+-----+-----+--
+
+3.18. Swap Server
+
+   This specifies the IP address of the client's swap server.
+
+   The code for this option is 16 and its length is 4.
+
+    Code   Len    Swap Server Address
+   +-----+-----+-----+-----+-----+-----+
+   |  16 |  n  |  a1 |  a2 |  a3 |  a4 |
+   +-----+-----+-----+-----+-----+-----+
+
+3.19. Root Path
+
+   This option specifies the path-name that contains the client's root
+   disk.  The path is formatted as a character string consisting of
+   characters from the NVT ASCII character set.
+
+   The code for this option is 17.  Its minimum length is 1.
+
+    Code   Len      Root Disk Pathname
+   +-----+-----+-----+-----+-----+-----+---
+   |  17 |  n  |  n1 |  n2 |  n3 |  n4 | ...
+   +-----+-----+-----+-----+-----+-----+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Alexander & Droms                                               [Page 9]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+3.20. Extensions Path
+
+   A string to specify a file, retrievable via TFTP, which contains
+   information which can be interpreted in the same way as the 64-octet
+   vendor-extension field within the BOOTP response, with the following
+   exceptions:
+
+          - the length of the file is unconstrained;
+          - all references to Tag 18 (i.e., instances of the
+            BOOTP Extensions Path field) within the file are
+            ignored.
+
+   The code for this option is 18.  Its minimum length is 1.
+
+    Code   Len      Extensions Pathname
+   +-----+-----+-----+-----+-----+-----+---
+   |  18 |  n  |  n1 |  n2 |  n3 |  n4 | ...
+   +-----+-----+-----+-----+-----+-----+---
+
+4. IP Layer Parameters per Host
+
+   This section details the options that affect the operation of the IP
+   layer on a per-host basis.
+
+4.1. IP Forwarding Enable/Disable Option
+
+   This option specifies whether the client should configure its IP
+   layer for packet forwarding.  A value of 0 means disable IP
+   forwarding, and a value of 1 means enable IP forwarding.
+
+   The code for this option is 19, and its length is 1.
+
+    Code   Len  Value
+   +-----+-----+-----+
+   |  19 |  1  | 0/1 |
+   +-----+-----+-----+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Alexander & Droms                                              [Page 10]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+4.2. Non-Local Source Routing Enable/Disable Option
+
+   This option specifies whether the client should configure its IP
+   layer to allow forwarding of datagrams with non-local source routes
+   (see Section 3.3.5 of [4] for a discussion of this topic).  A value
+   of 0 means disallow forwarding of such datagrams, and a value of 1
+   means allow forwarding.
+
+   The code for this option is 20, and its length is 1.
+
+    Code   Len  Value
+   +-----+-----+-----+
+   |  20 |  1  | 0/1 |
+   +-----+-----+-----+
+
+4.3. Policy Filter Option
+
+   This option specifies policy filters for non-local source routing.
+   The filters consist of a list of IP addresses and masks which specify
+   destination/mask pairs with which to filter incoming source routes.
+
+   Any source routed datagram whose next-hop address does not match one
+   of the filters should be discarded by the client.
+
+   See [4] for further information.
+
+   The code for this option is 21.  The minimum length of this option is
+   8, and the length MUST be a multiple of 8.
+
+    Code   Len         Address 1                  Mask 1
+   +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+   |  21 |  n  |  a1 |  a2 |  a3 |  a4 |  m1 |  m2 |  m3 |  m4 |
+   +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+           Address 2                  Mask 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+---
+   |  a1 |  a2 |  a3 |  a4 |  m1 |  m2 |  m3 |  m4 | ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Alexander & Droms                                              [Page 11]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+4.4. Maximum Datagram Reassembly Size
+
+   This option specifies the maximum size datagram that the client
+   should be prepared to reassemble.  The size is specified as a 16-bit
+   unsigned integer.  The minimum value legal value is 576.
+
+   The code for this option is 22, and its length is 2.
+
+    Code   Len      Size
+   +-----+-----+-----+-----+
+   |  22 |  2  |  s1 |  s2 |
+   +-----+-----+-----+-----+
+
+4.5. Default IP Time-to-live
+
+   This option specifies the default time-to-live that the client should
+   use on outgoing datagrams.  The TTL is specified as an octet with a
+   value between 1 and 255.
+
+   The code for this option is 23, and its length is 1.
+
+    Code   Len   TTL
+   +-----+-----+-----+
+   |  23 |  1  | ttl |
+   +-----+-----+-----+
+
+4.6. Path MTU Aging Timeout Option
+
+   This option specifies the timeout (in seconds) to use when aging Path
+   MTU values discovered by the mechanism defined in RFC 1191 [12].  The
+   timeout is specified as a 32-bit unsigned integer.
+
+   The code for this option is 24, and its length is 4.
+
+    Code   Len           Timeout
+   +-----+-----+-----+-----+-----+-----+
+   |  24 |  4  |  t1 |  t2 |  t3 |  t4 |
+   +-----+-----+-----+-----+-----+-----+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Alexander & Droms                                              [Page 12]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+4.7. Path MTU Plateau Table Option
+
+   This option specifies a table of MTU sizes to use when performing
+   Path MTU Discovery as defined in RFC 1191.  The table is formatted as
+   a list of 16-bit unsigned integers, ordered from smallest to largest.
+   The minimum MTU value cannot be smaller than 68.
+
+   The code for this option is 25.  Its minimum length is 2, and the
+   length MUST be a multiple of 2.
+
+    Code   Len     Size 1      Size 2
+   +-----+-----+-----+-----+-----+-----+---
+   |  25 |  n  |  s1 |  s2 |  s1 |  s2 | ...
+   +-----+-----+-----+-----+-----+-----+---
+
+5. IP Layer Parameters per Interface
+
+   This section details the options that affect the operation of the IP
+   layer on a per-interface basis.  It is expected that a client can
+   issue multiple requests, one per interface, in order to configure
+   interfaces with their specific parameters.
+
+5.1. Interface MTU Option
+
+   This option specifies the MTU to use on this interface.  The MTU is
+   specified as a 16-bit unsigned integer.  The minimum legal value for
+   the MTU is 68.
+
+   The code for this option is 26, and its length is 2.
+
+    Code   Len      MTU
+   +-----+-----+-----+-----+
+   |  26 |  2  |  m1 |  m2 |
+   +-----+-----+-----+-----+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Alexander & Droms                                              [Page 13]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+5.2. All Subnets are Local Option
+
+   This option specifies whether or not the client may assume that all
+   subnets of the IP network to which the client is connected use the
+   same MTU as the subnet of that network to which the client is
+   directly connected.  A value of 1 indicates that all subnets share
+   the same MTU.  A value of 0 means that the client should assume that
+   some subnets of the directly connected network may have smaller MTUs.
+
+   The code for this option is 27, and its length is 1.
+
+    Code   Len  Value
+   +-----+-----+-----+
+   |  27 |  1  | 0/1 |
+   +-----+-----+-----+
+
+5.3. Broadcast Address Option
+
+   This option specifies the broadcast address in use on the client's
+   subnet.  Legal values for broadcast addresses are specified in
+   section 3.2.1.3 of [4].
+
+   The code for this option is 28, and its length is 4.
+
+    Code   Len     Broadcast Address
+   +-----+-----+-----+-----+-----+-----+
+   |  28 |  4  |  b1 |  b2 |  b3 |  b4 |
+   +-----+-----+-----+-----+-----+-----+
+
+5.4. Perform Mask Discovery Option
+
+   This option specifies whether or not the client should perform subnet
+   mask discovery using ICMP.  A value of 0 indicates that the client
+   should not perform mask discovery.  A value of 1 means that the
+   client should perform mask discovery.
+
+   The code for this option is 29, and its length is 1.
+
+    Code   Len  Value
+   +-----+-----+-----+
+   |  29 |  1  | 0/1 |
+   +-----+-----+-----+
+
+
+
+
+
+
+
+
+
+Alexander & Droms                                              [Page 14]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+5.5. Mask Supplier Option
+
+   This option specifies whether or not the client should respond to
+   subnet mask requests using ICMP.  A value of 0 indicates that the
+   client should not respond.  A value of 1 means that the client should
+   respond.
+
+   The code for this option is 30, and its length is 1.
+
+    Code   Len  Value
+   +-----+-----+-----+
+   |  30 |  1  | 0/1 |
+   +-----+-----+-----+
+
+5.6. Perform Router Discovery Option
+
+   This option specifies whether or not the client should solicit
+   routers using the Router Discovery mechanism defined in RFC 1256
+   [13].  A value of 0 indicates that the client should not perform
+   router discovery.  A value of 1 means that the client should perform
+   router discovery.
+
+   The code for this option is 31, and its length is 1.
+
+    Code   Len  Value
+   +-----+-----+-----+
+   |  31 |  1  | 0/1 |
+   +-----+-----+-----+
+
+5.7. Router Solicitation Address Option
+
+   This option specifies the address to which the client should transmit
+   router solicitation requests.
+
+   The code for this option is 32, and its length is 4.
+
+    Code   Len            Address
+   +-----+-----+-----+-----+-----+-----+
+   |  32 |  4  |  a1 |  a2 |  a3 |  a4 |
+   +-----+-----+-----+-----+-----+-----+
+
+
+
+
+
+
+
+
+
+
+
+Alexander & Droms                                              [Page 15]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+5.8. Static Route Option
+
+   This option specifies a list of static routes that the client should
+   install in its routing cache.  If multiple routes to the same
+   destination are specified, they are listed in descending order of
+   priority.
+
+   The routes consist of a list of IP address pairs.  The first address
+   is the destination address, and the second address is the router for
+   the destination.
+
+   The default route (0.0.0.0) is an illegal destination for a static
+   route.  See section 3.5 for information about the router option.
+
+   The code for this option is 33.  The minimum length of this option is
+   8, and the length MUST be a multiple of 8.
+
+    Code   Len         Destination 1           Router 1
+   +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+   |  33 |  n  |  d1 |  d2 |  d3 |  d4 |  r1 |  r2 |  r3 |  r4 |
+   +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+           Destination 2           Router 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+---
+   |  d1 |  d2 |  d3 |  d4 |  r1 |  r2 |  r3 |  r4 | ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+---
+
+6. Link Layer Parameters per Interface
+
+   This section lists the options that affect the operation of the data
+   link layer on a per-interface basis.
+
+6.1. Trailer Encapsulation Option
+
+   This option specifies whether or not the client should negotiate the
+   use of trailers (RFC 893 [14]) when using the ARP protocol.  A value
+   of 0 indicates that the client should not attempt to use trailers.  A
+   value of 1 means that the client should attempt to use trailers.
+
+   The code for this option is 34, and its length is 1.
+
+    Code   Len  Value
+   +-----+-----+-----+
+   |  34 |  1  | 0/1 |
+   +-----+-----+-----+
+
+
+
+
+
+
+
+Alexander & Droms                                              [Page 16]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+6.2. ARP Cache Timeout Option
+
+   This option specifies the timeout in seconds for ARP cache entries.
+   The time is specified as a 32-bit unsigned integer.
+
+   The code for this option is 35, and its length is 4.
+
+    Code   Len           Time
+   +-----+-----+-----+-----+-----+-----+
+   |  35 |  4  |  t1 |  t2 |  t3 |  t4 |
+   +-----+-----+-----+-----+-----+-----+
+
+6.3. Ethernet Encapsulation Option
+
+   This option specifies whether or not the client should use Ethernet
+   Version 2 (RFC 894 [15]) or IEEE 802.3 (RFC 1042 [16]) encapsulation
+   if the interface is an Ethernet.  A value of 0 indicates that the
+   client should use RFC 894 encapsulation.  A value of 1 means that the
+   client should use RFC 1042 encapsulation.
+
+   The code for this option is 36, and its length is 1.
+
+    Code   Len  Value
+   +-----+-----+-----+
+   |  36 |  1  | 0/1 |
+   +-----+-----+-----+
+
+7. TCP Parameters
+
+   This section lists the options that affect the operation of the TCP
+   layer on a per-interface basis.
+
+7.1. TCP Default TTL Option
+
+   This option specifies the default TTL that the client should use when
+   sending TCP segments.  The value is represented as an 8-bit unsigned
+   integer.  The minimum value is 1.
+
+   The code for this option is 37, and its length is 1.
+
+    Code   Len   TTL
+   +-----+-----+-----+
+   |  37 |  1  |  n  |
+   +-----+-----+-----+
+
+
+
+
+
+
+
+Alexander & Droms                                              [Page 17]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+7.2. TCP Keepalive Interval Option
+
+   This option specifies the interval (in seconds) that the client TCP
+   should wait before sending a keepalive message on a TCP connection.
+   The time is specified as a 32-bit unsigned integer.  A value of zero
+   indicates that the client should not generate keepalive messages on
+   connections unless specifically requested by an application.
+
+   The code for this option is 38, and its length is 4.
+
+    Code   Len           Time
+   +-----+-----+-----+-----+-----+-----+
+   |  38 |  4  |  t1 |  t2 |  t3 |  t4 |
+   +-----+-----+-----+-----+-----+-----+
+
+7.3. TCP Keepalive Garbage Option
+
+   This option specifies the whether or not the client should send TCP
+   keepalive messages with a octet of garbage for compatibility with
+   older implementations.  A value of 0 indicates that a garbage octet
+   should not be sent. A value of 1 indicates that a garbage octet
+   should be sent.
+
+   The code for this option is 39, and its length is 1.
+
+    Code   Len  Value
+   +-----+-----+-----+
+   |  39 |  1  | 0/1 |
+   +-----+-----+-----+
+
+8. Application and Service Parameters
+
+   This section details some miscellaneous options used to configure
+   miscellaneous applications and services.
+
+8.1. Network Information Service Domain Option
+
+   This option specifies the name of the client's NIS [17] domain.  The
+   domain is formatted as a character string consisting of characters
+   from the NVT ASCII character set.
+
+   The code for this option is 40.  Its minimum length is 1.
+
+    Code   Len      NIS Domain Name
+   +-----+-----+-----+-----+-----+-----+---
+   |  40 |  n  |  n1 |  n2 |  n3 |  n4 | ...
+   +-----+-----+-----+-----+-----+-----+---
+
+
+
+
+Alexander & Droms                                              [Page 18]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+8.2. Network Information Servers Option
+
+   This option specifies a list of IP addresses indicating NIS servers
+   available to the client.  Servers SHOULD be listed in order of
+   preference.
+
+   The code for this option is 41.  Its minimum length is 4, and the
+   length MUST be a multiple of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  41 |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+8.3. Network Time Protocol Servers Option
+
+   This option specifies a list of IP addresses indicating NTP [18]
+   servers available to the client.  Servers SHOULD be listed in order
+   of preference.
+
+   The code for this option is 42.  Its minimum length is 4, and the
+   length MUST be a multiple of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+   |  42 |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+--
+
+8.4. Vendor Specific Information
+
+   This option is used by clients and servers to exchange vendor-
+   specific information.  The information is an opaque object of n
+   octets, presumably interpreted by vendor-specific code on the clients
+   and servers.  The definition of this information is vendor specific.
+   The vendor is indicated in the class-identifier option.  Servers not
+   equipped to interpret the vendor-specific information sent by a
+   client MUST ignore it (although it may be reported).  Clients which
+   do not receive desired vendor-specific information SHOULD make an
+   attempt to operate without it, although they may do so (and announce
+   they are doing so) in a degraded mode.
+
+   If a vendor potentially encodes more than one item of information in
+   this option, then the vendor SHOULD encode the option using
+   "Encapsulated vendor-specific options" as described below:
+
+   The Encapsulated vendor-specific options field SHOULD be encoded as a
+   sequence of code/length/value fields of identical syntax to the DHCP
+   options field with the following exceptions:
+
+
+
+Alexander & Droms                                              [Page 19]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+      1) There SHOULD NOT be a "magic cookie" field in the encapsulated
+         vendor-specific extensions field.
+
+      2) Codes other than 0 or 255 MAY be redefined by the vendor within
+         the encapsulated vendor-specific extensions field, but SHOULD
+         conform to the tag-length-value syntax defined in section 2.
+
+      3) Code 255 (END), if present, signifies the end of the
+         encapsulated vendor extensions, not the end of the vendor
+         extensions field. If no code 255 is present, then the end of
+         the enclosing vendor-specific information field is taken as the
+         end of the encapsulated vendor-specific extensions field.
+
+   The code for this option is 43 and its minimum length is 1.
+
+   Code   Len   Vendor-specific information
+   +-----+-----+-----+-----+---
+   |  43 |  n  |  i1 |  i2 | ...
+   +-----+-----+-----+-----+---
+
+   When encapsulated vendor-specific extensions are used, the
+   information bytes 1-n have the following format:
+
+    Code   Len   Data item        Code   Len   Data item       Code
+   +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+   |  T1 |  n  |  d1 |  d2 | ... |  T2 |  n  |  D1 |  D2 | ... | ... |
+   +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+
+8.5. NetBIOS over TCP/IP Name Server Option
+
+   The NetBIOS name server (NBNS) option specifies a list of RFC
+   1001/1002 [19] [20] NBNS name servers listed in order of preference.
+
+   The code for this option is 44.  The minimum length of the option is
+   4 octets, and the length must always be a multiple of 4.
+
+    Code   Len           Address 1              Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----
+   |  44 |  n  |  a1 |  a2 |  a3 |  a4 |  b1 |  b2 |  b3 |  b4 | ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----
+
+
+
+
+
+
+
+
+
+
+
+Alexander & Droms                                              [Page 20]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+8.6. NetBIOS over TCP/IP Datagram Distribution Server Option
+
+   The NetBIOS datagram distribution server (NBDD) option specifies a
+   list of RFC 1001/1002 NBDD servers listed in order of preference. The
+   code for this option is 45.  The minimum length of the option is 4
+   octets, and the length must always be a multiple of 4.
+
+    Code   Len           Address 1              Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----
+   |  45 |  n  |  a1 |  a2 |  a3 |  a4 |  b1 |  b2 |  b3 |  b4 | ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----
+
+8.7. NetBIOS over TCP/IP Node Type Option
+
+   The NetBIOS node type option allows NetBIOS over TCP/IP clients which
+   are configurable to be configured as described in RFC 1001/1002.  The
+   value is specified as a single octet which identifies the client type
+   as follows:
+
+      Value         Node Type
+      -----         ---------
+      0x1           B-node
+      0x2           P-node
+      0x4           M-node
+      0x8           H-node
+
+   In the above chart, the notation '0x' indicates a number in base-16
+   (hexadecimal).
+
+   The code for this option is 46.  The length of this option is always
+   1.
+
+    Code   Len  Node Type
+   +-----+-----+-----------+
+   |  46 |  1  | see above |
+   +-----+-----+-----------+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Alexander & Droms                                              [Page 21]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+8.8. NetBIOS over TCP/IP Scope Option
+
+   The NetBIOS scope option specifies the NetBIOS over TCP/IP scope
+   parameter for the client as specified in RFC 1001/1002. See [19],
+   [20], and [8] for character-set restrictions.
+
+   The code for this option is 47.  The minimum length of this option is
+   1.
+
+    Code   Len       NetBIOS Scope
+   +-----+-----+-----+-----+-----+-----+----
+   |  47 |  n  |  s1 |  s2 |  s3 |  s4 | ...
+   +-----+-----+-----+-----+-----+-----+----
+
+8.9. X Window System Font Server Option
+
+   This option specifies a list of X Window System [21] Font servers
+   available to the client. Servers SHOULD be listed in order of
+   preference.
+
+   The code for this option is 48.  The minimum length of this option is
+   4 octets, and the length MUST be a multiple of 4.
+
+    Code   Len         Address 1               Address 2
+   +-----+-----+-----+-----+-----+-----+-----+-----+---
+   |  48 |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |   ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+---
+
+8.10. X Window System Display Manager Option
+
+   This option specifies a list of IP addresses of systems that are
+   running the X Window System Display Manager and are available to the
+   client.
+
+   Addresses SHOULD be listed in order of preference.
+
+   The code for the this option is 49. The minimum length of this option
+   is 4, and the length MUST be a multiple of 4.
+
+    Code   Len         Address 1               Address 2
+
+   +-----+-----+-----+-----+-----+-----+-----+-----+---
+   |  49 |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |   ...
+   +-----+-----+-----+-----+-----+-----+-----+-----+---
+
+
+
+
+
+
+
+Alexander & Droms                                              [Page 22]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+9. DHCP Extensions
+
+   This section details the options that are specific to DHCP.
+
+9.1. Requested IP Address
+
+   This option is used in a client request (DHCPDISCOVER) to allow the
+   client to request that a particular IP address be assigned.
+
+   The code for this option is 50, and its length is 4.
+
+    Code   Len          Address
+   +-----+-----+-----+-----+-----+-----+
+   |  50 |  4  |  a1 |  a2 |  a3 |  a4 |
+   +-----+-----+-----+-----+-----+-----+
+
+9.2. IP Address Lease Time
+
+   This option is used in a client request (DHCPDISCOVER or DHCPREQUEST)
+   to allow the client to request a lease time for the IP address.  In a
+   server reply (DHCPOFFER), a DHCP server uses this option to specify
+   the lease time it is willing to offer.
+
+   The time is in units of seconds, and is specified as a 32-bit
+   unsigned integer.
+
+   The code for this option is 51, and its length is 4.
+
+    Code   Len         Lease Time
+   +-----+-----+-----+-----+-----+-----+
+   |  51 |  4  |  t1 |  t2 |  t3 |  t4 |
+   +-----+-----+-----+-----+-----+-----+
+
+9.3. Option Overload
+
+   This option is used to indicate that the DHCP "sname" or "file"
+   fields are being overloaded by using them to carry DHCP options. A
+   DHCP server inserts this option if the returned parameters will
+   exceed the usual space allotted for options.
+
+   If this option is present, the client interprets the specified
+   additional fields after it concludes interpretation of the standard
+   option fields.
+
+   The code for this option is 52, and its length is 1.  Legal values
+   for this option are:
+
+
+
+
+
+Alexander & Droms                                              [Page 23]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+           Value   Meaning
+           -----   --------
+             1     the "file" field is used to hold options
+             2     the "sname" field is used to hold options
+             3     both fields are used to hold options
+
+    Code   Len  Value
+   +-----+-----+-----+
+   |  52 |  1  |1/2/3|
+   +-----+-----+-----+
+
+9.4. DHCP Message Type
+
+   This option is used to convey the type of the DHCP message.  The code
+   for this option is 53, and its length is 1.  Legal values for this
+   option are:
+
+           Value   Message Type
+           -----   ------------
+             1     DHCPDISCOVER
+             2     DHCPOFFER
+             3     DHCPREQUEST
+             4     DHCPDECLINE
+             5     DHCPACK
+             6     DHCPNAK
+             7     DHCPRELEASE
+
+    Code   Len  Type
+   +-----+-----+-----+
+   |  53 |  1  | 1-7 |
+   +-----+-----+-----+
+
+9.5. Server Identifier
+
+   This option is used in DHCPOFFER and DHCPREQUEST messages, and may
+   optionally be included in the DHCPACK and DHCPNAK messages.  DHCP
+   servers include this option in the DHCPOFFER in order to allow the
+   client to distinguish between lease offers.  DHCP clients indicate
+   which of several lease offers is being accepted by including this
+   option in a DHCPREQUEST message.
+
+   The identifier is the IP address of the selected server.
+
+
+
+
+
+
+
+
+
+Alexander & Droms                                              [Page 24]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+   The code for this option is 54, and its length is 4.
+
+    Code   Len            Address
+   +-----+-----+-----+-----+-----+-----+
+   |  54 |  4  |  a1 |  a2 |  a3 |  a4 |
+   +-----+-----+-----+-----+-----+-----+
+
+9.6. Parameter Request List
+
+   This option is used by a DHCP client to request values for specified
+   configuration parameters.  The list of requested parameters is
+   specified as n octets, where each octet is a valid DHCP option code
+   as defined in this document.
+
+   The client MAY list the options in order of preference.  The DHCP
+   server is not required to return the options in the requested order,
+   but MUST try to insert the requested options in the order requested
+   by the client.
+
+   The code for this option is 55.  Its minimum length is 1.
+
+    Code   Len   Option Codes
+   +-----+-----+-----+-----+---
+   |  55 |  n  |  c1 |  c2 | ...
+   +-----+-----+-----+-----+---
+
+9.7. Message
+
+   This option is used by a DHCP server to provide an error message to a
+   DHCP client in a DHCPNAK message in the event of a failure. A client
+   may use this option in a DHCPDECLINE message to indicate the why the
+   client declined the offered parameters.  The message consists of n
+   octets of NVT ASCII text, which the client may display on an
+   available output device.
+
+   The code for this option is 56 and its minimum length is 1.
+
+    Code   Len     Text
+   +-----+-----+-----+-----+---
+   |  56 |  n  |  c1 |  c2 | ...
+   +-----+-----+-----+-----+---
+
+
+
+
+
+
+
+
+
+
+Alexander & Droms                                              [Page 25]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+9.8. Maximum DHCP Message Size
+
+   This option specifies the maximum length DHCP message that it is
+   willing to accept.  The length is specified as an unsigned 16-bit
+   integer.  A client may use the maximum DHCP message size option in
+   DHCPDISCOVER or DHCPREQUEST messages, but should not use the option
+   in DHCPDECLINE messages.
+
+   The code for this option is 57, and its length is 2.  The minimum
+   legal value is 576 octets.
+
+    Code   Len     Length
+   +-----+-----+-----+-----+
+   |  57 |  2  |  l1 |  l2 |
+   +-----+-----+-----+-----+
+
+9.9. Renewal (T1) Time Value
+
+   This option specifies the time interval from address assignment until
+   the client transitions to the RENEWING state.
+
+   The value is in units of seconds, and is specified as a 32-bit
+   unsigned integer.
+
+   The code for this option is 58, and its length is 4.
+
+    Code   Len         T1 Interval
+   +-----+-----+-----+-----+-----+-----+
+   |  58 |  4  |  t1 |  t2 |  t3 |  t4 |
+   +-----+-----+-----+-----+-----+-----+
+
+9.10. Rebinding (T2) Time Value
+
+   This option specifies the time interval from address assignment until
+   the client transitions to the REBINDING state.
+
+   The value is in units of seconds, and is specified as a 32-bit
+   unsigned integer.
+
+   The code for this option is 59, and its length is 4.
+
+    Code   Len         T2 Interval
+   +-----+-----+-----+-----+-----+-----+
+   |  59 |  4  |  t1 |  t2 |  t3 |  t4 |
+   +-----+-----+-----+-----+-----+-----+
+
+
+
+
+
+
+Alexander & Droms                                              [Page 26]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+9.11. Class-identifier
+
+   This option is used by DHCP clients to optionally identify the type
+   and configuration of a DHCP client.  The information is a string of n
+   octets, interpreted by servers.  Vendors and sites may choose to
+   define specific class identifiers to convey particular configuration
+   or other identification information about a client.  For example, the
+   identifier may encode the client's hardware configuration.  Servers
+   not equipped to interpret the class-specific information sent by a
+   client MUST ignore it (although it may be reported).
+
+   The code for this option is 60, and its minimum length is 1.
+
+   Code   Len   Class-Identifier
+   +-----+-----+-----+-----+---
+   |  60 |  n  |  i1 |  i2 | ...
+   +-----+-----+-----+-----+---
+
+9.12. Client-identifier
+
+   This option is used by DHCP clients to specify their unique
+   identifier.  DHCP servers use this value to index their database of
+   address bindings.  This value is expected to be unique for all
+   clients in an administrative domain.
+
+   Identifiers consist of a type-value pair, similar to the
+
+   It is expected that this field will typically contain a hardware type
+   and hardware address, but this is not required.  Current legal values
+   for hardware types are defined in [22].
+
+   The code for this option is 61, and its minimum length is 2.
+
+   Code   Len   Type  Client-Identifier
+   +-----+-----+-----+-----+-----+---
+   |  61 |  n  |  t1 |  i1 |  i2 | ...
+   +-----+-----+-----+-----+-----+---
+
+10. Extensions
+
+   Additional generic data fields may be registered by contacting:
+
+      Internet Assigned Numbers Authority (IANA)
+      USC/Information Sciences Institute
+      4676 Admiralty Way
+      Marina del Rey, California  90292-6695
+
+      or by email as: iana@isi.edu
+
+
+
+Alexander & Droms                                              [Page 27]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+   Implementation specific use of undefined generic types (those in the
+   range 61-127) may conflict with other implementations, and
+   registration is required.
+
+11. Acknowledgements
+
+   The authors would like to thank Philip Almquist for his feedback on
+   this document.  The comments of the DHCP Working Group are also
+   gratefully acknowledged.  In particular, Mike Carney and Jon Dreyer
+   from SunSelect suggested the current format of the Vendor-specific
+   Information option.
+
+   RFC 1497 is based on earlier work by Philip Prindeville, with help
+   from Drew Perkins, Bill Croft, and Steve Deering.
+
+12. References
+
+   [1] Droms, R., "Dynamic Host Configuration Protocol", RFC 1531,
+       Bucknell University, October 1993.
+
+   [2] Reynolds, J., "BOOTP Vendor Information Extensions", RFC 1497,
+       USC/Information Sciences Institute, August 1993.
+
+   [3] Croft, W., and J. Gilmore, "Bootstrap Protocol", RFC 951,
+       Stanford University and Sun Microsystems, September 1985.
+
+   [4] Braden, R., Editor, "Requirements for Internet Hosts -
+       Communication Layers", STD 3, RFC 1122, USC/Information Sciences
+       Institute, October 1989.
+
+   [5] Mogul, J., and J. Postel, "Internet Standard Subnetting
+       Procedure", STD 5, RFC 950, USC/Information Sciences Institute,
+       August 1985.
+
+   [6] Postel, J., and K. Harrenstien, "Time Protocol", STD 26, RFC
+       868, USC/Information Sciences Institute, SRI, May 1983.
+
+   [7] Postel, J., "Name Server", IEN 116, USC/Information Sciences
+       Institute, August 1979.
+
+   [8] Mockapetris, P., "Domain Names - Implementation and
+       Specification", STD 13, RFC 1035, USC/Information Sciences
+       Institute, November 1987.
+
+   [9] Postel, J., "Quote of the Day Protocol", STD 23, RFC 865,
+       USC/Information Sciences Institute, May 1983.
+
+
+
+
+
+Alexander & Droms                                              [Page 28]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+   [10] McLaughlin, L., "Line Printer Daemon Protocol", RFC 1179, The
+        Wollongong Group, August 1990.
+
+   [11] Accetta, M., "Resource Location Protocol", RFC 887, CMU,
+        December 1983.
+
+   [12] Mogul, J. and S. Deering, "Path MTU Discovery", RFC 1191,
+        DECWRL,  Stanford University, November 1990.
+
+   [13] Deering, S., "ICMP Router Discovery Messages", RFC 1256,
+        Xerox PARC, September 1991.
+
+   [14] Leffler, S. and M. Karels, "Trailer Encapsulations", RFC 893,
+        U. C. Berkeley, April 1984.
+
+   [15] Hornig, C., "Standard for the Transmission of IP Datagrams over
+        Ethernet Networks", RFC 894, Symbolics, April 1984.
+
+   [16] Postel, J. and J. Reynolds, "Standard for the Transmission of
+        IP Datagrams Over IEEE 802 Networks", RFC 1042,  USC/Information
+        Sciences Institute, February 1988.
+
+   [17] Sun Microsystems, "System and Network Administration", March
+        1990.
+
+   [18] Mills, D., "Internet Time Synchronization: The Network Time
+        Protocol", RFC 1305, UDEL, March 1992.
+
+   [19] NetBIOS Working Group, "Protocol Standard for a NetBIOS Service
+        on a TCP/UDP transport: Concepts and Methods", STD 19, RFC 1001,
+        March 1987.
+
+   [20] NetBIOS Working Group, "Protocol Standard for a NetBIOS Service
+        on a TCP/UDP transport: Detailed Specifications", STD 19, RFC
+        1002, March 1987.
+
+   [21] Scheifler, R., "FYI On the X Window System", FYI 6, RFC 1198,
+        MIT Laboratory for Computer Science, January 1991.
+
+   [22] Reynolds, J., and J. Postel, "Assigned Numbers", STD 2, RFC 1340,
+        USC/Information Sciences Institute, July 1992.
+
+13. Security Considerations
+
+   Security issues are not discussed in this memo.
+
+
+
+
+
+
+Alexander & Droms                                              [Page 29]
+\f
+RFC 1533        DHCP Options and BOOTP Vendor Extensions    October 1993
+
+
+14. Authors' Addresses
+
+   Steve Alexander
+   Lachman Technology, Inc.
+   1901 North Naper Boulevard
+   Naperville, IL 60563-8895
+
+   Phone: (708) 505-9555 x256
+   EMail: stevea@lachman.com
+
+
+   Ralph Droms
+   Computer Science Department
+   323 Dana Engineering
+   Bucknell University
+   Lewisburg, PA 17837
+
+   Phone: (717) 524-1145
+   EMail: droms@bucknell.edu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Alexander & Droms                                              [Page 30]
+\f
\ No newline at end of file
diff --git a/errwarn.c b/errwarn.c
new file mode 100644 (file)
index 0000000..d3c25c4
--- /dev/null
+++ b/errwarn.c
@@ -0,0 +1,200 @@
+/* errwarn.c
+
+   Errors and warnings... */
+
+/*
+ * Copyright (c) 1995 RadioMail Corporation.  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 RadioMail Corporation 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 RADIOMAIL CORPORATION 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
+ * RADIOMAIL CORPORATION 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 was written for RadioMail Corporation by Ted Lemon
+ * under a contract with Vixie Enterprises, and is based on an earlier
+ * design by Paul Vixie.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1995 RadioMail Corporation.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+#include <syslog.h>
+#include <errno.h>
+
+static void do_percentm PROTO ((char *obuf, char *ibuf));
+
+static char mbuf [1024];
+static char fbuf [1024];
+
+/* Log an error message, then exit... */
+
+int error (ANSI_DECL(char *) fmt, VA_DOTDOTDOT)
+     KandR (char *fmt;)
+     va_dcl
+{
+  va_list list;
+  extern int logged_in;
+
+  do_percentm (fbuf, fmt);
+
+  VA_start (list, fmt);
+  vsnprintf (mbuf, sizeof mbuf, fbuf, list);
+  va_end (list);
+#ifndef DEBUG
+  syslog (LOG_ERR, mbuf);
+#else
+  write (1, mbuf, strlen (mbuf));
+  write (1, "\n", 1);
+#endif
+
+  cleanup ();
+  exit (1);
+}
+
+/* Log a warning message... */
+
+int warn (ANSI_DECL (char *) fmt, VA_DOTDOTDOT)
+     KandR (char *fmt;)
+     va_dcl
+{
+  va_list list;
+
+  do_percentm (fbuf, fmt);
+
+  VA_start (list, fmt);
+  vsnprintf (mbuf, sizeof mbuf, fbuf, list);
+  va_end (list);
+#ifndef DEBUG
+  syslog (LOG_ERR, mbuf);
+#else
+  write (1, mbuf, strlen (mbuf));
+  write (1, "\n", 1);
+#endif
+  return 0;
+}
+
+/* Log a note... */
+
+int note (ANSI_DECL (char *) fmt, VA_DOTDOTDOT)
+     KandR (char *fmt;)
+     va_dcl
+{
+  va_list list;
+
+  do_percentm (fbuf, fmt);
+
+  VA_start (list, fmt);
+  vsnprintf (mbuf, sizeof mbuf, fbuf, list);
+  va_end (list);
+#ifndef DEBUG
+  syslog (LOG_INFO, mbuf);
+#else
+  write (1, mbuf, strlen (mbuf));
+  write (1, "\n", 1);
+#endif
+  return 0;
+}
+
+/* Log a debug message... */
+
+int debug (ANSI_DECL (char *) fmt, VA_DOTDOTDOT)
+     KandR (char *fmt;)
+     va_dcl
+{
+  va_list list;
+
+  do_percentm (fbuf, fmt);
+
+  VA_start (list, fmt);
+  vsnprintf (mbuf, sizeof mbuf, fbuf, list);
+  va_end (list);
+#ifndef DEBUG
+  syslog (LOG_DEBUG, mbuf);
+#else
+  write (1, mbuf, strlen (mbuf));
+  write (1, "\n", 1);
+#endif
+  return 0;
+}
+
+/* Find %m in the input string and substitute an error message string. */
+
+static void do_percentm (obuf, ibuf)
+     char *obuf;
+     char *ibuf;
+{
+  char *s = ibuf;
+  char *p = obuf;
+  int infmt = 0;
+
+  while (*s)
+    {
+      if (infmt)
+       {
+         if (*s == 'm')
+           {
+             strcpy (p - 1, strerror (errno));
+             p += strlen (p);
+             ++s;
+           }
+         else
+           *p++ = *s++;
+         infmt = 0;
+       }
+      else
+       {
+         if (*s == '%')
+           infmt = 1;
+         *p++ = *s++;
+       }
+    }
+  *p = 0;
+}
+
+
+int parse_warn (ANSI_DECL (char *) fmt, VA_DOTDOTDOT)
+       KandR (char *fmt;)
+       va_dcl
+{
+       extern int tline, tlpos;
+       va_list list;
+       
+       do_percentm (mbuf, fmt);
+       snprintf (fbuf, sizeof fbuf, "dhcpd.conf line %d char %d: %s",
+                 tline, tlpos, mbuf);
+       
+       VA_start (list, fmt);
+       vsnprintf (mbuf, sizeof mbuf, fbuf, list);
+       va_end (list);
+#ifndef DEBUG
+       syslog (LOG_ERROR, mbuf);
+#else
+       write (1, mbuf, strlen (mbuf));
+       write (1, "\n", 1);
+#endif
+       return 0;
+}
diff --git a/hash.c b/hash.c
new file mode 100644 (file)
index 0000000..9b2d5f9
--- /dev/null
+++ b/hash.c
@@ -0,0 +1,152 @@
+/* hash.c
+
+   Routines for manipulating hash tables... */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+struct hash_table *new_hash ()
+{
+       struct hash_table *rv = new_hash_table (DEFAULT_HASH_SIZE, "new_hash");
+       if (!rv)
+               return rv;
+       memset (&rv -> buckets, 0,
+               DEFAULT_HASH_SIZE * sizeof (struct hash_bucket *));
+       return rv;
+}
+
+static INLINE do_hash (name, len, size)
+       char *name;
+       int len;
+       int size;
+{
+       register int accum = 0;
+       register unsigned char *s = (unsigned char *)name;
+       int i = len;
+       if (i) {
+               while (i--) {
+                       /* Add the character in... */
+                       accum += *s++;
+                       /* Add carry back in... */
+                       while (accum > 255) {
+                               accum = (accum & 255) + (accum >> 8);
+                       }
+               }
+       } else {
+               while (*s) {
+                       /* Add the character in... */
+                       accum += *s++;
+                       /* Add carry back in... */
+                       while (accum > 255) {
+                               accum = (accum & 255) + (accum >> 8);
+                       }
+               }
+       }
+       return accum % size;
+}
+
+void add_hash (table, name, len, pointer)
+       struct hash_table *table;
+       int len;
+       char *name;
+       unsigned char *pointer;
+{
+       int hashno = do_hash (name, len, table -> hash_count);
+       struct hash_bucket *bp = new_hash_bucket ("add_hash");
+       if (!bp) {
+               warn ("Can't add %s to hash table.", name);
+               return;
+       }
+       bp -> name = name;
+       bp -> value = pointer;
+       bp -> next = table -> buckets [hashno];
+       table -> buckets [hashno] = bp;
+}
+
+void delete_hash_entry (table, name, len)
+       struct hash_table *table;
+       int len;
+       char *name;
+{
+       int hashno = do_hash (name, len, table -> hash_count);
+       struct hash_bucket *bp, *pbp = (struct hash_bucket *)0;
+
+       /* Go through the list looking for an entry that matches;
+          if we find it, delete it. */
+       for (bp = table -> buckets [hashno]; bp; bp = bp -> next) {
+               if ((!bp -> len && !strcmp (bp -> name, name)) ||
+                   (bp -> len == len &&
+                    !memcmp (bp -> name, name, len))) {
+                       if (pbp) {
+                               pbp -> next = bp -> next;
+                       } else {
+                               table -> buckets [hashno] = bp -> next;
+                       }
+                       free_hash_bucket (bp, "delete_hash_entry");
+                       break;
+               }
+       }
+}
+
+unsigned char *hash_lookup (table, name, len)
+       struct hash_table *table;
+       char *name;
+       int len;
+{
+       int hashno = do_hash (name, len, table -> hash_count);
+       struct hash_bucket *bp;
+
+       if (len) {
+               for (bp = table -> buckets [hashno]; bp; bp = bp -> next)
+                       if (len == bp -> len
+                           && !memcmp (bp -> name, name, len))
+                               return bp -> value;
+       } else {
+               for (bp = table -> buckets [hashno]; bp; bp = bp -> next)
+                       if (!strcmp (bp -> name, name))
+                               return bp -> value;
+       }
+       return (unsigned char *)0;
+}
+
diff --git a/hash.h b/hash.h
new file mode 100644 (file)
index 0000000..d30072b
--- /dev/null
+++ b/hash.h
@@ -0,0 +1,55 @@
+/* hash.h
+
+   Definitions for hashing... */
+
+/*
+ * Copyright (c) 1995 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''.
+ */
+
+#define DEFAULT_HASH_SIZE      97
+
+struct hash_bucket {
+       struct hash_bucket *next;
+       char *name;
+       int len;
+       unsigned char *value;
+};
+
+struct hash_table {
+       int hash_count;
+       struct hash_bucket *buckets [DEFAULT_HASH_SIZE];
+};
+
diff --git a/includes/cdefs.h b/includes/cdefs.h
new file mode 100644 (file)
index 0000000..4b94c99
--- /dev/null
@@ -0,0 +1,49 @@
+/* cdefs.h
+
+   Standard C definitions... */
+
+/*
+ * Copyright (c) 1995 RadioMail Corporation.  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 RadioMail Corporation 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 RADIOMAIL CORPORATION 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
+ * RADIOMAIL CORPORATION 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 was written for RadioMail Corporation by Ted Lemon
+ * under a contract with Vixie Enterprises, and is based on an earlier
+ * design by Paul Vixie.
+ */
+
+#if defined (__GNUC__) || defined (__STDC__)
+#define PROTO(x)       x
+#define KandR(x)
+#define ANSI_DECL(x)   x
+#define INLINE         inline
+#else
+#define PROTO(x)       ()
+#define KandR(x)       x
+#define ANSI_DECL(x)
+#define INLINE
+#endif
diff --git a/includes/cf/bsdos.h b/includes/cf/bsdos.h
new file mode 100644 (file)
index 0000000..bdac405
--- /dev/null
@@ -0,0 +1,106 @@
+/* bsdos.h
+
+   System dependencies for BSD/os... */
+
+/*
+ * Copyright (c) 1995 RadioMail Corporation.  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 RadioMail Corporation 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 RADIOMAIL CORPORATION 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
+ * RADIOMAIL CORPORATION 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 was written for RadioMail Corporation by Ted Lemon
+ * under a contract with Vixie Enterprises, and is based on an earlier
+ * design by Paul Vixie.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <paths.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <limits.h>
+
+#include <netdb.h>
+extern int h_errno;
+
+#include <net/if.h>
+
+/* Time stuff... */
+#include <sys/time.h>
+#define TIME struct timeval
+#define GET_TIME(x)    gettimeofday ((x), (struct timezone *)0)
+#define TIME_DIFF_US(high, low)                                        \
+  (((high) -> tv_sec - (low) -> tv_sec) * 1000000                      \
+   + ((high) -> tv_usec - (low) -> tv_usec))
+#define SET_TIME(x, y) (((x) -> tv_sec = ((y) / 1000000)),             \
+                        ((x) -> tv_usec = ((y) % 1000000)))
+#define DELAY() usleep (2000)
+#define DELAY_ONE_SECOND() usleep (1000000)
+
+/* Login stuff... */
+#include <utmp.h>
+#include <sys/syslimits.h>
+#define _PATH_LOGIN    "/usr/bin/login"
+#define SETLOGIN(x) setlogin (x)
+#define SETUID(x)      setuid (x)
+#define SETGID(x)      (setgroups (0, &x), setgid (x))
+#define USER_MAX       UT_NAMESIZE
+
+/* Varargs stuff... */
+#include <stdarg.h>
+#define VA_DOTDOTDOT ...
+#define va_dcl
+#define VA_start(list, last) va_start (list, last)
+
+#define _PATH_MPOOL_PID        "/var/run/mpoold.pid"
+
+#define EOL    '\n'
+#define VOIDPTR        void *
+
+/* Time stuff... */
+#include <sys/time.h>
+#define TIME struct timeval
+#define GET_TIME(x)    gettimeofday ((x), (struct timezone *)0)
+#define TIME_DIFF(high, low)                                           \
+  (((high) -> tv_sec == (low) -> tv_sec)                               \
+   ? ((high) -> tv_usec > (low) -> tv_usec                             \
+      ? 1 : (((high) -> tv_usec == (low) -> tv_usec) ? 0 : -1))                \
+   : (high) -> tv_sec - (low) -> tv_sec)
+#define SET_TIME(x, y) (((x) -> tv_sec = ((y))), ((x) -> tv_usec = 0))
+#define ADD_TIME(d, s1, s2) {                                          \
+                (d) -> tv_usec = (s1) -> tv_usec + (s2) -> tv_usec;    \
+                if ((d) -> tv_usec > 1000000 || (d) -> tv_usec < -1000000) { \
+                        (d) -> tv_sec = (d) -> tv_usec / 1000000;      \
+                        (d) -> tv_usec %= 1000000;                     \
+                } else                                                 \
+                        (d) -> tv_sec = 0;                             \
+                (d) -> tv_sec += (s1) -> tv_sec + (s2) -> tv_sec;      \
+       }
+#define SET_MAX_TIME(x)        (((x) -> tv_sec = INT_MAX),                     \
+                        ((x) -> tv_usec = 999999))
diff --git a/includes/cf/netbsd.h b/includes/cf/netbsd.h
new file mode 100644 (file)
index 0000000..d69ff1b
--- /dev/null
@@ -0,0 +1,73 @@
+/* netbsd.h
+
+   System dependencies for NetBSD... */
+
+/*
+ * Copyright (c) 1995 RadioMail Corporation.  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 RadioMail Corporation 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 RADIOMAIL CORPORATION 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
+ * RADIOMAIL CORPORATION 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 was written for RadioMail Corporation by Ted Lemon
+ * under a contract with Vixie Enterprises, and is based on an earlier
+ * design by Paul Vixie.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <paths.h>
+#include <errno.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <limits.h>
+
+#include <sys/wait.h>
+#include <signal.h>
+
+#include <netdb.h>
+extern int h_errno;
+
+#include <net/if.h>
+
+/* Varargs stuff... */
+#include <stdarg.h>
+#define VA_DOTDOTDOT ...
+#define va_dcl
+#define VA_start(list, last) va_start (list, last)
+
+#define _PATH_DHCPD_PID        "/var/run/dhcpd.pid"
+
+#define EOL    '\n'
+#define VOIDPTR void *
+
+/* Time stuff... */
+#include <sys/time.h>
+#define TIME time_t
+#define GET_TIME(x)    time ((x))
+#define TIME_DIFF(high, low)           (*(high) - *(low))
+#define SET_TIME(x, y) (*(x) = (y))
+#define ADD_TIME(d, s1, s2) (*(d) = *(s1) + *(s2))
+#define SET_MAX_TIME(x)        (*(x) = INT_MAX)
diff --git a/includes/cf/sunos4.h b/includes/cf/sunos4.h
new file mode 100644 (file)
index 0000000..fa97687
--- /dev/null
@@ -0,0 +1,83 @@
+/* sunos4.h
+
+   System dependencies for SunOS 4 (tested on 4.1.4)... */
+
+/*
+ * Copyright (c) 1995 RadioMail Corporation.  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 RadioMail Corporation 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 RADIOMAIL CORPORATION 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
+ * RADIOMAIL CORPORATION 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 was written for RadioMail Corporation by Ted Lemon
+ * under a contract with Vixie Enterprises, and is based on an earlier
+ * design by Paul Vixie.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <limits.h>
+
+#include <netdb.h>
+extern int h_errno;
+
+#include <net/if.h>
+
+/* Varargs stuff... */
+#include <varargs.h>
+#define VA_DOTDOTDOT va_alist
+#define VA_start(list, last) va_start (list)
+
+#define vsnprintf(buf, size, fmt, list) vsprintf (buf, fmt, list)
+
+#define EOL    '\n'
+#define VOIDPTR        void *
+
+/* Time stuff... */
+#include <sys/time.h>
+#define TIME struct timeval
+#define GET_TIME(x)    gettimeofday ((x), (struct timezone *)0)
+#define TIME_DIFF(high, low)                                           \
+  (((high) -> tv_sec == (low) -> tv_sec)                               \
+   ? ((high) -> tv_usec > (low) -> tv_usec                             \
+      ? 1 : (((high) -> tv_usec == (low) -> tv_usec) ? 0 : -1))                \
+   : (high) -> tv_sec - (low) -> tv_sec)
+#define SET_TIME(x, y) (((x) -> tv_sec = ((y))), ((x) -> tv_usec = 0))
+#define ADD_TIME(d, s1, s2) {                                          \
+                (d) -> tv_usec = (s1) -> tv_usec + (s2) -> tv_usec;    \
+                if ((d) -> tv_usec > 1000000 || (d) -> tv_usec < -1000000) { \
+                        (d) -> tv_sec = (d) -> tv_usec / 1000000;      \
+                        (d) -> tv_usec %= 1000000;                     \
+                } else                                                 \
+                        (d) -> tv_sec = 0;                             \
+                (d) -> tv_sec += (s1) -> tv_sec + (s2) -> tv_sec;      \
+       }
+#define SET_MAX_TIME(x)        (((x) -> tv_sec = INT_MAX),                     \
+                        ((x) -> tv_usec = 999999))
diff --git a/includes/dhcp.h b/includes/dhcp.h
new file mode 100644 (file)
index 0000000..f06571d
--- /dev/null
@@ -0,0 +1,155 @@
+/* dhcp.h
+
+   Protocol structures... */
+
+/*
+ * Copyright (c) 1995 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''.
+ */
+
+#define DHCP_UDP_OVERHEAD      (14 + /* Ethernet header */             \
+                                20 + /* IP header */                   \
+                                8)   /* UDP header */
+#define DHCP_SNAME_LEN         64
+#define DHCP_FILE_LEN          128
+#define DHCP_FIXED_LEN         (236 + DHCP_UDP_OVERHEAD) /* Everything but
+                                                            options. */
+#define DHCP_MTU_MAX           1500
+#define DHCP_OPTION_LEN                (DHCP_MTU_MAX - DHCP_FIXED_LEN)
+
+struct dhcp_packet {
+       u_int8_t  op;           /* Message opcode/type */
+       u_int8_t  htype;        /* Hardware addr type (see net/if_types.h) */
+       u_int8_t  hlen;         /* Hardware addr length */
+       u_int8_t  hops;         /* Number of relay agent hops from client */
+       u_int32_t xid;          /* Transaction ID */
+       u_int16_t secs;         /* Seconds since client started looking */
+       u_int16_t flags;        /* Flag bits */
+       struct in_addr ciaddr;  /* Client IP address (if already in use) */
+       struct in_addr yiaddr;  /* Client IP address */
+       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 options [DHCP_OPTION_LEN]; /* Optional parameters
+                                          (actual length dependent on MTU). */
+};
+
+/* BOOTP (rfc951) message types */
+#define        BOOTREQUEST     1
+#define BOOTREPLY      2
+
+/* Possible values for flags field... */
+#define BOOTP_BROADCAST 32768L
+
+/* Magic cookie validating dhcp options field (and bootp vendor
+   extensions field). */
+#define DHCP_OPTIONS_COOKIE    "\143\202\123\143"
+
+/* DHCP Option codes: */
+
+#define DHO_PAD                                0
+#define DHO_SUBNET_MASK                        1
+#define DHO_TIME_OFFSET                        2
+#define DHO_ROUTERS                    3
+#define DHO_TIME_SERVERS               4
+#define DHO_NAME_SERVERS               5
+#define DHO_DOMAIN_NAME_SERVERS                6
+#define DHO_LOG_SERVERS                        7
+#define DHO_COOKIE_SERVERS             8
+#define DHO_LPR_SERVERS                        9
+#define DHO_IMPRESS_SERVERS            10
+#define DHO_RESOURCE_LOCATION_SERVERS  11
+#define DHO_HOST_NAME                  12
+#define DHO_BOOT_SIZE                  13
+#define DHO_MERIT_DUMP                 14
+#define DHO_DOMAIN_NAME                        15
+#define DHO_SWAP_SERVER                        16
+#define DHO_ROOT_PATH                  17
+#define DHO_EXTENSIONS_PATH            18
+#define DHO_IP_FORWARDING              19
+#define DHO_NON_LOCAL_SOURCE_ROUTING   20
+#define DHO_POLICY_FILTER              21
+#define DHO_MAX_DGRAM_REASSEMBLY       22
+#define DHO_DEFAULT_IP_TTL             23
+#define DHO_PATH_MTU_AGING_TIMEOUT     24
+#define DHO_PATH_MTU_PLATEAU_TABLE     25
+#define DHO_INTERFACE_MTU              26
+#define DHO_ALL_SUBNETS_LOCAL          27
+#define DHO_BROADCAST_ADDRESS          28
+#define DHO_PERFORM_MASK_DISCOVERY     29
+#define DHO_MASK_SUPPLIER              30
+#define DHO_ROUTER_DISCOVERY           31
+#define DHO_ROUTER_SOLICITATION_ADDRESS        32
+#define DHO_STATIC_ROUTES              33
+#define DHO_TRAILER_ENCAPSULATION      34
+#define DHO_ARP_CACHE_TIMEOUT          35
+#define DHO_IEEE802_3_ENCAPSULATION    36
+#define DHO_DEFAULT_TCP_TTL            37
+#define DHO_TCP_KEEPALIVE_INTERVAL     38
+#define DHO_TCP_KEEPALIVE_GARBAGE      39
+#define DHO_NIS_DOMAIN                 40
+#define DHO_NIS_SERVERS                        41
+#define DHO_NTP_SERVERS                        42
+#define DHO_VENDOR_ENCAPSULATED_OPTIONS        43
+#define DHO_NETBIOS_NAME_SERVERS       44
+#define DHO_NETBIOS_DD_SERVER          45
+#define DHO_NETBIOS_NODE_TYPE          46
+#define DHO_NETBIOS_SCOPE              47
+#define DHO_FONT_SERVERS               48
+#define DHO_X_DISPLAY_MANAGER          49
+#define DHO_DHCP_REQUESTED_ADDRESS     50
+#define DHO_DHCP_LEASE_TIME            51
+#define DHO_DHCP_OPTION_OVERLOAD       52
+#define DHO_DHCP_MESSAGE_TYPE          53
+#define DHO_DHCP_SERVER_IDENTIFIER     54
+#define DHO_DHCP_PARAMETER_REQUEST_LIST        55
+#define DHO_DHCP_MESSAGE               56
+#define DHO_DHCP_MAX_MESSAGE_SIZE      57
+#define DHO_DHCP_RENEWAL_TIME          58
+#define DHO_DHCP_REBINDING_TIME                59
+#define DHO_DHCP_CLASS_IDENTIFIER      60
+#define DHO_DHCP_CLIENT_IDENTIFIER     61
+#define DHO_END                                255
+
+/* DHCP message types. */
+#define DHCPDISCOVER   1
+#define DHCPOFFER      2
+#define DHCPREQUEST    3
+#define DHCPDECLINE    4
+#define DHCPACK                5
+#define DHCPNAK                6
+#define DHCPRELEASE    7
diff --git a/includes/dhcpd.h b/includes/dhcpd.h
new file mode 100644 (file)
index 0000000..ac1367c
--- /dev/null
@@ -0,0 +1,263 @@
+/* dhcpd.h
+
+   Definitions for dhcpd... */
+
+/*
+ * Copyright (c) 1995 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 <sys/types.h>
+#include <syslog.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include "dhcp.h"
+#include "cdefs.h"
+#include "osdep.h"
+#include "tree.h"
+#include "hash.h"
+
+/* A dhcp packet and the pointers to its option values. */
+struct packet {
+       struct dhcp_packet *raw;
+       int packet_length;
+       int packet_type;
+       int options_valid;
+       struct sockaddr_in client;
+       int client_len;
+       int client_sock;
+       struct {
+               int len;
+               unsigned char *data;
+       } options [256];
+};
+
+struct hardware {
+       u_int8_t htype;
+       u_int8_t hlen;
+       u_int8_t haddr [16];
+};
+
+/* A dhcp host declaration structure. */
+struct host_decl {
+       struct host_decl *n_name, *n_haddr, *n_cid;
+       char *name;
+       struct hardware *interfaces;
+       int interface_count;
+       char *filename;
+       char *server_name;      
+       struct tree_cache *fixed_addr;
+       struct tree_cache *options [256];
+};
+
+/* A dhcp lease declaration structure. */
+struct lease {
+       struct lease *next;
+       struct lease *prev;
+       struct in_addr ip_addr;
+       TIME starts, ends, timestamp;
+       unsigned char *uid;
+       int uid_len;
+       struct host_decl *host;
+       struct subnet *contain;
+       struct hardware hardware_addr;
+       int state;
+};
+
+struct subnet {
+       struct in_addr net;
+       struct in_addr netmask;
+       struct lease *leases;
+       struct lease *insertion_point;
+};
+
+/* Bitmask of dhcp option codes. */
+typedef unsigned char option_mask [16];
+
+/* DHCP Option mask manipulation macros... */
+#define OPTION_ZERO(mask)      (memset (mask, 0, 16))
+#define OPTION_SET(mask, bit)  (mask [bit >> 8] |= (1 << (bit & 7)))
+#define OPTION_CLR(mask, bit)  (mask [bit >> 8] &= ~(1 << (bit & 7)))
+#define OPTION_ISSET(mask, bit)        (mask [bit >> 8] & (1 << (bit & 7)))
+#define OPTION_ISCLR(mask, bit)        (!OPTION_ISSET (mask, bit))
+
+/* An option occupies its length plus two header bytes (code and
+    length) for every 255 bytes that must be stored. */
+#define OPTION_SPACE(x)                ((x) + 2 * ((x) / 255 + 1))
+
+/* Default path to dhcpd config file. */
+#ifndef _PATH_DHCPD_CONF
+#ifdef DEBUG
+#define _PATH_DHCPD_CONF       "dhcpd.conf"
+#else
+#define _PATH_DHCPD_CONF       "/etc/dhcpd.conf"
+#endif
+#endif
+
+/* Subnet macros... */
+#define SUBNET(addr, mask) ((addr).s_addr & (netmask).s_addr)
+#define IP_ADDR(net, host) ((net).s_addr | i)
+#define HOST_ADDR(addr, mask)  ((addr).s_addr & ~(netmask).s_addr)
+#define MAX_TIME 0x7fffffff
+#define MIN_TIME 0
+
+/* External definitions... */
+
+/* options.c */
+
+void parse_options PROTO ((struct packet *));
+void parse_option_buffer PROTO ((struct packet *, unsigned char *, int));
+void cons_options PROTO ((struct packet *, struct dhcp_packet *,
+                         struct host_decl *, int));
+char *pretty_print_option PROTO ((unsigned char, unsigned char *, int));
+
+/* errwarn.c */
+int error PROTO ((char *, ...));
+int warn PROTO ((char *, ...));
+int note PROTO ((char *, ...));
+int debug PROTO ((char *, ...));
+int parse_warn PROTO ((char *, ...));
+
+/* dhcpd.c */
+TIME cur_time;
+extern u_int32_t *server_addrlist;
+extern int server_addrcount;
+extern u_int16_t server_port;
+int main PROTO ((int, char **, char **));
+void cleanup PROTO ((void));
+void do_packet PROTO ((unsigned char *, int, struct sockaddr_in *, int, int));
+u_int32_t pick_interface PROTO ((struct packet *));
+
+
+/* conflex.c */
+int next_token PROTO ((char **, FILE *));
+int peek_token PROTO ((char **, FILE *));
+
+/* confpars.c */
+void readconf PROTO ((void));
+void parse_statement PROTO ((FILE *));
+void skip_to_semi PROTO ((FILE *));
+struct host_decl *parse_host_statement PROTO ((FILE *, jmp_buf *));
+char *parse_host_name PROTO ((FILE *, jmp_buf *));
+void parse_host_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
+void parse_hardware_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
+struct hardware parse_hardware_addr PROTO ((FILE *, jmp_buf *));
+void parse_filename_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
+void parse_fixed_addr_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
+void parse_option_decl PROTO ((FILE *, jmp_buf *, struct host_decl *));
+TIME parse_timestamp PROTO ((FILE *, jmp_buf *));
+TIME parse_date PROTO ((FILE *, jmp_buf *));
+struct lease *parse_lease_statement PROTO ((FILE *, jmp_buf *));
+void parse_address_range PROTO ((FILE *, jmp_buf *));
+unsigned char *parse_numeric_aggregate PROTO ((FILE *, jmp_buf *,
+                                              unsigned char *, int *,
+                                              int, int, int));
+void convert_num PROTO ((unsigned char *, char *, int, int));
+
+/* tree.c */
+pair cons PROTO ((caddr_t, pair));
+struct tree_cache *tree_cache PROTO ((struct tree *));
+struct tree *tree_host_lookup PROTO ((char *));
+struct dns_host_entry *enter_dns_host PROTO ((char *));
+struct tree *tree_const PROTO ((unsigned char *, int));
+struct tree *tree_concat PROTO ((struct tree *, struct tree *));
+struct tree *tree_limit PROTO ((struct tree *, int));
+int tree_evaluate PROTO ((struct tree_cache *));
+
+/* dhcp.c */
+void dhcp PROTO ((struct packet *));
+
+/* bootp.c */
+void bootp PROTO ((struct packet *));
+
+/* memory.c */
+void enter_host PROTO ((struct host_decl *));
+struct host_decl *find_host_by_name PROTO ((char *name));
+struct host_decl *find_host_by_addr PROTO ((int, unsigned char *, int));
+extern struct subnet *find_subnet (struct in_addr);
+void enter_subnet (struct subnet *);
+void enter_lease PROTO ((struct lease *));
+void supersede_lease PROTO ((struct lease *, struct lease *));
+struct lease *find_lease_by_uid PROTO ((unsigned char *, int));
+struct lease *find_lease_by_ip_addr PROTO ((struct in_addr));
+struct lease *find_next_expiring_lease PROTO ((void));
+
+/* alloc.c */
+VOIDPTR dmalloc PROTO ((int, char *));
+void dfree PROTO ((VOIDPTR, char *));
+struct packet *new_packet PROTO ((char *));
+struct dhcp_packet *new_dhcp_packet PROTO ((char *));
+struct tree *new_tree PROTO ((char *));
+struct tree_cache *new_tree_cache PROTO ((char *));
+struct hash_table *new_hash_table PROTO ((int, char *));
+struct hash_bucket *new_hash_bucket PROTO ((char *));
+struct lease *new_lease PROTO ((char *));
+struct lease *new_leases (int, char *);
+struct subnet *new_subnet PROTO ((char *));
+void free_subnet PROTO ((struct subnet *, char *));
+void free_lease PROTO ((struct lease *, char *));
+void free_hash_bucket PROTO ((struct hash_bucket *, char *));
+void free_hash_table PROTO ((struct hash_table *, char *));
+void free_tree_cache PROTO ((struct tree_cache *, char *));
+void free_packet PROTO ((struct packet *, char *));
+void free_dhcp_packet PROTO ((struct dhcp_packet *, char *));
+void free_tree PROTO ((struct tree *, char *));
+
+/* print.c */
+char *print_hw_addr PROTO ((int, int, unsigned char *));
+
+/* socket.c */
+u_int32_t *get_interface_list PROTO ((int *));
+void listen_on PROTO ((u_int16_t, u_int32_t));
+void dispatch PROTO ((void));
+
+/* hash.c */
+struct hash_table *new_hash PROTO ((void));
+void add_hash PROTO ((struct hash_table *, char *, int, unsigned char *));
+void delete_hash_entry PROTO ((struct hash_table *, char *, int));
+unsigned char *hash_lookup PROTO ((struct hash_table *, char *, int));
+
+/* tables.c */
+extern struct option dhcp_options [256];
+extern unsigned char dhcp_option_default_priority_list [];
+extern int sizeof_dhcp_option_default_priority_list;
+extern struct hash_table universe_hash;
+extern struct universe dhcp_universe;
+void initialize_universes PROTO ((void));
+
diff --git a/includes/dhctoken.h b/includes/dhctoken.h
new file mode 100644 (file)
index 0000000..04f057e
--- /dev/null
@@ -0,0 +1,71 @@
+/* dhctoken.h
+
+   Tokens for config file lexer and parser. */
+
+/*
+ * Copyright (c) 1995 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''.
+ */
+
+#define SEMI ';'
+#define DOT '.'
+#define COLON ':'
+#define COMMA ','
+#define SLASH '/'
+
+#define FIRST_TOKEN    HOST
+#define HOST           256
+#define HARDWARE       257
+#define FILENAME       258
+#define FIXED_ADDR     259
+#define OPTION         260
+#define ETHERNET       261
+#define STRING         262
+#define NUMBER         263
+#define NUMBER_OR_ATOM 264
+#define ATOM           265
+#define TIMESTAMP      266
+#define STARTS         267
+#define ENDS           268
+#define UID            269
+#define CLASS          270
+#define LEASE          271
+#define RANGE          272
+#define LAST_TOKEN     RANGE
+
+#define is_identifier(x)       ((x) >= FIRST_TOKEN &&  \
+                                (x) <= FIRST_TOKEN &&  \
+                                (x) != STRING &&       \
+                                (x) != NUMBER)
diff --git a/includes/hash.h b/includes/hash.h
new file mode 100644 (file)
index 0000000..d30072b
--- /dev/null
@@ -0,0 +1,55 @@
+/* hash.h
+
+   Definitions for hashing... */
+
+/*
+ * Copyright (c) 1995 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''.
+ */
+
+#define DEFAULT_HASH_SIZE      97
+
+struct hash_bucket {
+       struct hash_bucket *next;
+       char *name;
+       int len;
+       unsigned char *value;
+};
+
+struct hash_table {
+       int hash_count;
+       struct hash_bucket *buckets [DEFAULT_HASH_SIZE];
+};
+
diff --git a/includes/osdep.h b/includes/osdep.h
new file mode 100644 (file)
index 0000000..1ff4e68
--- /dev/null
@@ -0,0 +1,50 @@
+/* osdep.h
+
+   Operating system dependencies... */
+
+/*
+ * Copyright (c) 1995 RadioMail Corporation.  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 RadioMail Corporation 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 RADIOMAIL CORPORATION 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
+ * RADIOMAIL CORPORATION 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 was written for RadioMail Corporation by Ted Lemon
+ * under a contract with Vixie Enterprises, and is based on an earlier
+ * design by Paul Vixie.
+ */
+
+#ifdef sun
+#include "cf/sunos4.h"
+#endif
+
+#ifdef bsdi
+#include "cf/bsdos.h"
+#endif
+
+#ifdef __NetBSD__
+#include "cf/netbsd.h"
+#endif
+
diff --git a/includes/tree.h b/includes/tree.h
new file mode 100644 (file)
index 0000000..c6b7a3b
--- /dev/null
@@ -0,0 +1,104 @@
+/* tree.h
+
+   Definitions for address trees... */
+
+/*
+ * Copyright (c) 1995 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''.
+ */
+
+/* A pair of pointers, suitable for making a linked list. */
+typedef struct _pair {
+       caddr_t car;
+       struct _pair *cdr;
+} *pair;
+
+/* Tree node types... */
+#define TREE_CONCAT            1
+#define TREE_HOST_LOOKUP       2
+#define TREE_CONST             3
+#define TREE_LIMIT             4
+
+/* Tree structure for deferred evaluation of changing values. */
+struct tree {
+       int op;
+       union {
+               struct concat {
+                       struct tree *left;
+                       struct tree *right;
+               } concat;
+               struct host_lookup {
+                       struct dns_host_entry *host;
+               } host_lookup;
+               struct const_val {
+                       unsigned char *data;
+                       int len;
+               } const_val;
+               struct limit {
+                       struct tree *tree;
+                       int limit;
+               } limit;
+       } data;
+};
+
+/* DNS host entry structure... */
+struct dns_host_entry {
+       char *hostname;
+       unsigned char *data;
+       int data_len;
+       int buf_len;
+       TIME timeout;
+};
+
+struct tree_cache {
+       unsigned char *value;
+       int len;
+       int buf_size;
+       TIME timeout;
+       struct tree *tree;
+};
+
+struct universe {
+       char *name;
+       struct hash_table *hash;
+       struct option *options [256];
+};
+
+struct option {
+       char *name;
+       char *format;
+       struct universe *universe;
+       unsigned char code;
+};
diff --git a/memory.c b/memory.c
new file mode 100644 (file)
index 0000000..c3e1abd
--- /dev/null
+++ b/memory.c
@@ -0,0 +1,395 @@
+/* memory.c
+
+   Memory-resident database... */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+static struct host_decl *hosts;
+static struct hash_table *subnet_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;
+
+void enter_host (hd)
+       struct host_decl *hd;
+{
+       hd -> n_name = hosts;
+       hd -> n_haddr = hosts;
+       hd -> n_cid = hosts;
+       
+       hosts = hd;
+}
+
+struct host_decl *find_host_by_name (name)
+       char *name;
+{
+       struct host_decl *foo;
+
+       for (foo = hosts; foo; foo = foo -> n_name)
+               if (!strcmp (name, foo -> name))
+                       return foo;
+       return (struct host_decl *)0;
+}
+
+struct host_decl *find_host_by_addr (htype, haddr, hlen)
+       int htype;
+       unsigned char *haddr;
+       int hlen;
+{
+       struct host_decl *foo;
+       int i;
+
+       for (foo = hosts; foo; foo = foo -> n_haddr)
+               for (i = 0; i < foo -> interface_count; i++)
+                       if (foo -> interfaces [i].htype == htype &&
+                           foo -> interfaces [i].hlen == hlen &&
+                           !memcmp (foo -> interfaces [i].haddr, haddr, hlen))
+                               return foo;
+       return (struct host_decl *)0;
+}
+
+void new_address_range (low, high, netmask)
+       struct in_addr low, high, netmask;
+{
+       struct lease *address_range, *lp, *plp;
+       struct subnet *subnet;
+       struct in_addr net;
+       int i, max;
+       char lowbuf [16], highbuf [16], netbuf [16];
+
+       /* Initialize the hash table if it hasn't been done yet. */
+       if (!subnet_hash)
+               subnet_hash = new_hash ();
+       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.s_addr = SUBNET (low, netmask);
+       if (net.s_addr != SUBNET (high, netmask)) {
+               strcpy (lowbuf, inet_ntoa (low));
+               strcpy (highbuf, inet_ntoa (high));
+               strcpy (netbuf, inet_ntoa (netmask));
+               error ("Address range %s to %s, netmask %s spans %s!",
+                      lowbuf, highbuf, netbuf, "multiple subnets");
+       }
+
+       /* See if this subnet is already known - if not, make a new one. */
+       subnet = find_subnet (net);
+       if (!subnet) {
+               subnet = new_subnet ("new_address_range");
+               if (!subnet)
+                       error ("No memory for new subnet");
+               subnet -> net = net;
+               subnet -> netmask = netmask;
+               subnet -> leases = (struct lease *)0;
+               enter_subnet (subnet);
+       }
+
+       /* Get the high and low host addresses... */
+       max = HOST_ADDR (high, netmask);
+       i = HOST_ADDR (low, netmask);
+
+       /* Allow range to be specified high-to-low as well as low-to-high. */
+       if (i > max) {
+               max = i;
+               i = HOST_ADDR (high, netmask);
+       }
+
+       /* Get a lease structure for each address in the range. */
+       address_range = new_leases (max - i + 1, "new_address_range");
+       if (!address_range) {
+               strcpy (lowbuf, inet_ntoa (low));
+               strcpy (highbuf, inet_ntoa (high));
+               error ("No memory for address range %s-%s.", lowbuf, highbuf);
+       }
+       memset (address_range, 0, (sizeof *address_range) * (max - i + 1));
+
+       /* Fill out the lease structures with some minimal information. */
+       for (; i <= max; i++) {
+               address_range [i].ip_addr.s_addr = IP_ADDR (subnet -> net, i);
+               address_range [i].starts =
+                       address_range [i].timestamp = MIN_TIME;
+               address_range [i].ends = MIN_TIME;
+               address_range [i].contain = subnet;
+
+               /* Link this entry into the list. */
+               address_range [i].next = subnet -> leases;
+               address_range [i].prev = (struct lease *)0;
+               subnet -> leases = &address_range [i];
+               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,
+                         (unsigned char *)&address_range [i]);
+       }
+
+       /* Find out if any dangling leases are in range... */
+       plp = (struct lease *)0;
+       for (lp = dangling_leases; lp; lp = lp -> next) {
+               struct in_addr lnet;
+               int lhost;
+
+               lnet.s_addr = SUBNET (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 (lnet.s_addr == subnet -> net.s_addr &&
+                   lhost >= i && lhost <= max) {
+                       if (plp) {
+                               plp -> next = lp -> next;
+                       } else {
+                               dangling_leases = lp -> next;
+                       }
+                       lp -> next = (struct lease *)0;
+                       supersede_lease (&address_range [lhost - i], lp);
+                       free_lease (lp, "new_address_range");
+               } else
+                       plp = lp;
+       }
+}
+
+struct subnet *find_subnet (subnet)
+       struct in_addr subnet;
+{
+       struct subnet *rv;
+
+       return (struct subnet *)hash_lookup (subnet_hash,
+                                            (char *)&subnet, sizeof subnet);
+}
+
+/* Enter a new subnet into the subnet hash. */
+
+void enter_subnet (subnet)
+       struct subnet *subnet;
+{
+       add_hash (subnet_hash, (char *)&subnet -> net,
+                 sizeof subnet -> net, (unsigned char *)subnet);
+}
+       
+/* Enter a lease into the system.   This is called by the parser each
+   time it reads in a new lease.   If the subnet for that lease has
+   already been read in (usually the case), just update that lease;
+   otherwise, allocate temporary storage for the lease and keep it around
+   until we're done reading in the config file. */
+
+void enter_lease (lease)
+       struct lease *lease;
+{
+       struct lease *comp = find_lease_by_ip_addr (lease -> ip_addr);
+
+       /* If we don't have a place for this lease yet, save it for
+          later. */
+       if (!comp) {
+               comp = new_lease ("enter_lease");
+               if (!comp) {
+                       error ("No memory for lease %s\n",
+                              inet_ntoa (lease -> ip_addr));
+               }
+               *comp = *lease;
+               lease -> next = dangling_leases;
+               lease -> prev = (struct lease *)0;
+               dangling_leases = lease;
+       } else {
+               supersede_lease (comp, lease);
+       }
+}
+
+/* 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. */
+
+void supersede_lease (comp, lease)
+       struct lease *comp, *lease;
+{
+       int enter_uid = 0;
+       int enter_hwaddr = 0;
+       struct subnet *parent;
+       struct lease *lp;
+
+       /* If the existing lease hasn't expired and has a different
+          unique identifier or, if it doesn't have a unique
+          identifier, a different hardware address, then the two
+          leases are in conflict. */
+       if (comp -> ends > cur_time &&
+           ((comp -> 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",
+                     inet_ntoa (comp -> ip_addr));
+       } else {
+               /* If there's a Unique ID, dissociate it from the hash
+                  table if necessary, and always free it. */
+               if (comp -> uid) {
+                       if (comp -> uid_len != lease -> uid_len ||
+                           memcmp (comp -> uid, lease -> uid,
+                                   comp -> uid_len)) {
+                               delete_hash_entry (lease_uid_hash,
+                                                  comp -> uid,
+                                                  comp -> uid_len);
+                               enter_uid = 1;
+                       }
+                       free (comp -> uid);
+               }
+               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)) {
+                       delete_hash_entry (lease_hw_addr_hash,
+                                          comp -> hardware_addr.haddr,
+                                          comp -> hardware_addr.hlen);
+                       enter_hwaddr = 1;
+               }
+
+               /* Copy the data files, but not the linkages. */
+               comp -> starts = lease -> starts;
+               comp -> ends = lease -> ends;
+               comp -> timestamp = lease -> timestamp;
+               comp -> uid = lease -> uid;
+               comp -> uid_len = lease -> uid_len;
+               comp -> host = lease -> host;
+               comp -> hardware_addr = lease -> hardware_addr;
+               comp -> state = lease -> state;
+
+               /* Record the lease in the uid hash if necessary. */
+               if (enter_uid && lease -> uid) {
+                       add_hash (lease_uid_hash, lease -> uid,
+                                 lease -> uid_len, (unsigned char *)lease);
+               }
+
+               /* Record it in the hardware address hash if necessary. */
+               if (enter_hwaddr && lease -> hardware_addr.htype) {
+                       add_hash (lease_hw_addr_hash,
+                                 lease -> hardware_addr.haddr,
+                                 lease -> hardware_addr.hlen,
+                                 (unsigned char *)lease);
+               }
+
+               /* Remove the lease from its current place in the list. */
+               if (comp -> prev) {
+                       comp -> prev -> next = comp -> next;
+               } else {
+                       comp -> contain -> leases = comp -> next;
+               }
+               if (comp -> next) {
+                       comp -> next -> prev = comp -> prev;
+               }
+
+               /* Find the last insertion point... */
+               if (comp == comp -> contain -> insertion_point ||
+                   !comp -> contain -> insertion_point) {
+                       lp = comp -> contain -> leases;
+               } else {
+                       lp = comp -> contain -> insertion_point;
+               }
+
+               if (!lp) {
+                       /* Nothing on the list yet?    Just make comp the
+                          head of the list. */
+                       comp -> contain -> leases = comp;
+               } else if (lp -> ends <= comp -> ends) {
+                       /* Skip down the list until we run out of list
+                          or find a place for comp. */
+                       while (lp -> next && lp -> ends < comp -> ends) {
+                               lp = lp -> next;
+                       }
+                       if (lp -> ends < comp -> ends) {
+                               /* If we ran out of list, put comp
+                                  at the end. */
+                               lp -> next = comp;
+                               comp -> prev = lp;
+                               comp -> next = (struct lease *)0;
+                       } else {
+                               /* If we didn't, put it between lp and
+                                  the previous item on the list. */
+                               comp -> prev = lp -> prev;
+                               comp -> prev -> next = comp;
+                               comp -> next = lp;
+                               lp -> prev = comp;
+                       }
+               } else {
+                       /* Skip ip the list until we run out of list
+                          or find a place for comp. */
+                       while (lp -> prev && lp -> ends > comp -> ends) {
+                               lp = lp -> prev;
+                       }
+                       if (lp -> ends > comp -> ends) {
+                               /* If we ran out of list, put comp
+                                  at the beginning. */
+                               lp -> prev = comp;
+                               comp -> next = lp;
+                               comp -> prev = (struct lease *)0;
+                               comp -> contain -> leases = comp;
+                       } else {
+                               /* If we didn't, put it between lp and
+                                  the next item on the list. */
+                               comp -> next = lp -> next;
+                               comp -> next -> prev = comp;
+                               comp -> prev = lp;
+                               lp -> next = comp;
+                       }
+               }
+               comp -> contain -> insertion_point = comp;
+       }
+}
diff --git a/options.c b/options.c
new file mode 100644 (file)
index 0000000..2a63279
--- /dev/null
+++ b/options.c
@@ -0,0 +1,556 @@
+/* options.c
+
+   DHCP options parsing and reassembly. */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#define DHCP_OPTION_DATA
+#include "dhcpd.h"
+
+/* Parse all available options out of the specified packet. */
+
+void parse_options (packet)
+       struct packet *packet;
+{
+       /* Initially, zero all option pointers. */
+       memset (packet -> options, 0, sizeof (packet -> options));
+
+       /* If we don't see the magic cookie, there's nothing to parse. */
+       if (memcmp (packet -> raw -> options, DHCP_OPTIONS_COOKIE, 4)) {
+               packet -> options_valid = 0;
+               return;
+       }
+
+       /* Go through the options field, up to the end of the packet
+          or the End field. */
+       parse_option_buffer (packet, &packet -> raw -> options [4],
+                            packet -> packet_length - DHCP_FIXED_LEN);
+       /* If we parsed a DHCP Option Overload option, parse more
+          options out of the buffer(s) containing them. */
+       if (packet -> options_valid
+           && packet -> options [DHO_DHCP_OPTION_OVERLOAD].data) {
+               if (packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 1)
+                       parse_option_buffer (packet,
+                                            packet -> raw -> file,
+                                            sizeof packet -> raw -> file);
+               if (packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 2)
+                       parse_option_buffer (packet,
+                                            packet -> raw -> sname,
+                                            sizeof packet -> raw -> sname);
+       }
+}
+
+/* Parse options out of the specified buffer, storing addresses of option
+   values in packet -> options and setting packet -> options_valid if no
+   errors are encountered. */
+
+void parse_option_buffer (packet, buffer, length)
+       struct packet *packet;
+       unsigned char *buffer;
+       int length;
+{
+       unsigned char *s, *t;
+       unsigned char *end = buffer + length;
+       int len;
+       int code;
+
+       for (s = buffer; *s != DHO_END && s < end; ) {
+               code = s [0];
+               /* Pad options don't have a length - just skip them. */
+               if (code == DHO_PAD) {
+                       ++s;
+                       continue;
+               }
+               /* All other fields (except end, see above) have a
+                  one-byte length. */
+               len = s [1];
+               /* If the length is outrageous, the options are bad. */
+               if (s + len + 2 > end) {
+                       warn ("Option %s length %d overflows input buffer.",
+                             dhcp_options [code].name,
+                             len);
+                       packet -> options_valid = 0;
+                       return;
+               }
+               /* If we haven't seen this option before, just make
+                  space for it and copy it there. */
+               if (!packet -> options [code].data) {
+                       if (!(t = (unsigned char *)malloc (len + 1)))
+                               error ("Can't allocate storage for option %s.",
+                                      dhcp_options [code].name);
+                       /* Copy and NUL-terminate the option (in case it's an
+                          ASCII string. */
+                       memcpy (t, &s [2], len);
+                       t [len] = 0;
+                       packet -> options [code].len = len;
+                       packet -> options [code].data = t;
+               } else {
+                       /* If it's a repeat, concatenate it to whatever
+                          we last saw.   This is really only required
+                          for clients, but what the heck... */
+                       t = (unsigned char *)
+                               malloc (len + packet -> options [code].len);
+                       if (!t)
+                               error ("Can't expand storage for option %s.",
+                                      dhcp_options [code].name);
+                       memcpy (t, packet -> options [code].data,
+                               packet -> options [code].len);
+                       memcpy (t + packet -> options [code].len,
+                               &s [2], len);
+                       packet -> options [code].len += len;
+                       t [packet -> options [code].len] = 0;
+                       free (packet -> options [code].data);
+                       packet -> options [code].data = t;
+               }
+               s += len + 2;
+       }
+       packet -> options_valid = 1;
+}
+
+/* Cons up options based on client-supplied desired option list (if any)
+   and selected server option list. */
+
+void cons_options (inpacket, outpacket, hp, overload)
+       struct packet *inpacket;
+       struct dhcp_packet *outpacket;
+       struct host_decl *hp;
+       int overload;   /* Overload flags that may be set. */
+{
+       option_mask options_have;       /* Options we can send. */
+       option_mask options_want;       /* Options client wants. */
+       option_mask options_done;       /* Options we've already encoded. */
+       option_mask temp;               /* Working option mask. */
+       unsigned char *priority_list;
+       int priority_len;
+       unsigned char *buffer = inpacket -> raw -> options;
+       int buflen, bufix;
+       int reserved = 3;               /* Reserved space for overload. */
+       unsigned char *overload_ptr = (unsigned char *)0;
+       int stored_length [256];
+       int missed = 0;
+       int missed_code;
+       int missed_length;
+       int result;
+       int i;
+
+       /* If there's no place to overload with options, don't save space
+          for an overload option. */
+       if (!overload)
+               reserved = 0;
+
+       /* Zero out the stored-lengths array. */
+       memset (stored_length, 0, sizeof stored_length);
+
+       /* If the client has provided a maximum DHCP message size,
+          use that.   Otherwise, we use the default MTU size (576 bytes). */
+       /* XXX Maybe it would be safe to assume that we can send a packet
+          to the client that's as big as the one it sent us, even if it
+          didn't specify a large MTU. */
+       if (inpacket -> options [DHO_DHCP_MAX_MESSAGE_SIZE].data)
+               buflen = (getUShort (inpacket -> options
+                                    [DHO_DHCP_MAX_MESSAGE_SIZE].data)
+                         - DHCP_FIXED_LEN);
+       else
+               buflen = 576 - DHCP_FIXED_LEN;
+
+       /* If the client has provided a list of options that it wishes
+          returned, use it to prioritize. */
+       if (inpacket -> options [DHO_DHCP_PARAMETER_REQUEST_LIST].data) {
+               priority_list =
+                       inpacket -> options
+                               [DHO_DHCP_PARAMETER_REQUEST_LIST].data;
+               priority_len =
+                       inpacket -> options
+                               [DHO_DHCP_PARAMETER_REQUEST_LIST].len;
+       } else {
+       /* Otherwise, prioritize based on the default priority list. */
+               priority_list = dhcp_option_default_priority_list;
+               priority_len = sizeof_dhcp_option_default_priority_list;
+       }
+
+       /* Make a bitmask of all the options the client wants. */
+       OPTION_ZERO (options_want);
+       for (i = 0; i < priority_len; i++)
+               OPTION_SET (options_want, priority_list [i]);
+
+       /* Make a bitmask of all the options we have available. */
+       OPTION_ZERO (options_have);
+       for (i = 0; i < 256; i++)
+               if (hp -> options [i])
+                       OPTION_SET (options_have, i);
+       
+      again:
+       /* Try copying out options that fit easily. */
+       for (i = 0; i < priority_len; i++) {
+               /* Code for next option to try to store. */
+               int code = priority_list [i];
+
+               /* Number of bytes left to store (some may already
+                  have been stored by a previous pass). */
+               int length;
+
+               /* If no data is available for this option, skip it. */
+               if (!hp -> options [code])
+                       continue;
+
+               /* Don't look at options that have already been stored. */
+               if (OPTION_ISSET (options_done, code))
+                       continue;
+
+               /* Find the value of the option... */
+               if (!tree_evaluate (hp -> options [code]))
+                       continue;
+
+               /* We should now have a constant length for the option. */
+               length = (hp -> options [code] -> len - stored_length [code]);
+
+               /* If there's no space for this option, skip it. */
+               if ((bufix + OPTION_SPACE (length) + reserved) > buflen) {
+                       /* If this is the first missed option, remember it. */
+                       if (++missed == 1) {
+                               missed_code = code;
+                               missed_length = length;
+                       }
+                       continue;
+               }
+               
+               /* Otherwise, store the option. */
+               result = store_option (outpacket, code,
+                                      buffer + bufix,
+                                      buflen - bufix - reserved,
+                                      stored_length);
+               bufix += result;
+
+               /* The following test should always succeed because of
+                  preconditioning above. */
+               if (stored_length [code] == hp -> options [code] -> len)
+                       OPTION_SET (options_done, code);
+               else {
+                       warn ("%s: Only stored %d out of %d bytes.",
+                             dhcp_options [code].name,
+                             stored_length [code],
+                             hp -> options [code] -> len);
+                       if (++missed == 1) {
+                               missed_code = code;
+                               missed_length = hp -> options [code] -> len
+                                       - stored_length [code];
+                       }
+               }
+       }
+
+       /* If we didn't miss any options, we're done. */
+       /* XXX Maybe we want to try to encode options the client didn't
+          request but that we have available? */
+       if (!missed)
+               return;
+
+       /* If we did miss one or more options, they must not have fit.
+          It's possible, though, that there's only one option left to
+          store, and that it would fit if we weren't reserving space
+          for the overload option.   In that case, we want to avoid
+          overloading. */
+       if (reserved && missed == 1
+           && (bufix + OPTION_SPACE (missed_length) <= buflen)) {
+               result = store_option (outpacket, missed_code,
+                                      buffer + bufix, buflen - bufix,
+                                      stored_length);
+               bufix += result;
+               /* This test should always fail -- we'll send bad
+                  data if it doesn't. */
+               if (stored_length [missed_code]
+                   == hp -> options [missed_code] -> len) {
+                       OPTION_SET (options_done, missed_code);
+               } else {
+                       warn ("%s (last): Only stored %d out of %d bytes.",
+                             dhcp_options [missed_code].name,
+                             stored_length [missed_code],
+                             hp -> options [missed_code] -> len);
+               }
+               return;
+       }
+
+       /* We've crammed in all the options that completely fit in
+          the current buffer, but maybe we can fit part of the next
+          option into the current buffer and part into the next. */
+       if (bufix + OPTION_SPACE (missed_length) + reserved
+           < buflen + (overload & 1 ? 128 : 0) + (overload & 2 ? 64 : 0)) {
+               result = store_option (outpacket, missed_code,
+                                      buffer + bufix,
+                                      buflen - bufix - reserved,
+                                      stored_length);
+               bufix += result;
+
+               /* This test should never fail. */
+               if (stored_length [missed_code]
+                   == hp -> options [missed_code] -> len) {
+                       OPTION_SET (options_done, missed_code);
+                       warn ("%s: Unexpected completed store.",
+                             dhcp_options [missed_code].name);
+               }
+       }
+
+       /* Okay, nothing else is going to fit in the current buffer
+          except possibly the override option.   Store that. */
+       if (reserved) {
+               buffer [bufix++] = DHO_DHCP_OPTION_OVERLOAD;
+               buffer [bufix++] = 1;
+               overload_ptr = buffer + bufix;
+               buffer [bufix++] = 0;
+               /* If there's space, store an End option code. */
+               if (bufix < buflen)
+                       buffer [bufix++] = DHO_END;
+               /* If there's still space, pad it. */
+               while (bufix < buflen)
+                       buffer [bufix++] = DHO_PAD;
+       }
+           
+       /* If we've fallen through to here, we still have options to
+          store, and may be able to overload options into the file
+          and server name fields of the DHCP packet. */
+
+       /* We should have stored an overload option by now if we're
+          going to need it, so if this test fails, there's a programming
+          error somewhere above. */
+       if (overload && !overload_ptr) {
+               warn ("Need to overload, but didn't store overload option!");
+               return;
+       }
+
+       /* Can we use the file buffer? */
+       if (overload & 1) {
+               buffer = inpacket -> raw -> file;
+               buflen = sizeof inpacket -> raw -> file;
+               bufix = 0;
+               overload &= ~1;
+               goto again;
+       }
+       /* Can we use the sname buffer? */
+       if (overload & 2) {
+               buffer = inpacket -> raw -> sname;
+               buflen = sizeof inpacket -> raw -> sname;
+               bufix = 0;
+               overload &= ~2;
+               goto again;
+       }
+
+       warn ("Insufficient packet space for all options.");
+}
+
+/* Copy the option data specified by code from the packet structure's
+   option array into an option buffer specified by buf and buflen,
+   updating stored_length[code] to reflect the amount of code's option
+   data that has been stored so far.   Return 1 if all the option data
+   has been stored. */
+   
+int store_option (packet, code, buffer, buflen, stored_length)
+       struct packet *packet;
+       unsigned char code;
+       unsigned char *buffer;
+       int buflen;
+       int *stored_length;
+{
+       int length = packet -> options [code].len - stored_length [code];
+       int bufix = 0;
+       int rv = 1;
+       if (length > buflen) {
+               rv = 0;
+               length = buflen;
+       }
+
+       /* If the option's length is more than 255, we must store it
+          in multiple hunks.   Store 255-byte hunks first. */
+       /* XXX Might a client lose its cookies if options aren't
+          chunked out so that each chunk is aligned to the size
+          of the data being represented? */
+       while (length) {
+               unsigned char incr = length > 255 ? 255 : length;
+               buffer [bufix] = code;
+               buffer [bufix + 1] = incr;
+               memcpy (buffer + bufix + 2, (packet -> options [code].data
+                                            + stored_length [code]), incr);
+               length -= incr;
+               stored_length [code] += incr;
+               bufix += 2 + incr;
+       }
+       return rv;
+}
+
+/* Format the specified option so that a human can easily read it. */
+
+char *pretty_print_option (code, data, len)
+       unsigned char code;
+       unsigned char *data;
+       int len;
+{
+       static char optbuf [32768]; /* XXX */
+       int hunksize = 0;
+       int numhunk = -1;
+       int numelem = 0;
+       char fmtbuf [32];
+       int i, j;
+       char *op = optbuf;
+       unsigned char *dp = data;
+       struct in_addr foo;
+
+       /* Figure out the size of the data. */
+       for (i = 0; dhcp_options [code].format [i]; i++) {
+               if (!numhunk) {
+                       warn ("%s: Excess information in format string: %s\n",
+                             dhcp_options [code].name,
+                             &(dhcp_options [code].format [i]));
+                       break;
+               }
+               numelem++;
+               fmtbuf [i] = dhcp_options [code].format [i];
+               switch (dhcp_options [code].format [i]) {
+                     case 'A':
+                       --numelem;
+                       fmtbuf [i] = 0;
+                       numhunk = 0;
+                       break;
+                     case 't':
+                       fmtbuf [i] = 't';
+                       fmtbuf [i + 1] = 0;
+                       numhunk = -2;
+                       break;
+                     case 'I':
+                     case 'l':
+                     case 'L':
+                       hunksize += 4;
+                       break;
+                     case 's':
+                     case 'S':
+                       hunksize += 2;
+                       break;
+                     case 'b':
+                     case 'B':
+                     case 'f':
+                       hunksize++;
+                       break;
+                     case 'e':
+                       break;
+                     default:
+                       warn ("%s: garbage in format string: %s\n",
+                             dhcp_options [code].name,
+                             &(dhcp_options [code].format [i]));
+                       break;
+               } 
+       }
+
+       /* Check for too few bytes... */
+       if (hunksize > len) {
+               warn ("%s: expecting at least %d bytes; got %d",
+                     dhcp_options [code].name,
+                     hunksize, len);
+               return "<error>";
+       }
+       /* Check for too many bytes... */
+       if (numhunk == -1 && hunksize < len)
+               warn ("%s: %d extra bytes",
+                     dhcp_options [code].name,
+                     len - hunksize);
+
+       /* If this is an array, compute its size. */
+       if (!numhunk)
+               numhunk = len / hunksize;
+       /* See if we got an exact number of hunks. */
+       if (numhunk > 0 && numhunk * hunksize < len)
+               warn ("%s: %d extra bytes at end of array\n",
+                     dhcp_options [code].name,
+                     len - numhunk * hunksize);
+
+       /* A one-hunk array prints the same as a single hunk. */
+       if (numhunk < 0)
+               numhunk = 1;
+
+printf ("numhunk = %d  numelem = %d\n", numhunk, numelem);
+       /* Cycle through the array (or hunk) printing the data. */
+       for (i = 0; i < numhunk; i++) {
+               for (j = 0; j < numelem; j++) {
+                       switch (fmtbuf [j]) {
+                             case 't':
+                               strcpy (op, dp);
+                               break;
+                             case 'I':
+                               foo.s_addr = htonl (getULong (dp));
+                               strcpy (op, inet_ntoa (foo));
+                               dp += 4;
+                               break;
+                             case 'l':
+                               sprintf (op, "%ld", getLong (dp));
+                               dp += 4;
+                               break;
+                             case 'L':
+                               sprintf (op, "%ld", getULong (dp));
+                               dp += 4;
+                               break;
+                             case 's':
+                               sprintf (op, "%d", getShort (dp));
+                               dp += 2;
+                               break;
+                             case 'S':
+                               sprintf (op, "%d", getUShort (dp));
+                               dp += 2;
+                               break;
+                             case 'b':
+                               sprintf (op, "%d", *(char *)dp++);
+                               break;
+                             case 'B':
+                               sprintf (op, "%d", *dp++);
+                               break;
+                             case 'f':
+                               strcpy (op, *dp++ ? "true" : "false");
+                               break;
+                             default:
+                               warn ("Unexpected format code %c", fmtbuf [j]);
+                       }
+                       op += strlen (op);
+                       *op++ = ' ';
+               }
+       }
+       *--op = 0;
+       return optbuf;
+}
+
+                       
+               
diff --git a/osdep.h b/osdep.h
new file mode 100644 (file)
index 0000000..1ff4e68
--- /dev/null
+++ b/osdep.h
@@ -0,0 +1,50 @@
+/* osdep.h
+
+   Operating system dependencies... */
+
+/*
+ * Copyright (c) 1995 RadioMail Corporation.  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 RadioMail Corporation 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 RADIOMAIL CORPORATION 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
+ * RADIOMAIL CORPORATION 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 was written for RadioMail Corporation by Ted Lemon
+ * under a contract with Vixie Enterprises, and is based on an earlier
+ * design by Paul Vixie.
+ */
+
+#ifdef sun
+#include "cf/sunos4.h"
+#endif
+
+#ifdef bsdi
+#include "cf/bsdos.h"
+#endif
+
+#ifdef __NetBSD__
+#include "cf/netbsd.h"
+#endif
+
diff --git a/print.c b/print.c
new file mode 100644 (file)
index 0000000..85e79fc
--- /dev/null
+++ b/print.c
@@ -0,0 +1,65 @@
+/* print.c
+
+   Turn data structures into printable text. */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+char *print_hw_addr (htype, hlen, data)
+       int htype;
+       int hlen;
+       unsigned char *data;
+{
+       static char habuf [49];
+       char *s;
+       int i;
+
+       s = habuf;
+       for (i = 0; i < hlen; i++) {
+               sprintf (s, "%x", data [i]);
+               s += strlen (s);
+               *s++ = ':';
+       }
+       *--s = 0;
+       return habuf;
+}
+
diff --git a/server/bootp.c b/server/bootp.c
new file mode 100644 (file)
index 0000000..6f5d1a5
--- /dev/null
@@ -0,0 +1,147 @@
+/* bootp.c
+
+   BOOTP Protocol support. */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+void bootp (packet)
+       struct packet *packet;
+{
+       int result;
+       struct host_decl *hp = find_host_by_addr (packet -> raw -> htype,
+                                                 packet -> raw -> chaddr,
+                                                 packet -> raw -> hlen);
+       struct dhcp_packet *reply;
+       struct sockaddr_in to;
+
+       /* If the packet is from a host we don't know, drop it on
+          the floor. XXX */
+       if (!hp) {
+               note ("Can't find record for BOOTP host %s",
+                     print_hw_addr (packet -> raw -> htype,
+                                    packet -> raw -> hlen,
+                                    packet -> raw -> chaddr));
+               return;
+       }
+       /* If we don't have a fixed address for it, drop it on the floor.
+          XXX */
+       if (!hp -> fixed_addr || !tree_evaluate (hp -> fixed_addr)) {
+               note ("No fixed address for BOOTP host %s (%s)",
+                     print_hw_addr (packet -> raw -> htype,
+                                    packet -> raw -> hlen,
+                                    packet -> raw -> chaddr),
+                     hp -> name);
+               return;
+       }
+       reply = new_dhcp_packet ("bootp");
+       if (!reply) {
+               free_dhcp_packet (packet -> raw, "bootp");
+               free_packet (packet, "bootp");
+               return;
+       }
+       /* Take the fields that we care about... */
+       reply -> op = BOOTREPLY;
+       reply -> htype = packet -> raw -> htype;
+       reply -> hlen = packet -> raw -> hlen;
+       memcpy (reply -> chaddr, packet -> raw -> chaddr, reply -> hlen);
+       memset (&reply -> chaddr [reply -> hlen], 0,
+               (sizeof reply -> chaddr) - reply -> hlen);
+       reply -> hops = packet -> raw -> hops;
+       reply -> xid = packet -> raw -> xid;
+       reply -> secs = packet -> raw -> secs;
+       reply -> flags = 0;
+       reply -> ciaddr = packet -> raw -> ciaddr;
+       if (!tree_evaluate (hp -> fixed_addr))
+               warn ("tree_evaluate failed.");
+       debug ("fixed_addr: %x %d %d %d %d %x",
+              *(int *)(hp -> fixed_addr -> value), hp -> fixed_addr -> len,
+              hp -> fixed_addr -> buf_size, hp -> fixed_addr -> timeout,
+              hp -> fixed_addr -> tree);
+       memcpy (&reply -> yiaddr, hp -> fixed_addr -> value,
+               sizeof reply -> yiaddr);
+       reply -> siaddr.s_addr = pick_interface (packet);
+       reply -> giaddr = packet -> raw -> giaddr;
+       if (hp -> server_name) {
+               strncpy (reply -> sname, hp -> server_name,
+                        (sizeof reply -> sname) - 1);
+               reply -> sname [(sizeof reply -> sname) - 1] = 0;
+       }
+       if (hp -> filename) {
+               strncpy (reply -> file, hp -> filename,
+                        (sizeof reply -> file) - 1);
+               reply -> file [(sizeof reply -> file) - 1] = 0;
+       }
+       reply -> options [0] = 0;
+       /* XXX gateways? */
+       to.sin_port = server_port;
+
+#if 0
+       if (packet -> raw -> flags & BOOTP_BROADCAST)
+#endif
+               to.sin_addr.s_addr = INADDR_BROADCAST;
+#if 0
+       else
+               to.sin_addr.s_addr = INADDR_ANY;
+#endif
+
+       memset (reply -> options, 0, sizeof (reply -> options));
+       /* If we got the magic cookie, send it back. */
+       if (packet -> options_valid)
+               memcpy (reply -> options, packet -> raw -> options, 4);
+       to.sin_port = packet -> client.sin_port;
+       to.sin_family = AF_INET;
+       to.sin_len = sizeof to;
+       memset (to.sin_zero, 0, sizeof to.sin_zero);
+
+       note ("Sending bootp reply to %s, port %d",
+             inet_ntoa (to.sin_addr), htons (to.sin_port));
+
+       errno = 0;
+       result = sendto (packet -> client_sock, reply,
+                        ((char *)(&reply -> options) - (char *)reply) + 64,
+                        0, (struct sockaddr *)&to, sizeof to);
+       if (result < 0)
+               warn ("sendto: %m");
+}
diff --git a/server/confpars.c b/server/confpars.c
new file mode 100644 (file)
index 0000000..05de625
--- /dev/null
@@ -0,0 +1,1048 @@
+/* confpars.c
+
+   Parser for dhcpd config file... */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+#include "dhctoken.h"
+
+static TIME parsed_time;
+
+/* conf-file :== statements
+   declarations :== <nil> | declaration | declarations declaration */
+
+void readconf (void)
+{
+       FILE *cfile;
+       char *val;
+       int token;
+
+       /* Set up the initial dhcp option universe. */
+       initialize_universes ();
+
+       if ((cfile = fopen (_PATH_DHCPD_CONF, "r")) == NULL)
+               error ("Can't open %s: %m", _PATH_DHCPD_CONF);
+       do {
+               token = peek_token (&val, cfile);
+               if (token == EOF)
+                       break;
+               parse_statement (cfile);
+       } while (1);
+}
+
+/* statement :== host_statement */
+
+void parse_statement (cfile)
+       FILE *cfile;
+{
+       char *val;
+       jmp_buf bc;
+
+       switch (next_token (&val, cfile)) {
+             case HOST:
+               if (!setjmp (bc)) {
+                       struct host_decl *hd =
+                               parse_host_statement (cfile, &bc);
+                       if (hd) {
+                               enter_host (hd);
+                       }
+               }
+               break;
+             case LEASE:
+               if (!setjmp (bc)) {
+                       struct lease *lease =
+                               parse_lease_statement (cfile, &bc);
+                       enter_lease (lease);
+               }
+               break;
+             case TIMESTAMP:
+               if (!setjmp (bc)) {
+                       parsed_time = parse_timestamp (cfile, &bc);
+               }
+               break;
+             case RANGE:
+               if (!setjmp (bc)) {
+                       parse_address_range (cfile, &bc);
+               }
+               break;
+             default:
+               parse_warn ("expecting a declaration.");
+               skip_to_semi (cfile);
+               break;
+       }
+}
+
+void skip_to_semi (cfile)
+       FILE *cfile;
+{
+       int token;
+       char *val;
+
+       do {
+               token = next_token (&val, cfile);
+       } while (token != SEMI && token != EOF);
+}
+
+/* host_statement :== HOST hostname declarations SEMI
+   host_declarations :== <nil> | host_declaration
+                              | host_declarations host_declaration */
+
+struct host_decl *parse_host_statement (cfile, bc)
+       FILE *cfile;
+       jmp_buf *bc;
+{
+       char *val;
+       int token;
+       struct host_decl tmp, *perm;
+
+       memset (&tmp, 0, sizeof tmp);
+       tmp.name = parse_host_name (cfile, bc);
+       do {
+               token = peek_token (&val, cfile);
+               if (token == SEMI) {
+                       token = next_token (&val, cfile);
+                       break;
+               }
+               parse_host_decl (cfile, bc, &tmp);
+       } while (1);
+       perm = (struct host_decl *)malloc (sizeof (struct host_decl));
+       if (!perm)
+               error ("can't allocate host decl struct for %s.", tmp.name);
+       *perm = tmp;
+       return perm;
+}
+
+/* host_name :== identifier | host_name DOT identifier */
+
+char *parse_host_name (cfile, bc)
+       FILE *cfile;
+       jmp_buf *bc;
+{
+       char *val;
+       int token;
+       int len = 0;
+       char *s;
+       char *t;
+       pair c = (pair)0;
+       
+       /* Read a dotted hostname... */
+       do {
+               /* Read a token, which should be an identifier. */
+               token = next_token (&val, cfile);
+               if (!is_identifier (token)) {
+                       parse_warn ("expecting an identified in hostname");
+                       skip_to_semi (cfile);
+                       longjmp (*bc, 1);
+               }
+               /* Store this identifier... */
+               if (!(s = (char *)malloc (strlen (val) + 1)))
+                       error ("can't allocate temp space for hostname.");
+               strcpy (s, val);
+               c = cons ((caddr_t)s, c);
+               len += strlen (s) + 1;
+               /* Look for a dot; if it's there, keep going, otherwise
+                  we're done. */
+               token = peek_token (&val, cfile);
+               if (token == DOT)
+                       token = next_token (&val, cfile);
+       } while (token == DOT);
+
+       /* Assemble the hostname together into a string. */
+       if (!(s = (char *)malloc (len)))
+               error ("can't allocate space for hostname.");
+       t = s + len;
+       *--t = 0;
+       while (c) {
+               pair cdr = c -> cdr;
+               int l = strlen ((char *)(c -> car));
+               t -= l;
+               memcpy (t, (char *)(c -> car), l);
+               /* Free up temp space. */
+               free (c -> car);
+               free (c);
+               c = cdr;
+               if (t != s)
+                       *--t = '.';
+       }
+       return s;
+}
+
+/* host_declaration :== hardware_declaration | filename_declaration
+                     | fixed_addr_declaration | option_declaration */
+
+void parse_host_decl (cfile, bc, decl)
+       FILE *cfile;
+       jmp_buf *bc;
+       struct host_decl *decl;
+{
+       char *val;
+       int token;
+
+       token = next_token (&val, cfile);
+       switch (token) {
+             case HARDWARE:
+               parse_hardware_decl (cfile, bc, decl);
+               break;
+             case FILENAME:
+               parse_filename_decl (cfile, bc, decl);
+               break;
+             case FIXED_ADDR:
+               parse_fixed_addr_decl (cfile, bc, decl);
+               break;
+             case OPTION:
+               parse_option_decl (cfile, bc, decl);
+               break;
+             default:
+               parse_warn ("expecting a dhcp option declaration.");
+               skip_to_semi (cfile);
+               longjmp (*bc, 1);
+               break;
+       }
+}
+
+/* hardware_decl :== HARDWARE ETHERNET NUMBER COLON NUMBER COLON NUMBER COLON
+                                      NUMBER COLON NUMBER COLON NUMBER */
+
+void parse_hardware_decl (cfile, bc, decl)
+       FILE *cfile;
+       jmp_buf *bc;
+       struct host_decl *decl;
+{
+       char *val;
+       int token;
+       struct hardware hw;
+
+       hw = parse_hardware_addr (cfile, bc);
+
+       /* Find space for the new interface... */
+       if (decl -> interfaces) {
+               decl -> interfaces =
+                       (struct hardware *)realloc (decl -> interfaces,
+                                                   ++decl -> interface_count *
+                                                   sizeof (struct hardware));
+       } else {
+               decl -> interfaces =
+                       (struct hardware *)malloc (sizeof (struct hardware));
+               decl -> interface_count = 1;
+       }
+       if (!decl -> interfaces)
+               error ("no memory for hardware interface info.");
+
+       /* Copy out the information... */
+       decl -> interfaces [decl -> interface_count - 1].htype = hw.htype;
+       decl -> interfaces [decl -> interface_count - 1].hlen = hw.hlen;
+       memcpy (decl -> interfaces [decl -> interface_count - 1].haddr,
+               &hw.haddr, hw.hlen);
+}
+
+struct hardware parse_hardware_addr (cfile, bc)
+       FILE *cfile;
+       jmp_buf *bc;
+{
+       char *val;
+       int token;
+       int hlen;
+       struct hardware rv;
+
+       token = next_token (&val, cfile);
+       switch (token) {
+             case ETHERNET:
+               rv.htype = ARPHRD_ETHER;
+               hlen = 6;
+               parse_numeric_aggregate (cfile, bc,
+                                        (unsigned char *)&rv.haddr, &hlen,
+                                        COLON, 16, 8);
+               rv.hlen = hlen;
+               break;
+             default:
+               parse_warn ("expecting a network hardware type");
+               skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       return rv;
+}
+
+/* filename_decl :== FILENAME STRING */
+
+void parse_filename_decl (cfile, bc, decl)
+       FILE *cfile;
+       jmp_buf *bc;
+       struct host_decl *decl;
+{
+       char *val;
+       int token;
+       char *s;
+
+       token = next_token (&val, cfile);
+       if (token != STRING) {
+               parse_warn ("filename must be a string");
+               skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       s = (char *)malloc (strlen (val));
+       if (!s)
+               error ("no memory for filename.");
+       strcpy (s, val);
+       decl -> filename = s;
+}
+
+/* ip_addr_or_hostname :== ip_address | hostname
+   ip_address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
+   
+   Parse an ip address or a hostname.   If uniform is zero, put in
+   a TREE_LIMIT node to catch hostnames that evaluate to more than
+   one IP address. */
+
+struct tree *parse_ip_addr_or_hostname (cfile, bc, uniform)
+       FILE *cfile;
+       jmp_buf *bc;
+       int uniform;
+{
+       char *val;
+       int token;
+       unsigned char addr [4];
+       int len = sizeof addr;
+       char *name;
+       struct tree *rv;
+
+       token = peek_token (&val, cfile);
+       if (is_identifier (token)) {
+               name = parse_host_name (cfile, bc);
+               rv = tree_host_lookup (name);
+               if (!uniform)
+                       rv = tree_limit (rv, 4);
+       } else if (token == NUMBER) {
+               parse_numeric_aggregate (cfile, bc, addr, &len, DOT, 10, 8);
+               rv = tree_const (addr, len);
+       } else {
+               parse_warn ("%s (%d): expecting IP address or hostname",
+                           val, token);
+               skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       return rv;
+}      
+       
+
+/* fixed_addr_declaration :== FIXED_ADDR ip_addr_or_hostname */
+
+void parse_fixed_addr_decl (cfile, bc, decl)
+       FILE *cfile;
+       jmp_buf *bc;
+       struct host_decl *decl;
+{
+       decl -> fixed_addr =
+               tree_cache (parse_ip_addr_or_hostname (cfile, bc, 0));
+}
+
+/* option_declaration :== OPTION identifier DOT identifier <syntax> |
+                         OPTION identifier <syntax>
+
+   Option syntax is handled specially through format strings, so it
+   would be painful to come up with BNF for it.   However, it always
+   starts as above. */
+
+void parse_option_decl (cfile, bc, decl)
+       FILE *cfile;
+       jmp_buf *bc;
+       struct host_decl *decl;
+{
+       char *val;
+       int token;
+       unsigned char buf [4];
+       char *vendor;
+       char *fmt;
+       struct universe *universe;
+       struct option *option;
+       struct tree *tree = (struct tree *)0;
+
+       token = next_token (&val, cfile);
+       if (!is_identifier (token)) {
+               parse_warn ("expecting identifier after option keyword.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       vendor = dmalloc (strlen (val) + 1, "parse_option_decl");
+       strcpy (vendor, val);
+       token = peek_token (&val, cfile);
+       if (token == DOT) {
+               /* Go ahead and take the DOT token... */
+               token = next_token (&val, cfile);
+
+               /* The next token should be an identifier... */
+               token = next_token (&val, cfile);
+               if (!is_identifier (token)) {
+                       parse_warn ("expecting identifier after '.'");
+                       if (token != SEMI)
+                               skip_to_semi (cfile);
+                       longjmp (*bc, 1);
+               }
+
+               /* Look up the option name hash table for the specified
+                  vendor. */
+               universe = (struct universe *)hash_lookup (&universe_hash,
+                                                          vendor, 0);
+               /* If it's not there, we can't parse the rest of the
+                  statement. */
+               if (!universe) {
+                       parse_warn ("no vendor named %s.", vendor);
+                       skip_to_semi (cfile);
+                       longjmp (*bc, 1);
+               }
+       } else {
+               /* Use the default hash table, which contains all the
+                  standard dhcp option names. */
+               val = vendor;
+               universe = &dhcp_universe;
+       }
+
+       /* Look up the actual option info... */
+       option = (struct option *)hash_lookup (universe -> hash, val, 0);
+
+       /* If we didn't get an option structure, it's an undefined option. */
+       if (!option) {
+               if (val == vendor)
+                       parse_warn ("no option named %s", val);
+               else
+                       parse_warn ("no option named %s for vendor %s",
+                                   val, vendor);
+               skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+
+       /* Free the initial identifier token. */
+       free (vendor);
+
+       /* Parse the option data... */
+       do {
+               /* Set a flag if this is an array of a simple type (i.e.,
+                  not an array of pairs of IP addresses, or something
+                  like that. */
+               int uniform = option -> format [1] == 'A';
+
+               for (fmt = option -> format; *fmt; fmt++) {
+                       if (*fmt == 'A')
+                               break;
+                       switch (*fmt) {
+                             case 't': /* Text string... */
+                               token = next_token (&val, cfile);
+                               if (token != STRING
+                                   && !is_identifier (token)) {
+                                       parse_warn ("expecting string.");
+                                       if (token != SEMI)
+                                               skip_to_semi (cfile);
+                                       longjmp (*bc, 1);
+                               }
+                               tree = tree_concat (tree,
+                                                   tree_const (val,
+                                                               strlen (val)));
+                               break;
+
+                             case 'I': /* IP address or hostname. */
+                               tree = tree_concat (tree,
+                                                   parse_ip_addr_or_hostname
+                                                   (cfile, bc, uniform));
+                               break;
+
+                             case 'L': /* Unsigned 32-bit integer... */
+                             case 'l': /* Signed 32-bit integer... */
+                               token = next_token (&val, cfile);
+                               if (token != NUMBER) {
+                                     need_number:
+                                       parse_warn ("expecting number.");
+                                       if (token != SEMI)
+                                               skip_to_semi (cfile);
+                                       longjmp (*bc, 1);
+                               }
+                               convert_num (buf, val, 0, 32);
+                               tree = tree_concat (tree, tree_const (buf, 4));
+                               break;
+                             case 's': /* Signed 16-bit integer. */
+                             case 'S': /* Unsigned 16-bit integer. */
+                               token = next_token (&val, cfile);
+                               if (token != NUMBER)
+                                       goto need_number;
+                               convert_num (buf, val, 0, 16);
+                               tree = tree_concat (tree, tree_const (buf, 2));
+                               break;
+                             case 'b': /* Signed 8-bit integer. */
+                             case 'B': /* Unsigned 8-bit integer. */
+                               token = next_token (&val, cfile);
+                               if (token != NUMBER)
+                                       goto need_number;
+                               convert_num (buf, val, 0, 8);
+                               tree = tree_concat (tree, tree_const (buf, 1));
+                               break;
+                             case 'f': /* Boolean flag. */
+                               token = next_token (&val, cfile);
+                               if (!is_identifier (token)) {
+                                       parse_warn ("expecting identifier.");
+                                     bad_flag:
+                                       if (token != SEMI)
+                                               skip_to_semi (cfile);
+                                       longjmp (*bc, 1);
+                               }
+                               if (!strcasecmp (val, "true")
+                                   || !strcasecmp (val, "on"))
+                                       buf [0] = 1;
+                               else if (!strcasecmp (val, "false")
+                                        || !strcasecmp (val, "off"))
+                                       buf [0] = 0;
+                               else {
+                                       parse_warn ("expecting boolean.");
+                                       goto bad_flag;
+                               }
+                               tree = tree_concat (tree, tree_const (buf, 1));
+                               break;
+                             default:
+                               warn ("Bad format %c in parse_option_decl.",
+                                     *fmt);
+                               skip_to_semi (cfile);
+                               longjmp (*bc, 1);
+                       }
+               }
+               if (*fmt == 'A') {
+                       token = peek_token (&val, cfile);
+                       if (token == COMMA) {
+                               token = next_token (&val, cfile);
+                               continue;
+                       }
+                       break;
+               }
+       } while (*fmt == 'A');
+
+       if (decl -> options [option -> code]) {
+               parse_warn ("duplicate option code %d (%s).",
+                           option -> code, option -> name);
+       }
+       decl -> options [option -> code] = tree_cache (tree);
+}
+
+/* timestamp :== TIMESTAMP date
+
+   Timestamps are actually not used in dhcpd.conf, which is a static file,
+   but rather in the database file and the journal file. */
+
+TIME parse_timestamp (cfile, bc)
+       FILE *cfile;
+       jmp_buf *bc;
+{
+       return parse_date (cfile, bc);
+}
+               
+/* lease_decl :== LEASE ip_address lease_modifiers
+   lease_modifiers :== <nil>
+               |       lease_modifier
+               |       lease_modifier lease_modifiers
+   lease_modifier :==  STARTS date
+               |       ENDS date
+               |       UID hex_numbers
+               |       HOST identifier
+               |       CLASS identifier
+               |       TIMESTAMP number */
+
+struct lease *parse_lease_statement (cfile, bc)
+       FILE *cfile;
+       jmp_buf *bc;
+{
+       char *val;
+       int token;
+       unsigned char addr [4];
+       int len = sizeof addr;
+       char *name;
+       unsigned char *uid;
+       int seenmask = 0;
+       int seenbit;
+       char tbuf [32];
+       char ubuf [1024];
+       static struct lease lease;
+
+       /* Get the address for which the lease has been issued. */
+       parse_numeric_aggregate (cfile, bc, addr, &len, DOT, 10, 8);
+       memcpy (&lease.ip_addr, addr, len);
+
+       do {
+               token = next_token (&val, cfile);
+               if (token == SEMI)
+                       break;
+               strncpy (val, tbuf, sizeof tbuf);
+               tbuf [(sizeof tbuf) - 1] = 0;
+
+               /* Parse any of the times associated with the lease. */
+               if (token == STARTS || token == ENDS || token == TIMESTAMP) {
+                       TIME t;
+                       t = parse_date (cfile, bc);
+                       switch (token) {
+                             case STARTS:
+                               seenbit = 1;
+                               lease.starts = t;
+                               break;
+                       
+                             case ENDS:
+                               seenbit = 2;
+                               lease.ends = t;
+                               break;
+                               
+                             case TIMESTAMP:
+                               seenbit = 4;
+                               lease.timestamp = t;
+                               break;
+                       }
+               } else {
+                       switch (token) {
+                               /* Colon-seperated hexadecimal octets... */
+                             case UID:
+                               seenbit = 8;
+                               lease.uid_len = 0;
+                               parse_numeric_aggregate (cfile, bc, ubuf,
+                                                        &lease.uid_len,
+                                                        ':', 16, 8);
+                               lease.uid = (unsigned char *)
+                                       malloc (lease.uid_len);
+                               if (!lease.uid) {
+                                       error ("No memory for lease uid");
+                               }
+                               memcpy (lease.uid, ubuf, lease.uid_len);
+                               break;
+
+                             case HOST:
+                               seenbit = 16;
+                               token = next_token (&val, cfile);
+                               if (!is_identifier (token)) {
+                                       if (token != SEMI)
+                                               skip_to_semi (cfile);
+                                       longjmp (*bc, 1);
+                               }
+                               lease.host =
+                                       find_host_by_name (val);
+                               if (!lease.host)
+                                       parse_warn ("lease host ``%s'' is %s",
+                                                   lease.host,
+                                                   "no longer known.");
+                               break;
+                                       
+                             case CLASS:
+                               seenbit = 32;
+                               token = next_token (&val, cfile);
+                               if (!is_identifier (token)) {
+                                       if (token != SEMI)
+                                               skip_to_semi (cfile);
+                                       longjmp (*bc, 1);
+                               }
+                               /* for now, we aren't using this. */
+                               break;
+
+                             case HARDWARE:
+                               seenbit = 64;
+                               lease.hardware_addr
+                                       = parse_hardware_addr (cfile, bc);
+                               break;
+
+                             default:
+                               if (token != SEMI)
+                                       skip_to_semi (cfile);
+                               longjmp (*bc, 1);
+                       }
+               }
+               if (seenmask & seenbit) {
+                       parse_warn ("Too many %s declarations in lease %s\n",
+                                   tbuf, inet_ntoa (lease.ip_addr));
+               } else
+                       seenmask |= seenbit;
+       } while (1);
+       return &lease;
+}
+
+/* address_range :== RANGE ip_address ip_address ip_address */
+
+void parse_address_range (cfile, bc)
+       FILE *cfile;
+       jmp_buf *bc;
+{
+       struct in_addr low, high, mask;
+       unsigned char addr [4];
+       int len = sizeof addr;
+
+       /* Get the bottom address in the range... */
+       parse_numeric_aggregate (cfile, bc, addr, &len, DOT, 10, 8);
+       memcpy (&low, addr, len);
+
+       /* Get the top address in the range... */
+       parse_numeric_aggregate (cfile, bc, addr, &len, DOT, 10, 8);
+       memcpy (&high, addr, len);
+
+       /* Get the netmask of the subnet containing the range... */
+       parse_numeric_aggregate (cfile, bc, addr, &len, DOT, 10, 8);
+       memcpy (&mask, addr, len);
+
+       /* Create the new address range... */
+       new_address_range (low, high, mask);
+}
+
+/* date :== NUMBER NUMBER/NUMBER/NUMBER NUMBER:NUMBER:NUMBER
+
+   Dates are always in GMT; first number is day of week; next is
+   year/month/day; next is hours:minutes:seconds on a 24-hour
+   clock. */
+
+TIME parse_date (cfile, bc)
+       FILE *cfile;
+       jmp_buf *bc;
+{
+       TIME t;
+       struct tm tm;
+       char *val;
+       int token;
+
+       /* Day of week... */
+       token = next_token (&val, cfile);
+       if (token != NUMBER) {
+               parse_warn ("numeric day of week expected.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       tm.tm_wday = atoi (token);
+
+       /* Year... */
+       token = next_token (&val, cfile);
+       if (token != NUMBER) {
+               parse_warn ("numeric year expected.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       tm.tm_year = atoi (token);
+       if (tm.tm_year > 1900)
+               tm.tm_year -= 1900;
+
+       /* Slash seperating year from month... */
+       token = next_token (&val, cfile);
+       if (token != SLASH) {
+               parse_warn ("expected slash seperating year from month.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+
+       /* Month... */
+       token = next_token (&val, cfile);
+       if (token != NUMBER) {
+               parse_warn ("numeric month expected.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       tm.tm_mon = atoi (token);
+
+       /* Slash seperating month from day... */
+       token = next_token (&val, cfile);
+       if (token != SLASH) {
+               parse_warn ("expected slash seperating month from day.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+
+       /* Month... */
+       token = next_token (&val, cfile);
+       if (token != NUMBER) {
+               parse_warn ("numeric day of month expected.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       tm.tm_mday = atoi (token);
+
+       /* Hour... */
+       token = next_token (&val, cfile);
+       if (token != NUMBER) {
+               parse_warn ("numeric hour expected.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       tm.tm_hour = atoi (token);
+
+       /* Colon seperating hour from minute... */
+       token = next_token (&val, cfile);
+       if (token != COLON) {
+               parse_warn ("expected colon seperating hour from minute.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+
+       /* Minute... */
+       token = next_token (&val, cfile);
+       if (token != NUMBER) {
+               parse_warn ("numeric minute expected.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       tm.tm_min = atoi (token);
+
+       /* Colon seperating minute from second... */
+       token = next_token (&val, cfile);
+       if (token != COLON) {
+               parse_warn ("expected colon seperating hour from minute.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+
+       /* Minute... */
+       token = next_token (&val, cfile);
+       if (token != NUMBER) {
+               parse_warn ("numeric minute expected.");
+               if (token != SEMI)
+                       skip_to_semi (cfile);
+               longjmp (*bc, 1);
+       }
+       tm.tm_sec = atoi (token);
+
+       tm.tm_zone = "GMT";
+       tm.tm_isdst = 0;
+       tm.tm_gmtoff = 0;
+
+       /* XXX */ /* We assume that mktime does not use tm_yday. */
+       tm.tm_yday = 0;
+
+       return mktime (&tm);
+}
+
+/* No BNF for numeric aggregates - that's defined by the caller.  What
+   this function does is to parse a sequence of numbers seperated by
+   the token specified in seperator.  If max is zero, any number of
+   numbers will be parsed; otherwise, exactly max numbers are
+   expected.  Base and size tell us how to internalize the numbers
+   once they've been tokenized. */
+
+unsigned char *parse_numeric_aggregate (cfile, bc, buf,
+                                       max, seperator, base, size)
+       FILE *cfile;
+       jmp_buf *bc;
+       unsigned char *buf;
+       int *max;
+       int seperator;
+       int base;
+       int size;
+{
+       char *val;
+       int token;
+       unsigned char *bufp = buf, *s, *t;
+       int count = 0;
+       pair c = (pair)0;
+
+       if (!bufp && *max) {
+               bufp = (unsigned char *)malloc (*max * size / 8);
+               if (!bufp)
+                       error ("can't allocate space for numeric aggregate");
+       } else
+               s = bufp;
+
+       do {
+               if (count) {
+                       token = peek_token (&val, cfile);
+                       if (token != seperator) {
+                               if (!*max)
+                                       break;
+                               parse_warn ("too few numbers.");
+                               skip_to_semi (cfile);
+                               longjmp (*bc, 1);
+                       }
+                       token = next_token (&val, cfile);
+               }
+               token = next_token (&val, cfile);
+               /* Allow NUMBER_OR_ATOM if base is 16. */
+               if (token != NUMBER &&
+                   (base != 16 || token != NUMBER_OR_ATOM)) {
+                       parse_warn ("expecting numeric value.");
+                       skip_to_semi (cfile);
+                       longjmp (*bc, 1);
+               }
+               /* If we can, convert the number now; otherwise, build
+                  a linked list of all the numbers. */
+               if (s) {
+                       convert_num (s, val, base, size);
+                       s += size / 8;
+               } else {
+                       t = (char *)malloc (strlen (val) + 1);
+                       if (!t)
+                               error ("no temp space for number.");
+                       strcpy (t, val);
+                       c = cons (t, c);
+               }
+       } while (++count != *max);
+
+       /* If we had to cons up a list, convert it now. */
+       if (c) {
+               bufp = (unsigned char *)malloc (count * size / 8);
+               if (!bufp)
+                       error ("can't allocate space for numeric aggregate.");
+               s = bufp;
+               *max = count;
+       }
+       while (c) {
+               pair cdr = c -> cdr;
+               convert_num (s, (char *)(c -> car), base, size);
+               s += size / 8;
+               /* Free up temp space. */
+               free (c -> car);
+               free (c);
+               c = cdr;
+       }
+       return bufp;
+}
+
+void convert_num (buf, str, base, size)
+       unsigned char *buf;
+       char *str;
+       int base;
+       int size;
+{
+       char *ptr = str;
+       int negative = 0;
+       u_int32_t val = 0;
+       int tval;
+       int max;
+
+       if (*ptr == '-') {
+               negative = 1;
+               ++ptr;
+       }
+
+       /* If base wasn't specified, figure it out from the data. */
+       if (!base) {
+               if (ptr [0] == '0') {
+                       if (ptr [1] == 'x') {
+                               base = 16;
+                               ptr += 2;
+                       } else if (isascii (ptr [1]) && isdigit (ptr [1])) {
+                               base = 8;
+                               ptr += 1;
+                       } else {
+                               base = 10;
+                       }
+               } else {
+                       base = 10;
+               }
+       }
+
+       do {
+               tval = *ptr++;
+               /* XXX assumes ASCII... */
+               if (tval >= 'a')
+                       tval = tval - 'a' + 10;
+               else if (tval >= 'A')
+                       tval = tval - 'A' + 10;
+               else if (tval >= '0')
+                       tval -= '0';
+               else {
+                       warn ("Bogus number: %s.", str);
+                       break;
+               }
+               if (tval >= base) {
+                       warn ("Bogus number: %s: digit %d not in base %d\n",
+                             str, tval, base);
+                       break;
+               }
+               val = val * base + tval;
+       } while (*ptr);
+
+       if (negative)
+               max = (1 << (size - 1));
+       else
+               max = (1 << size) - 1;
+       if (val > max) {
+               switch (base) {
+                     case 8:
+                       warn ("value %s%lo exceeds max (%d) for precision.",
+                             negative ? "-" : "", val, max);
+                       break;
+                     case 16:
+                       warn ("value %s%lx exceeds max (%d) for precision.",
+                             negative ? "-" : "", val, max);
+                       break;
+                     default:
+                       warn ("value %s%ld exceeds max (%d) for precision.",
+                             negative ? "-" : "", val, max);
+                       break;
+               }
+       }
+
+       if (negative) {
+               switch (size) {
+                     case 8:
+                       *buf = -(unsigned long)val;
+                       break;
+                     case 16:
+                       putShort (buf, -(unsigned long)val);
+                       break;
+                     case 32:
+                       putLong (buf, -(unsigned long)val);
+                       break;
+                     default:
+                       warn ("Unexpected integer size: %d\n");
+                       break;
+               }
+       } else {
+               switch (size) {
+                     case 8:
+                       *buf = (u_int8_t)val;
+                       break;
+                     case 16:
+                       putUShort (buf, (u_int16_t)val);
+                       break;
+                     case 32:
+                       putULong (buf, val);
+                       break;
+                     default:
+                       warn ("Unexpected integer size: %d\n");
+                       break;
+               }
+       }
+}
diff --git a/server/db.c b/server/db.c
new file mode 100644 (file)
index 0000000..66f47b3
--- /dev/null
@@ -0,0 +1,142 @@
+/* db.c
+
+   IP Address Allocation database... */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+/*
+   The IP Address Allocation Database tracks addresses that have been
+   allocated from the free pool as specified in dhcpd.conf.   The
+   database is maintained in two parts to maintain integrity: the
+   journal file and the data file.
+
+   Both files are free-form flat files similar to dhcpd.conf, but with
+   a more limited syntax - all that can be specified are leases and
+   who they belong to.
+
+   When dhcpd starts up, it reads the entire data file into memory.
+   It then reads the journal file into memory and makes corrections to
+   the data based on journal entries.
+
+   While dhcpd is running, it periodically records the current time,
+   forks (if possible) and dumps the recorded time and its internal
+   database of temporarily assigned addresses into a temporary file.
+   It then removes any existing backup file, renames the existing file
+   with the backup filename, and then renames the new temporary file
+   with the real data file name.  The link syscall is not present on
+   most systems, so a synchronous ``rename'' that guarantees that
+   exactly one file will be the master database may not be possible.
+   Therefore the recovery routine needs to know what to do if it finds
+   a backup and a temporary file, but no database file.
+
+   Whenever a client requests that an address be allocated to it, or
+   requests a lease renewal, and the server is able to satisfy the
+   request, it writes a record into the journal file indicating what
+   has been requested and waits for that information to reach the
+   disk.  Once the file's dirty buffers have been flushed, the server
+   responds to the request, and logs another record in the journal
+   indicating that it has done so.
+
+   Entries in the journal file are logged along with the time at which
+   the logging occurred.  When the server forks to dump the database,
+   it records the current time before forking.  The copy of the server
+   that writes out the database records the time read prior to forking
+   in the new data file.  The copy of the server that continues to
+   serve DHCP requests ensures that any journal entries subsequent to
+   the fork have time stamps that are greater than the time read
+   before forking.  When recovering from a crash, the server discards
+   any entries in the journal which have time stamps earlier than the
+   time stamp on the data file.
+
+   When recovering from a crash, dhcpd may find a journal entry for a
+   request, but no entry indicating that it was satisfied.  There is
+   no automatic way to recover from this, since the server may have
+   sent out a response, so in this case the server must notify
+   sysadmin of the problem and leave it to them to solve it.
+
+   In addition to the actual data files, we also keep a running log of
+   ``interesting'' events, which we mail to the dhcp-admin alias every
+   morning at 7:00 AM.  This log can be tailed by paranoid sysadmins
+   or in times of network trouble. */
+
+/* Initialize the internal database, perform crash recovery as needed. */
+
+void dbinit ()
+{
+       FILE *dbfile;
+
+       /* We are assuming that on entry, there is no other dhcpd
+          running on this machine.  If there were, there would be the
+          potential for serious database corruption.  The main code
+          currently assures that there is only one server running by
+          listening on the bootps port with INADDR_ANY.  Unices that
+          I'm familiar with will only allow one process to do this,
+          even if the SO_REUSEADDR option is set.   'twouldn't surprise
+          me terribly, though, if this didn't work for some other
+          operating system.   Beware.   XXX */
+
+       /* Look for a file under the official database name.
+          Failing that, look for a file under the backup name.
+          If we find neither, we assume that the database is empty. */
+
+       if ((dbfile = fopen (_PATH_DHCP_DB, "r")) != NULL
+           (dbfile = fopen (_PATH_DHCP_DB_BACKUP, "r") != NULL)) {
+
+               /* Read in the data file, making a list of assigned
+                  addresses that have been removed from dhcpd.conf. */
+
+       }
+
+       /* Open the journal file and read through any entries which
+           are out of date. */
+
+       /* Now read entries that postdate the last database sync,
+          keeping track of incomplete entries (when we're done, there
+          should never be more than one such entry. */
+
+       /* Now expire any leases that have lapsed since we last ran. */
+
+       /* ...and we're done... */
+}
diff --git a/server/dhcp.c b/server/dhcp.c
new file mode 100644 (file)
index 0000000..9f8946d
--- /dev/null
@@ -0,0 +1,52 @@
+/* dhcp.c
+
+   DHCP Protocol support. */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+void dhcp (packet)
+       struct packet *packet;
+{
+}
diff --git a/server/dhcpd.c b/server/dhcpd.c
new file mode 100644 (file)
index 0000000..b2687e6
--- /dev/null
@@ -0,0 +1,256 @@
+/* dhcpd.c
+
+   DHCP Server Daemon. */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+static void usage PROTO ((void));
+
+TIME cur_time;
+
+u_int32_t *server_addrlist;
+int server_addrcount;
+u_int16_t server_port;
+
+int main (argc, argv, envp)
+       int argc;
+       char **argv, **envp;
+{
+       struct in_addr addr;
+       int port = 0;
+       int i;
+       struct sockaddr_in name;
+       u_int32_t *addrlist = (u_int32_t *)0;
+       int addrcount = 0;
+       struct tree *addrtree = (struct tree *)0;
+       struct servent *ent;
+       int sock;
+       int pid;
+       int result;
+       int flag;
+
+       openlog ("dhcpd", LOG_NDELAY, LOG_DAEMON);
+#ifndef DEBUG
+       setlogmask (LOG_UPTO (LOG_INFO));
+
+       /* Become a daemon... */
+       if ((pid = fork ()) < 0)
+               error ("Can't fork daemon: %m");
+       else if (pid)
+               exit (0);
+       /* Become session leader and get pid... */
+       pid = setsid ();
+#endif 
+       for (i = 1; i < argc; i++) {
+               if (!strcmp (argv [i], "-p")) {
+                       if (++i == argc)
+                               usage ();
+                       server_port = htons (atoi (argv [i]));
+                       debug ("binding to user-specified port %d\n",
+                              ntohs (server_port));
+#if 0
+               } else if (!strcmp (argv [i], "-a")) {
+                       if (++i == argc)
+                               usage ();
+                       if (inet_aton (argv [i], &addr)) {
+                               addrtree =
+                                       tree_concat (addrtree,
+                                                    tree_const
+                                                    ((unsigned char *)&addr,
+                                                     sizeof addr));
+                       } else {
+                               addrtree = tree_concat (addrtree,
+                                                       tree_host_lookup
+                                                       (argv [i]));
+                       }
+#endif
+               } else
+                       usage ();
+       }
+
+       /* Default to the DHCP/BOOTP port. */
+       if (!server_port)
+       {
+               ent = getservbyname ("dhcp", "udp");
+               if (!ent)
+                       server_port = htons (67);
+               else
+                       server_port = ent -> s_port;
+               endservent ();
+       }
+  
+       /* Get the current time... */
+       GET_TIME (&cur_time);
+
+       /* Read the dhcpd.conf file... */
+       readconf ();
+
+#if 0
+       /* If addresses were specified on the command line, resolve them;
+          otherwise, just get a list of the addresses that are configured
+          on this host and listen on all of them. */
+       if (addrtree) {
+               tree_evaluate ((unsigned char **)&addrlist,
+                              &addrcount, addrtree);
+               addrcount /= 4;
+               if (!addrcount)
+                       error ("Server addresses resolve to nothing.");
+       } else {
+/*             addrlist = get_interface_list (&addrcount); */
+#endif
+               addr.s_addr = 0;
+               addrlist = (u_int32_t *)&(addr.s_addr);
+               addrcount = 1;
+#if 0
+       }
+#endif
+
+       server_addrlist = get_interface_list (&server_addrcount);
+
+       /* Listen on the specified (or default) port on each specified
+          (or default) IP address. */
+       for (i = 0; i < addrcount; i++) {
+               listen_on (server_port, addrlist [i]);
+       }
+
+       /* Write a pid file. */
+       if ((i = open (_PATH_DHCPD_PID, O_WRONLY | O_CREAT)) >= 0) {
+               char obuf [20];
+               sprintf (obuf, "%d\n", getpid ());
+               write (i, obuf, strlen (obuf));
+               close (i);
+       }
+
+       /* Receive packets and dispatch them... */
+       dispatch ();
+}
+
+/* Print usage message. */
+
+static void usage ()
+{
+       error ("Usage: dhcpd [-p <port>] [-a <ip-addr>]");
+}
+
+void cleanup ()
+{
+}
+
+void do_packet (packbuf, len, from, fromlen, sock)
+       unsigned char *packbuf;
+       int len;
+       struct sockaddr_in *from;
+       int fromlen;
+       int sock;
+{
+       struct packet *tp;
+       struct dhcp_packet *tdp;
+
+       if (!(tp = new_packet ("do_packet")))
+               return;
+       if (!(tdp = new_dhcp_packet ("do_packet"))) {
+               free_packet (tp, "do_packet");
+               return;
+       }
+       memcpy (tdp, packbuf, len);
+       memset (tp, 0, sizeof *tp);
+       tp -> raw = tdp;
+       tp -> packet_length = len;
+       tp -> client = *from;
+       tp -> client_len = fromlen;
+       tp -> client_sock = sock;
+       parse_options (tp);
+       if (tp -> options_valid &&
+           tp -> options [DHO_DHCP_MESSAGE_TYPE].data)
+               dhcp (tp);
+       else
+               bootp (tp);
+}
+
+dump_packet (tp)
+       struct packet *tp;
+{
+       struct dhcp_packet *tdp = tp -> raw;
+
+       debug ("op = %d  htype = %d  hlen = %d  hops = %d",
+              tdp -> op, tdp -> htype, tdp -> hlen, tdp -> hops);
+       debug ("xid = %x  secs = %d  flags = %x",
+              tdp -> xid, tdp -> secs, tdp -> flags);
+       debug ("ciaddr = %s  yiaddr = %s",
+              inet_ntoa (tdp -> ciaddr), inet_ntoa (tdp -> yiaddr));
+       debug ("siaddr = %s  giaddr = %s",
+              inet_ntoa (tdp -> siaddr), inet_ntoa (tdp -> giaddr));
+       debug ("chaddr = %02.2x:%02.2x:%02.2x:%02.2x:%02.2x:%02.2x",
+              ((unsigned char *)(tdp -> chaddr)) [0],
+              ((unsigned char *)(tdp -> chaddr)) [1],
+              ((unsigned char *)(tdp -> chaddr)) [2],
+              ((unsigned char *)(tdp -> chaddr)) [3],
+              ((unsigned char *)(tdp -> chaddr)) [4],
+              ((unsigned char *)(tdp -> chaddr)) [5]);
+       if (tp -> options_valid) {
+               int i;
+
+               for (i = 0; i < 256; i++) {
+                       if (tp -> options [i].data)
+                               printf ("  %s = %s\n",
+                                       dhcp_options [i].name,
+                                       pretty_print_option
+                                       (i, tp -> options [i].data,
+                                        tp -> options [i].len));
+               }
+       }
+}
+
+/* Based on the contents of packet, figure out which interface address
+   to use from server_addrlist.   Currently just picks the first
+   interface. */
+
+u_int32_t pick_interface (packet)
+       struct packet *packet;
+{
+       if (server_addrlist)
+               return server_addrlist [0];
+       return 0;
+}
diff --git a/server/dhcpd.conf b/server/dhcpd.conf
new file mode 100644 (file)
index 0000000..36d8f0e
--- /dev/null
@@ -0,0 +1,17 @@
+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";
+
diff --git a/socket.c b/socket.c
new file mode 100644 (file)
index 0000000..1ee6eb7
--- /dev/null
+++ b/socket.c
@@ -0,0 +1,208 @@
+/* socket.c
+
+   BSD socket interface code... */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+#include <sys/ioctl.h>
+
+/* List of sockets we're accepting packets on... */
+struct socklist {
+       struct socklist *next;
+       struct sockaddr_in addr;
+       int sock;
+} *sockets;
+
+/* Return the list of IP addresses associated with each network interface. */
+
+u_int32_t *get_interface_list (count)
+       int *count;
+{
+       u_int32_t *intbuf = (u_int32_t *)0;
+       static char buf [8192];
+       struct ifconf ic;
+       int i;
+       int sock;
+       int ifcount = 0;
+       int ifix = 0;
+
+       /* Create an unbound datagram socket to do the SIOCGIFADDR ioctl on. */
+       if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+               error ("Can't create addrlist socket");
+
+       /* Get the interface configuration information... */
+       ic.ifc_len = sizeof buf;
+       ic.ifc_ifcu.ifcu_buf = (caddr_t)buf;
+       i = ioctl(sock, SIOCGIFCONF, &ic);
+       close (sock);
+       if (i < 0)
+               error ("ioctl: SIOCGIFCONF: %m");
+
+      again:
+       /* Cycle through the list of interfaces looking for IP addresses.
+          Go through twice; once to count the number if addresses, and a
+          second time to copy them into an array of addresses. */
+       for (i = 0; i < ic.ifc_len;) {
+               struct ifreq *ifp = (struct ifreq *)((caddr_t)ic.ifc_req + i);
+               i += (sizeof ifp -> ifr_name) + ifp -> ifr_addr.sa_len;
+               if (ifp -> ifr_addr.sa_family == AF_INET) {
+                       struct sockaddr_in *foo =
+                               (struct sockaddr_in *)(&ifp -> ifr_addr);
+                       /* We don't want the loopback interface. */
+                       if (foo -> sin_addr.s_addr == INADDR_LOOPBACK)
+                               continue;
+                       if (intbuf)
+                               intbuf [ifix++] = foo -> sin_addr.s_addr;
+                       else
+                               ++ifcount;
+               }
+       }
+       /* If we haven't already filled our array, allocate it and go
+          again. */
+       if (!intbuf) {
+               intbuf = (u_int32_t *)dmalloc ((ifcount + 1)
+                                              * sizeof (u_int32_t),
+                                              "get_interface_list");
+               if (!intbuf)
+                       return intbuf;
+               goto again;
+       }
+       *count = ifcount;
+       return intbuf;
+}
+
+void listen_on (port, address)
+       u_int16_t port;
+       u_int32_t address;
+{
+       struct sockaddr_in name;
+       int sock;
+       struct socklist *tmp;
+       int flag;
+
+       name.sin_family = AF_INET;
+       name.sin_port = port;
+       name.sin_addr.s_addr = address;
+       memset (name.sin_zero, 0, sizeof (name.sin_zero));
+
+       /* List addresses on which we're listening. */
+       note ("Receiving on %s, port %d",
+             inet_ntoa (name.sin_addr), htons (name.sin_port));
+       if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+               error ("Can't create dhcp socket: %m");
+
+       flag = 1;
+       if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
+                       &flag, sizeof flag) < 0)
+               error ("Can't set SO_REUSEADDR option on dhcp socket: %m");
+
+       if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST,
+                       &flag, sizeof flag) < 0)
+               error ("Can't set SO_BROADCAST option on dhcp socket: %m");
+
+       if (bind (sock, (struct sockaddr *)&name, sizeof name) < 0)
+               error ("Can't bind to dhcp address: %m");
+
+       tmp = (struct socklist *)dmalloc (sizeof (struct socklist),
+                                         "listen_on");
+       if (!tmp)
+               error ("Can't allocate memory for socket list.");
+       tmp -> addr = name;
+       tmp -> sock = sock;
+       tmp -> next = sockets;
+       sockets = tmp;
+}
+
+unsigned char packbuf [65536]; /* Should cover the gnarliest MTU... */
+
+void dispatch ()
+{
+       struct sockaddr_in from;
+       int fromlen = sizeof from;
+       fd_set r, w, x;
+       struct socklist *l;
+       int max = 0;
+       int count;
+       int result;
+
+       FD_ZERO (&r);
+       FD_ZERO (&w);
+       FD_ZERO (&x);
+
+       do {
+               /* Set up the read mask. */
+               for (l = sockets; l; l = l -> next) {
+                       FD_SET (l -> sock, &r);
+                       FD_SET (l -> sock, &x);
+                       if (l -> sock > max)
+                               max = l -> sock;
+               }
+
+               /* Wait for a packet or a timeout... XXX */
+               count = select (max + 1, &r, &w, &x, (struct timeval *)0);
+
+               /* Not likely to be transitory... */
+               if (count < 0)
+                       error ("select: %m");
+
+               for (l = sockets; l; l = l -> next) {
+                       if (!FD_ISSET (l -> sock, &r))
+                               continue;
+                       if ((result =
+                            recvfrom (l -> sock, packbuf, sizeof packbuf, 0,
+                                      (struct sockaddr *)&from, &fromlen))
+                           < 0) {
+                               warn ("recvfrom failed on %s: %m",
+                                     inet_ntoa (l -> addr.sin_addr));
+                               sleep (5);
+                               continue;
+                       }
+                       note ("request from %s, port %d",
+                             inet_ntoa (from.sin_addr),
+                             htons (from.sin_port));
+                       do_packet (packbuf, result, &from, fromlen, l -> sock);
+               }
+       } while (1);
+}
+
diff --git a/tables.c b/tables.c
new file mode 100644 (file)
index 0000000..30b1ebd
--- /dev/null
+++ b/tables.c
@@ -0,0 +1,414 @@
+/* tables.c
+
+   Tables of information... */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+/* DHCP Option names, formats and codes, from RFC1533.
+
+   Format codes:
+
+   e - end of data
+   I - IP address
+   l - 32-bit signed integer
+   L - 32-bit unsigned integer
+   s - 16-bit signed integer
+   S - 16-bit unsigned integer
+   b - 8-bit signed integer
+   B - 8-bit unsigned integer
+   t - ASCII text
+   f - flag (true or false)
+   A - array of whatever precedes (e.g., IA means array of IP addresses)
+*/
+
+struct universe dhcp_universe;
+struct option dhcp_options [256] = {
+       "pad", "",                                      &dhcp_universe, 0,
+       "subnet-mask", "I",                             &dhcp_universe, 1,
+       "time-offset", "l",                             &dhcp_universe, 2,
+       "routers", "IA",                                &dhcp_universe, 3,
+       "time-servers", "IA",                           &dhcp_universe, 4,
+       "name-servers", "IA",                           &dhcp_universe, 5,
+       "domain-name-servers", "IA",                    &dhcp_universe, 6,
+       "log-servers", "IA",                            &dhcp_universe, 7,
+       "cookie-servers", "IA",                         &dhcp_universe, 8,
+       "lpr-servers", "IA",                            &dhcp_universe, 9,
+       "impress-servers", "IA",                        &dhcp_universe, 10,
+       "resource-location-servers", "IA",              &dhcp_universe, 11,
+       "host-name", "t",                               &dhcp_universe, 12,
+       "boot-size", "S",                               &dhcp_universe, 13,
+       "merit-dump", "t",                              &dhcp_universe, 14,
+       "domain-name", "t",                             &dhcp_universe, 15,
+       "swap-server", "I",                             &dhcp_universe, 16,
+       "root-path", "t",                               &dhcp_universe, 17,
+       "extensions-path", "t",                         &dhcp_universe, 18,
+       "ip-forwarding", "f",                           &dhcp_universe, 19,
+       "non-local-source-routing", "f",                &dhcp_universe, 20,
+       "policy-filter", "IIA",                         &dhcp_universe, 21,
+       "max-dgram-reassembly", "S",                    &dhcp_universe, 22,
+       "default-ip-ttl", "B",                          &dhcp_universe, 23,
+       "path-mtu-aging-timeout", "L",                  &dhcp_universe, 24,
+       "path-mtu-plateau-table", "SA",                 &dhcp_universe, 25,
+       "interface-mtu", "S",                           &dhcp_universe, 26,
+       "all-subnets-local", "f",                       &dhcp_universe, 27,
+       "broadcast-address", "I",                       &dhcp_universe, 28,
+       "perform-mask-discovery", "f",                  &dhcp_universe, 29,
+       "mask-supplier", "f",                           &dhcp_universe, 30,
+       "router-discovery", "f",                        &dhcp_universe, 31,
+       "router-solicitation-address", "I",             &dhcp_universe, 32,
+       "static-routes", "IIA",                         &dhcp_universe, 33,
+       "trailer-encapsulation", "f",                   &dhcp_universe, 34,
+       "arp-cache-timeout", "L",                       &dhcp_universe, 35,
+       "ieee802.3-encapsulation", "f",                 &dhcp_universe, 36,
+       "default-tcp-ttl", "B",                         &dhcp_universe, 37,
+       "tcp-keepalive-interval", "L",                  &dhcp_universe, 38,
+       "tcp-keepalive-garbage", "f",                   &dhcp_universe, 39,
+       "nis-domain", "t",                              &dhcp_universe, 40,
+       "nis-servers", "IA",                            &dhcp_universe, 41,
+       "ntp-servers", "IA",                            &dhcp_universe, 42,
+       "vendor-encapsulated-options", "t",             &dhcp_universe, 43,
+       "netbios-name-servers", "IA",                   &dhcp_universe, 44,
+       "netbios-dd-server", "IA",                      &dhcp_universe, 45,
+       "netbios-node-type", "B",                       &dhcp_universe, 46,
+       "netbios-scope", "t",                           &dhcp_universe, 47,
+       "font-servers", "IA",                           &dhcp_universe, 48,
+       "x-display-manager", "IA",                      &dhcp_universe, 49,
+       "dhcp-requested-address", "I",                  &dhcp_universe, 50,
+       "dhcp-lease-time", "L",                         &dhcp_universe, 51,
+       "dhcp-option-overload", "B",                    &dhcp_universe, 52,
+       "dhcp-message-type", "B",                       &dhcp_universe, 53,
+       "dhcp-server-identifier", "I",                  &dhcp_universe, 54,
+       "dhcp-parameter-request-list", "BA",            &dhcp_universe, 55,
+       "dhcp-message", "t",                            &dhcp_universe, 56,
+       "dhcp-max-message-size", "S",                   &dhcp_universe, 57,
+       "dhcp-renewal-time", "L",                       &dhcp_universe, 58,
+       "dhcp-rebinding-time", "L",                     &dhcp_universe, 59,
+       "dhcp-class-identifier", "t",                   &dhcp_universe, 60,
+       "dhcp-client-identifier", "t",                  &dhcp_universe, 61,
+       "option-62", "",                                &dhcp_universe, 62,
+       "option-63", "",                                &dhcp_universe, 63,
+       "option-64", "",                                &dhcp_universe, 64,
+       "option-65", "",                                &dhcp_universe, 65,
+       "option-66", "",                                &dhcp_universe, 66,
+       "option-67", "",                                &dhcp_universe, 67,
+       "option-68", "",                                &dhcp_universe, 68,
+       "option-69", "",                                &dhcp_universe, 69,
+       "option-70", "",                                &dhcp_universe, 70,
+       "option-71", "",                                &dhcp_universe, 71,
+       "option-72", "",                                &dhcp_universe, 72,
+       "option-73", "",                                &dhcp_universe, 73,
+       "option-74", "",                                &dhcp_universe, 74,
+       "option-75", "",                                &dhcp_universe, 75,
+       "option-76", "",                                &dhcp_universe, 76,
+       "option-77", "",                                &dhcp_universe, 77,
+       "option-78", "",                                &dhcp_universe, 78,
+       "option-79", "",                                &dhcp_universe, 79,
+       "option-80", "",                                &dhcp_universe, 80,
+       "option-81", "",                                &dhcp_universe, 81,
+       "option-82", "",                                &dhcp_universe, 82,
+       "option-83", "",                                &dhcp_universe, 83,
+       "option-84", "",                                &dhcp_universe, 84,
+       "option-85", "",                                &dhcp_universe, 85,
+       "option-86", "",                                &dhcp_universe, 86,
+       "option-87", "",                                &dhcp_universe, 87,
+       "option-88", "",                                &dhcp_universe, 88,
+       "option-89", "",                                &dhcp_universe, 89,
+       "option-90", "",                                &dhcp_universe, 90,
+       "option-91", "",                                &dhcp_universe, 91,
+       "option-92", "",                                &dhcp_universe, 92,
+       "option-93", "",                                &dhcp_universe, 93,
+       "option-94", "",                                &dhcp_universe, 94,
+       "option-95", "",                                &dhcp_universe, 95,
+       "option-96", "",                                &dhcp_universe, 96,
+       "option-97", "",                                &dhcp_universe, 97,
+       "option-98", "",                                &dhcp_universe, 98,
+       "option-99", "",                                &dhcp_universe, 99,
+       "option-100", "",                               &dhcp_universe, 100,
+       "option-101", "",                               &dhcp_universe, 101,
+       "option-102", "",                               &dhcp_universe, 102,
+       "option-103", "",                               &dhcp_universe, 103,
+       "option-104", "",                               &dhcp_universe, 104,
+       "option-105", "",                               &dhcp_universe, 105,
+       "option-106", "",                               &dhcp_universe, 106,
+       "option-107", "",                               &dhcp_universe, 107,
+       "option-108", "",                               &dhcp_universe, 108,
+       "option-109", "",                               &dhcp_universe, 109,
+       "option-110", "",                               &dhcp_universe, 110,
+       "option-111", "",                               &dhcp_universe, 111,
+       "option-112", "",                               &dhcp_universe, 112,
+       "option-113", "",                               &dhcp_universe, 113,
+       "option-114", "",                               &dhcp_universe, 114,
+       "option-115", "",                               &dhcp_universe, 115,
+       "option-116", "",                               &dhcp_universe, 116,
+       "option-117", "",                               &dhcp_universe, 117,
+       "option-118", "",                               &dhcp_universe, 118,
+       "option-119", "",                               &dhcp_universe, 119,
+       "option-120", "",                               &dhcp_universe, 120,
+       "option-121", "",                               &dhcp_universe, 121,
+       "option-122", "",                               &dhcp_universe, 122,
+       "option-123", "",                               &dhcp_universe, 123,
+       "option-124", "",                               &dhcp_universe, 124,
+       "option-125", "",                               &dhcp_universe, 125,
+       "option-126", "",                               &dhcp_universe, 126,
+       "option-127", "",                               &dhcp_universe, 127,
+       "option-128", "",                               &dhcp_universe, 128,
+       "option-129", "",                               &dhcp_universe, 129,
+       "option-130", "",                               &dhcp_universe, 130,
+       "option-131", "",                               &dhcp_universe, 131,
+       "option-132", "",                               &dhcp_universe, 132,
+       "option-133", "",                               &dhcp_universe, 133,
+       "option-134", "",                               &dhcp_universe, 134,
+       "option-135", "",                               &dhcp_universe, 135,
+       "option-136", "",                               &dhcp_universe, 136,
+       "option-137", "",                               &dhcp_universe, 137,
+       "option-138", "",                               &dhcp_universe, 138,
+       "option-139", "",                               &dhcp_universe, 139,
+       "option-140", "",                               &dhcp_universe, 140,
+       "option-141", "",                               &dhcp_universe, 141,
+       "option-142", "",                               &dhcp_universe, 142,
+       "option-143", "",                               &dhcp_universe, 143,
+       "option-144", "",                               &dhcp_universe, 144,
+       "option-145", "",                               &dhcp_universe, 145,
+       "option-146", "",                               &dhcp_universe, 146,
+       "option-147", "",                               &dhcp_universe, 147,
+       "option-148", "",                               &dhcp_universe, 148,
+       "option-149", "",                               &dhcp_universe, 149,
+       "option-150", "",                               &dhcp_universe, 150,
+       "option-151", "",                               &dhcp_universe, 151,
+       "option-152", "",                               &dhcp_universe, 152,
+       "option-153", "",                               &dhcp_universe, 153,
+       "option-154", "",                               &dhcp_universe, 154,
+       "option-155", "",                               &dhcp_universe, 155,
+       "option-156", "",                               &dhcp_universe, 156,
+       "option-157", "",                               &dhcp_universe, 157,
+       "option-158", "",                               &dhcp_universe, 158,
+       "option-159", "",                               &dhcp_universe, 159,
+       "option-160", "",                               &dhcp_universe, 160,
+       "option-161", "",                               &dhcp_universe, 161,
+       "option-162", "",                               &dhcp_universe, 162,
+       "option-163", "",                               &dhcp_universe, 163,
+       "option-164", "",                               &dhcp_universe, 164,
+       "option-165", "",                               &dhcp_universe, 165,
+       "option-166", "",                               &dhcp_universe, 166,
+       "option-167", "",                               &dhcp_universe, 167,
+       "option-168", "",                               &dhcp_universe, 168,
+       "option-169", "",                               &dhcp_universe, 169,
+       "option-170", "",                               &dhcp_universe, 170,
+       "option-171", "",                               &dhcp_universe, 171,
+       "option-172", "",                               &dhcp_universe, 172,
+       "option-173", "",                               &dhcp_universe, 173,
+       "option-174", "",                               &dhcp_universe, 174,
+       "option-175", "",                               &dhcp_universe, 175,
+       "option-176", "",                               &dhcp_universe, 176,
+       "option-177", "",                               &dhcp_universe, 177,
+       "option-178", "",                               &dhcp_universe, 178,
+       "option-179", "",                               &dhcp_universe, 179,
+       "option-180", "",                               &dhcp_universe, 180,
+       "option-181", "",                               &dhcp_universe, 181,
+       "option-182", "",                               &dhcp_universe, 182,
+       "option-183", "",                               &dhcp_universe, 183,
+       "option-184", "",                               &dhcp_universe, 184,
+       "option-185", "",                               &dhcp_universe, 185,
+       "option-186", "",                               &dhcp_universe, 186,
+       "option-187", "",                               &dhcp_universe, 187,
+       "option-188", "",                               &dhcp_universe, 188,
+       "option-189", "",                               &dhcp_universe, 189,
+       "option-190", "",                               &dhcp_universe, 190,
+       "option-191", "",                               &dhcp_universe, 191,
+       "option-192", "",                               &dhcp_universe, 192,
+       "option-193", "",                               &dhcp_universe, 193,
+       "option-194", "",                               &dhcp_universe, 194,
+       "option-195", "",                               &dhcp_universe, 195,
+       "option-196", "",                               &dhcp_universe, 196,
+       "option-197", "",                               &dhcp_universe, 197,
+       "option-198", "",                               &dhcp_universe, 198,
+       "option-199", "",                               &dhcp_universe, 199,
+       "option-200", "",                               &dhcp_universe, 200,
+       "option-201", "",                               &dhcp_universe, 201,
+       "option-202", "",                               &dhcp_universe, 202,
+       "option-203", "",                               &dhcp_universe, 203,
+       "option-204", "",                               &dhcp_universe, 204,
+       "option-205", "",                               &dhcp_universe, 205,
+       "option-206", "",                               &dhcp_universe, 206,
+       "option-207", "",                               &dhcp_universe, 207,
+       "option-208", "",                               &dhcp_universe, 208,
+       "option-209", "",                               &dhcp_universe, 209,
+       "option-210", "",                               &dhcp_universe, 210,
+       "option-211", "",                               &dhcp_universe, 211,
+       "option-212", "",                               &dhcp_universe, 212,
+       "option-213", "",                               &dhcp_universe, 213,
+       "option-214", "",                               &dhcp_universe, 214,
+       "option-215", "",                               &dhcp_universe, 215,
+       "option-216", "",                               &dhcp_universe, 216,
+       "option-217", "",                               &dhcp_universe, 217,
+       "option-218", "",                               &dhcp_universe, 218,
+       "option-219", "",                               &dhcp_universe, 219,
+       "option-220", "",                               &dhcp_universe, 220,
+       "option-221", "",                               &dhcp_universe, 221,
+       "option-222", "",                               &dhcp_universe, 222,
+       "option-223", "",                               &dhcp_universe, 223,
+       "option-224", "",                               &dhcp_universe, 224,
+       "option-225", "",                               &dhcp_universe, 225,
+       "option-226", "",                               &dhcp_universe, 226,
+       "option-227", "",                               &dhcp_universe, 227,
+       "option-228", "",                               &dhcp_universe, 228,
+       "option-229", "",                               &dhcp_universe, 229,
+       "option-230", "",                               &dhcp_universe, 230,
+       "option-231", "",                               &dhcp_universe, 231,
+       "option-232", "",                               &dhcp_universe, 232,
+       "option-233", "",                               &dhcp_universe, 233,
+       "option-234", "",                               &dhcp_universe, 234,
+       "option-235", "",                               &dhcp_universe, 235,
+       "option-236", "",                               &dhcp_universe, 236,
+       "option-237", "",                               &dhcp_universe, 237,
+       "option-238", "",                               &dhcp_universe, 238,
+       "option-239", "",                               &dhcp_universe, 239,
+       "option-240", "",                               &dhcp_universe, 240,
+       "option-241", "",                               &dhcp_universe, 241,
+       "option-242", "",                               &dhcp_universe, 242,
+       "option-243", "",                               &dhcp_universe, 243,
+       "option-244", "",                               &dhcp_universe, 244,
+       "option-245", "",                               &dhcp_universe, 245,
+       "option-246", "",                               &dhcp_universe, 246,
+       "option-247", "",                               &dhcp_universe, 247,
+       "option-248", "",                               &dhcp_universe, 248,
+       "option-249", "",                               &dhcp_universe, 249,
+       "option-250", "",                               &dhcp_universe, 250,
+       "option-251", "",                               &dhcp_universe, 251,
+       "option-252", "",                               &dhcp_universe, 252,
+       "option-253", "",                               &dhcp_universe, 253,
+       "option-254", "",                               &dhcp_universe, 254,
+       "option-end", "e",                              &dhcp_universe, 255,
+};
+
+/* Default dhcp option priority list (this is ad hoc and should not be
+   mistaken for a carefully crafted and optimized list). */
+unsigned char dhcp_option_default_priority_list [] = {
+       DHO_SUBNET_MASK,
+       DHO_TIME_OFFSET,
+       DHO_ROUTERS,
+       DHO_TIME_SERVERS,
+       DHO_NAME_SERVERS,
+       DHO_DOMAIN_NAME_SERVERS,
+       DHO_LOG_SERVERS,
+       DHO_COOKIE_SERVERS,
+       DHO_LPR_SERVERS,
+       DHO_IMPRESS_SERVERS,
+       DHO_RESOURCE_LOCATION_SERVERS,
+       DHO_HOST_NAME,
+       DHO_BOOT_SIZE,
+       DHO_MERIT_DUMP,
+       DHO_DOMAIN_NAME,
+       DHO_SWAP_SERVER,
+       DHO_ROOT_PATH,
+       DHO_EXTENSIONS_PATH,
+       DHO_IP_FORWARDING,
+       DHO_NON_LOCAL_SOURCE_ROUTING,
+       DHO_POLICY_FILTER,
+       DHO_MAX_DGRAM_REASSEMBLY,
+       DHO_DEFAULT_IP_TTL,
+       DHO_PATH_MTU_AGING_TIMEOUT,
+       DHO_PATH_MTU_PLATEAU_TABLE,
+       DHO_INTERFACE_MTU,
+       DHO_ALL_SUBNETS_LOCAL,
+       DHO_BROADCAST_ADDRESS,
+       DHO_PERFORM_MASK_DISCOVERY,
+       DHO_MASK_SUPPLIER,
+       DHO_ROUTER_DISCOVERY,
+       DHO_ROUTER_SOLICITATION_ADDRESS,
+       DHO_STATIC_ROUTES,
+       DHO_TRAILER_ENCAPSULATION,
+       DHO_ARP_CACHE_TIMEOUT,
+       DHO_IEEE802_3_ENCAPSULATION,
+       DHO_DEFAULT_TCP_TTL,
+       DHO_TCP_KEEPALIVE_INTERVAL,
+       DHO_TCP_KEEPALIVE_GARBAGE,
+       DHO_NIS_DOMAIN,
+       DHO_NIS_SERVERS,
+       DHO_NTP_SERVERS,
+       DHO_VENDOR_ENCAPSULATED_OPTIONS,
+       DHO_NETBIOS_NAME_SERVERS,
+       DHO_NETBIOS_DD_SERVER,
+       DHO_NETBIOS_NODE_TYPE,
+       DHO_NETBIOS_SCOPE,
+       DHO_FONT_SERVERS,
+       DHO_X_DISPLAY_MANAGER,
+       DHO_DHCP_REQUESTED_ADDRESS,
+       DHO_DHCP_LEASE_TIME,
+       DHO_DHCP_OPTION_OVERLOAD,
+       DHO_DHCP_MESSAGE_TYPE,
+       DHO_DHCP_SERVER_IDENTIFIER,
+       DHO_DHCP_PARAMETER_REQUEST_LIST,
+       DHO_DHCP_MESSAGE,
+       DHO_DHCP_MAX_MESSAGE_SIZE,
+       DHO_DHCP_RENEWAL_TIME,
+       DHO_DHCP_REBINDING_TIME,
+       DHO_DHCP_CLASS_IDENTIFIER,
+       DHO_DHCP_CLIENT_IDENTIFIER,
+};
+
+int sizeof_dhcp_option_default_priority_list =
+       sizeof dhcp_option_default_priority_list;
+
+
+struct hash_table universe_hash;
+
+void initialize_universes()
+{
+       int i;
+
+       dhcp_universe.name = "dhcp";
+       dhcp_universe.hash = new_hash ();
+       if (!dhcp_universe.hash)
+               error ("Can't allocate dhcp option hash table.");
+       for (i = 0; i < 256; i++) {
+               dhcp_universe.options [i] = &dhcp_options [i];
+               add_hash (dhcp_universe.hash, dhcp_options [i].name, 0,
+                         (unsigned char *)&dhcp_options [i]);
+       }
+       universe_hash.hash_count = DEFAULT_HASH_SIZE;
+       add_hash (&universe_hash, dhcp_universe.name, 0,
+                 (unsigned char *)&dhcp_universe);
+}
diff --git a/tree.c b/tree.c
new file mode 100644 (file)
index 0000000..3b3e894
--- /dev/null
+++ b/tree.c
@@ -0,0 +1,391 @@
+/* tree.c
+
+   Routines for manipulating parse trees... */
+
+/*
+ * Copyright (c) 1995 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 The Internet Software Consortium.  All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+static TIME tree_evaluate_recurse PROTO ((int *, unsigned char **, int *,
+                                         struct tree *));
+static TIME do_host_lookup PROTO ((int *, unsigned char **, int *,
+                                         struct dns_host_entry *));
+static void do_data_copy PROTO ((int *, unsigned char **, int *,
+                                unsigned char *, int));
+
+pair cons (car, cdr)
+       caddr_t car;
+       pair cdr;
+{
+       pair foo = (pair)dmalloc (sizeof *foo, "cons");
+       if (!foo)
+               error ("no memory for cons.");
+       foo -> car = car;
+       foo -> cdr = cdr;
+       return foo;
+}
+
+struct tree_cache *tree_cache (tree)
+       struct tree *tree;
+{
+       struct tree_cache *tc;
+
+       tc = new_tree_cache ("tree_cache");
+       if (!tc)
+               return 0;
+       tc -> value = (char *)0;
+       tc -> len = tc -> buf_size = 0;
+       tc -> timeout = 0;
+       tc -> tree = tree;
+       return tc;
+}
+
+struct tree *tree_host_lookup (name)
+       char *name;
+{
+       struct tree *nt;
+       nt = new_tree ("tree_host_lookup");
+       if (!nt)
+               error ("No memory for host lookup tree node.");
+       nt -> op = TREE_HOST_LOOKUP;
+       nt -> data.host_lookup.host = enter_dns_host (name);
+       return nt;
+}
+
+struct dns_host_entry *enter_dns_host (name)
+       char *name;
+{
+       struct dns_host_entry *dh;
+
+       if (!(dh = (struct dns_host_entry *)dmalloc
+             (sizeof (struct dns_host_entry), "enter_dns_host"))
+           || !(dh -> hostname = dmalloc (strlen (name) + 1,
+                                          "enter_dns_host")))
+               error ("Can't allocate space for new host.");
+       strcpy (dh -> hostname, name);
+       dh -> data = (unsigned char *)0;
+       dh -> data_len = 0;
+       dh -> timeout = 0;
+       return dh;
+}
+
+struct tree *tree_const (data, len)
+       unsigned char *data;
+       int len;
+{
+       struct tree *nt;
+       if (!(nt = new_tree ("tree_const"))
+           || !(nt -> data.const_val.data =
+                (unsigned char *)dmalloc (len, "tree_const")))
+               error ("No memory for constant data tree node.");
+       nt -> op = TREE_CONST;
+       memcpy (nt -> data.const_val.data, data, len);
+       nt -> data.const_val.len = len;
+       return nt;
+}
+
+struct tree *tree_concat (left, right)
+       struct tree *left, *right;
+{
+       struct tree *nt;
+
+       /* If we're concatenating a null tree to a non-null tree, just
+          return the non-null tree; if both trees are null, return
+          a null tree. */
+       if (!left)
+               return right;
+       if (!right)
+               return left;
+
+       /* If both trees are constant, combine them. */
+       if (left -> op = TREE_CONST && right -> op == TREE_CONST) {
+               unsigned char *buf = dmalloc (left -> data.const_val.len
+                                             + right -> data.const_val.len,
+                                             "tree_concat");
+               if (!buf)
+                       error ("No memory to concatenate constants.");
+               memcpy (buf, left -> data.const_val.data,
+                       left -> data.const_val.len);
+               memcpy (buf + left -> data.const_val.len,
+                       right -> data.const_val.data,
+                       right -> data.const_val.len);
+               dfree (left -> data.const_val.data, "tree_concat");
+               dfree (right -> data.const_val.data, "tree_concat");
+               left -> data.const_val.data = buf;
+               left -> data.const_val.len += right -> data.const_val.len;
+               free_tree (right, "tree_concat");
+               return left;
+       }
+                       
+       /* Otherwise, allocate a new node to concatenate the two. */
+       if (!(nt = new_tree ("tree_concat")))
+               error ("No memory for data tree concatenation node.");
+       nt -> op = TREE_CONCAT;
+       nt -> data.concat.left = left;
+       nt -> data.concat.right = right;
+       return nt;
+}
+
+struct tree *tree_limit (tree, limit)
+       struct tree *tree;
+       int limit;
+{
+       struct tree *rv;
+
+       /* If the tree we're limiting is constant, limit it now. */
+       if (tree -> op == TREE_CONST) {
+               if (tree -> data.const_val.len > limit)
+                       tree -> data.const_val.len = limit;
+               return tree;
+       }
+
+       /* Otherwise, put in a node which enforces the limit on evaluation. */
+       rv = new_tree ("tree_limit");
+       if (!rv)
+               return (struct tree *)0;
+       rv -> op = TREE_LIMIT;
+       rv -> data.limit.tree = tree;
+       rv -> data.limit.limit = limit;
+       return rv;
+}
+
+int tree_evaluate (tree_cache)
+       struct tree_cache *tree_cache;
+{
+       unsigned char *bp = tree_cache -> value;
+       int bc = tree_cache -> buf_size;
+       int bufix = 0;
+
+       /* If there's no tree associated with this cache, it evaluates
+          to a constant and that was detected at startup. */
+       if (!tree_cache -> tree)
+               return 1;
+
+       /* Try to evaluate the tree without allocating more memory... */
+       tree_cache -> timeout = tree_evaluate_recurse (&bufix, &bp, &bc,
+                                                      tree_cache -> tree);
+
+       /* No additional allocation needed? */
+       if (bufix <= bc) {
+               tree_cache -> len = bufix;
+               return 1;
+       }
+
+       /* If we can't allocate more memory, return with what we
+          have (maybe nothing). */
+       if (!(bp = (unsigned char *)dmalloc (bufix, "tree_evaluate")))
+               return 0;
+
+       /* Record the change in conditions... */
+       bc = bufix;
+       bufix = 0;
+
+       /* Note that the size of the result shouldn't change on the
+          second call to tree_evaluate_recurse, since we haven't
+          changed the ``current'' time. */
+       tree_evaluate_recurse (&bufix, &bp, &bc, tree_cache -> tree);
+
+       /* Free the old buffer if needed, then store the new buffer
+          location and size and return. */
+       if (tree_cache -> value)
+               dfree (tree_cache -> value, "tree_evaluate");
+       tree_cache -> value = bp;
+       tree_cache -> len = bufix;
+       tree_cache -> buf_size = bc;
+       return 1;
+}
+
+static TIME tree_evaluate_recurse (bufix, bufp, bufcount, tree)
+       int *bufix;
+       unsigned char **bufp;
+       int *bufcount;
+       struct tree *tree;
+{
+       int limit;
+       TIME t1, t2;
+
+       switch (tree -> op) {
+             case TREE_CONCAT:
+               t1 = tree_evaluate_recurse (bufix, bufp, bufcount,
+                                          tree -> data.concat.left);
+               t2 = tree_evaluate_recurse (bufix, bufp, bufcount,
+                                          tree -> data.concat.right);
+               if (t1 > t2)
+                       return t2;
+               return t1;
+
+             case TREE_HOST_LOOKUP:
+               return do_host_lookup (bufix, bufp, bufcount,
+                                      tree -> data.host_lookup.host);
+
+             case TREE_CONST:
+               do_data_copy (bufix, bufp, bufcount,
+                             tree -> data.const_val.data,
+                             tree -> data.const_val.len);
+               t1 = MAX_TIME;
+               return t1;
+
+             case TREE_LIMIT:
+               limit = *bufix + tree -> data.limit.limit;
+               t1 = tree_evaluate_recurse (bufix, bufp, bufcount,
+                                           tree -> data.limit.tree);
+               *bufix = limit;
+               return t1;
+
+             default:
+               warn ("Bad node id in tree: %d.");
+               t1 = MAX_TIME;
+               return t1;
+       }
+}
+
+static TIME do_host_lookup (bufix, bufp, bufcount, dns)
+       int *bufix;
+       unsigned char **bufp;
+       int *bufcount;
+       struct dns_host_entry *dns;
+{
+       struct hostent *h;
+       int i;
+       int new_len;
+
+       debug ("time: now = %d  dns = %d %d  diff = %d",
+              cur_time, dns -> timeout, cur_time - dns -> timeout);
+
+       /* If the record hasn't timed out, just copy the data and return. */
+       if (cur_time <= dns -> timeout) {
+               debug ("easy copy: %x %d %x",
+                      dns -> data, dns -> data_len, *(int *)(dns -> data));
+               do_data_copy (bufix, bufp, bufcount,
+                             dns -> data, dns -> data_len);
+               return dns -> timeout;
+       }
+       debug ("Looking up %s", dns -> hostname);
+
+       /* Otherwise, look it up... */
+       h = gethostbyname (dns -> hostname);
+       if (!h) {
+               switch (h_errno) {
+                     case HOST_NOT_FOUND:
+                       warn ("%s: host unknown.", dns -> hostname);
+                       break;
+                     case TRY_AGAIN:
+                       warn ("%s: temporary name server failure",
+                             dns -> hostname);
+                       break;
+                     case NO_RECOVERY:
+                       warn ("%s: name server failed", dns -> hostname);
+                       break;
+                     case NO_DATA:
+                       warn ("%s: no A record associated with address",
+                             dns -> hostname);
+               }
+
+               /* Okay to try again after a minute. */
+               return cur_time + 60;
+       }
+
+       debug ("Lookup succeeded; first address is %x",
+              h -> h_addr_list [0]);
+
+       /* Count the number of addresses we got... */
+       for (i = 0; h -> h_addr_list [i]; i++)
+               ;
+       
+       /* Do we need to allocate more memory? */
+       new_len = i * h -> h_length;
+       if (dns -> buf_len < i) {
+               unsigned char *buf =
+                       (unsigned char *)dmalloc (new_len, "do_host_lookup");
+               /* If we didn't get more memory, use what we have. */
+               if (!buf) {
+                       new_len = dns -> buf_len;
+                       if (!dns -> buf_len) {
+                               dns -> timeout = cur_time + 60;
+                               return dns -> timeout;
+                       }
+               } else {
+                       dfree (dns -> data, "do_host_lookup");
+                       dns -> data = buf;
+                       dns -> buf_len = new_len;
+               }
+       }
+
+       /* Addresses are conveniently stored one to the buffer, so we
+          have to copy them out one at a time... :'( */
+       for (i = 0; i < new_len / h -> h_length; i++)
+               memcpy (dns -> data + h -> h_length * i,
+                       h -> h_addr_list [i], h -> h_length);
+       debug ("dns -> data: %x  h -> h_addr_list [0]: %x",
+              *(int *)(dns -> data), h -> h_addr_list [0]);
+       dns -> data_len = new_len;
+
+       /* Set the timeout for an hour from now.
+          XXX This should really use the time on the DNS reply. */
+       dns -> timeout = cur_time + 3600;
+
+       debug ("hard copy: %x %d %x",
+              dns -> data, dns -> data_len, *(int *)(dns -> data));
+       do_data_copy (bufix, bufp, bufcount, dns -> data, dns -> data_len);
+       return dns -> timeout;
+}
+
+static void do_data_copy (bufix, bufp, bufcount, data, len)
+       int *bufix;
+       unsigned char **bufp;
+       int *bufcount;
+       unsigned char *data;
+       int len;
+{
+       int space = *bufcount - *bufix;
+
+       /* If there's more space than we need, use only what we need. */
+       if (space > len)
+               space = len;
+
+       /* Copy as much data as will fit, then increment the buffer index
+          by the amount we actually had to copy, which could be more. */
+       if (space > 0)
+               memcpy (*bufp + *bufix, data, space);
+       *bufix += len;
+}
diff --git a/tree.h b/tree.h
new file mode 100644 (file)
index 0000000..c6b7a3b
--- /dev/null
+++ b/tree.h
@@ -0,0 +1,104 @@
+/* tree.h
+
+   Definitions for address trees... */
+
+/*
+ * Copyright (c) 1995 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''.
+ */
+
+/* A pair of pointers, suitable for making a linked list. */
+typedef struct _pair {
+       caddr_t car;
+       struct _pair *cdr;
+} *pair;
+
+/* Tree node types... */
+#define TREE_CONCAT            1
+#define TREE_HOST_LOOKUP       2
+#define TREE_CONST             3
+#define TREE_LIMIT             4
+
+/* Tree structure for deferred evaluation of changing values. */
+struct tree {
+       int op;
+       union {
+               struct concat {
+                       struct tree *left;
+                       struct tree *right;
+               } concat;
+               struct host_lookup {
+                       struct dns_host_entry *host;
+               } host_lookup;
+               struct const_val {
+                       unsigned char *data;
+                       int len;
+               } const_val;
+               struct limit {
+                       struct tree *tree;
+                       int limit;
+               } limit;
+       } data;
+};
+
+/* DNS host entry structure... */
+struct dns_host_entry {
+       char *hostname;
+       unsigned char *data;
+       int data_len;
+       int buf_len;
+       TIME timeout;
+};
+
+struct tree_cache {
+       unsigned char *value;
+       int len;
+       int buf_size;
+       TIME timeout;
+       struct tree *tree;
+};
+
+struct universe {
+       char *name;
+       struct hash_table *hash;
+       struct option *options [256];
+};
+
+struct option {
+       char *name;
+       char *format;
+       struct universe *universe;
+       unsigned char code;
+};