aboutsummaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
authorMurray Stokely <murray@FreeBSD.org>2002-02-19 11:04:34 +0000
committerMurray Stokely <murray@FreeBSD.org>2002-02-19 11:04:34 +0000
commitce99b771f886a2c842db7aa803c9a5a5918f42c8 (patch)
tree229464d9b3244ab78e2784c9a0a1f78de317089a /contrib
parent7657fb140fbd218ea326d55bd3c43c4077f03d9a (diff)
downloadsrc-ce99b771f886a2c842db7aa803c9a5a5918f42c8.tar.gz
src-ce99b771f886a2c842db7aa803c9a5a5918f42c8.zip
Import ISC DHCP 3.0.1 RC6 client.
Notes
Notes: svn path=/vendor/isc-dhcp/dist/; revision=90908
Diffstat (limited to 'contrib')
-rw-r--r--contrib/isc-dhcp/ANONCVS129
-rw-r--r--contrib/isc-dhcp/COPYRIGHT17
-rw-r--r--contrib/isc-dhcp/Makefile96
-rw-r--r--contrib/isc-dhcp/Makefile.conf306
-rw-r--r--contrib/isc-dhcp/Makefile.dist81
-rw-r--r--contrib/isc-dhcp/README786
-rw-r--r--contrib/isc-dhcp/RELNOTES1213
-rw-r--r--contrib/isc-dhcp/client/Makefile.dist76
-rw-r--r--contrib/isc-dhcp/client/clparse.c1139
-rw-r--r--contrib/isc-dhcp/client/dhclient-script.860
-rw-r--r--contrib/isc-dhcp/client/dhclient.8250
-rw-r--r--contrib/isc-dhcp/client/dhclient.c3061
-rw-r--r--contrib/isc-dhcp/client/dhclient.conf.5120
-rw-r--r--contrib/isc-dhcp/client/dhclient.leases.58
-rwxr-xr-xcontrib/isc-dhcp/client/scripts/freebsd100
-rw-r--r--contrib/isc-dhcp/common/Makefile.dist195
-rw-r--r--contrib/isc-dhcp/common/alloc.c1338
-rw-r--r--contrib/isc-dhcp/common/bpf.c227
-rw-r--r--contrib/isc-dhcp/common/comapi.c958
-rw-r--r--contrib/isc-dhcp/common/conflex.c876
-rw-r--r--contrib/isc-dhcp/common/ctrace.c297
-rw-r--r--contrib/isc-dhcp/common/dhcp-eval.5484
-rw-r--r--contrib/isc-dhcp/common/dhcp-options.51359
-rw-r--r--contrib/isc-dhcp/common/discover.c1138
-rw-r--r--contrib/isc-dhcp/common/dispatch.c796
-rw-r--r--contrib/isc-dhcp/common/dlpi.c1345
-rw-r--r--contrib/isc-dhcp/common/dns.c943
-rw-r--r--contrib/isc-dhcp/common/ethernet.c45
-rw-r--r--contrib/isc-dhcp/common/execute.c1061
-rw-r--r--contrib/isc-dhcp/common/fddi.c106
-rw-r--r--contrib/isc-dhcp/common/icmp.c270
-rw-r--r--contrib/isc-dhcp/common/inet.c73
-rw-r--r--contrib/isc-dhcp/common/lpf.c203
-rw-r--r--contrib/isc-dhcp/common/memory.c996
-rw-r--r--contrib/isc-dhcp/common/nit.c160
-rw-r--r--contrib/isc-dhcp/common/options.c2106
-rw-r--r--contrib/isc-dhcp/common/packet.c121
-rw-r--r--contrib/isc-dhcp/common/parse.c4558
-rw-r--r--contrib/isc-dhcp/common/print.c1281
-rw-r--r--contrib/isc-dhcp/common/raw.c92
-rw-r--r--contrib/isc-dhcp/common/resolv.c212
-rw-r--r--contrib/isc-dhcp/common/socket.c152
-rw-r--r--contrib/isc-dhcp/common/tables.c1117
-rw-r--r--contrib/isc-dhcp/common/tr.c65
-rw-r--r--contrib/isc-dhcp/common/tree.c4195
-rw-r--r--contrib/isc-dhcp/common/upf.c142
-rwxr-xr-xcontrib/isc-dhcp/configure233
-rwxr-xr-xcontrib/isc-dhcp/contrib/3.0b1-lease-convert126
-rw-r--r--contrib/isc-dhcp/contrib/sethostname.sh29
-rw-r--r--contrib/isc-dhcp/dst/Makefile.dist55
-rw-r--r--contrib/isc-dhcp/dst/base64.c319
-rw-r--r--contrib/isc-dhcp/dst/dst_api.c1081
-rw-r--r--contrib/isc-dhcp/dst/dst_internal.h160
-rw-r--r--contrib/isc-dhcp/dst/dst_support.c463
-rw-r--r--contrib/isc-dhcp/dst/hmac_link.c494
-rw-r--r--contrib/isc-dhcp/dst/md5.h101
-rw-r--r--contrib/isc-dhcp/dst/md5_dgst.c373
-rw-r--r--contrib/isc-dhcp/dst/md5_locl.h190
-rw-r--r--contrib/isc-dhcp/dst/prandom.c862
-rw-r--r--contrib/isc-dhcp/includes/arpa/nameser.h612
-rw-r--r--contrib/isc-dhcp/includes/arpa/nameser_compat.h183
-rw-r--r--contrib/isc-dhcp/includes/cdefs.h45
-rw-r--r--contrib/isc-dhcp/includes/cf/freebsd.h87
-rw-r--r--contrib/isc-dhcp/includes/ctrace.h86
-rw-r--r--contrib/isc-dhcp/includes/dhcp.h71
-rw-r--r--contrib/isc-dhcp/includes/dhcpd.h2309
-rw-r--r--contrib/isc-dhcp/includes/dhctoken.h376
-rw-r--r--contrib/isc-dhcp/includes/failover.h322
-rw-r--r--contrib/isc-dhcp/includes/inet.h14
-rw-r--r--contrib/isc-dhcp/includes/isc-dhcp/boolean.h32
-rw-r--r--contrib/isc-dhcp/includes/isc-dhcp/dst.h142
-rw-r--r--contrib/isc-dhcp/includes/isc-dhcp/int.h36
-rw-r--r--contrib/isc-dhcp/includes/isc-dhcp/lang.h29
-rw-r--r--contrib/isc-dhcp/includes/isc-dhcp/list.h116
-rw-r--r--contrib/isc-dhcp/includes/isc-dhcp/result.h113
-rw-r--r--contrib/isc-dhcp/includes/isc-dhcp/types.h40
-rw-r--r--contrib/isc-dhcp/includes/minires/minires.h221
-rw-r--r--contrib/isc-dhcp/includes/minires/res_update.h51
-rw-r--r--contrib/isc-dhcp/includes/minires/resolv.h314
-rw-r--r--contrib/isc-dhcp/includes/netinet/if_ether.h22
-rw-r--r--contrib/isc-dhcp/includes/netinet/ip.h24
-rw-r--r--contrib/isc-dhcp/includes/netinet/udp.h2
-rw-r--r--contrib/isc-dhcp/includes/omapip/alloc.h120
-rw-r--r--contrib/isc-dhcp/includes/omapip/buffer.h92
-rw-r--r--contrib/isc-dhcp/includes/omapip/convert.h61
-rw-r--r--contrib/isc-dhcp/includes/omapip/hash.h159
-rw-r--r--contrib/isc-dhcp/includes/omapip/omapip.h620
-rw-r--r--contrib/isc-dhcp/includes/omapip/omapip_p.h302
-rw-r--r--contrib/isc-dhcp/includes/omapip/trace.h124
-rw-r--r--contrib/isc-dhcp/includes/osdep.h82
-rw-r--r--contrib/isc-dhcp/includes/site.h82
-rw-r--r--contrib/isc-dhcp/includes/statement.h113
-rw-r--r--contrib/isc-dhcp/includes/tree.h325
-rw-r--r--contrib/isc-dhcp/includes/version.h2
-rw-r--r--contrib/isc-dhcp/minires/Makefile.dist69
-rw-r--r--contrib/isc-dhcp/minires/ns_date.c129
-rw-r--r--contrib/isc-dhcp/minires/ns_name.c641
-rw-r--r--contrib/isc-dhcp/minires/ns_parse.c204
-rw-r--r--contrib/isc-dhcp/minires/ns_samedomain.c210
-rw-r--r--contrib/isc-dhcp/minires/ns_sign.c356
-rw-r--r--contrib/isc-dhcp/minires/ns_verify.c475
-rw-r--r--contrib/isc-dhcp/minires/res_comp.c236
-rw-r--r--contrib/isc-dhcp/minires/res_findzonecut.c608
-rw-r--r--contrib/isc-dhcp/minires/res_init.c486
-rw-r--r--contrib/isc-dhcp/minires/res_mkquery.c193
-rw-r--r--contrib/isc-dhcp/minires/res_mkupdate.c1101
-rw-r--r--contrib/isc-dhcp/minires/res_query.c413
-rw-r--r--contrib/isc-dhcp/minires/res_send.c871
-rw-r--r--contrib/isc-dhcp/minires/res_sendsigned.c116
-rw-r--r--contrib/isc-dhcp/minires/res_update.c219
-rw-r--r--contrib/isc-dhcp/omapip/Makefile.dist106
-rw-r--r--contrib/isc-dhcp/omapip/alloc.c1151
-rw-r--r--contrib/isc-dhcp/omapip/array.c172
-rw-r--r--contrib/isc-dhcp/omapip/auth.c273
-rw-r--r--contrib/isc-dhcp/omapip/buffer.c718
-rw-r--r--contrib/isc-dhcp/omapip/connection.c1026
-rw-r--r--contrib/isc-dhcp/omapip/convert.c193
-rw-r--r--contrib/isc-dhcp/omapip/dispatch.c604
-rw-r--r--contrib/isc-dhcp/omapip/errwarn.c363
-rw-r--r--contrib/isc-dhcp/omapip/generic.c311
-rw-r--r--contrib/isc-dhcp/omapip/handle.c304
-rw-r--r--contrib/isc-dhcp/omapip/hash.c425
-rw-r--r--contrib/isc-dhcp/omapip/inet_addr.c150
-rw-r--r--contrib/isc-dhcp/omapip/listener.c477
-rw-r--r--contrib/isc-dhcp/omapip/message.c769
-rw-r--r--contrib/isc-dhcp/omapip/mrtrace.c488
-rw-r--r--contrib/isc-dhcp/omapip/omapi.3254
-rw-r--r--contrib/isc-dhcp/omapip/protocol.c1319
-rw-r--r--contrib/isc-dhcp/omapip/result.c125
-rw-r--r--contrib/isc-dhcp/omapip/support.c872
-rw-r--r--contrib/isc-dhcp/omapip/test.c108
-rw-r--r--contrib/isc-dhcp/omapip/toisc.c324
-rw-r--r--contrib/isc-dhcp/omapip/trace.c718
-rw-r--r--contrib/isc-dhcp/site.conf2
-rw-r--r--contrib/isc-dhcp/tests/failover/dhcp-1.cf144
-rw-r--r--contrib/isc-dhcp/tests/failover/dhcp-2.cf142
-rwxr-xr-xcontrib/isc-dhcp/tests/failover/new-failover28
137 files changed, 56532 insertions, 7529 deletions
diff --git a/contrib/isc-dhcp/ANONCVS b/contrib/isc-dhcp/ANONCVS
new file mode 100644
index 000000000000..fa363db1875a
--- /dev/null
+++ b/contrib/isc-dhcp/ANONCVS
@@ -0,0 +1,129 @@
+ Anonymous CVS Access for the ISC DHCP Distribution
+
+The ISC DHCP distribution can be accessed using "anonymous" CVS.
+"Anonymous" cvs uses the CVS "pserver" mechanism to allow anybody on
+the Internet to access a CVS repository without having to register in
+any way. Anonymous CVS allows you to access changes as soon as the
+DHCP developers commit them, rather than having to wait for the next
+snapshot or patchlevel. Changes that have not yet been released yet
+are not guaranteed to work, but they can nonetheless be useful in many
+cases.
+
+ TABLE OF CONTENTS
+
+ 1. What is anonymous CVS?
+ 2. How can i start using it?
+ 3. Checking out the latest code in a release
+ 4. Checking out the latest code
+ 5. Checking out a specific release
+ 6. When to update
+
+ WHAT IS ANONYMOUS CVS?
+
+Anonymous CVS also allows you to browse through the history of the
+DHCP distribution, and examine the revision history of specific files
+to see how they have changed between revisions, to try to figure out
+why something that was working before is no longer working, or just to
+see when a certain change was made.
+
+ HOW CAN I START USING IT?
+
+To use anonymous CVS to access the DHCP distribution, you must first
+"log in". You should only need to do this once, but it is a
+necessary step, even though access is anonymous. Anonymous users log
+in as user "nobody", password "nobody". To do this, type:
+
+ cvs -d :pserver:nobody@dhcp.cvs.isc.org:/cvsroot login
+
+You will be prompted for a password - type "nobody". If you get some
+kind of error indicating that cvs doesn't know how to log you in, you
+are probably running an old version of cvs, and should upgrade. This
+should work with cvs version 1.10.
+
+Once you have logged in, you can check out a version of the DHCP
+distribution, so the next question is, which version?
+
+ CHECKING OUT THE LATEST CODE IN A RELEASE
+
+There are currently four major versions of the distribution - Release
+1, Release 2, Release 3, and the current development tree. Releases
+1, 2 and 3 are branches in the CVS repository. To check out the
+latest code on any of these branches, you would use a branch tag of
+RELEASE_1, RELEASE_2 or RELEASE_3 in the following command:
+
+ (setenv CVSROOT :pserver:nobody@dhcp.cvs.isc.org:/cvsroot;
+ cvs checkout -d dhcp-2.0 -r RELEASE_2 DHCP)
+
+Note that the example is for Release 2.
+
+ CHECKING OUT THE LATEST CODE
+
+To check out the current engineering version, use:
+
+ (setenv CVSROOT :pserver:nobody@dhcp.cvs.isc.org:/cvsroot;
+ cvs checkout -d dhcp-current DHCP)
+
+Note that the current engineering version is a work in progress, and
+there is no real guarantee that it will work for you.
+
+ CHECKING OUT A SPECIFIC RELEASE
+
+You can also check out specific versions of the DHCP distribution.
+There are three kinds of version tags you may find - alpha tags, beta
+tags and release tags. Alpha tags look like this:
+
+ V#-ALPHA-YYYYMMDD
+
+# is the release number. YYYYMMDD is the date of the release, with a
+4-digit year, the month expressed as a number (January=1), and the day
+of the month specified as a number, with the first day of the month
+being 1.
+
+Beta tags look like this:
+
+ V#-BETA-%-PATCH-*
+
+Where # is the release number, % is the Beta number (usually 1) and *
+is the patchlevel. In the future there may also be beta tags that
+look like this:
+
+ V#-#-BETA-%-PATCH-*
+
+Where #-# is the major version followed by the minor version - for
+example, when the first 3.1 beta comes out, the tag will look like
+this:
+
+ V3-1-BETA-1-PATCH-0
+
+Release tags look like this:
+
+ V#-%-*
+
+Where # is the major version, % is the minor version, and * is the
+patchlevel. So the tag for 1.0pl2 is V1-0-2, and to check it out,
+you'd type:
+
+ (setenv CVSROOT :pserver:nobody@dhcp.cvs.isc.org:/cvsroot;
+ cvs checkout -d dhcp-1.0pl2 -rV1-0-2 DHCP)
+
+Whenever changes are checked in to the ISC DHCP repository, or files
+are tagged, a notice is sent to the dhcp-source-changes@isc.org
+mailing list. You can subscribe to this list by sending mail to
+dhcp-source-changes-request@isc.org, and you will then get immediate
+notification when changes are made. You may find the volume of mail
+on this list annoying, however.
+
+ WHEN TO UPDATE
+
+We do not recommend that you do an update immediately after you see a
+change on the dhcp-source-changes mailing list - instead, it's best to
+wait a while to make sure that any changes that change depends on have
+also been committed. Also, sometimes when development is being done
+on two machines, the developers will check in a tentative change that
+hasn't been tested at all so that they can update on a different
+machine and test the change. The best way to avoid accidentally
+getting one of these changes is to not update aggressively - when a
+change is made, wait a while before updating, to make sure that it's
+not going to be quickly followed by another change.
+
+
diff --git a/contrib/isc-dhcp/COPYRIGHT b/contrib/isc-dhcp/COPYRIGHT
new file mode 100644
index 000000000000..0e5d81aa663f
--- /dev/null
+++ b/contrib/isc-dhcp/COPYRIGHT
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 1996-1999 Internet Software Consortium.
+ * Use is subject to license terms which appear in the file named
+ * ISC-LICENSE that should have accompanied this file when you
+ * received it. If a file named ISC-LICENSE did not accompany this
+ * file, or you are not sure the one you have is correct, you may
+ * obtain an applicable copy of the license at:
+ *
+ * http://www.isc.org/isc-license-1.0.html.
+ *
+ * This file is part of the ISC DHCP distribution. The documentation
+ * associated with this file is listed in the file DOCUMENTATION,
+ * included in the top-level directory of this release.
+ *
+ * Support and other services are available for ISC products - see
+ * http://www.isc.org for more information.
+ */
diff --git a/contrib/isc-dhcp/Makefile b/contrib/isc-dhcp/Makefile
new file mode 100644
index 000000000000..e6c2d1e5e235
--- /dev/null
+++ b/contrib/isc-dhcp/Makefile
@@ -0,0 +1,96 @@
+# Makefile
+#
+# Copyright (c) 2000 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 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 and Nominum, Inc.
+# To learn more about the Internet Software Consortium, see
+# ``http://www.isc.org/''. To learn more about Vixie Enterprises,
+# see ``http://www.vix.com''. To learn more about Nominum, Inc., see
+# ``http://www.nominum.com''.
+#
+
+all:
+ @sysname=`./configure --print-sysname`; \
+ if [ ! -d work.$$sysname ]; then \
+ echo No build directory for $$sysname - please run ./configure.; \
+ else \
+ (cd work.$$sysname; make all); \
+ fi
+
+install:
+ @sysname=`./configure --print-sysname`; \
+ if [ ! -d work.$$sysname ]; then \
+ echo No build directory for $$sysname - please run ./configure.; \
+ else \
+ (cd work.$$sysname; make install); \
+ fi
+
+depend:
+ @sysname=`./configure --print-sysname`; \
+ if [ ! -d work.$$sysname ]; then \
+ echo No build directory for $$sysname - please run ./configure.; \
+ else \
+ (cd work.$$sysname; make depend); \
+ fi
+
+clean:
+ @sysname=`./configure --print-sysname`; \
+ if [ ! -d work.$$sysname ]; then \
+ echo No build directory for $$sysname - please run ./configure.; \
+ else \
+ (cd work.$$sysname; make clean); \
+ fi
+
+realclean:
+ @sysname=`./configure --print-sysname`; \
+ if [ ! -d work.$$sysname ]; then \
+ echo No build directory for $$sysname - please run ./configure.; \
+ else \
+ (cd work.$$sysname; make realclean); \
+ fi
+
+distclean:
+ @sysname=`./configure --print-sysname`; \
+ if [ ! -d work.$$sysname ]; then \
+ echo No build directory for $$sysname - please run ./configure.; \
+ else \
+ (cd work.$$sysname; make distclean); \
+ fi
+
+links:
+ @sysname=`./configure --print-sysname`; \
+ if [ ! -d work.$$sysname ]; then \
+ echo No build directory for $$sysname - please run ./configure.; \
+ else \
+ (cd work.$$sysname; make links); \
+ fi
+
diff --git a/contrib/isc-dhcp/Makefile.conf b/contrib/isc-dhcp/Makefile.conf
index 509e32f823a3..a8c64ac6705f 100644
--- a/contrib/isc-dhcp/Makefile.conf
+++ b/contrib/isc-dhcp/Makefile.conf
@@ -1,53 +1,56 @@
# Makefile.conf
#
-# Copyright (c) 1996, 1997, 1998, 1999 The Internet Software Consortium.
-# All rights reserved.
+# Copyright (c) 1996-2000 Internet Software Consortium.
+# Use is subject to license terms which appear in the file named
+# ISC-LICENSE that should have accompanied this file when you
+# received it. If a file named ISC-LICENSE did not accompany this
+# file, or you are not sure the one you have is correct, you may
+# obtain an applicable copy of the license at:
#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
+# http://www.isc.org/isc-license-1.0.html.
#
-# 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 file is part of the ISC DHCP distribution. The documentation
+# associated with this file is listed in the file DOCUMENTATION,
+# included in the top-level directory of this release.
#
-# 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.
+# Support and other services are available for ISC products - see
+# http://www.isc.org for more information.
#
## Defaults...
SCRIPT = none
+USERBINDIR = /usr/bin
BINDIR = /usr/sbin
CLIENTBINDIR=/sbin
-ADMMANEXT = .0
-FFMANEXT = .0
ADMMANDIR = /usr/share/man/cat8
+ADMMANEXT = .0
FFMANDIR = /usr/share/man/cat5
-INSTALL = install -c
-MANINSTALL = install -c -m 444
+FFMANEXT = .0
+LIBMANDIR = /usr/share/man/cat3
+LIBMANEXT = .0
+USRMANDIR = /usr/share/man/cat1
+USRMANEXT = .0
+MANCAT = cat
+INSTALL = install -c -m 444
+MANINSTALL = install -c
CHMOD = chmod
CATMANPAGES =
-MANCAT = cat
ETC = /etc
VARRUN = /var/run
VARDB = /var/db
+LIBDIR=/usr/local/lib
+INCDIR=/usr/local/include
+LIBS =
+COPTS = $(BINDDEF) $(CC_OPTIONS)
+DEBUG = -g
+RANLIB = ranlib
+MKDEP = mkdep
CLIENT_PATH = '"PATH=/usr/ucb:/usr/bin:/usr/sbin:/bin:/sbin"'
+BINDLIB = ../minires/libres.a
+BINDINC =
+MINIRES = minires
+
# Major version number (if applicable)
##--majver--
MAJORVERSION=MajorVersion
@@ -70,12 +73,12 @@ MINORVERSION=MinorVersion
# removes the comment characters from the appropriate set of
# assignments, and writes the output to Makefile.
-## AIX 4.1.5.0
+## AIX 4.3
##--aix--
#CF = cf/aix.h
#CC=cc -Daix
-#INSTALL=/usr/ucb/install
-#MANINSTALL=/usr/ucb/install
+#INSTALL=/usr/ucb/install -c
+#MANINSTALL=/usr/ucb/install -c -m 444
#ADMMANEXT = .8
#FFMANEXT = .5
#VARRUN = /etc
@@ -84,21 +87,25 @@ MINORVERSION=MinorVersion
## NEXTSTEP 3.x,4.x
##--nextstep--
-#LIBS =
#CF = cf/nextstep.h
#CC=cc
-#COPTS = -Wall
+#COPTS = -Wall $(BINDDEF) $(CC_OPTIONS)
#BINDIR=/usr/etc
#ADMMANDIR = /usr/local/man/cat8
#FFMANDIR = /usr/local/man/cat5
+#LIBMANDIR = /usr/local/man/cat3
+#USRMANDIR = /usr/local/man/cat1
#ADMMANEXT = .8
#FFMANEXT = .5
+#LIBMANEXT = .3
+#USRMANEXT = .3
#VARRUN = /etc
#VARDB = /etc
##--nextstep--
## SunOS 4.1
##--sunos4--
+#CC = gcc
#LIBS = -lresolv
#CF = cf/sunos4.h
#BINDIR=/usr/etc
@@ -115,13 +122,20 @@ MINORVERSION=MinorVersion
#MANINSTALL=/usr/ucb/install
#LIBS = -lresolv -lsocket -lnsl -lgen
#CC=gcc
-#COPTS = -Wall -Wno-unused -Wno-implicit -Wno-comment \
-# -Wno-uninitialized -Wno-char-subscripts -Werror
+#COPTS = $(BINDDEF) -Wall -Wno-unused -Wno-implicit -Wno-comment \
+# -Wno-uninitialized -Wno-char-subscripts -Wno-switch -Werror \
+# -DSOLARIS_MAJOR=$(MAJORVERSION) -DSOLARIS_MINOR=$(MINORVERSION) \
+# $(CC_OPTIONS)
#CF = cf/sunos5-5.h
-#ADMMANDIR = /usr/share/man/cat1m
+#ADMMANDIR = /usr/share/man/man1m
#ADMMANEXT = .1m
-#FFMANDIR = /usr/share/man/cat4
+#FFMANDIR = /usr/share/man/man4
#FFMANEXT = .4
+#LIBMANDIR = /usr/share/man/man3
+#LIBMANEXT = .3
+#USRMANDIR = /usr/share/man/man1
+#USRMANEXT = .1
+#MANCAT = man
#VARRUN = /etc
#VARDB = /etc
#SCRIPT=solaris
@@ -131,14 +145,21 @@ MINORVERSION=MinorVersion
##--sunos5-cc--
#INSTALL=/usr/ucb/install
#MANINSTALL=/usr/ucb/install
-#LIBS = -lresolv -lsocket -lnsl -lgen
+#LIBS = -lresolv -lsocket -lnsl -lgen
#CC=cc
-#COPTS = -D__svr4__
+#COPTS = -D__svr4__ $(BINDDEF) -erroff=E_END_OF_LOOP_CODE_NOT_REACHED \
+# -DSOLARIS_MAJOR=$(MAJORVERSION) -DSOLARIS_MINOR=$(MINORVERSION) \
+# $(CC_OPTIONS)
#CF = cf/sunos5-5.h
-#ADMMANDIR = /usr/share/man/cat1m
+#ADMMANDIR = /usr/share/man/man1m
#ADMMANEXT = .1m
-#FFMANDIR = /usr/share/man/cat4
+#FFMANDIR = /usr/share/man/man4
#FFMANEXT = .4
+#LIBMANDIR = /usr/share/man/man3
+#LIBMANEXT = .3
+#USRMANDIR = /usr/share/man/man1
+#USRMANEXT = .1
+#MANCAT = man
#VARRUN = /etc
#VARDB = /etc
#SCRIPT=solaris
@@ -146,23 +167,35 @@ MINORVERSION=MinorVersion
## DEC Alpha/OSF1
##--alphaosf--
-#CC=cc -std0
-#INSTALL=/usr/ucb/installbsd
-#MANINSTALL=/usr/ucb/installbsd
-#LIBS=
+#COPTS = -std $(CC_OPTIONS)
+#INSTALL=/usr/ucb/installbsd -c
+#MANINSTALL=/usr/ucb/installbsd -c
#CF = cf/alphaosf.h
#ADMMANEXT = .8
#FFMANEXT = .5
#VARDB = /etc
##--alphaosf--
-## BSD/OS 2.1
+## BSD/OS 2.1 through 4.0
##--bsdos--
-#LIBS= -lresolv
+#LIBS = -lresolv
#CC=gcc2
#CF = cf/bsdos.h
+#SCRIPT=bsdos
##--bsdos--
+## BSD/OS 4.1 and higher.
+##--bsdos-4.1--
+#CF = cf/bsdos.h
+#SCRIPT=bsdos
+##--bsdos-4.1--
+
+## OpenBSD
+##--openbsd--
+#CF = cf/openbsd.h
+#SCRIPT=openbsd
+##--openbsd--
+
## FreeBSD
##--freebsd--
#CF = cf/freebsd.h
@@ -173,18 +206,47 @@ MINORVERSION=MinorVersion
##--rhapsody--
#CF = cf/rhapsody.h
#COPTS = -Wall -Wno-unused -Wno-implicit -Wno-comment \
-# -Wno-uninitialized -Werror -pipe
-#SCRIPT=rhapsody
+# -Wno-uninitialized -Wno-switch -Werror -pipe $(BINDDEF) $(CC_OPTIONS)
+##SCRIPT=rhapsody
##--rhapsody--
+## Darwin/MacOSX
+##--darwin--
+#CF = cf/rhapsody.h
+#COPTS = -Ddarwin -Wall -Wno-unused -Wno-implicit -Wno-comment \
+# -Wno-uninitialized -Wno-switch -Werror -pipe $(BINDDEF) $(CC_OPTIONS)
+##SCRIPT=rhapsody
+##--darwin--
+
## NetBSD
##--netbsd--
#CF = cf/netbsd.h
-#COPTS = -Wall -Wstrict-prototypes -Wno-unused -Wno-implicit -Wno-comment \
-# -Wno-uninitialized -Werror -pipe
+#COPTS = -Wall -Wstrict-prototypes -Wno-unused -Wno-comment \
+# -Wno-uninitialized -Werror \
+# -Wimplicit-function-declaration -Wpointer-arith -Wcast-qual \
+# -Wcast-align -Wwrite-strings -Wconversion -Wmissing-prototypes \
+# -Wmissing-declarations -Wnested-externs \
+# -pipe $(BINDDEF) $(CC_OPTIONS)
#SCRIPT=netbsd
+##MKDEP=makedepend
##--netbsd--
+## NetBSD nocast
+## Some versions of the arm32 gcc have a problem in cast conversions.
+## The Alpha definitely has a problem - if you pass '6' where a size_t
+## is expected, you get a warning. So on these architectures, we do
+## not ask for that sort of warning.
+##--netbsd-nocast--
+#CF = cf/netbsd.h
+#COPTS = -Wall -Wstrict-prototypes -Wno-unused -Wno-comment \
+# -Wno-uninitialized -Werror \
+# -Wimplicit-function-declaration -Wpointer-arith -Wcast-qual \
+# -Wwrite-strings -Wmissing-prototypes \
+# -Wmissing-declarations -Wnested-externs \
+# -pipe $(BINDDEF) $(CC_OPTIONS)
+#SCRIPT=netbsd
+##--netbsd-nocast--
+
## Ultrix
##--ultrix--
#BINDIR = /usr/etc
@@ -196,66 +258,98 @@ MINORVERSION=MinorVersion
#ADMMANEXT = .8
#FFMANDIR = /usr/man/man5
#FFMANEXT = .5
+#LIBMANDIR = /usr/man/cat3
+#LIBMANEXT = .3
+#USRMANDIR = /usr/man/cat1
+#USRMANEXT = .1
##--ultrix--
## Linux 1.x
##--linux-1--
-#COPTS = -DLINUX_MAJOR=$(MAJORVERSION) -DLINUX_MINOR=$(MINORVERSION)
+#COPTS = -DLINUX_MAJOR=$(MAJORVERSION) -DLINUX_MINOR=$(MINORVERSION) \
+# $(BINDDEF) $(CC_OPTIONS)
#CF = cf/linux.h
#ADMMANDIR = /usr/man/man8
#ADMMANEXT = .8
#FFMANDIR = /usr/man/man5
#FFMANEXT = .5
+#LIBMANDIR = /usr/man/man3
+#LIBMANEXT = .3
+#USRMANDIR = /usr/man/man1
+#USRMANEXT = .1
#MANCAT = man
#VARRUN = /var/run
-#VARDB = /var/state/dhcp # see rationale in includes/cf/linux.h
+#VARDB = /var/state/dhcp
#SCRIPT=linux
##--linux-1--
## Linux 2.0
##--linux-2.0--
-#COPTS = -DLINUX_MAJOR=$(MAJORVERSION) -DLINUX_MINOR=$(MINORVERSION)
+#COPTS = -DLINUX_MAJOR=$(MAJORVERSION) -DLINUX_MINOR=$(MINORVERSION) \
+# $(BINDDEF) $(CC_OPTIONS)
#CF = cf/linux.h
#ADMMANDIR = /usr/man/man8
#ADMMANEXT = .8
#FFMANDIR = /usr/man/man5
#FFMANEXT = .5
+#LIBMANDIR = /usr/man/man3
+#LIBMANEXT = .3
+#USRMANDIR = /usr/man/man1
+#USRMANEXT = .1
#MANCAT = man
#VARRUN = /var/run
-#VARDB = /var/state/dhcp # see rationale in includes/cf/linux.h
+#VARDB = /var/state/dhcp
#SCRIPT=linux
##--linux-2.0--
## Linux 2.1
##--linux-2.1--
-#COPTS = -DLINUX_MAJOR=$(MAJORVERSION) -DLINUX_MINOR=$(MINORVERSION)
+#COPTS = -DLINUX_MAJOR=$(MAJORVERSION) -DLINUX_MINOR=$(MINORVERSION) \
+# $(BINDDEF) $(CC_OPTIONS)
#CF = cf/linux.h
#ADMMANDIR = /usr/man/man8
#ADMMANEXT = .8
-#FFMANDIR = /usr/share/man/man5
+#FFMANDIR = /usr/man/man5
#FFMANEXT = .5
+#LIBMANDIR = /usr/man/man3
+#LIBMANEXT = .3
+#USRMANDIR = /usr/man/man1
+#USRMANEXT = .1
#MANCAT = man
#VARRUN = /var/run
-#VARDB = /var/state/dhcp # see rationale in includes/cf/linux.h
+#VARDB = /var/state/dhcp
#SCRIPT=linux
##--linux-2.1--
## Linux 2.2
##--linux-2.2--
-#COPTS = -DLINUX_MAJOR=$(MAJORVERSION) -DLINUX_MINOR=$(MINORVERSION)
+#COPTS = -DLINUX_MAJOR=$(MAJORVERSION) -DLINUX_MINOR=$(MINORVERSION) \
+# $(BINDDEF) $(CC_OPTIONS)
#CF = cf/linux.h
#ADMMANDIR = /usr/man/man8
#ADMMANEXT = .8
-#FFMANDIR = /usr/share/man/man5
+#FFMANDIR = /usr/man/man5
#FFMANEXT = .5
+#LIBMANDIR = /usr/man/man3
+#LIBMANEXT = .3
+#USRMANDIR = /usr/man/man1
+#USRMANEXT = .1
#MANCAT = man
#VARRUN = /var/run
-#VARDB = /var/state/dhcp # see rationale in includes/cf/linux.h
+#VARDB = /var/state/dhcp
#SCRIPT=linux
##--linux-2.2--
-## SCO
-##--sco--
+## SCO UnixWare 7
+##--uw7--
+#CF = cf/uw7.h
+#PREDEFINES=-DUW7
+#RANLIB=true
+#LIBS = -lresolv -lsocket -lnsl -lgen
+##--uw7--
+
+## SCO (with standard cc compiler)
+##--sco-cc--
#CF = cf/sco.h
#PREDEFINES=-DSCO -DBROKEN_ANSI
#BINDIR = /usr/etc
@@ -271,7 +365,30 @@ MINORVERSION=MinorVersion
#VARRUN = /etc
#VARDB = /etc
#CATMANPAGES=
-##--sco--
+##--sco-cc--
+
+## SCO (with GNU gcc compiler)
+##--sco-gcc--
+#CF = cf/sco.h
+#CC=gcc
+#PREDEFINES=-DSCO
+#LIBS = -lsocket
+#USERBINDIR = /usr/local/dhcp/bin
+#BINDIR = /usr/local/dhcp/bin
+#CLIENTBINDIR = /usr/local/dhcp/bin
+#ADMMANDIR = /usr/local/dhcp/man/cat.ADMN
+#ADMMANEXT = .ADMN.Z
+#FFMANDIR = /usr/local/dhcp/man/cat.SFF
+#FFMANEXT = .SFF.Z
+#INSTALL = /usr/local/bin/install
+#MANFROM = <
+#MANINSTALL = compress
+#MANTO = >
+#VARRUN = /usr/local/dhcp/var
+#VARDB = /usr/local/dhcp/var
+#CATMANPAGES=
+#CLIENT_PATH = '"PATH=/bin:/etc:/usr/bin:/tcb/bin:/usr/bin/X11:/usr/local/bin:/usr/local/dhcp/bin"'
+##--sco-gcc--
## QNX
##--qnx--
@@ -280,9 +397,13 @@ MINORVERSION=MinorVersion
#ADMMANEXT = .8
#FFMANDIR = /usr/man/man5
#FFMANEXT = .5
+#LIBMANDIR = /usr/man/man3
+#LIBMANEXT = .3
+#USRMANDIR = /usr/man/man1
+#USRMANEXT = .1
#MANCAT = man
#VARRUN = /etc
-#COPTS=-w3 -Dlint
+#COPTS=-w3 -Dlint $(BINDDEF) $(CC_OPTIONS)
#LFLAGS=$(DEBUG) "-Wl,op symfile" -l socket
#MANINSTALL = /bin/true
#INSTALL = cp
@@ -290,6 +411,26 @@ MINORVERSION=MinorVersion
#CLIENTBINDIR = /etc
##--qnx--
+
+## QNX RTP (v6, NTO)
+##--qnxnto--
+#CF = cf/qnx.h
+#ADMMANDIR = /opt/man/man8
+#ADMMANEXT = .8
+#FFMANDIR = /opt/man/man5
+#FFMANEXT = .5
+#LIBMANDIR = /opt/man/man3
+#LIBMANEXT = .3
+#MANCAT = man
+#COPTS=-w3 -Dlint $(BINDDEF)
+#LFLAGS=-l socket
+#MANINSTALL = /bin/cp
+#INSTALL = /bin/cp
+#BINDIR = /opt/sbin
+#USERBINDIR= /opt/bin
+#CLIENTBINDIR = /opt/sbin
+##--qnxnto--
+
## CygWin32
##--cygwin32--
#CF = cf/cygwin32.h
@@ -297,6 +438,10 @@ MINORVERSION=MinorVersion
#ADMMANEXT = .8
#FFMANDIR = /usr/man/man5
#FFMANEXT = .5
+#LIBMANDIR = /usr/man/man3
+#LIBMANEXT = .3
+#USRMANDIR = /usr/man/man1
+#USRMANEXT = .1
#VARRUN = /etc
#MANINSTALL = /bin/true
#INSTALL = cp
@@ -313,16 +458,19 @@ MINORVERSION=MinorVersion
## IRIX 6.x
##--irix--
-#LIBS = -lbind
-#LFLAGS=$(DEBUG) -L/usr/local/lib -Wl,-woff,84 -Wl,-woff,85 -Wl,-woff,134
+#LFLAGS=$(DEBUG) -Wl,-woff,84 -Wl,-woff,85 -Wl,-woff,134
#CC=gcc
-#COPTS = -I/usr/local/include
+#COPTS = -I/usr/local/include $(BINDDEF) $(CC_OPTIONS)
#CF = cf/irix.h
#BINDIR = /usr/local/etc
#ADMMANDIR = /usr/local/man/man8
#ADMMANEXT = .8
#FFMANDIR = /usr/local/man/man5
#FFMANEXT = .5
+#LIBMANDIR = /usr/local/man/man3
+#LIBMANEXT = .3
+#USRMANDIR = /usr/local/man/man1
+#USRMANEXT = .1
#MANCAT = man
#INSTALL = install
#MANINSTALL = install
@@ -331,3 +479,21 @@ MINORVERSION=MinorVersion
#VARRUN = /etc
#VARDB = /usr/local/etc/dhcp
##--irix--
+
+## HP-UX
+##--hpux-cc--
+#COPTS = $(BINDDEF) $(CC_OPTIONS)
+#LFLAGS = -Wl,+vnocompatwarnings
+#INSTALL = install -i
+#MANINSTALL = install -i
+##--hpux-cc--
+
+## HP-UX with gcc
+##--hpux-gcc--
+#CC = gcc
+#CF = cf/hpux.h
+#INSTALL = install -i
+#ADMMANEXT = .8
+#FFMANEXT = .5
+#MANINSTALL = install -i -m 444
+##--hpux-gcc--
diff --git a/contrib/isc-dhcp/Makefile.dist b/contrib/isc-dhcp/Makefile.dist
index e2dc4e28e7fb..7e4a2fc1d10e 100644
--- a/contrib/isc-dhcp/Makefile.dist
+++ b/contrib/isc-dhcp/Makefile.dist
@@ -1,78 +1,41 @@
# Makefile.dist
#
-# Copyright (c) 1996, 1997 The Internet Software Consortium.
-# All rights reserved.
+# Copyright (c) 1996-1999 Internet Software Consortium.
+# Use is subject to license terms which appear in the file named
+# ISC-LICENSE that should have accompanied this file when you
+# received it. If a file named ISC-LICENSE did not accompany this
+# file, or you are not sure the one you have is correct, you may
+# obtain an applicable copy of the license at:
#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
+# http://www.isc.org/isc-license-1.0.html.
#
-# 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 file is part of the ISC DHCP distribution. The documentation
+# associated with this file is listed in the file DOCUMENTATION,
+# included in the top-level directory of this release.
#
-# 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.
+# Support and other services are available for ISC products - see
+# http://www.isc.org for more information.
#
-SUBDIRS= common server client relay
+SUBDIRS= common $(MINIRES) dst omapip server client relay dhcpctl
all:
@for dir in ${SUBDIRS}; do \
echo "Making all in $$dir"; \
(cd $$dir; $(MAKE) all) || exit 1; \
done
- @if [ `uname` = Linux ]; then \
- echo; \
- echo " !!!! WARNING !!!!"; \
- echo ; \
- echo "The default location for the dhcpd.leases file has \
-changed!!!"; \
- echo; \
- echo "It is now in /var/state/dhcp. If you are not"; \
- echo "installing this for the first time, please move your"; \
- echo "lease database to the new location before using this"; \
- echo "software."; \
- echo; \
- echo " !!!! WARNING !!!!"; \
- echo; \
- fi
install:
@for dir in ${SUBDIRS}; do \
echo "Installing in $$dir"; \
(cd $$dir; $(MAKE) install) || exit 1; \
done
- @if [ `uname` = Linux ]; then \
- echo; \
- echo " !!!! WARNING !!!!"; \
- echo ; \
- echo "The default location for the dhcpd.leases file has \
-changed!!!"; \
- echo; \
- echo "It is now in /var/state/dhcp. If you are not"; \
- echo "installing this for the first time, please move your"; \
- echo "lease database to the new location before using this"; \
- echo "software."; \
- echo; \
- echo " !!!! WARNING !!!!"; \
- echo; \
- fi
+
+depend:
+ @for dir in ${SUBDIRS}; do \
+ echo "Making dependencies in $$dir"; \
+ (cd $$dir; $(MAKE) depend) || exit 1; \
+ done
clean:
@for dir in ${SUBDIRS}; do \
@@ -92,3 +55,9 @@ distclean:
(cd $$dir; $(MAKE) distclean) || exit 1; \
done
@rm -f Makefile
+
+links:
+ @for dir in ${SUBDIRS}; do \
+ echo "Making links in $$dir"; \
+ (cd $$dir; $(MAKE) links) || exit 1; \
+ done
diff --git a/contrib/isc-dhcp/README b/contrib/isc-dhcp/README
index 4c444005ecb8..530eb71ec228 100644
--- a/contrib/isc-dhcp/README
+++ b/contrib/isc-dhcp/README
@@ -1,81 +1,82 @@
-<C><H4>Internet Software Consortium</H4></C>
-<C><H4>Dynamic Host Configuration Protocol Distribution</H4></C>
-<C><H4>Version 2 Patchlevel 5</H4></C>
-<C><H4>September 6, 2000</H4></C>
-
-<C><H4>README FILE</H4></C>
-
-<P>You should read this file carefully before trying to install or use
-the ISC DHCP Distribution.</P>
-
-<OL>
-<C><B>TABLE OF CONTENTS</B></C>
-<DL>
-<DT><A HREF="#1"1</A><DD>WHERE TO FIND DOCUMENTATION
-<DT><A HREF="#2"2</A><DD>RELEASE STATUS
-<DT><A HREF="#3"3</A><DD>BUILDING THE DHCP DISTRIBUTION
-<DT><A HREF="#4"4</A><DD>INSTALLING THE DHCP DISTRIBUTION
-<DT><A HREF="#5"5</A><DD>USING THE DHCP DISTRIBUTION
-<DL>
-<DT><A HREF="#5.1"5.1</A><DD>LINUX
-<DL>
-<DT><A HREF="#5.1.1"5.1.1</A><DD>SO_ATTACH_FILTER UNDECLARED
-<DT><A HREF="#5.1.2"5.1.2</A><DD>PROTOCOL NOT CONFIGURED
-<DT><A HREF="#5.1.3"5.1.3</A><DD>BROADCAST
-<DT><A HREF="#5.1.4"5.1.4</A><DD>FIREWALL RULES
-<DT><A HREF="#5.1.5"5.1.5</A><DD>IP BOOTP AGENT
-<DT><A HREF="#5.1.6"5.1.6</A><DD>MULTIPLE INTERFACES
-</DL>
-<DT><A HREF="#5.2"5.2</A><DD>SCO
-<DT><A HREF="#5.3"5.3</A><DD>HP-UX
-<DT><A HREF="#5.4"5.4</A><DD>ULTRIX
-<DT><A HREF="#5.5"5.5</A><DD>FreeBSD
-<DT><A HREF="#5.6"5.6</A><DD>NeXTSTEP
-<DT><A HREF="#5.7"5.7</A><DD>SOLARIS
-</DL>
-<DT><A HREF="#6"6</A><DD>SUPPORT
-<DL>
-<DT><A HREF="#6.1"6.1</A><DD>HOW TO REPORT BUGS
-</DL>
-<DT><A HREF="#7"7</A><DD>KNOWN BUGS
-
-<H4 ID="1">Where to find documentation</H4>
-
-<P>Documentation for this software includes this README file, the
+ Internet Software Consortium DHCP Distribution
+ Version 3.0.1
+ Release Candidate 6
+ January 17, 2002
+
+ README FILE
+
+You should read this file carefully before trying to install or use
+the ISC DHCP Distribution.
+
+ TABLE OF CONTENTS
+
+ 1 WHERE TO FIND DOCUMENTATION
+ 2 RELEASE STATUS
+ 3 BUILDING THE DHCP DISTRIBUTION
+ 3.1 UNPACKING IT
+ 3.2 CONFIGURING IT
+ 3.2.1 DYNAMIC DNS UPDATES
+ 3.2.2 LOCALLY DEFINED OPTIONS
+ 3.3 BUILDING IT
+ 4 INSTALLING THE DHCP DISTRIBUTION
+ 5 USING THE DHCP DISTRIBUTION
+ 5.1 FIREWALL RULES
+ 5.2 LINUX
+ 5.2.1 IF_TR.H NOT FOUND
+ 5.2.2 SO_ATTACH_FILTER UNDECLARED
+ 5.2.3 PROTOCOL NOT CONFIGURED
+ 5.2.4 BROADCAST
+ 5.2.6 IP BOOTP AGENT
+ 5.2.7 MULTIPLE INTERFACES
+ 5.3 SCO
+ 5.4 HP-UX
+ 5.5 ULTRIX
+ 5.6 FreeBSD
+ 5.7 NeXTSTEP
+ 5.8 SOLARIS
+ 6 SUPPORT
+ 6.1 HOW TO REPORT BUGS
+
+ WHERE TO FIND DOCUMENTATION
+
+Documentation for this software includes this README file, the
RELNOTES file, and the manual pages, which are in the server, common,
-client and relay subdirectories. Internet standards relating to the
-DHCP protocol are stored in the doc subdirectory. You will have the
-best luck reading the manual pages if you build this software and then
-install it, although you can read them directly out of the
-distribution if you need to.</P>
-
-<P>DHCP server documentation is in the dhcpd man page. Information about
+client and relay subdirectories. The README file (this file) includes
+late-breaking operational and system-specific information that you
+should read even if you don't want to read the manual pages, and that
+you should *certainly* read if you run into trouble. Internet
+standards relating to the DHCP protocol are stored in the doc
+subdirectory. You will have the best luck reading the manual pages if
+you build this software and then install it, although you can read
+them directly out of the distribution if you need to.
+
+DHCP server documentation is in the dhcpd man page. Information about
the DHCP server lease database is in the dhcpd.leases man page.
Server configuration documentation is in the dhcpd.conf man page as
well as the dhcp-options man page. A sample DHCP server
configuration is in the file server/dhcpd.conf. The source for the
dhcpd, dhcpd.leases and dhcpd.conf man pages is in the server/ sub-
directory in the distribution. The source for the dhcp-options.5
-man page is in the common/ subdirectory.</P>
+man page is in the common/ subdirectory.
-<P>DHCP Client documentation is in the dhclient man page. DHCP client
+DHCP Client documentation is in the dhclient man page. DHCP client
configuration documentation is in the dhclient.conf man page and the
dhcp-options man page. The DHCP client configuration script is
documented in the dhclient-script man page. The format of the DHCP
client lease database is documented in the dhclient.leases man page.
The source for all these man pages is in the client/ subdirectory in
the distribution. In addition, the dhcp-options man page should be
-referred to for information about DHCP options.</P>
+referred to for information about DHCP options.
-<P>DHCP relay agent documentation is in the dhcrelay man page, the source
-for which is distributed in the relay/ subdirectory.</P>
+DHCP relay agent documentation is in the dhcrelay man page, the source
+for which is distributed in the relay/ subdirectory.
-<P>To read installed manual pages, use the man command. Type "man page"
+To read installed manual pages, use the man command. Type "man page"
where page is the name of the manual page. This will only work if
you have installed the ISC DHCP distribution using the ``make install''
-command (described later).</P>
+command (described later).
-<P>If you want to read manual pages that aren't installed, you can type
+If you want to read manual pages that aren't installed, you can type
``nroff -man page |more'' where page is the filename of the
unformatted manual page. The filename of an unformatted manual page
is the name of the manual page, followed by '.', followed by some
@@ -83,78 +84,106 @@ number - 5 for documentation about files, and 8 for documentation
about programs. For example, to read the dhcp-options man page,
you would type ``nroff -man common/dhcp-options.5 |more'', assuming
your current working directory is the top level directory of the ISC
-DHCP Distribution.</P>
+DHCP Distribution.
-<P>If you do not have the nroff command, you can type ``more catpage''
+If you do not have the nroff command, you can type ``more catpage''
where catpage is the filename of the catted man page. Catted man
pages names are the name of the manual page followed by ".cat"
-followed by 5 or 8, as with unformatted manual pages.</P>
+followed by 5 or 8, as with unformatted manual pages.
-<P>Please note that until you install the manual pages, the pathnames of
+Please note that until you install the manual pages, the pathnames of
files to which they refer will not be correct for your operating
-system.</P>
-
-<H4 ID="2">Release status</H4>
-
-<P>This is the final release of Version 2 of the Internet Software
-Consortium DHCP Distribution. In version 2.0, this distribution
-includes a DHCP server, a DHCP client, and a BOOTP/DHCP relay agent.
-This release is stable.</P>
-
-<P>In this release, the server and relay agent currently work well on
-NetBSD, Linux after kernel version 2.0.30, FreeBSD, BSD/OS, Ultrix,
-Digital Alpha OSF/1, Solaris and SunOS 4.1.4. On AIX, HPUX, IRIX and
-Linux 2.0.30, only a single broadcast network interface is supported.
-They also runs on QNX as long as only one broadcast network interface
-is configured and a host route is added from that interface to the
-255.255.255.255 broadcast address.</P>
-
-<P>The DHCP client currently only knows how to configure the network on
-NetBSD, FreeBSD, BSD/os, Linux, Solaris and NextStep. The client
-depends on a system-dependent shell script to do network
+system.
+
+ RELEASE STATUS
+
+This is the second beta release of version 3.0 of the ISC DHCP
+Distribution. Development of this release is approaching the point at
+which it will be frozen, and no significant new features will be
+added.
+
+In this release, the server and relay agent are currently fully
+functional on NetBSD, Linux systems with kernel version 2.2 or later,
+FreeBSD, OpenBSD, BSD/OS, Digital Tru64 Unix and Solaris. The
+software will also run on HP-UX, but only supports a single network
+interface. Ports also exist for QNX, SCO, NeXTStep, and MacOS X, but
+are not in wide use, with all that implies. We are not aware of an
+easy way to get this software running on HP-UX.
+
+The DHCP client currently only knows how to configure the network on
+NetBSD, FreeBSD, OpenBSD, BSD/os, Linux, Solaris and NextStep. The
+client depends on a system-dependent shell script to do network
configuration - support for other operating systems is simply a matter
-of porting this shell script to the new platform.</P>
+of porting this shell script to the new platform.
+
+If you are running the DHCP distribution on a machine which is a
+firewall, or if there is a firewall between your DHCP server(s) and
+DHCP clients, please read the section on firewalls which appears later
+in this document.
-<P>If you wish to run the DHCP Distribution on Linux, please see the
+If you wish to run the DHCP Distribution on Linux, please see the
Linux-specific notes later in this document. If you wish to run on an
SCO release, please see the SCO-specific notes later in this document.
You particularly need to read these notes if you intend to support
Windows 95 clients. If you are running a version of FreeBSD prior to
2.2, please read the note on FreeBSD. If you are running HP-UX or
-Ultrix, please read the notes for those operating systems below.
-If you are running NeXTSTEP, please see the notes on NeXTSTEP below.</P>
+Ultrix, please read the notes for those operating systems below. If
+you are running NeXTSTEP, please see the notes on NeXTSTEP below.
-<P>If you start dhcpd and get a message, "no free bpf", that means you
+If you start dhcpd and get a message, "no free bpf", that means you
need to configure the Berkeley Packet Filter into your operating
system kernel. On NetBSD, FreeBSD and BSD/os, type ``man bpf'' for
-information. On Digital Unix, type ``man pfilt''.</P>
+information. On Digital Unix, type ``man pfilt''.
+
+
+ BUILDING THE DHCP DISTRIBUTION
-<H4 ID="3">Building the DHCP Distribution</H4>
+ UNPACKING IT
-<P>To build the DHCP Distribution, unpack the compressed tar file using
-the tar utility and the gzip command - type something like:</P>
+To build the DHCP Distribution, unpack the compressed tar file using
+the tar utility and the gzip command - type something like:
-<BLOCKQUOTE>
- zcat dhcp-2.0pl5.tar.gz |tar xvf -
-</BLOCKQUOTE>
+ zcat dhcp-3.0.1rc6.tar.gz |tar xvf -
-<P>On BSD/OS, you have to type gzcat, not zcat, and you may run into
-similar problems on other operating systems.</P>
+On BSD/OS, you have to type gzcat, not zcat, and you may run into
+similar problems on other operating systems.
-<P>Now, cd to the dhcp-2.0pl5 subdirectory that you've just created and
-configure the source tree by typing:</P>
+ CONFIGURING IT
+
+Now, cd to the dhcp-3.0.1rc6 subdirectory that you've just
+created and configure the source tree by typing:
-<BLOCKQUOTE>
./configure
-</BLOCKQUOTE>
-<P>If the configure utility can figure out what sort of system you're
+If the configure utility can figure out what sort of system you're
running on, it will create a custom Makefile for you for that
system; otherwise, it will complain. If it can't figure out what
system you are using, that system is not supported - you are on
-your own.</P>
+your own.
+
+ DYNAMIC DNS UPDATES
+
+A fully-featured implementation of dynamic DNS updates is included in
+this release. There are no build dependencies with any BIND version
+- this version can and should just use the resolver in your C library.
+
+There is documentation for the DDNS support in the dhcpd.conf manual
+page - see the beginning of this document for information on finding
+manual pages.
-<P>Once you've run configure, just type ``make'', and after a while
+ LOCALLY DEFINED OPTIONS
+
+In previous versions of the DHCP server there was a mechanism whereby
+options that were not known by the server could be configured using
+a name made up of the option code number and an identifier:
+"option-nnn" This is no longer supported, because it is not future-
+proof. Instead, if you want to use an option that the server doesn't
+know about, you must explicitly define it using the method described
+in the dhcp-options man page under the DEFINING NEW OPTIONS heading.
+
+ BUILDING IT
+
+Once you've run configure, just type ``make'', and after a while
you should have a dhcp server. If you get compile errors on one
of the supported systems mentioned earlier, please let us know.
If you get warnings, it's not likely to be a problem - the DHCP
@@ -162,56 +191,96 @@ server compiles completely warning-free on as many architectures
as we can manage, but there are a few for which this is difficult.
If you get errors on a system not mentioned above, you will need
to do some programming or debugging on your own to get the DHCP
-Distribution working.</P>
+Distribution working.
-<H4 ID="4">Installing the dhcp distribution</H4>
+ INSTALLING THE DHCP DISTRIBUTION
-<P>Once you have successfully gotten the DHCP Distribution to build, you
+Once you have successfully gotten the DHCP Distribution to build, you
can install it by typing ``make install''. If you already have an old
version of the DHCP Distribution installed, you may want to save it
-before typing ``make install''.</P>
-
-<H4 ID="5">Using the dhcp distribution</H4>
-
-<H4 ID="5.1">Linux</H4>
-
-<P>There are three big LINUX issues: the all-ones broadcast address,
+before typing ``make install''.
+
+ USING THE DHCP DISTRIBUTION
+
+ FIREWALL RULES
+
+If you are running the DHCP server or client on a computer that's also
+acting as a firewall, you must be sure to allow DHCP packets through
+the firewall. In particular, your firewall rules _must_ allow packets
+from IP address 0.0.0.0 to IP address 255.255.255.255 from UDP port 68
+to UDP port 67 through. They must also allow packets from your local
+firewall's IP address and UDP port 67 through to any address your DHCP
+server might serve on UDP port 68. Finally, packets from relay agents
+on port 67 to the DHCP server on port 67, and vice versa, must be
+permitted.
+
+We have noticed that on some systems where we are using a packet
+filter, if you set up a firewall that blocks UDP port 67 and 68
+entirely, packets sent through the packet filter will not be blocked.
+However, unicast packets will be blocked. This can result in strange
+behaviour, particularly on DHCP clients, where the initial packet
+exchange is broadcast, but renewals are unicast - the client will
+appear to be unable to renew until it starts broadcasting its
+renewals, and then suddenly it'll work. The fix is to fix the
+firewall rules as described above.
+
+ PARTIAL SERVERS
+
+If you have a server that is connected to two networks, and you only
+want to provide DHCP service on one of those networks (e.g., you are
+using a cable modem and have set up a NAT router), if you don't write
+any subnet declaration for the network you aren't supporting, the DHCP
+server will ignore input on that network interface if it can. If it
+can't, it will refuse to run - some operating systems do not have the
+capability of supporting DHCP on machines with more than one
+interface, and ironically this is the case even if you don't want to
+provide DHCP service on one of those interfaces.
+
+ LINUX
+
+There are three big LINUX issues: the all-ones broadcast address,
Linux 2.1 ip_bootp_agent enabling, and operations with more than one
network interface. There are also two potential compilation/runtime
problems for Linux 2.1/2.2: the "SO_ATTACH_FILTER undeclared" problem
-and the "protocol not configured" problem.</P>
+and the "protocol not configured" problem.
+
+ LINUX: IF_TR.H NOT FOUND
-<H4 ID="5.1.1">So_attach_filter undeclared</H4>
+When you compile the distribution on Linux, you may get an error
+message indicating that the include file if_tr.h could not be found.
+If this happens, go into includes/cf/linux.h and delete the line that
+defined HAVE_TR_SUPPORT, or look into installing a new version of libc
+that includes the if_tr.h file. We will be working on removing this
+problem in the future, but for now, if you run into it, this should be
+a viable workaround.
-<P>In addition, there is a minor issue that we will mention here because
+ LINUX: SO_ATTACH_FILTER UNDECLARED
+
+In addition, there is a minor issue that we will mention here because
this release is so close on the heels of the Linux 2.2 release: there
is a symlink in /usr/include that points at the linux asm headers. It
appears to be not uncommon that this link won't be updated correctly,
-in which case you'll get the following error when you try to build:</P>
+in which case you'll get the following error when you try to build:
-<BLOCKQUOTE>
lpf.c: In function `if_register_receive':
lpf.c:152: `SO_ATTACH_FILTER' undeclared (first use this function)
lpf.c:152: (Each undeclared identifier is reported only once
lpf.c:152: for each function it appears in.)
-</BLOCKQUOTE>
-<P>The line numbers may be different, of course. If you see this
+The line numbers may be different, of course. If you see this
header, your linux asm header link is probably bad, and you should
-make sure it's pointing to correct linux source directory.</P>
+make sure it's pointing to correct linux source directory.
-<H4 ID="5.1.2">Protocol not configured</H4>
+ LINUX: PROTOCOL NOT CONFIGURED
-<P>One additional Linux 2.1/2.2 issue: if you get the following message,
+One additional Linux 2.1/2.2 issue: if you get the following message,
it's because your kernel doesn't have the linux packetfilter or raw
-packet socket configured:</P>
+packet socket configured:
-<BLOCKQUOTE>
Make sure CONFIG_PACKET (Packet socket) and CONFIG_FILTER (Socket
Filtering) are enabled in your kernel configuration
-</BLOCKQUOTE>
-<P>If this happens, you need to configure your Linux kernel to support
+If this happens, you need to configure your Linux kernel to support
Socket Filtering and the Packet socket. You can do this by typing
``make config'', ``make menuconfig'' or ``make xconfig'', and then
enabling the Packet socket and Socket Filtering options that you'll
@@ -222,90 +291,75 @@ afterwards, so that the changes you've made are propogated to the
kernel header files. After you've reconfigured, you need to type
``make'' to build a new Linux kernel, and then install it in the
appropriate place (probably /linux). Make sure to save a copy of your
-old /linux.</P>
+old /linux.
-<P>If the preceding paragraph made no sense to you, ask your Linux
-vendor/guru for help - please don't ask us.</P>
+If the preceding paragraph made no sense to you, ask your Linux
+vendor/guru for help - please don't ask us.
-<P>If you set CONFIG_PACKET=m or CONFIG_FILTER=m, then you must tell the
+If you set CONFIG_PACKET=m or CONFIG_FILTER=m, then you must tell the
kernel module loader to load the appropriate modules. If this doesn't
make sense to you, don't use CONFIG_whatever=m - use CONFIG_whatever=y.
Don't ask for help with this on the DHCP mailing list - it's a Linux
kernel issue. This is probably not a problem with the most recent
-Linux 2.2.x kernels.</P>
+Linux 2.2.x kernels.
+
+ LINUX: BROADCAST
-<H4 ID="5.1.3">Broadcast</H4>
+If you are running a recent version of Linux, this won't be a problem,
+but on older versions of Linux (kernel versions prior to 2.2), there
+is a potential problem with the broadcast address being sent
+incorrectly.
-<P>In order for dhcpd to work correctly with picky DHCP clients (e.g.,
+In order for dhcpd to work correctly with picky DHCP clients (e.g.,
Windows 95), it must be able to send packets with an IP destination
address of 255.255.255.255. Unfortunately, Linux changes an IP
destination of 255.255.255.255 into the local subnet broadcast address
-(here, that's 192.5.5.223). This isn't a problem on Linux 2.2 and
-later kernels, since we completely bypass the Linux IP stack, but on
-old versions of Linux 2.1 and all versions of Linux prior to 2.1, it
-is a problem - pickier DHCP clients connected to the same network as
-the ISC DHCP server or ISC relay agent will not see messages from the
-DHCP server.</P>
-
-<P>It is possible to work around this problem on some versions of Linux
+(here, that's 192.5.5.223).
+
+This isn't generally a problem on Linux 2.2 and later kernels, since
+we completely bypass the Linux IP stack, but on old versions of Linux
+2.1 and all versions of Linux prior to 2.1, it is a problem - pickier
+DHCP clients connected to the same network as the ISC DHCP server or
+ISC relay agent will not see messages from the DHCP server. It *is*
+possible to run into trouble with this on Linux 2.2 and later if you
+are running a verson of the DHCP server that was compiled on a Linux
+2.0 system, though.
+
+It is possible to work around this problem on some versions of Linux
by creating a host route from your network interface address to
255.255.255.255. The command you need to use to do this on Linux
-varies from version to version. The easiest version is:</P>
+varies from version to version. The easiest version is:
-<BLOCKQUOTE>
route add -host 255.255.255.255 dev eth0
-</BLOCKQUOTE>
-<P>On some older Linux systems, you will get an error if you try to do
+On some older Linux systems, you will get an error if you try to do
this. On those systems, try adding the following entry to your
-/etc/hosts file:</P>
+/etc/hosts file:
-<BLOCKQUOTE>
255.255.255.255 all-ones
-</BLOCKQUOTE>
-<P>Then, try:</P>
+Then, try:
-<BLOCKQUOTE>
route add -host all-ones dev eth0
-</BLOCKQUOTE>
-<P>Another route that has worked for some users is:</P>
+Another route that has worked for some users is:
-<BLOCKQUOTE>
route add -net 255.255.255.0 dev eth0
-</BLOCKQUOTE>
-
-<P>If you are not using eth0 as your network interface, you should
-specify the network interface you *are* using in your route command.</P>
-
-<H4 ID="5.1.4">Firewall rules</H4>
-<P>If you are running the DHCP server or client on a Linux system that's
-also acting as a firewall, you must be sure to allow DHCP packets
-through the firewall - Linux firewalls make filtering decisions before
-they make the forwarding decision, so they will filter packets that
-are intended for the firewall itself, as well as packets intended to
-be forwarded. In particular, your firewall rules _must_ allow
-packets from IP address 0.0.0.0 to IP address 255.255.255.255 from UDP
-port 68 to UDP port 67 through. They must also allow packets from
-your local firewall's IP address and UDP port 67 through to any
-address your DHCP server might serve on UDP port 68. Finally,
-packets from relay agents on port 67 to the DHCP server on port 67,
-and vice versa, must be permitted.</P>
+If you are not using eth0 as your network interface, you should
+specify the network interface you *are* using in your route command.
-<H4 ID="5.1.5">IP BOOTP agent</H4>
+ LINUX: IP BOOTP AGENT
-<P>Some versions of the Linux 2.1 kernel apparently prevent dhcpd from
-working unless you enable it by doing the following:</P>
+Some versions of the Linux 2.1 kernel apparently prevent dhcpd from
+working unless you enable it by doing the following:
-<BLOCKQUOTE>
echo 1 >/proc/sys/net/ipv4/ip_bootp_agent
-</BLOCKQUOTE>
-<H4 ID="5.1.6">Multiple interfaces</H4>
-<P>Very old versions of the Linux kernel do not provide a networking API
+ LINUX: MULTIPLE INTERFACES
+
+Very old versions of the Linux kernel do not provide a networking API
that allows dhcpd to operate correctly if the system has more than one
broadcast network interface. However, Linux 2.0 kernels with version
numbers greater than or equal to 2.0.31 add an API feature: the
@@ -313,100 +367,104 @@ SO_BINDTODEVICE socket option. If SO_BINDTODEVICE is present, it is
possible for dhcpd to operate on Linux with more than one network
interface. In order to take advantage of this, you must be running a
2.0.31 or greater kernel, and you must have 2.0.31 or later system
-headers installed *before* you build the DHCP Distribution.</P>
+headers installed *before* you build the DHCP Distribution.
-<P>We have heard reports that you must still add routes to 255.255.255.255
+We have heard reports that you must still add routes to 255.255.255.255
in order for the all-ones broadcast to work, even on 2.0.31 kernels.
In fact, you now need to add a route for each interface. Hopefully
-the Linux kernel gurus will get this straight eventually.</P>
+the Linux kernel gurus will get this straight eventually.
-<P>Linux 2.1 and later kernels do not use SO_BINDTODEVICE or require the
+Linux 2.1 and later kernels do not use SO_BINDTODEVICE or require the
broadcast address hack, but do support multiple interfaces, using the
-Linux Packet Filter.</P>
+Linux Packet Filter.
-<H4 ID="5.2">SCO</H4>
+ SCO
-<P>SCO has the same problem as Linux (described earlier). The thing is,
+SCO has the same problem as Linux (described earlier). The thing is,
SCO *really* doesn't want to let you add a host route to the all-ones
-broadcast address. One technique that has been successful on some
-versions of SCO is the very bizarre command:</P>
+broadcast address.
+
+On more recent versions of SCO, you can do this:
+
+ ifconfig net0 xxx.xxx.xxx.xxx netmask 0xNNNNNNNN broadcast 255.255.255.255
+
+If this doesn't work, you can also try the following strange hack:
-<BLOCKQUOTE>
- ifconfig net0 alias 10.1.1.1 netmask 8.0.0.0
-</BLOCKQUOTE>
+ ifconfig net0 alias 10.1.1.1 netmask 8.0.0.0
-<P>Apparently this works because of an interaction between SCO's support
+Apparently this works because of an interaction between SCO's support
for network classes and the weird netmask. The 10.* network is just a
dummy that can generally be assumed to be safe. Don't ask why this
-works. Just try it. If it works for you, great. If not, SCO is
-supposedly adding hooks to support real DHCP service in a future
-release - I have this on good authority from the people at SCO who do
-*their* DHCP server and client.</P>
+works. Just try it. If it works for you, great. SCO has added
+support for doing DHCP in a more sensible way, but I have not had the
+time or cause to implement them. If you are interested in this, and
+are able to hack your way out of a wet paper back without assistance,
+we'd appreciate it if you'd give it a try, but don't expect too much
+support from us (sorry!).
-<H4 ID="5.3">HP-UX</H4>
+ HP-UX
-<P>HP-UX has the same problem with the all-ones broadcast address that
+HP-UX has the same problem with the all-ones broadcast address that
SCO and Linux have. One user reported that adding the following to
/etc/rc.config.d/netconf helped (you may have to modify this to suit
-your local configuration):</P>
+your local configuration):
-<BLOCKQUOTE>
INTERFACE_NAME[0]=lan0
IP_ADDRESS[0]=1.1.1.1
SUBNET_MASK[0]=255.255.255.0
BROADCAST_ADDRESS[0]="255.255.255.255"
LANCONFIG_ARGS[0]="ether"
DHCP_ENABLE[0]=0
-</BLOCKQUOTE>
-<H4 ID="5.4">Ultrix</H4>
+ ULTRIX
-<P>Now that we have Ultrix packet filter support, the DHCP Distribution
+Now that we have Ultrix packet filter support, the DHCP Distribution
on Ultrix should be pretty trouble-free. However, one thing you do
need to be aware of is that it now requires that the pfilt device be
configured into your kernel and present in /dev. If you type ``man
packetfilter'', you will get some information on how to configure your
kernel for the packet filter (if it isn't already) and how to make an
-entry for it in /dev.</P>
+entry for it in /dev.
-<H4 ID="5.5">FreeBSD</H4>
+ FreeBSD
-<P>Versions of FreeBSD prior to 2.2 have a bug in BPF support in that the
+Versions of FreeBSD prior to 2.2 have a bug in BPF support in that the
ethernet driver swaps the ethertype field in the ethernet header
downstream from BPF, which corrupts the output packet. If you are
running a version of FreeBSD prior to 2.2, and you find that dhcpd
can't communicate with its clients, you should #define BROKEN_FREEBSD_BPF
-in site.h and recompile.</P>
+in site.h and recompile.
-<H4 ID="5.6">NeXTStep</H4>
+ NeXTSTEP
-<P>The NeXTSTEP support uses the NeXTSTEP Berkeley Packet Filter
+The NeXTSTEP support uses the NeXTSTEP Berkeley Packet Filter
extension, which is not included in the base NextStep system. You
-must install this extension in order to get dhcpd or dhclient to work.</P>
+must install this extension in order to get dhcpd or dhclient to work.
-<H4 ID="5.7">Solaris</H4>
+ SOLARIS
-<P>One problem which has been observed and is not fixed in this
+One problem which has been observed and is not fixed in this
patchlevel has to do with using DLPI on Solaris machines. The symptom
of this problem is that the DHCP server never receives any requests.
-If you are using Solaris 2.6, and you encounter this symptom, and
-you are running the DHCP server on a machine with a single broadcast
-network interface, you may wish to edit the includes/site.h file and
-uncomment the #define USE_SOCKETS line. Then type ``make clean;
-make''.</P>
-
-<P>The DHCP client on Solaris will only work with DLPI. If you run it
+This has been observed with Solaris 2.6 and Solaris 7 on Intel x86
+systems, although it may occur with other systems as well. If you
+encounter this symptom, and you are running the DHCP server on a
+machine with a single broadcast network interface, you may wish to
+edit the includes/site.h file and uncomment the #define USE_SOCKETS
+line. Then type ``make clean; make''.
+
+The DHCP client on Solaris will only work with DLPI. If you run it
and it just keeps saying it's sending DHCPREQUEST packets, but never
gets a response, you may be having DLPI trouble as described above.
-If so, you are SOL. Also, because Solaris requires you to "plumb" an
-interface before it can be detected by the DHCP client, you must
-either specify the name(s) of the interface(s) you want to configure
-on the command line, or must plumb the interfaces prior to invoking
-the DHCP client. This can be done with ``ifconfig iface plumb'',
-where iface is the name of the interface (e.g., ``ifconfig hme0
-plumb'').</P>
-
-<P>It should be noted that Solaris versions from 2.6 onward include a
+If so, we have no solution to offer at this time. Also, because
+Solaris requires you to "plumb" an interface before it can be detected
+by the DHCP client, you must either specify the name(s) of the
+interface(s) you want to configure on the command line, or must plumb
+the interfaces prior to invoking the DHCP client. This can be done
+with ``ifconfig iface plumb'', where iface is the name of the
+interface (e.g., ``ifconfig hme0 plumb'').
+
+It should be noted that Solaris versions from 2.6 onward include a
DHCP client that you can run with ``/sbin/ifconfig iface dhcp start''
rather than using the ISC DHCP client. The feature set of the Solaris
client is different (not necessarily better or worse) than that of the
@@ -415,121 +473,177 @@ use that. Please do not ask for help in using the Solaris DHCP client
on Internet Software Consortium mailing lists - that's why you're
paying Sun the big bucks. If you're having a problem with the
Solaris client interoperating with the ISC dhcp server, that's another
-matter, but please check with Sun first.</P>
+matter, but please check with Sun first.
-<H4 ID="6">Support</H4>
+ SUPPORT
-<P>The Internet Software Consortium DHCP server is not a commercial
-product, and is not supported in that sense. However, it has
-attracted a fairly sizable following on the Internet, which means that
-there are a lot of knowledgable users who may be able to help you if
-you get stuck. These people generally read the dhcp-server@fugue.com
-mailing list.</P>
+The Internet Software Consortium DHCP server is not a commercial
+product, and is not supported by the ISC. However, it has attracted a
+fairly sizable following on the Internet, which means that there are a
+lot of knowledgable users who may be able to help you if you get
+stuck. These people generally read the dhcp-server@isc.org mailing
+list.
-<P>If you are going to use dhcpd, you should probably subscribe to the
+If you are going to use dhcpd, you should probably subscribe to the
dhcp-server and dhcp-announce mailing lists. If you will be using
-dhclient, you should subscribe to the dhcp-client mailing list.</P>
-
-<P>If you need help, you should ask on the dhcp-server or dhcp-client
-mailing list (or both) - whichever is appropriate to your
-application. This includes reporting bugs. Please do not report
-bugs in old software releases - fetch the latest release and see if
-the bug is still in that copy of the software, and if it's not, _then_
-report it. It's okay to report bugs in the latest patchlevel of a
-major version that's not the most recent major version, though - for
-example, if you're running 2.0, you don't have to upgrade to 3.0
-before you can report bugs.</P>
-
-<H4 ID="6.1">Please read this readme file carefully before reporting bugs!</H4>
-<H4>How to report bugs</H4>
-
-<P>When you report bugs, please provide us complete information. A list
-of information we need follows. Please read it carefully, and put
-all the information you can into your initial bug report, so that we
-don't have to ask you any questions in order to figure out your
-problem.</P>
-
-<UL>
-<LI>The specific operating system name and version of the
-machine on which the DHCP server or client is running.
-<LI>The specific operating system name and version of the
-machine on which the client is running, if you are having
-trouble getting a client working with the server.
-<LI>If you're running Linux, the version number we care about is
-the kernel version and maybe the library version, not the
-distribution version - e.g., while we don't mind knowing
-that you're running Redhat version mumble.foo, we must know
-what kernel version you're running, and it helps if you can
-tell us what version of the C library you're running,
-although if you don't know that off the top of your head it
-may be hard for you to figure it out, so don't go crazy
-trying.
-<LI>The specific version of the DHCP distribution you're
-running, for example 2.0b1pl19, not 2.0.
-<LI>Please explain the problem carefully, thinking through what
-you're saying to ensure that you don't assume we know
-something about your situation that we don't know.
-<LI>Include your dhcpd.conf and dhcpd.leases file if they're not
-huge (if they are huge, we may need them anyway, but don't
-send them until you're asked).
-<LI>Include a log of your server or client running until it
-encounters the problem - for example, if you are having
-trouble getting some client to get an address, restart the
-server with the -d flag and then restart the client, and
-send us what the server prints. Likewise, with the client,
-include the output of the client as it fails to get an
-address or otherwise does the wrong thing. Do not leave
-out parts of the output that you think aren't interesting.
-<LI>If the client or server is dumping core, please run the
-debugger and get a stack trace, and include that in your
-bug report. For example, if your debugger is gdb, do the
-following:
-
-<BLOCKQUOTE>
+dhclient, you should subscribe to the dhcp-client mailing list.
+
+If you need help, you should ask on the dhcp-server or dhcp-client
+mailing list - whichever is appropriate to your application. Support
+requests for the ISC DHCP client should go to dhcp-client@isc.org.
+Support requests for the DHCP server should go to dhcp-server@isc.org.
+If you are having trouble with a combination of the client and server,
+send the request to dhcp-server@isc.org. Please do not cross-post to
+both lists under any circumstances.
+
+WHERE TO REPORT BUGS: If you want the act of sending in a bug report
+to result in you getting help in the form of a fixed piece of
+software, you are asking for help. Your bug report is helpful to us,
+but fundamentally you are making a support request, so please use the
+addresses described in the previous paragraphs. If you are _sure_ that
+your problem is a bug, and not user error, or if your bug report
+includes a patch, you can send it to dhcp-bugs@isc.org without
+subscribing. This mailing list goes into a bug tracking system, so
+you don't need to check periodically to see if we still remember the
+bug - if you haven't been notified that the bug has been closed, we
+still consider it a bug, and still have it in the system.
+
+PLEASE DO NOT REPORT BUGS IN OLD SOFTWARE RELEASES! Fetch the latest
+release and see if the bug is still in that version of the software,
+and if it's not, _then_ report it. It's okay to report bugs in the
+latest patchlevel of a major version that's not the most recent major
+version, though - for example, if you're running 2.0, you don't have
+to upgrade to 3.0 before you can report bugs.
+
+PLEASE DO NOT REPORT BUGS IF YOU ARE RUNNING A VERSION OF THE ISC
+DHCP DISTRIBUTION THAT YOU DIDN'T GET FROM THE ISC! Free operating
+system distributions are notorious for including outdated versions of
+software, and also versions of software that were not compiled on your
+particular version of the operating system. These versions
+frequently do not work. Getting a source distribution from the ISC
+and installing it frequently *does* work. Please try this *before*
+asking for help.
+
+PLEASE READ THIS README FILE CAREFULLY BEFORE REPORTING BUGS,
+PARTICULARLY THE SECTION BELOW ON WHAT TO INCLUDE IN A BUG REPORT OR
+HELP REQUEST.
+
+PLEASE DO NOT SEND REQUESTS FOR SUPPORT DIRECTLY TO THE ENGINEERS WHO
+WORK ON THE ISC DHCP DISTRIBUTION! *PARTICULARLY*, DO NOT SEND MAIL
+TO THE ENGINEERS BECAUSE YOU AREN'T SURE TO WHOM YOU SHOULD SEND MAIL
+- if you aren't sure, *ask* on the dhcp-server@isc.org or
+dhcp-client@isc.org mailing list.
+
+The number of people using the DHCP Distribution is sufficiently large
+that if we take interrupts every time any one of those people runs
+into trouble, we will never get any more coding done. If you send a
+support request directly to any ISC or Nominum engineer, we will
+forward it to the mailing list, or possibly ignore it, depending on
+how much stress we are under at the time.
+
+Please do not Cc: us on mail you send to these lists - we read both
+mailing lists, so this just means we get two copies!
+
+If your question can only be answered by one of the engineers, send it
+to the appropriate public mailing list anyway - we will answer it
+there. When we have time.
+
+Please do not think "Oh, I don't want to bother the whole mailing list
+with this question." If you are too embarrassed to ask publically,
+get a support contract.
+
+If you are concerned about bothering everybody on the list, that's
+great, but that's what the list is there for. When you send mail to
+one of the engineers, you are taking resources away from everybody on
+the mailing list *anyway* - they just don't know it.
+
+We're not writing this because we don't respect you - we really do
+want to help you, and we appreciate your bug reports and comments.
+But please use the mechanisms we have in place to provide you with
+help, because otherwise you are almost certainly depriving someone
+else of our help.
+
+PLEASE DO NOT CALL US ON THE PHONE FOR HELP! Answering the phone
+takes a lot more of our time and attention than answering email. If
+you do call us on the phone, we will tell you to send email to the
+mailing list or buy a support contract, so please don't waste your
+time or ours. If you have a support contract, please use the support
+channel mentioned in the support contract - otherwise you probably
+won't get timely support unless you happen to ask an interesting
+question and we happen to have some time to kill, because we can't
+tell you're a support customer if you send mail to the public mailing
+lists.
+
+ HOW TO REPORT BUGS OR REQUEST HELP
+
+When you report bugs or ask for help, please provide us complete
+information. A list of information we need follows. Please read it
+carefully, and put all the information you can into your initial bug
+report, so that we don't have to ask you any questions in order to
+figure out your problem. If you need handholding support, please
+consider contacting a commercial provider of the ISC DHCP
+Distribution.
+
+ 1. The specific operating system name and version of the
+ machine on which the DHCP server or client is running.
+ 2. The specific operating system name and version of the
+ machine on which the client is running, if you are having
+ trouble getting a client working with the server.
+ 3. If you're running Linux, the version number we care about is
+ the kernel version and maybe the library version, not the
+ distribution version - e.g., while we don't mind knowing
+ that you're running Redhat version mumble.foo, we must know
+ what kernel version you're running, and it helps if you can
+ tell us what version of the C library you're running,
+ although if you don't know that off the top of your head it
+ may be hard for you to figure it out, so don't go crazy
+ trying.
+ 4. The specific version of the DHCP distribution you're
+ running, for example "2.0b1pl19", not "2.0".
+ 5. Please explain the problem carefully, thinking through what
+ you're saying to ensure that you don't assume we know
+ something about your situation that we don't know.
+ 6. Include your dhcpd.conf and dhcpd.leases file if they're not
+ huge (if they are huge, we may need them anyway, but don't
+ send them until you're asked). Huge means more than 100
+ kilobytes each.
+ 7. Include a log of your server or client running until it
+ encounters the problem - for example, if you are having
+ trouble getting some client to get an address, restart the
+ server with the -d flag and then restart the client, and
+ send us what the server prints. Likewise, with the client,
+ include the output of the client as it fails to get an
+ address or otherwise does the wrong thing. Do not leave
+ out parts of the output that you think aren't interesting.
+ 8. If the client or server is dumping core, please run the
+ debugger and get a stack trace, and include that in your
+ bug report. For example, if your debugger is gdb, do the
+ following:
+
gdb dhcpd dhcpd.core
(gdb) where
[...]
(gdb) quit
-</BLOCKQUOTE>
-
-<P>This assumes that it's the dhcp server you're debugging, and
-that the core file is in dhcpd.core.</P>
-</UL>
-
-<P><EM>Please, <B>do not</B></EM> send queries about non-isc clients
-to the dhcp-client mailing list. If you're asking about them on an
-ISC mailing list, it's probably because you're using the ISC DHCP
-server, so ask there. If you are having problems with a client whose
-executable is called dhcpcd, this is <EM>not</EM> the ISC DHCP client,
-and we probably can't help you with it.</P>
-
-<P>Please see <A HREF="http://www.fugue.com/dhcp/lists">
-http://www.fugue.com/dhcp/lists</A> for details on how to subscribe.
-If you don't have WorldWide Web access, you can send mail to
-dhcp-request@fugue.com and tell me which lists you want to subscribe
-to, but please use the web interface if you can, since I have to
-handle the -request mailing list manually, and I will give you the
-third degree if you make me do your subscription manually.</P>
-
-<P><EM>Please do not send requests for help directly to the author!</EM>
-The number of people using the DHCP Distribution is sufficiently large
-that if we take an interrupt every time any one of those people runs into
-trouble, we will never get any more coding done.</P>
-
-<P><EM>Please do not call the author on the phone for support!</EM>
-Answering the phone takes a lot more time and attention than answering
-email. If you do call on the phone, you will be told to send email to
-the mailing list, so there's no point in doing it.</P>
-
-<P><B>Exception:</B> if you are a support customer, you already know
-how to get in touch with us. To become a support customer, see our
-<A HREF="/isc/ISC_HTML/services/support/index.phtml">Support web
-page</A>.
-<H4 ID="7">Known bugs</H4>
+ This assumes that it's the dhcp server you're debugging, and
+ that the core file is in dhcpd.core.
+ 9. If you know that the problem is an actual bug, and you can
+ reproduce the bug, you can skip steps 6 through 8 and instead
+ capture a trace file using the -tf flag (see the man page for
+ details). If you do this, and there is anything in your
+ dhcp configuration that you are not willing to make public,
+ please send the trace file to dhcp-bugs@isc.org and NOT to
+ dhcp-server@isc.org, because the tracefile contains your entire
+ dhcp configuration.
+
+PLEASE DO NOT send queries about non-isc clients to the dhcp-client
+mailing list. If you're asking about them on an ISC mailing list,
+it's probably because you're using the ISC DHCP server, so ask there.
+If you are having problems with a client whose executable is called
+dhcpcd, this is _not_ the ISC DHCP client, and we probably can't help
+you with it.
+
+Please see http://www.isc.org/services/public/lists/dhcp-lists.html
+for details on how to subscribe to the ISC DHCP mailing lists.
-<P>This release of the DHCP Distribution does not yet contain support for
-DHCPINFORM. The Vendor Specific Data option is not supported. Site-
-specific options are not supported. All of these are supported in the
-3.0 release of the DHCP distribution, which is now in beta testing.</P>
diff --git a/contrib/isc-dhcp/RELNOTES b/contrib/isc-dhcp/RELNOTES
index de029af09412..df58adc6b6ba 100644
--- a/contrib/isc-dhcp/RELNOTES
+++ b/contrib/isc-dhcp/RELNOTES
@@ -1,766 +1,1003 @@
- Internet Software Consortium
- Dynamic Host Configuration Protocol Distribution
- Version 2 Patchlevel 5
- September 6, 2000
+ Internet Software Consortium DHCP Distribution
+ Version 3.0.1
+ Release Candidate 6
+ January 17, 2002
Release Notes
-Version 2 of the ISC DHCP Distribution includes the ISC DHCP server,
-DHCP Client and DHCP/BOOTP Relay Agent.
-
-This version has been in a near feature freeze since January of 1998,
-was in Beta test from that time to June of 1999, and has now been
-released in its final form. It has a number of important features,
-and is the release that we would expect most sites to run.
+ NEW FEATURES
+
+Version 3 of the ISC DHCP Distribution includes the following features
+that are new since version 2.0:
+
+ - DHCP Failover Protocol support
+ - OMAPI, an API for accessing and modifying the DHCP server and
+ client state.
+ - Conditional behaviour
+ - Storing arbitrary information on leases
+ - Address pools with access control
+ - Client classing
+ - Address allocation restriction by class
+ - Relay agent information option support
+ - Dynamic DNS updates
+ - Many bug fixes, performance enhancements, and minor new DHCP
+ protocol features.
+
+This is a release candidate for a minor bug fix release to follow ISC
+DHCP 3.0. The main bug fixed here is a bug in the subclass allocation
+code that could result in a memory smash. Any users of the ISC DHCP server
+who are using subclasses should seriously consider upgrading to 3.0.1
+either now or when the final 3.0.1 release comes out.
+
+If you are running 3.0 beta 1 and are doing dynamic DNS updates, the
+lease file is no longer forward-compatible to 3.0 final. A script
+has been provided to convert 3.0b1 lease files. This is in
+contrib/3.0b1-lease-convert.
For information on how to install, configure and run this software,
as well as how to find documentation and report bugs, please consult
the README file.
- CHANGELOG
+The Dynamic DNS Update support is a descendent of an implementation
+done by Lans Carstensen and Brian Dols at Rose-Hulman Institute of
+Technology, Jim Watt at Applied Biosystems, Irina Goble at Integrated
+Measurement Systems, Igor Sharfmesser at Kazakh Telecom, and Brian
+Murrell at BC Tel Advanced Communications. I'd like to express my
+thanks to all of these good people here, both for working on the code
+and for prodding me into improving it.
-This log describes the changes that have been made in version 2.0
-since June of 1997.
+ Changes since 3.0.1rc5
- CHANGES FROM VERSION 2.0 PATCHLEVEL 4
+- Include some new documentation and changes provided by Karl Auer.
-- Fix a prototype mismatch that causes compiles to fail on some architectures.
+- Add a workaround for some Lexmark printers that send a double-NUL-
+ terminated host-name option, which would break DNS updates.
-- Two minor cosmetic changes to manual pages.
+- Fix an off-by-one error in the MAC-address checking code for
+ DHCPRELEASE that was added in 3.0.1rc5.
- CHANGES FROM VERSION 2.0 PATCHLEVEL 3
+- Fix a bug where client-specific information was not being discarded
+ from the lease when it expired or was released, resulting in
+ problems if the lease was reallocated to a different client.
-- Fix a bug introduced in the client in the previous patchlevel where the
- broadcast would be set to the subnet number instead of the broadcast
- address.
+- If more than one allocation pool is specified that has the same set
+ of constraints as another allocation pool on the same shared
+ network, merge the two pools.
- CHANGES FROM VERSION 2.0 PATCHLEVEL 2
+- Don't print an error in fallback_discard, since this just causes
+ confusion and does not appear to be helping to encourage anyone to
+ fix this bug.
-- Rather than calling a client environment setup script, set the
- environment up directly, so as to avoid any possible exploit making
- use of clever shell metacharacter hacks. This is a security fix
- that applies to the DHCP client *only*.
+ Changes since 3.0.1rc4
- CHANGES FROM VERSION 2.0 PATCHLEVEL 1
+- Fix a bug that would cause the DHCP server to spin if asked to parse
+ a certain kind of incorrect statement.
-- Fix a case where an unitialized pointer could result from an exceptional
- case in DHCPRELEASE and cause a core dump.
+- Fix a related bug that would prevent an error from being reported in
+ the same case.
- CHANGES FROM VERSION 2.0
+- Additional documentation.
-- Clean up DHCPRELEASE support.
+- Make sure that the hardware address matches the lease when
+ processing a DHCPRELEASE message.
-- Don't use the broadcast flag when doing BOOTP unless we need to.
+ Changes since 3.0.1rc3
-- Clean up the fallback mess.
+- A minor bug fix in the arguments to a logging function call.
+- Documentation update for dhcpd.conf.
-- Quote all shell special characters in the client script.
+ Changes since 3.0.1rc2
-- Fix ethernet header alignment on arm32.
+- Allow the primary to send a POOLREQ message. This isn't what the current
+ failover draft says to do, so we may have to back it out if I can't get the
+ authors to relent, but the scheme for balancing that's specified in the
+ current draft seems needlessly hairy, so I'm floating a trial balloon.
+ The rc1 code did not implement the method described in the draft either.
-- Clarify the "no subnet declaration" message.
+ Changes since 3.0.1rc1
-- Correctly store the tftp server name in the lease file and the
- client script file.
+- Treat NXDOMAIN and NXRRSET as success when we are trying to delete a
+ domain or RRSET. This allows the DHCP server to forget about a name
+ it added to the DNS once it's been removed, even if the DHCP server
+ wasn't the one that removed it.
-- Avoid a potential spin loop in client when script file creation
- fails for reasons other than the presence of an existing file of the
- same name.
+- Install defaults for failover maximum outstanding updates and maximum
+ silent time. This prevents problems that might occur if these values
+ were not configured.
-- Add support for Linux kernel versions greater than 2.2.
+- Don't do DDNS deletes if ddns-update-style is none.
-- Fix a problem in raw.c on Irix. Thanks to Don Badrak for the
- patch.
+- Return relay agent information options in DHCPNAK. This prevents DHCPNAK
+ messages from being dropped when the relay agent information option contains
+ routing information.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 29
+- Fix a problem where coming up in recover wouldn't result in an update
+ request being sent.
-- Define BYTE_ORDER in includes/cf/hpux.h so that ip.h will compile
- correctly on HP-UX.
+- Add some more chatty messages when we start a recovery update and when it's
+ done.
-- Fix a long-standing but minor bug in the way the program name for
- syslog was derived.
+- Fix a possible problem where some state might have been left around
+ after the peer lost contact and regained contact about how many updates
+ were pending.
-- Fix a long-standing bug that prevented the DHCP server from broadcasting
- responses to BOOTP clients that requested a broadcast response.
+- Don't nix a lease update because of a lease conflict. This test has
+ never (as far as I know) prevented a mistake, and it appears to cause
+ problems with failover.
-- In dhcprequest(), check to make sure that there's a lease before trying
- to acknowledge it to the client. This fixes a potential core dump that
- a few people observed.
+- Add support in rc history code for keeping a selective history, rather
+ than a history of all references and dereferences. This code is only used
+ when extensive additional debugging is enabled.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 28
+ Changes since 3.0
-- Fix some pastos I introduced when merging Andrew Chittenden's token
- ring support.
+- Make allocators for hash tables. As a side effect, this fixes a memory
+ smash in the subclass allocation code.
-- Apply a patch to the token ring support from Andrew Chittenden.
+- Fix a small bug in omshell where if you try to close an object when
+ no object is open, it dumps core.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 27
+- Fix an obscure coredump that could occur on shutdown.
-- Add dependencies to makefiles.
+- Fix a bug in the recording of host declaration rubouts in the lease file.
-- Don't use ping -w 1 in freebsd client script.
+- Fix two potential spins in the host deletion code.
-- Token ring support for LPF, contributed by Andrew Chittenden.
+- Fix a core dump that would happen if an application tried to update
+ a host object attribute with a null value.
-- Fix a subtle bug that would cause the server to respond incorrectly
- in some cases when the client sent duplicate DHCPREQUEST packets.
+ Changes since 3.0 Release Candidate 12
-- Fix option pretty printing for 'X' format.
+- Fix a memory leak in the evaluation code.
-- Add some special cases to deal with DHCPREQUEST packets from RFC1541
- clients.
+- Fix an obscure core dump.
-- Fix an obscure bug in nested subnet mask handling.
+- Print a couple of new warnings when parsing the configuration file
+ when crucial information is left out.
-- Fix a bug in abandoned lease reclamation.
+- Log "no free leases" as an error.
-- Allow maximum message size to be set in configuration file.
+- Documentation updates.
-- Allow parameter request list to be supplied in configuration file.
+ Changes since 3.0 Release Candidate 11
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 26
+- Always return a subnet selection option if one is sent.
-- Fix UDP/IP checksum code
+- Fix a warning that was being printed because an automatic data
+ structure wasn't zeroed.
-- Fix UDP payload length computation to prevent logging of spurious
- errors.
+- Fix some failover state transitions that were being handled
+ incorrectly.
-- Support compilation on MacOS X
+- When supersede_lease is called on a lease whose end time has already
+ expired, but for which a state transition has not yet been done, do
+ a state transition. This fixes the case where if the secondary
+ allocated a lease to a client and the lease "expired" while the
+ secondary was in partner-down, no expiry event would actually
+ happen, so the lease would remain active until the primary was
+ restarted.
-- Add support for some options that were added in RFC2132.
+ Changes since 3.0 Release Candidate 10
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 25
+- Fix a bug that was preventing released leases from changing state
+ in failover-enabled pools.
-- Use the udp header's length rather than computing the length based
- on the number of bytes received, because some broken relay agents
- send packets with ip lengths that are longer than then sum of the ip
- header size and the udp length.
+- Fix a core dump in the client identifier finder code (for host
+ declarations).
-- Do path keyword substitution on unformatted manual pages before
- installing them.
+- Finish fixing a bug where bogus data would sometimes get logged to
+ the dhclient.leases file because it was opened as descriptor 2.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 24
+- Fix the linux dhclient-script according to suggestions made by
+ several people on the dhcp-client mailing list.
-- D'oh! Fix a really stupid mistake in hash.c.
+- Log successful DNS updates at LOG_INFO, not LOG_ERROR.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 23
+- Print an error message and refuse to run if a failover peer is
+ defined but not referenced by any pools.
-- Support an always-reply-rfc1048 flag, which says to reply with an
- RFC1048-style vendor extensions buffer even if the client didn't
- send an RFC1048-style magic number.
+- Correct a confusing error message in failover.
-- Fix a null pointer dereference.
+ Changes since 3.0 Release Candidate 9
-- Use netmask from subnet if no netmask option specified.
+- Fix a bug in lease allocation for Dynamic BOOTP clients.
-- IRIX support (thanks to Don Badrak).
+ Changes since 3.0 Release Candidate 8 Patchlevel 2
-- Install unformatted manual pages on Linux.
+- Fix a bug that prevented update-static-leases from working.
-- Add note in README about zcat vs. gzcat on BSD/os.
+- Document failover-state OMAPI object.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 22
+- Fix a compilation error on SunOS 4.
-- Test for lease before dereferencing it in dhcprequest.
+ Changes since 3.0 Release Candidate 8 Patchlevel 1
-- Free the client parameter request list in dhcpnak if there is one.
+- Fix a parsing bug that broke dns updates (both interim and ad-hoc).
+ This was introduced in rc8pl1 as an unintended result of the memory
+ leakage fixes that were in pl1.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 21
+- Fix a long-standing bug where the server would record that an update
+ had been done for a client with no name, even though no update had
+ been done, and then when the client's lease expired the deletion of
+ that nonexistant record would time out because the name was the null
+ string.
-- Fix a pasto in options.c that will cause a core dump whenever a
- client sends in a request without a parameter request list.
+- Clean up the omshell, dhcpctl and omapi man pages a bit.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 20
+ Changes since 3.0 Release Candidate 8
-- Actually do the client fix mentioned below - Patchlevel 20 only contained
- half of the fix.
+- Fix a bug that could cause the DHCP server to spin if
+ one-lease-per-client was enabled.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 19
+- Fix a bug that was causing core dumps on BSD/os in the presence of
+ malformed packets.
-- Removed arp table clearing code from solaris client script.
+- In partner-down state, don't restrict lease lengths to MCLT.
-- Document Linux "protocol not configured" error more thoroughly.
+- On the failover secondary, record the MCLT received from the primary
+ so that if we come up without a connection to the primary we don't
+ wind up giving out zero-length leases.
-- Clean up some unused variables.
+- Fix some compilation problems on BSD/os.
-- Add entry and exit hooks to all dhcp client scripts, along with a
- make_resolv_conf function that can be redefined in the entry hooks.
- Document this new feature set.
+- Fix a bunch of memory leaks.
-- Fix client to take advantage of network APIs that allow it to
- receive a unicast instead of requesting that the DHCP server
- broadcast its response.
+- Fix a couple of bugs in the option printer.
-- Add -pf flag to all daemons allowing user to specify PID file name
- on command line.
+- Fix an obscure error reporting bug in the dns update code, and also
+ make the message clearer when a key algorithm isn't supported.
-- Undo a previous change that attempted to be clever about testing
- interface flags but wound up being stupid instead.
+- Fix a bug in the tracing code that prevented trace runs that used
+ tcp connections from being played back.
-- Enforce access control on DHCPREQUEST messages as well as
- DHCPDISCOVER messages.
+- Add some additional debugging capability for catching memory leaks
+ on exit.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 18
+- Make the client release the lease correctly on shutdown.
-- Support added for AIX 4.1.5.0 (and hopefully other versions).
+- Add some configurability to the build system.
-- Use /var/run instead of /etc on Digital Unix.
+- Install omshell manual page in man1, not man8.
-- Change DHCP client exponential backoff code to back off more slowly,
- so that it is more robust in lossy environments, at the expense of
- being a bit less polite to the server.
+- Craig Gwydir sent in a patch that fixes a long-standing bug in the
+ DHCP client that could cause core dumps, but that for some reason
+ hadn't been noticed until now.
-- Don't request a specific lease interval in the client unless the
- user says to do so.
+ Changes since 3.0 Release Candidate 7
-- Don't print DHCPXXX in wrong xxx messages unless DEBUG is defined.
+- Fix a bug in failover where we weren't sending updates after a
+ transition from communications-interrupted to normal.
-- Fix handling of secs field.
+- Handle expired/released/reset -> free transition according to the
+ protocol specification (this works - the other way not only wasn't
+ conformant, but also didn't work).
-- Fix handling of append statement.
+- Add a control object in both client and server that allows either
+ daemon to be shut down cleanly.
-- Fix documentation for append and prepend statements.
+- When writing a lease, if we run out of disk space, shut down the
+ output file and insist on writing a new one before proceeding.
-- Fix server support for parameter request list and maximum message
- size.
+- In the server, if the OMAPI listener port is occupied, keep trying
+ to get it, rather than simply giving up and exiting.
-- Parameterize more hardware types in discover_interfaces. Check for
- IFF_BROADCAST instead of !IFF_POINTOPOINT
+- Support fetching variables from leases and also updating and adding
+ variables to leases via OMAPI.
-- Print kernel configuration warning message if we get EINVAL when
- opening or configuring the Linux packet filter.
+- If two failover peers have wildly different clocks, refuse to start
+ doing failover.
-- Fix a bug in UDP checksum code (thanks to John Nemeth for figuring
- this out) and re-enable UDP checksumming. This allows the client
- to work with some buggy DHCP servers that can't handle zero
- checksums in the UDP header - in particular, the one John's cable
- modem ISP is using.
+- Fix a bug in the DNS update code that could cause core dumps when
+ running on alpha processors.
-- Don't report packet header checksum errors unless we see a lot of
- them. It's perfectly normal for some number of checksum errors to
- occur.
+- Fixed a bug in ddns updates for static lease entries, thanks to a
+ patch from Andrey M Linkevitch.
-- Refer to the dhcpd.leases man page when printing an error message
- prior to exiting because there's no lease database.
+- Add support for Darwin/MacOS X
-- Add information to the README telling the reader how to get to the
- manual pages.
+- Install omshell (including new documentation).
-- Fix the server packet transmission code to unicast when it can.
+- Support DNS updates in the client (this is a very obscure feature
+ that most DHCP client users probably will not be able to use).
-- Fix a typo in the dhcpd.conf manual page.
+- Somewhat cleaner status logging in the client.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 17
+- Make OMAPI key naming syntax compatible with the way keys are
+ actually named (key names are domain names).
-- Fix a bug in the relay agent where messages to the client would be
- unicast in the IP header but broadcast in the link header. The
- Microsoft DHCP client would reject such packets, preventing it from
- being configured. This was only a problem on non-socket-API
- platforms.
+- Fix a bug in the lease file writer.
-- Do not attempt to reclaim requested abandoned leases in response to
- DHCPDISCOVER messages.
+- Install DHCP ISC headers in a different place than BIND 9 ISC
+ headers, to avoid causing trouble in BIND 9 builds.
-- Allow the maximum lease time parameter in a host declaration to
- override the maximum lease time parameter in a subnet declaration.
+- Don't send updates for attributes on an object when the attributes
+ haven't changed. Support deleting attributes on remote objects.
-- Better document the -p flag for dhclient, dhcrelay and dhcpd.
+- Fix a number of bugs in omshell, and add the unset and refresh
+ statements.
-- Apply John Wehle's patch to fix the endianness bug in the dlpi
- packet filter on Solaris.
+- Handle disconnects in OMAPI a little bit more intelligently (so that
+ the caller gets ECONNRESET instead of EINVAL).
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 16
+- Fix a bunch of bugs in the handling of clients that have existing
+ leases when the try to renew their leases while failover is
+ operating.
-- Fix linux man page install location.
+ Changes since 3.0 Release Candidate 6
-- Fix some confusion in the dhclient-script man page.
+- Fix a core dump that could happen when processing a DHCPREQUEST from
+ a client that had a host declaration that contained both a
+ fixed-address declaration and a dhcp-client-identifier option
+ declaration, if the client identifier was longer than nine bytes.
-- Fix error in includes/cf/linux.h that would have made network API
- selections in site.h work incorrectly.
+- Fix a memory leak that could happen in certain obscure cases when
+ using omapi to manipulate leases.
-- Fix some major stupidity in the code that figures out where or not a
- client owns a particular lease.
+- Fix some bugs and omissions in omshell.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 15
-- Fix Makefile.conf on Linux to refer to /var/state/dhcp instead of
- /var/state/dhcpd.
+ Changes since 3.0 Release Candidate 5
-- Eliminate redundant #defines in includes/cf/linux.h (for neatness).
+- Fix a bug in omapi_object_dereference that prevented objects in
+ chains from having their reference counts decreased on dereference.
-- Fix an obscure case where dhcpd is started by the /etc/rc system
- with exactly the same pid each time, dhcpd.pid is not erased on
- reboot, and therefore dhcpd would detect a server (itself) with the
- pid in dhcpd.pid and decide that another server was running and
- exit.
+- Fix a bug in omapi_object_dereference that would prevent object
+ chains from being freed upon removal of the last reference external
+ to the chain.
+
+- Fix a number of other memory leaks in the OMAPI protocol subsystem.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 14
+- Add code in the OMAPI protocol handler to trace memory leakage.
-- Install the dhcp databases in /var/state/dhcp instead of /etc or
- /var/dhcpd, as suggested in the Linux Filesystem Hierarchy
- Standard.
+- Clean up the memory allocation/reference history printer.
-- Fix an endianness bug in dlpi.c. As a consequence, make the
- Solaris/i386 use dlpi again.
+- Support input of dotted quads and colon-seperated hex lists as
+ attribute values in omshell.
-- Fix a bunch of bugs in the Solaris client script.
+- Fix a typo in the linux interface discovery code.
-- Add some more information about Solaris to the README file.
+- Conditionalize a piece of trace code that wasn't conditional.
-- Adjust startup message in interface probe so that the relay agent
- and client's unattached status will not trigger questions.
+ Changes since 3.0 Release Candidate 4
-- Update some error messages to provide more help to new users for
- some common mistakes.
+- Fix a bug that would prevent leases from being abandoned properly on
+ DHCPDECLINE.
-- Create an interface alias on Solaris when setting up IP aliases,
- rather than trying to do things the *BSD way.
+- Fix failover peer OMAPI support.
-- Fix a null pointer dereference bug (this time I went through the
- whole function and audited it for more null pointer dereferences,
- and I didn't find any, for what that's worth).
+- In failover, correctly handle expiration of leases. Previously,
+ leases would never be reclaimed because they couldn't make the
+ transition from EXPIRED to FREE.
-- Don't ever release leases in response to a DHCPDISCOVER (I think
- this was unlikely anyway, but why not be correct?).
+- Fix some broken failover state transitions.
-- Remove the shared-network example from the sample dhcpd.conf file.
+- Documentation fixes.
-- Make ``make install'' make all first.
+- Take out an unnecessary check in DHCP relay agent information option
+ stashing code that was preventing REBINDING clients from rebinding.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 13
+- Prevent failover peers from allocating leases in DHCPREQUEST
+ processing if the lease belongs to the other server.
-- Support DESTDIR on installs.
+- Record server version in lease file introductory comment.
-- Fix a bug in dhcp.c where a store through a null pointer would
- be made under some reasonably common circumstances.
+- Correctly report connection errors in OMAPI and failover.
-- Add test for ARPHRD_TUNNEL so that client and server do not fail on
- versions of Linux running IPsec implementations or the like.
+- Make authentication signature algorithm name comparisons in OMAPI
+ case-insensitive.
-- Move tests for constants defined in O.S. headers into osdep.h - test
- for HAVE_whatever in .c files. Define relevant HAVE_whatevers in
- linux.h, so that versions of linux that define these constants as
- enums will still work.
+- Fix compile problem on SunOS 4.x
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 12
+- If a signature algorithm is not termined with '.', terminate it so
+ that comparisons between fully-qualified names will work
+ consistently.
-- Initialize the "quiet" variable in dhclient.c to zero (it was used
- without first having been initialized).
+- Different SIOCGIFCONF probe code, may "fix" problem on some Linux
+ systems with the probe not working correctly.
-- Fix the parser code for the authoritative keyword.
+- Don't allow user to type omapi key on command line of omshell.
-- Adjust lease discovery code to NAK more aggressively for addresses
- the server knows it owns.
+ Changes since 3.0 Release Candidate 3
-- Add several new messages for DHCPNAK.
+- Do lease billing on startup in a way that I *think* will finally do
+ the billing correctly - the previous method could overbill as a
+ result of duplicate leases.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 11
+- Document OMAPI server objects.
-- Use DLPI only on sparcs running Solaris, since it seems not to work
- on i386 boxes running Solaris for reasons yet to be determined.
+ Changes since 3.0 Release Candidate 2 Patchlevel 1
-- In the client, close standard I/O descriptors when forking a daemon.
+- Fix some problems in the DDNS update code. Thanks to Albert
+ Herranz for figuring out the main problem.
-- Don't let large lease lengths wrap lease expiry times - just use
- what fits into a TIME value.
+- Fix some reference counting errors on host entries that were causing
+ core dumps.
-- Fix a bug in the SIOCGIFCONF interface scanning code.
+- Fix a byte-swap bug in the token ring code, thanks to Jochen
+ Friedrich.
-- Fix a core dump in the interface scanner that crops up on Linux when
- an interface is specified on the command line.
+- Fix a bug in lease billing, thanks to Jonas Bulow.
-- Don't use %D in strftime because egcs complains about it.
+ Changes since 3.0 Release Candidate 2
-- Print the error message if SO_BINDTODEVICE fails.
+- Change the conditions under which a DHCPRELEASE is actually
+ committed to be consistent with lease binding states rather than
+ using the lease end time. THis may fix some problems with the
+ billing class code.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 10
+- Fix a bug where lease updates would fail on Digital Unix (and maybe
+ others) because malloc was called with a size of zero.
-- Update top-level Makefile so that it exits correctly on errors in
- submakes under bash/gnu make (dunno which is the culprit, and don't
- really care).
+- Fix a core dump that happens when the DHCP server can't create its
+ trace file.
-- Print a more helpful message if no free BPF devices are found.
+ Changes since 3.0 Release Candidate 1 Patchlevel 1
-- Add support for specifying that the server is or is not
- authoritative for a particular network segment.
+- Fix the dhcp_failover_put_message to not attempt to allocate a
+ zero-length buffer. Some versions of malloc() fail if you try to
+ allocate a zero-length buffer, and this was causing problems on,
+ e.g., Digital Unix.
-- Fix two stupid typos in lpf.c.
+- Fix a case where the failover code was printing an error message
+ when no error had occurred.
-- Print a more helpful message if we can't create an LPF socket or
- can't attach a filter to it.
+- Fix a problem where when a server went down and back up again, the
+ peer would not see a state transition and so would stay in the
+ non-communicating state.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 9
+- Be smart about going into recover_wait.
-- Correct the hopelessly outdated information about Linux at the top
- of the README - many apologies to the Linux people who have had to
- read that nonsense for the past couple of snapshots and have been
- confused or annoyed by it. I simply hadn't read it recently, and
- didn't realize how out-of-date it was.
+- Fix a problem in the failover implementation where peers would fail
+ to come into sync if interrupted in the RECOVER state. This could
+ have been the cause of some problems people have reported recently.
-- Print a message if the client finds no broadcast interfaces to
- configure.
+- Fix a problem with billing classes where they would not be unbilled
+ when the client lease expired.
-- Add support for use-lease-addr-for-default-route flag in server, so
- that Windows machines can be made to ARP for all addresses.
+- If select fails, figure out which descriptor is bad, and cut it out
+ of the I/O loop. This prevents a potentially nasty spin. I
+ haven't heard any report it in a while, but it came up consistently
+ in testing.
-- Update README file to mention new Linux gotchas.
+- Fix a bug in the relay agent where if you specified interfaces on
+ the command line, it would fail.
-- After finally understanding Brian Murrel's code (my fault, not his)
- to get interface names from /proc/net/dev on Linux, fix what I broke
- of his code and document it.
+- Fix a couple of small bugs in the omapi connection object (no known
+ user impact).
-- Use sendto rather than send for SOCK_PACKET sockets, because they
- can't be connected, only bound. :'(
+- Add the missing 3.0 Beta 1 lease conversion script.
-- Fix up SOCK_PACKET creation so that the kernel doesn't complain
- about it.
+- Read dhcp client script hooks if they exist, rather than only if
+ they're executable.
-- Fix incorrect tests in linux client script:
- [ $relmajor == 2 ] -> [ $relmajor -eq 2 ]
+ Changes since 3.0 Release Candidate 1
-- Make typedefs for u8, u16 and u32 types. These are Linux kernel
- internal data types which are unfortunately exposed in the linux
- packetfilter header file.
+- Fix a memory smash that happens when fixed-address leases are used.
+ ANY SITE AT WHICH FIXED-ADDRESS STATEMENTS ARE BEING USED SHOULD
+ UPGRADE IMMEDIATELY. This has been a long-standing bug - thanks to
+ Alvise Nobile for discovering it and helping me to find it!
-- Don't include <net/ethernet.h> in lpf.c - it defines things we're
- already correctly defining elsewhere, and doesn't define any useful
- new stuff.
+- Fix a small bug in binary-to-ascii, thanks to H. Peter Anvin of
+ Transmeta.
-- Finally fix client PREINIT bug that causes interfaces not specified
- on the command line to be preinitialized. If no interfaces are
- specified on the command line, all interfaces are still
- preinitialized.
+- There is a known problem with the DHCP server doing failover on
+ Compaq Alpha systems. This patchlevel is not a release candidate
+ because of this bug. The bug should be straightforward to fix, so
+ a new release candidate is expected shortly.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 8
+- There is a known problem in the DDNS update code that is probably a
+ bug, and is not, as far as we know, fixed in this patchlevel.
-- Fix socket API fallback setup code, which was causing Linux servers
- and clients to loop endlessly on select when run as daemons.
+ Changes since 3.0 Beta 2 Patchlevel 24
-- Add support for Linux 2.2 version number (treated the same as Linux
- 2.1, for now).
+- Went over problematic failover state transitions and made them all
+ work, so that failover should now much less fragile.
-- Correct apparent error in DHCPREQUEST destination address handling
- when in INIT-REBOOT state.
+- Add some dhcpctl and omapi documentation
-- Do not set BROADCAST flag if we have a valid IP address.
+- Fix compile errors when compiling with unusual predefines.
-- Remove hard-coded filenames and use system-specific manifest
- constants.
+- Make Token Ring work on Linux 2.4
-- Add entry and exit hooks to Linux dhclient-script (should be added
- to all operating systems once tested).
+- Fix the Digital Unix BPF_WORDALIGN bug.
-- Test for linux major and minor version so as to correctly invoke
- network configuration programs.
+- Fix some dhcp client documentation errors.
-- Add support for Linux's gratuitous name change of bpf_insn structure
- (can't pollute precious Linux sources with the "Berkeley" word, I
- guess.
+- Update some parts of the README file.
-- Correct USE_BPF_{SEND,RECEIVE} ifdefs for if_reinitialize_*
- functions.
+- Support GCC on SCO.
-- Ensure that we have ifreq structure before initializing interface -
- if an interface was specified on the command line on Linux, this was
- not the case.
+ Changes since 3.0 Beta 2 Patchlevel 23
-- Get rid of references to enstamp structure in lpf.c. Correctly
- declare and initialize sock_fprog structure (aka bpf_filter
- structure on non-Linux machines).
+- Fix a bug in the DNS update code where a status code was not being
+ checked. This may have been causing core dumps.
-- Define ssize_t on Ultrix.
+- When parsing the lease file, if a lease declaration includes a
+ billing class statement, and the lease already has a billing class,
+ unbill the old class.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 7
+- When processing failover transactions, where acks will be deferred,
+ process the state transition immediately.
-- Generalize FDDI support.
+- Don't try to use the new SIOCGIFCONF buffer size detection code on
+ Linux 2.0, which doesn't provide this functionality.
-- Fix potential core dump in interface discovery code.
+- Apply a patch suggested by Tuan Uong for a problem in dlpi.c.
-- Put explicit release versions on startup messages.
+- Fix a problem in using the which command in the configure script.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 6
+- Fix a parse error in the client when setting up an omapi listener.
-- Add support for Linux Packet Filter (thanks to Brian Murrell, Interlinx).
+- Document the -n and -g flags to the client.
-- Add support for FDDI hardware type.
+- Make sure there is always a stdin and stdout on startup. This
+ prevents shell scripts from accidentally writing error messages into
+ configuration files that happen to be opened as stderr.
-- Fix a long-standing bug in DLPI support where the ethertype was
- being set incorrectly (thanks to Gong Wei, CCENet).
+- If an interface is removed, the client will now notice that it is
+ gone rather than spinning. This has only been tested on NetBSD.
-- Don't use DLPI RAW mode on Solaris.
+- The client will attempt to get an address even if it can't create a
+ lease file.
-- In the client, when a lease expires, the interface to which that
- lease is attached is unconfigured. On systems that use the socket
- API, the interface needs to then be reconfigured with the 0.0.0.0
- address so that it can be used to get a new address.
+- Don't overwrite tracefiles.
-- Add fallback support for Linux. This fixes a problem with the
- relay agent when relaying over non-broadcast links, and may also fix
- some obscure problems with unicasting DHCPACKs in both the server and
- relay agent.
+- Fix some memory allocation bugs in failover.
-- When allocating leases, if the oldest lease is abandoned, try to
- find a younger-but-still-expired lease rather than reclaiming the
- abandoned lease.
+ Changes since 3.0 Beta 2 Patchlevel 22
-- Add more documentation to README.
+- Apply some patches suggested by Cyrille Lefevre, who is maintaining
+ the FreeBSD ISC DHCP Distribution port.
-- The absence of the /etc/dhclient.conf file is no longer considered
- an error.
+- Fix a core dump in DHCPRELEASE.
-- The dhcp client's lease file name can be specified on the command
- line.
+ Changes since 3.0 Beta 2 Patchlevel 21
-- The DHCP client should no longer zap interfaces that it has not been
- directed to configure.
+- This time for sure: fix the spin described in the changes for pl20.
-- If a client starts up in the init-reboot state, the xid will be a
- "random" number rather than always being zero, as was previously the
- case.
+ Changes since 3.0 Beta 2 Patchlevel 20
-- In addition to comparing transaction IDs, compare hardware addresses
- in response packets to verify that they are ours.
+- Fix a problem with Linux detecting large numbers of interfaces (Ben)
-- Rewrite the client lease database after 20 leases have been written.
+- Fix a memory smash in the quotify code, which was introduced in
+ pl19.
-- Fix the exponential backoff code.
+- Actually fix the spin described in the changes for pl20. The
+ previous fix only partially fixed the problem - enough to get it
+ past the regression test.
-- Add a Y2k comment to indicate that something suspicious-looking is
- in fact _not_ a problem.
+ Changes since 3.0 Beta 2 Patchlevel 19
-- Use mkstemp if possible.
+- Fix a bug that could cause the server to abort if compiled with
+ POINTER_DEBUG enabled.
-- Add missing fi in various client scripts.
+- Fix a bug that could cause the server to spin when responding to a
+ DHCPREQUEST.
-- Use "search" instead of "domain" in linux resolv.conf files.
+- Apply Joost Mulders' suggested patches for DLPI on x86.
-- Specify a hop count in all route command on solaris.
+- Support NUL characters in quoted strings.
-- If an allocation fails, don't try to zero out the allocation buffer
- we didn't get.
+- Install unformatted man pages on SunOS.
-- Support subnets that are subsets of other subnets - that is, for
- example, 10.0.1.0/24 and 10.0.0.0/16. This is useful in fairly
- obscure circumstances.
+ Changes since 3.0 Beta 2 Patchlevel 18
-- Don't set the lease end time if it's already expired.
+- Allow the server to be placed in partner-down state using OMAPI.
+ (Damien Neil)
-- Don't define INADDR_LOOPBACK on FreeBSD if it's already defined in a
- system header.
+- Implement omshell, which can be used to do arbitrary things to the
+ server (in theory). (Damien Neil)
-- Use the broadcast address in the relay agent if we are using the BSD
- socket API.
+- Fix a case where if a client had two different leases the server could
+ actually dereference the second one when it hadn't been referenced,
+ leading to memory corruption and a core dump. (James Brister)
-- Allow host declarations without names.
+- Fix a case where a client could request the address of another client's
+ lease, but find_lease wouldn't detect that the other client had it, and
+ would attempt to allocate it to the client, resulting in a lease conflict
+ message.
-- Allow the server identifier option to be specified.
+- Fix a case where a client with more than one client identifier could be
+ given a lease where the hardware address was correct but the client
+ identifier was not, resulting in a lease conflict message.
-- Don't dump hostnames into the lease file if they contain
- non-printable characters.
+- Fix a problem where the server could write out a colon-seperated
+ hex list as a value for a variable, which would then not parse.
+ The fix is to always write strings as quoted strings, with any
+ non-printable characters quoted as octal escape sequences. So
+ a file written the old way still won't work, but new files written
+ this way will work.
-- Copy the entire client hardware address buffer that the client sends
- to the output packet, not just the portion of it that's supposedly
- significant according to the hardware address length field. This
- is done for the benefit of certain Microsoft clients.
+- Fix documentation for sending non-standard options.
-- Don't send a second ICMP echo request if we receive two DHCPDISCOVER
- messages in quick succession. This prevents a rather annoying
- timing race in configuring some Win95 clients.
+- Use unparsable names for unknown options. WARNING: this will
+ break any configuration files that use the option-nnn convention.
+ If you want to continue to use this convention for some options,
+ please be sure to write a definition, like this:
-- Fix up dhcp-options man page to make it more readable. Note that
- netbios-name-server is the same thing as WINS.
+ option option-nnn code nnn = string;
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 5
+ You can use a descriptive name instead of option-nnn if you like.
-- Define some extra DLPI support flags that make DLPI work much better
- on Solaris.
+- Fix a problem where we would see a DHCPDISCOVER/DHCPOFFER/
+ DHCPREQUEST/DHCPACK/DHCPREQUEST/DHCPNAK sequence. This was the
+ result of a deceptively silly bug in supersede_lease.
-- Fix inet_aton prototype/declaration to match Internet Software
- Consortium BIND distribution.
+- Fix client script exit status check, according to a fix supplied by
+ Hermann Lauer.
-- Document new server-identifier functionality.
+- Fix an endianness bug in the tracefile support, regarding ICMP
+ messages.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 4
+- Fix a bug in the client where the medium would not work correctly if
+ it contained quoted strings.
-- Do not use -Wstrict-prototypes on Solaris with gcc - if the Internet
- Software Consortium BIND distribution is not installed, this produces
- errors.
+ ** there was no pl17 **
-- Actually use the new DLPI support on Solaris - although the code was
- added in Patchlevel 2, it wasn't enabled (blush).
+ Changes since 3.0 Beta 2 Patchlevel 16
-- Fix a prototype bug that's exposed when DLPI support is enabled on
+- Add support for transaction tracing. This allows the state of the
+ DHCP server on startup, and all the subsequent transactions, to be
+ recorded in a file which can then be played back to reproduce the
+ behaviour of the DHCP server. This can be used to quickly
+ reproduce bugs that cause core dumps or corruption, and also for
+ tracking down memory leaks.
+
+- Incorporate some bug fixes provided by Joost Mulders for the DLPI
+ package which should clear up problems people have been seeing on
Solaris.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 3
+- Fix bugs in the handling of options stored as linked lists (agent
+ options, fqdn options and nwip options) that could cause memory
+ corruption and core dumps.
-- Fix a makefile botch that prevents the DHCP Distribution from
- from compiling on Solaris with gcc. Sigh.
+- Fix a bug in DHCPREQUEST handling that resulted in DHCPNAK messages
+ not being send in some cases when they were needed.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 2
+- Make the lease structure somewhat more compact.
-- Allow server-identifier in any scope. Use in-scope server
- identifier option rather than the default, if one exists.
+- Make initial failover startup *much* faster. This was researched
+ and implemented by Damien Neil.
-- Delete newlines from abandoned lease reclaimation warning.
+- Add a --version flag to all executables, which prints the program
+ name and version to standard output.
-- Only release other applicable leases held by a client when the
- client sends a DHCPREQUEST.
+- Don't rewrite the lease file every thousand leases.
-- Fix core dump when find_lease didn't find a lease.
+- A bug in nit.c for older SunOS machines was fixed by a patch sent in
+ by Takeshi Hagiwara.
-- Update dhcpd.leases man page.
+- Fix a memory corruption bug in the DHCP client.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 1
+- Lots of documentation updates.
-- Use -Wno-char-subscript on Solaris to prevent bogus warnings from
- gcc on Solaris 2.6.
+- Add a feature allowing environment variables to be passed to the
+ DHCP client script on the DHCP client command line.
-- Add support for Apple's new Rhapsody operating system.
+- Fix client medium support, which had been broken for some time.
-- Use DLPI on Solaris instead of using the BSD Sockets API.
+- Fix a bug in the DHCP client initial startup backoff interval, which
+ would cause two DHCPDISCOVERS to be sent back-to-back on startup.
-- Fix two network input buffer overflow problems which could allow an
- attacker to pervert the stack.
-- Fix an ancient typo that could theoretically cause memory
- corruption.
+ Changes since 3.0 Beta 2 Patchlevel 15
-- Sort abandoned leases in at current time rather than end of time.
- This allows abandoned leases to be reclaimed if there are no
- available free leases.
+- Some documentation tweaks.
-- If a client explicitly requests a lease that's been abandoned, it's
- probably the system that was answering pings on that address, so let it
- have the lease.
+- Maybe fix a problem in the DLPI code.
-- Fix a bunch of type conversion errors that are flagged by the Solaris
- C compiler.
+- Fix some error code space inconsistencies in ddns update code.
- CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 0
+- Support relay agents that intercept unicast DHCP messages to stuff
+ agent options into them.
-- Fix two potential buffer overflow problems.
+- Fix a small memory leak in the relay agent option support code.
-- Differentiate between versions of Linux for better success in
- compiling.
+- Fix a core dump that would occur if a packet was sent with no
+ options.
-- Fix bug in linux client script regarding routing setup.
+ Changes since 3.0 Beta 2 Patchlevel 14
-- Clarify socket API error message on multiple interfaces.
+- Finish fixing a long-standing bug in the agent options code. This
+ was causing core dumps and failing to operate correctly - in
+ particular, agent option stashing wasn't working. Agent option
+ stashing should now be working, meaning that agent options can be
+ used in class statements to control address allocation.
-- Fix broken comparison that was setting IP source address to zero.
+- Fix up documentation.
-- Reclaim abandoned leases if we run out of free leases.
+- Fix a couple of small memory leaks that would have added up
+ significantly in a high-demand situation.
- CHANGES FROM THE DECEMBER 2, 1997 SNAPSHOT
+- Add a log-facility configuration parameter.
-- Use %ld to print pid_t and cast pid_t values to long to avoid
- inconsistent declarations between different POSIX flavours.
+- Fix a compile error on some older operating systems.
-- Add support for ARPHRD_IEEE802 (token ring) hardware type.
+- Add the ability in the client to execute certain statements before
+ transmitting packets to the server. Handy for debugging; not much
+ practical use otherwise.
-- If we own an address and a client requests it, but we can't assign
- it to that client, we now NAK it so that the client doesn't try to
- reuse it.
+- Don't send faked-out giaddr when renewing or bound - again, useful
+ for debugging.
- CHANGES FROM THE JUNE SNAPSHOT
+ Changes since 3.0 Beta 2 Patchlevel 13
-- Support for NeXTstep 3.x and 4.x
+- Fixed a problem where the fqdn decoder would sometimes try to store
+ an option with an (unsigned) negative length, resulting in a core
+ dump on some systems.
-- Added man pages for dhcpd.leases, dhclient-script, dhclient.leases
- and dhclient.conf. Move general documentation of DHCP options into
- a seperate man page which is referred to by the dhclient.conf and
- dhcpd.conf man pages.
+- Work around the Win98 DHCP client, which NUL-terminates the FQDN
+ option.
-- Updated README to answer some frequently asked questions.
+- Work around Win98 and Win2k clients that will claim they want to do
+ the update even when they don't have any way to do it.
-- Fixed a bug in command-line interface specification in dhclient - it
- was formerly not possible to specify that only certain interfaces be
- configured.
+- Fix some log messages that can be printed when failover is operating
+ that were not printing enough information.
-- Do not leave client scripts lying around in /tmp after they've been
- used unless the -D flag is specified.
+- It was possible for a DHCPDISCOVER to get an allocation even when
+ the state machine said the server shouldn't be responding.
-- Add a new, non-standard, not-guaranteed-to-stay-the-same system
- configuration status message server which can be used to trigger the
- client to recheck its address, e.g., after a laptop has been put to
- sleep and then awakened (this has yet to be documented).
+- Don't load balance DHCPREQUESTs from clients in RENEWING and
+ REBINDING, since in RENEWING, if we heard it, it's for us, and in
+ REBINDING, the client wouldn't have got to REBINDING if its primary
+ were answering.
-- Fix handling of media selection in the REBOOT phase - previously the
- media type would not be remembered, which could cause severe delays
- in reacquiring an address if the default media type was wrong.
+- When we get a bogus state lease binding state transition, don't do
+ the transition.
+
-- Allocate space for a NUL terminator on the end of client options -
- this was previously overlooked, and could cause garbage characters
- to be written to the temporary client script files.
+ Changes since 3.0 Beta 2 Patchlevel 12
-- Use mkstemp if it's available.
+- Fixed a couple of silly compile errors.
-- Supply network number and broadcast address to the client script so
- that on systems that need these values, they don't need to be
- computed with an awk script.
+ Changes since 3.0 Beta 2 Patchlevel 11
-- Keep a PID file for the client and the relay agent, and have the
- relay agent background itself by default.
+- Albert Herranz tracked down and fixed a subtle bug in the base64
+ decoder that would prevent any key with an 'x' in its base64
+ representation from working correctly.
-- Add client script for bsd/os, fix many niggling bugs in existing
- client scripts and add support for static routing tables to all bsd
- scripts.
+- Thanks to Chris Cheney and Michael Sanders, we have a fix for the
+ hang that they both spotted in the DHCP server - when
+ one-lease-per-client was set, the code to release the "other" lease
+ could spin.
-- Add a -q option to the client, server and relay agent so that they
- can be started from /etc/rc scripts without spewing a bunch of
- garbage on the console. By default, all three daemons still print
- startup messages, since these are helpful in bug reporting.
+- Fix a problem with alignment of the input buffer in bpf in cases
+ where two packets arrive in the same bpf read.
-- Don't print anything to stderr or stdout after going into
- background.
+- Fix a problem where the relay agent would crash if you specified an
+ interface name on the command line.
-- Fix bug where hostname keyword was not being recognized in
- dhcpd.leases file, resulting in the loss of lease database entries.
+- Add the ability to conditionalize client behaviour based on the
+ client state.
-- Fix problem on some operating systems where zero-length ifreq
- structures were being offset incorrectly when scanning the interface
- list on startup.
+- Add support for the FQDN option, and added support for a new way of
+ doing ddns updates (ddns update style interim) that allows more than
+ one DHCP server to update the DNS for the same network(s). This
+ was implemented by Damien Neil with some additional functionality
+ added by Ted Lemon.
-- Unless a BOOTP client requests it, never send more than 64 bytes of
- options.
+- Damien added a "log" statement, so that the configuration file can
+ be made to log debugging information and other information.
+
+- Fixed a bug that caused option buffers not to be terminated with an
+ end option.
+
+- Fixed a long-standing bug in the support for option spaces where the
+ options are stored as an ordered list rather than in a hash table,
+ which could theoretically result in memory pool corruption.
+
+- Prevent hardware declarations with no actual hardware address from
+ being written as something unparsable, and behave correctly in the
+ face of a null hardware address on input.
+
+- Allow key names to be FQDNs, and qualify the algorithm name if it is
+ specified unqualified.
+
+- Modify the DDNS update code so that it never prints the "resolver
+ failed" message, but instead says *why* the resolver failed.
+
+- Officially support the subnet selection option, which now has an
+ RFC.
+
+- Fix a build bug on MacOS X.
+
+- Allow administrator to disable ping checking.
+
+- Clean up dhcpd.conf documentation and add more information about how
+ it works.
+
+ Changes since 3.0 Beta 2 Patchlevel 10
+
+- Fix a bug introduced during debugging (!) and accidentally committed
+ to CVS.
+
+ Changes since 3.0 Beta 2 Patchlevel 9
+
+- Fix DHCP client handling of vendor encapsulated options.
+
+- Fix a bug in the handling of relay agent information options introduced
+ in patchlevel 9.
+
+- Stash agent options on client leases by default, and use the stashed
+ options at renewal time.
+
+- Add the ability to test the client's binding state in the client
+ configuration language.
+
+- Fix a core dump in the DNS update code.
+
+- Fix some expression evaluation bugs that were causing updates to be
+ done when no client hostname was received.
+
+- Fix expression evaluation debugging printfs.
+
+- Teach pretty_print_option to print options in option spaces other than
+ the DHCP option space.
+
+- Add a warning message if the RHS of a not is not boolean.
+
+- Never select for more than a day, because some implementations of
+ select will just fail if the timeout is too long (!).
+
+- Fix a case where a DHCPDISCOVER from an unknown network would be
+ silently dropped.
+
+- Fix a bug where if a client requested an IP address for which a different
+ client had the lease, the DHCP server would reallocate it anyway.
+
+- Fix the DNS update code so that if the client changes its name, the DNS
+ will be correctly updated.
+
+ Changes since 3.0 Beta 2 Patchlevel 8
+
+- Oops, there was another subtle math error in the header-length
+ bounds-checking.
+
+ Changes since 3.0 Beta 2 Patchlevel 7
+
+- Oops, forgot to byte-swap udp header length before bounds-checking it.
+
+ Changes since 3.0 Beta 2 Patchlevel 6
-- Don't ping static leases, since we don't have a lease structure on
- the heap to work with later.
+- Fix a possible DoS attack where a client could cause the checksummer
+ to dump core. This was a read, not a write, so it shouldn't be
+ possible to exploit it any further than that.
-- Fixed a compile problem on Solaris 2.6.
+- Implement client- and server-side support for using the Client FQDN
+ option.
-- Support interface aliases on Solaris.
+- Support for other option spaces in the client has been added. This
+ means that it is now possible to define a vendor option space on the
+ client, request options in that space from the server (which must
+ define the same option space), and then use those options in the
+ client. This also allows NWIP and Client FQDN options to be used
+ meaningfully.
-- Print day and month with leading zero in lease files if less than
- ten, for easier parsing by perl/sed/awk scripts.
+- Add object initializer support. This means that objects can now be
+ initialized to something other than all-zeros when allocated, which
+ makes, e.g., the interface object support code a little more robust.
-- Never make the lease database world writable, even if dhcpd is
- invoked with a bogus umask.
+- Fix an off-by-one bug in the host stuffer. This was causing host
+ deletes not the work, and may also have been causing OMAPI
+ connections to get dropped. Thanks to James Brister for tracking
+ this one down!
-- Fix DHCPRELEASE handling (before, addressed would never be
- released.)
+- Fixed a core dump in the interface discovery code that is triggered
+ when there is no subnet declaration for an interface, but the server
+ decides to continue running. Thanks to Shane Kerr for tracking
+ down and fixing this problem.
-- If there is more than one lease for a particular client on a
- particular network, find the lease the client is asking for so as to
- avoid a cycle of NAKs.
+ Changes since 3.0 Beta 2 Patchlevel 5
-- If a BOOTP request is received from a particular client and that
- client has previously received a DHCP address, make sure that we
- still find a valid BOOTP lease so that we don't cycle through
- addresses.
+- Fix a bug in the recent enhancement to the interface discovery code
+ to support arbitrary-length interface lists.
-- Remove server-identifier option from documentation, other than to
- document that it has been deprecated.
+- Support NUL-terminated DHCP options when initializing client-script
+ environment.
-- Don't give up if we get an EINTR or EAGAIN while polling or
- selecting - these return statuses can occur spuriously without
- indicating a fatal problem.
+- Fix suffix operator.
+
+- Fix NetWare/IP option parsing.
+
+- Better error/status checking in dhcpctl initialization and omapi
+ connection code.
+
+- Fix a potential memory smash in dhcpctl code.
+
+- Fix SunOS4 and (maybe) Ultrix builds.
+
+- Fix a bug where a certain sort of incoming packet could cause a core
+ dump on Solaris (and probably elsewhere).
+
+- Add some more safety checks in error logging code.
+
+- Add support for ISC_R_INCOMPLETE in OMAPI protocol connection code.
+
+- Fix relay agent so that if an interface is specified on the command
+ line, the relay agent does not dump core.
+
+- Fix class matching so that match if can be combined with match or
+ spawn with.
+
+- Do not allow spurious leases in the lease database to introduce
+ potentially bogus leases into the in-memory database.
+
+- Fix a byte-order problem in the client hardware address type code
+ for OMAPI.
+
+- Be slightly less picky about what sort of hardware addresses OMAPI
+ can install in host declarations.
+
+ Changes since 3.0 Beta 2 Patchlevel 4
+
+- Incorporated Peter Marschall's proposed change to array/record
+ parsing, which allows things like the slp-agent option to be encoded
+ correctly. Thanks very much to Peter for taking the initiative to
+ do this, and for doing such a careful job of it (e.g., updating the
+ comments)!
+
+- Added an encoding for the slp-agent option. :')
+
+- Fixed SunOS 4 build. Thanks to Robert Elz for responding to my
+ request for help on this with patches!
+
+- Incorporated a change that should fix a problem reported by Philippe
+ Jumelle where when the network connection between two servers is
+ lost, they never reconnect.
+
+- Fix client script files other than that for NetBSD to actually use
+ make_resolv_conf as documented in the manual page.
+
+- Fix a bug in the packet handling code that could result in a core
+ dump.
+
+- Fix a bug in the bootp code where responses on the local net would
+ be sent to the wrong MAC address. Thanks to Jerry Schave for
+ catching this one.
+
+ Changes since 3.0 Beta 2 Patchlevel 3
+
+- In the DHCP client, execute client statements prior to using the values
+ of options, so that the client configuration can overried, e.g., the
+ lease renewal time.
+
+- Fix a reference counting error that would result in very reproducible
+ failures in updates, as well as occasional core dumps, if a zone was
+ declared without a key.
+
+- Fix some Linux 2.0 compilation problems.
+
+- Fix a bug in scope evaluation during execution of "on" statements that
+ caused values not to be recorded on leases.
+
+- If the dhcp-max-message-size option is specified in scope, and the
+ client didn't send this option, use the one specified in scope to
+ determine the maximum size of the response.
+
+ Changes since 3.0 Beta 2 Patchlevel 2
+
+- Fix a case where spawning subclasses were being allocated
+ incorrectly, resulting in a core dump.
+
+- Fix a case where the DHCP server might inappropriately NAK a
+ RENEWING client.
+
+- Fix a place dhcprequest() where static leases could leak.
+
+- Include memory.h in omapip_p.h so that we don't get warnings about
+ using memcmp().
+
+ Changes since 3.0 Beta 2 Patchlevel 1
+
+- Notice when SIOCFIGCONF returns more data than fit in the buffer -
+ allocate a larger buffer, and retry. Thanks to Greg Fausak for
+ pointing this out.
+
+- In the server, if no interfaces were configured, report an error and
+ exit.
-- Do not select for exceptions, since we don't handle them. This was
- causing massive CPU consumption on some systems.
+- Don't ever record a state of 'startup'.
-- When a DHCP client has been assigned a fixed address but had
- previously had a lease, it will request the old leased address. In
- such an event, send a DHCPNAK so that it will discover its new
- static binding.
+- Don't try to evaluate the local failover binding address if none was
+ specified. Thanks to Joseph Breu for finding this.
diff --git a/contrib/isc-dhcp/client/Makefile.dist b/contrib/isc-dhcp/client/Makefile.dist
index 2b261a7e4610..a1f8a38aa937 100644
--- a/contrib/isc-dhcp/client/Makefile.dist
+++ b/contrib/isc-dhcp/client/Makefile.dist
@@ -1,33 +1,20 @@
# Makefile.dist
#
-# Copyright (c) 1996, 1997, 1999 The Internet Software Consortium.
-# All rights reserved.
+# Copyright (c) 1996-1999 Internet Software Consortium.
+# Use is subject to license terms which appear in the file named
+# ISC-LICENSE that should have accompanied this file when you
+# received it. If a file named ISC-LICENSE did not accompany this
+# file, or you are not sure the one you have is correct, you may
+# obtain an applicable copy of the license at:
#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
+# http://www.isc.org/isc-license-1.0.html.
#
-# 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 file is part of the ISC DHCP distribution. The documentation
+# associated with this file is listed in the file DOCUMENTATION,
+# included in the top-level directory of this release.
#
-# 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.
+# Support and other services are available for ISC products - see
+# http://www.isc.org for more information.
#
CATMANPAGES = dhclient.cat8 dhclient.conf.cat5 dhclient-script.cat8 \
@@ -39,9 +26,8 @@ OBJS = dhclient.o clparse.o
PROG = dhclient
MAN = dhclient.8 dhclient.conf.5 dhclient-script.8 dhclient.leases.5
-DEBUG = -g
-INCLUDES = -I.. -I../includes
-DHCPLIB = ../common/libdhcp.a
+INCLUDES = -I$(TOP) $(BINDINC) -I$(TOP)/includes
+DHCPLIB = ../common/libdhcp.a $(BINDLIB) ../omapip/libomapi.a ../dst/libdst.a
CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS) \
-DCLIENT_PATH=${CLIENT_PATH}
@@ -64,8 +50,9 @@ install: all
if [ x$(SCRIPT) = xnone ]; then \
echo "No client script available."; \
else \
- $(INSTALL) scripts/$(SCRIPT) $(DESTDIR)$(ETC)/dhclient-script; \
- $(CHMOD) 700 $(DESTDIR)$(ETC)/dhclient-script; \
+ $(INSTALL) $(TOP)/client/scripts/$(SCRIPT)\
+ $(DESTDIR)$(CLIENTBINDIR)/dhclient-script; \
+ $(CHMOD) 700 $(DESTDIR)$(CLIENTBINDIR)/dhclient-script; \
fi
$(MANINSTALL) $(MANFROM) dhclient.$(MANCAT)8 $(MANTO) \
$(DESTDIR)$(ADMMANDIR)/dhclient$(ADMMANEXT)
@@ -76,15 +63,26 @@ install: all
$(MANINSTALL) $(MANFROM) dhclient.leases.$(MANCAT)5 $(MANTO) \
$(DESTDIR)$(FFMANDIR)/dhclient.leases$(FFMANEXT)
+depend:
+ $(MKDEP) $(INCLUDES) $(PREDEFINES) $(SRCS)
+
clean:
-rm -f $(OBJS)
-
+
realclean: clean
-rm -f $(PROG) $(CATMANPAGES) $(SEDMANPAGES) *~ #*
distclean: realclean
-rm -f Makefile
+links:
+ @for foo in $(SRCS) $(MAN); do \
+ if [ ! -b $$foo ]; then \
+ rm -f $$foo; \
+ fi; \
+ ln -s $(TOP)/client/$$foo $$foo; \
+ done
+
# These should only be done on 4.4 BSD-based systems, since the mandoc
# macros aren't available on older unices. Catted man pages are
# provided in the distribution so that this doesn't become a problem.
@@ -94,6 +92,7 @@ dhclient.cat8: dhclient.man8
dhclient.man8: dhclient.8
sed -e "s#ETCDIR#$(ETC)#g" -e "s#DBDIR#$(VARDB)#g" \
+ -e "s#CLIENTBINDIR#$(CLIENTBINDIR)#g" \
-e "s#RUNDIR#$(VARRUN)#g" < dhclient.8 >dhclient.man8
dhclient-script.cat8: dhclient-script.man8
@@ -101,11 +100,13 @@ dhclient-script.cat8: dhclient-script.man8
dhclient-script.man8: dhclient-script.8
sed -e "s#ETCDIR#$(ETC)#g" -e "s#DBDIR#$(VARDB)#g" \
+ -e "s#CLIENTBINDIR#$(CLIENTBINDIR)#g" \
-e "s#RUNDIR#$(VARRUN)#g" < dhclient-script.8 \
>dhclient-script.man8
dhclient.conf.man5: dhclient.conf.5
sed -e "s#ETCDIR#$(ETC)#g" -e "s#DBDIR#$(VARDB)#g" \
+ -e "s#CLIENTBINDIR#$(CLIENTBINDIR)#g" \
-e "s#RUNDIR#$(VARRUN)#g" < dhclient.conf.5 \
>dhclient.conf.man5
@@ -114,24 +115,15 @@ dhclient.conf.cat5: dhclient.conf.man5
dhclient.leases.man5: dhclient.leases.5
sed -e "s#ETCDIR#$(ETC)#g" -e "s#DBDIR#$(VARDB)#g" \
+ -e "s#CLIENTBINDIR#$(CLIENTBINDIR)#g" \
-e "s#RUNDIR#$(VARRUN)#g" < dhclient.leases.5 \
>dhclient.leases.man5
dhclient.leases.cat5: dhclient.leases.man5
nroff -man dhclient.leases.man5 >dhclient.leases.cat5
+
dhclient: $(OBJS) $(DHCPLIB)
$(CC) $(LFLAGS) -o $(PROG) $(OBJS) $(DHCPLIB) $(LIBS)
# Dependencies (semi-automatically-generated)
-
-dhclient.o: dhclient.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h ../includes/version.h
-clparse.o: clparse.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h ../includes/dhctoken.h
diff --git a/contrib/isc-dhcp/client/clparse.c b/contrib/isc-dhcp/client/clparse.c
index 9af7744f8765..7cd8529e1956 100644
--- a/contrib/isc-dhcp/client/clparse.c
+++ b/contrib/isc-dhcp/client/clparse.c
@@ -3,7 +3,7 @@
Parser for dhclient config and lease files... */
/*
- * Copyright (c) 1997 The Internet Software Consortium.
+ * Copyright (c) 1996-2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,41 +34,49 @@
* SUCH DAMAGE.
*
* This software has been written for the Internet Software Consortium
- * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
- * Enterprises. To learn more about the Internet Software Consortium,
- * see ``http://www.vix.com/isc''. To learn more about Vixie
- * Enterprises, see ``http://www.vix.com''.
+ * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
+ * To learn more about the Internet Software Consortium, see
+ * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
+ * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
+ * ``http://www.nominum.com''.
*/
#ifndef lint
static char copyright[] =
-"$Id: clparse.c,v 1.13.2.5 2000/07/20 05:06:40 mellon Exp $ Copyright (c) 1997 The Internet Software Consortium. All rights reserved.\n";
+"$Id: clparse.c,v 1.62.2.1 2001/06/01 17:26:44 mellon Exp $ Copyright (c) 1996-2001 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
-#include "dhctoken.h"
-struct client_config top_level_config;
+static TIME parsed_time;
-char client_script_name [] = "/etc/dhclient-script";
+struct client_config top_level_config;
-/* client-conf-file :== client-declarations EOF
+u_int32_t default_requested_options [] = {
+ DHO_SUBNET_MASK,
+ DHO_BROADCAST_ADDRESS,
+ DHO_TIME_OFFSET,
+ DHO_ROUTERS,
+ DHO_DOMAIN_NAME,
+ DHO_DOMAIN_NAME_SERVERS,
+ DHO_HOST_NAME,
+ 0
+};
+
+/* client-conf-file :== client-declarations END_OF_FILE
client-declarations :== <nil>
| client-declaration
| client-declarations client-declaration */
-int read_client_conf ()
+isc_result_t read_client_conf ()
{
- FILE *cfile;
- char *val;
- int token;
struct client_config *config;
+ struct client_state *state;
struct interface_info *ip;
-
- new_parse (path_dhclient_conf);
+ isc_result_t status;
/* Set up the initial dhcp option universe. */
- initialize_universes ();
+ initialize_common_option_spaces ();
/* Initialize the top level client configuration. */
memset (&top_level_config, 0, sizeof top_level_config);
@@ -80,98 +88,138 @@ int read_client_conf ()
top_level_config.retry_interval = 300;
top_level_config.backoff_cutoff = 15;
top_level_config.initial_interval = 3;
- top_level_config.bootp_policy = ACCEPT;
- top_level_config.script_name = client_script_name;
- top_level_config.requested_options
- [top_level_config.requested_option_count++] =
- DHO_SUBNET_MASK;
- top_level_config.requested_options
- [top_level_config.requested_option_count++] =
- DHO_BROADCAST_ADDRESS;
- top_level_config.requested_options
- [top_level_config.requested_option_count++] =
- DHO_TIME_OFFSET;
- top_level_config.requested_options
- [top_level_config.requested_option_count++] =
- DHO_ROUTERS;
- top_level_config.requested_options
- [top_level_config.requested_option_count++] =
- DHO_DOMAIN_NAME;
- top_level_config.requested_options
- [top_level_config.requested_option_count++] =
- DHO_DOMAIN_NAME_SERVERS;
- top_level_config.requested_options
- [top_level_config.requested_option_count++] =
- DHO_HOST_NAME;
-
- if ((cfile = fopen (path_dhclient_conf, "r")) != NULL) {
+ top_level_config.bootp_policy = P_ACCEPT;
+ top_level_config.script_name = path_dhclient_script;
+ top_level_config.requested_options = default_requested_options;
+ top_level_config.omapi_port = -1;
+
+ group_allocate (&top_level_config.on_receipt, MDL);
+ if (!top_level_config.on_receipt)
+ log_fatal ("no memory for top-level on_receipt group");
+
+ group_allocate (&top_level_config.on_transmission, MDL);
+ if (!top_level_config.on_transmission)
+ log_fatal ("no memory for top-level on_transmission group");
+
+ status = read_client_conf_file (path_dhclient_conf,
+ (struct interface_info *)0,
+ &top_level_config);
+ if (status != ISC_R_SUCCESS) {
+ ;
+#ifdef LATER
+ /* Set up the standard name service updater routine. */
+ parse = (struct parse *)0;
+ status = new_parse (&parse, -1, default_client_config,
+ (sizeof default_client_config) - 1,
+ "default client configuration", 0);
+ if (status != ISC_R_SUCCESS)
+ log_fatal ("can't begin default client config!");
+
do {
- token = peek_token (&val, cfile);
- if (token == EOF)
+ token = peek_token (&val, (unsigned *)0, cfile);
+ if (token == END_OF_FILE)
break;
parse_client_statement (cfile,
(struct interface_info *)0,
&top_level_config);
} while (1);
- token = next_token (&val, cfile); /* Clear the peek buffer */
- fclose (cfile);
+ end_parse (&parse);
+#endif
}
/* Set up state and config structures for clients that don't
- have per-interface configuration declarations. */
+ have per-interface configuration statements. */
config = (struct client_config *)0;
for (ip = interfaces; ip; ip = ip -> next) {
if (!ip -> client) {
ip -> client = (struct client_state *)
- malloc (sizeof (struct client_state));
+ dmalloc (sizeof (struct client_state), MDL);
if (!ip -> client)
- error ("no memory for client state.");
+ log_fatal ("no memory for client state.");
memset (ip -> client, 0, sizeof *(ip -> client));
+ ip -> client -> interface = ip;
}
+
if (!ip -> client -> config) {
if (!config) {
config = (struct client_config *)
- malloc (sizeof (struct client_config));
+ dmalloc (sizeof (struct client_config),
+ MDL);
if (!config)
- error ("no memory for client config.");
+ log_fatal ("no memory for client config.");
memcpy (config, &top_level_config,
sizeof top_level_config);
}
ip -> client -> config = config;
}
}
+ return status;
+}
+
+int read_client_conf_file (const char *name, struct interface_info *ip,
+ struct client_config *client)
+{
+ int file;
+ struct parse *cfile;
+ const char *val;
+ int token;
+ isc_result_t status;
+
+ if ((file = open (name, O_RDONLY)) < 0)
+ return uerr2isc (errno);
+
+ cfile = (struct parse *)0;
+ new_parse (&cfile, file, (char *)0, 0, path_dhclient_conf, 0);
- return !warnings_occurred;
+ do {
+ token = peek_token (&val, (unsigned *)0, cfile);
+ if (token == END_OF_FILE)
+ break;
+ parse_client_statement (cfile, ip, client);
+ } while (1);
+ token = next_token (&val, (unsigned *)0, cfile);
+ status = (cfile -> warnings_occurred
+ ? ISC_R_BADPARSE
+ : ISC_R_SUCCESS);
+ close (file);
+ end_parse (&cfile);
+ return status;
}
-/* lease-file :== client-lease-statements EOF
+
+/* lease-file :== client-lease-statements END_OF_FILE
client-lease-statements :== <nil>
| client-lease-statements LEASE client-lease-statement */
void read_client_leases ()
{
- FILE *cfile;
- char *val;
+ int file;
+ struct parse *cfile;
+ const char *val;
int token;
- new_parse (path_dhclient_db);
-
/* Open the lease file. If we can't open it, just return -
we can safely trust the server to remember our state. */
- if ((cfile = fopen (path_dhclient_db, "r")) == NULL)
+ if ((file = open (path_dhclient_db, O_RDONLY)) < 0)
return;
+ cfile = (struct parse *)0;
+ new_parse (&cfile, file, (char *)0, 0, path_dhclient_db, 0);
+
do {
- token = next_token (&val, cfile);
- if (token == EOF)
+ token = next_token (&val, (unsigned *)0, cfile);
+ if (token == END_OF_FILE)
break;
if (token != LEASE) {
- warn ("Corrupt lease file - possible data loss!");
+ log_error ("Corrupt lease file - possible data loss!");
skip_to_semi (cfile);
break;
} else
parse_client_lease_statement (cfile, 0);
} while (1);
+
+ close (file);
+ end_parse (&cfile);
}
/* client-declaration :==
@@ -188,332 +236,569 @@ void read_client_leases ()
REBOOT number |
SELECT_TIMEOUT number |
SCRIPT string |
+ VENDOR_SPACE string |
interface-declaration |
LEASE client-lease-statement |
- ALIAS client-lease-statement */
+ ALIAS client-lease-statement |
+ KEY key-definition */
void parse_client_statement (cfile, ip, config)
- FILE *cfile;
+ struct parse *cfile;
struct interface_info *ip;
struct client_config *config;
{
int token;
- char *val;
+ const char *val;
struct option *option;
-
- switch (next_token (&val, cfile)) {
- case SEND:
- parse_option_decl (cfile, &config -> send_options [0]);
+ struct executable_statement *stmt, **p;
+ enum statement_op op;
+ int lose;
+ char *name;
+ struct data_string key_id;
+ enum policy policy;
+ int known;
+ int tmp, i;
+ isc_result_t status;
+
+ switch (peek_token (&val, (unsigned *)0, cfile)) {
+ case INCLUDE:
+ next_token (&val, (unsigned *)0, cfile);
+ token = next_token (&val, (unsigned *)0, cfile);
+ if (token != STRING) {
+ parse_warn (cfile, "filename string expected.");
+ skip_to_semi (cfile);
+ } else {
+ status = read_client_conf_file (val, ip, config);
+ if (status != ISC_R_SUCCESS)
+ parse_warn (cfile, "%s: bad parse.", val);
+ parse_semi (cfile);
+ }
return;
-
- case DEFAULT:
- option = parse_option_decl (cfile, &config -> defaults [0]);
- if (option)
- config -> default_actions [option -> code] =
- ACTION_DEFAULT;
+
+ case KEY:
+ next_token (&val, (unsigned *)0, cfile);
+ if (ip) {
+ /* This may seem arbitrary, but there's a reason for
+ doing it: the authentication key database is not
+ scoped. If we allow the user to declare a key other
+ than in the outer scope, the user is very likely to
+ believe that the key will only be used in that
+ scope. If the user only wants the key to be used on
+ one interface, because it's known that the other
+ interface may be connected to an insecure net and
+ the secret key is considered sensitive, we don't
+ want to lull them into believing they've gotten
+ their way. This is a bit contrived, but people
+ tend not to be entirely rational about security. */
+ parse_warn (cfile, "key definition not allowed here.");
+ skip_to_semi (cfile);
+ break;
+ }
+ parse_key (cfile);
return;
- case SUPERSEDE:
- option = parse_option_decl (cfile, &config -> defaults [0]);
- if (option)
- config -> default_actions [option -> code] =
- ACTION_SUPERSEDE;
+ /* REQUIRE can either start a policy statement or a
+ comma-seperated list of names of required options. */
+ case REQUIRE:
+ next_token (&val, (unsigned *)0, cfile);
+ token = peek_token (&val, (unsigned *)0, cfile);
+ if (token == AUTHENTICATION) {
+ policy = P_REQUIRE;
+ goto do_policy;
+ }
+ parse_option_list (cfile, &config -> required_options);
return;
- case APPEND:
- option = parse_option_decl (cfile, &config -> defaults [0]);
- if (option)
- config -> default_actions [option -> code] =
- ACTION_APPEND;
- return;
+ case IGNORE:
+ next_token (&val, (unsigned *)0, cfile);
+ policy = P_IGNORE;
+ goto do_policy;
+
+ case ACCEPT:
+ next_token (&val, (unsigned *)0, cfile);
+ policy = P_ACCEPT;
+ goto do_policy;
+
+ case PREFER:
+ next_token (&val, (unsigned *)0, cfile);
+ policy = P_PREFER;
+ goto do_policy;
+
+ case DONT:
+ next_token (&val, (unsigned *)0, cfile);
+ policy = P_DONT;
+ goto do_policy;
+
+ do_policy:
+ token = next_token (&val, (unsigned *)0, cfile);
+ if (token == AUTHENTICATION) {
+ if (policy != P_PREFER &&
+ policy != P_REQUIRE &&
+ policy != P_DONT) {
+ parse_warn (cfile,
+ "invalid authentication policy.");
+ skip_to_semi (cfile);
+ return;
+ }
+ config -> auth_policy = policy;
+ } else if (token != TOKEN_BOOTP) {
+ if (policy != P_PREFER &&
+ policy != P_IGNORE &&
+ policy != P_ACCEPT) {
+ parse_warn (cfile, "invalid bootp policy.");
+ skip_to_semi (cfile);
+ return;
+ }
+ config -> bootp_policy = policy;
+ } else {
+ parse_warn (cfile, "expecting a policy type.");
+ skip_to_semi (cfile);
+ return;
+ }
+ break;
+
+ case OPTION:
+ token = next_token (&val, (unsigned *)0, cfile);
+
+ token = peek_token (&val, (unsigned *)0, cfile);
+ if (token == SPACE) {
+ if (ip) {
+ parse_warn (cfile,
+ "option space definitions %s",
+ " may not be scoped.");
+ skip_to_semi (cfile);
+ break;
+ }
+ parse_option_space_decl (cfile);
+ return;
+ }
+
+ option = parse_option_name (cfile, 1, &known);
+ if (!option)
+ return;
- case PREPEND:
- option = parse_option_decl (cfile, &config -> defaults [0]);
- if (option)
- config -> default_actions [option -> code] =
- ACTION_PREPEND;
+ token = next_token (&val, (unsigned *)0, cfile);
+ if (token != CODE) {
+ parse_warn (cfile, "expecting \"code\" keyword.");
+ skip_to_semi (cfile);
+ free_option (option, MDL);
+ return;
+ }
+ if (ip) {
+ parse_warn (cfile,
+ "option definitions may only appear in %s",
+ "the outermost scope.");
+ skip_to_semi (cfile);
+ free_option (option, MDL);
+ return;
+ }
+ if (!parse_option_code_definition (cfile, option))
+ free_option (option, MDL);
return;
case MEDIA:
+ token = next_token (&val, (unsigned *)0, cfile);
parse_string_list (cfile, &config -> media, 1);
return;
case HARDWARE:
+ token = next_token (&val, (unsigned *)0, cfile);
if (ip) {
parse_hardware_param (cfile, &ip -> hw_address);
} else {
- parse_warn ("hardware address parameter %s",
+ parse_warn (cfile, "hardware address parameter %s",
"not allowed here.");
skip_to_semi (cfile);
}
return;
case REQUEST:
- config -> requested_option_count =
- parse_option_list (cfile, config -> requested_options);
- return;
-
- case REQUIRE:
- memset (config -> required_options, 0,
- sizeof config -> required_options);
- parse_option_list (cfile, config -> required_options);
+ token = next_token (&val, (unsigned *)0, cfile);
+ if (config -> requested_options == default_requested_options)
+ config -> requested_options = (u_int32_t *)0;
+ parse_option_list (cfile, &config -> requested_options);
return;
case TIMEOUT:
+ token = next_token (&val, (unsigned *)0, cfile);
parse_lease_time (cfile, &config -> timeout);
return;
case RETRY:
+ token = next_token (&val, (unsigned *)0, cfile);
parse_lease_time (cfile, &config -> retry_interval);
return;
case SELECT_TIMEOUT:
+ token = next_token (&val, (unsigned *)0, cfile);
parse_lease_time (cfile, &config -> select_interval);
return;
+ case OMAPI:
+ token = next_token (&val, (unsigned *)0, cfile);
+ token = next_token (&val, (unsigned *)0, cfile);
+ if (token != PORT) {
+ parse_warn (cfile,
+ "unexpected omapi subtype: %s", val);
+ skip_to_semi (cfile);
+ return;
+ }
+ token = next_token (&val, (unsigned *)0, cfile);
+ if (token != NUMBER) {
+ parse_warn (cfile, "invalid port number: `%s'", val);
+ skip_to_semi (cfile);
+ return;
+ }
+ tmp = atoi (val);
+ if (tmp < 0 || tmp > 65535)
+ parse_warn (cfile, "invalid omapi port %d.", tmp);
+ else if (config != &top_level_config)
+ parse_warn (cfile,
+ "omapi port only works at top level.");
+ else
+ config -> omapi_port = tmp;
+ parse_semi (cfile);
+ return;
+
case REBOOT:
+ token = next_token (&val, (unsigned *)0, cfile);
parse_lease_time (cfile, &config -> reboot_timeout);
return;
case BACKOFF_CUTOFF:
+ token = next_token (&val, (unsigned *)0, cfile);
parse_lease_time (cfile, &config -> backoff_cutoff);
return;
case INITIAL_INTERVAL:
+ token = next_token (&val, (unsigned *)0, cfile);
parse_lease_time (cfile, &config -> initial_interval);
return;
case SCRIPT:
- config -> script_name = parse_string (cfile);
+ token = next_token (&val, (unsigned *)0, cfile);
+ parse_string (cfile, &config -> script_name, (unsigned *)0);
+ return;
+
+ case VENDOR:
+ token = next_token (&val, (unsigned *)0, cfile);
+ token = next_token (&val, (unsigned *)0, cfile);
+ if (token != OPTION) {
+ parse_warn (cfile, "expecting 'vendor option space'");
+ skip_to_semi (cfile);
+ return;
+ }
+ token = next_token (&val, (unsigned *)0, cfile);
+ if (token != SPACE) {
+ parse_warn (cfile, "expecting 'vendor option space'");
+ skip_to_semi (cfile);
+ return;
+ }
+ token = next_token (&val, (unsigned *)0, cfile);
+ if (!is_identifier (token)) {
+ parse_warn (cfile, "expecting an identifier.");
+ skip_to_semi (cfile);
+ return;
+ }
+ config -> vendor_space_name = dmalloc (strlen (val) + 1, MDL);
+ if (!config -> vendor_space_name)
+ log_fatal ("no memory for vendor option space name.");
+ strcpy (config -> vendor_space_name, val);
+ for (i = 0; i < universe_count; i++)
+ if (!strcmp (universes [i] -> name,
+ config -> vendor_space_name))
+ break;
+ if (i == universe_count) {
+ log_error ("vendor option space %s not found.",
+ config -> vendor_space_name);
+ }
+ parse_semi (cfile);
return;
case INTERFACE:
+ token = next_token (&val, (unsigned *)0, cfile);
if (ip)
- parse_warn ("nested interface declaration.");
- parse_interface_declaration (cfile, config);
+ parse_warn (cfile, "nested interface declaration.");
+ parse_interface_declaration (cfile, config, (char *)0);
return;
+ case PSEUDO:
+ token = next_token (&val, (unsigned *)0, cfile);
+ token = next_token (&val, (unsigned *)0, cfile);
+ name = dmalloc (strlen (val) + 1, MDL);
+ if (!name)
+ log_fatal ("no memory for pseudo interface name");
+ strcpy (name, val);
+ parse_interface_declaration (cfile, config, name);
+ return;
+
case LEASE:
+ token = next_token (&val, (unsigned *)0, cfile);
parse_client_lease_statement (cfile, 1);
return;
case ALIAS:
+ token = next_token (&val, (unsigned *)0, cfile);
parse_client_lease_statement (cfile, 2);
return;
case REJECT:
+ token = next_token (&val, (unsigned *)0, cfile);
parse_reject_statement (cfile, config);
return;
default:
- parse_warn ("expecting a statement.");
- skip_to_semi (cfile);
- break;
- }
- token = next_token (&val, cfile);
- if (token != SEMI) {
- parse_warn ("semicolon expected.");
- skip_to_semi (cfile);
- }
-}
-
-int parse_X (cfile, buf, max)
- FILE *cfile;
- u_int8_t *buf;
- int max;
-{
- int token;
- char *val;
- int len;
-
- token = peek_token (&val, cfile);
- if (token == NUMBER_OR_NAME || token == NUMBER) {
- len = 0;
- do {
- token = next_token (&val, cfile);
- if (token != NUMBER && token != NUMBER_OR_NAME) {
- parse_warn ("expecting hexadecimal constant.");
+ lose = 0;
+ stmt = (struct executable_statement *)0;
+ if (!parse_executable_statement (&stmt,
+ cfile, &lose, context_any)) {
+ if (!lose) {
+ parse_warn (cfile, "expecting a statement.");
skip_to_semi (cfile);
- return 0;
}
- convert_num (&buf [len], val, 16, 8);
- if (len++ > max) {
- parse_warn ("hexadecimal constant too long.");
- skip_to_semi (cfile);
- return 0;
+ } else {
+ struct executable_statement **eptr, *sptr;
+ if (stmt &&
+ (stmt -> op == send_option_statement ||
+ (stmt -> op == on_statement &&
+ (stmt -> data.on.evtypes & ON_TRANSMISSION)))) {
+ eptr = &config -> on_transmission -> statements;
+ if (stmt -> op == on_statement) {
+ sptr = (struct executable_statement *)0;
+ executable_statement_reference
+ (&sptr,
+ stmt -> data.on.statements, MDL);
+ executable_statement_dereference (&stmt,
+ MDL);
+ executable_statement_reference (&stmt,
+ sptr,
+ MDL);
+ executable_statement_dereference (&sptr,
+ MDL);
+ }
+ } else
+ eptr = &config -> on_receipt -> statements;
+
+ if (stmt) {
+ for (; *eptr; eptr = &(*eptr) -> next)
+ ;
+ executable_statement_reference (eptr,
+ stmt, MDL);
}
- token = peek_token (&val, cfile);
- if (token == COLON)
- token = next_token (&val, cfile);
- } while (token == COLON);
- val = (char *)buf;
- } else if (token == STRING) {
- token = next_token (&val, cfile);
- len = strlen (val);
- if (len + 1 > max) {
- parse_warn ("string constant too long.");
- skip_to_semi (cfile);
- return 0;
+ return;
}
- memcpy (buf, val, len + 1);
- } else {
- parse_warn ("expecting string or hexadecimal data");
- skip_to_semi (cfile);
- return 0;
+ break;
}
- return len;
+ parse_semi (cfile);
}
/* option-list :== option_name |
option_list COMMA option_name */
-int parse_option_list (cfile, list)
- FILE *cfile;
- u_int8_t *list;
+void parse_option_list (cfile, list)
+ struct parse *cfile;
+ u_int32_t **list;
{
int ix, i;
int token;
- char *val;
+ const char *val;
+ pair p = (pair)0, q, r;
ix = 0;
do {
- token = next_token (&val, cfile);
+ token = next_token (&val, (unsigned *)0, cfile);
+ if (token == SEMI)
+ break;
if (!is_identifier (token)) {
- parse_warn ("expected option name.");
+ parse_warn (cfile, "%s: expected option name.", val);
skip_to_semi (cfile);
- return 0;
+ return;
}
for (i = 0; i < 256; i++) {
if (!strcasecmp (dhcp_options [i].name, val))
break;
}
if (i == 256) {
- parse_warn ("%s: expected option name.");
- skip_to_semi (cfile);
- return 0;
- }
- list [ix++] = i;
- if (ix == 256) {
- parse_warn ("%s: too many options.", val);
+ parse_warn (cfile, "%s: expected option name.", val);
skip_to_semi (cfile);
- return 0;
+ return;
}
- token = next_token (&val, cfile);
+ r = new_pair (MDL);
+ if (!r)
+ log_fatal ("can't allocate pair for option code.");
+ r -> car = (caddr_t)(long)i;
+ r -> cdr = (pair)0;
+ if (p)
+ q -> cdr = r;
+ else
+ p = r;
+ q = r;
+ ++ix;
+ token = next_token (&val, (unsigned *)0, cfile);
} while (token == COMMA);
if (token != SEMI) {
- parse_warn ("expecting semicolon.");
+ parse_warn (cfile, "expecting semicolon.");
skip_to_semi (cfile);
- return 0;
+ return;
+ }
+ /* XXX we can't free the list here, because we may have copied
+ XXX it from an outer config state. */
+ *list = (u_int32_t *)0;
+ if (ix) {
+ *list = dmalloc ((ix + 1) * sizeof **list, MDL);
+ if (!*list)
+ log_error ("no memory for option list.");
+ else {
+ ix = 0;
+ for (q = p; q; q = q -> cdr)
+ (*list) [ix++] = (u_int32_t)(long)q -> car;
+ (*list) [ix] = 0;
+ }
+ while (p) {
+ q = p -> cdr;
+ free_pair (p, MDL);
+ p = q;
+ }
}
- return ix;
}
/* interface-declaration :==
INTERFACE string LBRACE client-declarations RBRACE */
-void parse_interface_declaration (cfile, outer_config)
- FILE *cfile;
+void parse_interface_declaration (cfile, outer_config, name)
+ struct parse *cfile;
struct client_config *outer_config;
+ char *name;
{
int token;
- char *val;
+ const char *val;
+ struct client_state *client, **cp;
+ struct interface_info *ip = (struct interface_info *)0;
- struct interface_info *ip;
-
- token = next_token (&val, cfile);
+ token = next_token (&val, (unsigned *)0, cfile);
if (token != STRING) {
- parse_warn ("expecting interface name (in quotes).");
+ parse_warn (cfile, "expecting interface name (in quotes).");
skip_to_semi (cfile);
return;
}
- ip = interface_or_dummy (val);
+ if (!interface_or_dummy (&ip, val))
+ log_fatal ("Can't allocate interface %s.", val);
- if (!ip -> client)
- make_client_state (ip);
+ /* If we were given a name, this is a pseudo-interface. */
+ if (name) {
+ make_client_state (&client);
+ client -> name = name;
+ client -> interface = ip;
+ for (cp = &ip -> client; *cp; cp = &((*cp) -> next))
+ ;
+ *cp = client;
+ } else {
+ if (!ip -> client) {
+ make_client_state (&ip -> client);
+ ip -> client -> interface = ip;
+ }
+ client = ip -> client;
+ }
- if (!ip -> client -> config)
- make_client_config (ip, outer_config);
+ if (!client -> config)
+ make_client_config (client, outer_config);
ip -> flags &= ~INTERFACE_AUTOMATIC;
interfaces_requested = 1;
- token = next_token (&val, cfile);
+ token = next_token (&val, (unsigned *)0, cfile);
if (token != LBRACE) {
- parse_warn ("expecting left brace.");
+ parse_warn (cfile, "expecting left brace.");
skip_to_semi (cfile);
return;
}
do {
- token = peek_token (&val, cfile);
- if (token == EOF) {
- parse_warn ("unterminated interface declaration.");
+ token = peek_token (&val, (unsigned *)0, cfile);
+ if (token == END_OF_FILE) {
+ parse_warn (cfile,
+ "unterminated interface declaration.");
return;
}
if (token == RBRACE)
break;
- parse_client_statement (cfile, ip, ip -> client -> config);
+ parse_client_statement (cfile, ip, client -> config);
} while (1);
- token = next_token (&val, cfile);
+ token = next_token (&val, (unsigned *)0, cfile);
}
-struct interface_info *interface_or_dummy (name)
- char *name;
+int interface_or_dummy (struct interface_info **pi, const char *name)
{
- struct interface_info *ip;
+ struct interface_info *i;
+ struct interface_info *ip = (struct interface_info *)0;
+ isc_result_t status;
/* Find the interface (if any) that matches the name. */
- for (ip = interfaces; ip; ip = ip -> next) {
- if (!strcmp (ip -> name, name))
+ for (i = interfaces; i; i = i -> next) {
+ if (!strcmp (i -> name, name)) {
+ interface_reference (&ip, i, MDL);
break;
+ }
}
/* If it's not a real interface, see if it's on the dummy list. */
if (!ip) {
for (ip = dummy_interfaces; ip; ip = ip -> next) {
- if (!strcmp (ip -> name, name))
+ if (!strcmp (ip -> name, name)) {
+ interface_reference (&ip, i, MDL);
break;
+ }
}
}
/* If we didn't find an interface, make a dummy interface as
a placeholder. */
if (!ip) {
- ip = ((struct interface_info *)malloc (sizeof *ip));
- if (!ip)
- error ("Insufficient memory to record interface %s",
- name);
- memset (ip, 0, sizeof *ip);
+ isc_result_t status;
+ status = interface_allocate (&ip, MDL);
+ if (status != ISC_R_SUCCESS)
+ log_fatal ("Can't record interface %s: %s",
+ name, isc_result_totext (status));
strcpy (ip -> name, name);
- ip -> next = dummy_interfaces;
- dummy_interfaces = ip;
+ if (dummy_interfaces) {
+ interface_reference (&ip -> next,
+ dummy_interfaces, MDL);
+ interface_dereference (&dummy_interfaces, MDL);
+ }
+ interface_reference (&dummy_interfaces, ip, MDL);
}
- return ip;
+ if (pi)
+ status = interface_reference (pi, ip, MDL);
+ interface_dereference (&ip, MDL);
+ if (status != ISC_R_SUCCESS)
+ return 0;
+ return 1;
}
-void make_client_state (ip)
- struct interface_info *ip;
+void make_client_state (state)
+ struct client_state **state;
{
- ip -> client =
- ((struct client_state *)malloc (sizeof *(ip -> client)));
- if (!ip -> client)
- error ("no memory for state on %s\n", ip -> name);
- memset (ip -> client, 0, sizeof *(ip -> client));
+ *state = ((struct client_state *)dmalloc (sizeof **state, MDL));
+ if (!*state)
+ log_fatal ("no memory for client state\n");
+ memset (*state, 0, sizeof **state);
}
-void make_client_config (ip, config)
- struct interface_info *ip;
+void make_client_config (client, config)
+ struct client_state *client;
struct client_config *config;
{
- ip -> client -> config =
- ((struct client_config *)
- malloc (sizeof (struct client_config)));
- if (!ip -> client -> config)
- error ("no memory for config for %s\n", ip -> name);
- memset (ip -> client -> config, 0,
- sizeof *(ip -> client -> config));
- memcpy (ip -> client -> config, config, sizeof *config);
+ client -> config = (((struct client_config *)
+ dmalloc (sizeof (struct client_config), MDL)));
+ if (!client -> config)
+ log_fatal ("no memory for client config\n");
+ memcpy (client -> config, config, sizeof *config);
+ if (!clone_group (&client -> config -> on_receipt,
+ config -> on_receipt, MDL) ||
+ !clone_group (&client -> config -> on_transmission,
+ config -> on_transmission, MDL))
+ log_fatal ("no memory for client state groups.");
}
/* client-lease-statement :==
@@ -526,51 +811,57 @@ void make_client_config (ip, config)
void parse_client_lease_statement (cfile, is_static)
- FILE *cfile;
+ struct parse *cfile;
int is_static;
{
struct client_lease *lease, *lp, *pl;
- struct interface_info *ip;
+ struct interface_info *ip = (struct interface_info *)0;
int token;
- char *val;
+ const char *val;
+ struct client_state *client = (struct client_state *)0;
- token = next_token (&val, cfile);
+ token = next_token (&val, (unsigned *)0, cfile);
if (token != LBRACE) {
- parse_warn ("expecting left brace.");
+ parse_warn (cfile, "expecting left brace.");
skip_to_semi (cfile);
return;
}
- lease = (struct client_lease *)malloc (sizeof (struct client_lease));
+ lease = ((struct client_lease *)
+ dmalloc (sizeof (struct client_lease), MDL));
if (!lease)
- error ("no memory for lease.\n");
+ log_fatal ("no memory for lease.\n");
memset (lease, 0, sizeof *lease);
lease -> is_static = is_static;
-
- ip = (struct interface_info *)0;
+ if (!option_state_allocate (&lease -> options, MDL))
+ log_fatal ("no memory for lease options.\n");
do {
- token = peek_token (&val, cfile);
- if (token == EOF) {
- parse_warn ("unterminated lease declaration.");
+ token = peek_token (&val, (unsigned *)0, cfile);
+ if (token == END_OF_FILE) {
+ parse_warn (cfile, "unterminated lease declaration.");
return;
}
if (token == RBRACE)
break;
- parse_client_lease_declaration (cfile, lease, &ip);
+ parse_client_lease_declaration (cfile, lease, &ip, &client);
} while (1);
- token = next_token (&val, cfile);
+ token = next_token (&val, (unsigned *)0, cfile);
/* If the lease declaration didn't include an interface
declaration that we recognized, it's of no use to us. */
if (!ip) {
- free_client_lease (lease);
+ destroy_client_lease (lease);
return;
}
/* Make sure there's a client state structure... */
- if (!ip -> client)
- make_client_state (ip);
+ if (!ip -> client) {
+ make_client_state (&ip -> client);
+ ip -> client -> interface = ip;
+ }
+ if (!client)
+ client = ip -> client;
/* If this is an alias lease, it doesn't need to be sorted in. */
if (is_static == 2) {
@@ -583,15 +874,15 @@ void parse_client_lease_statement (cfile, is_static)
lease list looking for a lease with the same address, and
if we find it, toss it. */
pl = (struct client_lease *)0;
- for (lp = ip -> client -> leases; lp; lp = lp -> next) {
+ for (lp = client -> leases; lp; lp = lp -> next) {
if (lp -> address.len == lease -> address.len &&
!memcmp (lp -> address.iabuf, lease -> address.iabuf,
lease -> address.len)) {
if (pl)
pl -> next = lp -> next;
else
- ip -> client -> leases = lp -> next;
- free_client_lease (lp);
+ client -> leases = lp -> next;
+ destroy_client_lease (lp);
break;
}
}
@@ -599,8 +890,8 @@ void parse_client_lease_statement (cfile, is_static)
/* If this is a preloaded lease, just put it on the list of recorded
leases - don't make it the active lease. */
if (is_static) {
- lease -> next = ip -> client -> leases;
- ip -> client -> leases = lease;
+ lease -> next = client -> leases;
+ client -> leases = lease;
return;
}
@@ -615,22 +906,21 @@ void parse_client_lease_statement (cfile, is_static)
then if the old active lease has expired, we dump it; if not,
we put it on the list of leases for this interface which are
still valid but no longer active. */
- if (ip -> client -> active) {
- if (ip -> client -> active -> expiry < cur_time)
- free_client_lease (ip -> client -> active);
- else if (ip -> client -> active -> address.len ==
+ if (client -> active) {
+ if (client -> active -> expiry < cur_time)
+ destroy_client_lease (client -> active);
+ else if (client -> active -> address.len ==
lease -> address.len &&
- !memcmp (ip -> client -> active -> address.iabuf,
+ !memcmp (client -> active -> address.iabuf,
lease -> address.iabuf,
lease -> address.len))
- free_client_lease (ip -> client -> active);
+ destroy_client_lease (client -> active);
else {
- ip -> client -> active -> next =
- ip -> client -> leases;
- ip -> client -> leases = ip -> client -> active;
+ client -> active -> next = client -> leases;
+ client -> leases = client -> active;
}
}
- ip -> client -> active = lease;
+ client -> active = lease;
/* phew. */
}
@@ -644,31 +934,65 @@ void parse_client_lease_statement (cfile, is_static)
OPTION option-decl |
RENEW time-decl |
REBIND time-decl |
- EXPIRE time-decl */
+ EXPIRE time-decl |
+ KEY id */
-void parse_client_lease_declaration (cfile, lease, ipp)
- FILE *cfile;
+void parse_client_lease_declaration (cfile, lease, ipp, clientp)
+ struct parse *cfile;
struct client_lease *lease;
struct interface_info **ipp;
+ struct client_state **clientp;
{
int token;
- char *val;
+ const char *val;
+ char *t, *n;
struct interface_info *ip;
-
- switch (next_token (&val, cfile)) {
- case BOOTP:
+ struct option_cache *oc;
+ struct client_state *client = (struct client_state *)0;
+ struct data_string key_id;
+
+ switch (next_token (&val, (unsigned *)0, cfile)) {
+ case KEY:
+ token = next_token (&val, (unsigned *)0, cfile);
+ if (token != STRING && !is_identifier (token)) {
+ parse_warn (cfile, "expecting key name.");
+ skip_to_semi (cfile);
+ break;
+ }
+ if (omapi_auth_key_lookup_name (&lease -> key, val) !=
+ ISC_R_SUCCESS)
+ parse_warn (cfile, "unknown key %s", val);
+ parse_semi (cfile);
+ break;
+ case TOKEN_BOOTP:
lease -> is_bootp = 1;
break;
case INTERFACE:
- token = next_token (&val, cfile);
+ token = next_token (&val, (unsigned *)0, cfile);
if (token != STRING) {
- parse_warn ("expecting interface name (in quotes).");
+ parse_warn (cfile,
+ "expecting interface name (in quotes).");
skip_to_semi (cfile);
break;
}
- ip = interface_or_dummy (val);
- *ipp = ip;
+ interface_or_dummy (ipp, val);
+ break;
+
+ case NAME:
+ token = next_token (&val, (unsigned *)0, cfile);
+ ip = *ipp;
+ if (!ip) {
+ parse_warn (cfile, "state name precedes interface.");
+ break;
+ }
+ for (client = ip -> client; client; client = client -> next)
+ if (client -> name && !strcmp (client -> name, val))
+ break;
+ if (!client)
+ parse_warn (cfile,
+ "lease specified for unknown pseudo.");
+ *clientp = client;
break;
case FIXED_ADDR:
@@ -681,11 +1005,11 @@ void parse_client_lease_declaration (cfile, lease, ipp)
return;
case FILENAME:
- lease -> filename = parse_string (cfile);
+ parse_string (cfile, &lease -> filename, (unsigned *)0);
return;
case SERVER_NAME:
- lease -> server_name = parse_string (cfile);
+ parse_string (cfile, &lease -> server_name, (unsigned *)0);
return;
case RENEW:
@@ -701,239 +1025,33 @@ void parse_client_lease_declaration (cfile, lease, ipp)
return;
case OPTION:
- parse_option_decl (cfile, lease -> options);
+ oc = (struct option_cache *)0;
+ if (parse_option_decl (&oc, cfile)) {
+ save_option (oc -> option -> universe,
+ lease -> options, oc);
+ option_cache_dereference (&oc, MDL);
+ }
return;
default:
- parse_warn ("expecting lease declaration.");
+ parse_warn (cfile, "expecting lease declaration.");
skip_to_semi (cfile);
break;
}
- token = next_token (&val, cfile);
+ token = next_token (&val, (unsigned *)0, cfile);
if (token != SEMI) {
- parse_warn ("expecting semicolon.");
+ parse_warn (cfile, "expecting semicolon.");
skip_to_semi (cfile);
}
}
-struct option *parse_option_decl (cfile, options)
- FILE *cfile;
- struct option_data *options;
-{
- char *val;
- int token;
- u_int8_t buf [4];
- u_int8_t hunkbuf [1024];
- int hunkix = 0;
- char *vendor;
- char *fmt;
- struct universe *universe;
- struct option *option;
- struct iaddr ip_addr;
- u_int8_t *dp;
- int len;
- int nul_term = 0;
-
- token = next_token (&val, cfile);
- if (!is_identifier (token)) {
- parse_warn ("expecting identifier after option keyword.");
- if (token != SEMI)
- skip_to_semi (cfile);
- return (struct option *)0;
- }
- vendor = malloc (strlen (val) + 1);
- if (!vendor)
- error ("no memory for vendor information.");
- 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);
- return (struct option *)0;
- }
-
- /* Look up the option name hash table for the specified
- vendor. */
- universe = ((struct universe *)
- hash_lookup (&universe_hash,
- (unsigned char *)vendor, 0));
- /* If it's not there, we can't parse the rest of the
- declaration. */
- if (!universe) {
- parse_warn ("no vendor named %s.", vendor);
- skip_to_semi (cfile);
- return (struct option *)0;
- }
- } 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,
- (unsigned char *)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);
- return (struct option *)0;
- }
-
- /* Free the initial identifier token. */
- free (vendor);
-
- /* Parse the option data... */
- do {
- for (fmt = option -> format; *fmt; fmt++) {
- if (*fmt == 'A')
- break;
- switch (*fmt) {
- case 'X':
- len = parse_X (cfile, &hunkbuf [hunkix],
- sizeof hunkbuf - hunkix);
- hunkix += len;
- break;
-
- case 't': /* Text string... */
- token = next_token (&val, cfile);
- if (token != STRING) {
- parse_warn ("expecting string.");
- skip_to_semi (cfile);
- return (struct option *)0;
- }
- len = strlen (val);
- if (hunkix + len + 1 > sizeof hunkbuf) {
- parse_warn ("option data buffer %s",
- "overflow");
- skip_to_semi (cfile);
- return (struct option *)0;
- }
- memcpy (&hunkbuf [hunkix], val, len + 1);
- nul_term = 1;
- hunkix += len;
- break;
-
- case 'I': /* IP address. */
- if (!parse_ip_addr (cfile, &ip_addr))
- return (struct option *)0;
- len = ip_addr.len;
- dp = ip_addr.iabuf;
-
- alloc:
- if (hunkix + len > sizeof hunkbuf) {
- parse_warn ("option data buffer %s",
- "overflow");
- skip_to_semi (cfile);
- return (struct option *)0;
- }
- memcpy (&hunkbuf [hunkix], dp, len);
- hunkix += len;
- 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);
- return (struct option *)0;
- }
- convert_num (buf, val, 0, 32);
- len = 4;
- dp = buf;
- goto alloc;
-
- 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);
- len = 2;
- dp = buf;
- goto alloc;
-
- 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);
- len = 1;
- dp = buf;
- goto alloc;
-
- 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);
- return (struct option *)0;
- }
- 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;
- }
- len = 1;
- dp = buf;
- goto alloc;
-
- default:
- warn ("Bad format %c in parse_option_param.",
- *fmt);
- skip_to_semi (cfile);
- return (struct option *)0;
- }
- }
- token = next_token (&val, cfile);
- } while (*fmt == 'A' && token == COMMA);
-
- if (token != SEMI) {
- parse_warn ("semicolon expected.");
- skip_to_semi (cfile);
- return (struct option *)0;
- }
-
- options [option -> code].data =
- (unsigned char *)malloc (hunkix + nul_term);
- if (!options [option -> code].data)
- error ("out of memory allocating option data.");
- memcpy (options [option -> code].data, hunkbuf, hunkix + nul_term);
- options [option -> code].len = hunkix;
- return option;
-}
-
void parse_string_list (cfile, lp, multiple)
- FILE *cfile;
+ struct parse *cfile;
struct string_list **lp;
int multiple;
{
int token;
- char *val;
+ const char *val;
struct string_list *cur, *tmp;
/* Find the last medium in the media list. */
@@ -945,18 +1063,18 @@ void parse_string_list (cfile, lp, multiple)
}
do {
- token = next_token (&val, cfile);
+ token = next_token (&val, (unsigned *)0, cfile);
if (token != STRING) {
- parse_warn ("Expecting media options.");
+ parse_warn (cfile, "Expecting media options.");
skip_to_semi (cfile);
return;
}
- tmp = (struct string_list *)malloc (strlen (val) + 1 +
- sizeof
- (struct string_list *));
+ tmp = ((struct string_list *)
+ dmalloc (strlen (val) + sizeof (struct string_list),
+ MDL));
if (!tmp)
- error ("no memory for string list entry.");
+ log_fatal ("no memory for string list entry.");
strcpy (tmp -> string, val);
tmp -> next = (struct string_list *)0;
@@ -968,44 +1086,67 @@ void parse_string_list (cfile, lp, multiple)
*lp = tmp;
cur = tmp;
- token = next_token (&val, cfile);
+ token = next_token (&val, (unsigned *)0, cfile);
} while (multiple && token == COMMA);
if (token != SEMI) {
- parse_warn ("expecting semicolon.");
+ parse_warn (cfile, "expecting semicolon.");
skip_to_semi (cfile);
}
}
void parse_reject_statement (cfile, config)
- FILE *cfile;
+ struct parse *cfile;
struct client_config *config;
{
int token;
- char *val;
+ const char *val;
struct iaddr addr;
struct iaddrlist *list;
do {
if (!parse_ip_addr (cfile, &addr)) {
- parse_warn ("expecting IP address.");
+ parse_warn (cfile, "expecting IP address.");
skip_to_semi (cfile);
return;
}
- list = (struct iaddrlist *)malloc (sizeof (struct iaddrlist));
+ list = (struct iaddrlist *)dmalloc (sizeof (struct iaddrlist),
+ MDL);
if (!list)
- error ("no memory for reject list!");
+ log_fatal ("no memory for reject list!");
list -> addr = addr;
list -> next = config -> reject_list;
config -> reject_list = list;
- token = next_token (&val, cfile);
+ token = next_token (&val, (unsigned *)0, cfile);
} while (token == COMMA);
if (token != SEMI) {
- parse_warn ("expecting semicolon.");
+ parse_warn (cfile, "expecting semicolon.");
skip_to_semi (cfile);
}
}
+
+/* allow-deny-keyword :== BOOTP
+ | BOOTING
+ | DYNAMIC_BOOTP
+ | UNKNOWN_CLIENTS */
+
+int parse_allow_deny (oc, cfile, flag)
+ struct option_cache **oc;
+ struct parse *cfile;
+ int flag;
+{
+ enum dhcp_token token;
+ const char *val;
+ unsigned char rf = flag;
+ struct expression *data = (struct expression *)0;
+ int status;
+
+ parse_warn (cfile, "allow/deny/ignore not permitted here.");
+ skip_to_semi (cfile);
+ return 0;
+}
+
diff --git a/contrib/isc-dhcp/client/dhclient-script.8 b/contrib/isc-dhcp/client/dhclient-script.8
index 82212db6cf6d..02b22527f4bd 100644
--- a/contrib/isc-dhcp/client/dhclient-script.8
+++ b/contrib/isc-dhcp/client/dhclient-script.8
@@ -1,8 +1,6 @@
.\" dhclient-script.8
.\"
-.\" Copyright (c) 1997 The Internet Software Consortium.
-.\" All rights reserved.
-.\"
+.\" Copyright (c) 1996-2001 Internet Software Consortium.
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
@@ -31,10 +29,11 @@
.\" SUCH DAMAGE.
.\"
.\" This software has been written for the Internet Software Consortium
-.\" by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
-.\" Enterprises. To learn more about the Internet Software Consortium,
-.\" see ``http://www.isc.org/isc''. To learn more about Vixie
-.\" Enterprises, see ``http://www.vix.com''.
+.\" by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
+.\" To learn more about the Internet Software Consortium, see
+.\" ``http://www.isc.org/''. To learn more about Vixie Enterprises,
+.\" see ``http://www.vix.com''. To learn more about Nominum, Inc., see
+.\" ``http://www.nominum.com''.
.TH dhclient-script 8
.SH NAME
dhclient-script - DHCP client network configuration script
@@ -61,7 +60,7 @@ to a particular computer should be done in the
.B ETCDIR/dhclient.conf
file. If you find that you can't make such a customization without
customizing
-.B dhclient-script
+.B ETCDIR/dhclient.conf
or using the enter and exit hooks, please submit a bug report.
.SH HOOKS
When it starts, the client script first defines a shell function,
@@ -80,23 +79,29 @@ is available to this script, which may modify the environment if needed
to change the behaviour of the script. If an error occurs during the
execution of the script, it can set the exit_status variable to a nonzero
value, and
-.B ETCDIR/dhclient-script
+.B CLIENTBINDIR/dhclient-script
will exit with that error code immediately after the client script exits.
.PP
After all processing has completed,
-.B ETCDIR/dhclient-script
+.B CLIENTBINDIR/dhclient-script
checks for the presence of an executable
.B ETCDIR/dhclient-exit-hooks
-script, which if present is invoked using the '.' command. The exit status
-is passed in the exit_status shell variable, and will always be zero if the
-script succeeded at the task for which it was invoked.
+script, which if present is invoked using the '.' command. The exit
+status of dhclient-script will be passed to dhclient-exit-hooks in the
+exit_status shell variable, and will always be zero if the script
+succeeded at the task for which it was invoked. The rest of the
+environment as described previously for dhclient-enter-hooks is also
+present. The
+.B ETCDIR/dhclient-exit-hooks
+script can modify the valid of exit_status to change the exit status
+of dhclient-script.
.SH OPERATION
When dhclient needs to invoke the client configuration script, it
-writes a shell script into /tmp which defines a variety of variables.
+defines a set of variables in the environment, and then invokes
+.B CLIENTBINDIR/dhclient-script.
In all cases, $reason is set to the name of the reason why the script
has been invoked. The following reasons are currently defined:
-MEDIUM, PREINIT, ARPCHECK, ARPSEND, BOUND, RENEW, REBIND, REBOOT,
-EXPIRE, FAIL and TIMEOUT.
+MEDIUM, PREINIT, BOUND, RENEW, REBIND, REBOOT, EXPIRE, FAIL and TIMEOUT.
.PP
.SH MEDIUM
The DHCP client is requesting that an interface's media type
@@ -115,18 +120,6 @@ and the media type in $medium.
If an IP alias has been declared in dhclient.conf, its address will be
passed in $alias_ip_address, and that ip alias should be deleted from
the interface, along with any routes to it.
-.SH ARPSEND
-The DHCP client is requesting that an address that has been offered to
-it be checked to see if somebody else is using it, by sending an ARP
-request for that address. It's not clear how to implement this, so
-no examples exist yet. The IP address to check is passed in
-$new_ip_address, and the interface name is passed in $interface.
-.SH ARPCHECK
-The DHCP client wants to know if a response to the ARP request send
-using ARPSEND has been received. If one has, the script should exit
-with a nonzero status, indicating that the offered address has already
-been requested and should be declined. $new_ip_address and
-$interface are set as with ARPSEND.
.SH BOUND
The DHCP client has done an initial binding to a new address. The
new ip address is passed in $new_ip_address, and the interface name is
@@ -137,6 +130,13 @@ by underscores ('_') in order to make valid shell variables, and the
variable names start with new_. So for example, the new subnet mask
would be passed in $new_subnet_mask.
.PP
+Before actually configuring the address, dhclient-script should
+somehow ARP for it and exit with a nonzero status if it receives a
+reply. In this case, the client will send a DHCPDECLINE message to
+the server and acquire a different address. This may also be done in
+the RENEW, REBIND, or REBOOT states, but is not required, and indeed
+may not be desirable.
+.PP
When a binding has been completed, a lot of network parameters are
likely to need to be set up. A new /etc/resolv.conf needs to be
created, using the values of $new_domain_name and
@@ -216,10 +216,10 @@ dhclient.leases(5).
.SH AUTHOR
.B dhclient-script(8)
has been written for the Internet Software Consortium
-by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+by Ted Lemon in cooperation with Vixie
Enterprises. To learn more about the Internet Software Consortium,
see
-.B http://www.vix.com/isc.
+.B http://www.isc.org.
To learn more about Vixie
Enterprises, see
.B http://www.vix.com.
diff --git a/contrib/isc-dhcp/client/dhclient.8 b/contrib/isc-dhcp/client/dhclient.8
index eae843776c74..b47a4fdfff57 100644
--- a/contrib/isc-dhcp/client/dhclient.8
+++ b/contrib/isc-dhcp/client/dhclient.8
@@ -1,40 +1,20 @@
.\" dhclient.8
.\"
-.\" Copyright (c) 1997 The Internet Software Consortium.
-.\" All rights reserved.
+.\" Copyright (c) 1996-1999 Internet Software Consortium.
+.\" Use is subject to license terms which appear in the file named
+.\" ISC-LICENSE that should have accompanied this file when you
+.\" received it. If a file named ISC-LICENSE did not accompany this
+.\" file, or you are not sure the one you have is correct, you may
+.\" obtain an applicable copy of the license at:
.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
+.\" http://www.isc.org/isc-license-1.0.html.
.\"
-.\" 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 file is part of the ISC DHCP distribution. The documentation
+.\" associated with this file is listed in the file DOCUMENTATION,
+.\" included in the top-level directory of this release.
.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
-.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-.\" DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
-.\" CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-.\" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
-.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" This software has been written for the Internet Software Consortium
-.\" by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
-.\" Enterprises. To learn more about the Internet Software Consortium,
-.\" see ``http://www.isc.org/isc''. To learn more about Vixie
-.\" Enterprises, see ``http://www.vix.com''.
+.\" Support and other services are available for ISC products - see
+.\" http://www.isc.org for more information.
.TH dhclient 8
.SH NAME
dhclient - Dynamic Host Configuration Protocol Client
@@ -48,6 +28,48 @@ dhclient - Dynamic Host Configuration Protocol Client
.B -d
]
[
+.B -q
+]
+[
+.B -1
+]
+[
+.B -r
+]
+[
+.B -lf
+.I lease-file
+]
+[
+.B -pf
+.I pid-file
+]
+[
+.B -cf
+.I config-file
+]
+[
+.B -sf
+.I script-file
+]
+[
+.B -s
+server
+]
+[
+.B -g
+relay
+]
+[
+.B -n
+]
+[
+.B -nw
+]
+[
+.B -w
+]
+[
.I if0
[
.I ...ifN
@@ -87,7 +109,7 @@ dhclient.leases file. In order to prevent the file from becoming
arbitrarily large, from time to time dhclient creates a new
dhclient.leases file from its in-core lease database. The old version
of the dhclient.leases file is retained under the name
-.IR dhcpd.leases~
+.IR dhclient.leases~
until the next time dhclient rewrites the database.
.PP
Old leases are kept around in case the DHCP server is unavailable when
@@ -112,49 +134,163 @@ than cycling through the list of old leases.
.PP
The names of the network interfaces that dhclient should attempt to
configure may be specified on the command line. If no interface names
-are specified on the command line dhclient will identify all network
-interfaces, elimininating non-broadcast interfaces if possible, and
-attempt to configure each interface.
+are specified on the command line dhclient will normally identify all
+network interfaces, elimininating non-broadcast interfaces if
+possible, and attempt to configure each interface.
.PP
-If dhclient should listen and transmit on a port other than the
+It is also possible to specify interfaces by name in the
+.B dhclient.conf(5)
+file. If interfaces are specified in this way, then the client will
+only configure interfaces that are either specified in the
+configuration file or on the command line, and will ignore all other
+interfaces.
+.PP
+If the DHCP client should listen and transmit on a port other than the
standard (port 68), the
.B -p
flag may used. It should be followed by the udp port number that
dhclient should use. This is mostly useful for debugging purposes.
-If the
-.B -p
-flag is specified, the client will transmit responses to servers at a
-port number that is one less than the one specified - i.e., if you
-specify
-.B -p
-68, then the client will listen on port 68 and transmit to port 67.
-Datagrams that must go through relay agents are sent to the port
-number specified with the
-.B -p
-flag - if you wish to use alternate port numbers, you must configure
-any relay agents you are using to use the same alternate port numbers.
+If a different port is specified for the client to listen on and
+transmit on, the client will also use a different destination port -
+one greater than the specified destination port.
+.PP
+The DHCP client normally transmits any protocol messages it sends
+before acquiring an IP address to, 255.255.255.255, the IP limited
+broadcast address. For debugging purposes, it may be useful to have
+the server transmit these messages to some other address. This can
+be specified with the
+.B -s
+flag, followed by the IP address or domain name of the destination.
.PP
-Dhclient will normally run in the foreground until it has configured
-an interface, and then will revert to running in the background.
-To run force dhclient to always run as a foreground process, the
+For testing purposes, the giaddr field of all packets that the client
+sends can be set using the
+.B -g
+flag, followed by the IP address to send. This is only useful for testing,
+and should not be expected to work in any consistent or useful way.
+.PP
+The DHCP client will normally run in the foreground until it has
+configured an interface, and then will revert to running in the
+background. To run force dhclient to always run as a foreground
+process, the
.B -d
-flag should be specified. This is useful when running dhclient under
-a debugger, or when running it out of inittab on System V systems.
+flag should be specified. This is useful when running the client
+under a debugger, or when running it out of inittab on System V
+systems.
+.PP
+The client normally prints a startup message and displays the
+protocol sequence to the standard error descriptor until it has
+acquired an address, and then only logs messages using the
+.B syslog (3)
+facility. The
+.B -q
+flag prevents any messages other than errors from being printed to the
+standard error descriptor.
+.PP
+The client normally doesn't release the current lease as it is not
+required by the DHCP protocol. Some cable ISPs require their clients
+to notify the server if they wish to release an assigned IP address.
+The
+.B -r
+flag explicitly releases the current lease, and once the lease has been
+released, the client exits.
+.PP
+The
+.B -1
+flag cause dhclient to try once to get a lease. If it fails, dhclient exits
+with exit code two.
+.PP
+The DHCP client normally gets its configuration information from
+.B ETCDIR/dhclient.conf,
+its lease database from
+.B DBDIR/dhclient.leases,
+stores its process ID in a file called
+.B RUNDIR/dhclient.pid,
+and configures the network interface using
+.B CLIENTBINDIR/dhclient-script
+To specify different names and/or locations for these files, use the
+.B -cf,
+.B -lf,
+.B -pf
+and
+.B -sf
+flags, respectively, followed by the name of the file. This can be
+particularly useful if, for example,
+.B DBDIR
+or
+.B RUNDIR
+has not yet been mounted when the DHCP client is started.
.PP
+The DHCP client normally exits if it isn't able to identify any
+network interfaces to configure. On laptop computers and other
+computers with hot-swappable I/O buses, it is possible that a
+broadcast interface may be added after system startup. The
+.B -w
+flag can be used to cause the client not to exit when it doesn't find
+any such interfaces. The
+.B omshell (8)
+program can then be used to notify the client when a network interface
+has been added or removed, so that the client can attempt to configure an IP
+address on that interface.
+.PP
+The DHCP client can be directed not to attempt to configure any interfaces
+using the
+.B -n
+flag. This is most likely to be useful in combination with the
+.B -w
+flag.
+.PP
+The client can also be instructed to become a daemon immediately, rather
+than waiting until it has acquired an IP address. This can be done by
+supplying the
+.B -nw
+flag.
.SH CONFIGURATION
The syntax of the dhclient.conf(8) file is discussed seperately.
+.SH OMAPI
+The DHCP client provides some ability to control it while it is
+running, without stopping it. This capability is provided using OMAPI,
+an API for manipulating remote objects. OMAPI clients connect to the
+client using TCP/IP, authenticate, and can then examine the client's
+current status and make changes to it.
+.PP
+Rather than implementing the underlying OMAPI protocol directly, user
+programs should use the dhcpctl API or OMAPI itself. Dhcpctl is a
+wrapper that handles some of the housekeeping chores that OMAPI does
+not do automatically. Dhcpctl and OMAPI are documented in \fBdhcpctl(3)\fR
+and \fBomapi(3)\fR. Most things you'd want to do with the client can
+be done directly using the \fBomshell(1)\fR command, rather than
+having to write a special program.
+.SH THE CONTROL OBJECT
+The control object allows you to shut the client down, releasing all
+leases that it holds and deleting any DNS records it may have added.
+It also allows you to pause the client - this unconfigures any
+interfaces the client is using. You can then restart it, which
+causes it to reconfigure those interfaces. You would normally pause
+the client prior to going into hibernation or sleep on a laptop
+computer. You would then resume it after the power comes back.
+This allows PC cards to be shut down while the computer is hibernating
+or sleeping, and then reinitialized to their previous state once the
+computer comes out of hibernation or sleep.
+.PP
+The control object has one attribute - the state attribute. To shut
+the client down, set its state attribute to 2. It will automatically
+do a DHCPRELEASE. To pause it, set its state attribute to 3. To
+resume it, set its state attribute to 4.
+.PP
.SH FILES
+.B CLIENTBINDIR/dhclient-script,
.B ETCDIR/dhclient.conf, DBDIR/dhclient.leases, RUNDIR/dhclient.pid,
.B DBDIR/dhclient.leases~.
.SH SEE ALSO
-dhcpd(8), dhcrelay(8), dhclient.conf(5), dhclient.leases(5)
+dhcpd(8), dhcrelay(8), dhclient-script (8), dhclient.conf(5),
+dhclient.leases(5).
.SH AUTHOR
.B dhclient(8)
has been written for the Internet Software Consortium
-by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+by Ted Lemon in cooperation with Vixie
Enterprises. To learn more about the Internet Software Consortium,
see
-.B http://www.vix.com/isc.
+.B http://www.isc.org
To learn more about Vixie
Enterprises, see
.B http://www.vix.com.
diff --git a/contrib/isc-dhcp/client/dhclient.c b/contrib/isc-dhcp/client/dhclient.c
index 129f99ab9e45..f1c0ddd34674 100644
--- a/contrib/isc-dhcp/client/dhclient.c
+++ b/contrib/isc-dhcp/client/dhclient.c
@@ -3,8 +3,8 @@
DHCP Client. */
/*
- * Copyright (c) 1995, 1996, 1997, 1998, 1999
- * The Internet Software Consortium. All rights reserved.
+ * Copyright (c) 1995-2001 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
@@ -15,7 +15,7 @@
* 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
+ * 3. Neither the name of 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.
*
@@ -33,30 +33,15 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * This software has been written for the Internet Software Consortium
- * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
- * Enterprises. To learn more about the Internet Software Consortium,
- * see ``http://www.vix.com/isc''. To learn more about Vixie
- * Enterprises, see ``http://www.vix.com''.
- *
- * This client was substantially modified and enhanced by Elliot Poger
- * for use on Linux while he was working on the MosquitoNet project at
- * Stanford.
- *
- * The current version owes much to Elliot's Linux enhancements, but
- * was substantially reorganized and partially rewritten by Ted Lemon
- * so as to use the same networking framework that the Internet Software
- * Consortium DHCP server uses. Much system-specific configuration code
- * was moved into a shell script so that as support for more operating
- * systems is added, it will not be necessary to port and maintain
- * system-specific configuration code to these operating systems - instead,
- * the shell script can invoke the native tools to accomplish the same
- * purpose.
+ * This code is based on the original client state machine that was
+ * written by Elliot Poger. The code has been extensively hacked on
+ * by Ted Lemon since then, so any mistakes you find are probably his
+ * fault and not Elliot's.
*/
#ifndef lint
static char ocopyright[] =
-"$Id: dhclient.c,v 1.44.2.47 2000/09/06 20:59:09 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
+"$Id: dhclient.c,v 1.129.2.7 2001/08/08 14:46:14 mellon Exp $ Copyright (c) 1995-2001 Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -65,39 +50,44 @@ static char ocopyright[] =
TIME cur_time;
TIME default_lease_time = 43200; /* 12 hours... */
TIME max_lease_time = 86400; /* 24 hours... */
-struct tree_cache *global_options [256];
-char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
-char *path_dhclient_db = _PATH_DHCLIENT_DB;
-char *path_dhclient_pid = _PATH_DHCLIENT_PID;
+const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
+const char *path_dhclient_db = _PATH_DHCLIENT_DB;
+const char *path_dhclient_pid = _PATH_DHCLIENT_PID;
+static char path_dhclient_script_array [] = _PATH_DHCLIENT_SCRIPT;
+char *path_dhclient_script = path_dhclient_script_array;
-int interfaces_requested = 0;
+int dhcp_max_agent_option_packet_length = 0;
-int log_perror = 1;
+int interfaces_requested = 0;
struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
struct iaddr iaddr_any = { 4, { 0, 0, 0, 0 } };
struct in_addr inaddr_any;
struct sockaddr_in sockaddr_broadcast;
+struct in_addr giaddr;
/* ASSERT_STATE() does nothing now; it used to be
assert (state_is == state_shouldbe). */
#define ASSERT_STATE(state_is, state_shouldbe) {}
+static char copyright[] = "Copyright 1995-2001 Internet Software Consortium.";
+static char arr [] = "All rights reserved.";
+static char message [] = "Internet Software Consortium DHCP Client";
+static char url [] = "For info, please visit http://www.isc.org/products/DHCP";
+
u_int16_t local_port;
u_int16_t remote_port;
-int log_priority;
int no_daemon;
-int save_scripts;
+struct string_list *client_env;
+int client_env_count;
+int onetry;
+int quiet;
+int nowait;
-static char copyright[] =
-"Copyright 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.";
-static char arr [] = "All rights reserved.";
-static char message [] = "Internet Software Consortium DHCP Client";
-static char contrib [] = "Please contribute if you find this software useful.";
-static char url [] = "For info, please visit http://www.isc.org/dhcp-contrib.html";
+static void usage PROTO ((void));
-static void usage PROTO ((char *));
+void do_release(struct client_state *);
int main (argc, argv, envp)
int argc;
@@ -106,105 +96,242 @@ int main (argc, argv, envp)
int i;
struct servent *ent;
struct interface_info *ip;
- int seed;
- int quiet = 0;
+ struct client_state *client;
+ unsigned seed;
+ char *server = (char *)0;
+ char *relay = (char *)0;
+ isc_result_t status;
+ int release_mode = 0;
+ omapi_object_t *listener;
+ isc_result_t result;
+ int persist = 0;
+ int omapi_port;
+ int no_dhclient_conf = 0;
+ int no_dhclient_db = 0;
+ int no_dhclient_pid = 0;
+ int no_dhclient_script = 0;
char *s;
- s = strrchr (argv [0], '/');
- if (!s)
- s = argv [0];
- else
- s++;
+ /* Make sure we have stdin, stdout and stderr. */
+ i = open ("/dev/null", O_RDWR);
+ if (i == 0)
+ i = open ("/dev/null", O_RDWR);
+ if (i == 1) {
+ i = open ("/dev/null", O_RDWR);
+ log_perror = 0; /* No sense logging to /dev/null. */
+ } else if (i != -1)
+ close (i);
- /* Initially, log errors to stderr as well as to syslogd. */
#ifdef SYSLOG_4_2
- openlog (s, LOG_NDELAY);
- log_priority = DHCPD_LOG_FACILITY;
+ openlog ("dhclient", LOG_NDELAY);
+ log_priority = LOG_DAEMON;
#else
- openlog (s, LOG_NDELAY, DHCPD_LOG_FACILITY);
+ openlog ("dhclient", LOG_NDELAY, LOG_DAEMON);
#endif
#if !(defined (DEBUG) || defined (SYSLOG_4_2) || defined (__CYGWIN32__))
setlogmask (LOG_UPTO (LOG_INFO));
#endif
+ /* Set up the OMAPI. */
+ status = omapi_init ();
+ if (status != ISC_R_SUCCESS)
+ log_fatal ("Can't initialize OMAPI: %s",
+ isc_result_totext (status));
+
+ /* Set up the OMAPI wrappers for various server database internal
+ objects. */
+ dhcp_common_objects_setup ();
+
+ dhcp_interface_discovery_hook = dhclient_interface_discovery_hook;
+ dhcp_interface_shutdown_hook = dhclient_interface_shutdown_hook;
+ dhcp_interface_startup_hook = dhclient_interface_startup_hook;
+
for (i = 1; i < argc; i++) {
- if (!strcmp (argv [i], "-p")) {
+ if (!strcmp (argv [i], "-r")) {
+ release_mode = 1;
+ no_daemon = 1;
+ } else if (!strcmp (argv [i], "-p")) {
if (++i == argc)
- usage (s);
+ usage ();
local_port = htons (atoi (argv [i]));
- debug ("binding to user-specified port %d",
+ log_debug ("binding to user-specified port %d",
ntohs (local_port));
} else if (!strcmp (argv [i], "-d")) {
no_daemon = 1;
- } else if (!strcmp (argv [i], "-D")) {
- save_scripts = 1;
- } else if (!strcmp (argv [i], "-cf")) {
+ } else if (!strcmp (argv [i], "-pf")) {
+ if (++i == argc)
+ usage ();
+ path_dhclient_pid = argv [i];
+ no_dhclient_pid = 1;
+ } else if (!strcmp (argv [i], "-cf")) {
+ if (++i == argc)
+ usage ();
+ path_dhclient_conf = argv [i];
+ no_dhclient_conf = 1;
+ } else if (!strcmp (argv [i], "-lf")) {
+ if (++i == argc)
+ usage ();
+ path_dhclient_db = argv [i];
+ no_dhclient_db = 1;
+ } else if (!strcmp (argv [i], "-sf")) {
if (++i == argc)
- usage (s);
- path_dhclient_conf = argv [i];
- } else if (!strcmp (argv [i], "-pf")) {
- if (++i == argc)
- usage (s);
- path_dhclient_pid = argv [i];
- } else if (!strcmp (argv [i], "-lf")) {
- if (++i == argc)
- usage (s);
- path_dhclient_db = argv [i];
+ usage ();
+ path_dhclient_script = argv [i];
+ no_dhclient_script = 1;
+ } else if (!strcmp (argv [i], "-1")) {
+ onetry = 1;
} else if (!strcmp (argv [i], "-q")) {
quiet = 1;
quiet_interface_discovery = 1;
+ } else if (!strcmp (argv [i], "-s")) {
+ if (++i == argc)
+ usage ();
+ server = argv [i];
+ } else if (!strcmp (argv [i], "-g")) {
+ if (++i == argc)
+ usage ();
+ relay = argv [i];
+ } else if (!strcmp (argv [i], "-n")) {
+ /* do not start up any interfaces */
+ interfaces_requested = 1;
+ } else if (!strcmp (argv [i], "-w")) {
+ /* do not exit if there are no broadcast interfaces. */
+ persist = 1;
} else if (argv [i][0] == '-') {
- usage (s);
+ usage ();
+ } else if (!strcmp (argv [i], "-e")) {
+ struct string_list *tmp;
+ if (++i == argc)
+ usage ();
+ tmp = dmalloc (strlen (argv [i]) + sizeof *tmp, MDL);
+ if (!tmp)
+ log_fatal ("No memory for %s", argv [i]);
+ strcpy (tmp -> string, argv [i]);
+ tmp -> next = client_env;
+ client_env = tmp;
+ client_env_count++;
+ } else if (!strcmp (argv [i], "--version")) {
+ log_info ("isc-dhclient-%s", DHCP_VERSION);
+ exit (0);
+ } else if (!strcmp (argv [i], "-nw")) {
+ nowait = 1;
} else {
- struct interface_info *tmp =
- ((struct interface_info *)
- dmalloc (sizeof *tmp, "specified_interface"));
- if (!tmp)
- error ("Insufficient memory to %s %s",
- "record interface", argv [i]);
- memset (tmp, 0, sizeof *tmp);
+ struct interface_info *tmp = (struct interface_info *)0;
+ status = interface_allocate (&tmp, MDL);
+ if (status != ISC_R_SUCCESS)
+ log_fatal ("Can't record interface %s:%s",
+ argv [i], isc_result_totext (status));
+ if (strlen (argv [i]) > sizeof tmp -> name)
+ log_fatal ("%s: interface name too long (max %ld)",
+ argv [i], (long)strlen (argv [i]));
strcpy (tmp -> name, argv [i]);
- tmp -> next = interfaces;
+ if (interfaces) {
+ interface_reference (&tmp -> next,
+ interfaces, MDL);
+ interface_dereference (&interfaces, MDL);
+ }
+ interface_reference (&interfaces, tmp, MDL);
tmp -> flags = INTERFACE_REQUESTED;
interfaces_requested = 1;
- interfaces = tmp;
}
}
+ if (!no_dhclient_conf && (s = getenv ("PATH_DHCLIENT_CONF"))) {
+ path_dhclient_conf = s;
+ }
+ if (!no_dhclient_db && (s = getenv ("PATH_DHCLIENT_DB"))) {
+ path_dhclient_db = s;
+ }
+ if (!no_dhclient_pid && (s = getenv ("PATH_DHCLIENT_PID"))) {
+ path_dhclient_pid = s;
+ }
+ if (!no_dhclient_script && (s = getenv ("PATH_DHCLIENT_SCRIPT"))) {
+ path_dhclient_script = s;
+ }
+
+ /* first kill of any currently running client */
+ if (release_mode) {
+ /* XXX inelegant hack to prove concept */
+ char command[1024];
+
+#if !defined (NO_SNPRINTF)
+ snprintf (command, 1024, "kill `cat %s`", path_dhclient_pid);
+#else
+ sprintf (command, "kill `cat %s`", path_dhclient_pid);
+#endif
+ system (command);
+ }
+
if (!quiet) {
- note ("%s %s", message, DHCP_VERSION);
- note (copyright);
- note (arr);
- note ("");
- note (contrib);
- note (url);
- note ("");
+ log_info ("%s %s", message, DHCP_VERSION);
+ log_info (copyright);
+ log_info (arr);
+ log_info (url);
+ log_info ("%s", "");
} else
log_perror = 0;
+ /* If we're given a relay agent address to insert, for testing
+ purposes, figure out what it is. */
+ if (relay) {
+ if (!inet_aton (relay, &giaddr)) {
+ struct hostent *he;
+ he = gethostbyname (relay);
+ if (he) {
+ memcpy (&giaddr, he -> h_addr_list [0],
+ sizeof giaddr);
+ } else {
+ log_fatal ("%s: no such host", relay);
+ }
+ }
+ }
+
/* Default to the DHCP/BOOTP port. */
if (!local_port) {
- ent = getservbyname ("dhcpc", "udp");
- if (!ent)
- local_port = htons (68);
- else
- local_port = ent -> s_port;
+ if (relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) {
+ local_port = htons (67);
+ } else {
+ ent = getservbyname ("dhcpc", "udp");
+ if (!ent)
+ local_port = htons (68);
+ else
+ local_port = ent -> s_port;
#ifndef __CYGWIN32__
- endservent ();
+ endservent ();
#endif
+ }
}
- remote_port = htons (ntohs (local_port) - 1); /* XXX */
+
+ /* If we're faking a relay agent, and we're not using loopback,
+ use the server port, not the client port. */
+ if (relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) {
+ local_port = htons (ntohs (local_port) - 1);
+ remote_port = local_port;
+ } else
+ remote_port = htons (ntohs (local_port) - 1); /* XXX */
/* Get the current time... */
GET_TIME (&cur_time);
sockaddr_broadcast.sin_family = AF_INET;
sockaddr_broadcast.sin_port = remote_port;
- sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
-#ifdef HAVE_SA_LEN
- sockaddr_broadcast.sin_len = sizeof sockaddr_broadcast;
-#endif
+ if (server) {
+ if (!inet_aton (server, &sockaddr_broadcast.sin_addr)) {
+ struct hostent *he;
+ he = gethostbyname (server);
+ if (he) {
+ memcpy (&sockaddr_broadcast.sin_addr,
+ he -> h_addr_list [0],
+ sizeof sockaddr_broadcast.sin_addr);
+ } else
+ sockaddr_broadcast.sin_addr.s_addr =
+ INADDR_BROADCAST;
+ }
+ } else {
+ sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
+ }
+
inaddr_any.s_addr = INADDR_ANY;
/* Discover all the network interfaces. */
@@ -219,17 +346,26 @@ int main (argc, argv, envp)
/* Rewrite the lease database... */
rewrite_client_leases ();
+ /* XXX */
+/* config_counter(&snd_counter, &rcv_counter); */
+
/* If no broadcast interfaces were discovered, call the script
and tell it so. */
if (!interfaces) {
- script_init ((struct interface_info *)0, "NBI",
+ /* Call dhclient-script with the NBI flag, in case somebody
+ cares. */
+ script_init ((struct client_state *)0, "NBI",
(struct string_list *)0);
- script_go ((struct interface_info *)0);
-
- note ("No broadcast interfaces found - exiting.");
- /* Nothing more to do. */
- exit (0);
- } else {
+ script_go ((struct client_state *)0);
+
+ /* If we haven't been asked to persist, waiting for new
+ interfaces, then just exit. */
+ if (!persist) {
+ /* Nothing more to do. */
+ log_info ("No broadcast interfaces found - exiting.");
+ exit (0);
+ }
+ } else if (!release_mode) {
/* Call the script with the list of interfaces. */
for (ip = interfaces; ip; ip = ip -> next) {
/* If interfaces were specified, don't configure
@@ -239,11 +375,12 @@ int main (argc, argv, envp)
INTERFACE_AUTOMATIC)) !=
INTERFACE_REQUESTED))
continue;
- script_init (ip, "PREINIT", (struct string_list *)0);
+ script_init (ip -> client,
+ "PREINIT", (struct string_list *)0);
if (ip -> client -> alias)
- script_write_params (ip, "alias_",
+ script_write_params (ip -> client, "alias_",
ip -> client -> alias);
- script_go (ip);
+ script_go (ip -> client);
}
}
@@ -260,25 +397,71 @@ int main (argc, argv, envp)
interface's hardware address interpreted as an integer.
Not much entropy, but we're booting, so we're not likely to
find anything better. */
- seed = 0; /* Unfortunately, what's on the stack isn't random. :') */
+ seed = 0;
for (ip = interfaces; ip; ip = ip -> next) {
int junk;
memcpy (&junk,
- &ip -> hw_address.haddr [ip -> hw_address.hlen -
- sizeof seed], sizeof seed);
+ &ip -> hw_address.hbuf [ip -> hw_address.hlen -
+ sizeof seed], sizeof seed);
seed += junk;
}
srandom (seed + cur_time);
/* Start a configuration state machine for each interface. */
for (ip = interfaces; ip; ip = ip -> next) {
- ip -> client -> state = S_INIT;
- state_reboot (ip);
+ ip -> flags |= INTERFACE_RUNNING;
+ for (client = ip -> client; client; client = client -> next) {
+ if (release_mode)
+ do_release (client);
+ else {
+ client -> state = S_INIT;
+ /* Set up a timeout to start the initialization
+ process. */
+ add_timeout (cur_time + random () % 5,
+ state_reboot, client, 0, 0);
+ }
+ }
+ }
+
+ if (release_mode)
+ return 0;
+
+ /* Start up a listener for the object management API protocol. */
+ if (top_level_config.omapi_port != -1) {
+ listener = (omapi_object_t *)0;
+ result = omapi_generic_new (&listener, MDL);
+ if (result != ISC_R_SUCCESS)
+ log_fatal ("Can't allocate new generic object: %s\n",
+ isc_result_totext (result));
+ result = omapi_protocol_listen (listener,
+ (unsigned)
+ top_level_config.omapi_port,
+ 1);
+ if (result != ISC_R_SUCCESS)
+ log_fatal ("Can't start OMAPI protocol: %s",
+ isc_result_totext (result));
}
/* Set up the bootp packet handler... */
bootp_packet_handler = do_packet;
+#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
+ defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
+ dmalloc_cutoff_generation = dmalloc_generation;
+ dmalloc_longterm = dmalloc_outstanding;
+ dmalloc_outstanding = 0;
+#endif
+
+ /* If we're not supposed to wait before getting the address,
+ don't. */
+ if (nowait)
+ go_daemon ();
+
+ /* If we're not going to daemonize, write the pid file
+ now. */
+ if (no_daemon || nowait)
+ write_client_pid_file ();
+
/* Start dispatching packets and timeouts... */
dispatch ();
@@ -286,23 +469,51 @@ int main (argc, argv, envp)
return 0;
}
-static void usage (appname)
- char *appname;
+static void usage ()
+{
+ log_info ("%s %s", message, DHCP_VERSION);
+ log_info (copyright);
+ log_info (arr);
+ log_info (url);
+
+ log_error ("Usage: dhclient [-1dqr] [-nw] [-p <port>] %s",
+ "[-s server]");
+ log_error (" [-cf config-file] [-lf lease-file]%s",
+ "[-pf pid-file] [-e VAR=val]");
+ log_fatal (" [-sf script-file] [interface]");
+}
+
+isc_result_t find_class (struct class **c,
+ const char *s, const char *file, int line)
{
- note (message);
- note (copyright);
- note (arr);
- note ("");
- note (contrib);
- note (url);
- note ("");
-
- warn ("Usage: %s [-c] [-p <port>] [-lf lease-file]", appname);
- error (" [-pf pidfile] [interface]");
+ return 0;
}
-void cleanup ()
+int check_collection (packet, lease, collection)
+ struct packet *packet;
+ struct lease *lease;
+ struct collection *collection;
{
+ return 0;
+}
+
+void classify (packet, class)
+ struct packet *packet;
+ struct class *class;
+{
+}
+
+int unbill_class (lease, class)
+ struct lease *lease;
+ struct class *class;
+{
+ return 0;
+}
+
+int find_subnet (struct subnet **sp,
+ struct iaddr addr, const char *file, int line)
+{
+ return 0;
}
/* Individual States:
@@ -334,152 +545,141 @@ void cleanup ()
* can no longer legitimately use the lease.
*/
-void state_reboot (ipp)
- void *ipp;
+void state_reboot (cpp)
+ void *cpp;
{
- struct interface_info *ip = ipp;
+ struct client_state *client = cpp;
/* If we don't remember an active lease, go straight to INIT. */
- if (!ip -> client -> active ||
- ip -> client -> active -> is_bootp) {
- state_init (ip);
+ if (!client -> active ||
+ client -> active -> is_bootp ||
+ client -> active -> expiry <= cur_time) {
+ state_init (client);
return;
}
/* We are in the rebooting state. */
- ip -> client -> state = S_REBOOTING;
+ client -> state = S_REBOOTING;
/* make_request doesn't initialize xid because it normally comes
from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
so pick an xid now. */
- ip -> client -> xid = random ();
+ client -> xid = random ();
/* Make a DHCPREQUEST packet, and set appropriate per-interface
flags. */
- make_request (ip, ip -> client -> active);
- ip -> client -> destination = iaddr_broadcast;
- ip -> client -> first_sending = cur_time;
- ip -> client -> interval = ip -> client -> config -> initial_interval;
+ make_request (client, client -> active);
+ client -> destination = iaddr_broadcast;
+ client -> first_sending = cur_time;
+ client -> interval = client -> config -> initial_interval;
/* Zap the medium list... */
- ip -> client -> medium = (struct string_list *)0;
+ client -> medium = (struct string_list *)0;
/* Send out the first DHCPREQUEST packet. */
- send_request (ip);
+ send_request (client);
}
/* Called when a lease has completely expired and we've been unable to
renew it. */
-void state_init (ipp)
- void *ipp;
+void state_init (cpp)
+ void *cpp;
{
- struct interface_info *ip = ipp;
+ struct client_state *client = cpp;
ASSERT_STATE(state, S_INIT);
/* Make a DHCPDISCOVER packet, and set appropriate per-interface
flags. */
- make_discover (ip, ip -> client -> active);
- ip -> client -> xid = ip -> client -> packet.xid;
- ip -> client -> destination = iaddr_broadcast;
- ip -> client -> state = S_SELECTING;
- ip -> client -> first_sending = cur_time;
- ip -> client -> interval = ip -> client -> config -> initial_interval;
+ make_discover (client, client -> active);
+ client -> xid = client -> packet.xid;
+ client -> destination = iaddr_broadcast;
+ client -> state = S_SELECTING;
+ client -> first_sending = cur_time;
+ client -> interval = client -> config -> initial_interval;
/* Add an immediate timeout to cause the first DHCPDISCOVER packet
to go out. */
- send_discover (ip);
+ send_discover (client);
}
/* state_selecting is called when one or more DHCPOFFER packets have been
received and a configurable period of time has passed. */
-void state_selecting (ipp)
- void *ipp;
+void state_selecting (cpp)
+ void *cpp;
{
- struct interface_info *ip = ipp;
-
+ struct client_state *client = cpp;
struct client_lease *lp, *next, *picked;
+
ASSERT_STATE(state, S_SELECTING);
/* Cancel state_selecting and send_discover timeouts, since either
one could have got us here. */
- cancel_timeout (state_selecting, ip);
- cancel_timeout (send_discover, ip);
+ cancel_timeout (state_selecting, client);
+ cancel_timeout (send_discover, client);
/* We have received one or more DHCPOFFER packets. Currently,
the only criterion by which we judge leases is whether or
not we get a response when we arp for them. */
picked = (struct client_lease *)0;
- for (lp = ip -> client -> offered_leases; lp; lp = next) {
+ for (lp = client -> offered_leases; lp; lp = next) {
next = lp -> next;
/* Check to see if we got an ARPREPLY for the address
in this particular lease. */
if (!picked) {
- script_init (ip, "ARPCHECK", lp -> medium);
- script_write_params (ip, "check_", lp);
-
- /* If the ARPCHECK code detects another
- machine using the offered address, it exits
- nonzero. We need to send a DHCPDECLINE and
- toss the lease. */
- if (script_go (ip)) {
- make_decline (ip, lp);
- send_decline (ip);
- goto freeit;
- }
picked = lp;
picked -> next = (struct client_lease *)0;
} else {
freeit:
- free_client_lease (lp);
+ destroy_client_lease (lp);
}
}
- ip -> client -> offered_leases = (struct client_lease *)0;
+ client -> offered_leases = (struct client_lease *)0;
/* If we just tossed all the leases we were offered, go back
to square one. */
if (!picked) {
- ip -> client -> state = S_INIT;
- state_init (ip);
+ client -> state = S_INIT;
+ state_init (client);
return;
}
/* If it was a BOOTREPLY, we can just take the address right now. */
- if (!picked -> options [DHO_DHCP_MESSAGE_TYPE].len) {
- ip -> client -> new = picked;
+ if (picked -> is_bootp) {
+ client -> new = picked;
/* Make up some lease expiry times
XXX these should be configurable. */
- ip -> client -> new -> expiry = cur_time + 12000;
- ip -> client -> new -> renewal += cur_time + 8000;
- ip -> client -> new -> rebind += cur_time + 10000;
+ client -> new -> expiry = cur_time + 12000;
+ client -> new -> renewal += cur_time + 8000;
+ client -> new -> rebind += cur_time + 10000;
- ip -> client -> state = S_REQUESTING;
+ client -> state = S_REQUESTING;
/* Bind to the address we received. */
- bind_lease (ip);
+ bind_lease (client);
return;
}
/* Go to the REQUESTING state. */
- ip -> client -> destination = iaddr_broadcast;
- ip -> client -> state = S_REQUESTING;
- ip -> client -> first_sending = cur_time;
- ip -> client -> interval = ip -> client -> config -> initial_interval;
+ client -> destination = iaddr_broadcast;
+ client -> state = S_REQUESTING;
+ client -> first_sending = cur_time;
+ client -> interval = client -> config -> initial_interval;
/* Make a DHCPREQUEST packet from the lease we picked. */
- make_request (ip, picked);
- ip -> client -> xid = ip -> client -> packet.xid;
+ make_request (client, picked);
+ client -> xid = client -> packet.xid;
/* Toss the lease we picked - we'll get it back in a DHCPACK. */
- free_client_lease (picked);
+ destroy_client_lease (picked);
/* Add an immediate timeout to send the first DHCPREQUEST packet. */
- send_request (ip);
+ send_request (client);
}
/* state_requesting is called when we receive a DHCPACK message after
@@ -489,128 +689,200 @@ void dhcpack (packet)
struct packet *packet;
{
struct interface_info *ip = packet -> interface;
+ struct client_state *client;
struct client_lease *lease;
+ struct option_cache *oc;
+ struct data_string ds;
+ int i;
/* If we're not receptive to an offer right now, or if the offer
has an unrecognizable transaction id, then just drop it. */
- if (packet -> interface -> client -> xid != packet -> raw -> xid ||
- (packet -> interface -> hw_address.hlen !=
+ for (client = ip -> client; client; client = client -> next) {
+ if (client -> xid == packet -> raw -> xid)
+ break;
+ }
+ if (!client ||
+ (packet -> interface -> hw_address.hlen - 1 !=
packet -> raw -> hlen) ||
- (memcmp (packet -> interface -> hw_address.haddr,
+ (memcmp (&packet -> interface -> hw_address.hbuf [1],
packet -> raw -> chaddr, packet -> raw -> hlen))) {
#if defined (DEBUG)
- debug ("DHCPACK in wrong transaction.");
+ log_debug ("DHCPACK in wrong transaction.");
#endif
return;
}
- if (ip -> client -> state != S_REBOOTING &&
- ip -> client -> state != S_REQUESTING &&
- ip -> client -> state != S_RENEWING &&
- ip -> client -> state != S_REBINDING) {
+ if (client -> state != S_REBOOTING &&
+ client -> state != S_REQUESTING &&
+ client -> state != S_RENEWING &&
+ client -> state != S_REBINDING) {
#if defined (DEBUG)
- debug ("DHCPACK in wrong state.");
+ log_debug ("DHCPACK in wrong state.");
#endif
return;
}
- note ("DHCPACK from %s", piaddr (packet -> client_addr));
+ log_info ("DHCPACK from %s", piaddr (packet -> client_addr));
- lease = packet_to_lease (packet);
+ lease = packet_to_lease (packet, client);
if (!lease) {
- note ("packet_to_lease failed.");
+ log_info ("packet_to_lease failed.");
return;
}
- ip -> client -> new = lease;
+ client -> new = lease;
/* Stop resending DHCPREQUEST. */
- cancel_timeout (send_request, ip);
+ cancel_timeout (send_request, client);
/* Figure out the lease time. */
- ip -> client -> new -> expiry =
- getULong (ip -> client ->
- new -> options [DHO_DHCP_LEASE_TIME].data);
+ oc = lookup_option (&dhcp_universe, client -> new -> options,
+ DHO_DHCP_LEASE_TIME);
+ memset (&ds, 0, sizeof ds);
+ if (oc &&
+ evaluate_option_cache (&ds, packet, (struct lease *)0, client,
+ packet -> options, client -> new -> options,
+ &global_scope, oc, MDL)) {
+ if (ds.len > 3)
+ client -> new -> expiry = getULong (ds.data);
+ else
+ client -> new -> expiry = 0;
+ data_string_forget (&ds, MDL);
+ } else
+ client -> new -> expiry = 0;
+
+ if (!client -> new -> expiry) {
+ log_error ("no expiry time on offered lease.");
+ /* XXX this is going to be bad - if this _does_
+ XXX happen, we should probably dynamically
+ XXX disqualify the DHCP server that gave us the
+ XXX bad packet from future selections and
+ XXX then go back into the init state. */
+ state_init (client);
+ return;
+ }
+
/* A number that looks negative here is really just very large,
because the lease expiry offset is unsigned. */
- if (ip -> client -> new -> expiry < 0)
- ip -> client -> new -> expiry = TIME_MAX;
-
- /* Take the server-provided renewal time if there is one;
- otherwise figure it out according to the spec. */
- if (ip -> client -> new -> options [DHO_DHCP_RENEWAL_TIME].len)
- ip -> client -> new -> renewal =
- getULong (ip -> client ->
- new -> options [DHO_DHCP_RENEWAL_TIME].data);
- else
- ip -> client -> new -> renewal =
- ip -> client -> new -> expiry / 2;
+ if (client -> new -> expiry < 0)
+ client -> new -> expiry = TIME_MAX;
+ /* Take the server-provided renewal time if there is one. */
+ oc = lookup_option (&dhcp_universe, client -> new -> options,
+ DHO_DHCP_RENEWAL_TIME);
+ if (oc &&
+ evaluate_option_cache (&ds, packet, (struct lease *)0, client,
+ packet -> options, client -> new -> options,
+ &global_scope, oc, MDL)) {
+ if (ds.len > 3)
+ client -> new -> renewal = getULong (ds.data);
+ else
+ client -> new -> renewal = 0;
+ data_string_forget (&ds, MDL);
+ } else
+ client -> new -> renewal = 0;
+
+ /* If it wasn't specified by the server, calculate it. */
+ if (!client -> new -> renewal)
+ client -> new -> renewal =
+ client -> new -> expiry / 2;
+
+ /* Now introduce some randomness to the renewal time: */
+ client -> new -> renewal = (((client -> new -> renewal + 3) * 3 / 4) +
+ (random () % /* XXX NUMS */
+ ((client -> new -> renewal + 3) / 4)));
/* Same deal with the rebind time. */
- if (ip -> client -> new -> options [DHO_DHCP_REBINDING_TIME].len)
- ip -> client -> new -> rebind =
- getULong (ip -> client -> new ->
- options [DHO_DHCP_REBINDING_TIME].data);
- else
- ip -> client -> new -> rebind =
- ip -> client -> new -> renewal +
- ip -> client -> new -> renewal / 2 +
- ip -> client -> new -> renewal / 4;
+ oc = lookup_option (&dhcp_universe, client -> new -> options,
+ DHO_DHCP_REBINDING_TIME);
+ if (oc &&
+ evaluate_option_cache (&ds, packet, (struct lease *)0, client,
+ packet -> options, client -> new -> options,
+ &global_scope, oc, MDL)) {
+ if (ds.len > 3)
+ client -> new -> rebind = getULong (ds.data);
+ else
+ client -> new -> rebind = 0;
+ data_string_forget (&ds, MDL);
+ } else
+ client -> new -> rebind = 0;
+
+ if (!client -> new -> rebind)
+ client -> new -> rebind =
+ (client -> new -> expiry * 7) / 8; /* XXX NUMS */
+
+ /* Make sure our randomness didn't run the renewal time past the
+ rebind time. */
+ if (client -> new -> renewal > client -> new -> rebind)
+ client -> new -> renewal = (client -> new -> rebind * 3) / 4;
- ip -> client -> new -> expiry += cur_time;
+ client -> new -> expiry += cur_time;
/* Lease lengths can never be negative. */
- if (ip -> client -> new -> expiry < cur_time)
- ip -> client -> new -> expiry = TIME_MAX;
- ip -> client -> new -> renewal += cur_time;
- if (ip -> client -> new -> renewal < cur_time)
- ip -> client -> new -> renewal = TIME_MAX;
- ip -> client -> new -> rebind += cur_time;
- if (ip -> client -> new -> rebind < cur_time)
- ip -> client -> new -> rebind = TIME_MAX;
-
- bind_lease (ip);
+ if (client -> new -> expiry < cur_time)
+ client -> new -> expiry = TIME_MAX;
+ client -> new -> renewal += cur_time;
+ if (client -> new -> renewal < cur_time)
+ client -> new -> renewal = TIME_MAX;
+ client -> new -> rebind += cur_time;
+ if (client -> new -> rebind < cur_time)
+ client -> new -> rebind = TIME_MAX;
+
+ bind_lease (client);
}
-void bind_lease (ip)
- struct interface_info *ip;
+void bind_lease (client)
+ struct client_state *client;
{
- /* Remember the medium. */
- ip -> client -> new -> medium = ip -> client -> medium;
+ struct interface_info *ip = client -> interface;
- /* Write out the new lease. */
- write_client_lease (ip, ip -> client -> new, 0);
+ /* Remember the medium. */
+ client -> new -> medium = client -> medium;
/* Run the client script with the new parameters. */
- script_init (ip, (ip -> client -> state == S_REQUESTING
+ script_init (client, (client -> state == S_REQUESTING
? "BOUND"
- : (ip -> client -> state == S_RENEWING
+ : (client -> state == S_RENEWING
? "RENEW"
- : (ip -> client -> state == S_REBOOTING
+ : (client -> state == S_REBOOTING
? "REBOOT" : "REBIND"))),
- ip -> client -> new -> medium);
- if (ip -> client -> active && ip -> client -> state != S_REBOOTING)
- script_write_params (ip, "old_", ip -> client -> active);
- script_write_params (ip, "new_", ip -> client -> new);
- if (ip -> client -> alias)
- script_write_params (ip, "alias_", ip -> client -> alias);
- script_go (ip);
+ client -> new -> medium);
+ if (client -> active && client -> state != S_REBOOTING)
+ script_write_params (client, "old_", client -> active);
+ script_write_params (client, "new_", client -> new);
+ if (client -> alias)
+ script_write_params (client, "alias_", client -> alias);
+
+ /* If the BOUND/RENEW code detects another machine using the
+ offered address, it exits nonzero. We need to send a
+ DHCPDECLINE and toss the lease. */
+ if (script_go (client)) {
+ make_decline (client, client -> new);
+ send_decline (client);
+ destroy_client_lease (client -> new);
+ client -> new = (struct client_lease *)0;
+ state_init (client);
+ return;
+ }
+
+ /* Write out the new lease. */
+ write_client_lease (client, client -> new, 0, 0);
/* Replace the old active lease with the new one. */
- if (ip -> client -> active)
- free_client_lease (ip -> client -> active);
- ip -> client -> active = ip -> client -> new;
- ip -> client -> new = (struct client_lease *)0;
+ if (client -> active)
+ destroy_client_lease (client -> active);
+ client -> active = client -> new;
+ client -> new = (struct client_lease *)0;
/* Set up a timeout to start the renewal process. */
- add_timeout (ip -> client -> active -> renewal,
- state_bound, ip);
+ add_timeout (client -> active -> renewal,
+ state_bound, client, 0, 0);
- note ("bound to %s -- renewal in %d seconds.",
- piaddr (ip -> client -> active -> address),
- ip -> client -> active -> renewal - cur_time);
- ip -> client -> state = S_BOUND;
+ log_info ("bound to %s -- renewal in %ld seconds.",
+ piaddr (client -> active -> address),
+ (long)(client -> active -> renewal - cur_time));
+ client -> state = S_BOUND;
reinitialize_interfaces ();
go_daemon ();
+ client_dns_update (client, 1);
}
/* state_bound is called when we've successfully bound to a particular
@@ -618,32 +890,68 @@ void bind_lease (ip)
expected to unicast a DHCPREQUEST to the server that gave us our
original lease. */
-void state_bound (ipp)
- void *ipp;
+void state_bound (cpp)
+ void *cpp;
{
- struct interface_info *ip = ipp;
+ struct client_state *client = cpp;
+ int i;
+ struct option_cache *oc;
+ struct data_string ds;
ASSERT_STATE(state, S_BOUND);
/* T1 has expired. */
- make_request (ip, ip -> client -> active);
- ip -> client -> xid = ip -> client -> packet.xid;
-
- if (ip -> client -> active ->
- options [DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
- memcpy (ip -> client -> destination.iabuf,
- ip -> client -> active ->
- options [DHO_DHCP_SERVER_IDENTIFIER].data, 4);
- ip -> client -> destination.len = 4;
+ make_request (client, client -> active);
+ client -> xid = client -> packet.xid;
+
+ memset (&ds, 0, sizeof ds);
+ oc = lookup_option (&dhcp_universe, client -> active -> options,
+ DHO_DHCP_SERVER_IDENTIFIER);
+ if (oc &&
+ evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0,
+ client, (struct option_state *)0,
+ client -> active -> options,
+ &global_scope, oc, MDL)) {
+ if (ds.len > 3) {
+ memcpy (client -> destination.iabuf, ds.data, 4);
+ client -> destination.len = 4;
+ } else
+ client -> destination = iaddr_broadcast;
} else
- ip -> client -> destination = iaddr_broadcast;
+ client -> destination = iaddr_broadcast;
- ip -> client -> first_sending = cur_time;
- ip -> client -> interval = ip -> client -> config -> initial_interval;
- ip -> client -> state = S_RENEWING;
+ client -> first_sending = cur_time;
+ client -> interval = client -> config -> initial_interval;
+ client -> state = S_RENEWING;
/* Send the first packet immediately. */
- send_request (ip);
+ send_request (client);
+}
+
+/* state_stop is called when we've been told to shut down. We unconfigure
+ the interfaces, and then stop operating until told otherwise. */
+
+void state_stop (cpp)
+ void *cpp;
+{
+ struct client_state *client = cpp;
+ int i;
+
+ /* Cancel all timeouts. */
+ cancel_timeout (state_selecting, client);
+ cancel_timeout (send_discover, client);
+ cancel_timeout (send_request, client);
+ cancel_timeout (state_bound, client);
+
+ /* If we have an address, unconfigure it. */
+ if (client -> active) {
+ script_init (client, "STOP", client -> active -> medium);
+ script_write_params (client, "old_", client -> active);
+ if (client -> alias)
+ script_write_params (client, "alias_",
+ client -> alias);
+ script_go (client);
+ }
}
int commit_leases ()
@@ -657,7 +965,14 @@ int write_lease (lease)
return 0;
}
-void db_startup ()
+int write_host (host)
+ struct host_decl *host;
+{
+ return 0;
+}
+
+void db_startup (testp)
+ int testp;
{
}
@@ -674,7 +989,7 @@ void bootp (packet)
for (ap = packet -> interface -> client -> config -> reject_list;
ap; ap = ap -> next) {
if (addr_eq (packet -> client_addr, ap -> addr)) {
- note ("BOOTREPLY from %s rejected.",
+ log_info ("BOOTREPLY from %s rejected.",
piaddr (ap -> addr));
return;
}
@@ -689,7 +1004,7 @@ void dhcp (packet)
{
struct iaddrlist *ap;
void (*handler) PROTO ((struct packet *));
- char *type;
+ const char *type;
switch (packet -> packet_type) {
case DHCPOFFER:
@@ -716,7 +1031,7 @@ void dhcp (packet)
for (ap = packet -> interface -> client -> config -> reject_list;
ap; ap = ap -> next) {
if (addr_eq (packet -> client_addr, ap -> addr)) {
- note ("%s from %s rejected.",
+ log_info ("%s from %s rejected.",
type, piaddr (ap -> addr));
return;
}
@@ -728,186 +1043,196 @@ void dhcpoffer (packet)
struct packet *packet;
{
struct interface_info *ip = packet -> interface;
+ struct client_state *client;
struct client_lease *lease, *lp;
int i;
- int arp_timeout_needed, stop_selecting;
- char *name = (packet -> options [DHO_DHCP_MESSAGE_TYPE].len
- ? "DHCPOFFER" : "BOOTREPLY");
+ int stop_selecting;
+ const char *name = packet -> packet_type ? "DHCPOFFER" : "BOOTREPLY";
+ struct iaddrlist *ap;
+ struct option_cache *oc;
+ char obuf [1024];
#ifdef DEBUG_PACKET
dump_packet (packet);
#endif
+ /* Find a client state that matches the xid... */
+ for (client = ip -> client; client; client = client -> next)
+ if (client -> xid == packet -> raw -> xid)
+ break;
+
/* If we're not receptive to an offer right now, or if the offer
has an unrecognizable transaction id, then just drop it. */
- if (ip -> client -> state != S_SELECTING ||
- packet -> interface -> client -> xid != packet -> raw -> xid ||
- (packet -> interface -> hw_address.hlen !=
+ if (!client ||
+ client -> state != S_SELECTING ||
+ (packet -> interface -> hw_address.hlen - 1 !=
packet -> raw -> hlen) ||
- (memcmp (packet -> interface -> hw_address.haddr,
+ (memcmp (&packet -> interface -> hw_address.hbuf [1],
packet -> raw -> chaddr, packet -> raw -> hlen))) {
#if defined (DEBUG)
- debug ("%s in wrong transaction.", name);
+ log_debug ("%s in wrong transaction.", name);
#endif
return;
}
- note ("%s from %s", name, piaddr (packet -> client_addr));
+ sprintf (obuf, "%s from %s", name, piaddr (packet -> client_addr));
/* If this lease doesn't supply the minimum required parameters,
blow it off. */
- for (i = 0; ip -> client -> config -> required_options [i]; i++) {
- if (!packet -> options [ip -> client -> config ->
- required_options [i]].len) {
- note ("%s isn't satisfactory.", name);
- return;
+ if (client -> config -> required_options) {
+ for (i = 0; client -> config -> required_options [i]; i++) {
+ if (!lookup_option
+ (&dhcp_universe, packet -> options,
+ client -> config -> required_options [i])) {
+ log_info ("%s: no %s option.",
+ obuf, (dhcp_universe.options
+ [client -> config -> required_options [i]]
+ -> name));
+ return;
+ }
}
}
/* If we've already seen this lease, don't record it again. */
- for (lease = ip -> client -> offered_leases;
- lease; lease = lease -> next) {
+ for (lease = client -> offered_leases; lease; lease = lease -> next) {
if (lease -> address.len == sizeof packet -> raw -> yiaddr &&
!memcmp (lease -> address.iabuf,
&packet -> raw -> yiaddr, lease -> address.len)) {
- debug ("%s already seen.", name);
+ log_debug ("%s: already seen.", obuf);
return;
}
}
- lease = packet_to_lease (packet);
+ lease = packet_to_lease (packet, client);
if (!lease) {
- note ("packet_to_lease failed.");
+ log_info ("%s: packet_to_lease failed.", obuf);
return;
}
/* If this lease was acquired through a BOOTREPLY, record that
fact. */
- if (!packet -> options [DHO_DHCP_MESSAGE_TYPE].len)
+ if (!packet -> options_valid || !packet -> packet_type)
lease -> is_bootp = 1;
/* Record the medium under which this lease was offered. */
- lease -> medium = ip -> client -> medium;
-
- /* Send out an ARP Request for the offered IP address. */
- script_init (ip, "ARPSEND", lease -> medium);
- script_write_params (ip, "check_", lease);
- /* If the script can't send an ARP request without waiting,
- we'll be waiting when we do the ARPCHECK, so don't wait now. */
- if (script_go (ip))
- arp_timeout_needed = 0;
- else
- arp_timeout_needed = 2;
+ lease -> medium = client -> medium;
/* Figure out when we're supposed to stop selecting. */
- stop_selecting = (ip -> client -> first_sending +
- ip -> client -> config -> select_interval);
+ stop_selecting = (client -> first_sending +
+ client -> config -> select_interval);
/* If this is the lease we asked for, put it at the head of the
list, and don't mess with the arp request timeout. */
- if (lease -> address.len == ip -> client -> requested_address.len &&
+ if (lease -> address.len == client -> requested_address.len &&
!memcmp (lease -> address.iabuf,
- ip -> client -> requested_address.iabuf,
- ip -> client -> requested_address.len)) {
- lease -> next = ip -> client -> offered_leases;
- ip -> client -> offered_leases = lease;
+ client -> requested_address.iabuf,
+ client -> requested_address.len)) {
+ lease -> next = client -> offered_leases;
+ client -> offered_leases = lease;
} else {
- /* If we already have an offer, and arping for this
- offer would take us past the selection timeout,
- then don't extend the timeout - just hope for the
- best. */
- if (ip -> client -> offered_leases &&
- (cur_time + arp_timeout_needed) > stop_selecting)
- arp_timeout_needed = 0;
-
/* Put the lease at the end of the list. */
lease -> next = (struct client_lease *)0;
- if (!ip -> client -> offered_leases)
- ip -> client -> offered_leases = lease;
+ if (!client -> offered_leases)
+ client -> offered_leases = lease;
else {
- for (lp = ip -> client -> offered_leases; lp -> next;
+ for (lp = client -> offered_leases; lp -> next;
lp = lp -> next)
;
lp -> next = lease;
}
}
- /* If we're supposed to stop selecting before we've had time
- to wait for the ARPREPLY, add some delay to wait for
- the ARPREPLY. */
- if (stop_selecting - cur_time < arp_timeout_needed)
- stop_selecting = cur_time + arp_timeout_needed;
-
/* If the selecting interval has expired, go immediately to
state_selecting(). Otherwise, time out into
state_selecting at the select interval. */
if (stop_selecting <= 0)
- state_selecting (ip);
+ state_selecting (client);
else {
- add_timeout (stop_selecting, state_selecting, ip);
- cancel_timeout (send_discover, ip);
+ add_timeout (stop_selecting, state_selecting, client, 0, 0);
+ cancel_timeout (send_discover, client);
}
+ log_info ("%s", obuf);
}
/* Allocate a client_lease structure and initialize it from the parameters
in the specified packet. */
-struct client_lease *packet_to_lease (packet)
+struct client_lease *packet_to_lease (packet, client)
struct packet *packet;
+ struct client_state *client;
{
struct client_lease *lease;
- int i;
+ unsigned i;
+ struct option_cache *oc;
+ struct data_string data;
- lease = (struct client_lease *)malloc (sizeof (struct client_lease));
+ lease = (struct client_lease *)new_client_lease (MDL);
if (!lease) {
- warn ("dhcpoffer: no memory to record lease.\n");
+ log_error ("packet_to_lease: no memory to record lease.\n");
return (struct client_lease *)0;
}
memset (lease, 0, sizeof *lease);
/* Copy the lease options. */
- for (i = 0; i < 256; i++) {
- if (packet -> options [i].len) {
- lease -> options [i].data =
- (unsigned char *)
- malloc (packet -> options [i].len + 1);
- if (!lease -> options [i].data) {
- warn ("dhcpoffer: no memory for option %d\n",
- i);
- free_client_lease (lease);
- return (struct client_lease *)0;
- } else {
- memcpy (lease -> options [i].data,
- packet -> options [i].data,
- packet -> options [i].len);
- lease -> options [i].len =
- packet -> options [i].len;
- lease -> options [i].data
- [lease -> options [i].len] = 0;
- }
- }
- }
+ option_state_reference (&lease -> options, packet -> options, MDL);
lease -> address.len = sizeof (packet -> raw -> yiaddr);
memcpy (lease -> address.iabuf, &packet -> raw -> yiaddr,
lease -> address.len);
+ if (client -> config -> vendor_space_name) {
+ i = DHO_VENDOR_ENCAPSULATED_OPTIONS;
+
+ /* See if there was a vendor encapsulation option. */
+ oc = lookup_option (&dhcp_universe, lease -> options, i);
+ memset (&data, 0, sizeof data);
+ if (oc &&
+ client -> config -> vendor_space_name &&
+ evaluate_option_cache (&data, packet,
+ (struct lease *)0, client,
+ packet -> options, lease -> options,
+ &global_scope, oc, MDL)) {
+ if (data.len) {
+ parse_encapsulated_suboptions
+ (packet -> options, &dhcp_options [i],
+ data.data, data.len, &dhcp_universe,
+ client -> config -> vendor_space_name
+ );
+ }
+ data_string_forget (&data, MDL);
+ }
+ } else
+ i = 0;
+
+ /* Figure out the overload flag. */
+ oc = lookup_option (&dhcp_universe, lease -> options,
+ DHO_DHCP_OPTION_OVERLOAD);
+ if (oc &&
+ evaluate_option_cache (&data, packet, (struct lease *)0, client,
+ packet -> options, lease -> options,
+ &global_scope, oc, MDL)) {
+ if (data.len > 0)
+ i = data.data [0];
+ else
+ i = 0;
+ data_string_forget (&data, MDL);
+ } else
+ i = 0;
+
/* If the server name was filled out, copy it. */
- if ((!packet -> options [DHO_DHCP_OPTION_OVERLOAD].len ||
- !(packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 2)) &&
- packet -> raw -> sname [0]) {
- int len;
+ if (!(i & 2) && packet -> raw -> sname [0]) {
+ unsigned len;
/* Don't count on the NUL terminator. */
for (len = 0; len < 64; len++)
if (!packet -> raw -> sname [len])
break;
- lease -> server_name = malloc (len + 1);
+ lease -> server_name = dmalloc (len + 1, MDL);
if (!lease -> server_name) {
- warn ("dhcpoffer: no memory for filename.\n");
- free_client_lease (lease);
+ log_error ("dhcpoffer: no memory for filename.\n");
+ destroy_client_lease (lease);
return (struct client_lease *)0;
} else {
memcpy (lease -> server_name,
@@ -917,18 +1242,16 @@ struct client_lease *packet_to_lease (packet)
}
/* Ditto for the filename. */
- if ((!packet -> options [DHO_DHCP_OPTION_OVERLOAD].len ||
- !(packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 1)) &&
- packet -> raw -> file [0]) {
- int len;
+ if (!(i & 1) && packet -> raw -> file [0]) {
+ unsigned len;
/* Don't count on the NUL terminator. */
for (len = 0; len < 64; len++)
if (!packet -> raw -> file [len])
break;
- lease -> filename = malloc (len + 1);
+ lease -> filename = dmalloc (len + 1, MDL);
if (!lease -> filename) {
- warn ("dhcpoffer: no memory for filename.\n");
- free_client_lease (lease);
+ log_error ("dhcpoffer: no memory for filename.\n");
+ destroy_client_lease (lease);
return (struct client_lease *)0;
} else {
memcpy (lease -> filename,
@@ -936,6 +1259,15 @@ struct client_lease *packet_to_lease (packet)
lease -> filename [len] = 0;
}
}
+
+ execute_statements_in_scope ((struct binding_value **)0,
+ (struct packet *)packet,
+ (struct lease *)0, client,
+ lease -> options, lease -> options,
+ &global_scope,
+ client -> config -> on_receipt,
+ (struct group *)0);
+
return lease;
}
@@ -943,95 +1275,103 @@ void dhcpnak (packet)
struct packet *packet;
{
struct interface_info *ip = packet -> interface;
+ struct client_state *client;
+
+ /* Find a client state that matches the xid... */
+ for (client = ip -> client; client; client = client -> next)
+ if (client -> xid == packet -> raw -> xid)
+ break;
/* If we're not receptive to an offer right now, or if the offer
has an unrecognizable transaction id, then just drop it. */
- if (packet -> interface -> client -> xid != packet -> raw -> xid ||
- (packet -> interface -> hw_address.hlen !=
+ if (!client ||
+ (packet -> interface -> hw_address.hlen - 1 !=
packet -> raw -> hlen) ||
- (memcmp (packet -> interface -> hw_address.haddr,
+ (memcmp (&packet -> interface -> hw_address.hbuf [1],
packet -> raw -> chaddr, packet -> raw -> hlen))) {
#if defined (DEBUG)
- debug ("DHCPNAK in wrong transaction.");
+ log_debug ("DHCPNAK in wrong transaction.");
#endif
return;
}
- if (ip -> client -> state != S_REBOOTING &&
- ip -> client -> state != S_REQUESTING &&
- ip -> client -> state != S_RENEWING &&
- ip -> client -> state != S_REBINDING) {
+ if (client -> state != S_REBOOTING &&
+ client -> state != S_REQUESTING &&
+ client -> state != S_RENEWING &&
+ client -> state != S_REBINDING) {
#if defined (DEBUG)
- debug ("DHCPNAK in wrong state.");
+ log_debug ("DHCPNAK in wrong state.");
#endif
return;
}
- note ("DHCPNAK from %s", piaddr (packet -> client_addr));
+ log_info ("DHCPNAK from %s", piaddr (packet -> client_addr));
- if (!ip -> client -> active) {
- note ("DHCPNAK with no active lease.\n");
+ if (!client -> active) {
+#if defined (DEBUG)
+ log_info ("DHCPNAK with no active lease.\n");
+#endif
return;
}
- free_client_lease (ip -> client -> active);
- ip -> client -> active = (struct client_lease *)0;
+ destroy_client_lease (client -> active);
+ client -> active = (struct client_lease *)0;
/* Stop sending DHCPREQUEST packets... */
- cancel_timeout (send_request, ip);
+ cancel_timeout (send_request, client);
- ip -> client -> state = S_INIT;
- state_init (ip);
+ client -> state = S_INIT;
+ state_init (client);
}
/* Send out a DHCPDISCOVER packet, and set a timeout to send out another
one after the right interval has expired. If we don't get an offer by
the time we reach the panic interval, call the panic function. */
-void send_discover (ipp)
- void *ipp;
+void send_discover (cpp)
+ void *cpp;
{
- struct interface_info *ip = ipp;
+ struct client_state *client = cpp;
int result;
int interval;
int increase = 1;
/* Figure out how long it's been since we started transmitting. */
- interval = cur_time - ip -> client -> first_sending;
+ interval = cur_time - client -> first_sending;
/* If we're past the panic timeout, call the script and tell it
we haven't found anything for this interface yet. */
- if (interval > ip -> client -> config -> timeout) {
- state_panic (ip);
+ if (interval > client -> config -> timeout) {
+ state_panic (client);
return;
}
/* If we're selecting media, try the whole list before doing
the exponential backoff, but if we've already received an
offer, stop looping, because we obviously have it right. */
- if (!ip -> client -> offered_leases &&
- ip -> client -> config -> media) {
+ if (!client -> offered_leases &&
+ client -> config -> media) {
int fail = 0;
again:
- if (ip -> client -> medium) {
- ip -> client -> medium =
- ip -> client -> medium -> next;
+ if (client -> medium) {
+ client -> medium = client -> medium -> next;
increase = 0;
}
- if (!ip -> client -> medium) {
+ if (!client -> medium) {
if (fail)
- error ("No valid media types for %s!",
- ip -> name);
- ip -> client -> medium =
- ip -> client -> config -> media;
+ log_fatal ("No valid media types for %s!",
+ client -> interface -> name);
+ client -> medium =
+ client -> config -> media;
increase = 1;
}
- note ("Trying medium \"%s\" %d",
- ip -> client -> medium -> string, increase);
- script_init (ip, "MEDIUM", ip -> client -> medium);
- if (script_go (ip)) {
+ log_info ("Trying medium \"%s\" %d",
+ client -> medium -> string, increase);
+ script_init (client, "MEDIUM", client -> medium);
+ if (script_go (client)) {
+ fail = 1;
goto again;
}
}
@@ -1042,54 +1382,52 @@ void send_discover (ipp)
zero and two times itself. On average, this means that it
will double with every transmission. */
if (increase) {
- if (!ip -> client -> interval)
- ip -> client -> interval =
- ip -> client -> config -> initial_interval;
- else {
- ip -> client -> interval +=
- ((random () >> 2) %
- (2 * ip -> client -> interval));
- }
+ if (!client -> interval)
+ client -> interval =
+ client -> config -> initial_interval;
+ else
+ client -> interval += ((random () >> 2) %
+ (2 * client -> interval));
/* Don't backoff past cutoff. */
- if (ip -> client -> interval >
- ip -> client -> config -> backoff_cutoff)
- ip -> client -> interval =
- ((ip -> client -> config -> backoff_cutoff / 2)
+ if (client -> interval >
+ client -> config -> backoff_cutoff)
+ client -> interval =
+ ((client -> config -> backoff_cutoff / 2)
+ ((random () >> 2) %
- ip -> client -> config -> backoff_cutoff));
- } else if (!ip -> client -> interval)
- ip -> client -> interval =
- ip -> client -> config -> initial_interval;
+ client -> config -> backoff_cutoff));
+ } else if (!client -> interval)
+ client -> interval = client -> config -> initial_interval;
/* If the backoff would take us to the panic timeout, just use that
as the interval. */
- if (cur_time + ip -> client -> interval >
- ip -> client -> first_sending + ip -> client -> config -> timeout)
- ip -> client -> interval =
- (ip -> client -> first_sending +
- ip -> client -> config -> timeout) - cur_time + 1;
+ if (cur_time + client -> interval >
+ client -> first_sending + client -> config -> timeout)
+ client -> interval =
+ (client -> first_sending +
+ client -> config -> timeout) - cur_time + 1;
/* Record the number of seconds since we started sending. */
if (interval < 65536)
- ip -> client -> packet.secs = htons (interval);
+ client -> packet.secs = htons (interval);
else
- ip -> client -> packet.secs = htons (65535);
- ip -> client -> secs = ip -> client -> packet.secs;
+ client -> packet.secs = htons (65535);
+ client -> secs = client -> packet.secs;
- note ("DHCPDISCOVER on %s to %s port %d interval %ld",
- ip -> name,
+ log_info ("DHCPDISCOVER on %s to %s port %d interval %ld",
+ client -> name ? client -> name : client -> interface -> name,
inet_ntoa (sockaddr_broadcast.sin_addr),
- ntohs (sockaddr_broadcast.sin_port), ip -> client -> interval);
+ ntohs (sockaddr_broadcast.sin_port), (long)(client -> interval));
/* Send out a packet. */
- result = send_packet (ip, (struct packet *)0,
- &ip -> client -> packet,
- ip -> client -> packet_length,
+ result = send_packet (client -> interface, (struct packet *)0,
+ &client -> packet,
+ client -> packet_length,
inaddr_any, &sockaddr_broadcast,
(struct hardware *)0);
- add_timeout (cur_time + ip -> client -> interval, send_discover, ip);
+ add_timeout (cur_time + client -> interval,
+ send_discover, client, 0, 0);
}
/* state_panic gets called if we haven't received any offers in a preset
@@ -1097,106 +1435,113 @@ void send_discover (ipp)
haven't yet expired, and failing that, we call the client script and
hope it can do something. */
-void state_panic (ipp)
- void *ipp;
+void state_panic (cpp)
+ void *cpp;
{
- struct interface_info *ip = ipp;
-
- struct client_lease *loop = ip -> client -> active;
+ struct client_state *client = cpp;
+ struct client_lease *loop;
struct client_lease *lp;
- note ("No DHCPOFFERS received.");
+ loop = lp = client -> active;
+
+ log_info ("No DHCPOFFERS received.");
/* We may not have an active lease, but we may have some
predefined leases that we can try. */
- if (!ip -> client -> active && ip -> client -> leases)
+ if (!client -> active && client -> leases)
goto activate_next;
/* Run through the list of leases and see if one can be used. */
- while (ip -> client -> active) {
- if (ip -> client -> active -> expiry > cur_time) {
- note ("Trying recorded lease %s",
- piaddr (ip -> client -> active -> address));
+ while (client -> active) {
+ if (client -> active -> expiry > cur_time) {
+ log_info ("Trying recorded lease %s",
+ piaddr (client -> active -> address));
/* Run the client script with the existing
parameters. */
- script_init (ip, "TIMEOUT",
- ip -> client -> active -> medium);
- script_write_params (ip, "new_",
- ip -> client -> active);
- if (ip -> client -> alias)
- script_write_params (ip, "alias_",
- ip -> client -> alias);
+ script_init (client, "TIMEOUT",
+ client -> active -> medium);
+ script_write_params (client, "new_", client -> active);
+ if (client -> alias)
+ script_write_params (client, "alias_",
+ client -> alias);
/* If the old lease is still good and doesn't
yet need renewal, go into BOUND state and
timeout at the renewal time. */
- if (!script_go (ip)) {
- if (cur_time <
- ip -> client -> active -> renewal) {
- ip -> client -> state = S_BOUND;
- note ("bound: renewal in %d seconds.",
- ip -> client -> active -> renewal
- - cur_time);
- add_timeout ((ip -> client ->
- active -> renewal),
- state_bound, ip);
- } else {
- ip -> client -> state = S_BOUND;
- note ("bound: immediate renewal.");
- state_bound (ip);
- }
- reinitialize_interfaces ();
- go_daemon ();
- return;
+ if (!script_go (client)) {
+ if (cur_time < client -> active -> renewal) {
+ client -> state = S_BOUND;
+ log_info ("bound: renewal in %ld %s.",
+ (long)(client -> active -> renewal -
+ cur_time), "seconds");
+ add_timeout (client -> active -> renewal,
+ state_bound, client, 0, 0);
+ } else {
+ client -> state = S_BOUND;
+ log_info ("bound: immediate renewal.");
+ state_bound (client);
+ }
+ reinitialize_interfaces ();
+ go_daemon ();
+ return;
}
}
/* If there are no other leases, give up. */
- if (!ip -> client -> leases) {
- ip -> client -> leases = ip -> client -> active;
- ip -> client -> active = (struct client_lease *)0;
+ if (!client -> leases) {
+ client -> leases = client -> active;
+ client -> active = (struct client_lease *)0;
break;
}
activate_next:
/* Otherwise, put the active lease at the end of the
lease list, and try another lease.. */
- for (lp = ip -> client -> leases; lp -> next; lp = lp -> next)
+ for (lp = client -> leases; lp -> next; lp = lp -> next)
;
- lp -> next = ip -> client -> active;
+ lp -> next = client -> active;
if (lp -> next) {
lp -> next -> next = (struct client_lease *)0;
}
- ip -> client -> active = ip -> client -> leases;
- ip -> client -> leases = ip -> client -> leases -> next;
+ client -> active = client -> leases;
+ client -> leases = client -> leases -> next;
/* If we already tried this lease, we've exhausted the
set of leases, so we might as well give up for
now. */
- if (ip -> client -> active == loop)
+ if (client -> active == loop)
break;
else if (!loop)
- loop = ip -> client -> active;
+ loop = client -> active;
}
/* No leases were available, or what was available didn't work, so
tell the shell script that we failed to allocate an address,
and try again later. */
- note ("No working leases in persistent database - sleeping.\n");
- script_init (ip, "FAIL", (struct string_list *)0);
- if (ip -> client -> alias)
- script_write_params (ip, "alias_", ip -> client -> alias);
- script_go (ip);
- ip -> client -> state = S_INIT;
- add_timeout (cur_time + ip -> client -> config -> retry_interval,
- state_init, ip);
+ if (onetry) {
+ if (!quiet)
+ log_info ("Unable to obtain a lease on first try.%s",
+ " Exiting.");
+ exit (2);
+ }
+
+ log_info ("No working leases in persistent database - sleeping.");
+ script_init (client, "FAIL", (struct string_list *)0);
+ if (client -> alias)
+ script_write_params (client, "alias_", client -> alias);
+ script_go (client);
+ client -> state = S_INIT;
+ add_timeout (cur_time +
+ ((client -> config -> retry_interval + 1) / 2 +
+ (random () % client -> config -> retry_interval)),
+ state_init, client, 0, 0);
go_daemon ();
}
-void send_request (ipp)
- void *ipp;
+void send_request (cpp)
+ void *cpp;
{
- struct interface_info *ip = ipp;
+ struct client_state *client = cpp;
int result;
int interval;
@@ -1204,7 +1549,7 @@ void send_request (ipp)
struct in_addr from;
/* Figure out how long it's been since we started transmitting. */
- interval = cur_time - ip -> client -> first_sending;
+ interval = cur_time - client -> first_sending;
/* If we're in the INIT-REBOOT or REQUESTING state and we're
past the reboot timeout, go to INIT and see if we can
@@ -1216,91 +1561,87 @@ void send_request (ipp)
us a new address, but we could also have successfully
reused our old address. In the former case, we're hosed
anyway. This is not a win-prone situation. */
- if ((ip -> client -> state == S_REBOOTING ||
- ip -> client -> state == S_REQUESTING) &&
- interval > ip -> client -> config -> reboot_timeout) {
+ if ((client -> state == S_REBOOTING ||
+ client -> state == S_REQUESTING) &&
+ interval > client -> config -> reboot_timeout) {
cancel:
- ip -> client -> state = S_INIT;
- cancel_timeout (send_request, ip);
- state_init (ip);
+ client -> state = S_INIT;
+ cancel_timeout (send_request, client);
+ state_init (client);
return;
}
/* If we're in the reboot state, make sure the media is set up
correctly. */
- if (ip -> client -> state == S_REBOOTING &&
- !ip -> client -> medium &&
- ip -> client -> active -> medium ) {
- script_init (ip, "MEDIUM", ip -> client -> active -> medium);
+ if (client -> state == S_REBOOTING &&
+ !client -> medium &&
+ client -> active -> medium ) {
+ script_init (client, "MEDIUM", client -> active -> medium);
/* If the medium we chose won't fly, go to INIT state. */
- if (script_go (ip))
+ if (script_go (client))
goto cancel;
/* Record the medium. */
- ip -> client -> medium = ip -> client -> active -> medium;
+ client -> medium = client -> active -> medium;
}
/* If the lease has expired, relinquish the address and go back
to the INIT state. */
- if (ip -> client -> state != S_REQUESTING &&
- cur_time > ip -> client -> active -> expiry) {
+ if (client -> state != S_REQUESTING &&
+ cur_time > client -> active -> expiry) {
/* Run the client script with the new parameters. */
- script_init (ip, "EXPIRE", (struct string_list *)0);
- script_write_params (ip, "old_", ip -> client -> active);
- if (ip -> client -> alias)
- script_write_params (ip, "alias_",
- ip -> client -> alias);
- script_go (ip);
+ script_init (client, "EXPIRE", (struct string_list *)0);
+ script_write_params (client, "old_", client -> active);
+ if (client -> alias)
+ script_write_params (client, "alias_",
+ client -> alias);
+ script_go (client);
/* Now do a preinit on the interface so that we can
discover a new address. */
- script_init (ip, "PREINIT", (struct string_list *)0);
- if (ip -> client -> alias)
- script_write_params (ip, "alias_",
- ip -> client -> alias);
- script_go (ip);
-
- ip -> client -> state = S_INIT;
- state_init (ip);
+ script_init (client, "PREINIT", (struct string_list *)0);
+ if (client -> alias)
+ script_write_params (client, "alias_",
+ client -> alias);
+ script_go (client);
+
+ client -> state = S_INIT;
+ state_init (client);
return;
}
/* Do the exponential backoff... */
- if (!ip -> client -> interval)
- ip -> client -> interval =
- ip -> client -> config -> initial_interval;
+ if (!client -> interval)
+ client -> interval = client -> config -> initial_interval;
else {
- ip -> client -> interval +=
- ((random () >> 2) %
- (2 * ip -> client -> interval));
+ client -> interval += ((random () >> 2) %
+ (2 * client -> interval));
}
/* Don't backoff past cutoff. */
- if (ip -> client -> interval >
- ip -> client -> config -> backoff_cutoff)
- ip -> client -> interval =
- ((ip -> client -> config -> backoff_cutoff / 2)
- + ((random () >> 2)
- % ip -> client -> interval));
+ if (client -> interval >
+ client -> config -> backoff_cutoff)
+ client -> interval =
+ ((client -> config -> backoff_cutoff / 2)
+ + ((random () >> 2) % client -> interval));
/* If the backoff would take us to the expiry time, just set the
timeout to the expiry time. */
- if (ip -> client -> state != S_REQUESTING &&
- cur_time + ip -> client -> interval >
- ip -> client -> active -> expiry)
- ip -> client -> interval =
- ip -> client -> active -> expiry - cur_time + 1;
+ if (client -> state != S_REQUESTING &&
+ cur_time + client -> interval > client -> active -> expiry)
+ client -> interval =
+ client -> active -> expiry - cur_time + 1;
/* If the lease T2 time has elapsed, or if we're not yet bound,
broadcast the DHCPREQUEST rather than unicasting. */
- if (ip -> client -> state == S_REQUESTING ||
- ip -> client -> state == S_REBOOTING ||
- cur_time > ip -> client -> active -> rebind)
- destination.sin_addr.s_addr = INADDR_BROADCAST;
+ if (client -> state == S_REQUESTING ||
+ client -> state == S_REBOOTING ||
+ cur_time > client -> active -> rebind)
+ destination.sin_addr = sockaddr_broadcast.sin_addr;
else
memcpy (&destination.sin_addr.s_addr,
- ip -> client -> destination.iabuf,
+ client -> destination.iabuf,
sizeof destination.sin_addr.s_addr);
destination.sin_port = remote_port;
destination.sin_family = AF_INET;
@@ -1308,23 +1649,25 @@ void send_request (ipp)
destination.sin_len = sizeof destination;
#endif
- if (ip -> client -> state != S_REQUESTING)
- memcpy (&from, ip -> client -> active -> address.iabuf,
+ if (client -> state == S_RENEWING ||
+ client -> state == S_REBINDING)
+ memcpy (&from, client -> active -> address.iabuf,
sizeof from);
else
from.s_addr = INADDR_ANY;
/* Record the number of seconds since we started sending. */
- if (ip -> client -> state == S_REQUESTING)
- ip -> client -> packet.secs = ip -> client -> secs;
+ if (client -> state == S_REQUESTING)
+ client -> packet.secs = client -> secs;
else {
if (interval < 65536)
- ip -> client -> packet.secs = htons (interval);
+ client -> packet.secs = htons (interval);
else
- ip -> client -> packet.secs = htons (65535);
+ client -> packet.secs = htons (65535);
}
- note ("DHCPREQUEST on %s to %s port %d", ip -> name,
+ log_info ("DHCPREQUEST on %s to %s port %d",
+ client -> name ? client -> name : client -> interface -> name,
inet_ntoa (destination.sin_addr),
ntohs (destination.sin_port));
@@ -1332,451 +1675,429 @@ void send_request (ipp)
fallback_interface)
result = send_packet (fallback_interface,
(struct packet *)0,
- &ip -> client -> packet,
- ip -> client -> packet_length,
+ &client -> packet,
+ client -> packet_length,
from, &destination,
(struct hardware *)0);
else
/* Send out a packet. */
- result = send_packet (ip, (struct packet *)0,
- &ip -> client -> packet,
- ip -> client -> packet_length,
+ result = send_packet (client -> interface, (struct packet *)0,
+ &client -> packet,
+ client -> packet_length,
from, &destination,
(struct hardware *)0);
- add_timeout (cur_time + ip -> client -> interval,
- send_request, ip);
+ add_timeout (cur_time + client -> interval,
+ send_request, client, 0, 0);
}
-void send_decline (ipp)
- void *ipp;
+void send_decline (cpp)
+ void *cpp;
{
- struct interface_info *ip = ipp;
+ struct client_state *client = cpp;
int result;
- note ("DHCPDECLINE on %s to %s port %d", ip -> name,
+ log_info ("DHCPDECLINE on %s to %s port %d",
+ client -> name ? client -> name : client -> interface -> name,
inet_ntoa (sockaddr_broadcast.sin_addr),
ntohs (sockaddr_broadcast.sin_port));
/* Send out a packet. */
- result = send_packet (ip, (struct packet *)0,
- &ip -> client -> packet,
- ip -> client -> packet_length,
+ result = send_packet (client -> interface, (struct packet *)0,
+ &client -> packet,
+ client -> packet_length,
inaddr_any, &sockaddr_broadcast,
(struct hardware *)0);
}
-void send_release (ipp)
- void *ipp;
+void send_release (cpp)
+ void *cpp;
{
- struct interface_info *ip = ipp;
+ struct client_state *client = cpp;
int result;
+ struct sockaddr_in destination;
+ struct in_addr from;
- note ("DHCPRELEASE on %s to %s port %d", ip -> name,
- inet_ntoa (sockaddr_broadcast.sin_addr),
- ntohs (sockaddr_broadcast.sin_port));
+ memcpy (&from, client -> active -> address.iabuf,
+ sizeof from);
+ memcpy (&destination.sin_addr.s_addr,
+ client -> destination.iabuf,
+ sizeof destination.sin_addr.s_addr);
+ destination.sin_port = remote_port;
+ destination.sin_family = AF_INET;
+#ifdef HAVE_SA_LEN
+ destination.sin_len = sizeof destination;
+#endif
- /* Send out a packet. */
- result = send_packet (ip, (struct packet *)0,
- &ip -> client -> packet,
- ip -> client -> packet_length,
- inaddr_any, &sockaddr_broadcast,
- (struct hardware *)0);
+ /* Set the lease to end now, so that we don't accidentally
+ reuse it if we restart before the old expiry time. */
+ client -> active -> expiry =
+ client -> active -> renewal =
+ client -> active -> rebind = cur_time;
+ if (!write_client_lease (client, client -> active, 1, 1)) {
+ log_error ("Can't release lease: lease write failed.");
+ return;
+ }
+
+ log_info ("DHCPRELEASE on %s to %s port %d",
+ client -> name ? client -> name : client -> interface -> name,
+ inet_ntoa (destination.sin_addr),
+ ntohs (destination.sin_port));
+
+ if (fallback_interface)
+ result = send_packet (fallback_interface,
+ (struct packet *)0,
+ &client -> packet,
+ client -> packet_length,
+ from, &destination,
+ (struct hardware *)0);
+ else
+ /* Send out a packet. */
+ result = send_packet (client -> interface, (struct packet *)0,
+ &client -> packet,
+ client -> packet_length,
+ from, &destination,
+ (struct hardware *)0);
}
-void make_discover (ip, lease)
- struct interface_info *ip;
+void make_client_options (client, lease, type, sid, rip, prl, op)
+ struct client_state *client;
struct client_lease *lease;
+ u_int8_t *type;
+ struct option_cache *sid;
+ struct iaddr *rip;
+ u_int32_t *prl;
+ struct option_state **op;
{
- unsigned char discover = DHCPDISCOVER;
- int i;
-
- struct tree_cache *options [256];
- struct tree_cache option_elements [256];
-
- memset (option_elements, 0, sizeof option_elements);
- memset (options, 0, sizeof options);
- memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet));
-
- /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
- i = DHO_DHCP_MESSAGE_TYPE;
- options [i] = &option_elements [i];
- options [i] -> value = &discover;
- options [i] -> len = sizeof discover;
- options [i] -> buf_size = sizeof discover;
- options [i] -> timeout = 0xFFFFFFFF;
- options [i] -> tree = (struct tree *)0;
-
- /* Request the options we want */
- i = DHO_DHCP_PARAMETER_REQUEST_LIST;
- options [i] = &option_elements [i];
- options [i] -> value = ip -> client -> config -> requested_options;
- options [i] -> len = ip -> client -> config -> requested_option_count;
- options [i] -> buf_size =
- ip -> client -> config -> requested_option_count;
- options [i] -> timeout = 0xFFFFFFFF;
- options [i] -> tree = (struct tree *)0;
-
- /* If we had an address, try to get it again. */
- if (lease) {
- ip -> client -> requested_address = lease -> address;
- i = DHO_DHCP_REQUESTED_ADDRESS;
- options [i] = &option_elements [i];
- options [i] -> value = lease -> address.iabuf;
- options [i] -> len = lease -> address.len;
- options [i] -> buf_size = lease -> address.len;
- options [i] -> timeout = 0xFFFFFFFF;
- options [i] -> tree = (struct tree *)0;
+ unsigned i;
+ struct option_cache *oc;
+ struct buffer *bp = (struct buffer *)0;
+
+ /* If there are any leftover options, get rid of them. */
+ if (*op)
+ option_state_dereference (op, MDL);
+
+ /* Allocate space for options. */
+ option_state_allocate (op, MDL);
+
+ /* Send the server identifier if provided. */
+ if (sid)
+ save_option (&dhcp_universe, *op, sid);
+
+ oc = (struct option_cache *)0;
+
+ /* Send the requested address if provided. */
+ if (rip) {
+ client -> requested_address = *rip;
+ if (!(make_const_option_cache
+ (&oc, (struct buffer **)0, rip -> iabuf, rip -> len,
+ &dhcp_options [DHO_DHCP_REQUESTED_ADDRESS], MDL)))
+ log_error ("can't make requested address cache.");
+ else {
+ save_option (&dhcp_universe, *op, oc);
+ option_cache_dereference (&oc, MDL);
+ }
} else {
- ip -> client -> requested_address.len = 0;
- }
-
- /* Send any options requested in the config file. */
- for (i = 0; i < 256; i++) {
- if (!options [i] &&
- ip -> client -> config -> send_options [i].data) {
- options [i] = &option_elements [i];
- options [i] -> value = ip -> client -> config ->
- send_options [i].data;
- options [i] -> len = ip -> client -> config ->
- send_options [i].len;
- options [i] -> buf_size = ip -> client -> config ->
- send_options [i].len;
- options [i] -> timeout = 0xFFFFFFFF;
- options [i] -> tree = (struct tree *)0;
+ client -> requested_address.len = 0;
+ }
+
+ if (!(make_const_option_cache
+ (&oc, (struct buffer **)0,
+ type, 1, &dhcp_options [DHO_DHCP_MESSAGE_TYPE], MDL)))
+ log_error ("can't make message type.");
+ else {
+ save_option (&dhcp_universe, *op, oc);
+ option_cache_dereference (&oc, MDL);
+ }
+
+ if (prl) {
+ /* Figure out how many parameters were requested. */
+ for (i = 0; prl [i]; i++)
+ ;
+ if (!buffer_allocate (&bp, i, MDL))
+ log_error ("can't make parameter list buffer.");
+ else {
+ for (i = 0; prl [i]; i++)
+ bp -> data [i] = prl [i];
+ if (!(make_const_option_cache
+ (&oc, &bp, (u_int8_t *)0, i,
+ &dhcp_options [DHO_DHCP_PARAMETER_REQUEST_LIST],
+ MDL)))
+ log_error ("can't make option cache");
+ else {
+ save_option (&dhcp_universe, *op, oc);
+ option_cache_dereference (&oc, MDL);
+ }
}
}
+ /* Run statements that need to be run on transmission. */
+ if (client -> config -> on_transmission)
+ execute_statements_in_scope
+ ((struct binding_value **)0,
+ (struct packet *)0, (struct lease *)0, client,
+ (lease ? lease -> options : (struct option_state *)0),
+ *op, &global_scope,
+ client -> config -> on_transmission,
+ (struct group *)0);
+}
+
+void make_discover (client, lease)
+ struct client_state *client;
+ struct client_lease *lease;
+{
+ unsigned char discover = DHCPDISCOVER;
+ int i;
+ struct option_state *options = (struct option_state *)0;
+
+ memset (&client -> packet, 0, sizeof (client -> packet));
+
+ make_client_options (client,
+ lease, &discover, (struct option_cache *)0,
+ lease ? &lease -> address : (struct iaddr *)0,
+ client -> config -> requested_options,
+ &options);
+
/* Set up the option buffer... */
- ip -> client -> packet_length =
- cons_options ((struct packet *)0, &ip -> client -> packet, 0,
- options, 0, 0, 0, (u_int8_t *)0, 0);
- if (ip -> client -> packet_length < BOOTP_MIN_LEN)
- ip -> client -> packet_length = BOOTP_MIN_LEN;
-
- ip -> client -> packet.op = BOOTREQUEST;
- ip -> client -> packet.htype = ip -> hw_address.htype;
- ip -> client -> packet.hlen = ip -> hw_address.hlen;
- ip -> client -> packet.hops = 0;
- ip -> client -> packet.xid = random ();
- ip -> client -> packet.secs = 0; /* filled in by send_discover. */
-
- if (can_receive_unicast_unconfigured (ip))
- ip -> client -> packet.flags = 0;
+ client -> packet_length =
+ cons_options ((struct packet *)0, &client -> packet,
+ (struct lease *)0, client, 0,
+ (struct option_state *)0, options,
+ &global_scope, 0, 0, 0, (struct data_string *)0,
+ client -> config -> vendor_space_name);
+ if (client -> packet_length < BOOTP_MIN_LEN)
+ client -> packet_length = BOOTP_MIN_LEN;
+
+ client -> packet.op = BOOTREQUEST;
+ client -> packet.htype = client -> interface -> hw_address.hbuf [0];
+ client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
+ client -> packet.hops = 0;
+ client -> packet.xid = random ();
+ client -> packet.secs = 0; /* filled in by send_discover. */
+
+ if (can_receive_unicast_unconfigured (client -> interface))
+ client -> packet.flags = 0;
else
- ip -> client -> packet.flags = htons (BOOTP_BROADCAST);
-
- memset (&(ip -> client -> packet.ciaddr),
- 0, sizeof ip -> client -> packet.ciaddr);
- memset (&(ip -> client -> packet.yiaddr),
- 0, sizeof ip -> client -> packet.yiaddr);
- memset (&(ip -> client -> packet.siaddr),
- 0, sizeof ip -> client -> packet.siaddr);
- memset (&(ip -> client -> packet.giaddr),
- 0, sizeof ip -> client -> packet.giaddr);
- memcpy (ip -> client -> packet.chaddr,
- ip -> hw_address.haddr, ip -> hw_address.hlen);
+ client -> packet.flags = htons (BOOTP_BROADCAST);
+
+ memset (&(client -> packet.ciaddr),
+ 0, sizeof client -> packet.ciaddr);
+ memset (&(client -> packet.yiaddr),
+ 0, sizeof client -> packet.yiaddr);
+ memset (&(client -> packet.siaddr),
+ 0, sizeof client -> packet.siaddr);
+ client -> packet.giaddr = giaddr;
+ if (client -> interface -> hw_address.hlen > 0)
+ memcpy (client -> packet.chaddr,
+ &client -> interface -> hw_address.hbuf [1],
+ (unsigned)(client -> interface -> hw_address.hlen - 1));
#ifdef DEBUG_PACKET
- dump_packet (sendpkt);
- dump_raw ((unsigned char *)ip -> client -> packet,
- sendpkt->packet_length);
+ dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
#endif
}
-void make_request (ip, lease)
- struct interface_info *ip;
+void make_request (client, lease)
+ struct client_state *client;
struct client_lease *lease;
{
unsigned char request = DHCPREQUEST;
- int i;
+ int i, j;
+ unsigned char *tmp, *digest;
+ unsigned char *old_digest_loc;
+ struct option_cache *oc;
- struct tree_cache *options [256];
- struct tree_cache option_elements [256];
-
- memset (options, 0, sizeof options);
- memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet));
-
- /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
- i = DHO_DHCP_MESSAGE_TYPE;
- options [i] = &option_elements [i];
- options [i] -> value = &request;
- options [i] -> len = sizeof request;
- options [i] -> buf_size = sizeof request;
- options [i] -> timeout = 0xFFFFFFFF;
- options [i] -> tree = (struct tree *)0;
-
- /* Request the options we want */
- i = DHO_DHCP_PARAMETER_REQUEST_LIST;
- options [i] = &option_elements [i];
- options [i] -> value = ip -> client -> config -> requested_options;
- options [i] -> len = ip -> client -> config -> requested_option_count;
- options [i] -> buf_size =
- ip -> client -> config -> requested_option_count;
- options [i] -> timeout = 0xFFFFFFFF;
- options [i] -> tree = (struct tree *)0;
-
- /* If we are requesting an address that hasn't yet been assigned
- to us, use the DHCP Requested Address option. */
- if (ip -> client -> state == S_REQUESTING) {
- /* Send back the server identifier... */
- i = DHO_DHCP_SERVER_IDENTIFIER;
- options [i] = &option_elements [i];
- options [i] -> value = lease -> options [i].data;
- options [i] -> len = lease -> options [i].len;
- options [i] -> buf_size = lease -> options [i].len;
- options [i] -> timeout = 0xFFFFFFFF;
- options [i] -> tree = (struct tree *)0;
- }
- if (ip -> client -> state == S_REQUESTING ||
- ip -> client -> state == S_REBOOTING) {
- ip -> client -> requested_address = lease -> address;
- i = DHO_DHCP_REQUESTED_ADDRESS;
- options [i] = &option_elements [i];
- options [i] -> value = lease -> address.iabuf;
- options [i] -> len = lease -> address.len;
- options [i] -> buf_size = lease -> address.len;
- options [i] -> timeout = 0xFFFFFFFF;
- options [i] -> tree = (struct tree *)0;
- } else {
- ip -> client -> requested_address.len = 0;
- }
-
- /* Send any options requested in the config file. */
- for (i = 0; i < 256; i++) {
- if (!options [i] &&
- ip -> client -> config -> send_options [i].data) {
- options [i] = &option_elements [i];
- options [i] -> value = ip -> client -> config ->
- send_options [i].data;
- options [i] -> len = ip -> client -> config ->
- send_options [i].len;
- options [i] -> buf_size = ip -> client -> config ->
- send_options [i].len;
- options [i] -> timeout = 0xFFFFFFFF;
- options [i] -> tree = (struct tree *)0;
- }
- }
+ memset (&client -> packet, 0, sizeof (client -> packet));
+
+ if (client -> state == S_REQUESTING)
+ oc = lookup_option (&dhcp_universe, lease -> options,
+ DHO_DHCP_SERVER_IDENTIFIER);
+ else
+ oc = (struct option_cache *)0;
+
+ make_client_options (client, lease, &request, oc,
+ ((client -> state == S_REQUESTING ||
+ client -> state == S_REBOOTING)
+ ? &lease -> address
+ : (struct iaddr *)0),
+ client -> config -> requested_options,
+ &client -> sent_options);
/* Set up the option buffer... */
- ip -> client -> packet_length =
- cons_options ((struct packet *)0, &ip -> client -> packet, 0,
- options, 0, 0, 0, (u_int8_t *)0, 0);
- if (ip -> client -> packet_length < BOOTP_MIN_LEN)
- ip -> client -> packet_length = BOOTP_MIN_LEN;
-
- ip -> client -> packet.op = BOOTREQUEST;
- ip -> client -> packet.htype = ip -> hw_address.htype;
- ip -> client -> packet.hlen = ip -> hw_address.hlen;
- ip -> client -> packet.hops = 0;
- ip -> client -> packet.xid = ip -> client -> xid;
- ip -> client -> packet.secs = 0; /* Filled in by send_request. */
+ client -> packet_length =
+ cons_options ((struct packet *)0, &client -> packet,
+ (struct lease *)0, client, 0,
+ (struct option_state *)0, client -> sent_options,
+ &global_scope, 0, 0, 0, (struct data_string *)0,
+ client -> config -> vendor_space_name);
+ if (client -> packet_length < BOOTP_MIN_LEN)
+ client -> packet_length = BOOTP_MIN_LEN;
+
+ client -> packet.op = BOOTREQUEST;
+ client -> packet.htype = client -> interface -> hw_address.hbuf [0];
+ client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
+ client -> packet.hops = 0;
+ client -> packet.xid = client -> xid;
+ client -> packet.secs = 0; /* Filled in by send_request. */
/* If we own the address we're requesting, put it in ciaddr;
otherwise set ciaddr to zero. */
- if (ip -> client -> state == S_BOUND ||
- ip -> client -> state == S_RENEWING ||
- ip -> client -> state == S_REBINDING) {
- memcpy (&ip -> client -> packet.ciaddr,
+ if (client -> state == S_BOUND ||
+ client -> state == S_RENEWING ||
+ client -> state == S_REBINDING) {
+ memcpy (&client -> packet.ciaddr,
lease -> address.iabuf, lease -> address.len);
- ip -> client -> packet.flags = 0;
+ client -> packet.flags = 0;
} else {
- memset (&ip -> client -> packet.ciaddr, 0,
- sizeof ip -> client -> packet.ciaddr);
- if (can_receive_unicast_unconfigured (ip))
- ip -> client -> packet.flags = 0;
+ memset (&client -> packet.ciaddr, 0,
+ sizeof client -> packet.ciaddr);
+ if (can_receive_unicast_unconfigured (client -> interface))
+ client -> packet.flags = 0;
else
- ip -> client -> packet.flags = htons (BOOTP_BROADCAST);
+ client -> packet.flags = htons (BOOTP_BROADCAST);
}
- memset (&ip -> client -> packet.yiaddr, 0,
- sizeof ip -> client -> packet.yiaddr);
- memset (&ip -> client -> packet.siaddr, 0,
- sizeof ip -> client -> packet.siaddr);
- memset (&ip -> client -> packet.giaddr, 0,
- sizeof ip -> client -> packet.giaddr);
- memcpy (ip -> client -> packet.chaddr,
- ip -> hw_address.haddr, ip -> hw_address.hlen);
+ memset (&client -> packet.yiaddr, 0,
+ sizeof client -> packet.yiaddr);
+ memset (&client -> packet.siaddr, 0,
+ sizeof client -> packet.siaddr);
+ if (client -> state != S_BOUND &&
+ client -> state != S_RENEWING)
+ client -> packet.giaddr = giaddr;
+ else
+ memset (&client -> packet.giaddr, 0,
+ sizeof client -> packet.giaddr);
+ if (client -> interface -> hw_address.hlen > 0)
+ memcpy (client -> packet.chaddr,
+ &client -> interface -> hw_address.hbuf [1],
+ (unsigned)(client -> interface -> hw_address.hlen - 1));
#ifdef DEBUG_PACKET
- dump_packet (sendpkt);
- dump_raw ((unsigned char *)ip -> client -> packet, sendpkt->packet_length);
+ dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
#endif
}
-void make_decline (ip, lease)
- struct interface_info *ip;
+void make_decline (client, lease)
+ struct client_state *client;
struct client_lease *lease;
{
unsigned char decline = DHCPDECLINE;
int i;
+ struct option_cache *oc;
- struct tree_cache *options [256];
- struct tree_cache message_type_tree;
- struct tree_cache requested_address_tree;
- struct tree_cache server_id_tree;
- struct tree_cache client_id_tree;
-
- memset (options, 0, sizeof options);
- memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet));
-
- /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
- i = DHO_DHCP_MESSAGE_TYPE;
- options [i] = &message_type_tree;
- options [i] -> value = &decline;
- options [i] -> len = sizeof decline;
- options [i] -> buf_size = sizeof decline;
- options [i] -> timeout = 0xFFFFFFFF;
- options [i] -> tree = (struct tree *)0;
-
- /* Send back the server identifier... */
- i = DHO_DHCP_SERVER_IDENTIFIER;
- options [i] = &server_id_tree;
- options [i] -> value = lease -> options [i].data;
- options [i] -> len = lease -> options [i].len;
- options [i] -> buf_size = lease -> options [i].len;
- options [i] -> timeout = 0xFFFFFFFF;
- options [i] -> tree = (struct tree *)0;
-
- /* Send back the address we're declining. */
- i = DHO_DHCP_REQUESTED_ADDRESS;
- options [i] = &requested_address_tree;
- options [i] -> value = lease -> address.iabuf;
- options [i] -> len = lease -> address.len;
- options [i] -> buf_size = lease -> address.len;
- options [i] -> timeout = 0xFFFFFFFF;
- options [i] -> tree = (struct tree *)0;
-
- /* Send the uid if the user supplied one. */
- i = DHO_DHCP_CLIENT_IDENTIFIER;
- if (ip -> client -> config -> send_options [i].len) {
- options [i] = &client_id_tree;
- options [i] -> value = ip -> client -> config ->
- send_options [i].data;
- options [i] -> len = ip -> client -> config ->
- send_options [i].len;
- options [i] -> buf_size = ip -> client -> config ->
- send_options [i].len;
- options [i] -> timeout = 0xFFFFFFFF;
- options [i] -> tree = (struct tree *)0;
- }
+ struct option_state *options = (struct option_state *)0;
+ oc = lookup_option (&dhcp_universe, lease -> options,
+ DHO_DHCP_SERVER_IDENTIFIER);
+ make_client_options (client, lease, &decline, oc,
+ &lease -> address, (u_int32_t *)0, &options);
/* Set up the option buffer... */
- ip -> client -> packet_length =
- cons_options ((struct packet *)0, &ip -> client -> packet, 0,
- options, 0, 0, 0, (u_int8_t *)0, 0);
- if (ip -> client -> packet_length < BOOTP_MIN_LEN)
- ip -> client -> packet_length = BOOTP_MIN_LEN;
-
- ip -> client -> packet.op = BOOTREQUEST;
- ip -> client -> packet.htype = ip -> hw_address.htype;
- ip -> client -> packet.hlen = ip -> hw_address.hlen;
- ip -> client -> packet.hops = 0;
- ip -> client -> packet.xid = ip -> client -> xid;
- ip -> client -> packet.secs = 0; /* Filled in by send_request. */
- ip -> client -> packet.flags = 0;
+ memset (&client -> packet, 0, sizeof (client -> packet));
+ client -> packet_length =
+ cons_options ((struct packet *)0, &client -> packet,
+ (struct lease *)0, client, 0,
+ (struct option_state *)0, options,
+ &global_scope, 0, 0, 0, (struct data_string *)0,
+ client -> config -> vendor_space_name);
+ if (client -> packet_length < BOOTP_MIN_LEN)
+ client -> packet_length = BOOTP_MIN_LEN;
+ option_state_dereference (&options, MDL);
+
+ client -> packet.op = BOOTREQUEST;
+ client -> packet.htype = client -> interface -> hw_address.hbuf [0];
+ client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
+ client -> packet.hops = 0;
+ client -> packet.xid = client -> xid;
+ client -> packet.secs = 0; /* Filled in by send_request. */
+ if (can_receive_unicast_unconfigured (client -> interface))
+ client -> packet.flags = 0;
+ else
+ client -> packet.flags = htons (BOOTP_BROADCAST);
/* ciaddr must always be zero. */
- memset (&ip -> client -> packet.ciaddr, 0,
- sizeof ip -> client -> packet.ciaddr);
- memset (&ip -> client -> packet.yiaddr, 0,
- sizeof ip -> client -> packet.yiaddr);
- memset (&ip -> client -> packet.siaddr, 0,
- sizeof ip -> client -> packet.siaddr);
- memset (&ip -> client -> packet.giaddr, 0,
- sizeof ip -> client -> packet.giaddr);
- memcpy (ip -> client -> packet.chaddr,
- ip -> hw_address.haddr, ip -> hw_address.hlen);
+ memset (&client -> packet.ciaddr, 0,
+ sizeof client -> packet.ciaddr);
+ memset (&client -> packet.yiaddr, 0,
+ sizeof client -> packet.yiaddr);
+ memset (&client -> packet.siaddr, 0,
+ sizeof client -> packet.siaddr);
+ client -> packet.giaddr = giaddr;
+ memcpy (client -> packet.chaddr,
+ &client -> interface -> hw_address.hbuf [1],
+ client -> interface -> hw_address.hlen);
#ifdef DEBUG_PACKET
- dump_packet (sendpkt);
- dump_raw ((unsigned char *)ip -> client -> packet, sendpkt->packet_length);
+ dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
#endif
}
-void make_release (ip, lease)
- struct interface_info *ip;
+void make_release (client, lease)
+ struct client_state *client;
struct client_lease *lease;
{
unsigned char request = DHCPRELEASE;
int i;
+ struct option_cache *oc;
+
+ struct option_state *options = (struct option_state *)0;
- struct tree_cache *options [256];
- struct tree_cache message_type_tree;
- struct tree_cache server_id_tree;
-
- memset (options, 0, sizeof options);
- memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet));
-
- /* Set DHCP_MESSAGE_TYPE to DHCPRELEASE */
- i = DHO_DHCP_MESSAGE_TYPE;
- options [i] = &message_type_tree;
- options [i] -> value = &request;
- options [i] -> len = sizeof request;
- options [i] -> buf_size = sizeof request;
- options [i] -> timeout = 0xFFFFFFFF;
- options [i] -> tree = (struct tree *)0;
-
- /* Send back the server identifier... */
- i = DHO_DHCP_SERVER_IDENTIFIER;
- options [i] = &server_id_tree;
- options [i] -> value = lease -> options [i].data;
- options [i] -> len = lease -> options [i].len;
- options [i] -> buf_size = lease -> options [i].len;
- options [i] -> timeout = 0xFFFFFFFF;
- options [i] -> tree = (struct tree *)0;
+ memset (&client -> packet, 0, sizeof (client -> packet));
+
+ oc = lookup_option (&dhcp_universe, lease -> options,
+ DHO_DHCP_SERVER_IDENTIFIER);
+ make_client_options (client, lease, &request, oc,
+ (struct iaddr *)0, (u_int32_t *)0,
+ &options);
/* Set up the option buffer... */
- ip -> client -> packet_length =
- cons_options ((struct packet *)0, &ip -> client -> packet, 0,
- options, 0, 0, 0, (u_int8_t *)0, 0);
- if (ip -> client -> packet_length < BOOTP_MIN_LEN)
- ip -> client -> packet_length = BOOTP_MIN_LEN;
-
- ip -> client -> packet.op = BOOTREQUEST;
- ip -> client -> packet.htype = ip -> hw_address.htype;
- ip -> client -> packet.hlen = ip -> hw_address.hlen;
- ip -> client -> packet.hops = 0;
- ip -> client -> packet.xid = random ();
- ip -> client -> packet.secs = 0;
- ip -> client -> packet.flags = 0;
-
- memset (&ip -> client -> packet.ciaddr, 0,
- sizeof ip -> client -> packet.ciaddr);
- memset (&ip -> client -> packet.yiaddr, 0,
- sizeof ip -> client -> packet.yiaddr);
- memset (&ip -> client -> packet.siaddr, 0,
- sizeof ip -> client -> packet.siaddr);
- memset (&ip -> client -> packet.giaddr, 0,
- sizeof ip -> client -> packet.giaddr);
- memcpy (ip -> client -> packet.chaddr,
- ip -> hw_address.haddr, ip -> hw_address.hlen);
+ client -> packet_length =
+ cons_options ((struct packet *)0, &client -> packet,
+ (struct lease *)0, client, 0,
+ (struct option_state *)0, options,
+ &global_scope, 0, 0, 0, (struct data_string *)0,
+ client -> config -> vendor_space_name);
+ if (client -> packet_length < BOOTP_MIN_LEN)
+ client -> packet_length = BOOTP_MIN_LEN;
+ option_state_dereference (&options, MDL);
+
+ client -> packet.op = BOOTREQUEST;
+ client -> packet.htype = client -> interface -> hw_address.hbuf [0];
+ client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
+ client -> packet.hops = 0;
+ client -> packet.xid = random ();
+ client -> packet.secs = 0;
+ client -> packet.flags = 0;
+ memcpy (&client -> packet.ciaddr,
+ lease -> address.iabuf, lease -> address.len);
+ memset (&client -> packet.yiaddr, 0,
+ sizeof client -> packet.yiaddr);
+ memset (&client -> packet.siaddr, 0,
+ sizeof client -> packet.siaddr);
+ client -> packet.giaddr = giaddr;
+ memcpy (client -> packet.chaddr,
+ &client -> interface -> hw_address.hbuf [1],
+ client -> interface -> hw_address.hlen);
#ifdef DEBUG_PACKET
- dump_packet (sendpkt);
- dump_raw ((unsigned char *)ip -> client -> packet,
- ip -> client -> packet_length);
+ dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
#endif
}
-void free_client_lease (lease)
+void destroy_client_lease (lease)
struct client_lease *lease;
{
int i;
if (lease -> server_name)
- free (lease -> server_name);
+ dfree (lease -> server_name, MDL);
if (lease -> filename)
- free (lease -> filename);
- for (i = 0; i < 256; i++) {
- if (lease -> options [i].len)
- free (lease -> options [i].data);
- }
- free (lease);
+ dfree (lease -> filename, MDL);
+ option_state_dereference (&lease -> options, MDL);
+ free_client_lease (lease, MDL);
}
FILE *leaseFile;
@@ -1784,44 +2105,92 @@ FILE *leaseFile;
void rewrite_client_leases ()
{
struct interface_info *ip;
+ struct client_state *client;
struct client_lease *lp;
if (leaseFile)
fclose (leaseFile);
leaseFile = fopen (path_dhclient_db, "w");
- if (!leaseFile)
- error ("can't create %s: %m", path_dhclient_db);
+ if (!leaseFile) {
+ log_error ("can't create %s: %m", path_dhclient_db);
+ return;
+ }
/* Write out all the leases attached to configured interfaces that
we know about. */
for (ip = interfaces; ip; ip = ip -> next) {
- for (lp = ip -> client -> leases; lp; lp = lp -> next) {
- write_client_lease (ip, lp, 1);
+ for (client = ip -> client; client; client = client -> next) {
+ for (lp = client -> leases; lp; lp = lp -> next) {
+ write_client_lease (client, lp, 1, 0);
+ }
+ if (client -> active)
+ write_client_lease (client,
+ client -> active, 1, 0);
}
- if (ip -> client -> active)
- write_client_lease (ip, ip -> client -> active, 1);
}
/* Write out any leases that are attached to interfaces that aren't
currently configured. */
for (ip = dummy_interfaces; ip; ip = ip -> next) {
- for (lp = ip -> client -> leases; lp; lp = lp -> next) {
- write_client_lease (ip, lp, 1);
+ for (client = ip -> client; client; client = client -> next) {
+ for (lp = client -> leases; lp; lp = lp -> next) {
+ write_client_lease (client, lp, 1, 0);
+ }
+ if (client -> active)
+ write_client_lease (client,
+ client -> active, 1, 0);
}
- if (ip -> client -> active)
- write_client_lease (ip, ip -> client -> active, 1);
}
fflush (leaseFile);
}
-void write_client_lease (ip, lease, rewrite)
- struct interface_info *ip;
+void write_lease_option (struct option_cache *oc,
+ struct packet *packet, struct lease *lease,
+ struct client_state *client_state,
+ struct option_state *in_options,
+ struct option_state *cfg_options,
+ struct binding_scope **scope,
+ struct universe *u, void *stuff)
+{
+ const char *name, *dot;
+ struct data_string ds;
+ int status;
+ struct client_state *client;
+
+ memset (&ds, 0, sizeof ds);
+
+ if (u != &dhcp_universe) {
+ name = u -> name;
+ dot = ".";
+ } else {
+ name = "";
+ dot = "";
+ }
+ if (evaluate_option_cache (&ds, packet, lease, client_state,
+ in_options, cfg_options, scope, oc, MDL)) {
+ fprintf (leaseFile,
+ " option %s%s%s %s;\n",
+ name, dot, oc -> option -> name,
+ pretty_print_option (oc -> option,
+ ds.data, ds.len, 1, 1));
+ data_string_forget (&ds, MDL);
+ }
+}
+
+int write_client_lease (client, lease, rewrite, makesure)
+ struct client_state *client;
struct client_lease *lease;
int rewrite;
+ int makesure;
{
int i;
struct tm *t;
static int leases_written;
+ struct option_cache *oc;
+ struct data_string ds;
+ pair *hash;
+ int errors = 0;
+ char *s;
if (!rewrite) {
if (leases_written++ > 20) {
@@ -1833,38 +2202,94 @@ void write_client_lease (ip, lease, rewrite)
/* If the lease came from the config file, we don't need to stash
a copy in the lease database. */
if (lease -> is_static)
- return;
+ return 1;
if (!leaseFile) { /* XXX */
leaseFile = fopen (path_dhclient_db, "w");
- if (!leaseFile)
- error ("can't create %s: %m", path_dhclient_db);
+ if (!leaseFile) {
+ log_error ("can't create %s: %m", path_dhclient_db);
+ return 0;
+ }
}
+ errno = 0;
fprintf (leaseFile, "lease {\n");
- if (lease -> is_bootp)
+ if (lease -> is_bootp) {
fprintf (leaseFile, " bootp;\n");
- fprintf (leaseFile, " interface \"%s\";\n", ip -> name);
+ if (errno) {
+ ++errors;
+ errno = 0;
+ }
+ }
+ fprintf (leaseFile, " interface \"%s\";\n",
+ client -> interface -> name);
+ if (errno) {
+ ++errors;
+ errno = 0;
+ }
+ if (client -> name) {
+ fprintf (leaseFile, " name \"%s\";\n", client -> name);
+ if (errno) {
+ ++errors;
+ errno = 0;
+ }
+ }
fprintf (leaseFile, " fixed-address %s;\n",
piaddr (lease -> address));
- if (lease -> filename)
- fprintf (leaseFile, " filename \"%s\";\n",
- lease -> filename);
- if (lease -> server_name)
- fprintf (leaseFile, " server-name \"%s\";\n",
- lease -> server_name);
- if (lease -> medium)
- fprintf (leaseFile, " medium \"%s\";\n",
- lease -> medium -> string);
- for (i = 0; i < 256; i++) {
- if (lease -> options [i].len) {
- fprintf (leaseFile,
- " option %s %s;\n",
- dhcp_options [i].name,
- pretty_print_option
- (i, lease -> options [i].data,
- lease -> options [i].len, 1, 1));
- }
+ if (errno) {
+ ++errors;
+ errno = 0;
+ }
+ if (lease -> filename) {
+ s = quotify_string (lease -> filename, MDL);
+ if (s) {
+ fprintf (leaseFile, " filename \"%s\";\n", s);
+ if (errno) {
+ ++errors;
+ errno = 0;
+ }
+ dfree (s, MDL);
+ } else
+ errors++;
+
+ }
+ if (lease -> server_name) {
+ s = quotify_string (lease -> filename, MDL);
+ if (s) {
+ fprintf (leaseFile, " server-name \"%s\";\n", s);
+ if (errno) {
+ ++errors;
+ errno = 0;
+ }
+ dfree (s, MDL);
+ } else
+ ++errors;
+ }
+ if (lease -> medium) {
+ s = quotify_string (lease -> medium -> string, MDL);
+ if (s) {
+ fprintf (leaseFile, " medium \"%s\";\n", s);
+ if (errno) {
+ ++errors;
+ errno = 0;
+ }
+ dfree (s, MDL);
+ } else
+ errors++;
+ }
+ if (errno != 0) {
+ errors++;
+ errno = 0;
+ }
+
+ memset (&ds, 0, sizeof ds);
+
+ for (i = 0; i < lease -> options -> universe_count; i++) {
+ option_space_foreach ((struct packet *)0, (struct lease *)0,
+ client, (struct option_state *)0,
+ lease -> options, &global_scope,
+ universes [i],
+ client, write_lease_option);
}
/* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
@@ -1876,20 +2301,47 @@ void write_client_lease (ip, lease, rewrite)
t -> tm_wday, t -> tm_year + 1900,
t -> tm_mon + 1, t -> tm_mday,
t -> tm_hour, t -> tm_min, t -> tm_sec);
+ if (errno != 0) {
+ errors++;
+ errno = 0;
+ }
t = gmtime (&lease -> rebind);
fprintf (leaseFile,
" rebind %d %d/%d/%d %02d:%02d:%02d;\n",
t -> tm_wday, t -> tm_year + 1900,
t -> tm_mon + 1, t -> tm_mday,
t -> tm_hour, t -> tm_min, t -> tm_sec);
+ if (errno != 0) {
+ errors++;
+ errno = 0;
+ }
t = gmtime (&lease -> expiry);
fprintf (leaseFile,
" expire %d %d/%d/%d %02d:%02d:%02d;\n",
t -> tm_wday, t -> tm_year + 1900,
t -> tm_mon + 1, t -> tm_mday,
t -> tm_hour, t -> tm_min, t -> tm_sec);
+ if (errno != 0) {
+ errors++;
+ errno = 0;
+ }
fprintf (leaseFile, "}\n");
+ if (errno != 0) {
+ errors++;
+ errno = 0;
+ }
fflush (leaseFile);
+ if (errno != 0) {
+ errors++;
+ errno = 0;
+ }
+ if (!errors && makesure) {
+ if (fsync (fileno (leaseFile)) < 0) {
+ log_info ("write_client_lease: %m");
+ return 0;
+ }
+ }
+ return errors ? 0 : 1;
}
/* Variables holding name of script and file pointer for writing to
@@ -1898,41 +2350,88 @@ void write_client_lease (ip, lease, rewrite)
char scriptName [256];
FILE *scriptFile;
-void script_init (ip, reason, medium)
- struct interface_info *ip;
- char *reason;
+void script_init (client, reason, medium)
+ struct client_state *client;
+ const char *reason;
struct string_list *medium;
{
struct string_list *sl, *next;
- if (ip) {
- for (sl = ip -> client -> env; sl; sl = next) {
+ if (client) {
+ for (sl = client -> env; sl; sl = next) {
next = sl -> next;
- dfree (sl, "script_init");
+ dfree (sl, MDL);
}
- ip -> client -> env = (struct string_list *)0;
- ip -> client -> envc = 0;
+ client -> env = (struct string_list *)0;
+ client -> envc = 0;
- client_envadd (ip -> client, "", "interface", "%s",
- ip -> name);
+ if (client -> interface) {
+ client_envadd (client, "", "interface", "%s",
+ client -> interface -> name);
+ }
+ if (client -> name)
+ client_envadd (client,
+ "", "client", "%s", client -> name);
if (medium)
- client_envadd (ip -> client,
+ client_envadd (client,
"", "medium", "%s", medium -> string);
- client_envadd (ip -> client, "", "reason", "%s", reason);
+ client_envadd (client, "", "reason", "%s", reason);
+ client_envadd (client, "", "pid", "%ld", (long int)getpid ());
}
}
-void script_write_params (ip, prefix, lease)
- struct interface_info *ip;
- char *prefix;
+struct envadd_state {
+ struct client_state *client;
+ const char *prefix;
+};
+
+void client_option_envadd (struct option_cache *oc,
+ struct packet *packet, struct lease *lease,
+ struct client_state *client_state,
+ struct option_state *in_options,
+ struct option_state *cfg_options,
+ struct binding_scope **scope,
+ struct universe *u, void *stuff)
+{
+ struct envadd_state *es = stuff;
+ struct data_string data;
+ memset (&data, 0, sizeof data);
+
+ if (evaluate_option_cache (&data, packet, lease, client_state,
+ in_options, cfg_options, scope, oc, MDL)) {
+ if (data.len) {
+ char name [256];
+ if (dhcp_option_ev_name (name, sizeof name,
+ oc -> option)) {
+ client_envadd (es -> client, es -> prefix,
+ name, "%s",
+ (pretty_print_option
+ (oc -> option,
+ data.data, data.len,
+ 0, 0)));
+ data_string_forget (&data, MDL);
+ }
+ }
+ }
+}
+
+void script_write_params (client, prefix, lease)
+ struct client_state *client;
+ const char *prefix;
struct client_lease *lease;
{
int i;
- u_int8_t dbuf [1500];
- int len;
+ struct data_string data;
+ struct option_cache *oc;
+ pair *hash;
+ char *s, *t;
+ struct envadd_state es;
- client_envadd (ip -> client,
+ es.client = client;
+ es.prefix = prefix;
+
+ client_envadd (client,
prefix, "ip_address", "%s", piaddr (lease -> address));
/* For the benefit of Linux (and operating systems which may
@@ -1942,125 +2441,66 @@ void script_write_params (ip, prefix, lease)
broadcast address, not the host address all zeroes
broadcast address). */
- if (lease -> options [DHO_SUBNET_MASK].len &&
- (lease -> options [DHO_SUBNET_MASK].len <
- sizeof lease -> address.iabuf)) {
- struct iaddr netmask, subnet, broadcast;
-
- memcpy (netmask.iabuf,
- lease -> options [DHO_SUBNET_MASK].data,
- lease -> options [DHO_SUBNET_MASK].len);
- netmask.len = lease -> options [DHO_SUBNET_MASK].len;
-
- subnet = subnet_number (lease -> address, netmask);
- if (subnet.len) {
- client_envadd (ip -> client, prefix, "network_number",
- "%s", piaddr (subnet));
-
- if (!lease -> options [DHO_BROADCAST_ADDRESS].len) {
+ memset (&data, 0, sizeof data);
+ oc = lookup_option (&dhcp_universe, lease -> options, DHO_SUBNET_MASK);
+ if (oc && evaluate_option_cache (&data, (struct packet *)0,
+ (struct lease *)0, client,
+ (struct option_state *)0,
+ lease -> options,
+ &global_scope, oc, MDL)) {
+ if (data.len > 3) {
+ struct iaddr netmask, subnet, broadcast;
+
+ memcpy (netmask.iabuf, data.data, data.len);
+ netmask.len = data.len;
+ data_string_forget (&data, MDL);
+
+ subnet = subnet_number (lease -> address, netmask);
+ if (subnet.len) {
+ client_envadd (client, prefix, "network_number",
+ "%s", piaddr (subnet));
+
+ oc = lookup_option (&dhcp_universe,
+ lease -> options,
+ DHO_BROADCAST_ADDRESS);
+ if (!oc ||
+ !(evaluate_option_cache
+ (&data, (struct packet *)0,
+ (struct lease *)0, client,
+ (struct option_state *)0,
+ lease -> options,
+ &global_scope, oc, MDL))) {
broadcast = broadcast_addr (subnet, netmask);
if (broadcast.len) {
- client_envadd (ip -> client,
+ client_envadd (client,
prefix, "broadcast_address",
"%s", piaddr (broadcast));
}
+ }
}
}
+ data_string_forget (&data, MDL);
}
if (lease -> filename)
- client_envadd (ip -> client,
+ client_envadd (client,
prefix, "filename", "%s", lease -> filename);
if (lease -> server_name)
- client_envadd (ip -> client, prefix, "server_name",
+ client_envadd (client, prefix, "server_name",
"%s", lease -> server_name);
- for (i = 0; i < 256; i++) {
- u_int8_t *dp;
-
- if (ip -> client -> config -> defaults [i].len) {
- if (lease -> options [i].len) {
- switch (ip -> client ->
- config -> default_actions [i]) {
- case ACTION_DEFAULT:
- dp = lease -> options [i].data;
- len = lease -> options [i].len;
- break;
- case ACTION_SUPERSEDE:
- supersede:
- dp = ip -> client ->
- config -> defaults [i].data;
- len = ip -> client ->
- config -> defaults [i].len;
- break;
- case ACTION_PREPEND:
- len = (ip -> client ->
- config -> defaults [i].len +
- lease -> options [i].len);
- if (len > sizeof dbuf) {
- warn ("no space to %s %s",
- "prepend option",
- dhcp_options [i].name);
- goto supersede;
- }
- dp = dbuf;
- memcpy (dp,
- ip -> client ->
- config -> defaults [i].data,
- ip -> client ->
- config -> defaults [i].len);
- memcpy (dp + ip -> client ->
- config -> defaults [i].len,
- lease -> options [i].data,
- lease -> options [i].len);
- break;
- case ACTION_APPEND:
- len = (ip -> client ->
- config -> defaults [i].len +
- lease -> options [i].len);
- if (len > sizeof dbuf) {
- warn ("no space to %s %s",
- "append option",
- dhcp_options [i].name);
- goto supersede;
- }
- dp = dbuf;
- memcpy (dp,
- lease -> options [i].data,
- lease -> options [i].len);
- memcpy (dp + lease -> options [i].len,
- ip -> client ->
- config -> defaults [i].data,
- ip -> client ->
- config -> defaults [i].len);
- }
- } else {
- dp = ip -> client ->
- config -> defaults [i].data;
- len = ip -> client ->
- config -> defaults [i].len;
- }
- } else if (lease -> options [i].len) {
- len = lease -> options [i].len;
- dp = lease -> options [i].data;
- } else {
- len = 0;
- }
- if (len) {
- char name [256];
- if (dhcp_option_ev_name (name, sizeof name,
- &dhcp_options [i])) {
- client_envadd (ip -> client, prefix, name, "%s",
- (pretty_print_option (i, dp,
- len, 0, 0)));
- }
- }
+
+ for (i = 0; i < lease -> options -> universe_count; i++) {
+ option_space_foreach ((struct packet *)0, (struct lease *)0,
+ client, (struct option_state *)0,
+ lease -> options, &global_scope,
+ universes [i],
+ &es, client_option_envadd);
}
- client_envadd (ip -> client,
- prefix, "expiry", "%d", (int)(lease -> expiry));
+ client_envadd (client, prefix, "expiry", "%d", (int)(lease -> expiry));
}
-int script_go (ip)
- struct interface_info *ip;
+int script_go (client)
+ struct client_state *client;
{
int rval;
char *scriptName;
@@ -2073,59 +2513,68 @@ int script_go (ip)
struct string_list *sp, *next;
int pid, wpid, wstatus;
- if (ip) {
- scriptName = ip -> client -> config -> script_name;
- envp = dmalloc ((ip -> client -> envc + 2) * sizeof (char *),
- "script_go");
- if (!envp) {
- error ("No memory for client script environment.");
- return 0;
- }
- i = 0;
- for (sp = ip -> client -> env; sp; sp = sp -> next) {
+ if (client)
+ scriptName = client -> config -> script_name;
+ else
+ scriptName = top_level_config.script_name;
+
+ envp = dmalloc (((client ? client -> envc : 2) +
+ client_env_count + 2) * sizeof (char *), MDL);
+ if (!envp) {
+ log_error ("No memory for client script environment.");
+ return 0;
+ }
+ i = 0;
+ /* Copy out the environment specified on the command line,
+ if any. */
+ for (sp = client_env; sp; sp = sp -> next) {
+ envp [i++] = sp -> string;
+ }
+ /* Copy out the environment specified by dhclient. */
+ if (client) {
+ for (sp = client -> env; sp; sp = sp -> next) {
envp [i++] = sp -> string;
}
- envp [i++] = client_path;
- envp [i] = (char *)0;
} else {
- scriptName = top_level_config.script_name;
- epp [0] = reason;
- epp [1] = client_path;
- epp [2] = (char *)0;
- envp = epp;
+ envp [i++] = reason;
}
+ /* Set $PATH. */
+ envp [i++] = client_path;
+ envp [i] = (char *)0;
argv [0] = scriptName;
argv [1] = (char *)0;
pid = fork ();
if (pid < 0) {
- error ("fork: %m");
+ log_error ("fork: %m");
wstatus = 0;
} else if (pid) {
do {
wpid = wait (&wstatus);
} while (wpid != pid && wpid > 0);
if (wpid < 0) {
- error ("wait: %m");
+ log_error ("wait: %m");
wstatus = 0;
}
} else {
execve (scriptName, argv, envp);
- error ("execve (%s, ...): %m", scriptName);
+ log_error ("execve (%s, ...): %m", scriptName);
exit (0);
}
- if (ip) {
- for (sp = ip -> client -> env; sp; sp = next) {
+ if (client) {
+ for (sp = client -> env; sp; sp = next) {
next = sp -> next;
- dfree (sp, "script_go");
+ dfree (sp, MDL);
}
- ip -> client -> env = (struct string_list *)0;
- ip -> client -> envc = 0;
- dfree (envp, "script_go");
+ client -> env = (struct string_list *)0;
+ client -> envc = 0;
}
- return wstatus & 0xff;
+ dfree (envp, MDL);
+ GET_TIME (&cur_time);
+ return (WIFEXITED (wstatus) ?
+ WEXITSTATUS (wstatus) : -WTERMSIG (wstatus));
}
void client_envadd (struct client_state *client,
@@ -2142,7 +2591,7 @@ void client_envadd (struct client_state *client,
va_end (list);
val = dmalloc (strlen (prefix) + strlen (name) + 1 /* = */ +
- len + sizeof *val, "client_envadd");
+ len + sizeof *val, MDL);
if (!val)
return;
s = val -> string;
@@ -2166,25 +2615,46 @@ int dhcp_option_ev_name (buf, buflen, option)
size_t buflen;
struct option *option;
{
- int i;
+ int i, j;
+ const char *s;
- for (i = 0; option -> name [i]; i++) {
- if (i + 1 == buflen)
- return 0;
- if (option -> name [i] == '-')
- buf [i] = '_';
- else
- buf [i] = option -> name [i];
+ j = 0;
+ if (option -> universe != &dhcp_universe) {
+ s = option -> universe -> name;
+ i = 0;
+ } else {
+ s = option -> name;
+ i = 1;
}
- buf [i] = 0;
+ do {
+ while (*s) {
+ if (j + 1 == buflen)
+ return 0;
+ if (*s == '-')
+ buf [j++] = '_';
+ else
+ buf [j++] = *s;
+ ++s;
+ }
+ if (!i) {
+ s = option -> name;
+ if (j + 1 == buflen)
+ return 0;
+ buf [j++] = '_';
+ }
+ ++i;
+ } while (i != 2);
+
+ buf [j] = 0;
return 1;
}
-
+
void go_daemon ()
{
static int state = 0;
int pid;
+ int i;
/* Don't become a daemon if the user requested otherwise. */
if (no_daemon) {
@@ -2202,7 +2672,7 @@ void go_daemon ()
/* Become a daemon... */
if ((pid = fork ()) < 0)
- error ("Can't fork daemon: %m");
+ log_fatal ("Can't fork daemon: %m");
else if (pid)
exit (0);
/* Become session leader and get pid... */
@@ -2213,6 +2683,16 @@ void go_daemon ()
close(1);
close(2);
+ /* Reopen them on /dev/null. */
+ i = open ("/dev/null", O_RDWR);
+ if (i == 0)
+ i = open ("/dev/null", O_RDWR);
+ if (i == 1) {
+ i = open ("/dev/null", O_RDWR);
+ log_perror = 0; /* No sense logging to /dev/null. */
+ } else if (i != -1)
+ close (i);
+
write_client_pid_file ();
}
@@ -2224,15 +2704,384 @@ void write_client_pid_file ()
pfdesc = open (path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY, 0644);
if (pfdesc < 0) {
- warn ("Can't create %s: %m", path_dhclient_pid);
+ log_error ("Can't create %s: %m", path_dhclient_pid);
return;
}
pf = fdopen (pfdesc, "w");
if (!pf)
- warn ("Can't fdopen %s: %m", path_dhclient_pid);
+ log_error ("Can't fdopen %s: %m", path_dhclient_pid);
else {
fprintf (pf, "%ld\n", (long)getpid ());
fclose (pf);
}
}
+
+void client_location_changed ()
+{
+ struct interface_info *ip;
+ struct client_state *client;
+
+ for (ip = interfaces; ip; ip = ip -> next) {
+ for (client = ip -> client; client; client = client -> next) {
+ switch (client -> state) {
+ case S_SELECTING:
+ cancel_timeout (send_discover, client);
+ break;
+
+ case S_BOUND:
+ cancel_timeout (state_bound, client);
+ break;
+
+ case S_REBOOTING:
+ case S_REQUESTING:
+ case S_RENEWING:
+ cancel_timeout (send_request, client);
+ break;
+
+ case S_INIT:
+ case S_REBINDING:
+ case S_STOPPED:
+ break;
+ }
+ client -> state = S_INIT;
+ state_reboot (client);
+ }
+ }
+}
+
+void do_release(client)
+ struct client_state *client;
+{
+ struct data_string ds;
+ struct option_cache *oc;
+
+ /* Pick a random xid. */
+ client -> xid = random ();
+
+ /* is there even a lease to release? */
+ if (client -> active) {
+ /* Make a DHCPRELEASE packet, and set appropriate per-interface
+ flags. */
+ make_release (client, client -> active);
+
+ memset (&ds, 0, sizeof ds);
+ oc = lookup_option (&dhcp_universe,
+ client -> active -> options,
+ DHO_DHCP_SERVER_IDENTIFIER);
+ if (oc &&
+ evaluate_option_cache (&ds, (struct packet *)0,
+ (struct lease *)0, client,
+ (struct option_state *)0,
+ client -> active -> options,
+ &global_scope, oc, MDL)) {
+ if (ds.len > 3) {
+ memcpy (client -> destination.iabuf,
+ ds.data, 4);
+ client -> destination.len = 4;
+ } else
+ client -> destination = iaddr_broadcast;
+ } else
+ client -> destination = iaddr_broadcast;
+ client -> first_sending = cur_time;
+ client -> interval = client -> config -> initial_interval;
+
+ /* Zap the medium list... */
+ client -> medium = (struct string_list *)0;
+
+ /* Send out the first and only DHCPRELEASE packet. */
+ send_release (client);
+
+ /* Do the client script RELEASE operation. */
+ script_init (client,
+ "RELEASE", (struct string_list *)0);
+ if (client -> alias)
+ script_write_params (client, "alias_",
+ client -> alias);
+ script_write_params (client, "old_", client -> active);
+ script_go (client);
+ }
+
+ /* Cancel any timeouts. */
+ cancel_timeout (state_bound, client);
+ cancel_timeout (send_discover, client);
+ cancel_timeout (state_init, client);
+ cancel_timeout (send_request, client);
+ cancel_timeout (state_reboot, client);
+ client -> state = S_STOPPED;
+}
+
+int dhclient_interface_shutdown_hook (struct interface_info *interface)
+{
+ do_release (interface -> client);
+
+ return 1;
+}
+
+int dhclient_interface_discovery_hook (struct interface_info *tmp)
+{
+ struct interface_info *last, *ip;
+ /* See if we can find the client from dummy_interfaces */
+ last = 0;
+ for (ip = dummy_interfaces; ip; ip = ip -> next) {
+ if (!strcmp (ip -> name, tmp -> name)) {
+ /* Remove from dummy_interfaces */
+ if (last) {
+ ip = (struct interface_info *)0;
+ interface_reference (&ip, last -> next, MDL);
+ interface_dereference (&last -> next, MDL);
+ if (ip -> next) {
+ interface_reference (&last -> next,
+ ip -> next, MDL);
+ interface_dereference (&ip -> next,
+ MDL);
+ }
+ } else {
+ ip = (struct interface_info *)0;
+ interface_reference (&ip,
+ dummy_interfaces, MDL);
+ interface_dereference (&dummy_interfaces, MDL);
+ if (ip -> next) {
+ interface_reference (&dummy_interfaces,
+ ip -> next, MDL);
+ interface_dereference (&ip -> next,
+ MDL);
+ }
+ }
+ /* Copy "client" to tmp */
+ if (ip -> client) {
+ tmp -> client = ip -> client;
+ tmp -> client -> interface = tmp;
+ }
+ interface_dereference (&ip, MDL);
+ break;
+ }
+ last = ip;
+ }
+ return 1;
+}
+
+isc_result_t dhclient_interface_startup_hook (struct interface_info *interface)
+{
+ struct interface_info *ip;
+ struct client_state *client;
+
+ /* This code needs some rethinking. It doesn't test against
+ a signal name, and it just kind of bulls into doing something
+ that may or may not be appropriate. */
+
+ if (interfaces) {
+ interface_reference (&interface -> next, interfaces, MDL);
+ interface_dereference (&interfaces, MDL);
+ }
+ interface_reference (&interfaces, interface, MDL);
+
+ discover_interfaces (DISCOVER_UNCONFIGURED);
+
+ for (ip = interfaces; ip; ip = ip -> next) {
+ /* If interfaces were specified, don't configure
+ interfaces that weren't specified! */
+ if (ip -> flags & INTERFACE_RUNNING ||
+ (ip -> flags & (INTERFACE_REQUESTED |
+ INTERFACE_AUTOMATIC)) !=
+ INTERFACE_REQUESTED)
+ continue;
+ script_init (ip -> client,
+ "PREINIT", (struct string_list *)0);
+ if (ip -> client -> alias)
+ script_write_params (ip -> client, "alias_",
+ ip -> client -> alias);
+ script_go (ip -> client);
+ }
+
+ discover_interfaces (interfaces_requested
+ ? DISCOVER_REQUESTED
+ : DISCOVER_RUNNING);
+
+ for (ip = interfaces; ip; ip = ip -> next) {
+ if (ip -> flags & INTERFACE_RUNNING)
+ continue;
+ ip -> flags |= INTERFACE_RUNNING;
+ for (client = ip -> client; client; client = client -> next) {
+ client -> state = S_INIT;
+ /* Set up a timeout to start the initialization
+ process. */
+ add_timeout (cur_time + random () % 5,
+ state_reboot, client, 0, 0);
+ }
+ }
+ return ISC_R_SUCCESS;
+}
+
+/* The client should never receive a relay agent information option,
+ so if it does, log it and discard it. */
+
+int parse_agent_information_option (packet, len, data)
+ struct packet *packet;
+ int len;
+ u_int8_t *data;
+{
+ return 1;
+}
+
+/* The client never sends relay agent information options. */
+
+unsigned cons_agent_information_options (cfg_options, outpacket,
+ agentix, length)
+ struct option_state *cfg_options;
+ struct dhcp_packet *outpacket;
+ unsigned agentix;
+ unsigned length;
+{
+ return length;
+}
+
+static void shutdown_exit (void *foo)
+{
+ exit (0);
+}
+
+isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
+ control_object_state_t newstate)
+{
+ struct interface_info *ip;
+ struct client_state *client;
+
+ /* Do the right thing for each interface. */
+ for (ip = interfaces; ip; ip = ip -> next) {
+ for (client = ip -> client; client; client = client -> next) {
+ switch (newstate) {
+ case server_startup:
+ return ISC_R_SUCCESS;
+
+ case server_running:
+ return ISC_R_SUCCESS;
+
+ case server_shutdown:
+ if (client -> active &&
+ client -> active -> expiry > cur_time) {
+ client_dns_update (client, 0);
+ do_release (client);
+ }
+ break;
+
+ case server_hibernate:
+ state_stop (client);
+ break;
+
+ case server_awaken:
+ state_reboot (client);
+ break;
+ }
+ }
+ }
+ if (newstate == server_shutdown)
+ add_timeout (cur_time + 1, shutdown_exit, 0, 0, 0);
+ return ISC_R_SUCCESS;
+}
+
+/* See if we should do a DNS update, and if so, do it. */
+
+void client_dns_update (struct client_state *client, int addp)
+{
+ struct data_string ddns_fqdn, ddns_fwd_name,
+ ddns_dhcid, client_identifier;
+ struct option_cache *oc;
+ int ignorep;
+ int result;
+ isc_result_t rcode;
+
+ /* If we didn't send an FQDN option, we certainly aren't going to
+ be doing an update. */
+ if (!client -> sent_options)
+ return;
+
+ /* If we don't have a lease, we can't do an update. */
+ if (!client -> active)
+ return;
+
+ /* If we set the no client update flag, don't do the update. */
+ if ((oc = lookup_option (&fqdn_universe, client -> sent_options,
+ FQDN_NO_CLIENT_UPDATE)) &&
+ evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
+ (struct lease *)0, client,
+ client -> sent_options,
+ (struct option_state *)0,
+ &global_scope, oc, MDL))
+ return;
+
+ /* If we set the "server, please update" flag, or didn't set it
+ to false, don't do the update. */
+ if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
+ FQDN_SERVER_UPDATE)) ||
+ evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
+ (struct lease *)0, client,
+ client -> sent_options,
+ (struct option_state *)0,
+ &global_scope, oc, MDL))
+ return;
+
+ /* If no FQDN option was supplied, don't do the update. */
+ memset (&ddns_fwd_name, 0, sizeof ddns_fwd_name);
+ if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
+ FQDN_FQDN)) ||
+ !evaluate_option_cache (&ddns_fwd_name, (struct packet *)0,
+ (struct lease *)0, client,
+ client -> sent_options,
+ (struct option_state *)0,
+ &global_scope, oc, MDL))
+ return;
+
+ /* Make a dhcid string out of either the client identifier,
+ if we are sending one, or the interface's MAC address,
+ otherwise. */
+ memset (&ddns_dhcid, 0, sizeof ddns_dhcid);
+
+ memset (&client_identifier, 0, sizeof client_identifier);
+ if ((oc = lookup_option (&dhcp_universe, client -> sent_options,
+ DHO_DHCP_CLIENT_IDENTIFIER)) &&
+ evaluate_option_cache (&client_identifier, (struct packet *)0,
+ (struct lease *)0, client,
+ client -> sent_options,
+ (struct option_state *)0,
+ &global_scope, oc, MDL)) {
+ result = get_dhcid (&ddns_dhcid,
+ DHO_DHCP_CLIENT_IDENTIFIER,
+ client_identifier.data,
+ client_identifier.len);
+ data_string_forget (&client_identifier, MDL);
+ } else
+ result = get_dhcid (&ddns_dhcid, 0,
+ client -> interface -> hw_address.hbuf,
+ client -> interface -> hw_address.hlen);
+ if (!result) {
+ data_string_forget (&ddns_fwd_name, MDL);
+ return;
+ }
+
+ /* Start the resolver, if necessary. */
+ if (!resolver_inited) {
+ minires_ninit (&resolver_state);
+ resolver_inited = 1;
+ resolver_state.retrans = 1;
+ resolver_state.retry = 1;
+ }
+
+ /*
+ * Perform updates.
+ */
+ if (ddns_fwd_name.len && ddns_dhcid.len) {
+ if (addp)
+ rcode = ddns_update_a (&ddns_fwd_name,
+ client -> active -> address,
+ &ddns_dhcid, DEFAULT_DDNS_TTL,
+ 1);
+ else
+ rcode = ddns_remove_a (&ddns_fwd_name,
+ client -> active -> address,
+ &ddns_dhcid);
+ }
+
+ data_string_forget (&ddns_fwd_name, MDL);
+ data_string_forget (&ddns_dhcid, MDL);
+}
diff --git a/contrib/isc-dhcp/client/dhclient.conf.5 b/contrib/isc-dhcp/client/dhclient.conf.5
index 691908193e00..ecdd4eb6dbc2 100644
--- a/contrib/isc-dhcp/client/dhclient.conf.5
+++ b/contrib/isc-dhcp/client/dhclient.conf.5
@@ -1,8 +1,6 @@
.\" dhclient.conf.5
.\"
-.\" Copyright (c) 1997 The Internet Software Consortium.
-.\" All rights reserved.
-.\"
+.\" Copyright (c) 1996-2001 Internet Software Consortium.
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
@@ -31,10 +29,11 @@
.\" SUCH DAMAGE.
.\"
.\" This software has been written for the Internet Software Consortium
-.\" by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
-.\" Enterprises. To learn more about the Internet Software Consortium,
-.\" see ``http://www.isc.org/isc''. To learn more about Vixie
-.\" Enterprises, see ``http://www.vix.com''.
+.\" by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
+.\" To learn more about the Internet Software Consortium, see
+.\" ``http://www.isc.org/''. To learn more about Vixie Enterprises,
+.\" see ``http://www.vix.com''. To learn more about Nominum, Inc., see
+.\" ``http://www.nominum.com''.
.TH dhclient.conf 5
.SH NAME
dhclient.conf - DHCP client configuration file
@@ -190,7 +189,17 @@ are called \fIDHCP Options\fR. DHCP Options are defined in
The request statement causes the client to request that any server
responding to the client send the client its values for the specified
options. Only the option names should be specified in the request
-statement - not option parameters.
+statement - not option parameters. By default, the DHCP server
+requests the subnet-mask, broadcast-address, time-offset, routers,
+domain-name, domain-name-servers and host-name options.
+.PP
+In some cases, it may be desirable to send no parameter request list
+at all. To do this, simply write the request statement but specify
+no parameters:
+.PP
+.nf
+ request;
+.fi
.PP
.I The
.B require
@@ -218,6 +227,26 @@ than the default requested lease time, which is two hours. The other
obvious use for this statement is to send information to the server
that will allow it to differentiate between this client and other
clients or kinds of clients.
+.SH DYNAMIC DNS
+The client now has some very limited support for doing DNS updates
+when a lease is acquired. This is prototypical, and probably doesn't
+do what you want. It also only works if you happen to have control
+over your DNS server, which isn't very likely.
+.PP
+To make it work, you have to declare a key and zone as in the DHCP
+server (see \fBdhcpd.conf\fR(5) for details). You also need to
+configure the fqdn option on the client, as follows:
+.PP
+.nf
+ send fqdn.fqdn "grosse.fugue.com.";
+ send fqdn.encoded on;
+ send fqdn.server-update off;
+.fi
+.PP
+The \fIfqdn.fqdn\fR option \fBMUST\fR be a fully-qualified domain
+name. You \fBMUST\fR define a zone statement for the zone to be
+updated. The \fIfqdn.encoded\fR option may need to be set to
+\fIon\fR or \fIoff\fR, depending on the DHCP server you are using.
.SH OPTION MODIFIERS
In some cases, a client may receive option data from the server which
is not really appropriate for that client, or may not receive
@@ -230,10 +259,9 @@ needs, several option modifiers are available.
.B default
.I statement
.PP
- \fBdefault { [ \fIoption declaration\fR ]
-[\fB,\fI ... \fIoption declaration\fR ]\fB}\fR
+ \fBdefault [ \fIoption declaration\fR ] \fB;\fR
.PP
-If for some set of options the client should use the value supplied by
+If for some option the client should use the value supplied by
the server, but needs to use some default value if no value was supplied
by the server, these values can be defined in the
.B default
@@ -243,12 +271,11 @@ statement.
.B supersede
.I statement
.PP
- \fBsupersede { [ \fIoption declaration\fR ]
-[\fB,\fI ... \fIoption declaration\fR ]\fB}\fR
+ \fBsupersede [ \fIoption declaration\fR ] \fB;\fR
.PP
-If for some set of options the client should always use its own value
-rather than any value supplied by the server, these values can be
-defined in the
+If for some option the client should always use a locally-configured
+value or values rather than whatever is supplied by the server, these
+values can be defined in the
.B supersede
statement.
.PP
@@ -256,8 +283,7 @@ statement.
.B prepend
.I statement
.PP
- \fBprepend { [ \fIoption declaration\fR ]
-[\fB,\fI ... \fIoption declaration\fR ]\fB}\fR
+ \fBprepend [ \fIoption declaration\fR ] \fB;\fR
.PP
If for some set of options the client should use a value you
supply, and then use the values supplied by
@@ -267,14 +293,13 @@ statement. The
.B prepend
statement can only be used for options which
allow more than one value to be given. This restriction is not
-enforced - if violated, the results are unpredictable.
+enforced - if you ignore it, the behaviour will be unpredictable.
.PP
.I The
.B append
.I statement
.PP
- \fBappend { [ \fIoption declaration\fR ]
-[\fB,\fI ... \fIoption declaration\fR ]\fB}\fR
+ \fBappend [ \fIoption declaration\fR ] \fB;\fR
.PP
If for some set of options the client should first use the values
supplied by the server, if any, and then use values you supply, these
@@ -380,7 +405,18 @@ interface's final configuration once a lease has been acquired. If
no lease is acquired, the script is used to test predefined leases, if
any, and also called once if no valid lease can be identified. For
more information, see
-.B dhclient-lease(8).
+.B dhclient-script(8).
+.PP
+ \fBvendor option space "\fIname\fB";\fR
+.PP
+The
+.B vendor option space
+statement is used to specify which option space should be used for
+decoding the vendor-encapsulate-options option if one is received.
+The \fIdhcp-vendor-identifier\fR can be used to request a specific
+class of vendor options from the server. See
+.B dhcp-options(5)
+for details.
.PP
\fBmedium "\fImedia setup\fB";\fR
.PP
@@ -432,8 +468,8 @@ specified as zero. The year is specified with the century, so it
should generally be four digits except for really long leases. The
month is specified as a number starting with 1 for January. The day
of the month is likewise specified starting with 1. The hour is a
-number between 0 and 23, the minute a number between 0 and 69, and the
-second also a number between 0 and 69.
+number between 0 and 23, the minute a number between 0 and 59, and the
+second also a number between 0 and 59.
.SH ALIAS DECLARATIONS
\fBalias { \fI declarations ... \fB}\fR
.PP
@@ -474,6 +510,36 @@ specified name. Interfaces for which there is no interface
declaration will use the parameters declared outside of any interface
declaration, or the default settings.
.PP
+ \fBpseudo "\fIname\fR" "\fIreal-name\fB" { \fIdeclarations ... \fB }
+.PP
+Under some circumstances it can be useful to declare a pseudo-interface
+and have the DHCP client acquire a configuration for that interface.
+Each interface that the DHCP client is supporting normally has a DHCP
+client state machine running on it to acquire and maintain its lease.
+A pseudo-interface is just another state machine running on the
+interface named \fIreal-name\fR, with its own lease and its own
+state. If you use this feature, you must provide a client identifier
+for both the pseudo-interface and the actual interface, and the two
+identifiers must be different. You must also provide a seperate
+client script for the pseudo-interface to do what you want with the IP
+address. For example:
+.PP
+.nf
+ interface "ep0" {
+ send dhcp-client-identifier "my-client-ep0";
+ }
+ pseudo "secondary" "ep0" {
+ send dhcp-client-identifier "my-client-ep0-secondary";
+ script "/etc/dhclient-secondary";
+ }
+.fi
+.PP
+The client script for the pseudo-interface should not configure the
+interface up or down - essentially, all it needs to handle are the
+states where a lease has been acquired or renewed, and the states
+where a lease has expired. See \fBdhclient-script(8)\fR for more
+information.
+.PP
\fBmedia "\fImedia setup\fB"\fI [ \fB, "\fImedia setup\fB", \fI... ]\fB;\fR
.PP
The
@@ -538,8 +604,8 @@ dhcp-options(5), dhclient.leases(5), dhcpd(8), dhcpd.conf(5), RFC2132,
RFC2131.
.SH AUTHOR
.B dhclient(8)
-was written by Ted Lemon <mellon@vix.com>
+was written by Ted Lemon
under a contract with Vixie Labs. Funding
-for this project was provided by the Internet Software Corporation.
+for this project was provided by the Internet Software Consortium.
Information about the Internet Software Consortium can be found at
-.B http://www.isc.org/isc.
+.B http://www.isc.org.
diff --git a/contrib/isc-dhcp/client/dhclient.leases.5 b/contrib/isc-dhcp/client/dhclient.leases.5
index e0da360524a8..5f1418e8058f 100644
--- a/contrib/isc-dhcp/client/dhclient.leases.5
+++ b/contrib/isc-dhcp/client/dhclient.leases.5
@@ -31,7 +31,7 @@
.\" SUCH DAMAGE.
.\"
.\" This software has been written for the Internet Software Consortium
-.\" by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+.\" by Ted Lemon in cooperation with Vixie
.\" Enterprises. To learn more about the Internet Software Consortium,
.\" see ``http://www.isc.org/isc''. To learn more about Vixie
.\" Enterprises, see ``http://www.vix.com''.
@@ -55,8 +55,8 @@ dhclient(8), dhcp-options(5), dhclient.conf(5), dhcpd(8),
dhcpd.conf(5), RFC2132, RFC2131.
.SH AUTHOR
.B dhclient(8)
-was written by Ted Lemon <mellon@vix.com>
+was written by Ted Lemon
under a contract with Vixie Labs. Funding
-for this project was provided by the Internet Software Corporation.
+for this project was provided by the Internet Software Consortium.
Information about the Internet Software Consortium can be found at
-.B http://www.isc.org/isc.
+.B http://www.isc.org.
diff --git a/contrib/isc-dhcp/client/scripts/freebsd b/contrib/isc-dhcp/client/scripts/freebsd
index ce7a1bf25fbb..652d0d0683d6 100755
--- a/contrib/isc-dhcp/client/scripts/freebsd
+++ b/contrib/isc-dhcp/client/scripts/freebsd
@@ -1,16 +1,24 @@
#!/bin/sh
+if [ -x /usr/bin/logger ]; then
+ LOGGER="/usr/bin/logger -s -p user.notice -t dhclient"
+else
+ LOGGER=echo
+fi
+
make_resolv_conf() {
- echo search $new_domain_name >/etc/resolv.conf
- for nameserver in $new_domain_name_servers; do
- echo nameserver $nameserver >>/etc/resolv.conf
- done
+ if [ "x$new_domain_name" != x ] && [ x"$new_domain_name_servers" != x ]; then
+ echo search $new_domain_name >/etc/resolv.conf
+ for nameserver in $new_domain_name_servers; do
+ echo nameserver $nameserver >>/etc/resolv.conf
+ done
+ fi
}
# Must be used on exit. Invokes the local dhcp client exit hooks, if any.
exit_with_hooks() {
exit_status=$1
- if [ -x /etc/dhclient-exit-hooks ]; then
+ if [ -f /etc/dhclient-exit-hooks ]; then
. /etc/dhclient-exit-hooks
fi
# probably should do something with exit status of the local script
@@ -18,7 +26,7 @@ exit_with_hooks() {
}
# Invoke the local dhcp client enter hooks, if they exist.
-if [ -x /etc/dhclient-enter-hooks ]; then
+if [ -f /etc/dhclient-enter-hooks ]; then
exit_status=0
. /etc/dhclient-enter-hooks
# allow the local script to abort processing of this state
@@ -29,11 +37,11 @@ if [ -x /etc/dhclient-enter-hooks ]; then
fi
if [ x$new_network_number != x ]; then
- echo New Network Number: $new_network_number
+ $LOGGER New Network Number: $new_network_number
fi
if [ x$new_broadcast_address != x ]; then
- echo New Broadcast Address: $new_broadcast_address
+ $LOGGER New Broadcast Address: $new_broadcast_address
new_broadcast_arg="broadcast $new_broadcast_address"
fi
if [ x$old_broadcast_address != x ]; then
@@ -50,8 +58,8 @@ if [ x$alias_subnet_mask != x ]; then
fi
if [ x$reason = xMEDIUM ]; then
- ifconfig $interface $medium
- ifconfig $interface inet -alias 0.0.0.0 $medium >/dev/null 2>&1
+ eval "ifconfig $interface $medium"
+ eval "ifconfig $interface inet -alias 0.0.0.0 $medium" >/dev/null 2>&1
sleep 1
exit_with_hooks 0
fi
@@ -72,36 +80,53 @@ fi
if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \
[ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then
+ current_hostname=`hostname`
+ if [ x$current_hostname = x ] || \
+ [ x$current_hostname = x$old_host_name ]; then
+ if [ x$current_hostname = x ] || \
+ [ x$new_host_name != x$old_host_name ]; then
+ $LOGGER "New Hostname: $new_host_name"
+ hostname $new_host_name
+ fi
+ fi
if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \
[ x$alias_ip_address != x$old_ip_address ]; then
ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
fi
- if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]; then
- ifconfig $interface inet -alias $old_ip_address $medium
+ if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]
+ then
+ eval "ifconfig $interface inet -alias $old_ip_address $medium"
route delete $old_ip_address 127.1 >/dev/null 2>&1
for router in $old_routers; do
route delete default $router >/dev/null 2>&1
done
if [ "$old_static_routes" != "" ]; then
- set $old_static_routes
+ set -- $old_static_routes
while [ $# -gt 1 ]; do
route delete $1 $2
shift; shift
done
fi
- arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' |sh
+ arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -d \1/p' |sh
fi
if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \
[ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then
- ifconfig $interface inet $new_ip_address $new_netmask_arg \
- $new_broadcast_arg $medium
+ eval "ifconfig $interface inet $new_ip_address $new_netmask_arg \
+ $new_broadcast_arg $medium"
+ $LOGGER "New IP Address($interface): $new_ip_address"
+ $LOGGER "New Subnet Mask($interface): $new_subnet_mask"
+ $LOGGER "New Broadcast Address($interface): $new_broadcast_address"
+ if [ "$new_routers" != "" ]; then
+ $LOGGER "New Routers: $new_routers"
+ fi
route add $new_ip_address 127.1 >/dev/null 2>&1
for router in $new_routers; do
route add default $router >/dev/null 2>&1
done
if [ "$new_static_routes" != "" ]; then
- set $new_static_routes
+ $LOGGER "New Static Routes: $new_static_routes"
+ set -- $new_static_routes
while [ $# -gt 1 ]; do
route add $1 $2
shift; shift
@@ -113,26 +138,24 @@ if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \
ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg
route add $alias_ip_address 127.0.0.1
fi
- echo search $new_domain_name >/etc/resolv.conf
- for nameserver in $new_domain_name_servers; do
- echo nameserver $nameserver >>/etc/resolv.conf
- done
+ make_resolv_conf
exit_with_hooks 0
fi
-if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ]; then
+if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ] || [ x$reason = xRELEASE ] \
+ || [ x$reason = xSTOP ]; then
if [ x$alias_ip_address != x ]; then
ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
fi
if [ x$old_ip_address != x ]; then
- ifconfig $interface inet -alias $old_ip_address $medium
+ eval "ifconfig $interface inet -alias $old_ip_address $medium"
route delete $old_ip_address 127.1 >/dev/null 2>&1
for router in $old_routers; do
route delete default $router >/dev/null 2>&1
done
if [ "$old_static_routes" != "" ]; then
- set $old_static_routes
+ set -- $old_static_routes
while [ $# -gt 1 ]; do
route delete $1 $2
shift; shift
@@ -153,11 +176,15 @@ if [ x$reason = xTIMEOUT ]; then
ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
fi
- ifconfig $interface inet $new_ip_address $new_netmask_arg \
- $new_broadcast_arg $medium
+ eval "ifconfig $interface inet $new_ip_address $new_netmask_arg \
+ $new_broadcast_arg $medium"
+ $LOGGER "New IP Address($interface): $new_ip_address"
+ $LOGGER "New Subnet Mask($interface): $new_subnet_mask"
+ $LOGGER "New Broadcast Address($interface): $new_broadcast_address"
sleep 1
if [ "$new_routers" != "" ]; then
- set $new_routers
+ $LOGGER "New Routers: $new_routers"
+ set -- $new_routers
if ping -q -c 1 $1; then
if [ x$new_ip_address != x$alias_ip_address ] && \
[ x$alias_ip_address != x ]; then
@@ -168,34 +195,27 @@ if [ x$reason = xTIMEOUT ]; then
for router in $new_routers; do
route add default $router >/dev/null 2>&1
done
- set $new_static_routes
+ set -- $new_static_routes
while [ $# -gt 1 ]; do
- route add $0 $1
+ route add $1 $2
shift; shift
done
- echo search $new_domain_name >/etc/resolv.conf.std
- for nameserver in $new_domain_name_servers; do
- echo nameserver $nameserver >>/etc/resolv.conf.std
- done
- if [ -f /etc/resolv.conf ]; then
- rm -f /etc/resolv.conf
- fi
- mv /etc/resolv.conf.std /etc/resolv.conf
+ make_resolv_conf
exit_with_hooks 0
fi
fi
- ifconfig $interface inet -alias $new_ip_address $medium
+ eval "ifconfig $interface inet -alias $new_ip_address $medium"
for router in $old_routers; do
route delete default $router >/dev/null 2>&1
done
if [ "$old_static_routes" != "" ]; then
- set $old_static_routes
+ set -- $old_static_routes
while [ $# -gt 1 ]; do
route delete $1 $2
shift; shift
done
fi
- arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' \
+ arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -d \1/p' \
|sh >/dev/null 2>&1
exit_with_hooks 1
fi
diff --git a/contrib/isc-dhcp/common/Makefile.dist b/contrib/isc-dhcp/common/Makefile.dist
index 1e3e062cd775..3efa1205071a 100644
--- a/contrib/isc-dhcp/common/Makefile.dist
+++ b/contrib/isc-dhcp/common/Makefile.dist
@@ -1,49 +1,18 @@
# Makefile.dist
-#
-# Copyright (c) 1996, 1999 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.
-#
-CATMANPAGES = dhcp-options.cat5
-SEDMANPAGES = dhcp-options.man5
+CATMANPAGES = dhcp-options.cat5 dhcp-eval.cat5
+SEDMANPAGES = dhcp-options.man5 dhcp-eval.man5
SRC = raw.c parse.c nit.c icmp.c dispatch.c conflex.c upf.c bpf.c socket.c \
- lpf.c packet.c memory.c print.c options.c inet.c convert.c \
- tree.c tables.c hash.c alloc.c errwarn.c inet_addr.c dlpi.c \
- tr.c ethernet.c
+ lpf.c dlpi.c packet.c tr.c ethernet.c memory.c print.c options.c \
+ inet.c tree.c tables.c alloc.c fddi.c ctrace.c \
+ dns.c resolv.c execute.c discover.c comapi.c
OBJ = raw.o parse.o nit.o icmp.o dispatch.o conflex.o upf.o bpf.o socket.o \
- lpf.o packet.o memory.o print.o options.o inet.o convert.o \
- tree.o tables.o hash.o alloc.o errwarn.o inet_addr.o dlpi.o \
- tr.o ethernet.o
-MAN = dhcp-options.5
+ lpf.o dlpi.o packet.o tr.o ethernet.o memory.o print.o options.o \
+ inet.o tree.o tables.o alloc.o fddi.o ctrace.o \
+ dns.o resolv.o execute.o discover.o comapi.o
+MAN = dhcp-options.5 dhcp-eval.5
-DEBUG = -g
-INCLUDES = -I.. -I../includes
+INCLUDES = -I$(TOP) $(BINDINC) -I$(TOP)/includes
CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS)
all: libdhcp.a $(CATMANPAGES)
@@ -51,7 +20,7 @@ all: libdhcp.a $(CATMANPAGES)
libdhcp.a: $(OBJ)
rm -f libdhcp.a
ar cruv libdhcp.a $(OBJ)
- ranlib libdhcp.a
+ $(RANLIB) libdhcp.a
install: all
for dir in $(FFMANDIR); do \
@@ -66,17 +35,29 @@ install: all
done
$(MANINSTALL) $(MANFROM) dhcp-options.$(MANCAT)5 $(MANTO) \
$(DESTDIR)$(FFMANDIR)/dhcp-options$(FFMANEXT)
+ $(MANINSTALL) $(MANFROM) dhcp-eval.$(MANCAT)5 $(MANTO) \
+ $(DESTDIR)$(FFMANDIR)/dhcp-eval$(FFMANEXT)
+depend:
+ $(MKDEP) $(INCLUDES) $(PREDEFINES) $(SRC)
clean:
-rm -f $(OBJ)
-
+
realclean: clean
- -rm -f libdhcp.a *~ #* $(CATMANPAGES) $(SEDMANPAGES)
+ -rm -f libdhcp.a $(CATMANPAGES) $(SEDMANPAGES) *~ #*
distclean: realclean
-rm -f Makefile
+links:
+ @for foo in $(SRC) $(MAN); do \
+ if [ ! -b $$foo ]; then \
+ rm -f $$foo; \
+ fi; \
+ ln -s $(TOP)/common/$$foo $$foo; \
+ done
+
dhcp-options.cat5: dhcp-options.man5
nroff -man dhcp-options.man5 >dhcp-options.cat5
@@ -84,123 +65,11 @@ dhcp-options.man5: dhcp-options.5
sed -e "s#ETCDIR#$(ETC)#g" -e "s#DBDIR#$(VARDB)#g" \
-e "s#RUNDIR#$(VARRUN)#g" < dhcp-options.5 >dhcp-options.man5
-# Dependencies (semi-automatically-generated)
+dhcp-eval.cat5: dhcp-eval.man5
+ nroff -man dhcp-eval.man5 >dhcp-eval.cat5
-raw.o: raw.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h
-parse.o: parse.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h \
- ../includes/dhcp.h ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h ../includes/dhctoken.h
-nit.o: nit.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h
-icmp.o: icmp.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h ../includes/netinet/ip.h \
- ../includes/netinet/ip_icmp.h
-dispatch.o: dispatch.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h \
- conflex.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h ../includes/dhctoken.h
-upf.o: upf.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h
-bpf.o: bpf.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h ../includes/netinet/ip.h ../includes/netinet/udp.h \
- ../includes/netinet/if_ether.h
-socket.o: socket.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h
-lpf.o: lpf.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h
-packet.o: packet.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h ../includes/netinet/ip.h \
- ../includes/netinet/udp.h ../includes/netinet/if_ether.h
-memory.o: memory.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h
-print.o: print.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h
-options.o: options.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h
-inet.o: inet.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h
-convert.o: convert.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h
-tree.o: tree.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h
-tables.o: tables.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h
-hash.o: hash.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h
-alloc.o: alloc.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h
-errwarn.o: errwarn.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h
-inet_addr.o: inet_addr.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h
-dlpi.o: dlpi.c ../includes/dhcpd.h \
- ../includes/cdefs.h ../includes/osdep.h ../includes/site.h \
- ../includes/cf/netbsd.h ../includes/dhcp.h \
- ../includes/tree.h ../includes/hash.h ../includes/inet.h \
- ../includes/sysconf.h
+dhcp-eval.man5: dhcp-eval.5
+ sed -e "s#ETCDIR#$(ETC)#g" -e "s#DBDIR#$(VARDB)#g" \
+ -e "s#RUNDIR#$(VARRUN)#g" < dhcp-eval.5 >dhcp-eval.man5
+
+# Dependencies (semi-automatically-generated)
diff --git a/contrib/isc-dhcp/common/alloc.c b/contrib/isc-dhcp/common/alloc.c
index 61d7572626ab..5ed0204e596c 100644
--- a/contrib/isc-dhcp/common/alloc.c
+++ b/contrib/isc-dhcp/common/alloc.c
@@ -3,7 +3,7 @@
Memory allocation... */
/*
- * Copyright (c) 1995, 1996, 1998 The Internet Software Consortium.
+ * Copyright (c) 1996-2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,299 +34,1293 @@
* SUCH DAMAGE.
*
* This software has been written for the Internet Software Consortium
- * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
- * Enterprises. To learn more about the Internet Software Consortium,
- * see ``http://www.vix.com/isc''. To learn more about Vixie
- * Enterprises, see ``http://www.vix.com''.
+ * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
+ * To learn more about the Internet Software Consortium, see
+ * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
+ * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
+ * ``http://www.nominum.com''.
*/
#ifndef lint
static char copyright[] =
-"$Id: alloc.c,v 1.13.2.2 1999/03/26 16:39:36 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
+"$Id: alloc.c,v 1.53.2.8 2001/10/18 20:30:02 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
+#include <omapip/omapip_p.h>
struct dhcp_packet *dhcp_free_list;
struct packet *packet_free_list;
-VOIDPTR dmalloc (size, name)
+int option_chain_head_allocate (ptr, file, line)
+ struct option_chain_head **ptr;
+ const char *file;
+ int line;
+{
int size;
- char *name;
+ struct option_chain_head *h;
+
+ if (!ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+ if (*ptr) {
+ log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ *ptr = (struct option_chain_head *)0;
+#endif
+ }
+
+ h = dmalloc (sizeof *h, file, line);
+ if (h) {
+ memset (h, 0, sizeof *h);
+ return option_chain_head_reference (ptr, h, file, line);
+ }
+ return 0;
+}
+
+int option_chain_head_reference (ptr, bp, file, line)
+ struct option_chain_head **ptr;
+ struct option_chain_head *bp;
+ const char *file;
+ int line;
{
- VOIDPTR foo = (VOIDPTR)malloc (size);
- if (!foo)
- warn ("No memory for %s.", name);
- else
- memset (foo, 0, size);
- return foo;
+ if (!ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+ if (*ptr) {
+ log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ *ptr = (struct option_chain_head *)0;
+#endif
+ }
+ *ptr = bp;
+ bp -> refcnt++;
+ rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC);
+ return 1;
+}
+
+int option_chain_head_dereference (ptr, file, line)
+ struct option_chain_head **ptr;
+ const char *file;
+ int line;
+{
+ int i;
+ struct option_chain_head *option_chain_head;
+ pair car, cdr;
+
+ if (!ptr || !*ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+
+ option_chain_head = *ptr;
+ *ptr = (struct option_chain_head *)0;
+ --option_chain_head -> refcnt;
+ rc_register (file, line, ptr, option_chain_head,
+ option_chain_head -> refcnt, 1, RC_MISC);
+ if (option_chain_head -> refcnt > 0)
+ return 1;
+
+ if (option_chain_head -> refcnt < 0) {
+ log_error ("%s(%d): negative refcnt!", file, line);
+#if defined (DEBUG_RC_HISTORY)
+ dump_rc_history (option_chain_head);
+#endif
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+
+ /* If there are any options on this head, free them. */
+ for (car = option_chain_head -> first; car; car = cdr) {
+ cdr = car -> cdr;
+ if (car -> car)
+ option_cache_dereference ((struct option_cache **)
+ (&car -> car), MDL);
+ dfree (car, MDL);
+ car = cdr;
+ }
+
+ dfree (option_chain_head, file, line);
+ return 1;
}
-void dfree (ptr, name)
- VOIDPTR ptr;
- char *name;
+int group_allocate (ptr, file, line)
+ struct group **ptr;
+ const char *file;
+ int line;
{
+ int size;
+ struct group *g;
+
if (!ptr) {
- warn ("dfree %s: free on null pointer.", name);
- return;
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+ if (*ptr) {
+ log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ *ptr = (struct group *)0;
+#endif
}
- free (ptr);
+
+ g = dmalloc (sizeof *g, file, line);
+ if (g) {
+ memset (g, 0, sizeof *g);
+ return group_reference (ptr, g, file, line);
+ }
+ return 0;
}
-struct packet *new_packet (name)
- char *name;
+int group_reference (ptr, bp, file, line)
+ struct group **ptr;
+ struct group *bp;
+ const char *file;
+ int line;
{
- struct packet *rval;
- rval = (struct packet *)dmalloc (sizeof (struct packet), name);
- return rval;
+ if (!ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+ if (*ptr) {
+ log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ *ptr = (struct group *)0;
+#endif
+ }
+ *ptr = bp;
+ bp -> refcnt++;
+ rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC);
+ return 1;
+}
+
+int group_dereference (ptr, file, line)
+ struct group **ptr;
+ const char *file;
+ int line;
+{
+ int i;
+ struct group *group;
+
+ if (!ptr || !*ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+
+ group = *ptr;
+ *ptr = (struct group *)0;
+ --group -> refcnt;
+ rc_register (file, line, ptr, group, group -> refcnt, 1, RC_MISC);
+ if (group -> refcnt > 0)
+ return 1;
+
+ if (group -> refcnt < 0) {
+ log_error ("%s(%d): negative refcnt!", file, line);
+#if defined (DEBUG_RC_HISTORY)
+ dump_rc_history (group);
+#endif
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+
+ if (group -> object)
+ group_object_dereference (&group -> object, file, line);
+ if (group -> subnet)
+ subnet_dereference (&group -> subnet, file, line);
+ if (group -> shared_network)
+ shared_network_dereference (&group -> shared_network,
+ file, line);
+ if (group -> statements)
+ executable_statement_dereference (&group -> statements,
+ file, line);
+ if (group -> next)
+ group_dereference (&group -> next, file, line);
+ dfree (group, file, line);
+ return 1;
}
-struct dhcp_packet *new_dhcp_packet (name)
- char *name;
+struct dhcp_packet *new_dhcp_packet (file, line)
+ const char *file;
+ int line;
{
struct dhcp_packet *rval;
rval = (struct dhcp_packet *)dmalloc (sizeof (struct dhcp_packet),
- name);
+ file, line);
+ return rval;
+}
+
+struct protocol *new_protocol (file, line)
+ const char *file;
+ int line;
+{
+ struct protocol *rval = dmalloc (sizeof (struct protocol), file, line);
+ return rval;
+}
+
+struct domain_search_list *new_domain_search_list (file, line)
+ const char *file;
+ int line;
+{
+ struct domain_search_list *rval =
+ dmalloc (sizeof (struct domain_search_list), file, line);
+ return rval;
+}
+
+struct name_server *new_name_server (file, line)
+ const char *file;
+ int line;
+{
+ struct name_server *rval =
+ dmalloc (sizeof (struct name_server), file, line);
+ return rval;
+}
+
+void free_name_server (ptr, file, line)
+ struct name_server *ptr;
+ const char *file;
+ int line;
+{
+ dfree ((VOIDPTR)ptr, file, line);
+}
+
+struct option *new_option (file, line)
+ const char *file;
+ int line;
+{
+ struct option *rval =
+ dmalloc (sizeof (struct option), file, line);
+ if (rval)
+ memset (rval, 0, sizeof *rval);
return rval;
}
-struct tree *new_tree (name)
- char *name;
+void free_option (ptr, file, line)
+ struct option *ptr;
+ const char *file;
+ int line;
+{
+/* XXX have to put all options on heap before this is possible. */
+#if 0
+ if (ptr -> name)
+ dfree ((VOIDPTR)option -> name, file, line);
+ dfree ((VOIDPTR)ptr, file, line);
+#endif
+}
+
+struct universe *new_universe (file, line)
+ const char *file;
+ int line;
{
- struct tree *rval = dmalloc (sizeof (struct tree), name);
+ struct universe *rval =
+ dmalloc (sizeof (struct universe), file, line);
return rval;
}
-struct tree_cache *free_tree_caches;
+void free_universe (ptr, file, line)
+ struct universe *ptr;
+ const char *file;
+ int line;
+{
+ dfree ((VOIDPTR)ptr, file, line);
+}
+
+void free_domain_search_list (ptr, file, line)
+ struct domain_search_list *ptr;
+ const char *file;
+ int line;
+{
+ dfree ((VOIDPTR)ptr, file, line);
+}
+
+void free_protocol (ptr, file, line)
+ struct protocol *ptr;
+ const char *file;
+ int line;
+{
+ dfree ((VOIDPTR)ptr, file, line);
+}
+
+void free_dhcp_packet (ptr, file, line)
+ struct dhcp_packet *ptr;
+ const char *file;
+ int line;
+{
+ dfree ((VOIDPTR)ptr, file, line);
+}
+
+struct client_lease *new_client_lease (file, line)
+ const char *file;
+ int line;
+{
+ return (struct client_lease *)dmalloc (sizeof (struct client_lease),
+ file, line);
+}
+
+void free_client_lease (lease, file, line)
+ struct client_lease *lease;
+ const char *file;
+ int line;
+{
+ dfree (lease, file, line);
+}
+
+pair free_pairs;
-struct tree_cache *new_tree_cache (name)
- char *name;
+pair new_pair (file, line)
+ const char *file;
+ int line;
{
- struct tree_cache *rval;
+ pair foo;
+
+ if (free_pairs) {
+ foo = free_pairs;
+ free_pairs = foo -> cdr;
+ memset (foo, 0, sizeof *foo);
+ dmalloc_reuse (foo, file, line, 0);
+ return foo;
+ }
+
+ foo = dmalloc (sizeof *foo, file, line);
+ if (!foo)
+ return foo;
+ memset (foo, 0, sizeof *foo);
+ return foo;
+}
- if (free_tree_caches) {
- rval = free_tree_caches;
- free_tree_caches =
- (struct tree_cache *)(rval -> value);
+void free_pair (foo, file, line)
+ pair foo;
+ const char *file;
+ int line;
+{
+ foo -> cdr = free_pairs;
+ free_pairs = foo;
+ dmalloc_reuse (free_pairs, (char *)0, 0, 0);
+}
+
+#if defined (DEBUG_MEMORY_LEAKAGE) || \
+ defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
+void relinquish_free_pairs ()
+{
+ pair pf, pc;
+
+ for (pf = free_pairs; pf; pf = pc) {
+ pc = pf -> cdr;
+ dfree (pf, MDL);
+ }
+ free_pairs = (pair)0;
+}
+#endif
+
+struct expression *free_expressions;
+
+int expression_allocate (cptr, file, line)
+ struct expression **cptr;
+ const char *file;
+ int line;
+{
+ struct expression *rval;
+
+ if (free_expressions) {
+ rval = free_expressions;
+ free_expressions = rval -> data.not;
+ dmalloc_reuse (rval, file, line, 1);
} else {
- rval = dmalloc (sizeof (struct tree_cache), name);
+ rval = dmalloc (sizeof (struct expression), file, line);
if (!rval)
- error ("unable to allocate tree cache for %s.", name);
+ return 0;
}
- return rval;
+ memset (rval, 0, sizeof *rval);
+ return expression_reference (cptr, rval, file, line);
}
-struct hash_table *new_hash_table (count, name)
- int count;
- char *name;
+int expression_reference (ptr, src, file, line)
+ struct expression **ptr;
+ struct expression *src;
+ const char *file;
+ int line;
{
- 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;
+ if (!ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+ if (*ptr) {
+ log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ *ptr = (struct expression *)0;
+#endif
+ }
+ *ptr = src;
+ src -> refcnt++;
+ rc_register (file, line, ptr, src, src -> refcnt, 0, RC_MISC);
+ return 1;
}
-struct hash_bucket *new_hash_bucket (name)
- char *name;
+void free_expression (expr, file, line)
+ struct expression *expr;
+ const char *file;
+ int line;
{
- struct hash_bucket *rval = dmalloc (sizeof (struct hash_bucket), name);
- return rval;
+ expr -> data.not = free_expressions;
+ free_expressions = expr;
+ dmalloc_reuse (free_expressions, (char *)0, 0, 0);
}
-struct lease *new_leases (n, name)
- int n;
- char *name;
+#if defined (DEBUG_MEMORY_LEAKAGE) || \
+ defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
+void relinquish_free_expressions ()
{
- struct lease *rval = dmalloc (n * sizeof (struct lease), name);
- return rval;
+ struct expression *e, *n;
+
+ for (e = free_expressions; e; e = n) {
+ n = e -> data.not;
+ dfree (e, MDL);
+ }
+ free_expressions = (struct expression *)0;
}
+#endif
-struct lease *new_lease (name)
- char *name;
+struct binding_value *free_binding_values;
+
+int binding_value_allocate (cptr, file, line)
+ struct binding_value **cptr;
+ const char *file;
+ int line;
{
- struct lease *rval = dmalloc (sizeof (struct lease), name);
- return rval;
+ struct binding_value *rval;
+
+ if (free_binding_values) {
+ rval = free_binding_values;
+ free_binding_values = rval -> value.bv;
+ dmalloc_reuse (rval, file, line, 1);
+ } else {
+ rval = dmalloc (sizeof (struct binding_value), file, line);
+ if (!rval)
+ return 0;
+ }
+ memset (rval, 0, sizeof *rval);
+ return binding_value_reference (cptr, rval, file, line);
}
-struct subnet *new_subnet (name)
- char *name;
+int binding_value_reference (ptr, src, file, line)
+ struct binding_value **ptr;
+ struct binding_value *src;
+ const char *file;
+ int line;
{
- struct subnet *rval = dmalloc (sizeof (struct subnet), name);
- return rval;
+ if (!ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+ if (*ptr) {
+ log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ *ptr = (struct binding_value *)0;
+#endif
+ }
+ *ptr = src;
+ src -> refcnt++;
+ rc_register (file, line, ptr, src, src -> refcnt, 0, RC_MISC);
+ return 1;
}
-struct class *new_class (name)
- char *name;
+void free_binding_value (bv, file, line)
+ struct binding_value *bv;
+ const char *file;
+ int line;
{
- struct class *rval = dmalloc (sizeof (struct class), name);
- return rval;
+ bv -> value.bv = free_binding_values;
+ free_binding_values = bv;
+ dmalloc_reuse (free_binding_values, (char *)0, 0, 0);
}
-struct shared_network *new_shared_network (name)
- char *name;
+#if defined (DEBUG_MEMORY_LEAKAGE) || \
+ defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
+void relinquish_free_binding_values ()
{
- struct shared_network *rval =
- dmalloc (sizeof (struct shared_network), name);
- return rval;
+ struct binding_value *b, *n;
+
+ for (b = free_binding_values; b; b = n) {
+ n = b -> value.bv;
+ dfree (b, MDL);
+ }
+ free_binding_values = (struct binding_value *)0;
}
+#endif
-struct group *new_group (name)
- char *name;
+int fundef_allocate (cptr, file, line)
+ struct fundef **cptr;
+ const char *file;
+ int line;
{
- struct group *rval =
- dmalloc (sizeof (struct group), name);
- return rval;
+ struct fundef *rval;
+
+ rval = dmalloc (sizeof (struct fundef), file, line);
+ if (!rval)
+ return 0;
+ memset (rval, 0, sizeof *rval);
+ return fundef_reference (cptr, rval, file, line);
}
-struct protocol *new_protocol (name)
- char *name;
+int fundef_reference (ptr, src, file, line)
+ struct fundef **ptr;
+ struct fundef *src;
+ const char *file;
+ int line;
{
- struct protocol *rval = dmalloc (sizeof (struct protocol), name);
- return rval;
+ if (!ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+ if (*ptr) {
+ log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ *ptr = (struct fundef *)0;
+#endif
+ }
+ *ptr = src;
+ src -> refcnt++;
+ rc_register (file, line, ptr, src, src -> refcnt, 0, RC_MISC);
+ return 1;
}
-struct lease_state *free_lease_states;
+struct option_cache *free_option_caches;
-struct lease_state *new_lease_state (name)
- char *name;
+#if defined (DEBUG_MEMORY_LEAKAGE) || \
+ defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
+void relinquish_free_option_caches ()
{
- struct lease_state *rval;
+ struct option_cache *o, *n;
- if (free_lease_states) {
- rval = free_lease_states;
- free_lease_states =
- (struct lease_state *)(free_lease_states -> next);
+ for (o = free_option_caches; o; o = n) {
+ n = (struct option_cache *)(o -> expression);
+ dfree (o, MDL);
+ }
+ free_option_caches = (struct option_cache *)0;
+}
+#endif
+
+int option_cache_allocate (cptr, file, line)
+ struct option_cache **cptr;
+ const char *file;
+ int line;
+{
+ struct option_cache *rval;
+
+ if (free_option_caches) {
+ rval = free_option_caches;
+ free_option_caches =
+ (struct option_cache *)(rval -> expression);
+ dmalloc_reuse (rval, file, line, 0);
} else {
- rval = dmalloc (sizeof (struct lease_state), name);
+ rval = dmalloc (sizeof (struct option_cache), file, line);
+ if (!rval)
+ return 0;
}
- return rval;
+ memset (rval, 0, sizeof *rval);
+ return option_cache_reference (cptr, rval, file, line);
}
-struct domain_search_list *new_domain_search_list (name)
- char *name;
+int option_cache_reference (ptr, src, file, line)
+ struct option_cache **ptr;
+ struct option_cache *src;
+ const char *file;
+ int line;
{
- struct domain_search_list *rval =
- dmalloc (sizeof (struct domain_search_list), name);
- return rval;
+ if (!ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+ if (*ptr) {
+ log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ *ptr = (struct option_cache *)0;
+#endif
+ }
+ *ptr = src;
+ src -> refcnt++;
+ rc_register (file, line, ptr, src, src -> refcnt, 0, RC_MISC);
+ return 1;
}
-struct name_server *new_name_server (name)
- char *name;
+int buffer_allocate (ptr, len, file, line)
+ struct buffer **ptr;
+ unsigned len;
+ const char *file;
+ int line;
{
- struct name_server *rval =
- dmalloc (sizeof (struct name_server), name);
- return rval;
+ struct buffer *bp;
+
+ bp = dmalloc (len + sizeof *bp, file, line);
+ if (!bp)
+ return 0;
+ memset (bp, 0, sizeof *bp);
+ bp -> refcnt = 0;
+ return buffer_reference (ptr, bp, file, line);
}
-void free_name_server (ptr, name)
- struct name_server *ptr;
- char *name;
+int buffer_reference (ptr, bp, file, line)
+ struct buffer **ptr;
+ struct buffer *bp;
+ const char *file;
+ int line;
{
- dfree ((VOIDPTR)ptr, name);
+ if (!ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+ if (*ptr) {
+ log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ *ptr = (struct buffer *)0;
+#endif
+ }
+ *ptr = bp;
+ bp -> refcnt++;
+ rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC);
+ return 1;
}
-void free_domain_search_list (ptr, name)
- struct domain_search_list *ptr;
- char *name;
+int buffer_dereference (ptr, file, line)
+ struct buffer **ptr;
+ const char *file;
+ int line;
{
- dfree ((VOIDPTR)ptr, name);
+ struct buffer *bp;
+
+ if (!ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+
+ if (!*ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+
+ (*ptr) -> refcnt--;
+ rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC);
+ if (!(*ptr) -> refcnt) {
+ dfree ((*ptr), file, line);
+ } else if ((*ptr) -> refcnt < 0) {
+ log_error ("%s(%d): negative refcnt!", file, line);
+#if defined (DEBUG_RC_HISTORY)
+ dump_rc_history (*ptr);
+#endif
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+ *ptr = (struct buffer *)0;
+ return 1;
}
-void free_lease_state (ptr, name)
- struct lease_state *ptr;
- char *name;
+int dns_host_entry_allocate (ptr, hostname, file, line)
+ struct dns_host_entry **ptr;
+ const char *hostname;
+ const char *file;
+ int line;
{
- if (ptr -> prl)
- dfree (ptr -> prl, name);
- ptr -> next = free_lease_states;
- free_lease_states = ptr;
+ struct dns_host_entry *bp;
+
+ bp = dmalloc (strlen (hostname) + sizeof *bp, file, line);
+ if (!bp)
+ return 0;
+ memset (bp, 0, sizeof *bp);
+ bp -> refcnt = 0;
+ strcpy (bp -> hostname, hostname);
+ return dns_host_entry_reference (ptr, bp, file, line);
}
-void free_protocol (ptr, name)
- struct protocol *ptr;
- char *name;
+int dns_host_entry_reference (ptr, bp, file, line)
+ struct dns_host_entry **ptr;
+ struct dns_host_entry *bp;
+ const char *file;
+ int line;
+{
+ if (!ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+ if (*ptr) {
+ log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ *ptr = (struct dns_host_entry *)0;
+#endif
+ }
+ *ptr = bp;
+ bp -> refcnt++;
+ rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC);
+ return 1;
+}
+
+int dns_host_entry_dereference (ptr, file, line)
+ struct dns_host_entry **ptr;
+ const char *file;
+ int line;
+{
+ struct dns_host_entry *bp;
+
+ if (!ptr || !*ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+
+ (*ptr) -> refcnt--;
+ rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC);
+ if (!(*ptr) -> refcnt)
+ dfree ((*ptr), file, line);
+ if ((*ptr) -> refcnt < 0) {
+ log_error ("%s(%d): negative refcnt!", file, line);
+#if defined (DEBUG_RC_HISTORY)
+ dump_rc_history (*ptr);
+#endif
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+ *ptr = (struct dns_host_entry *)0;
+ return 1;
+}
+
+int option_state_allocate (ptr, file, line)
+ struct option_state **ptr;
+ const char *file;
+ int line;
+{
+ unsigned size;
+
+ if (!ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+ if (*ptr) {
+ log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ *ptr = (struct option_state *)0;
+#endif
+ }
+
+ size = sizeof **ptr + (universe_count - 1) * sizeof (VOIDPTR);
+ *ptr = dmalloc (size, file, line);
+ if (*ptr) {
+ memset (*ptr, 0, size);
+ (*ptr) -> universe_count = universe_count;
+ (*ptr) -> refcnt = 1;
+ rc_register (file, line,
+ ptr, *ptr, (*ptr) -> refcnt, 0, RC_MISC);
+ return 1;
+ }
+ return 0;
+}
+
+int option_state_reference (ptr, bp, file, line)
+ struct option_state **ptr;
+ struct option_state *bp;
+ const char *file;
+ int line;
+{
+ if (!ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+ if (*ptr) {
+ log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ *ptr = (struct option_state *)0;
+#endif
+ }
+ *ptr = bp;
+ bp -> refcnt++;
+ rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC);
+ return 1;
+}
+
+int option_state_dereference (ptr, file, line)
+ struct option_state **ptr;
+ const char *file;
+ int line;
{
- dfree ((VOIDPTR)ptr, name);
+ int i;
+ struct option_state *options;
+
+ if (!ptr || !*ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+
+ options = *ptr;
+ *ptr = (struct option_state *)0;
+ --options -> refcnt;
+ rc_register (file, line, ptr, options, options -> refcnt, 1, RC_MISC);
+ if (options -> refcnt > 0)
+ return 1;
+
+ if (options -> refcnt < 0) {
+ log_error ("%s(%d): negative refcnt!", file, line);
+#if defined (DEBUG_RC_HISTORY)
+ dump_rc_history (options);
+#endif
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+
+ /* Loop through the per-universe state. */
+ for (i = 0; i < options -> universe_count; i++)
+ if (options -> universes [i] &&
+ universes [i] -> option_state_dereference)
+ ((*(universes [i] -> option_state_dereference))
+ (universes [i], options, file, line));
+ dfree (options, file, line);
+ return 1;
}
-void free_group (ptr, name)
- struct group *ptr;
- char *name;
+int executable_statement_allocate (ptr, file, line)
+ struct executable_statement **ptr;
+ const char *file;
+ int line;
{
- dfree ((VOIDPTR)ptr, name);
+ struct executable_statement *bp;
+
+ bp = dmalloc (sizeof *bp, file, line);
+ if (!bp)
+ return 0;
+ memset (bp, 0, sizeof *bp);
+ return executable_statement_reference (ptr, bp, file, line);
}
-void free_shared_network (ptr, name)
- struct shared_network *ptr;
- char *name;
+int executable_statement_reference (ptr, bp, file, line)
+ struct executable_statement **ptr;
+ struct executable_statement *bp;
+ const char *file;
+ int line;
{
- dfree ((VOIDPTR)ptr, name);
+ if (!ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+ if (*ptr) {
+ log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ *ptr = (struct executable_statement *)0;
+#endif
+ }
+ *ptr = bp;
+ bp -> refcnt++;
+ rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC);
+ return 1;
}
-void free_class (ptr, name)
- struct class *ptr;
- char *name;
+static struct packet *free_packets;
+
+#if defined (DEBUG_MEMORY_LEAKAGE) || \
+ defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
+void relinquish_free_packets ()
{
- dfree ((VOIDPTR)ptr, name);
+ struct packet *p, *n;
+ for (p = free_packets; p; p = n) {
+ n = (struct packet *)(p -> raw);
+ dfree (p, MDL);
+ }
+ free_packets = (struct packet *)0;
}
+#endif
-void free_subnet (ptr, name)
- struct subnet *ptr;
- char *name;
+int packet_allocate (ptr, file, line)
+ struct packet **ptr;
+ const char *file;
+ int line;
{
- dfree ((VOIDPTR)ptr, name);
+ int size;
+ struct packet *p;
+
+ if (!ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+ if (*ptr) {
+ log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ *ptr = (struct packet *)0;
+#endif
+ }
+
+ if (free_packets) {
+ p = free_packets;
+ free_packets = (struct packet *)(p -> raw);
+ dmalloc_reuse (p, file, line, 1);
+ } else {
+ p = dmalloc (sizeof *p, file, line);
+ }
+ if (p) {
+ memset (p, 0, sizeof *p);
+ return packet_reference (ptr, p, file, line);
+ }
+ return 0;
}
-void free_lease (ptr, name)
- struct lease *ptr;
- char *name;
+int packet_reference (ptr, bp, file, line)
+ struct packet **ptr;
+ struct packet *bp;
+ const char *file;
+ int line;
{
- dfree ((VOIDPTR)ptr, name);
+ if (!ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+ if (*ptr) {
+ log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ *ptr = (struct packet *)0;
+#endif
+ }
+ *ptr = bp;
+ bp -> refcnt++;
+ rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC);
+ return 1;
}
-void free_hash_bucket (ptr, name)
- struct hash_bucket *ptr;
- char *name;
+int packet_dereference (ptr, file, line)
+ struct packet **ptr;
+ const char *file;
+ int line;
{
- dfree ((VOIDPTR)ptr, name);
+ int i;
+ struct packet *packet;
+
+ if (!ptr || !*ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+
+ packet = *ptr;
+ *ptr = (struct packet *)0;
+ --packet -> refcnt;
+ rc_register (file, line, ptr, packet, packet -> refcnt, 1, RC_MISC);
+ if (packet -> refcnt > 0)
+ return 1;
+
+ if (packet -> refcnt < 0) {
+ log_error ("%s(%d): negative refcnt!", file, line);
+#if defined (DEBUG_RC_HISTORY)
+ dump_rc_history (packet);
+#endif
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+
+ if (packet -> options)
+ option_state_dereference (&packet -> options, file, line);
+ if (packet -> interface)
+ interface_dereference (&packet -> interface, MDL);
+ if (packet -> shared_network)
+ shared_network_dereference (&packet -> shared_network, MDL);
+ for (i = 0; i < packet -> class_count && i < PACKET_MAX_CLASSES; i++) {
+ if (packet -> classes [i])
+ omapi_object_dereference ((omapi_object_t **)
+ &packet -> classes [i], MDL);
+ }
+ packet -> raw = (struct dhcp_packet *)free_packets;
+ free_packets = packet;
+ dmalloc_reuse (free_packets, (char *)0, 0, 0);
+ return 1;
}
-void free_hash_table (ptr, name)
- struct hash_table *ptr;
- char *name;
+int dns_zone_allocate (ptr, file, line)
+ struct dns_zone **ptr;
+ const char *file;
+ int line;
{
- dfree ((VOIDPTR)ptr, name);
+ int size;
+ struct dns_zone *d;
+
+ if (!ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+ if (*ptr) {
+ log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ *ptr = (struct dns_zone *)0;
+#endif
+ }
+
+ d = dmalloc (sizeof *d, file, line);
+ if (d) {
+ memset (d, 0, sizeof *d);
+ return dns_zone_reference (ptr, d, file, line);
+ }
+ return 0;
}
-void free_tree_cache (ptr, name)
- struct tree_cache *ptr;
- char *name;
+int dns_zone_reference (ptr, bp, file, line)
+ struct dns_zone **ptr;
+ struct dns_zone *bp;
+ const char *file;
+ int line;
{
- ptr -> value = (unsigned char *)free_tree_caches;
- free_tree_caches = ptr;
+ if (!ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+ if (*ptr) {
+ log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ *ptr = (struct dns_zone *)0;
+#endif
+ }
+ *ptr = bp;
+ bp -> refcnt++;
+ rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC);
+ return 1;
}
-void free_packet (ptr, name)
- struct packet *ptr;
- char *name;
+int binding_scope_allocate (ptr, file, line)
+ struct binding_scope **ptr;
+ const char *file;
+ int line;
{
- dfree ((VOIDPTR)ptr, name);
+ struct binding_scope *bp;
+
+ if (!ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+
+ if (*ptr) {
+ log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+
+ bp = dmalloc (sizeof *bp, file, line);
+ if (!bp)
+ return 0;
+ memset (bp, 0, sizeof *bp);
+ binding_scope_reference (ptr, bp, file, line);
+ return 1;
}
-void free_dhcp_packet (ptr, name)
- struct dhcp_packet *ptr;
- char *name;
+int binding_scope_reference (ptr, bp, file, line)
+ struct binding_scope **ptr;
+ struct binding_scope *bp;
+ const char *file;
+ int line;
{
- dfree ((VOIDPTR)ptr, name);
+ if (!ptr) {
+ log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+ if (*ptr) {
+ log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ *ptr = (struct binding_scope *)0;
+#endif
+ }
+ *ptr = bp;
+ bp -> refcnt++;
+ rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC);
+ return 1;
}
-void free_tree (ptr, name)
- struct tree *ptr;
- char *name;
+/* Make a copy of the data in data_string, upping the buffer reference
+ count if there's a buffer. */
+
+void data_string_copy (dest, src, file, line)
+ struct data_string *dest;
+ struct data_string *src;
+ const char *file;
+ int line;
{
- dfree ((VOIDPTR)ptr, name);
+ if (src -> buffer)
+ buffer_reference (&dest -> buffer, src -> buffer, file, line);
+ dest -> data = src -> data;
+ dest -> terminated = src -> terminated;
+ dest -> len = src -> len;
+}
+
+/* Release the reference count to a data string's buffer (if any) and
+ zero out the other information, yielding the null data string. */
+
+void data_string_forget (data, file, line)
+ struct data_string *data;
+ const char *file;
+ int line;
+{
+ if (data -> buffer)
+ buffer_dereference (&data -> buffer, file, line);
+ memset (data, 0, sizeof *data);
+}
+
+/* Make a copy of the data in data_string, upping the buffer reference
+ count if there's a buffer. */
+
+void data_string_truncate (dp, len)
+ struct data_string *dp;
+ int len;
+{
+ if (len < dp -> len) {
+ dp -> terminated = 0;
+ dp -> len = len;
+ }
}
diff --git a/contrib/isc-dhcp/common/bpf.c b/contrib/isc-dhcp/common/bpf.c
index e204dfe2e0f1..49af907dcadb 100644
--- a/contrib/isc-dhcp/common/bpf.c
+++ b/contrib/isc-dhcp/common/bpf.c
@@ -3,8 +3,8 @@
BPF socket interface code, originally contributed by Archie Cobbs. */
/*
- * Copyright (c) 1995, 1996, 1998, 1999
- * The Internet Software Consortium. All rights reserved.
+ * Copyright (c) 1996-2000 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
@@ -33,16 +33,21 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * This software has been written for the Internet Software Consortium
- * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
- * Enterprises. To learn more about the Internet Software Consortium,
- * see ``http://www.vix.com/isc''. To learn more about Vixie
- * Enterprises, see ``http://www.vix.com''.
+ * This software was contributed to the Internet Software Consortium
+ * by Archie Cobbs, and is now maintained by Ted Lemon in cooperation
+ * with Nominum, Inc. To learn more about the Internet Software
+ * Consortium, see ``http://www.isc.org/''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''. To learn more about
+ * Nominum, Inc., see ``http://www.nominum.com''.
+ *
+ * Patches for FDDI support on Digital Unix were written by Bill
+ * Stapleton, and maintained for a while by Mike Meredith before he
+ * managed to get me to integrate them.
*/
#ifndef lint
static char copyright[] =
-"$Id: bpf.c,v 1.19.2.10 1999/05/27 17:44:51 mellon Exp $ Copyright (c) 1995, 1996, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
+"$Id: bpf.c,v 1.48 2001/04/08 21:12:49 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -55,7 +60,6 @@ static char copyright[] =
# else
# include <sys/ioctl.h>
# include <sys/uio.h>
-
# include <net/bpf.h>
# if defined (NEED_OSF_PFILT_HACKS)
# include <net/pfilt.h>
@@ -110,11 +114,11 @@ int if_register_bpf (info)
continue;
} else {
if (!b)
- error ("No bpf devices.%s%s%s",
+ log_fatal ("No bpf devices.%s%s%s",
" Please read the README",
" section for your operating",
" system.");
- error ("Can't find free bpf: %m");
+ log_fatal ("Can't find free bpf: %m");
}
} else {
break;
@@ -123,7 +127,7 @@ int if_register_bpf (info)
/* Set the BPF device to point at this interface. */
if (ioctl (sock, BIOCSETIF, info -> ifp) < 0)
- error ("Can't attach interface %s to bpf device %s: %m",
+ log_fatal ("Can't attach interface %s to bpf device %s: %m",
info -> name, filename);
return sock;
@@ -142,11 +146,32 @@ void if_register_send (info)
info -> wfdesc = info -> rfdesc;
#endif
if (!quiet_interface_discovery)
- note ("Sending on BPF/%s/%s%s%s",
+ log_info ("Sending on BPF/%s/%s%s%s",
+ info -> name,
+ print_hw_addr (info -> hw_address.hbuf [0],
+ info -> hw_address.hlen - 1,
+ &info -> hw_address.hbuf [1]),
+ (info -> shared_network ? "/" : ""),
+ (info -> shared_network ?
+ info -> shared_network -> name : ""));
+}
+
+void if_deregister_send (info)
+ struct interface_info *info;
+{
+ /* If we're using the bpf API for sending and receiving,
+ we don't need to register this interface twice. */
+#ifndef USE_BPF_RECEIVE
+ close (info -> wfdesc);
+#endif
+ info -> wfdesc = -1;
+
+ if (!quiet_interface_discovery)
+ log_info ("Disabling output on BPF/%s/%s%s%s",
info -> name,
- print_hw_addr (info -> hw_address.htype,
- info -> hw_address.hlen,
- info -> hw_address.haddr),
+ print_hw_addr (info -> hw_address.hbuf [0],
+ info -> hw_address.hlen - 1,
+ &info -> hw_address.hbuf [1]),
(info -> shared_network ? "/" : ""),
(info -> shared_network ?
info -> shared_network -> name : ""));
@@ -185,8 +210,12 @@ struct bpf_insn dhcp_bpf_filter [] = {
BPF_STMT(BPF_RET+BPF_K, 0),
};
-int dhcp_bpf_filter_len = sizeof dhcp_bpf_filter / sizeof (struct bpf_insn);
+#if defined (DEC_FDDI)
+struct bpf_insn *bpf_fddi_filter;
+#endif
+int dhcp_bpf_filter_len = sizeof dhcp_bpf_filter / sizeof (struct bpf_insn);
+#if defined (HAVE_TR_SUPPORT)
struct bpf_insn dhcp_bpf_tr_filter [] = {
/* accept all token ring packets due to variable length header */
/* if we want to get clever, insert the program here */
@@ -200,7 +229,8 @@ struct bpf_insn dhcp_bpf_tr_filter [] = {
int dhcp_bpf_tr_filter_len = (sizeof dhcp_bpf_tr_filter /
sizeof (struct bpf_insn));
-#endif
+#endif /* HAVE_TR_SUPPORT */
+#endif /* USE_LPF_RECEIVE || USE_BPF_RECEIVE */
#if defined (USE_BPF_RECEIVE)
void if_register_receive (info)
@@ -211,50 +241,80 @@ void if_register_receive (info)
u_int32_t addr;
struct bpf_program p;
u_int32_t bits;
+#ifdef DEC_FDDI
+ int link_layer;
+#endif /* DEC_FDDI */
/* Open a BPF device and hang it on this interface... */
info -> rfdesc = if_register_bpf (info);
/* Make sure the BPF version is in range... */
if (ioctl (info -> rfdesc, BIOCVERSION, &v) < 0)
- error ("Can't get BPF version: %m");
+ log_fatal ("Can't get BPF version: %m");
if (v.bv_major != BPF_MAJOR_VERSION ||
v.bv_minor < BPF_MINOR_VERSION)
- error ("Kernel BPF version out of range - recompile dhcpd!");
+ log_fatal ("BPF version mismatch - recompile DHCP!");
/* Set immediate mode so that reads return as soon as a packet
comes in, rather than waiting for the input buffer to fill with
packets. */
if (ioctl (info -> rfdesc, BIOCIMMEDIATE, &flag) < 0)
- error ("Can't set immediate mode on bpf device: %m");
+ log_fatal ("Can't set immediate mode on bpf device: %m");
#ifdef NEED_OSF_PFILT_HACKS
/* Allow the copyall flag to be set... */
if (ioctl(info -> rfdesc, EIOCALLOWCOPYALL, &flag) < 0)
- error ("Can't set ALLOWCOPYALL: %m");
+ log_fatal ("Can't set ALLOWCOPYALL: %m");
/* Clear all the packet filter mode bits first... */
bits = 0;
if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0)
- error ("Can't clear pfilt bits: %m");
+ log_fatal ("Can't clear pfilt bits: %m");
/* Set the ENBATCH, ENCOPYALL, ENBPFHDR bits... */
bits = ENBATCH | ENCOPYALL | ENBPFHDR;
if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0)
- error ("Can't set ENBATCH|ENCOPYALL|ENBPFHDR: %m");
+ log_fatal ("Can't set ENBATCH|ENCOPYALL|ENBPFHDR: %m");
#endif
/* Get the required BPF buffer length from the kernel. */
if (ioctl (info -> rfdesc, BIOCGBLEN, &info -> rbuf_max) < 0)
- error ("Can't get bpf buffer length: %m");
- info -> rbuf = malloc (info -> rbuf_max);
+ log_fatal ("Can't get bpf buffer length: %m");
+ info -> rbuf = dmalloc (info -> rbuf_max, MDL);
if (!info -> rbuf)
- error ("Can't allocate %d bytes for bpf input buffer.");
+ log_fatal ("Can't allocate %ld bytes for bpf input buffer.",
+ (long)(info -> rbuf_max));
info -> rbuf_offset = 0;
info -> rbuf_len = 0;
/* Set up the bpf filter program structure. */
p.bf_len = dhcp_bpf_filter_len;
+
+#ifdef DEC_FDDI
+ /* See if this is an FDDI interface, flag it for later. */
+ if (ioctl(info -> rfdesc, BIOCGDLT, &link_layer) >= 0 &&
+ link_layer == DLT_FDDI) {
+ if (!bpf_fddi_filter) {
+ bpf_fddi_filter = dmalloc (sizeof bpf_fddi_filter,
+ MDL);
+ if (!bpf_fddi_filter)
+ log_fatal ("No memory for FDDI filter.");
+ memcpy (bpf_fddi_filter,
+ dhcp_bpf_filter, sizeof dhcp_bpf_filter);
+ /* Patch the BPF program to account for the difference
+ in length between ethernet headers (14), FDDI and
+ 802.2 headers (16 +8=24, +10).
+ XXX changes to filter program may require changes to
+ XXX the insn number(s) used below! */
+ bpf_fddi_filter[0].k += 10;
+ bpf_fddi_filter[2].k += 10;
+ bpf_fddi_filter[4].k += 10;
+ bpf_fddi_filter[6].k += 10;
+ bpf_fddi_filter[7].k += 10;
+ }
+ p.bf_insns = bpf_fddi_filter;
+ } else
+#endif /* DEC_FDDI */
p.bf_insns = dhcp_bpf_filter;
/* Patch the server port into the BPF program...
@@ -263,13 +323,30 @@ void if_register_receive (info)
dhcp_bpf_filter [8].k = ntohs (local_port);
if (ioctl (info -> rfdesc, BIOCSETF, &p) < 0)
- error ("Can't install packet filter program: %m");
+ log_fatal ("Can't install packet filter program: %m");
if (!quiet_interface_discovery)
- note ("Listening on BPF/%s/%s%s%s",
+ log_info ("Listening on BPF/%s/%s%s%s",
info -> name,
- print_hw_addr (info -> hw_address.htype,
- info -> hw_address.hlen,
- info -> hw_address.haddr),
+ print_hw_addr (info -> hw_address.hbuf [0],
+ info -> hw_address.hlen - 1,
+ &info -> hw_address.hbuf [1]),
+ (info -> shared_network ? "/" : ""),
+ (info -> shared_network ?
+ info -> shared_network -> name : ""));
+}
+
+void if_deregister_receive (info)
+ struct interface_info *info;
+{
+ close (info -> rfdesc);
+ info -> rfdesc = -1;
+
+ if (!quiet_interface_discovery)
+ log_info ("Disabling input on BPF/%s/%s%s%s",
+ info -> name,
+ print_hw_addr (info -> hw_address.hbuf [0],
+ info -> hw_address.hlen - 1,
+ &info -> hw_address.hbuf [1]),
(info -> shared_network ? "/" : ""),
(info -> shared_network ?
info -> shared_network -> name : ""));
@@ -286,30 +363,35 @@ ssize_t send_packet (interface, packet, raw, len, from, to, hto)
struct sockaddr_in *to;
struct hardware *hto;
{
- int bufp = 0;
- unsigned char buf [256];
- struct iovec iov [2];
+ unsigned hbufp = 0, ibufp = 0;
+ double hw [4];
+ double ip [32];
+ struct iovec iov [3];
int result;
+ int fudge;
if (!strcmp (interface -> name, "fallback"))
return send_fallback (interface, packet, raw,
len, from, to, hto);
/* Assemble the headers... */
- assemble_hw_header (interface, buf, &bufp, hto);
- assemble_udp_ip_header (interface, buf, &bufp, from.s_addr,
+ assemble_hw_header (interface, (unsigned char *)hw, &hbufp, hto);
+ assemble_udp_ip_header (interface,
+ (unsigned char *)ip, &ibufp, from.s_addr,
to -> sin_addr.s_addr, to -> sin_port,
(unsigned char *)raw, len);
/* Fire it off */
- iov [0].iov_base = (char *)buf;
- iov [0].iov_len = bufp;
- iov [1].iov_base = (char *)raw;
- iov [1].iov_len = len;
-
- result = writev(interface -> wfdesc, iov, 2);
+ iov [0].iov_base = ((char *)hw);
+ iov [0].iov_len = hbufp;
+ iov [1].iov_base = ((char *)ip);
+ iov [1].iov_len = ibufp;
+ iov [2].iov_base = (char *)raw;
+ iov [2].iov_len = len;
+
+ result = writev(interface -> wfdesc, iov, 3);
if (result < 0)
- warn ("send_packet: %m");
+ log_error ("send_packet: %m");
return result;
}
#endif /* USE_BPF_SEND */
@@ -340,10 +422,16 @@ ssize_t receive_packet (interface, buf, len, from, hfrom)
length = read (interface -> rfdesc,
interface -> rbuf,
interface -> rbuf_max);
- if (length <= 0)
+ if (length <= 0) {
+ if (errno == EIO) {
+ dhcp_interface_remove
+ ((omapi_object_t *)interface,
+ (omapi_object_t *)0);
+ }
return length;
+ }
interface -> rbuf_offset = 0;
- interface -> rbuf_len = length;
+ interface -> rbuf_len = BPF_WORDALIGN (length);
}
/* If there isn't room for a whole bpf header, something went
@@ -370,8 +458,9 @@ ssize_t receive_packet (interface, buf, len, from, hfrom)
the packet won't fit in the input buffer, all we
can do is drop it. */
if (hdr.bh_caplen != hdr.bh_datalen) {
- interface -> rbuf_offset +=
- hdr.bh_hdrlen = hdr.bh_caplen;
+ interface -> rbuf_offset =
+ BPF_WORDALIGN (interface -> rbuf_offset +
+ hdr.bh_hdrlen + hdr.bh_caplen);
continue;
}
@@ -388,7 +477,9 @@ ssize_t receive_packet (interface, buf, len, from, hfrom)
physical layer that supports this, but WTH), skip this
packet. */
if (offset < 0) {
- interface -> rbuf_offset += hdr.bh_caplen;
+ interface -> rbuf_offset =
+ BPF_WORDALIGN (interface -> rbuf_offset +
+ hdr.bh_caplen);
continue;
}
interface -> rbuf_offset += offset;
@@ -404,30 +495,37 @@ ssize_t receive_packet (interface, buf, len, from, hfrom)
/* If the IP or UDP checksum was bad, skip the packet... */
if (offset < 0) {
- interface -> rbuf_offset += hdr.bh_caplen;
+ interface -> rbuf_offset =
+ BPF_WORDALIGN (interface -> rbuf_offset +
+ hdr.bh_caplen);
continue;
}
- interface -> rbuf_offset += offset;
+ interface -> rbuf_offset = interface -> rbuf_offset + offset;
hdr.bh_caplen -= offset;
/* If there's not enough room to stash the packet data,
we have to skip it (this shouldn't happen in real
life, though). */
if (hdr.bh_caplen > len) {
- interface -> rbuf_offset += hdr.bh_caplen;
+ interface -> rbuf_offset =
+ BPF_WORDALIGN (interface -> rbuf_offset +
+ hdr.bh_caplen);
continue;
}
/* Copy out the data in the packet... */
memcpy (buf, interface -> rbuf + interface -> rbuf_offset,
hdr.bh_caplen);
- interface -> rbuf_offset += hdr.bh_caplen;
+ interface -> rbuf_offset =
+ BPF_WORDALIGN (interface -> rbuf_offset +
+ hdr.bh_caplen);
return hdr.bh_caplen;
} while (!length);
return 0;
}
-int can_unicast_without_arp ()
+int can_unicast_without_arp (ip)
+ struct interface_info *ip;
{
return 1;
}
@@ -438,14 +536,25 @@ int can_receive_unicast_unconfigured (ip)
return 1;
}
+int supports_multiple_interfaces (ip)
+ struct interface_info *ip;
+{
+ return 1;
+}
+
void maybe_setup_fallback ()
{
- struct interface_info *fbi;
- fbi = setup_fallback ();
- if (fbi) {
+ isc_result_t status;
+ struct interface_info *fbi = (struct interface_info *)0;
+ if (setup_fallback (&fbi, MDL)) {
if_register_fallback (fbi);
- add_protocol ("fallback", fallback_interface -> wfdesc,
- fallback_discard, fallback_interface);
+ status = omapi_register_io_object ((omapi_object_t *)fbi,
+ if_readsocket, 0,
+ fallback_discard, 0, 0);
+ if (status != ISC_R_SUCCESS)
+ log_fatal ("Can't register I/O handle for %s: %s",
+ fbi -> name, isc_result_totext (status));
+ interface_dereference (&fbi, MDL);
}
}
#endif
diff --git a/contrib/isc-dhcp/common/comapi.c b/contrib/isc-dhcp/common/comapi.c
new file mode 100644
index 000000000000..a038903fb283
--- /dev/null
+++ b/contrib/isc-dhcp/common/comapi.c
@@ -0,0 +1,958 @@
+/* omapi.c
+
+ OMAPI object interfaces for the DHCP server. */
+
+/*
+ * Copyright (c) 1999-2001 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 and Nominum, Inc.
+ * To learn more about the Internet Software Consortium, see
+ * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
+ * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
+ * ``http://www.nominum.com''.
+ */
+
+/* Many, many thanks to Brian Murrell and BCtel for this code - BCtel
+ provided the funding that resulted in this code and the entire
+ OMAPI support library being written, and Brian helped brainstorm
+ and refine the requirements. To the extent that this code is
+ useful, you have Brian and BCtel to thank. Any limitations in the
+ code are a result of mistakes on my part. -- Ted Lemon */
+
+#ifndef lint
+static char copyright[] =
+"$Id: comapi.c,v 1.9.2.5 2001/10/18 20:09:59 mellon Exp $ Copyright (c) 1999-2001 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+#include <omapip/omapip_p.h>
+
+OMAPI_OBJECT_ALLOC (subnet, struct subnet, dhcp_type_subnet)
+OMAPI_OBJECT_ALLOC (shared_network, struct shared_network,
+ dhcp_type_shared_network)
+OMAPI_OBJECT_ALLOC (group_object, struct group_object, dhcp_type_group)
+OMAPI_OBJECT_ALLOC (dhcp_control, dhcp_control_object_t, dhcp_type_control)
+
+omapi_object_type_t *dhcp_type_interface;
+omapi_object_type_t *dhcp_type_group;
+omapi_object_type_t *dhcp_type_shared_network;
+omapi_object_type_t *dhcp_type_subnet;
+omapi_object_type_t *dhcp_type_control;
+dhcp_control_object_t *dhcp_control_object;
+
+void dhcp_common_objects_setup ()
+{
+ isc_result_t status;
+
+ status = omapi_object_type_register (&dhcp_type_control,
+ "control",
+ dhcp_control_set_value,
+ dhcp_control_get_value,
+ dhcp_control_destroy,
+ dhcp_control_signal_handler,
+ dhcp_control_stuff_values,
+ dhcp_control_lookup,
+ dhcp_control_create,
+ dhcp_control_remove, 0, 0, 0,
+ sizeof (dhcp_control_object_t),
+ 0, RC_MISC);
+ if (status != ISC_R_SUCCESS)
+ log_fatal ("Can't register control object type: %s",
+ isc_result_totext (status));
+ status = dhcp_control_allocate (&dhcp_control_object, MDL);
+ if (status != ISC_R_SUCCESS)
+ log_fatal ("Can't make initial control object: %s",
+ isc_result_totext (status));
+ dhcp_control_object -> state = server_startup;
+
+ status = omapi_object_type_register (&dhcp_type_group,
+ "group",
+ dhcp_group_set_value,
+ dhcp_group_get_value,
+ dhcp_group_destroy,
+ dhcp_group_signal_handler,
+ dhcp_group_stuff_values,
+ dhcp_group_lookup,
+ dhcp_group_create,
+ dhcp_group_remove, 0, 0, 0,
+ sizeof (struct group_object), 0,
+ RC_MISC);
+ if (status != ISC_R_SUCCESS)
+ log_fatal ("Can't register group object type: %s",
+ isc_result_totext (status));
+
+ status = omapi_object_type_register (&dhcp_type_subnet,
+ "subnet",
+ dhcp_subnet_set_value,
+ dhcp_subnet_get_value,
+ dhcp_subnet_destroy,
+ dhcp_subnet_signal_handler,
+ dhcp_subnet_stuff_values,
+ dhcp_subnet_lookup,
+ dhcp_subnet_create,
+ dhcp_subnet_remove, 0, 0, 0,
+ sizeof (struct subnet), 0,
+ RC_MISC);
+ if (status != ISC_R_SUCCESS)
+ log_fatal ("Can't register subnet object type: %s",
+ isc_result_totext (status));
+
+ status = omapi_object_type_register
+ (&dhcp_type_shared_network,
+ "shared-network",
+ dhcp_shared_network_set_value,
+ dhcp_shared_network_get_value,
+ dhcp_shared_network_destroy,
+ dhcp_shared_network_signal_handler,
+ dhcp_shared_network_stuff_values,
+ dhcp_shared_network_lookup,
+ dhcp_shared_network_create,
+ dhcp_shared_network_remove, 0, 0, 0,
+ sizeof (struct shared_network), 0, RC_MISC);
+ if (status != ISC_R_SUCCESS)
+ log_fatal ("Can't register shared network object type: %s",
+ isc_result_totext (status));
+
+ interface_setup ();
+}
+
+isc_result_t dhcp_group_set_value (omapi_object_t *h,
+ omapi_object_t *id,
+ omapi_data_string_t *name,
+ omapi_typed_data_t *value)
+{
+ struct group_object *group;
+ isc_result_t status;
+ int foo;
+
+ if (h -> type != dhcp_type_group)
+ return ISC_R_INVALIDARG;
+ group = (struct group_object *)h;
+
+ /* XXX For now, we can only set these values on new group objects.
+ XXX Soon, we need to be able to update group objects. */
+ if (!omapi_ds_strcmp (name, "name")) {
+ if (group -> name)
+ return ISC_R_EXISTS;
+ if (value -> type == omapi_datatype_data ||
+ value -> type == omapi_datatype_string) {
+ group -> name = dmalloc (value -> u.buffer.len + 1,
+ MDL);
+ if (!group -> name)
+ return ISC_R_NOMEMORY;
+ memcpy (group -> name,
+ value -> u.buffer.value,
+ value -> u.buffer.len);
+ group -> name [value -> u.buffer.len] = 0;
+ } else
+ return ISC_R_INVALIDARG;
+ return ISC_R_SUCCESS;
+ }
+
+ if (!omapi_ds_strcmp (name, "statements")) {
+ if (group -> group && group -> group -> statements)
+ return ISC_R_EXISTS;
+ if (!group -> group) {
+ if (!clone_group (&group -> group, root_group, MDL))
+ return ISC_R_NOMEMORY;
+ }
+ if (value -> type == omapi_datatype_data ||
+ value -> type == omapi_datatype_string) {
+ struct parse *parse;
+ int lose = 0;
+ parse = (struct parse *)0;
+ status = new_parse (&parse, -1,
+ (char *)value -> u.buffer.value,
+ value -> u.buffer.len,
+ "network client", 0);
+ if (status != ISC_R_SUCCESS)
+ return status;
+ if (!(parse_executable_statements
+ (&group -> group -> statements, parse, &lose,
+ context_any))) {
+ end_parse (&parse);
+ return ISC_R_BADPARSE;
+ }
+ end_parse (&parse);
+ return ISC_R_SUCCESS;
+ } else
+ return ISC_R_INVALIDARG;
+ }
+
+ /* Try to find some inner object that can take the value. */
+ if (h -> inner && h -> inner -> type -> set_value) {
+ status = ((*(h -> inner -> type -> set_value))
+ (h -> inner, id, name, value));
+ if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED)
+ return status;
+ }
+
+ return ISC_R_NOTFOUND;
+}
+
+
+isc_result_t dhcp_group_get_value (omapi_object_t *h, omapi_object_t *id,
+ omapi_data_string_t *name,
+ omapi_value_t **value)
+{
+ struct group_object *group;
+ isc_result_t status;
+ struct data_string ip_addrs;
+
+ if (h -> type != dhcp_type_group)
+ return ISC_R_INVALIDARG;
+ group = (struct group_object *)h;
+
+ if (!omapi_ds_strcmp (name, "name"))
+ return omapi_make_string_value (value,
+ name, group -> name, MDL);
+
+ /* Try to find some inner object that can take the value. */
+ if (h -> inner && h -> inner -> type -> get_value) {
+ status = ((*(h -> inner -> type -> get_value))
+ (h -> inner, id, name, value));
+ if (status == ISC_R_SUCCESS)
+ return status;
+ }
+ return ISC_R_NOTFOUND;
+}
+
+isc_result_t dhcp_group_destroy (omapi_object_t *h, const char *file, int line)
+{
+ struct group_object *group, *t;
+ isc_result_t status;
+
+ if (h -> type != dhcp_type_group)
+ return ISC_R_INVALIDARG;
+ group = (struct group_object *)h;
+
+ if (group -> name) {
+ if (group_name_hash) {
+ t = (struct group_object *)0;
+ if (group_hash_lookup (&t, group_name_hash,
+ group -> name,
+ strlen (group -> name), MDL)) {
+ group_hash_delete (group_name_hash,
+ group -> name,
+ strlen (group -> name),
+ MDL);
+ group_object_dereference (&t, MDL);
+ }
+ }
+ dfree (group -> name, file, line);
+ group -> name = (char *)0;
+ }
+ if (group -> group)
+ group_dereference (&group -> group, MDL);
+
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_group_signal_handler (omapi_object_t *h,
+ const char *name, va_list ap)
+{
+ struct group_object *group, *t;
+ isc_result_t status;
+ int updatep = 0;
+
+ if (h -> type != dhcp_type_group)
+ return ISC_R_INVALIDARG;
+ group = (struct group_object *)h;
+
+ if (!strcmp (name, "updated")) {
+ /* A group object isn't valid if a subgroup hasn't yet been
+ associated with it. */
+ if (!group -> group)
+ return ISC_R_INVALIDARG;
+
+ /* Group objects always have to have names. */
+ if (!group -> name) {
+ char hnbuf [64];
+ sprintf (hnbuf, "ng%08lx%08lx",
+ (unsigned long)cur_time,
+ (unsigned long)group);
+ group -> name = dmalloc (strlen (hnbuf) + 1, MDL);
+ if (!group -> name)
+ return ISC_R_NOMEMORY;
+ strcpy (group -> name, hnbuf);
+ }
+
+ supersede_group (group, 1);
+ updatep = 1;
+ }
+
+ /* Try to find some inner object that can take the value. */
+ if (h -> inner && h -> inner -> type -> get_value) {
+ status = ((*(h -> inner -> type -> signal_handler))
+ (h -> inner, name, ap));
+ if (status == ISC_R_SUCCESS)
+ return status;
+ }
+ if (updatep)
+ return ISC_R_SUCCESS;
+ return ISC_R_NOTFOUND;
+}
+
+isc_result_t dhcp_group_stuff_values (omapi_object_t *c,
+ omapi_object_t *id,
+ omapi_object_t *h)
+{
+ struct group_object *group;
+ isc_result_t status;
+
+ if (h -> type != dhcp_type_group)
+ return ISC_R_INVALIDARG;
+ group = (struct group_object *)h;
+
+ /* Write out all the values. */
+ if (group -> name) {
+ status = omapi_connection_put_name (c, "name");
+ if (status != ISC_R_SUCCESS)
+ return status;
+ status = omapi_connection_put_string (c, group -> name);
+ if (status != ISC_R_SUCCESS)
+ return status;
+ }
+
+ /* Write out the inner object, if any. */
+ if (h -> inner && h -> inner -> type -> stuff_values) {
+ status = ((*(h -> inner -> type -> stuff_values))
+ (c, id, h -> inner));
+ if (status == ISC_R_SUCCESS)
+ return status;
+ }
+
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_group_lookup (omapi_object_t **lp,
+ omapi_object_t *id, omapi_object_t *ref)
+{
+ omapi_value_t *tv = (omapi_value_t *)0;
+ isc_result_t status;
+ struct group_object *group;
+
+ if (!ref)
+ return ISC_R_NOKEYS;
+
+ /* First see if we were sent a handle. */
+ status = omapi_get_value_str (ref, id, "handle", &tv);
+ if (status == ISC_R_SUCCESS) {
+ status = omapi_handle_td_lookup (lp, tv -> value);
+
+ omapi_value_dereference (&tv, MDL);
+ if (status != ISC_R_SUCCESS)
+ return status;
+
+ /* Don't return the object if the type is wrong. */
+ if ((*lp) -> type != dhcp_type_group) {
+ omapi_object_dereference (lp, MDL);
+ return ISC_R_INVALIDARG;
+ }
+ }
+
+ /* Now look for a name. */
+ status = omapi_get_value_str (ref, id, "name", &tv);
+ if (status == ISC_R_SUCCESS) {
+ group = (struct group_object *)0;
+ if (group_name_hash &&
+ group_hash_lookup (&group, group_name_hash,
+ (const char *)
+ tv -> value -> u.buffer.value,
+ tv -> value -> u.buffer.len, MDL)) {
+ omapi_value_dereference (&tv, MDL);
+
+ if (*lp && *lp != (omapi_object_t *)group) {
+ group_object_dereference (&group, MDL);
+ omapi_object_dereference (lp, MDL);
+ return ISC_R_KEYCONFLICT;
+ } else if (!*lp) {
+ /* XXX fix so that hash lookup itself creates
+ XXX the reference. */
+ omapi_object_reference (lp,
+ (omapi_object_t *)group,
+ MDL);
+ group_object_dereference (&group, MDL);
+ }
+ } else if (!*lp)
+ return ISC_R_NOTFOUND;
+ }
+
+ /* If we get to here without finding a group, no valid key was
+ specified. */
+ if (!*lp)
+ return ISC_R_NOKEYS;
+
+ if (((struct group_object *)(*lp)) -> flags & GROUP_OBJECT_DELETED) {
+ omapi_object_dereference (lp, MDL);
+ return ISC_R_NOTFOUND;
+ }
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_group_create (omapi_object_t **lp,
+ omapi_object_t *id)
+{
+ struct group_object *group;
+ isc_result_t status;
+ group = (struct group_object *)0;
+
+ status = group_object_allocate (&group, MDL);
+ if (status != ISC_R_SUCCESS)
+ return status;
+ group -> flags = GROUP_OBJECT_DYNAMIC;
+ status = omapi_object_reference (lp, (omapi_object_t *)group, MDL);
+ group_object_dereference (&group, MDL);
+ return status;
+}
+
+isc_result_t dhcp_group_remove (omapi_object_t *lp,
+ omapi_object_t *id)
+{
+ struct group_object *group;
+ isc_result_t status;
+ if (lp -> type != dhcp_type_group)
+ return ISC_R_INVALIDARG;
+ group = (struct group_object *)lp;
+
+ group -> flags |= GROUP_OBJECT_DELETED;
+ if (group_write_hook) {
+ if (!(*group_write_hook) (group))
+ return ISC_R_IOERROR;
+ }
+
+ status = dhcp_group_destroy ((omapi_object_t *)group, MDL);
+
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_control_set_value (omapi_object_t *h,
+ omapi_object_t *id,
+ omapi_data_string_t *name,
+ omapi_typed_data_t *value)
+{
+ dhcp_control_object_t *control;
+ isc_result_t status;
+ int foo;
+ unsigned long newstate;
+
+ if (h -> type != dhcp_type_control)
+ return ISC_R_INVALIDARG;
+ control = (dhcp_control_object_t *)h;
+
+ if (!omapi_ds_strcmp (name, "state")) {
+ status = omapi_get_int_value (&newstate, value);
+ if (status != ISC_R_SUCCESS)
+ return status;
+ status = dhcp_set_control_state (control -> state, newstate);
+ if (status == ISC_R_SUCCESS)
+ control -> state = value -> u.integer;
+ return status;
+ }
+
+ /* Try to find some inner object that can take the value. */
+ if (h -> inner && h -> inner -> type -> set_value) {
+ status = ((*(h -> inner -> type -> set_value))
+ (h -> inner, id, name, value));
+ if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED)
+ return status;
+ }
+
+ return ISC_R_NOTFOUND;
+}
+
+
+isc_result_t dhcp_control_get_value (omapi_object_t *h, omapi_object_t *id,
+ omapi_data_string_t *name,
+ omapi_value_t **value)
+{
+ dhcp_control_object_t *control;
+ isc_result_t status;
+ struct data_string ip_addrs;
+
+ if (h -> type != dhcp_type_control)
+ return ISC_R_INVALIDARG;
+ control = (dhcp_control_object_t *)h;
+
+ if (!omapi_ds_strcmp (name, "state"))
+ return omapi_make_int_value (value,
+ name, (int)control -> state, MDL);
+
+ /* Try to find some inner object that can take the value. */
+ if (h -> inner && h -> inner -> type -> get_value) {
+ status = ((*(h -> inner -> type -> get_value))
+ (h -> inner, id, name, value));
+ if (status == ISC_R_SUCCESS)
+ return status;
+ }
+ return ISC_R_NOTFOUND;
+}
+
+isc_result_t dhcp_control_destroy (omapi_object_t *h,
+ const char *file, int line)
+{
+ dhcp_control_object_t *control, *t;
+ isc_result_t status;
+
+ if (h -> type != dhcp_type_control)
+ return ISC_R_INVALIDARG;
+
+ /* Can't destroy the control object. */
+ return ISC_R_NOPERM;
+}
+
+isc_result_t dhcp_control_signal_handler (omapi_object_t *h,
+ const char *name, va_list ap)
+{
+ dhcp_control_object_t *control, *t;
+ isc_result_t status;
+ int updatep = 0;
+
+ if (h -> type != dhcp_type_control)
+ return ISC_R_INVALIDARG;
+ control = (dhcp_control_object_t *)h;
+
+ /* Try to find some inner object that can take the value. */
+ if (h -> inner && h -> inner -> type -> get_value) {
+ status = ((*(h -> inner -> type -> signal_handler))
+ (h -> inner, name, ap));
+ if (status == ISC_R_SUCCESS)
+ return status;
+ }
+ return ISC_R_NOTFOUND;
+}
+
+isc_result_t dhcp_control_stuff_values (omapi_object_t *c,
+ omapi_object_t *id,
+ omapi_object_t *h)
+{
+ dhcp_control_object_t *control;
+ isc_result_t status;
+
+ if (h -> type != dhcp_type_control)
+ return ISC_R_INVALIDARG;
+ control = (dhcp_control_object_t *)h;
+
+ /* Write out all the values. */
+ status = omapi_connection_put_name (c, "state");
+ if (status != ISC_R_SUCCESS)
+ return status;
+ status = omapi_connection_put_uint32 (c, sizeof (u_int32_t));
+ if (status != ISC_R_SUCCESS)
+ return status;
+ status = omapi_connection_put_uint32 (c, control -> state);
+ if (status != ISC_R_SUCCESS)
+ return status;
+
+ /* Write out the inner object, if any. */
+ if (h -> inner && h -> inner -> type -> stuff_values) {
+ status = ((*(h -> inner -> type -> stuff_values))
+ (c, id, h -> inner));
+ if (status == ISC_R_SUCCESS)
+ return status;
+ }
+
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_control_lookup (omapi_object_t **lp,
+ omapi_object_t *id, omapi_object_t *ref)
+{
+ omapi_value_t *tv = (omapi_value_t *)0;
+ isc_result_t status;
+ dhcp_control_object_t *control;
+
+ /* First see if we were sent a handle. */
+ if (ref) {
+ status = omapi_get_value_str (ref, id, "handle", &tv);
+ if (status == ISC_R_SUCCESS) {
+ status = omapi_handle_td_lookup (lp, tv -> value);
+
+ omapi_value_dereference (&tv, MDL);
+ if (status != ISC_R_SUCCESS)
+ return status;
+
+ /* Don't return the object if the type is wrong. */
+ if ((*lp) -> type != dhcp_type_control) {
+ omapi_object_dereference (lp, MDL);
+ return ISC_R_INVALIDARG;
+ }
+ }
+ }
+
+ /* Otherwise, stop playing coy - there's only one control object,
+ so we can just return it. */
+ dhcp_control_reference ((dhcp_control_object_t **)lp,
+ dhcp_control_object, MDL);
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_control_create (omapi_object_t **lp,
+ omapi_object_t *id)
+{
+ /* Can't create a control object - there can be only one. */
+ return ISC_R_NOPERM;
+}
+
+isc_result_t dhcp_control_remove (omapi_object_t *lp,
+ omapi_object_t *id)
+{
+ /* Form is emptiness; emptiness form. The control object
+ cannot go out of existance. */
+ return ISC_R_NOPERM;
+}
+
+isc_result_t dhcp_subnet_set_value (omapi_object_t *h,
+ omapi_object_t *id,
+ omapi_data_string_t *name,
+ omapi_typed_data_t *value)
+{
+ struct subnet *subnet;
+ isc_result_t status;
+ int foo;
+
+ if (h -> type != dhcp_type_subnet)
+ return ISC_R_INVALIDARG;
+ subnet = (struct subnet *)h;
+
+ /* No values to set yet. */
+
+ /* Try to find some inner object that can take the value. */
+ if (h -> inner && h -> inner -> type -> set_value) {
+ status = ((*(h -> inner -> type -> set_value))
+ (h -> inner, id, name, value));
+ if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED)
+ return status;
+ }
+
+ return ISC_R_NOTFOUND;
+}
+
+
+isc_result_t dhcp_subnet_get_value (omapi_object_t *h, omapi_object_t *id,
+ omapi_data_string_t *name,
+ omapi_value_t **value)
+{
+ struct subnet *subnet;
+ isc_result_t status;
+
+ if (h -> type != dhcp_type_subnet)
+ return ISC_R_INVALIDARG;
+ subnet = (struct subnet *)h;
+
+ /* No values to get yet. */
+
+ /* Try to find some inner object that can provide the value. */
+ if (h -> inner && h -> inner -> type -> get_value) {
+ status = ((*(h -> inner -> type -> get_value))
+ (h -> inner, id, name, value));
+ if (status == ISC_R_SUCCESS)
+ return status;
+ }
+ return ISC_R_NOTFOUND;
+}
+
+isc_result_t dhcp_subnet_destroy (omapi_object_t *h, const char *file, int line)
+{
+ struct subnet *subnet;
+ isc_result_t status;
+
+ if (h -> type != dhcp_type_subnet)
+ return ISC_R_INVALIDARG;
+ subnet = (struct subnet *)h;
+
+#if defined (DEBUG_MEMORY_LEAKAGE) || \
+ defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
+ if (subnet -> next_subnet)
+ subnet_dereference (&subnet -> next_subnet, file, line);
+ if (subnet -> next_sibling)
+ subnet_dereference (&subnet -> next_sibling, file, line);
+ if (subnet -> shared_network)
+ shared_network_dereference (&subnet -> shared_network,
+ file, line);
+ if (subnet -> interface)
+ interface_dereference (&subnet -> interface, file, line);
+ if (subnet -> group)
+ group_dereference (&subnet -> group, file, line);
+#endif
+
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_subnet_signal_handler (omapi_object_t *h,
+ const char *name, va_list ap)
+{
+ struct subnet *subnet;
+ isc_result_t status;
+ int updatep = 0;
+
+ if (h -> type != dhcp_type_subnet)
+ return ISC_R_INVALIDARG;
+ subnet = (struct subnet *)h;
+
+ /* Can't write subnets yet. */
+
+ /* Try to find some inner object that can take the value. */
+ if (h -> inner && h -> inner -> type -> get_value) {
+ status = ((*(h -> inner -> type -> signal_handler))
+ (h -> inner, name, ap));
+ if (status == ISC_R_SUCCESS)
+ return status;
+ }
+ if (updatep)
+ return ISC_R_SUCCESS;
+ return ISC_R_NOTFOUND;
+}
+
+isc_result_t dhcp_subnet_stuff_values (omapi_object_t *c,
+ omapi_object_t *id,
+ omapi_object_t *h)
+{
+ struct subnet *subnet;
+ isc_result_t status;
+
+ if (h -> type != dhcp_type_subnet)
+ return ISC_R_INVALIDARG;
+ subnet = (struct subnet *)h;
+
+ /* Can't stuff subnet values yet. */
+
+ /* Write out the inner object, if any. */
+ if (h -> inner && h -> inner -> type -> stuff_values) {
+ status = ((*(h -> inner -> type -> stuff_values))
+ (c, id, h -> inner));
+ if (status == ISC_R_SUCCESS)
+ return status;
+ }
+
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_subnet_lookup (omapi_object_t **lp,
+ omapi_object_t *id,
+ omapi_object_t *ref)
+{
+ omapi_value_t *tv = (omapi_value_t *)0;
+ isc_result_t status;
+ struct subnet *subnet;
+
+ /* Can't look up subnets yet. */
+
+ /* If we get to here without finding a subnet, no valid key was
+ specified. */
+ if (!*lp)
+ return ISC_R_NOKEYS;
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_subnet_create (omapi_object_t **lp,
+ omapi_object_t *id)
+{
+ return ISC_R_NOTIMPLEMENTED;
+}
+
+isc_result_t dhcp_subnet_remove (omapi_object_t *lp,
+ omapi_object_t *id)
+{
+ return ISC_R_NOTIMPLEMENTED;
+}
+
+isc_result_t dhcp_shared_network_set_value (omapi_object_t *h,
+ omapi_object_t *id,
+ omapi_data_string_t *name,
+ omapi_typed_data_t *value)
+{
+ struct shared_network *shared_network;
+ isc_result_t status;
+ int foo;
+
+ if (h -> type != dhcp_type_shared_network)
+ return ISC_R_INVALIDARG;
+ shared_network = (struct shared_network *)h;
+
+ /* No values to set yet. */
+
+ /* Try to find some inner object that can take the value. */
+ if (h -> inner && h -> inner -> type -> set_value) {
+ status = ((*(h -> inner -> type -> set_value))
+ (h -> inner, id, name, value));
+ if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED)
+ return status;
+ }
+
+ return ISC_R_NOTFOUND;
+}
+
+
+isc_result_t dhcp_shared_network_get_value (omapi_object_t *h,
+ omapi_object_t *id,
+ omapi_data_string_t *name,
+ omapi_value_t **value)
+{
+ struct shared_network *shared_network;
+ isc_result_t status;
+
+ if (h -> type != dhcp_type_shared_network)
+ return ISC_R_INVALIDARG;
+ shared_network = (struct shared_network *)h;
+
+ /* No values to get yet. */
+
+ /* Try to find some inner object that can provide the value. */
+ if (h -> inner && h -> inner -> type -> get_value) {
+ status = ((*(h -> inner -> type -> get_value))
+ (h -> inner, id, name, value));
+ if (status == ISC_R_SUCCESS)
+ return status;
+ }
+ return ISC_R_NOTFOUND;
+}
+
+isc_result_t dhcp_shared_network_destroy (omapi_object_t *h,
+ const char *file, int line)
+{
+ struct shared_network *shared_network;
+ isc_result_t status;
+
+ if (h -> type != dhcp_type_shared_network)
+ return ISC_R_INVALIDARG;
+ shared_network = (struct shared_network *)h;
+
+#if defined (DEBUG_MEMORY_LEAKAGE) || \
+ defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
+ if (shared_network -> next)
+ shared_network_dereference (&shared_network -> next,
+ file, line);
+ if (shared_network -> name) {
+ dfree (shared_network -> name, file, line);
+ shared_network -> name = 0;
+ }
+ if (shared_network -> subnets)
+ subnet_dereference (&shared_network -> subnets, file, line);
+ if (shared_network -> interface)
+ interface_dereference (&shared_network -> interface,
+ file, line);
+ if (shared_network -> pools)
+ omapi_object_dereference ((omapi_object_t **)
+ &shared_network -> pools, file, line);
+ if (shared_network -> group)
+ group_dereference (&shared_network -> group, file, line);
+#if defined (FAILOVER_PROTOCOL)
+ if (shared_network -> failover_peer)
+ omapi_object_dereference ((omapi_object_t **)
+ &shared_network -> failover_peer,
+ file, line);
+#endif
+#endif /* DEBUG_MEMORY_LEAKAGE */
+
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_shared_network_signal_handler (omapi_object_t *h,
+ const char *name,
+ va_list ap)
+{
+ struct shared_network *shared_network;
+ isc_result_t status;
+ int updatep = 0;
+
+ if (h -> type != dhcp_type_shared_network)
+ return ISC_R_INVALIDARG;
+ shared_network = (struct shared_network *)h;
+
+ /* Can't write shared_networks yet. */
+
+ /* Try to find some inner object that can take the value. */
+ if (h -> inner && h -> inner -> type -> get_value) {
+ status = ((*(h -> inner -> type -> signal_handler))
+ (h -> inner, name, ap));
+ if (status == ISC_R_SUCCESS)
+ return status;
+ }
+ if (updatep)
+ return ISC_R_SUCCESS;
+ return ISC_R_NOTFOUND;
+}
+
+isc_result_t dhcp_shared_network_stuff_values (omapi_object_t *c,
+ omapi_object_t *id,
+ omapi_object_t *h)
+{
+ struct shared_network *shared_network;
+ isc_result_t status;
+
+ if (h -> type != dhcp_type_shared_network)
+ return ISC_R_INVALIDARG;
+ shared_network = (struct shared_network *)h;
+
+ /* Can't stuff shared_network values yet. */
+
+ /* Write out the inner object, if any. */
+ if (h -> inner && h -> inner -> type -> stuff_values) {
+ status = ((*(h -> inner -> type -> stuff_values))
+ (c, id, h -> inner));
+ if (status == ISC_R_SUCCESS)
+ return status;
+ }
+
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_shared_network_lookup (omapi_object_t **lp,
+ omapi_object_t *id,
+ omapi_object_t *ref)
+{
+ omapi_value_t *tv = (omapi_value_t *)0;
+ isc_result_t status;
+ struct shared_network *shared_network;
+
+ /* Can't look up shared_networks yet. */
+
+ /* If we get to here without finding a shared_network, no valid key was
+ specified. */
+ if (!*lp)
+ return ISC_R_NOKEYS;
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_shared_network_create (omapi_object_t **lp,
+ omapi_object_t *id)
+{
+ return ISC_R_NOTIMPLEMENTED;
+}
+
+isc_result_t dhcp_shared_network_remove (omapi_object_t *lp,
+ omapi_object_t *id)
+{
+ return ISC_R_NOTIMPLEMENTED;
+}
+
diff --git a/contrib/isc-dhcp/common/conflex.c b/contrib/isc-dhcp/common/conflex.c
index ddb78e60d41e..ac73de54966f 100644
--- a/contrib/isc-dhcp/common/conflex.c
+++ b/contrib/isc-dhcp/common/conflex.c
@@ -3,7 +3,7 @@
Lexical scanner for dhcpd config file... */
/*
- * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium.
+ * Copyright (c) 1995-2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,146 +34,193 @@
* SUCH DAMAGE.
*
* This software has been written for the Internet Software Consortium
- * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
- * Enterprises. To learn more about the Internet Software Consortium,
- * see ``http://www.vix.com/isc''. To learn more about Vixie
- * Enterprises, see ``http://www.vix.com''.
+ * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
+ * To learn more about the Internet Software Consortium, see
+ * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
+ * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
+ * ``http://www.nominum.com''.
*/
#ifndef lint
static char copyright[] =
-"$Id: conflex.c,v 1.29.2.4 1999/04/06 14:58:55 mellon Exp $ Copyright (c) 1995, 1996, 1997 The Internet Software Consortium. All rights reserved.\n";
+"$Id: conflex.c,v 1.92.2.4 2002/01/10 19:35:59 mellon Exp $ Copyright (c) 1995-2001 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
-#include "dhctoken.h"
#include <ctype.h>
-int lexline;
-int lexchar;
-char *token_line;
-char *prev_line;
-char *cur_line;
-char *tlname;
-int eol_token;
-
-static char line1 [81];
-static char line2 [81];
-static int lpos;
-static int line;
-static int tlpos;
-static int tline;
-static int token;
-static int ugflag;
-static char *tval;
-static char tokbuf [1500];
+static int get_char PROTO ((struct parse *));
+static enum dhcp_token get_token PROTO ((struct parse *));
+static void skip_to_eol PROTO ((struct parse *));
+static enum dhcp_token read_string PROTO ((struct parse *));
+static enum dhcp_token read_number PROTO ((int, struct parse *));
+static enum dhcp_token read_num_or_name PROTO ((int, struct parse *));
+static enum dhcp_token intern PROTO ((char *, enum dhcp_token));
-#ifdef OLD_LEXER
-char comments [4096];
-int comment_index;
-#endif
+isc_result_t new_parse (cfile, file, inbuf, buflen, name, eolp)
+ struct parse **cfile;
+ int file;
+ char *inbuf;
+ unsigned buflen;
+ const char *name;
+ int eolp;
+{
+ struct parse *tmp;
+
+ tmp = dmalloc (sizeof (struct parse), MDL);
+ if (!tmp)
+ return ISC_R_NOMEMORY;
+ memset (tmp, 0, sizeof *tmp);
+ tmp -> token = 0;
+ tmp -> tlname = name;
+ tmp -> lpos = tmp -> line = 1;
+ tmp -> cur_line = tmp -> line1;
+ tmp -> prev_line = tmp -> line2;
+ tmp -> token_line = tmp -> cur_line;
+ tmp -> cur_line [0] = tmp -> prev_line [0] = 0;
+ tmp -> warnings_occurred = 0;
+ tmp -> file = file;
+ tmp -> eol_token = eolp;
-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_name PROTO ((int, FILE *));
-static int intern PROTO ((char *, int));
+ tmp -> bufix = 0;
+ tmp -> buflen = buflen;
+ if (inbuf) {
+ tmp -> bufsiz = 0;
+ tmp -> inbuf = inbuf;
+ } else {
+ tmp -> inbuf = dmalloc (8192, MDL);
+ if (!tmp -> inbuf) {
+ dfree (tmp, MDL);
+ return ISC_R_NOMEMORY;
+ }
+ tmp -> bufsiz = 8192;
+ }
-void new_parse (name)
- char *name;
+ *cfile = tmp;
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t end_parse (cfile)
+ struct parse **cfile;
{
- tlname = name;
- lpos = line = 1;
- cur_line = line1;
- prev_line = line2;
- token_line = cur_line;
- cur_line [0] = prev_line [0] = 0;
- warnings_occurred = 0;
+ if ((*cfile) -> bufsiz)
+ dfree ((*cfile) -> inbuf, MDL);
+ dfree (*cfile, MDL);
+ *cfile = (struct parse *)0;
+ return ISC_R_SUCCESS;
}
static int get_char (cfile)
- FILE *cfile;
+ struct parse *cfile;
{
- int c = getc (cfile);
- if (!ugflag) {
+ /* My kingdom for WITH... */
+ int c;
+
+ if (cfile -> bufix == cfile -> buflen) {
+ if (cfile -> file != -1) {
+ cfile -> buflen =
+ read (cfile -> file,
+ cfile -> inbuf, cfile -> bufsiz);
+ if (cfile -> buflen == 0) {
+ c = EOF;
+ cfile -> bufix = 0;
+ } else if (cfile -> buflen < 0) {
+ c = EOF;
+ cfile -> bufix = cfile -> buflen = 0;
+ } else {
+ c = cfile -> inbuf [0];
+ cfile -> bufix = 1;
+ }
+ } else
+ c = EOF;
+ } else {
+ c = cfile -> inbuf [cfile -> bufix];
+ cfile -> bufix++;
+ }
+
+ if (!cfile -> ugflag) {
if (c == EOL) {
- if (cur_line == line1) {
- cur_line = line2;
- prev_line = line1;
+ if (cfile -> cur_line == cfile -> line1) {
+ cfile -> cur_line = cfile -> line2;
+ cfile -> prev_line = cfile -> line1;
} else {
- cur_line = line2;
- prev_line = line1;
+ cfile -> cur_line = cfile -> line1;
+ cfile -> prev_line = cfile -> line2;
}
- line++;
- lpos = 1;
- cur_line [0] = 0;
+ cfile -> line++;
+ cfile -> lpos = 1;
+ cfile -> cur_line [0] = 0;
} else if (c != EOF) {
- if (lpos <= 81) {
- cur_line [lpos - 1] = c;
- cur_line [lpos] = 0;
+ if (cfile -> lpos <= 80) {
+ cfile -> cur_line [cfile -> lpos - 1] = c;
+ cfile -> cur_line [cfile -> lpos] = 0;
}
- lpos++;
+ cfile -> lpos++;
}
} else
- ugflag = 0;
+ cfile -> ugflag = 0;
return c;
}
-static int get_token (cfile)
- FILE *cfile;
+static enum dhcp_token get_token (cfile)
+ struct parse *cfile;
{
int c;
- int ttok;
+ enum dhcp_token ttok;
static char tb [2];
int l, p, u;
do {
- l = line;
- p = lpos;
- u = ugflag;
+ l = cfile -> line;
+ p = cfile -> lpos;
+ u = cfile -> ugflag;
c = get_char (cfile);
#ifdef OLD_LEXER
if (c == '\n' && p == 1 && !u
- && comment_index < sizeof comments)
- comments [comment_index++] = '\n';
+ && cfile -> comment_index < sizeof cfile -> comments)
+ cfile -> comments [cfile -> comment_index++] = '\n';
#endif
- if (!(c == '\n' && eol_token) && isascii (c) && isspace (c))
+ if (!(c == '\n' && cfile -> eol_token)
+ && isascii (c) && isspace (c))
continue;
if (c == '#') {
#ifdef OLD_LEXER
- if (comment_index < sizeof comments)
- comments [comment_index++] = '#';
+ if (cfile -> comment_index < sizeof cfile -> comments)
+ cfile -> comments [cfile -> comment_index++] = '#';
#endif
skip_to_eol (cfile);
continue;
}
if (c == '"') {
- lexline = l;
- lexchar = p;
+ cfile -> lexline = l;
+ cfile -> lexchar = p;
ttok = read_string (cfile);
break;
}
if ((isascii (c) && isdigit (c)) || c == '-') {
- lexline = l;
- lexchar = p;
+ cfile -> lexline = l;
+ cfile -> lexchar = p;
ttok = read_number (c, cfile);
break;
} else if (isascii (c) && isalpha (c)) {
- lexline = l;
- lexchar = p;
+ cfile -> lexline = l;
+ cfile -> lexchar = p;
ttok = read_num_or_name (c, cfile);
break;
+ } else if (c == EOF) {
+ ttok = END_OF_FILE;
+ cfile -> tlen = 0;
+ break;
} else {
- lexline = l;
- lexchar = p;
+ cfile -> lexline = l;
+ cfile -> lexchar = p;
tb [0] = c;
tb [1] = 0;
- tval = tb;
+ cfile -> tval = tb;
+ cfile -> tlen = 1;
ttok = c;
break;
}
@@ -181,56 +228,68 @@ static int get_token (cfile)
return ttok;
}
-int next_token (rval, cfile)
- char **rval;
- FILE *cfile;
+enum dhcp_token next_token (rval, rlen, cfile)
+ const char **rval;
+ unsigned *rlen;
+ struct parse *cfile;
{
int rv;
- if (token) {
- if (lexline != tline)
- token_line = cur_line;
- lexchar = tlpos;
- lexline = tline;
- rv = token;
- token = 0;
+ if (cfile -> token) {
+ if (cfile -> lexline != cfile -> tline)
+ cfile -> token_line = cfile -> cur_line;
+ cfile -> lexchar = cfile -> tlpos;
+ cfile -> lexline = cfile -> tline;
+ rv = cfile -> token;
+ cfile -> token = 0;
} else {
rv = get_token (cfile);
- token_line = cur_line;
+ cfile -> token_line = cfile -> cur_line;
}
if (rval)
- *rval = tval;
+ *rval = cfile -> tval;
+ if (rlen)
+ *rlen = cfile -> tlen;
#ifdef DEBUG_TOKENS
- fprintf (stderr, "%s:%d ", tval, rv);
+ fprintf (stderr, "%s:%d ", cfile -> tval, rv);
#endif
return rv;
}
-int peek_token (rval, cfile)
- char **rval;
- FILE *cfile;
+enum dhcp_token peek_token (rval, rlen, cfile)
+ const char **rval;
+ unsigned int *rlen;
+ struct parse *cfile;
{
int x;
- if (!token) {
- tlpos = lexchar;
- tline = lexline;
- token = get_token (cfile);
- if (lexline != tline)
- token_line = prev_line;
- x = lexchar; lexchar = tlpos; tlpos = x;
- x = lexline; lexline = tline; tline = x;
+ if (!cfile -> token) {
+ cfile -> tlpos = cfile -> lexchar;
+ cfile -> tline = cfile -> lexline;
+ cfile -> token = get_token (cfile);
+ if (cfile -> lexline != cfile -> tline)
+ cfile -> token_line = cfile -> prev_line;
+
+ x = cfile -> lexchar;
+ cfile -> lexchar = cfile -> tlpos;
+ cfile -> tlpos = x;
+
+ x = cfile -> lexline;
+ cfile -> lexline = cfile -> tline;
+ cfile -> tline = x;
}
if (rval)
- *rval = tval;
+ *rval = cfile -> tval;
+ if (rlen)
+ *rlen = cfile -> tlen;
#ifdef DEBUG_TOKENS
- fprintf (stderr, "(%s:%d) ", tval, token);
+ fprintf (stderr, "(%s:%d) ", cfile -> tval, cfile -> token);
#endif
- return token;
+ return cfile -> token;
}
static void skip_to_eol (cfile)
- FILE *cfile;
+ struct parse *cfile;
{
int c;
do {
@@ -238,8 +297,8 @@ static void skip_to_eol (cfile)
if (c == EOF)
return;
#ifdef OLD_LEXER
- if (comment_index < sizeof (comments))
- comments [comment_index++] = c;
+ if (cfile -> comment_index < sizeof (cfile -> comments))
+ comments [cfile -> comment_index++] = c;
#endif
if (c == EOL) {
return;
@@ -247,50 +306,125 @@ static void skip_to_eol (cfile)
} while (1);
}
-static int read_string (cfile)
- FILE *cfile;
+static enum dhcp_token read_string (cfile)
+ struct parse *cfile;
{
int i;
int bs = 0;
int c;
+ int value;
+ int hex;
- for (i = 0; i < sizeof tokbuf; i++) {
+ for (i = 0; i < sizeof cfile -> tokbuf; i++) {
+ again:
c = get_char (cfile);
if (c == EOF) {
- parse_warn ("eof in string constant");
+ parse_warn (cfile, "eof in string constant");
break;
}
- if (bs) {
+ if (bs == 1) {
+ switch (c) {
+ case 't':
+ cfile -> tokbuf [i] = '\t';
+ break;
+ case 'r':
+ cfile -> tokbuf [i] = '\r';
+ break;
+ case 'n':
+ cfile -> tokbuf [i] = '\n';
+ break;
+ case 'b':
+ cfile -> tokbuf [i] = '\b';
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ hex = 0;
+ value = c - '0';
+ ++bs;
+ goto again;
+ case 'x':
+ hex = 1;
+ value = 0;
+ ++bs;
+ goto again;
+ default:
+ cfile -> tokbuf [i] = c;
+ bs = 0;
+ break;
+ }
bs = 0;
- tokbuf [i] = c;
- } else if (c == '\\')
+ } else if (bs > 1) {
+ if (hex) {
+ if (c >= '0' && c <= '9') {
+ value = value * 16 + (c - '0');
+ } else if (c >= 'a' && c <= 'f') {
+ value = value * 16 + (c - 'a' + 10);
+ } else if (c >= 'A' && c <= 'F') {
+ value = value * 16 + (c - 'A' + 10);
+ } else {
+ parse_warn (cfile,
+ "invalid hex digit: %x",
+ c);
+ bs = 0;
+ continue;
+ }
+ if (++bs == 4) {
+ cfile -> tokbuf [i] = value;
+ bs = 0;
+ } else
+ goto again;
+ } else {
+ if (c >= '0' && c <= '9') {
+ value = value * 8 + (c - '0');
+ } else {
+ if (value != 0) {
+ parse_warn (cfile,
+ "invalid octal digit %x",
+ c);
+ continue;
+ } else
+ cfile -> tokbuf [i] = 0;
+ bs = 0;
+ }
+ if (++bs == 4) {
+ cfile -> tokbuf [i] = value;
+ bs = 0;
+ } else
+ goto again;
+ }
+ } else if (c == '\\') {
bs = 1;
- else if (c == '"')
+ goto again;
+ } else if (c == '"')
break;
else
- tokbuf [i] = c;
+ cfile -> 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");
+ if (i == sizeof cfile -> tokbuf) {
+ parse_warn (cfile,
+ "string constant larger than internal buffer");
--i;
}
- tokbuf [i] = 0;
- tval = tokbuf;
+ cfile -> tokbuf [i] = 0;
+ cfile -> tlen = i;
+ cfile -> tval = cfile -> tokbuf;
return STRING;
}
-static int read_number (c, cfile)
+static enum dhcp_token read_number (c, cfile)
int c;
- FILE *cfile;
+ struct parse *cfile;
{
int seenx = 0;
int i = 0;
int token = NUMBER;
- tokbuf [i++] = c;
- for (; i < sizeof tokbuf; i++) {
+ cfile -> tokbuf [i++] = c;
+ for (; i < sizeof cfile -> tokbuf; i++) {
c = get_char (cfile);
if (!seenx && c == 'x') {
seenx = 1;
@@ -302,95 +436,190 @@ static int read_number (c, cfile)
token = NUMBER_OR_NAME;
#endif
} else if (!isascii (c) || !isxdigit (c)) {
- ungetc (c, cfile);
- ugflag = 1;
+ if (c != EOF) {
+ cfile -> bufix--;
+ cfile -> ugflag = 1;
+ }
break;
}
- tokbuf [i] = c;
+ cfile -> tokbuf [i] = c;
}
- if (i == sizeof tokbuf) {
- parse_warn ("numeric token larger than internal buffer");
+ if (i == sizeof cfile -> tokbuf) {
+ parse_warn (cfile,
+ "numeric token larger than internal buffer");
--i;
}
- tokbuf [i] = 0;
- tval = tokbuf;
+ cfile -> tokbuf [i] = 0;
+ cfile -> tlen = i;
+ cfile -> tval = cfile -> tokbuf;
return token;
}
-static int read_num_or_name (c, cfile)
+static enum dhcp_token read_num_or_name (c, cfile)
int c;
- FILE *cfile;
+ struct parse *cfile;
{
int i = 0;
- int rv = NUMBER_OR_NAME;
- tokbuf [i++] = c;
- for (; i < sizeof tokbuf; i++) {
+ enum dhcp_token rv = NUMBER_OR_NAME;
+ cfile -> tokbuf [i++] = c;
+ for (; i < sizeof cfile -> tokbuf; i++) {
c = get_char (cfile);
if (!isascii (c) ||
(c != '-' && c != '_' && !isalnum (c))) {
- ungetc (c, cfile);
- ugflag = 1;
+ if (c != EOF) {
+ cfile -> bufix--;
+ cfile -> ugflag = 1;
+ }
break;
}
if (!isxdigit (c))
rv = NAME;
- tokbuf [i] = c;
+ cfile -> tokbuf [i] = c;
}
- if (i == sizeof tokbuf) {
- parse_warn ("token larger than internal buffer");
+ if (i == sizeof cfile -> tokbuf) {
+ parse_warn (cfile, "token larger than internal buffer");
--i;
}
- tokbuf [i] = 0;
- tval = tokbuf;
- return intern (tval, rv);
+ cfile -> tokbuf [i] = 0;
+ cfile -> tlen = i;
+ cfile -> tval = cfile -> tokbuf;
+ return intern (cfile -> tval, rv);
}
-static int intern (atom, dfv)
+static enum dhcp_token intern (atom, dfv)
char *atom;
- int dfv;
+ enum dhcp_token dfv;
{
if (!isascii (atom [0]))
return dfv;
switch (tolower (atom [0])) {
+ case '-':
+ if (atom [1] == 0)
+ return MINUS;
+ break;
+
case 'a':
- if (!strcasecmp (atom + 1, "lways-reply-rfc1048"))
- return ALWAYS_REPLY_RFC1048;
+ if (!strncasecmp (atom + 1, "uth", 3)) {
+ if (!strncasecmp (atom + 3, "uthenticat", 10)) {
+ if (!strcasecmp (atom + 13, "ed"))
+ return AUTHENTICATED;
+ if (!strcasecmp (atom + 13, "ion"))
+ return AUTHENTICATION;
+ break;
+ }
+ if (!strcasecmp (atom + 1, "uthoritative"))
+ return AUTHORITATIVE;
+ break;
+ }
+ if (!strcasecmp (atom + 1, "nd"))
+ return AND;
if (!strcasecmp (atom + 1, "ppend"))
return APPEND;
if (!strcasecmp (atom + 1, "llow"))
return ALLOW;
if (!strcasecmp (atom + 1, "lias"))
return ALIAS;
+ if (!strcasecmp (atom + 1, "lgorithm"))
+ return ALGORITHM;
if (!strcasecmp (atom + 1, "bandoned"))
- return ABANDONED;
- if (!strcasecmp (atom + 1, "uthoritative"))
- return AUTHORITATIVE;
+ return TOKEN_ABANDONED;
+ if (!strcasecmp (atom + 1, "dd"))
+ return TOKEN_ADD;
+ if (!strcasecmp (atom + 1, "ll"))
+ return ALL;
+ if (!strcasecmp (atom + 1, "t"))
+ return AT;
+ if (!strcasecmp (atom + 1, "rray"))
+ return ARRAY;
+ if (!strcasecmp (atom + 1, "ddress"))
+ return ADDRESS;
+ if (!strcasecmp (atom + 1, "ctive"))
+ return TOKEN_ACTIVE;
break;
case 'b':
+ if (!strcasecmp (atom + 1, "ackup"))
+ return TOKEN_BACKUP;
+ if (!strcasecmp (atom + 1, "ootp"))
+ return TOKEN_BOOTP;
+ if (!strcasecmp (atom + 1, "inding"))
+ return BINDING;
+ if (!strcasecmp (atom + 1, "inary-to-ascii"))
+ return BINARY_TO_ASCII;
if (!strcasecmp (atom + 1, "ackoff-cutoff"))
return BACKOFF_CUTOFF;
- if (!strcasecmp (atom + 1, "ootp"))
- return BOOTP;
if (!strcasecmp (atom + 1, "ooting"))
return BOOTING;
if (!strcasecmp (atom + 1, "oot-unknown-clients"))
return BOOT_UNKNOWN_CLIENTS;
+ if (!strcasecmp (atom + 1, "reak"))
+ return BREAK;
+ if (!strcasecmp (atom + 1, "illing"))
+ return BILLING;
+ if (!strcasecmp (atom + 1, "oolean"))
+ return BOOLEAN;
+ if (!strcasecmp (atom + 1, "alance"))
+ return BALANCE;
+ if (!strcasecmp (atom + 1, "ound"))
+ return BOUND;
+ break;
case 'c':
+ if (!strcasecmp (atom + 1, "ase"))
+ return CASE;
+ if (!strcasecmp (atom + 1, "ommit"))
+ return COMMIT;
+ if (!strcasecmp (atom + 1, "ode"))
+ return CODE;
+ if (!strcasecmp (atom + 1, "onfig-option"))
+ return CONFIG_OPTION;
+ if (!strcasecmp (atom + 1, "heck"))
+ return CHECK;
if (!strcasecmp (atom + 1, "lass"))
return CLASS;
+ if (!strcasecmp (atom + 1, "lose"))
+ return TOKEN_CLOSE;
+ if (!strcasecmp (atom + 1, "reate"))
+ return TOKEN_CREATE;
if (!strcasecmp (atom + 1, "iaddr"))
return CIADDR;
- if (!strcasecmp (atom + 1, "lient-identifier"))
- return CLIENT_IDENTIFIER;
- if (!strcasecmp (atom + 1, "lient-hostname"))
- return CLIENT_HOSTNAME;
+ if (!strncasecmp (atom + 1, "lient", 5)) {
+ if (!strcasecmp (atom + 6, "-identifier"))
+ return CLIENT_IDENTIFIER;
+ if (!strcasecmp (atom + 6, "-hostname"))
+ return CLIENT_HOSTNAME;
+ if (!strcasecmp (atom + 6, "-state"))
+ return CLIENT_STATE;
+ if (!strcasecmp (atom + 6, "-updates"))
+ return CLIENT_UPDATES;
+ if (!strcasecmp (atom + 6, "s"))
+ return CLIENTS;
+ }
+ if (!strcasecmp (atom + 1, "oncat"))
+ return CONCAT;
+ if (!strcasecmp (atom + 1, "onnect"))
+ return CONNECT;
+ if (!strcasecmp (atom + 1, "ommunications-interrupted"))
+ return COMMUNICATIONS_INTERRUPTED;
+ if (!strcasecmp (atom + 1, "ltt"))
+ return CLTT;
break;
case 'd':
+ if (!strcasecmp (atom + 1, "ns-update"))
+ return DNS_UPDATE;
+ if (!strcasecmp (atom + 1, "ns-delete"))
+ return DNS_DELETE;
if (!strcasecmp (atom + 1, "omain"))
return DOMAIN;
+ if (!strcasecmp (atom + 1, "omain-name"))
+ return DOMAIN_NAME;
+ if (!strcasecmp (atom + 1, "ebug"))
+ return TOKEN_DEBUG;
if (!strcasecmp (atom + 1, "eny"))
return DENY;
+ if (!strcasecmp (atom + 1, "eleted"))
+ return TOKEN_DELETED;
+ if (!strcasecmp (atom + 1, "elete"))
+ return TOKEN_DELETE;
if (!strncasecmp (atom + 1, "efault", 6)) {
if (!atom [7])
return DEFAULT;
@@ -398,31 +627,80 @@ static int intern (atom, dfv)
return DEFAULT_LEASE_TIME;
break;
}
- if (!strncasecmp (atom + 1, "ynamic-bootp", 12)) {
- if (!atom [13])
- return DYNAMIC_BOOTP;
- if (!strcasecmp (atom + 13, "-lease-cutoff"))
- return DYNAMIC_BOOTP_LEASE_CUTOFF;
- if (!strcasecmp (atom + 13, "-lease-length"))
- return DYNAMIC_BOOTP_LEASE_LENGTH;
- break;
+ if (!strncasecmp (atom + 1, "ynamic", 6)) {
+ if (!atom [7])
+ return DYNAMIC;
+ if (!strncasecmp (atom + 7, "-bootp", 6)) {
+ if (!atom [13])
+ return DYNAMIC_BOOTP;
+ if (!strcasecmp (atom + 13, "-lease-cutoff"))
+ return DYNAMIC_BOOTP_LEASE_CUTOFF;
+ if (!strcasecmp (atom + 13, "-lease-length"))
+ return DYNAMIC_BOOTP_LEASE_LENGTH;
+ break;
+ }
+ }
+ if (!strcasecmp (atom + 1, "uplicates"))
+ return DUPLICATES;
+ if (!strcasecmp (atom + 1, "eclines"))
+ return DECLINES;
+ if (!strncasecmp (atom + 1, "efine", 5)) {
+ if (!strcasecmp (atom + 6, "d"))
+ return DEFINED;
+ if (!atom [6])
+ return DEFINE;
}
break;
case 'e':
+ if (isascii (atom [1]) && tolower (atom [1]) == 'x') {
+ if (!strcasecmp (atom + 2, "tract-int"))
+ return EXTRACT_INT;
+ if (!strcasecmp (atom + 2, "ists"))
+ return EXISTS;
+ if (!strcasecmp (atom + 2, "piry"))
+ return EXPIRY;
+ if (!strcasecmp (atom + 2, "pire"))
+ return EXPIRE;
+ if (!strcasecmp (atom + 2, "pired"))
+ return TOKEN_EXPIRED;
+ }
+ if (!strcasecmp (atom + 1, "ncode-int"))
+ return ENCODE_INT;
if (!strcasecmp (atom + 1, "thernet"))
return ETHERNET;
if (!strcasecmp (atom + 1, "nds"))
return ENDS;
- if (!strcasecmp (atom + 1, "xpire"))
- return EXPIRE;
+ if (!strncasecmp (atom + 1, "ls", 2)) {
+ if (!strcasecmp (atom + 3, "e"))
+ return ELSE;
+ if (!strcasecmp (atom + 3, "if"))
+ return ELSIF;
+ break;
+ }
+ if (!strcasecmp (atom + 1, "rror"))
+ return ERROR;
+ if (!strcasecmp (atom + 1, "val"))
+ return EVAL;
+ if (!strcasecmp (atom + 1, "ncapsulate"))
+ return ENCAPSULATE;
break;
case 'f':
+ if (!strcasecmp (atom + 1, "atal"))
+ return FATAL;
if (!strcasecmp (atom + 1, "ilename"))
return FILENAME;
if (!strcasecmp (atom + 1, "ixed-address"))
return FIXED_ADDR;
if (!strcasecmp (atom + 1, "ddi"))
return FDDI;
+ if (!strcasecmp (atom + 1, "ormerr"))
+ return NS_FORMERR;
+ if (!strcasecmp (atom + 1, "unction"))
+ return FUNCTION;
+ if (!strcasecmp (atom + 1, "ailover"))
+ return FAILOVER;
+ if (!strcasecmp (atom + 1, "ree"))
+ return TOKEN_FREE;
break;
case 'g':
if (!strcasecmp (atom + 1, "iaddr"))
@@ -433,26 +711,85 @@ static int intern (atom, dfv)
return GET_LEASE_HOSTNAMES;
break;
case 'h':
+ if (!strcasecmp (atom + 1, "ba"))
+ return HBA;
if (!strcasecmp (atom + 1, "ost"))
return HOST;
+ if (!strcasecmp (atom + 1, "ost-decl-name"))
+ return HOST_DECL_NAME;
if (!strcasecmp (atom + 1, "ardware"))
return HARDWARE;
if (!strcasecmp (atom + 1, "ostname"))
return HOSTNAME;
+ if (!strcasecmp (atom + 1, "elp"))
+ return TOKEN_HELP;
break;
case 'i':
+ if (!strcasecmp (atom + 1, "nclude"))
+ return INCLUDE;
+ if (!strcasecmp (atom + 1, "nteger"))
+ return INTEGER;
+ if (!strcasecmp (atom + 1, "nfinite"))
+ return INFINITE;
+ if (!strcasecmp (atom + 1, "nfo"))
+ return INFO;
+ if (!strcasecmp (atom + 1, "p-address"))
+ return IP_ADDRESS;
if (!strcasecmp (atom + 1, "nitial-interval"))
return INITIAL_INTERVAL;
if (!strcasecmp (atom + 1, "nterface"))
return INTERFACE;
+ if (!strcasecmp (atom + 1, "dentifier"))
+ return IDENTIFIER;
+ if (!strcasecmp (atom + 1, "f"))
+ return IF;
+ if (!strcasecmp (atom + 1, "s"))
+ return IS;
+ if (!strcasecmp (atom + 1, "gnore"))
+ return IGNORE;
+ break;
+ case 'k':
+ if (!strcasecmp (atom + 1, "nown"))
+ return KNOWN;
+ if (!strcasecmp (atom + 1, "ey"))
+ return KEY;
break;
case 'l':
if (!strcasecmp (atom + 1, "ease"))
return LEASE;
+ if (!strcasecmp (atom + 1, "eased-address"))
+ return LEASED_ADDRESS;
+ if (!strcasecmp (atom + 1, "ease-time"))
+ return LEASE_TIME;
+ if (!strcasecmp (atom + 1, "imit"))
+ return LIMIT;
+ if (!strcasecmp (atom + 1, "et"))
+ return LET;
+ if (!strcasecmp (atom + 1, "oad"))
+ return LOAD;
+ if (!strcasecmp (atom + 1, "og"))
+ return LOG;
break;
case 'm':
- if (!strcasecmp (atom + 1, "ax-lease-time"))
- return MAX_LEASE_TIME;
+ if (!strncasecmp (atom + 1, "ax", 2)) {
+ if (!atom [3])
+ return TOKEN_MAX;
+ if (!strcasecmp (atom + 3, "-lease-time"))
+ return MAX_LEASE_TIME;
+ if (!strcasecmp (atom + 3, "-transmit-idle"))
+ return MAX_TRANSMIT_IDLE;
+ if (!strcasecmp (atom + 3, "-response-delay"))
+ return MAX_RESPONSE_DELAY;
+ if (!strcasecmp (atom + 3, "-unacked-updates"))
+ return MAX_UNACKED_UPDATES;
+ }
+ if (!strncasecmp (atom + 1, "in-", 3)) {
+ if (!strcasecmp (atom + 4, "lease-time"))
+ return MIN_LEASE_TIME;
+ if (!strcasecmp (atom + 4, "secs"))
+ return MIN_SECS;
+ break;
+ }
if (!strncasecmp (atom + 1, "edi", 3)) {
if (!strcasecmp (atom + 4, "a"))
return MEDIA;
@@ -460,38 +797,121 @@ static int intern (atom, dfv)
return MEDIUM;
break;
}
+ if (!strcasecmp (atom + 1, "atch"))
+ return MATCH;
+ if (!strcasecmp (atom + 1, "embers"))
+ return MEMBERS;
+ if (!strcasecmp (atom + 1, "y"))
+ return MY;
+ if (!strcasecmp (atom + 1, "clt"))
+ return MCLT;
break;
case 'n':
+ if (!strcasecmp (atom + 1, "ormal"))
+ return NORMAL;
if (!strcasecmp (atom + 1, "ameserver"))
return NAMESERVER;
if (!strcasecmp (atom + 1, "etmask"))
return NETMASK;
+ if (!strcasecmp (atom + 1, "ever"))
+ return NEVER;
if (!strcasecmp (atom + 1, "ext-server"))
return NEXT_SERVER;
if (!strcasecmp (atom + 1, "ot"))
return TOKEN_NOT;
+ if (!strcasecmp (atom + 1, "o"))
+ return NO;
+ if (!strcasecmp (atom + 1, "s-update"))
+ return NS_UPDATE;
+ if (!strcasecmp (atom + 1, "oerror"))
+ return NS_NOERROR;
+ if (!strcasecmp (atom + 1, "otauth"))
+ return NS_NOTAUTH;
+ if (!strcasecmp (atom + 1, "otimp"))
+ return NS_NOTIMP;
+ if (!strcasecmp (atom + 1, "otzone"))
+ return NS_NOTZONE;
+ if (!strcasecmp (atom + 1, "xdomain"))
+ return NS_NXDOMAIN;
+ if (!strcasecmp (atom + 1, "xrrset"))
+ return NS_NXRRSET;
+ if (!strcasecmp (atom + 1, "ull"))
+ return TOKEN_NULL;
+ if (!strcasecmp (atom + 1, "ext"))
+ return TOKEN_NEXT;
+ if (!strcasecmp (atom + 1, "ew"))
+ return TOKEN_NEW;
break;
case 'o':
+ if (!strcasecmp (atom + 1, "mapi"))
+ return OMAPI;
+ if (!strcasecmp (atom + 1, "r"))
+ return OR;
+ if (!strcasecmp (atom + 1, "n"))
+ return ON;
+ if (!strcasecmp (atom + 1, "pen"))
+ return TOKEN_OPEN;
if (!strcasecmp (atom + 1, "ption"))
return OPTION;
if (!strcasecmp (atom + 1, "ne-lease-per-client"))
return ONE_LEASE_PER_CLIENT;
+ if (!strcasecmp (atom + 1, "f"))
+ return OF;
+ if (!strcasecmp (atom + 1, "wner"))
+ return OWNER;
break;
case 'p':
if (!strcasecmp (atom + 1, "repend"))
return PREPEND;
if (!strcasecmp (atom + 1, "acket"))
return PACKET;
+ if (!strcasecmp (atom + 1, "ool"))
+ return POOL;
+ if (!strcasecmp (atom + 1, "seudo"))
+ return PSEUDO;
+ if (!strcasecmp (atom + 1, "eer"))
+ return PEER;
+ if (!strcasecmp (atom + 1, "rimary"))
+ return PRIMARY;
+ if (!strncasecmp (atom + 1, "artner", 6)) {
+ if (!atom [7])
+ return PARTNER;
+ if (!strcasecmp (atom + 7, "-down"))
+ return PARTNER_DOWN;
+ }
+ if (!strcasecmp (atom + 1, "ort"))
+ return PORT;
+ if (!strcasecmp (atom + 1, "otential-conflict"))
+ return POTENTIAL_CONFLICT;
+ if (!strcasecmp (atom + 1, "ick-first-value") ||
+ !strcasecmp (atom + 1, "ick"))
+ return PICK;
+ if (!strcasecmp (atom + 1, "aused"))
+ return PAUSED;
break;
case 'r':
+ if (!strcasecmp (atom + 1, "esolution-interrupted"))
+ return RESOLUTION_INTERRUPTED;
if (!strcasecmp (atom + 1, "ange"))
return RANGE;
+ if (!strcasecmp (atom + 1, "ecover"))
+ return RECOVER;
+ if (!strcasecmp (atom + 1, "ecover-done"))
+ return RECOVER_DONE;
+ if (!strcasecmp (atom + 1, "ecover-wait"))
+ return RECOVER_WAIT;
+ if (!strcasecmp (atom + 1, "econtact-interval"))
+ return RECONTACT_INTERVAL;
if (!strcasecmp (atom + 1, "equest"))
return REQUEST;
if (!strcasecmp (atom + 1, "equire"))
return REQUIRE;
+ if (!strcasecmp (atom + 1, "equire"))
+ return REQUIRE;
if (!strcasecmp (atom + 1, "etry"))
return RETRY;
+ if (!strcasecmp (atom + 1, "eturn"))
+ return RETURN;
if (!strcasecmp (atom + 1, "enew"))
return RENEW;
if (!strcasecmp (atom + 1, "ebind"))
@@ -500,30 +920,89 @@ static int intern (atom, dfv)
return REBOOT;
if (!strcasecmp (atom + 1, "eject"))
return REJECT;
+ if (!strcasecmp (atom + 1, "everse"))
+ return REVERSE;
+ if (!strcasecmp (atom + 1, "elease"))
+ return RELEASE;
+ if (!strcasecmp (atom + 1, "efused"))
+ return NS_REFUSED;
+ if (!strcasecmp (atom + 1, "eleased"))
+ return TOKEN_RELEASED;
+ if (!strcasecmp (atom + 1, "eset"))
+ return TOKEN_RESET;
+ if (!strcasecmp (atom + 1, "eserved"))
+ return TOKEN_RESERVED;
+ if (!strcasecmp (atom + 1, "emove"))
+ return REMOVE;
+ if (!strcasecmp (atom + 1, "efresh"))
+ return REFRESH;
break;
case 's':
+ if (!strcasecmp (atom + 1, "tate"))
+ return STATE;
+ if (!strcasecmp (atom + 1, "ecret"))
+ return SECRET;
+ if (!strcasecmp (atom + 1, "ervfail"))
+ return NS_SERVFAIL;
+ if (!strcasecmp (atom + 1, "witch"))
+ return SWITCH;
+ if (!strcasecmp (atom + 1, "igned"))
+ return SIGNED;
+ if (!strcasecmp (atom + 1, "tring"))
+ return STRING_TOKEN;
+ if (!strcasecmp (atom + 1, "uffix"))
+ return SUFFIX;
if (!strcasecmp (atom + 1, "earch"))
return SEARCH;
if (!strcasecmp (atom + 1, "tarts"))
return STARTS;
if (!strcasecmp (atom + 1, "iaddr"))
return SIADDR;
- if (!strcasecmp (atom + 1, "ubnet"))
- return SUBNET;
if (!strcasecmp (atom + 1, "hared-network"))
return SHARED_NETWORK;
+ if (!strcasecmp (atom + 1, "econdary"))
+ return SECONDARY;
if (!strcasecmp (atom + 1, "erver-name"))
return SERVER_NAME;
if (!strcasecmp (atom + 1, "erver-identifier"))
return SERVER_IDENTIFIER;
+ if (!strcasecmp (atom + 1, "erver"))
+ return SERVER;
if (!strcasecmp (atom + 1, "elect-timeout"))
return SELECT_TIMEOUT;
+ if (!strcasecmp (atom + 1, "elect"))
+ return SELECT;
if (!strcasecmp (atom + 1, "end"))
return SEND;
if (!strcasecmp (atom + 1, "cript"))
return SCRIPT;
if (!strcasecmp (atom + 1, "upersede"))
return SUPERSEDE;
+ if (!strncasecmp (atom + 1, "ub", 2)) {
+ if (!strcasecmp (atom + 3, "string"))
+ return SUBSTRING;
+ if (!strcasecmp (atom + 3, "net"))
+ return SUBNET;
+ if (!strcasecmp (atom + 3, "class"))
+ return SUBCLASS;
+ break;
+ }
+ if (!strcasecmp (atom + 1, "pawn"))
+ return SPAWN;
+ if (!strcasecmp (atom + 1, "pace"))
+ return SPACE;
+ if (!strcasecmp (atom + 1, "tatic"))
+ return STATIC;
+ if (!strcasecmp (atom + 1, "plit"))
+ return SPLIT;
+ if (!strcasecmp (atom + 1, "et"))
+ return TOKEN_SET;
+ if (!strcasecmp (atom + 1, "econds"))
+ return SECONDS;
+ if (!strcasecmp (atom + 1, "hutdown"))
+ return SHUTDOWN;
+ if (!strcasecmp (atom + 1, "tartup"))
+ return STARTUP;
break;
case 't':
if (!strcasecmp (atom + 1, "imestamp"))
@@ -532,8 +1011,22 @@ static int intern (atom, dfv)
return TIMEOUT;
if (!strcasecmp (atom + 1, "oken-ring"))
return TOKEN_RING;
+ if (!strcasecmp (atom + 1, "ext"))
+ return TEXT;
+ if (!strcasecmp (atom + 1, "stp"))
+ return TSTP;
+ if (!strcasecmp (atom + 1, "sfp"))
+ return TSFP;
+ if (!strcasecmp (atom + 1, "ransmission"))
+ return TRANSMISSION;
break;
case 'u':
+ if (!strcasecmp (atom + 1, "nset"))
+ return UNSET;
+ if (!strcasecmp (atom + 1, "nsigned"))
+ return UNSIGNED;
+ if (!strcasecmp (atom + 1, "id"))
+ return UID;
if (!strncasecmp (atom + 1, "se", 2)) {
if (!strcasecmp (atom + 3, "r-class"))
return USER_CLASS;
@@ -544,18 +1037,43 @@ static int intern (atom, dfv)
return USE_LEASE_ADDR_FOR_DEFAULT_ROUTE;
break;
}
- if (!strcasecmp (atom + 1, "id"))
- return UID;
- if (!strcasecmp (atom + 1, "nknown-clients"))
- return UNKNOWN_CLIENTS;
+ if (!strncasecmp (atom + 1, "nknown", 6)) {
+ if (!strcasecmp (atom + 7, "-clients"))
+ return UNKNOWN_CLIENTS;
+ if (!strcasecmp (atom + 7, "-state"))
+ return UNKNOWN_STATE;
+ if (!atom [7])
+ return UNKNOWN;
+ break;
+ }
+ if (!strcasecmp (atom + 1, "nauthenticated"))
+ return AUTHENTICATED;
+ if (!strcasecmp (atom + 1, "pdated-dns-rr"))
+ return UPDATED_DNS_RR;
+ if (!strcasecmp (atom + 1, "pdate"))
+ return UPDATE;
break;
case 'v':
if (!strcasecmp (atom + 1, "endor-class"))
return VENDOR_CLASS;
+ if (!strcasecmp (atom + 1, "endor"))
+ return VENDOR;
+ break;
+ case 'w':
+ if (!strcasecmp (atom + 1, "ith"))
+ return WITH;
break;
case 'y':
if (!strcasecmp (atom + 1, "iaddr"))
return YIADDR;
+ if (!strcasecmp (atom + 1, "xdomain"))
+ return NS_YXDOMAIN;
+ if (!strcasecmp (atom + 1, "xrrset"))
+ return NS_YXRRSET;
+ break;
+ case 'z':
+ if (!strcasecmp (atom + 1, "one"))
+ return ZONE;
break;
}
return dfv;
diff --git a/contrib/isc-dhcp/common/ctrace.c b/contrib/isc-dhcp/common/ctrace.c
new file mode 100644
index 000000000000..bea933cb433c
--- /dev/null
+++ b/contrib/isc-dhcp/common/ctrace.c
@@ -0,0 +1,297 @@
+/* trace.c
+
+ Subroutines that support dhcp tracing... */
+
+/*
+ * Copyright (c) 2001 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, as part of a project for Nominum, Inc. To learn more
+ * about the Internet Software Consortium, see http://www.isc.org/. To
+ * learn more about Nominum, Inc., see ``http://www.nominum.com''.
+ */
+
+#include "dhcpd.h"
+
+#if defined (TRACING)
+void trace_interface_register (trace_type_t *ttype, struct interface_info *ip)
+{
+ trace_interface_packet_t tipkt;
+
+ if (trace_record ()) {
+ memset (&tipkt, 0, sizeof tipkt);
+ memcpy (&tipkt.hw_address,
+ &ip -> hw_address, sizeof ip -> hw_address);
+ memcpy (&tipkt.primary_address,
+ &ip -> primary_address, sizeof ip -> primary_address);
+ memcpy (tipkt.name, ip -> name, sizeof ip -> name);
+ tipkt.index = htonl (ip -> index);
+
+ trace_write_packet (ttype, sizeof tipkt, (char *)&tipkt, MDL);
+ }
+}
+
+void trace_interface_input (trace_type_t *ttype, unsigned len, char *buf)
+{
+ trace_interface_packet_t *tipkt;
+ struct interface_info *ip;
+ struct sockaddr_in *sin;
+ struct iaddr addr;
+ isc_result_t status;
+
+ if (len != sizeof *tipkt) {
+ log_error ("trace interface packet size mismatch: %ld != %d",
+ (long)(sizeof *tipkt), len);
+ return;
+ }
+ tipkt = (trace_interface_packet_t *)buf;
+
+ ip = (struct interface_info *)0;
+ status = interface_allocate (&ip, MDL);
+ if (status != ISC_R_SUCCESS) {
+ foo:
+ log_error ("trace_interface_input: %s.",
+ isc_result_totext (status));
+ return;
+ }
+ ip -> ifp = dmalloc (sizeof *(ip -> ifp), MDL);
+ if (!ip -> ifp) {
+ interface_dereference (&ip, MDL);
+ status = ISC_R_NOMEMORY;
+ goto foo;
+ }
+
+ memcpy (&ip -> hw_address, &tipkt -> hw_address,
+ sizeof ip -> hw_address);
+ memcpy (&ip -> primary_address, &tipkt -> primary_address,
+ sizeof ip -> primary_address);
+ memcpy (ip -> name, tipkt -> name, sizeof ip -> name);
+ ip -> index = ntohl (tipkt -> index);
+
+ interface_snorf (ip, 0);
+ if (dhcp_interface_discovery_hook)
+ (*dhcp_interface_discovery_hook) (ip);
+
+ /* Fake up an ifp. */
+ memcpy (ip -> ifp -> ifr_name, ip -> name, sizeof ip -> name);
+#ifdef HAVE_SA_LEN
+ ip -> ifp -> ifr_addr.sa_len = sizeof (struct sockaddr_in);
+#endif
+ sin = (struct sockaddr_in *)&ip -> ifp -> ifr_addr;
+ sin -> sin_addr = ip -> primary_address;
+
+ addr.len = 4;
+ memcpy (addr.iabuf, &sin -> sin_addr.s_addr, addr.len);
+ if (dhcp_interface_setup_hook)
+ (*dhcp_interface_setup_hook) (ip, &addr);
+ interface_stash (ip);
+
+ if (!quiet_interface_discovery) {
+ log_info ("Listening on Trace/%s/%s%s%s",
+ ip -> name,
+ print_hw_addr (ip -> hw_address.hbuf [0],
+ ip -> hw_address.hlen - 1,
+ &ip -> hw_address.hbuf [1]),
+ (ip -> shared_network ? "/" : ""),
+ (ip -> shared_network ?
+ ip -> shared_network -> name : ""));
+ if (strcmp (ip -> name, "fallback")) {
+ log_info ("Sending on Trace/%s/%s%s%s",
+ ip -> name,
+ print_hw_addr (ip -> hw_address.hbuf [0],
+ ip -> hw_address.hlen - 1,
+ &ip -> hw_address.hbuf [1]),
+ (ip -> shared_network ? "/" : ""),
+ (ip -> shared_network ?
+ ip -> shared_network -> name : ""));
+ }
+ }
+ interface_dereference (&ip, MDL);
+}
+
+void trace_interface_stop (trace_type_t *ttype) {
+ /* XXX */
+}
+
+void trace_inpacket_stash (struct interface_info *interface,
+ struct dhcp_packet *packet,
+ unsigned len,
+ unsigned int from_port,
+ struct iaddr from,
+ struct hardware *hfrom)
+{
+ trace_inpacket_t tip;
+ trace_iov_t iov [2];
+
+ if (!trace_record ())
+ return;
+ tip.from_port = from_port;
+ tip.from = from;
+ if (hfrom) {
+ tip.hfrom = *hfrom;
+ tip.havehfrom = 1;
+ } else {
+ memset (&tip.hfrom, 0, sizeof tip.hfrom);
+ tip.havehfrom = 0;
+ }
+ tip.index = htonl (interface -> index);
+
+ iov [0].buf = (char *)&tip;
+ iov [0].len = sizeof tip;
+ iov [1].buf = (char *)packet;
+ iov [1].len = len;
+ trace_write_packet_iov (inpacket_trace, 2, iov, MDL);
+}
+
+void trace_inpacket_input (trace_type_t *ttype, unsigned len, char *buf)
+{
+ trace_inpacket_t *tip;
+ int index;
+
+ if (len < sizeof *tip) {
+ log_error ("trace_input_packet: too short - %d", len);
+ return;
+ }
+ tip = (trace_inpacket_t *)buf;
+ index = ntohl (tip -> index);
+
+ if (index > interface_count ||
+ index < 0 ||
+ !interface_vector [index]) {
+ log_error ("trace_input_packet: unknown interface index %d",
+ index);
+ return;
+ }
+
+ if (!bootp_packet_handler) {
+ log_error ("trace_input_packet: no bootp packet handler.");
+ return;
+ }
+
+ (*bootp_packet_handler) (interface_vector [index],
+ (struct dhcp_packet *)(tip + 1),
+ len - sizeof *tip,
+ tip -> from_port,
+ tip -> from,
+ (tip -> havehfrom ?
+ &tip -> hfrom
+ : (struct hardware *)0));
+}
+
+void trace_inpacket_stop (trace_type_t *ttype) { }
+
+ssize_t trace_packet_send (struct interface_info *interface,
+ struct packet *packet,
+ struct dhcp_packet *raw,
+ size_t len,
+ struct in_addr from,
+ struct sockaddr_in *to,
+ struct hardware *hto)
+{
+ trace_outpacket_t tip;
+ trace_iov_t iov [2];
+
+ if (trace_record ()) {
+ if (hto) {
+ tip.hto = *hto;
+ tip.havehto = 1;
+ } else {
+ memset (&tip.hto, 0, sizeof tip.hto);
+ tip.havehto = 0;
+ }
+ tip.from.len = 4;
+ memcpy (tip.from.iabuf, &from, 4);
+ tip.to.len = 4;
+ memcpy (tip.to.iabuf, &to -> sin_addr, 4);
+ tip.to_port = to -> sin_port;
+ tip.index = htonl (interface -> index);
+
+ iov [0].buf = (char *)&tip;
+ iov [0].len = sizeof tip;
+ iov [1].buf = (char *)raw;
+ iov [1].len = len;
+ trace_write_packet_iov (outpacket_trace, 2, iov, MDL);
+ }
+ if (!trace_playback ()) {
+ return send_packet (interface, packet, raw, len,
+ from, to, hto);
+ }
+ return len;
+}
+
+void trace_outpacket_input (trace_type_t *ttype, unsigned len, char *buf)
+{
+ trace_outpacket_t *tip;
+ int index;
+
+ if (len < sizeof *tip) {
+ log_error ("trace_input_packet: too short - %d", len);
+ return;
+ }
+ tip = (trace_outpacket_t *)buf;
+ index = ntohl (tip -> index);
+
+ if (index > interface_count ||
+ index < 0 ||
+ !interface_vector [index]) {
+ log_error ("trace_input_packet: unknown interface index %d",
+ index);
+ return;
+ }
+
+ /* XXX would be nice to somehow take notice of these. */
+}
+
+void trace_outpacket_stop (trace_type_t *ttype) { }
+
+void trace_seed_stash (trace_type_t *ttype, unsigned seed)
+{
+ u_int32_t outseed;
+ if (!trace_record ())
+ return;
+ outseed = htonl (seed);
+ trace_write_packet (ttype, sizeof outseed, (char *)&outseed, MDL);
+ return;
+}
+
+void trace_seed_input (trace_type_t *ttype, unsigned length, char *buf)
+{
+ u_int32_t *seed;
+
+ if (length != sizeof seed) {
+ log_error ("trace_seed_input: wrong size (%d)", length);
+ }
+ seed = (u_int32_t *)buf;
+ srandom (ntohl (*seed));
+}
+
+void trace_seed_stop (trace_type_t *ttype) { }
+#endif /* TRACING */
diff --git a/contrib/isc-dhcp/common/dhcp-eval.5 b/contrib/isc-dhcp/common/dhcp-eval.5
new file mode 100644
index 000000000000..cbb77452da2b
--- /dev/null
+++ b/contrib/isc-dhcp/common/dhcp-eval.5
@@ -0,0 +1,484 @@
+.\" dhcp-eval.5
+.\"
+.\" Copyright (c) 1996-2001 Internet Software Consortium.
+.\" 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 and Nominum, Inc.
+.\" To learn more about the Internet Software Consortium, see
+.\" ``http://www.isc.org/''. To learn more about Vixie Enterprises,
+.\" see ``http://www.vix.com''. To learn more about Nominum, Inc., see
+.\" ``http://www.nominum.com''.
+.TH dhcp-eval 5
+.SH NAME
+dhcp-eval - ISC DHCP conditional evaluation
+.SH DESCRIPTION
+The Internet Software Consortium DHCP client and server both provide
+the ability to perform conditional behavior depending on the contents
+of packets they receive. The syntax for specifying this conditional
+behaviour is documented here.
+.SH REFERENCE: CONDITIONAL BEHAVIOUR
+Conditional behaviour is specified using the if statement and the else
+or elsif statements. A conditional statement can appear anywhere
+that a regular statement (e.g., an option statement) can appear, and
+can enclose one or more such statements. A typical conditional
+statement in a server might be:
+.PP
+.nf
+if option dhcp-user-class = "accounting" {
+ max-lease-time 17600;
+ option domain-name "accounting.example.org";
+ option domain-name-servers ns1.accounting.example.org,
+ ns2.accounting.example.org;
+} elsif option dhcp-user-class = "sales" {
+ max-lease-time 17600;
+ option domain-name "sales.example.org";
+ option domain-name-servers ns1.sales.example.org,
+ ns2.sales.example.org;
+} elsif option dhcp-user-class = "engineering" {
+ max-lease-time 17600;
+ option domain-name "engineering.example.org";
+ option domain-name-servers ns1.engineering.example.org,
+ ns2.engineering.example.org;
+} else {
+ max-lease-time 600;
+ option domain-name "misc.example.org";
+ option domain-name-servers ns1.misc.example.org,
+ ns2.misc.example.org;
+}
+.fi
+.PP
+On the client side, an example of conditional evaluation might be:
+.PP
+.nf
+# example.org filters DNS at its firewall, so we have to use their DNS
+# servers when we connect to their network. If we are not at
+# example.org, prefer our own DNS server.
+if not option domain-name = "example.org" {
+ prepend domain-name-servers 127.0.0.1;
+}
+.fi
+.PP
+The
+.B if
+statement and the
+.B elsif
+continuation statement both take boolean expressions as their
+arguments. That is, they take expressions that, when evaluated,
+produce a boolean result. If the expression evaluates to true, then
+the statements enclosed in braces following the
+.B if
+statement are executed, and all subsequent
+.B elsif
+and
+.B else
+clauses are skipped. Otherwise, each subsequent
+.B elsif
+clause's expression is checked, until an elsif clause is encountered
+whose test evaluates to true. If such a clause is found, the
+statements in braces following it are executed, and then any
+subsequent
+.B elsif
+and
+.B else
+clauses are skipped. If all the
+.B if
+and
+.B elsif
+clauses are checked but none
+of their expressions evaluate true, then if there is an
+.B else
+clause, the statements enclosed in braces following the
+.B else
+are evaluated. Boolean expressions that evaluate to null are
+treated as false in conditionals.
+.SH BOOLEAN EXPRESSIONS
+The following is the current list of boolean expressions that are
+supported by the DHCP distribution.
+.PP
+.I data-expression-1 \fB=\fI data-expression-2\fR
+.RS 0.25i
+.PP
+The \fB=\fR operator compares the values of two data expressions,
+returning true if they are the same, false if they are not. If
+either the left-hand side or the right-hand side are null, the
+result is also null.
+.RE
+.PP
+.I boolean-expression-1 \fBand\fI boolean-expression-2\fR
+.PP
+.RS 0.25i
+The \fBand\fR operator evaluates to true if the boolean expression on
+the left-hand side and the boolean expression on the right-hand side
+both evaluate to true. Otherwise, it evaluates to false. If either
+the expression on the left-hand side or the expression on the
+right-hand side are null, the result is null.
+.RE
+.PP
+.I boolean-expression-1 \fBor\fI boolean-expression-2\fR
+.PP
+.RS 0.25i
+The \fBor\fR operator evaluates to true if either the boolean
+expression on the left-hand side or the boolean expression on the
+right-hand side evaluate to true. Otherwise, it evaluates to false.
+If either the expression on the left-hand side or the expression on
+the right-hand side are null, the result is null.
+.RE
+.PP
+.B not \fIboolean-expression
+.PP
+.RS 0.25i
+The \fBnot\fR operator evaluates to true if \fIboolean-expression\fR
+evaluates to false, and returns false if \fIboolean-expression\fR evaluates
+to true. If \fIboolean-expression\fR evaluates to null, the result
+is also null.
+.RE
+.PP
+.B exists \fIoption-name\fR
+.PP
+.RS 0.25i
+The \fBexists\fR expression returns true if the specified option
+exists in the incoming DHCP packet being processed.
+.RE
+.B known
+.PP
+.RS 0.25i
+The \fBknown\fR expression returns true if the client whose request is
+currently being processed is known - that is, if there's a host
+declaration for it.
+.RE
+.B static
+.PP
+.RS 0.25i
+The \fBstatic\fR expression returns true if the lease assigned to the
+client whose request is currently being processed is derived from a static
+address assignment.
+.RE
+.SH DATA EXPRESSIONS
+Several of the boolean expressions above depend on the results of
+evaluating data expressions. A list of these expressions is provided
+here.
+.PP
+.B substring (\fIdata-expr\fB, \fIoffset\fB, \fIlength\fB)\fR
+.PP
+.RS 0.25i
+The \fBsubstring\fR operator evaluates the data expression and returns
+the substring of the result of that evaluation that starts
+\fIoffset\fR bytes from the beginning, continuing for \fIlength\fR
+bytes. \fIOffset\fR and \fIlength\fR are both numeric expressions.
+If \fIdata-expr\fR, \fIoffset\fR or \fIlength\fR evaluate to null,
+then the result is also null. If \fIoffset\fR is greater than or
+equal to the length of the evaluated data, then a zero-length data
+string is returned. If \fIlength\fI is greater then the remaining
+length of the evaluated data after \fIoffset\fR, then a data string
+containing all data from \fIoffset\fR to the end of the evaluated data
+is returned.
+.RE
+.PP
+.B suffix (\fIdata-expr\fB, \fIlength\fB)\fR
+.PP
+.RS 0.25i
+The \fBsuffix\fR operator evaluates \fIdata-expr\fR and returns the
+last \fIlength\fR bytes of the result of that evaluation. \fILength\fR
+is a numeric expression. If \fIdata-expr\fR or \fIlength\fR evaluate
+to null, then the result is also null. If \fIsuffix\fR evaluates to a
+number greater than the length of the evaluated data, then the
+evaluated data is returned.
+.RE
+.PP
+.B option \fIoption-name\fR
+.PP
+.RS 0.25i
+The \fBoption\fR operator returns the contents of the specified option in
+the packet to which the server is responding.
+.RE
+.PP
+.B config-option \fIoption-name\fR
+.PP
+.RS 0.25i
+The \fBconfig-option\fR operator returns the value for the specified option
+that the DHCP client or server has been configured to send.
+.RE
+.PP
+.B hardware
+.PP
+.RS 0.25i
+The \fBhardware\fR operator returns a data string whose first element
+is the type of network interface indicated in packet being considered,
+and whose subsequent elements are client's link-layer address. If
+there is no packet, or if the RFC2131 \fIhlen\fR field is invalid,
+then the result is null. Hardware types include ethernet (1),
+token-ring (6), and fddi (8). Hardware types are specified by the
+IETF, and details on how the type numbers are defined can be found in
+RFC2131 (in the ISC DHCP distribution, this is included in the doc/
+subdirectory).
+.RE
+.PP
+.B packet (\fIoffset\fB, \fIlength\fB)\fR
+.PP
+.RS 0.25i
+The \fBpacket\fR operator returns the specified portion of the packet
+being considered, or null in contexts where no packet is being
+considered. \fIOffset\fR and \fIlength\fR are applied to the
+contents packet as in the \fBsubstring\fR operator.
+.RE
+.PP
+.I string
+.PP
+.RS 0.25i
+A string, enclosed in quotes, may be specified as a data expression,
+and returns the text between the quotes, encoded in ASCII. The
+backslash ('\\') character is treated specially, as in C programming:
+'\\t' means TAB, '\\r' means carriage return, '\\n' means newline, and
+'\\b' means bell. Any octal value can be specified with '\\nnn',
+where nnn is any positive octal number less than 0400. Any
+hexadecimal value can be specified with '\xnn', where nn is any
+positive hexadecimal number less than 0xff.
+.RE
+.PP
+.I colon-seperated hexadecimal list
+.PP
+.RS 0.25i
+A list of hexadecimal octet values, seperated by colons, may be
+specified as a data expression.
+.RE
+.PP
+.B concat (\fIdata-expr1\fB, ..., \fIdata-exprN\fB)\fR
+.RS 0.25i
+The expressions are evaluated, and the results of each evaluation are
+concatenated in the sequence that the subexpressions are listed. If
+any subexpression evaluates to null, the result of the concatenation
+is null.
+.RE
+.PP
+.B reverse (\fInumeric-expr1\fB, \fIdata-expr2\fB)\fR
+.RS 0.25i
+The two expressions are evaluated, and then the result of evaluating
+the data expression is reversed in place, using hunks of the size
+specified in the numeric expression. For example, if the numeric
+expression evaluates to four, and the data expression evaluates to
+twelve bytes of data, then the reverse expression will evaluate to
+twelve bytes of data, consisting of the last four bytes of the the
+input data, followed by the middle four bytes, followed by the first
+four bytes.
+.RE
+.PP
+.B leased-address
+.RS 0.25i
+In any context where the client whose request is being processed has
+been assigned an IP address, this data expression returns that IP
+address.
+.RE
+.PP
+.B binary-to-ascii (\fInumeric-expr1\fB, \fInumeric-expr2\fB,
+.B \fIdata-expr1\fB,\fR \fIdata-expr2\fB)\fR
+.RS 0.25i
+Converts the result of evaluating data-expr2 into a text string
+containing one number for each element of the result of evaluating
+data-expr2. Each number is seperated from the other by the result of
+evaluating data-expr1. The result of evaluating numeric-expr1
+specifies the base (2 through 16) into which the numbers should be
+converted. The result of evaluating numeric-expr2 specifies the
+width in bits of each number, which may be either 8, 16 or 32.
+.PP
+As an example of the preceding three types of expressions, to produce
+the name of a PTR record for the IP address being assigned to a
+client, one could write the following expression:
+.RE
+.PP
+.nf
+ concat (binary-to-ascii (10, 8, ".",
+ reverse (1, leased-address)),
+ ".in-addr.arpa.");
+
+.fi
+.PP
+.B encode-int (\fInumeric-expr\fB, \fIwidth\fB)\fR
+.RS 0.25i
+Numeric-expr is evaluated and encoded as a data string of the
+specified width, in network byte order (most significant byte first).
+If the numeric expression evaluates to the null value, the result is
+also null.
+.PP
+.B pick-first-value (\fIdata-expr1\fR [ ... \fIexpr\fRn ] \fB)\fR
+.RS 0.25i
+The pick-first-value function takes any number of data expressions as
+its arguments. Each expression is evaluated, starting with the first
+in the list, until an expression is found that does not evaluate to a
+null value. That expression is returned, and none of the subsequent
+expressions are evaluated. If all expressions evaluate to a null
+value, the null value is returned.
+.RE
+.PP
+.B host-decl-name
+.RS 0.25i
+The host-decl-name function returns the name of the host declaration
+that matched the client whose request is currently being processed, if
+any. If no host declaration matched, the result is the null value.
+.RE
+.SH NUMERIC EXPRESSIONS
+Numeric expressions are expressions that evaluate to an integer. In
+general, the maximum size of such an integer should not be assumed to
+be representable in fewer than 32 bits, but the precision of such
+integers may be more than 32 bits.
+.PP
+.B extract-int (\fIdata-expr\fB, \fIwidth\fB)\fR
+.PP
+.RS 0.25i
+The \fBextract-int\fR operator extracts an integer value in network
+byte order from the result of evaluating the specified data
+expression. Width is the width in bits of the integer to extract.
+Currently, the only supported widths are 8, 16 and 32. If the
+evaluation of the data expression doesn't provide sufficient bits to
+extract an integer of the specified size, the null value is returned.
+.RE
+.PP
+.B lease-time
+.PP
+.RS 0.25i
+The duration of the current lease - that is, the difference between
+the current time and the time that the lease expires.
+.RE
+.PP
+.I number
+.PP
+.RS 0.25i
+Any number between zero and the maximum representable size may be
+specified as a numeric expression.
+.RE
+.PP
+.B client-state
+.PP
+.RS 0.25i
+The current state of the client instance being processed. This is
+only useful in DHCP client configuration files. Possible values are:
+.TP 2
+.I \(bu
+Booting - DHCP client is in the INIT state, and does not yet have an
+IP address. The next message transmitted will be a DHCPDISCOVER,
+which will be broadcast.
+.TP
+.I \(bu
+Reboot - DHCP client is in the INIT-REBOOT state. It has an IP
+address, but is not yet using it. The next message to be transmitted
+will be a DHCPREQUEST, which will be broadcast. If no response is
+heard, the client will bind to its address and move to the BOUND state.
+.TP
+.I \(bu
+Select - DHCP client is in the SELECTING state - it has received at
+least one DHCPOFFER message, but is waiting to see if it may receive
+other DHCPOFFER messages from other servers. No messages are sent in
+the SELECTING state.
+.TP
+.I \(bu
+Request - DHCP client is in the REQUESTING state - it has received at
+least one DHCPOFFER message, and has chosen which one it will
+request. The next message to be sent will be a DHCPREQUEST message,
+which will be broadcast.
+.TP
+.I \(bu
+Bound - DHCP client is in the BOUND state - it has an IP address. No
+messages are transmitted in this state.
+.TP
+.I \(bu
+Renew - DHCP client is in the RENEWING state - it has an IP address,
+and is trying to contact the server to renew it. The next message to
+be sent will be a DHCPREQUEST message, which will be unicast directly
+to the server.
+.TP
+.I \(bu
+Rebind - DHCP client is in the REBINDING state - it has an IP address,
+and is trying to contact any server to renew it. The next message to
+be sent will be a DHCPREQUEST, which will be broadcast.
+.RE
+.SH REFERENCE: LOGGING
+Logging statements may be used to send information to the standard logging
+channels. A logging statement includes an optional priority (\fBfatal\fR,
+\fBerror\fR, \fBinfo\fR, or \fBdebug\fR), and a data expression.
+.PP
+.B log (\fIpriority\fB, \fIdata-expr\FB)\fR
+.PP
+Logging statements take only a single data expression argument, so if you
+want to output multiple data values, you will need to use the \fBconcat\fR
+operator to concatenate them.
+.RE
+.SH REFERENCE: DYNAMIC DNS UPDATES
+.PP
+The DHCP client and server have the ability to dynamically update the
+Domain Name System. Within the configuration files, you can define
+how you want the Domain Name System to be updated. These updates are
+RFC 2136 compliant so any DNS server supporting RFC 2136 should be
+able to accept updates from the DHCP server.
+.SH SECURITY
+Support for TSIG and DNSSEC is not yet available. When you set your
+DNS server up to allow updates from the DHCP server or client, you may
+be exposing it to unauthorized updates. To avoid this, the best you
+can do right now is to use IP address-based packet filtering to
+prevent unauthorized hosts from submitting update requests.
+Obviously, there is currently no way to provide security for client
+updates - this will require TSIG or DNSSEC, neither of which is yet
+available in the DHCP distribution.
+.PP
+Dynamic DNS (DDNS) updates are performed by using the \fBdns-update\fR
+expression. The \fBdns-update\fR expression is a boolean expression
+that takes four parameters. If the update succeeds, the result is
+true. If it fails, the result is false. The four parameters that the
+are the resource record type (RR), the left hand side of the RR, the
+right hand side of the RR and the ttl that should be applied to the
+record. The simplest example of the use of the function can be found
+in the reference section of the dhcpd.conf file, where events are
+described. In this example several statements are being used to make
+the arguments to the \fBdns-update\f\R.
+.PP
+In the example, the first argument to the first \f\Bdns-update\fR
+expression is a data expression that evaluates to the A RR type. The
+second argument is constructed by concatenating the DHCP host-name
+option with a text string containing the local domain, in this case
+"ssd.example.net". The third argument is constructed by converting
+the address the client has been assigned from a 32-bit number into an
+ascii string with each byte separated by a ".". The fourth argument,
+the TTL, specifies the amount of time remaining in the lease (note
+that this isn't really correct, since the DNS server will pass this
+TTL out whenever a request comes in, even if that is only a few
+seconds before the lease expires).
+.PP
+If the first \fBdns-update\fR statement succeeds, it is followed up
+with a second update to install a PTR RR. The installation of a PTR
+record is similar to installing an A RR except that the left hand side
+of the record is the leased address, reversed, with ".in-addr.arpa"
+concatenated. The right hand side is the fully qualified domain name
+of the client to which the address is being leased.
+.SH SEE ALSO
+dhcpd.conf(5), dhcpd.leases(5), dhclient.conf(5), dhcp-eval(5), dhcpd(8),
+dhclient(8), RFC2132, RFC2131.
+.SH AUTHOR
+The Internet Software Consortium DHCP Distribution was written by Ted
+Lemon under a contract with Vixie Labs. Funding for
+this project was provided through the Internet Software Consortium.
+Information about the Internet Software Consortium can be found at
+.B http://www.isc.org.
diff --git a/contrib/isc-dhcp/common/dhcp-options.5 b/contrib/isc-dhcp/common/dhcp-options.5
index 5e7ca0002493..6f5d6f715234 100644
--- a/contrib/isc-dhcp/common/dhcp-options.5
+++ b/contrib/isc-dhcp/common/dhcp-options.5
@@ -1,8 +1,6 @@
.\" dhcp-options.5
.\"
-.\" Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.
-.\" All rights reserved.
-.\"
+.\" Copyright (c) 1996-2001 Internet Software Consortium.
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
@@ -31,10 +29,11 @@
.\" SUCH DAMAGE.
.\"
.\" This software has been written for the Internet Software Consortium
-.\" by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
-.\" Enterprises. To learn more about the Internet Software Consortium,
-.\" see ``http://www.isc.org/isc''. To learn more about Vixie
-.\" Enterprises, see ``http://www.vix.com''.
+.\" by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
+.\" To learn more about the Internet Software Consortium, see
+.\" ``http://www.isc.org/''. To learn more about Vixie Enterprises,
+.\" see ``http://www.vix.com''. To learn more about Nominum, Inc., see
+.\" ``http://www.nominum.com''.
.TH dhcpd-options 5
.SH NAME
dhcp-options - Dynamic Host Configuration Protocol options
@@ -82,94 +81,310 @@ data types specify signed and unsigned 8-bit integers.
Unsigned 8-bit integers are also sometimes referred to as octets.
.PP
The
-.B string
+.B text
data type specifies an NVT ASCII string, which must be
-enclosed in double quotes - for example, to specify a domain-name
+enclosed in double quotes - for example, to specify a root-path
option, the syntax would be
.nf
.sp 1
- option domain-name "isc.org";
+option root-path "10.0.1.4:/var/tmp/rootfs";
.fi
.PP
The
+.B domain-name
+data type specifies a domain name, which must not
+enclosed in double quotes. This data type is not used for any
+existing DHCP options. The domain name is stored just as if it were
+a text option.
+.PP
+The
.B flag
data type specifies a boolean value. Booleans can be either true or
false (or on or off, if that makes more sense to you).
.PP
The
-.B data-string
+.B string
data type specifies either an NVT ASCII string
enclosed in double quotes, or a series of octets specified in
hexadecimal, seperated by colons. For example:
.nf
.sp 1
- option dhcp-client-identifier "CLIENT-FOO";
+ option dhcp-client-identifier "CLIENT-FOO";
or
- option dhcp-client-identifier 43:4c:49:45:54:2d:46:4f:4f;
+ option dhcp-client-identifier 43:4c:49:45:54:2d:46:4f:4f;
+.fi
+.SH SETTING OPTION VALUES USING EXPRESSIONS
+Sometimes it's helpful to be able to set the value of a DHCP option
+based on some value that the client has sent. To do this, you can
+use expression evaluation. The
+.B dhcp-eval(5)
+manual page describes how to write expressions. To assign the result
+of an evaluation to an option, define the option as follows:
+.nf
+.sp 1
+ \fBoption \fImy-option \fB= \fIexpression \fB;\fR
.fi
.PP
+For example:
+.nf
+.sp 1
+ option hostname = binary-to-ascii (16, 8, "-",
+ substring (hardware, 1, 6));
+.fi
+.SH STANDARD DHCP OPTIONS
The documentation for the various options mentioned below is taken
-from the latest IETF draft document on DHCP options. Options which
-are not listed by name may be defined by the name option-\fInnn\fR,
-where \fInnn\fI is the decimal number of the option code. These
-options may be followed either by a string, enclosed in quotes, or by
-a series of octets, expressed as two-digit hexadecimal numbers seperated
-by colons. For example:
+from the latest IETF draft document on DHCP options. Options not
+listed below may not yet be implemented, but it is possible to use
+such options by defining them in the configuration file. Please see
+the DEFINING NEW OPTIONS heading later in this document for more
+information.
+.PP
+Some of the options documented here are automatically generated by
+the DHCP server or by clients, and cannot be configured by the user.
+The value of such an option can be used in the configuration file of
+the receiving DHCP protocol agent (server or client), for example in
+conditional expressions. However, the value of the option cannot be
+used in the configuration file of the sending agent, because the value
+is determined only \fIafter\fR the configuration file has been
+processed. In the following documentation, such options will be shown
+as "not user configurable"
+.PP
+The standard options are:
+.PP
+.B option \fBall-subnets-local\fR \fIflag\fR\fB;\fR
+.RS 0.25i
+.PP
+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 true indicates that all subnets share
+the same MTU. A value of false means that the client should assume that
+some subnets of the directly connected network may have smaller MTUs.
+.RE
+.PP
+.B option \fBarp-cache-timeout\fR \fIuint32\fR\fB;\fR
+.RS 0.25i
+.PP
+This option specifies the timeout in seconds for ARP cache entries.
+.RE
+.PP
+.B option \fBbootfile-name\fR \fItext\fR\fB;\fR
+.RS 0.25i
+.PP
+This option is used to identify a bootstrap file. If supported by the
+client, it should have the same effect as the \fBfilename\fR
+declaration. BOOTP clients are unlikely to support this option. Some
+DHCP clients will support it, and others actually require it.
+.RE
+.PP
+.B option \fBboot-size\fR \fIuint16\fR\fB;\fR
+.RS 0.25i
+.PP
+This option specifies the length in 512-octet blocks of the default
+boot image for the client.
+.RE
+.PP
+.B option \fBbroadcast-address\fR \fIip-address\fR\fB;\fR
+.RS 0.25i
+.PP
+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 STD 3 (RFC1122).
+.RE
+.PP
+.B option \fBcookie-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
+]\fB;\fR
+.RS 0.25i
+.PP
+The cookie server option specifies a list of RFC 865 cookie
+servers available to the client. Servers should be listed in order
+of preference.
+.RE
+.PP
+.B option \fBdefault-ip-ttl\fR \fIuint8;\fR
+.RS 0.25i
.PP
+This option specifies the default time-to-live that the client should
+use on outgoing datagrams.
+.RE
+.PP
+.B option \fBdefault-tcp-ttl\fR \fIuint8\fR\fB;\fR
+.RS 0.25i
+.PP
+This option specifies the default TTL that the client should use when
+sending TCP segments. The minimum value is 1.
+.RE
+.PP
+.B option \fBdhcp-client-identifier\fR \fIstring\fR\fB;\fR
+.RS 0.25i
+.PP
+This option can be used to specify the a DHCP client identifier in a
+host declaration, so that dhcpd can find the host record by matching
+against the client identifier.
+.PP
+Please be aware that some DHCP clients, when configured with client
+identifiers that are ASCII text, will prepend a zero to the ASCII
+text. So you may need to write:
.nf
- option option-133 "my-option-133-text";
- option option-129 1:54:c9:2b:47;
+
+ option dhcp-client-identifier "\\0foo";
+
+rather than:
+
+ option dhcp-client-identifier "foo";
.fi
+.RE
.PP
-Because dhcpd does not know the format of these undefined option codes,
-no checking is done to ensure the correctness of the entered data.
+.B option \fBdhcp-lease-time\fR \fIuint32\fR\fB;\fR
+.RS 0.25i
.PP
-The standard options are:
+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.
.PP
-.B option subnet-mask \fIip-address\fR\fB;\fR
+This option is not directly user configurable in the server; refer to the
+\fImax-lease-time\fR and \fidefault-lease-time\fR server options in
+.B dhcpd.conf(5).
+.RE
+.PP
+.B option \fBdhcp-max-message-size\fR \fIuint16\fR\fB;\fR
.RS 0.25i
.PP
-The subnet mask option specifies the client's subnet mask as per RFC
-950. If no subnet mask option is provided anywhere in scope, as a
-last resort dhcpd will use the subnet mask from the subnet declaration
-for the network on which an address is being assigned. However,
-.I any
-subnet-mask option declaration that is in scope for the address being
-assigned will override the subnet mask specified in the subnet
-declaration.
+This option, when sent by the client, specifies the maximum size of
+any response that the server sends to the client. When specified on
+the server, if the client did not send a dhcp-max-message-size option,
+the size specified on the server is used. This works for BOOTP as
+well as DHCP responses.
.RE
.PP
-.B option time-offset \fIint32\fR\fB;\fR
+.B option \fBdhcp-message\fR \fItext\fR\fB;\fR
.RS 0.25i
.PP
-The time-offset option specifies the offset of the client's subnet in
-seconds from Coordinated Universal Time (UTC).
+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 why the
+client declined the offered parameters.
+.PP
+This option is not user configurable.
.RE
.PP
-.B option routers \fIip-address\fR [\fB,\fR \fIip-address\fR...
-]\fB;\fR
+.B option \fBdhcp-message-type\fR \fIuint8\fR\fB;\fR
.RS 0.25i
.PP
-The routers option specifies a list of IP addresses for routers on the
-client's subnet. Routers should be listed in order of preference.
+This option, sent by both client and server, specifies the type of DHCP
+message contained in the DHCP packet. Possible values (taken directly from
+RFC2132) are:
+.PP
+.nf
+ 1 DHCPDISCOVER
+ 2 DHCPOFFER
+ 3 DHCPREQUEST
+ 4 DHCPDECLINE
+ 5 DHCPACK
+ 6 DHCPNAK
+ 7 DHCPRELEASE
+ 8 DHCPINFORM
+.fi
+.PP
+This option is not user configurable.
+.PP
.RE
+.B option \fBdhcp-option-overload\fR \fIuint8\fR\fB;\fR
+.RS 0.25i
.PP
-.B option time-servers \fIip-address\fR [, \fIip-address\fR...
-]\fB;\fR
+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.
+.PP
+If this option is present, the client interprets the specified
+additional fields after it concludes interpretation of the standard
+option fields.
+.PP
+Legal values for this option are:
+.PP
+.nf
+ 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
+.fi
+.PP
+This option is not user configurable.
+.PP
+.RE
+.PP
+.B option \fBdhcp-parameter-request-list\fR \fIuint16\fR\fB;\fR
.RS 0.25i
.PP
-The time-server option specifies a list of RFC 868 time servers
-available to the client. Servers should be listed in order of
-preference.
+This option, when sent by the client, specifies which options the
+client wishes the server to return. Normally, in the ISC DHCP
+client, this is done using the \fIrequest\fR statement. If this
+option is not specified by the client, the DHCP server will normally
+return every option that is valid in scope and that fits into the
+reply. When this option is specified on the server, the server
+returns the specified options. This can be used to force a client to
+take options that it hasn't requested, and it can also be used to
+tailor the response of the DHCP server for clients that may need a
+more limited set of options than those the server would normally
+return.
.RE
.PP
-.B option \fBien116-name-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
-];
+.B option \fBdhcp-rebinding-time\fR \fIuint32\fR\fB;\fR
.RS 0.25i
.PP
-The ien116-name-servers option specifies a list of IEN 116 name servers
-available to the client. Servers should be listed in order of
-preference.
+This option specifies the number of seconds from the time a client gets
+an address until the client transitions to the REBINDING state.
+.PP
+This option is not user configurable.
+.PP
+.RE
+.PP
+.B option \fBdhcp-renewal-time\fR \fIuint32\fR\fB;\fR
+.RS 0.25i
+.PP
+This option specifies the number of seconds from the time a client gets
+an address until the client transitions to the RENEWING state.
+.PP
+This option is not user configurable.
+.PP
+.RE
+.PP
+.B option \fBdhcp-requested-address\fR \fIip-address\fR\fB;\fR
+.RS 0.25i
+.PP
+This option is used by the client in a DHCPDISCOVER to
+request that a particular IP address be assigned.
+.PP
+This option is not user configurable.
+.PP
+.RE
+.PP
+.B option \fBdhcp-server-identifier\fR \fIip-address\fR\fB;\fR
+.RS 0.25i
+.PP
+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 use the
+contents of the 'server identifier' field as the destination address
+for any DHCP messages unicast to the DHCP server. DHCP clients also
+indicate which of several lease offers is being accepted by including
+this option in a DHCPREQUEST message.
+.PP
+The value of this option is the IP address of the server.
+.PP
+This option is not directly user configurable. See the
+\fIserver-identifier\fR server option in
+.B \fIdhcpd.conf(5).
+.PP
+.RE
+.PP
+.B option \fBdomain-name\fR \fItext\fR\fB;\fR
+.RS 0.25i
+.PP
+This option specifies the domain name that client should use when
+resolving hostnames via the Domain Name System.
.RE
.PP
.B option \fBdomain-name-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
@@ -181,68 +396,126 @@ The domain-name-servers option specifies a list of Domain Name System
should be listed in order of preference.
.RE
.PP
-.B option \fBlog-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
+.B option \fBextensions-path\fR \fItext\fR\fB;\fR
+.RS 0.25i
+.PP
+This option specifies the name of a file containing additional options
+to be interpreted according to the DHCP option format as specified in
+RFC2132.
+.RE
+.PP
+.B option \fBfinger-server\fR \fIip-address\fR [\fB,\fR
+\fIip-address\fR... ]\fB;\fR
+.RS 0.25i
+.PP
+The Finger server option specifies a list of Finger available to the
+client. Servers should be listed in order of preference.
+.RE
+.PP
+.B option \fBfont-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
]\fB;\fR
.RS 0.25i
.PP
-The log-server option specifies a list of MIT-LCS UDP log servers
+This option specifies a list of X Window System Font servers available
+to the client. Servers should be listed in order of preference.
+.RE
+.PP
+.B option \fBhost-name\fR \fIstring\fR\fB;\fR
+.RS 0.25i
+.PP
+This option specifies the name of the client. The name may or may
+not be qualified with the local domain name (it is preferable to use
+the domain-name option to specify the domain name). See RFC 1035 for
+character set restrictions.
+.RE
+.PP
+.B option \fBieee802-3-encapsulation\fR \fIflag\fR\fB;\fR
+.RS 0.25i
+.PP
+This option specifies whether or not the client should use Ethernet
+Version 2 (RFC 894) or IEEE 802.3 (RFC 1042) encapsulation if the
+interface is an Ethernet. A value of false indicates that the client
+should use RFC 894 encapsulation. A value of true means that the client
+should use RFC 1042 encapsulation.
+.RE
+.PP
+.B option \fBien116-name-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
+];
+.RS 0.25i
+.PP
+The ien116-name-servers option specifies a list of IEN 116 name servers
available to the client. Servers should be listed in order of
preference.
.RE
.PP
-.B option \fBcookie-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
+.B option \fBimpress-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
]\fB;\fR
.RS 0.25i
.PP
-The cookie server option specifies a list of RFC 865 cookie
-servers available to the client. Servers should be listed in order
-of preference.
+The impress-server option specifies a list of Imagen Impress servers
+available to the client. Servers should be listed in order of
+preference.
.RE
.PP
-.B option \fBlpr-servers\fR \fIip-address \fR [\fB,\fR \fIip-address\fR...
-]\fB;\fR
+.B option \fBinterface-mtu\fR \fIuint16\fR\fB;\fR
.RS 0.25i
.PP
-The LPR server option specifies a list of RFC 1179 line printer
-servers available to the client. Servers should be listed in order
-of preference.
+This option specifies the MTU to use on this interface. The minimum
+legal value for the MTU is 68.
.RE
.PP
-.B option \fBimpress-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
+.B option \fBip-forwarding\fR \fIflag\fR\fB;\fR
+.RS 0.25i
+.PP
+This option specifies whether the client should configure its IP
+layer for packet forwarding. A value of false means disable IP
+forwarding, and a value of true means enable IP forwarding.
+.RE
+.PP
+.B option \fBirc-server\fR \fIip-address\fR [\fB,\fR
+\fIip-address\fR... ]\fB;\fR
+.RS 0.25i
+.PP
+The IRC server option specifies a list of IRC available to the
+client. Servers should be listed in order of preference.
+.RE
+.PP
+.B option \fBlog-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
]\fB;\fR
.RS 0.25i
.PP
-The impress-server option specifies a list of Imagen Impress servers
+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.
.RE
.PP
-.B option \fBresource-location-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
+.B option \fBlpr-servers\fR \fIip-address \fR [\fB,\fR \fIip-address\fR...
]\fB;\fR
.RS 0.25i
.PP
-This option specifies a list of RFC 887 Resource Location
+The LPR server option specifies a list of RFC 1179 line printer
servers available to the client. Servers should be listed in order
of preference.
.RE
.PP
-.B option \fBhost-name\fR \fIstring\fR\fB;\fR
+.B option \fBmask-supplier\fR \fIflag\fR\fB;\fR
.RS 0.25i
.PP
-This option specifies the name of the client. The name may or may
-not be qualified with the local domain name (it is preferable to use
-the domain-name option to specify the domain name). See RFC 1035 for
-character set restrictions.
+This option specifies whether or not the client should respond to
+subnet mask requests using ICMP. A value of false indicates that the
+client should not respond. A value of true means that the client should
+respond.
.RE
.PP
-.B option \fBboot-size\fR \fIuint16\fR\fB;\fR
+.B option \fBmax-dgram-reassembly\fR \fIuint16\fR\fB;\fR
.RS 0.25i
.PP
-This option specifies the length in 512-octet blocks of the default
-boot image for the client.
+This option specifies the maximum size datagram that the client
+should be prepared to reassemble. The minimum value legal value is
+576.
.RE
.PP
-.B option \fBmerit-dump\fR \fIstring\fR\fB;\fR
+.B option \fBmerit-dump\fR \fItext\fR\fB;\fR
.RS 0.25i
.PP
This option specifies the path-name of a file to which the client's
@@ -251,33 +524,123 @@ path is formatted as a character string consisting of characters from
the NVT ASCII character set.
.RE
.PP
-.B option \fBdomain-name\fR \fIstring\fR\fB;\fR
+.B option \fBmobile-ip-home-agent\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... ]\fB;\fR
.RS 0.25i
.PP
-This option specifies the domain name that client should use when
-resolving hostnames via the Domain Name System.
+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, although normally there will be only one such
+agent.
.RE
.PP
-.B option \fBswap-server\fR \fIip-address\fR\fB;\fR
+.B option \fBnds-context\fR \fIstring\fR\fB;\fR
.RS 0.25i
.PP
-This specifies the IP address of the client's swap server.
+The nds-context option specifies the name of the initial Netware
+Directory Service for an NDS client.
.RE
.PP
-.B option \fBroot-path\fR \fIstring\fB;\fR\fR
+.B option \fBnds-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... ]\fB;\fR
.RS 0.25i
.PP
-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 nds-servers option specifies a list of IP addresses of NDS servers.
.RE
.PP
-.B option \fBip-forwarding\fR \fIflag\fR\fB;\fR
+.B option \fBnds-tree-name\fR \fIstring\fR\fB;\fR
.RS 0.25i
.PP
-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 nds-context option specifies NDS tree name that the NDS client
+should use.
+.RE
+.PP
+.B option \fBnetbios-dd-server\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
+]\fB;\fR
+.RS 0.25i
+.PP
+The NetBIOS datagram distribution server (NBDD) option specifies a
+list of RFC 1001/1002 NBDD servers listed in order of preference.
+.RE
+.PP
+.B option \fBnetbios-name-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...]\fB;\fR
+.RS 0.25i
+.PP
+The NetBIOS name server (NBNS) option specifies a list of RFC
+1001/1002 NBNS name servers listed in order of preference. NetBIOS
+Name Service is currently more commonly referred to as WINS. WINS
+servers can be specified using the netbios-name-servers option.
+.RE
+.PP
+.B option \fBnetbios-node-type\fR \fIuint8\fR\fB;\fR
+.RS 0.25i
+.PP
+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.
+.PP
+Possible node types are:
+.PP
+.TP 5
+.I 1
+B-node: Broadcast - no WINS
+.TP
+.I 2
+P-node: Peer - WINS only.
+.TP
+.I 4
+M-node: Mixed - broadcast, then WINS
+.TP
+.I 8
+H-node: Hybrid - WINS, then broadcast
+.RE
+.PP
+.B option \fBnetbios-scope\fR \fIstring\fR\fB;\fR
+.RS 0.25i
+.PP
+The NetBIOS scope option specifies the NetBIOS over TCP/IP scope
+parameter for the client as specified in RFC 1001/1002. See RFC1001,
+RFC1002, and RFC1035 for character-set restrictions.
+.RE
+.PP
+.B option \fBnis-domain\fR \fItext\fR\fB;\fR
+.RS 0.25i
+.PP
+This option specifies the name of the client's NIS (Sun Network
+Information Services) domain. The domain is formatted as a character
+string consisting of characters from the NVT ASCII character set.
+.RE
+.PP
+.B option \fBnis-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
+]\fB;\fR
+.RS 0.25i
+.PP
+This option specifies a list of IP addresses indicating NIS servers
+available to the client. Servers should be listed in order of
+preference.
+.RE
+.PP
+.B option \fBnisplus-domain\fR \fItext\fR\fB;\fR
+.RS 0.25i
+.PP
+This option specifies the name of the client's NIS+ domain. The
+domain is formatted as a character string consisting of characters
+from the NVT ASCII character set.
+.RE
+.PP
+.B option \fBnisplus-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
+]\fB;\fR
+.RS 0.25i
+.PP
+This option specifies a list of IP addresses indicating NIS+ servers
+available to the client. Servers should be listed in order of
+preference.
+.RE
+.PP
+.B option \fBnntp-server\fR \fIip-address\fR [\fB,\fR
+\fIip-address\fR... ]\fB;\fR
+.RS 0.25i
+.PP
+The NNTP server option specifies a list of NNTP available to the
+client. Servers should be listed in order of preference.
.RE
.PP
.B option \fBnon-local-source-routing\fR \fIflag\fR\fB;\fR
@@ -286,37 +649,33 @@ forwarding, and a value of 1 means enable IP forwarding.
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
+of 0 means disallow forwarding of such datagrams, and a value of true
means allow forwarding.
.RE
.PP
-.B option \fBpolicy-filter\fR \fIip-address ip-address\fR [\fB,\fR \fIip-address ip-address\fR...
+.B option \fBntp-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
]\fB;\fR
.RS 0.25i
.PP
-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.
-.PP
-Any source routed datagram whose next-hop address does not match one
-of the filters should be discarded by the client.
-.PP
-See STD 3 (RFC1122) for further information.
+This option specifies a list of IP addresses indicating NTP (RFC 1035)
+servers available to the client. Servers should be listed in order
+of preference.
.RE
.PP
-.B option \fBmax-dgram-reassembly\fR \fIuint16\fR\fB;\fR
+.B option \fBnwip-domain\fR \fIstring\fR\fB;\fR
.RS 0.25i
.PP
-This option specifies the maximum size datagram that the client
-should be prepared to reassemble. The minimum value legal value is
-576.
+The name of the NetWare/IP domain that a NetWare/IP client should
+use.
.RE
.PP
-.B option \fBdefault-ip-ttl\fR \fIuint8;\fR
+.B option \fBnwip-suboptions\fR \fIstring\fR\fB;\fR
.RS 0.25i
.PP
-This option specifies the default time-to-live that the client should
-use on outgoing datagrams.
+A sequence of suboptions for NetWare/IP clients - see RFC2242 for
+details. Normally this option is set by specifying specific
+NetWare/IP suboptions - see the NETWARE/IP SUBOPTIONS section for more
+information.
.RE
.PP
.B option \fBpath-mtu-aging-timeout\fR \fIuint32\fR\fB;\fR
@@ -336,48 +695,55 @@ a list of 16-bit unsigned integers, ordered from smallest to largest.
The minimum MTU value cannot be smaller than 68.
.RE
.PP
-.B option \fBinterface-mtu\fR \fIuint16\fR\fB;\fR
+.B option \fBperform-mask-discovery\fR \fIflag\fR\fB;\fR
.RS 0.25i
.PP
-This option specifies the MTU to use on this interface. The minimum
-legal value for the MTU is 68.
+This option specifies whether or not the client should perform subnet
+mask discovery using ICMP. A value of false indicates that the client
+should not perform mask discovery. A value of true means that the
+client should perform mask discovery.
.RE
.PP
-.B option \fBall-subnets-local\fR \fIflag\fR\fB;\fR
+.nf
+.B option \fBpolicy-filter\fR \fIip-address ip-address\fR
+ [\fB,\fR \fIip-address ip-address\fR...]\fB;\fR
+.RE
+.fi
.RS 0.25i
.PP
-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.
+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.
+.PP
+Any source routed datagram whose next-hop address does not match one
+of the filters should be discarded by the client.
+.PP
+See STD 3 (RFC1122) for further information.
.RE
.PP
-.B option \fBbroadcast-address\fR \fIip-address\fR\fB;\fR
+.B option \fBpop-server\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... ]\fB;\fR
.RS 0.25i
.PP
-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 STD 3 (RFC1122).
+The POP3 server option specifies a list of POP3 available to the
+client. Servers should be listed in order of preference.
.RE
.PP
-.B option \fBperform-mask-discovery\fR \fIflag\fR\fB;\fR
+.B option \fBresource-location-servers\fR \fIip-address\fR
+ [\fB, \fR\fIip-address\fR...]\fB;\fR
+.fi
.RS 0.25i
.PP
-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.
+This option specifies a list of RFC 887 Resource Location
+servers available to the client. Servers should be listed in order
+of preference.
.RE
.PP
-.B option \fBmask-supplier\fR \fIflag\fR\fB;\fR
+.B option \fBroot-path\fR \fItext\fB;\fR\fR
.RS 0.25i
.PP
-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.
+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.
.RE
.PP
.B option \fBrouter-discovery\fR \fIflag\fR\fB;\fR
@@ -385,8 +751,8 @@ respond.
.PP
This option specifies whether or not the client should solicit
routers using the Router Discovery mechanism defined in RFC 1256.
-A value of 0 indicates that the client should not perform
-router discovery. A value of 1 means that the client should perform
+A value of false indicates that the client should not perform
+router discovery. A value of true means that the client should perform
router discovery.
.RE
.PP
@@ -397,10 +763,65 @@ This option specifies the address to which the client should transmit
router solicitation requests.
.RE
.PP
-.B option \fBstatic-routes\fR \fIip-address ip-address\fR [\fB,\fR \fIip-address ip-address\fR...
+.B option routers \fIip-address\fR [\fB,\fR \fIip-address\fR...
]\fB;\fR
.RS 0.25i
.PP
+The routers option specifies a list of IP addresses for routers on the
+client's subnet. Routers should be listed in order of preference.
+.RE
+.PP
+.B option slp-directory-agent \fIboolean ip-address
+[\fB,\fR \fIip-address\fR... ]\fB;\fR
+.RS 0.25i
+.PP
+This option specifies two things: the IP addresses of one or more
+Service Location Protocol Directory Agents, and whether the use of
+these addresses is mandatory. If the initial boolean value is true,
+the SLP agent should just use the IP addresses given. If the value
+is false, the SLP agent may additionally do active or passive
+multicast discovery of SLP agents (see RFC2165 for details).
+.PP
+Please note that in this option and the slp-service-scope option, the
+term "SLP Agent" is being used to refer to a Service Location Protocol
+agent running on a machine that is being configured using the DHCP
+protocol.
+.PP
+Also, please be aware that some companies may refer to SLP as NDS.
+If you have an NDS directory agent whose address you need to
+configure, the slp-directory-agent option should work.
+.RE
+.PP
+.B option slp-service-scope \fIboolean text\fR\fB;\fR
+.RS 0.25i
+.PP
+The Service Location Protocol Service Scope Option specifies two
+things: a list of service scopes for SLP, and whether the use of this
+list is mandatory. If the initial boolean value is true, the SLP
+agent should only use the list of scopes provided in this option;
+otherwise, it may use its own static configuration in preference to
+the list provided in this option.
+.PP
+The text string should be a comma-seperated list of scopes that the
+SLP agent should use. It may be omitted, in which case the SLP Agent
+will use the aggregated list of scopes of all directory agents known
+to the SLP agent.
+.RE
+.PP
+.B option \fBsmtp-server\fR \fIip-address\fR [\fB,\fR
+\fIip-address\fR... ]\fB;\fR
+.RS 0.25i
+.PP
+The SMTP server option specifies a list of SMTP servers available to
+the client. Servers should be listed in order of preference.
+.RE
+.PP
+.nf
+.B option \fBstatic-routes\fR \fIip-address ip-address\fR
+ [\fB,\fR \fIip-address ip-address\fR...]\fB;\fR
+.fi
+.RS 0.25i
+.PP
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
@@ -413,39 +834,73 @@ the destination.
The default route (0.0.0.0) is an illegal destination for a static
route. To specify the default route, use the
.B routers
-option.
+option. Also, please note that this option is not intended for
+classless IP routing - it does not include a subnet mask. Since
+classless IP routing is now the most widely deployed routing standard,
+this option is virtually useless, and is not implemented by any of the
+popular DHCP clients, for example the Microsoft DHCP client.
.RE
.PP
-.B option \fBtrailer-encapsulation\fR \fIflag\fR\fB;\fR
+.nf
+.B option \fBstreettalk-directory-assistance-server\fR \fIip-address\fR
+ [\fB,\fR \fIip-address\fR...]\fB;\fR
+.fi
.RS 0.25i
.PP
-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 StreetTalk Directory Assistance (STDA) server option specifies a
+list of STDA servers available to the client. Servers should be
+listed in order of preference.
.RE
.PP
-.B option \fBarp-cache-timeout\fR \fIuint32\fR\fB;\fR
+.B option \fBstreettalk-server\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... ]\fB;\fR
.RS 0.25i
.PP
-This option specifies the timeout in seconds for ARP cache entries.
+The StreetTalk server option specifies a list of StreetTalk servers
+available to the client. Servers should be listed in order of
+preference.
.RE
.PP
-.B option \fBieee802-3-encapsulation\fR \fIflag\fR\fB;\fR
+.B option subnet-mask \fIip-address\fR\fB;\fR
.RS 0.25i
.PP
-This option specifies whether or not the client should use Ethernet
-Version 2 (RFC 894) or IEEE 802.3 (RFC 1042) 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 subnet mask option specifies the client's subnet mask as per RFC
+950. If no subnet mask option is provided anywhere in scope, as a
+last resort dhcpd will use the subnet mask from the subnet declaration
+for the network on which an address is being assigned. However,
+.I any
+subnet-mask option declaration that is in scope for the address being
+assigned will override the subnet mask specified in the subnet
+declaration.
.RE
.PP
-.B option \fBdefault-tcp-ttl\fR \fIuint8\fR\fB;\fR
+.B option \fBsubnet-selection\fR \fIstring\fR\fB;\fR
.RS 0.25i
.PP
-This option specifies the default TTL that the client should use when
-sending TCP segments. The minimum value is 1.
+Sent by the client if an address is required in a subnet other than the one
+that would normally be selected (based on the relaying address of the
+connected subnet the request is obtained from). See RFC3011. Note that the
+option number used by this server is 118; this has not always been the
+defined number, and some clients may use a different value. Use of this
+option should be regarded as slightly experimental!
+.RE
+.PP
+This option is not user configurable in the server.
+.PP
+.PP
+.B option \fBswap-server\fR \fIip-address\fR\fB;\fR
+.RS 0.25i
+.PP
+This specifies the IP address of the client's swap server.
+.RE
+.PP
+.B option \fBtcp-keepalive-garbage\fR \fIflag\fR\fB;\fR
+.RS 0.25i
+.PP
+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 false indicates that a garbage octet
+should not be sent. A value of true indicates that a garbage octet
+should be sent.
.RE
.PP
.B option \fBtcp-keepalive-interval\fR \fIuint32\fR\fB;\fR
@@ -458,99 +913,117 @@ indicates that the client should not generate keepalive messages on
connections unless specifically requested by an application.
.RE
.PP
-.B option \fBtcp-keepalive-garbage\fR \fIflag\fR\fB;\fR
+.B option \fBtftp-server-name\fR \fItext\fR\fB;\fR
.RS 0.25i
.PP
-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.
+This option is used to identify a TFTP server and, if supported by the
+client, should have the same effect as the \fBserver-name\fR
+declaration. BOOTP clients are unlikely to support this option.
+Some DHCP clients will support it, and others actually require it.
.RE
.PP
-.B option \fBnis-domain\fR \fIstring\fR\fB;\fR
+.B option time-offset \fIint32\fR\fB;\fR
.RS 0.25i
.PP
-This option specifies the name of the client's NIS (Sun Network
-Information Services) domain. The domain is formatted as a character
-string consisting of characters from the NVT ASCII character set.
+The time-offset option specifies the offset of the client's subnet in
+seconds from Coordinated Universal Time (UTC).
.RE
.PP
-.B option \fBnis-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
+.B option time-servers \fIip-address\fR [, \fIip-address\fR...
]\fB;\fR
.RS 0.25i
.PP
-This option specifies a list of IP addresses indicating NIS servers
+The time-server option specifies a list of RFC 868 time servers
available to the client. Servers should be listed in order of
preference.
.RE
.PP
-.B option \fBntp-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
-]\fB;\fR
+.B option \fBtrailer-encapsulation\fR \fIflag\fR\fB;\fR
.RS 0.25i
.PP
-This option specifies a list of IP addresses indicating NTP (RFC 1035)
-servers available to the client. Servers should be listed in order
-of preference.
+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 true means that the client should attempt to use trailers.
.RE
.PP
-.B option \fBnetbios-name-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
-]\fB;\fR
+.B option \fBuap-servers\fR \fItext\fR\fB;\fR
.RS 0.25i
.PP
-The NetBIOS name server (NBNS) option specifies a list of RFC
-1001/1002 NBNS name servers listed in order of preference. NetBIOS
-Name Service is currently more commonly referred to as WINS. WINS
-servers can be specified using the netbios-name-servers option.
+This option specifies a list of URLs, each pointing to a user
+authentication service that is capable of processing authentication
+requests encapsulated in the User Authentication Protocol (UAP). UAP
+servers can accept either HTTP 1.1 or SSLv3 connections. If the list
+includes a URL that does not contain a port component, the normal
+default port is assumed (i.e., port 80 for http and port 443 for
+https). If the list includes a URL that does not contain a path
+component, the path /uap is assumed. If more than one URL is
+specified in this list, the URLs are seperated by spaces.
.RE
.PP
-.B option \fBnetbios-dd-server\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
-]\fB;\fR
+.B option \fBuser-class\fR \fIstring\fR\fB;\fR
.RS 0.25i
.PP
-The NetBIOS datagram distribution server (NBDD) option specifies a
-list of RFC 1001/1002 NBDD servers listed in order of preference.
-.RE
+This option is used by some DHCP clients as a way for users to
+specify identifying information to the client. This can be used in a
+similar way to the vendor-class-identifier option, but the value of
+the option is specified by the user, not the vendor. Most recent
+DHCP clients have a way in the user interface to specify the value for
+this identifier, usually as a text string.
.PP
-.B option \fBnetbios-node-type\fR \fIuint8\fR\fB;\fR
+.B option \fBvendor-class-identifier\fR \fIstring\fR\fB;\fR
.RS 0.25i
.PP
-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.
+This option is used by some DHCP clients to identify the vendor
+type and possibly the configuration of a DHCP client. The information
+is a string of bytes whose contents are specific to the vendor and are
+not specified in a standard. To see what vendor class identifier a
+clients are sending, you can write the following in your DHCP server
+configuration file:
+.nf
.PP
-Possible node types are:
+set vendor-class option vendor-class-identifier;
+.fi
.PP
-.TP 5
-.I 1
-B-node: Broadcast - no WINS
-.TP
-.I 2
-P-node: Peer - WINS only.
-.TP
-.I 4
-M-node: Mixed - broadcast, then WINS
-.TP
-.I 8
-H-node: Hybrid - WINS, then broadcast
+This will result in all entries in the DHCP server lease database file
+for clients that sent vendor-class-identifier options having a set
+statement that looks something like this:
+.nf
+.PP
+set vendor-class "SUNW.Ultra-5_10";
+.fi
+.PP
+The vendor-class-identifier option is normally used by the DHCP server
+to determine the options that are returned in the
+.B vendor-encapsulated-options
+option. Please see the VENDOR ENCAPSULATED OPTIONS section of the
+dhcpd.conf manual page for further information.
.RE
.PP
-.B option
-.B netbios-scope
-.I string\fB;\fR
+.B option \fBvendor-encapsulated-options\fR \fIstring\fR\fB;\fR
.RS 0.25i
.PP
-The NetBIOS scope option specifies the NetBIOS over TCP/IP scope
-parameter for the client as specified in RFC 1001/1002. See RFC1001,
-RFC1002, and RFC1035 for character-set restrictions.
+The \fBvendor-encapsulated-options\fR option can contain either a
+single vendor-specific value or one or more vendor-specific
+suboptions. This option is not normally specified in the DHCP server
+configuration file - instead, a vendor class is defined for each
+vendor, vendor class suboptions are defined, values for those
+suboptions are defined, and the DHCP server makes up a response on
+that basis.
+.PP
+Some default behaviours for well-known DHCP client vendors (currently,
+the Microsoft Windows 2000 DHCP client) are configured automatically,
+but otherwise this must be configured manually - see the VENDOR
+ENCAPSULATED OPTIONS section of the \fIdhcpd.conf\fI manual page for
+details.
.RE
.PP
-.B option \fBfont-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
-]\fB;\fR
+.B option \fBwww-server\fR \fIip-address\fR [\fB,\fR
+\fIip-address\fR... ]\fB;\fR
.RS 0.25i
.PP
-This option specifies a list of X Window System Font servers available
-to the client. Servers should be listed in order of preference.
+The WWW server option specifies a list of WWW available to the
+client. Servers should be listed in order of preference.
.RE
.PP
.B option \fBx-display-manager\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
@@ -561,130 +1034,466 @@ This option specifies a list 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.
.RE
-.PP
-.B option \fBdhcp-client-identifier\fR \fIdata-string\fR\fB;\fR
+.SH RELAY AGENT INFORMATION OPTION
+An IETF draft, draft-ietf-dhc-agent-options-11.txt, defines a series
+of encapsulated options that a relay agent can add to a DHCP packet
+when relaying it to the DHCP server. The server can then make
+address allocation decisions (or whatever other decisions it wants)
+based on these options. The server also returns these options in any
+replies it sends through the relay agent, so that the relay agent can
+use the information in these options for delivery or accounting
+purposes.
+.PP
+The current draft defines two options. To reference
+these options in the dhcp server, specify the option space name,
+"agent", followed by a period, followed by the option name. It is
+not normally useful to define values for these options in the server,
+although it is permissible. These options are not supported in the
+client.
+.PP
+.B option \fBagent.circuit-id\fR \fIstring\fR\fB;\fR
.RS 0.25i
.PP
-This option can be used to specify the a DHCP client identifier in a
-host declaration, so that dhcpd can find the host record by matching
-against the client identifier.
+The circuit-id suboption encodes an agent-local identifier of the
+circuit from which a DHCP client-to-server packet was received. It is
+intended for use by agents in relaying DHCP responses back to the
+proper circuit. The format of this option is currently defined to be
+vendor-dependent, and will probably remain that way, although the
+current draft allows for for the possibility of standardizing the
+format in the future.
.RE
-.B option \fBnisplus-domain\fR \fIstring\fR\fB;\fR
+.PP
+.B option \fBagent.remote-id\fR \fIstring\fR\fB;\fR
.RS 0.25i
.PP
-This option specifies the name of the client's NIS+ domain. The
-domain is formatted as a character string consisting of characters
-from the NVT ASCII character set.
+The remote-id suboption encodes information about the remote host end
+of a circuit. Examples of what it might contain include caller ID
+information, username information, remote ATM address, cable modem ID,
+and similar things. In principal, the meaning is not well-specified,
+and it should generally be assumed to be an opaque object that is
+administratively guaranteed to be unique to a particular remote end of
+a circuit.
.RE
-.B option \fBnisplus-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...
-]\fB;\fR
+.SH THE CLIENT FQDN SUBOPTIONS
+The Client FQDN option, currently defined in the Internet Draft
+draft-ietf-dhc-fqdn-option-00.txt is not a standard yet, but is in
+sufficiently wide use already that we have implemented it. Due to
+the complexity of the option format, we have implemented it as a
+suboption space rather than a single option. In general this
+option should not be configured by the user - instead it should be
+used as part of an automatic DNS update system.
+.PP
+.B option fqdn.no-client-update \fIflag\fB;
.RS 0.25i
.PP
-This option specifies a list of IP addresses indicating NIS+ servers
-available to the client. Servers should be listed in order of
-preference.
+When the client sends this, if it is true, it means the client will not
+attempt to update its A record. When sent by the server to the client,
+it means that the client \fIshould not\fR update its own A record.
.RE
.PP
-.B option \fBtftp-server-name\fR \fIstring\fR\fB;\fR
+.B option fqdn.server-update \fIflag\fB;
.RS 0.25i
.PP
-This option is used to identify a TFTP server and, if supported by the
-client, should have the same effect as the \fBserver-name\fR
-declaration. BOOTP clients are unlikely to support this option.
-Some DHCP clients will support it, and others actually require it.
+When the client sends this to the server, it is requesting that the server
+update its A record. When sent by the server, it means that the server
+has updated (or is about to update) the client's A record.
.RE
.PP
-.B option \fBbootfile-name\fR \fIstring\fR\fB;\fR
+.B option fqdn.encoded \fIflag\fB;
.RS 0.25i
.PP
-This option is used to identify a bootstrap file. If supported by the
-client, it should have the same effect as the \fBfilename\fR
-declaration. BOOTP clients are unlikely to support this option. Some
-DHCP clients will support it, and others actually require it.
+If true, this indicates that the domain name included in the option is
+encoded in DNS wire format, rather than as plain ASCII text. The client
+normally sets this to false if it doesn't support DNS wire format in the
+FQDN option. The server should always send back the same value that the
+client sent. When this value is set on the configuration side, it controls
+the format in which the \fIfqdn.fqdn\fR suboption is encoded.
.RE
.PP
-.B option \fBmobile-ip-home-agent\fR \fIip-address\fR [\fB,\fR
-\fIip-address\fR... ]\fB;\fR
+.B option fqdn.rcode1 \fIflag\fB;
+.PP
+.B option fqdn.rcode1 \fIflag\fB;
.RS 0.25i
.PP
-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, although normally there will be only one such
-agent.
+These options specify the result of the updates of the A and PTR records,
+respectively, and are only sent by the DHCP server to the DHCP client.
+The values of these fields are those defined in the DNS protocol specification.
.RE
.PP
-.B option \fBsmtp-server\fR \fIip-address\fR [\fB,\fR
-\fIip-address\fR... ]\fB;\fR
+.B option fqdn.fqdn \fItext\fB;
.RS 0.25i
.PP
-The SMTP server option specifies a list of SMTP servers available to
-the client. Servers should be listed in order of preference.
+Specifies the domain name that the client wishes to use. This can be a
+fully-qualified domain name, or a single label. If there is no trailing
+'.' character in the name, it is not fully-qualified, and the server will
+generally update that name in some locally-defined domain.
.RE
.PP
-.B option \fBpop-server\fR \fIip-address\fR [\fB,\fR
-\fIip-address\fR... ]\fB;\fR
+If you wish to use any of these suboptions, we strongly recommend that you
+refer to the Client FQDN option draft (or standard, when it becomes a
+standard) - the documentation here is sketchy and incomplete in comparison,
+and is just intended for reference by people who already understand the
+Client FQDN option specification.
+.SH THE NETWARE/IP SUBOPTIONS
+RFC2242 defines a set of encapsulated options for Novell NetWare/IP
+clients. To use these options in the dhcp server, specify the option
+space name, "nwip", followed by a period, followed by the option name.
+The following options can be specified:
+.PP
+.B option \fBnwip.nsq-broadcast\fR \fIflag\fR\fB;\fR
.RS 0.25i
.PP
-The POP3 server option specifies a list of POP3 available to the
-client. Servers should be listed in order of preference.
-.RE
+If true, the client should use the NetWare Nearest Server Query to
+locate a NetWare/IP server. The behaviour of the Novell client if
+this suboption is false, or is not present, is not specified.
.PP
-.B option \fBnntp-server\fR \fIip-address\fR [\fB,\fR
-\fIip-address\fR... ]\fB;\fR
+.RE
+.B option \fBnwip.preferred-dss\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... ]\fR\fB;\fR
.RS 0.25i
.PP
-The NNTP server option specifies a list of NNTP available to the
-client. Servers should be listed in order of preference.
+This suboption specifies a list of up to five IP addresses, each of
+which should be the IP address of a NetWare Domain SAP/RIP server
+(DSS).
.RE
.PP
-.B option \fBwww-server\fR \fIip-address\fR [\fB,\fR
-\fIip-address\fR... ]\fB;\fR
+.B option \fBnwip.nearest-nwip-server\fR \fI\fIip-address\fR
+ [\fB,\fR \fIip-address\fR...]\fR\fB;\fR
.RS 0.25i
.PP
-The WWW server option specifies a list of WWW available to the
-client. Servers should be listed in order of preference.
+This suboption specifies a list of up to five IP addresses, each of
+which should be the IP address of a Nearest NetWare IP server.
.RE
.PP
-.B option \fBfinger-server\fR \fIip-address\fR [\fB,\fR
-\fIip-address\fR... ]\fB;\fR
+.B option \fBnwip.autoretries\fR \fIuint8\fR\fB;\fR
.RS 0.25i
.PP
-The Finger server option specifies a list of Finger available to the
-client. Servers should be listed in order of preference.
+Specifies the number of times that a NetWare/IP client should attempt
+to communicate with a given DSS server at startup.
.RE
.PP
-.B option \fBirc-server\fR \fIip-address\fR [\fB,\fR
-\fIip-address\fR... ]\fB;\fR
+.B option \fBnwip.autoretry-secs\fR \fIuint8\fR\fB;\fR
.RS 0.25i
.PP
-The IRC server option specifies a list of IRC available to the
-client. Servers should be listed in order of preference.
+Specifies the number of seconds that a Netware/IP client should wait
+between retries when attempting to establish communications with a DSS
+server at startup.
.RE
.PP
-.B option \fBstreettalk-server\fR \fIip-address\fR [\fB,\fR
-\fIip-address\fR... ]\fB;\fR
+.B option \fBnwip.nwip-1-1\fR \fIuint8\fR\fB;\fR
.RS 0.25i
.PP
-The StreetTalk server option specifies a list of StreetTalk servers
-available to the client. Servers should be listed in order of
-preference.
+If true, the NetWare/IP client should support NetWare/IP version 1.1
+compatibility. This is only needed if the client will be contacting
+Netware/IP version 1.1 servers.
.RE
.PP
-.B option \fBstreetalk-directory-assistance-server\fR \fIip-address\fR [\fB,\fR
-\fIip-address\fR... ]\fB;\fR
+.B option \fBnwip.primary-dss\fR \fIip-address\fR\fB;\fR
.RS 0.25i
.PP
-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.
+Specifies the IP address of the Primary Domain SAP/RIP Service server
+(DSS) for this NetWare/IP domain. The NetWare/IP administration
+utility uses this value as Primary DSS server when configuring a
+secondary DSS server.
.RE
+.SH DEFINING NEW OPTIONS
+The Internet Software Consortium DHCP client and server provide the
+capability to define new options. Each DHCP option has a name, a
+code, and a structure. The name is used by you to refer to the
+option. The code is a number, used by the DHCP server and client to
+refer to an option. The structure describes what the contents of an
+option looks like.
+.PP
+To define a new option, you need to choose a name for it that is not
+in use for some other option - for example, you can't use "host-name"
+because the DHCP protocol already defines a host-name option, which is
+documented earlier in this manual page. If an option name doesn't
+appear in this manual page, you can use it, but it's probably a good
+idea to put some kind of unique string at the beginning so you can be
+sure that future options don't take your name. For example, you
+might define an option, "local-host-name", feeling some confidence
+that no official DHCP option name will ever start with "local".
+.PP
+Once you have chosen a name, you must choose a code. For site-local
+options, all codes between 128 and 254 are reserved for DHCP options,
+so you can pick any one of these. In practice, some vendors have
+interpreted the protocol rather loosely and have used option code
+values greater than 128 themselves. There's no real way to avoid
+this problem, but it's not likely to cause too much trouble in
+practice.
+.PP
+The structure of an option is simply the format in which the option
+data appears. The ISC DHCP server currently supports a few simple
+types, like integers, booleans, strings and IP addresses, and it also
+supports the ability to define arrays of single types or arrays of
+fixed sequences of types.
+.PP
+New options are declared as follows:
+.PP
+.B option
+.I new-name
+.B code
+.I new-code
+.B =
+.I definition
+.B ;
+.PP
+The values of
+.I new-name
+and
+.I new-code
+should be the name you have chosen for the new option and the code you
+have chosen. The
+.I definition
+should be the definition of the structure of the option.
+.PP
+The following simple option type definitions are supported:
+.PP
+.B BOOLEAN
+.PP
+.B option
+.I new-name
+.B code
+.I new-code
+.B =
+.B boolean
+.B ;
+.PP
+An option of type boolean is a flag with a value of either on or off
+(or true or false). So an example use of the boolean type would be:
+.nf
+
+option use-zephyr code 180 = boolean;
+option use-zephyr on;
+
+.fi
+.B INTEGER
+.PP
+.B option
+.I new-name
+.B code
+.I new-code
+.B =
+.I sign
+.B integer
+.I width
+.B ;
+.PP
+The \fIsign\fR token should either be blank, \fIunsigned\fR
+or \fIsigned\fR. The width can be either 8, 16 or 32, and refers to
+the number of bits in the integer. So for example, the following two
+lines show a definition of the sql-connection-max option and its use:
+.nf
+
+option sql-connection-max code 192 = unsigned integer 16;
+option sql-connection-max 1536;
+
+.fi
+.B IP-ADDRESS
+.PP
+.B option
+.I new-name
+.B code
+.I new-code
+.B =
+.B ip-address
+.B ;
+.PP
+An option whose structure is an IP address can be expressed either as
+a domain name or as a dotted quad. So the following is an example use
+of the ip-address type:
+.nf
+
+option sql-server-address code 193 = ip-address;
+option sql-server-address sql.example.com;
+
+.fi
+.PP
+.B TEXT
+.PP
+.B option
+.I new-name
+.B code
+.I new-code
+.B =
+.B text
+.B ;
+.PP
+An option whose type is text will encode an ASCII text string. For
+example:
+.nf
+
+option sql-default-connection-name code 194 = text;
+option sql-default-connection-name "PRODZA";
+
+.fi
+.PP
+.B DATA STRING
+.PP
+.B option
+.I new-name
+.B code
+.I new-code
+.B =
+.B string
+.B ;
+.PP
+An option whose type is a data string is essentially just a collection
+of bytes, and can be specified either as quoted text, like the text
+type, or as a list of hexadecimal contents seperated by colons whose
+values must be between 0 and FF. For example:
+.nf
+
+option sql-identification-token code 195 = string;
+option sql-identification-token 17:23:19:a6:42:ea:99:7c:22;
+
+.fi
+.PP
+.B ENCAPSULATION
+.PP
+.B option
+.I new-name
+.B code
+.I new-code
+.B =
+.B encapsulate
+.I identifier
+.B ;
+.PP
+An option whose type is \fBencapsulate\fR will encapsulate the
+contents of the option space specified in \fIidentifier\fR. Examples
+of encapsulated options in the DHCP protocol as it currently exists
+include the vendor-encapsulated-options option, the netware-suboptions
+option and the relay-agent-information option.
+.nf
+
+option space local;
+option local.demo code 1 = text;
+option local-encapsulation code 197 = encapsulate local;
+option local.demo "demo";
+
+.fi
+.PP
+.B ARRAYS
+.PP
+Options can contain arrays of any of the above types except for the
+text and data string types, which aren't currently supported in
+arrays. An example of an array definition is as follows:
+.nf
+
+option kerberos-servers code 200 = array of ip-address;
+option kerberos-servers 10.20.10.1, 10.20.11.1;
+
+.fi
+.B RECORDS
+.PP
+Options can also contain data structures consisting of a sequence of
+data types, which is sometimes called a record type. For example:
+.nf
+
+option contrived-001 code 201 = { boolean, integer 32, text };
+option contrived-001 on 1772 "contrivance";
+
+.fi
+It's also possible to have options that are arrays of records, for
+example:
+.nf
+
+option new-static-routes code 201 = array of {
+ ip-address, ip-address, ip-address, integer 8 };
+option static-routes
+ 10.0.0.0 255.255.255.0 net-0-rtr.example.com 1,
+ 10.0.1.0 255.255.255.0 net-1-rtr.example.com 1,
+ 10.2.0.0 255.255.224.0 net-2-0-rtr.example.com 3;
+
+.fi
+.SH VENDOR ENCAPSULATED OPTIONS
+The DHCP protocol defines the \fB vendor-encapsulated-options\fR
+option, which allows vendors to define their own options that will be
+sent encapsulated in a standard DHCP option. The format of the
+.B vendor-encapsulated-options
+option is either a series of bytes whose format is not specified, or
+a sequence of options, each of which consists of a single-byte
+vendor-specific option code, followed by a single-byte length,
+followed by as many bytes of data as are specified in the length (the
+length does not include itself or the option code).
+.PP
+The value of this option can be set in one of two ways. The first
+way is to simply specify the data directly, using a text string or a
+colon-seperated list of hexadecimal values. For example:
+.PP
+.nf
+option vendor-encapsulated-options
+ 2:4:AC:11:41:1:
+ 3:12:73:75:6e:64:68:63:70:2d:73:65:72:76:65:72:31:37:2d:31:
+ 4:12:2f:65:78:70:6f:72:74:2f:72:6f:6f:74:2f:69:38:36:70:63;
+.fi
+.PP
+The second way of setting the value of this option is to have the DHCP
+server generate a vendor-specific option buffer. To do this, you
+must do four things: define an option space, define some options in
+that option space, provide values for them, and specify that that
+option space should be used to generate the
+.B vendor-encapsulated-options
+option.
+.PP
+To define a new option space in which vendor options can be stored,
+use the \fRoption space\fP statement:
+.PP
+.B option
+.B space
+.I name
+.B ;
+.PP
+The name can then be used in option definitions, as described earlier in
+this document. For example:
+.nf
+
+option space SUNW;
+option SUNW.server-address code 2 = ip-address;
+option SUNW.server-name code 3 = text;
+option SUNW.root-path code 4 = text;
+
+.fi
+Once you have defined an option space and the format of some options,
+you can set up scopes that define values for those options, and you
+can say when to use them. For example, suppose you want to handle
+two different classes of clients. Using the option space definition
+shown in the previous example, you can send different option values to
+different clients based on the vendor-class-identifier option that the
+clients send, as follows:
+.PP
+.nf
+class "vendor-classes" {
+ match option vendor-class-identifier;
+}
+
+option SUNW.server-address 172.17.65.1;
+option SUNW.server-name "sundhcp-server17-1";
+
+subclass "vendor-classes" "SUNW.Ultra-5_10" {
+ vendor-option-space SUNW;
+ option SUNW.root-path "/export/root/sparc";
+}
+
+subclass "vendor-classes" "SUNW.i86pc" {
+ vendor-option-space SUNW;
+ option SUNW.root-path "/export/root/i86pc";
+}
+.fi
+.PP
+As you can see in the preceding example, regular scoping rules apply,
+so you can define values that are global in the global scope, and only
+define values that are specific to a particular class in the local
+scope. The \fBvendor-option-space\fR declaration tells the DHCP
+server to use options in the SUNW option space to construct the
+.B vendor-encapsulated-options
+option.
.SH SEE ALSO
-dhcpd.conf(5), dhcpd.leases(5), dhclient.conf(5), dhcpd(8),
-dhclient(8), RFC2132, RFC2131.
+dhcpd.conf(5), dhcpd.leases(5), dhclient.conf(5), dhcp-eval(5), dhcpd(8),
+dhclient(8), RFC2132, RFC2131, draft-ietf-dhc-agent-options-??.txt.
.SH AUTHOR
-.B dhcpd(8)
-was written by Ted Lemon <mellon@vix.com>
-under a contract with Vixie Labs. Funding
-for this project was provided by the Internet Software Corporation.
+The Internet Software Consortium DHCP Distribution was written by Ted
+Lemon under a contract with Vixie Labs. Funding for
+this project was provided through the Internet Software Consortium.
Information about the Internet Software Consortium can be found at
-.B http://www.isc.org/isc.
+.B http://www.isc.org.
diff --git a/contrib/isc-dhcp/common/discover.c b/contrib/isc-dhcp/common/discover.c
new file mode 100644
index 000000000000..953bab0a1961
--- /dev/null
+++ b/contrib/isc-dhcp/common/discover.c
@@ -0,0 +1,1138 @@
+/* dispatch.c
+
+ Network input dispatcher... */
+
+/*
+ * Copyright (c) 1995-2001 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 and Nominum, Inc.
+ * To learn more about the Internet Software Consortium, see
+ * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
+ * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
+ * ``http://www.nominum.com''.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: discover.c,v 1.42.2.8 2001/10/18 20:10:26 mellon Exp $ Copyright (c) 1995-2001 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+#include <sys/ioctl.h>
+
+struct interface_info *interfaces, *dummy_interfaces, *fallback_interface;
+int interfaces_invalidated;
+int quiet_interface_discovery;
+u_int16_t local_port;
+u_int16_t remote_port;
+int (*dhcp_interface_setup_hook) (struct interface_info *, struct iaddr *);
+int (*dhcp_interface_discovery_hook) (struct interface_info *);
+isc_result_t (*dhcp_interface_startup_hook) (struct interface_info *);
+int (*dhcp_interface_shutdown_hook) (struct interface_info *);
+
+struct in_addr limited_broadcast;
+struct in_addr local_address;
+
+void (*bootp_packet_handler) PROTO ((struct interface_info *,
+ struct dhcp_packet *, unsigned,
+ unsigned int,
+ struct iaddr, struct hardware *));
+
+omapi_object_type_t *dhcp_type_interface;
+#if defined (TRACING)
+trace_type_t *interface_trace;
+trace_type_t *inpacket_trace;
+trace_type_t *outpacket_trace;
+#endif
+struct interface_info **interface_vector;
+int interface_count;
+int interface_max;
+
+OMAPI_OBJECT_ALLOC (interface, struct interface_info, dhcp_type_interface)
+
+isc_result_t interface_setup ()
+{
+ isc_result_t status;
+ status = omapi_object_type_register (&dhcp_type_interface,
+ "interface",
+ dhcp_interface_set_value,
+ dhcp_interface_get_value,
+ dhcp_interface_destroy,
+ dhcp_interface_signal_handler,
+ dhcp_interface_stuff_values,
+ dhcp_interface_lookup,
+ dhcp_interface_create,
+ dhcp_interface_remove,
+ 0, 0, 0,
+ sizeof (struct interface_info),
+ interface_initialize, RC_MISC);
+ if (status != ISC_R_SUCCESS)
+ log_fatal ("Can't register interface object type: %s",
+ isc_result_totext (status));
+
+ return status;
+}
+
+#if defined (TRACING)
+void interface_trace_setup ()
+{
+ interface_trace = trace_type_register ("interface", (void *)0,
+ trace_interface_input,
+ trace_interface_stop, MDL);
+ inpacket_trace = trace_type_register ("inpacket", (void *)0,
+ trace_inpacket_input,
+ trace_inpacket_stop, MDL);
+ outpacket_trace = trace_type_register ("outpacket", (void *)0,
+ trace_outpacket_input,
+ trace_outpacket_stop, MDL);
+}
+#endif
+
+isc_result_t interface_initialize (omapi_object_t *ipo,
+ const char *file, int line)
+{
+ struct interface_info *ip = (struct interface_info *)ipo;
+ ip -> rfdesc = ip -> wfdesc = -1;
+ return ISC_R_SUCCESS;
+}
+
+/* Use the SIOCGIFCONF ioctl to get a list of all the attached interfaces.
+ For each interface that's of type INET and not the loopback interface,
+ register that interface with the network I/O software, figure out what
+ subnet it's on, and add it to the list of interfaces. */
+
+void discover_interfaces (state)
+ int state;
+{
+ struct interface_info *tmp, *ip;
+ struct interface_info *last, *next;
+ char buf [2048];
+ struct ifconf ic;
+ struct ifreq ifr;
+ int i;
+ int sock;
+ int address_count = 0;
+ struct subnet *subnet;
+ struct shared_network *share;
+ struct sockaddr_in foo;
+ int ir;
+ struct ifreq *tif;
+#ifdef ALIAS_NAMES_PERMUTED
+ char *s;
+#endif
+ isc_result_t status;
+ static int setup_fallback = 0;
+ int wifcount = 0;
+
+ /* Create an unbound datagram socket to do the SIOCGIFADDR ioctl on. */
+ if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ log_fatal ("Can't create addrlist socket");
+
+ /* Get the interface configuration information... */
+
+#ifdef SIOCGIFCONF_ZERO_PROBE
+ /* linux will only tell us how long a buffer it wants if we give it
+ * a null buffer first. So, do a dry run to figure out the length.
+ *
+ * XXX this code is duplicated from below because trying to fold
+ * the logic into the if statement and goto resulted in excesssive
+ * obfuscation. The intent is that unless you run Linux you shouldn't
+ * have to deal with this. */
+
+ ic.ifc_len = 0;
+ ic.ifc_ifcu.ifcu_buf = (caddr_t)NULL;
+#else
+ /* otherwise, we just feed it a starting size, and it'll tell us if
+ * it needs more */
+
+ ic.ifc_len = sizeof buf;
+ ic.ifc_ifcu.ifcu_buf = (caddr_t)buf;
+#endif
+
+ gifconf_again:
+ i = ioctl(sock, SIOCGIFCONF, &ic);
+
+ if (i < 0)
+ log_fatal ("ioctl: SIOCGIFCONF: %m");
+
+#ifdef SIOCGIFCONF_ZERO_PROBE
+ /* Workaround for SIOCGIFCONF bug on some Linux versions. */
+ if (ic.ifc_ifcu.ifcu_buf == 0 && ic.ifc_len == 0) {
+ ic.ifc_len = sizeof buf;
+ ic.ifc_ifcu.ifcu_buf = (caddr_t)buf;
+ goto gifconf_again;
+ }
+#endif
+
+ /* If the SIOCGIFCONF resulted in more data than would fit in
+ a buffer, allocate a bigger buffer. */
+ if ((ic.ifc_ifcu.ifcu_buf == buf
+#ifdef SIOCGIFCONF_ZERO_PROBE
+ || ic.ifc_ifcu.ifcu_buf == 0
+#endif
+ ) && ic.ifc_len > sizeof buf) {
+ ic.ifc_ifcu.ifcu_buf = dmalloc ((size_t)ic.ifc_len, MDL);
+ if (!ic.ifc_ifcu.ifcu_buf)
+ log_fatal ("Can't allocate SIOCGIFCONF buffer.");
+ goto gifconf_again;
+#ifdef SIOCGIFCONF_ZERO_PROBE
+ } else if (ic.ifc_ifcu.ifcu_buf == 0) {
+ ic.ifc_ifcu.ifcu_buf = (caddr_t)buf;
+ ic.ifc_len = sizeof buf;
+ goto gifconf_again;
+#endif
+ }
+
+
+ /* If we already have a list of interfaces, and we're running as
+ a DHCP server, the interfaces were requested. */
+ if (interfaces && (state == DISCOVER_SERVER ||
+ state == DISCOVER_RELAY ||
+ state == DISCOVER_REQUESTED))
+ ir = 0;
+ else if (state == DISCOVER_UNCONFIGURED)
+ ir = INTERFACE_REQUESTED | INTERFACE_AUTOMATIC;
+ else
+ ir = INTERFACE_REQUESTED;
+
+ /* Cycle through the list of interfaces looking for IP addresses. */
+ for (i = 0; i < ic.ifc_len;) {
+ struct ifreq *ifp = (struct ifreq *)((caddr_t)ic.ifc_req + i);
+#ifdef HAVE_SA_LEN
+ if (ifp -> ifr_