From d7837182d3cc1aa28fec66ebb2e23f759ea003b9 Mon Sep 17 00:00:00 2001 From: Ted Lemon Date: Wed, 29 Nov 1995 07:40:04 +0000 Subject: [PATCH] DHCP Server Daemon --- Design | 78 + Makefile | 8 + alloc.c | 197 ++ bootp.c | 147 ++ cdefs.h | 49 + cf/bsdos.h | 106 + cf/netbsd.h | 73 + cf/sunos4.h | 83 + common/alloc.c | 197 ++ common/conflex.c | 280 +++ common/convert.c | 117 + common/errwarn.c | 200 ++ common/hash.c | 152 ++ common/memory.c | 395 ++++ common/options.c | 556 +++++ common/print.c | 65 + common/socket.c | 208 ++ common/tables.c | 414 ++++ common/tree.c | 391 ++++ conf.y | 114 + conflex.c | 280 +++ confpars.c | 1048 +++++++++ convert.c | 117 + db.c | 142 ++ dhcp.c | 52 + dhcp.h | 155 ++ dhcpd.c | 256 +++ dhcpd.conf | 17 + dhcpd.h | 263 +++ dhctoken.h | 71 + doc/dhc-minutes-94dec.txt | 188 ++ doc/dns-minutes-93nov.txt | 267 +++ doc/draft-ietf-dhc-dhcp-03.txt | 2043 ++++++++++++++++++ doc/draft-ietf-dhc-options-1533update-01.txt | 1516 +++++++++++++ doc/draft-ietf-dnsind-dynDNS-00.txt | 1254 +++++++++++ doc/draft-ohta-dynamic-dns-00.txt | 5 + doc/rfc1533.txt | 1683 +++++++++++++++ errwarn.c | 200 ++ hash.c | 152 ++ hash.h | 55 + includes/cdefs.h | 49 + includes/cf/bsdos.h | 106 + includes/cf/netbsd.h | 73 + includes/cf/sunos4.h | 83 + includes/dhcp.h | 155 ++ includes/dhcpd.h | 263 +++ includes/dhctoken.h | 71 + includes/hash.h | 55 + includes/osdep.h | 50 + includes/tree.h | 104 + memory.c | 395 ++++ options.c | 556 +++++ osdep.h | 50 + print.c | 65 + server/bootp.c | 147 ++ server/confpars.c | 1048 +++++++++ server/db.c | 142 ++ server/dhcp.c | 52 + server/dhcpd.c | 256 +++ server/dhcpd.conf | 17 + socket.c | 208 ++ tables.c | 414 ++++ tree.c | 391 ++++ tree.h | 104 + 64 files changed, 18448 insertions(+) create mode 100644 Design create mode 100644 Makefile create mode 100644 alloc.c create mode 100644 bootp.c create mode 100644 cdefs.h create mode 100644 cf/bsdos.h create mode 100644 cf/netbsd.h create mode 100644 cf/sunos4.h create mode 100644 common/alloc.c create mode 100644 common/conflex.c create mode 100644 common/convert.c create mode 100644 common/errwarn.c create mode 100644 common/hash.c create mode 100644 common/memory.c create mode 100644 common/options.c create mode 100644 common/print.c create mode 100644 common/socket.c create mode 100644 common/tables.c create mode 100644 common/tree.c create mode 100644 conf.y create mode 100644 conflex.c create mode 100644 confpars.c create mode 100644 convert.c create mode 100644 db.c create mode 100644 dhcp.c create mode 100644 dhcp.h create mode 100644 dhcpd.c create mode 100644 dhcpd.conf create mode 100644 dhcpd.h create mode 100644 dhctoken.h create mode 100644 doc/dhc-minutes-94dec.txt create mode 100644 doc/dns-minutes-93nov.txt create mode 100644 doc/draft-ietf-dhc-dhcp-03.txt create mode 100644 doc/draft-ietf-dhc-options-1533update-01.txt create mode 100644 doc/draft-ietf-dnsind-dynDNS-00.txt create mode 100644 doc/draft-ohta-dynamic-dns-00.txt create mode 100644 doc/rfc1533.txt create mode 100644 errwarn.c create mode 100644 hash.c create mode 100644 hash.h create mode 100644 includes/cdefs.h create mode 100644 includes/cf/bsdos.h create mode 100644 includes/cf/netbsd.h create mode 100644 includes/cf/sunos4.h create mode 100644 includes/dhcp.h create mode 100644 includes/dhcpd.h create mode 100644 includes/dhctoken.h create mode 100644 includes/hash.h create mode 100644 includes/osdep.h create mode 100644 includes/tree.h create mode 100644 memory.c create mode 100644 options.c create mode 100644 osdep.h create mode 100644 print.c create mode 100644 server/bootp.c create mode 100644 server/confpars.c create mode 100644 server/db.c create mode 100644 server/dhcp.c create mode 100644 server/dhcpd.c create mode 100644 server/dhcpd.conf create mode 100644 socket.c create mode 100644 tables.c create mode 100644 tree.c create mode 100644 tree.h diff --git a/Design b/Design new file mode 100644 index 00000000..59be2fd1 --- /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 index 00000000..e4a4adda --- /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 + +CFLAGS += -DDEBUG -g diff --git a/alloc.c b/alloc.c new file mode 100644 index 00000000..9dbeadb7 --- /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 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 index 00000000..6f5d1a5b --- /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 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 index 00000000..4b94c991 --- /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 index 00000000..bdac405f --- /dev/null +++ b/cf/bsdos.h @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +extern int h_errno; + +#include + +/* Time stuff... */ +#include +#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 +#include +#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 +#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 +#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 index 00000000..d69ff1b8 --- /dev/null +++ b/cf/netbsd.h @@ -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 +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +extern int h_errno; + +#include + +/* Varargs stuff... */ +#include +#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 +#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 index 00000000..fa976878 --- /dev/null +++ b/cf/sunos4.h @@ -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 +#include +#include +#include +#include +#include +#include +#include + +#include +extern int h_errno; + +#include + +/* Varargs stuff... */ +#include +#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 +#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 index 00000000..9dbeadb7 --- /dev/null +++ b/common/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 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 index 00000000..a7b56dd8 --- /dev/null +++ b/common/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 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 + +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 index 00000000..bd423a05 --- /dev/null +++ b/common/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 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 index 00000000..d3c25c41 --- /dev/null +++ b/common/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 +#include + +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 index 00000000..9b2d5f9e --- /dev/null +++ b/common/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 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 index 00000000..c3e1abd5 --- /dev/null +++ b/common/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 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 index 00000000..2a632797 --- /dev/null +++ b/common/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 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 ""; + } + /* 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 index 00000000..85e79fc6 --- /dev/null +++ b/common/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 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 index 00000000..1ee6eb78 --- /dev/null +++ b/common/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 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 + +/* 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 index 00000000..30b1ebd5 --- /dev/null +++ b/common/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 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 index 00000000..3b3e8941 --- /dev/null +++ b/common/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 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 index 00000000..28ce4f40 --- /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 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 index 00000000..a7b56dd8 --- /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 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 + +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 index 00000000..05de6259 --- /dev/null +++ b/confpars.c @@ -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 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 :== | 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 :== | 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 | + OPTION identifier + + 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 :== + | 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 index 00000000..bd423a05 --- /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 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 index 00000000..66f47b31 --- /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 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 index 00000000..9f8946da --- /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 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 index 00000000..f06571d1 --- /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 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 index 00000000..b2687e65 --- /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 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 ] [-a ]"); +} + +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 index 00000000..36d8f0ee --- /dev/null +++ b/dhcpd.conf @@ -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 index 00000000..ac1367cd --- /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 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 +#include +#include +#include +#include +#include +#include +#include +#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 index 00000000..04f057ef --- /dev/null +++ b/dhctoken.h @@ -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 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 index 00000000..a1beb766 --- /dev/null +++ b/doc/dhc-minutes-94dec.txt @@ -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 index 00000000..aa028020 --- /dev/null +++ b/doc/dns-minutes-93nov.txt @@ -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 index 00000000..08ac2124 --- /dev/null +++ b/doc/draft-ietf-dhc-dhcp-03.txt @@ -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 + + +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 index 00000000..e171eb04 --- /dev/null +++ b/doc/draft-ietf-dhc-options-1533update-01.txt @@ -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 + + +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 index 00000000..1bbfdad8 --- /dev/null +++ b/doc/draft-ietf-dnsind-dynDNS-00.txt @@ -0,0 +1,1254 @@ + + + + + + +DNSIND Working Group Susan Thomson (Bellcore) +INTERNET-DRAFT Yakov Rekhter (IBM) + 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] + + + + + + INTERNET-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] + + + + + + INTERNET-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] + + + + + + INTERNET-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] + + + + + + INTERNET-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] + + + + + + INTERNET-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] + + + + + + INTERNET-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] + + + + + + INTERNET-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] + + + + + + INTERNET-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] + + + + + + INTERNET-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] + + + + + + INTERNET-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] + + + + + + INTERNET-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] + + + + + + INTERNET-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] + + + + + + INTERNET-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] + + + + + + INTERNET-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] + + + + + + INTERNET-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] + + + + + + INTERNET-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] + + + + + + INTERNET-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] + + + + + + INTERNET-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] + + + + + + INTERNET-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] + + + + + + INTERNET-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, + . + + [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, . + + + + + + + + + + + + + + + + + + + + + + + + + + + +Expires July 31, 1995 [Page 21] + + + + + + INTERNET-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 index 00000000..f361d776 --- /dev/null +++ b/doc/draft-ohta-dynamic-dns-00.txt @@ -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 index 00000000..39677787 --- /dev/null +++ b/doc/rfc1533.txt @@ -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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + +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] + \ No newline at end of file diff --git a/errwarn.c b/errwarn.c new file mode 100644 index 00000000..d3c25c41 --- /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 +#include + +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 index 00000000..9b2d5f9e --- /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 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 index 00000000..d30072b3 --- /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 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 index 00000000..4b94c991 --- /dev/null +++ b/includes/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/includes/cf/bsdos.h b/includes/cf/bsdos.h new file mode 100644 index 00000000..bdac405f --- /dev/null +++ b/includes/cf/bsdos.h @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +extern int h_errno; + +#include + +/* Time stuff... */ +#include +#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 +#include +#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 +#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 +#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 index 00000000..d69ff1b8 --- /dev/null +++ b/includes/cf/netbsd.h @@ -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 +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +extern int h_errno; + +#include + +/* Varargs stuff... */ +#include +#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 +#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 index 00000000..fa976878 --- /dev/null +++ b/includes/cf/sunos4.h @@ -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 +#include +#include +#include +#include +#include +#include +#include + +#include +extern int h_errno; + +#include + +/* Varargs stuff... */ +#include +#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 +#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 index 00000000..f06571d1 --- /dev/null +++ b/includes/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 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 index 00000000..ac1367cd --- /dev/null +++ b/includes/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 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 +#include +#include +#include +#include +#include +#include +#include +#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 index 00000000..04f057ef --- /dev/null +++ b/includes/dhctoken.h @@ -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 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 index 00000000..d30072b3 --- /dev/null +++ b/includes/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 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 index 00000000..1ff4e68d --- /dev/null +++ b/includes/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/includes/tree.h b/includes/tree.h new file mode 100644 index 00000000..c6b7a3ba --- /dev/null +++ b/includes/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 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 index 00000000..c3e1abd5 --- /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 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 index 00000000..2a632797 --- /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 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 ""; + } + /* 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 index 00000000..1ff4e68d --- /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 index 00000000..85e79fc6 --- /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 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 index 00000000..6f5d1a5b --- /dev/null +++ b/server/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 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 index 00000000..05de6259 --- /dev/null +++ b/server/confpars.c @@ -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 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 :== | 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 :== | 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 | + OPTION identifier + + 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 :== + | 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 index 00000000..66f47b31 --- /dev/null +++ b/server/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 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 index 00000000..9f8946da --- /dev/null +++ b/server/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 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 index 00000000..b2687e65 --- /dev/null +++ b/server/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 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 ] [-a ]"); +} + +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 index 00000000..36d8f0ee --- /dev/null +++ b/server/dhcpd.conf @@ -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 index 00000000..1ee6eb78 --- /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 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 + +/* 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 index 00000000..30b1ebd5 --- /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 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 index 00000000..3b3e8941 --- /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 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 index 00000000..c6b7a3ba --- /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 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; +};