commit d7837182d3cc1aa28fec66ebb2e23f759ea003b9 Author: Ted Lemon Date: Wed Nov 29 07:40:04 1995 +0000 DHCP Server Daemon 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; +};