Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/LICENSE =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/LICENSE (nonexistent) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/LICENSE (revision 131136) @@ -0,0 +1,20 @@ +# Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") +# Copyright (c) 1995-2003 by Internet Software Consortium +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# Internet Systems Consortium, Inc. +# 950 Charter Street +# Redwood City, CA 94063 +# +# http://www.isc.org/ Property changes on: vendor/isc-dhcp/dist/contrib/isc-dhcp/LICENSE ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/Makefile =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/Makefile (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/Makefile (revision 131136) @@ -1,96 +1,86 @@ # Makefile # -# Copyright (c) 2002 Internet Software Consortium. -# All rights reserved. +# Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") +# Copyright (c) 1995-2003 by Internet Software Consortium # -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. # -# 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. +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -# 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. +# Internet Systems Consortium, Inc. +# 950 Charter Street +# Redwood City, CA 94063 +# +# http://www.isc.org/ # -# This software has been written for the Internet Software Consortium +# This software has been written for Internet Systems Consortium # by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. -# To learn more about the Internet Software Consortium, see +# To learn more about Internet Systems 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 Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/Makefile.conf =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/Makefile.conf (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/Makefile.conf (revision 131136) @@ -1,499 +1,503 @@ # Makefile.conf # -# Copyright (c) 1996-2002 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: +# Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") +# Copyright (c) 1995-2003 by Internet Software Consortium # -# http://www.isc.org/isc-license-1.0.html. +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. # -# 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. +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -# Support and other services are available for ISC products - see -# http://www.isc.org for more information. -# +# Internet Systems Consortium, Inc. +# 950 Charter Street +# Redwood City, CA 94063 +# +# http://www.isc.org/ ## Defaults... SCRIPT = none USERBINDIR = /usr/bin BINDIR = /usr/sbin CLIENTBINDIR=/sbin ADMMANDIR = /usr/share/man/cat8 ADMMANEXT = .0 FFMANDIR = /usr/share/man/cat5 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 = 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 ##--majver-- # Minor version number (if applicable) ##--minver-- MINORVERSION=MinorVersion ##--minver-- ## Porting:: # # For each supported operating system, there is a block of text below # beginning with #--os-name-- and ending with #--os-name--. Between # these delimiters are assignments, commented out, which define the # Makefile variables required for that operating system. # # The configure shell script figures out what operating system it's # being run on and then runs Makefile.dist through a sed script which # removes the comment characters from the appropriate set of # assignments, and writes the output to Makefile. ## AIX 4.3 ##--aix-- #CF = cf/aix.h #CC=cc -Daix #INSTALL=/usr/ucb/install -c #MANINSTALL=/usr/ucb/install -c -m 444 #ADMMANEXT = .8 #FFMANEXT = .5 #VARRUN = /etc #VARDB = /etc ##--aix-- ## NEXTSTEP 3.x,4.x ##--nextstep-- #CF = cf/nextstep.h #CC=cc #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 #CLIENTBINDIR=/etc #ADMMANEXT = .8 #FFMANEXT = .5 #VARRUN = /etc #VARDB = /etc ##--sunos4-- ## Solaris 2.5 (with gcc) ##--sunos5-gcc-- #INSTALL=/usr/ucb/install #MANINSTALL=/usr/ucb/install #LIBS = -lresolv -lsocket -lnsl -lgen #CC=gcc #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/man1m #ADMMANEXT = .1m #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 ##--sunos5-gcc-- ## Solaris 2.5 (with Sun cc) ##--sunos5-cc-- #INSTALL=/usr/ucb/install #MANINSTALL=/usr/ucb/install #LIBS = -lresolv -lsocket -lnsl -lgen #CC=cc #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/man1m #ADMMANEXT = .1m #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 ##--sunos5-cc-- ## DEC Alpha/OSF1 ##--alphaosf-- #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 through 4.0 ##--bsdos-- #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 #SCRIPT=freebsd ##--freebsd-- ## Rhapsody ##--rhapsody-- #CF = cf/rhapsody.h #COPTS = -Wall -Wno-unused -Wno-implicit -Wno-comment \ # -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=freebsd ##--darwin-- ## NetBSD ##--netbsd-- #CF = cf/netbsd.h #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 #CLIENTBINDIR=/etc #VARRUN = /etc #VARDB = /etc #CF = cf/ultrix.h #ADMMANDIR = /usr/man/man8 #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) \ # $(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 #SCRIPT=linux ##--linux-1-- ## Linux 2.0 ##--linux-2.0-- #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 #SCRIPT=linux ##--linux-2.0-- ## Linux 2.1 ##--linux-2.1-- #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 #SCRIPT=linux ##--linux-2.1-- ## Linux 2.2 ##--linux-2.2-- #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 #SCRIPT=linux ##--linux-2.2-- ## 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 #CLIENTBINDIR=/etc #ADMMANDIR = /usr/man/cat.ADMN #ADMMANEXT = .ADMN.Z #FFMANDIR = /usr/man/cat.SFF #FFMANEXT = .SFF.Z #INSTALL = cp #MANFROM = < #MANINSTALL = compress #MANTO = > #VARRUN = /etc #VARDB = /etc #CATMANPAGES= ##--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-- #CF = cf/qnx.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 = /etc #COPTS=-w3 -Dlint $(BINDDEF) $(CC_OPTIONS) #LFLAGS=$(DEBUG) "-Wl,op symfile" -l socket #MANINSTALL = /bin/true #INSTALL = cp #BINDIR = /etc #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 #ADMMANDIR = /usr/man/man8 #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 #BINDIR = /etc #CLIENTBINDIR = /etc #CC=/usr/local/i386-unknown-cygwin32/bin/gcc #AR=/usr/local/i386-unknown-cygwin32/bin/ar #AS=/usr/local/i386-unknown-cygwin32/bin/as #LD=/usr/local/i386-unknown-cygwin32/bin/ld #NM=/usr/local/i386-unknown-cygwin32/bin/nm #RANLIB=/usr/local/i386-unknown-cygwin32/bin/ranlib #STRIP=/usr/local/i386-unknown-cygwin32/bin/strip ##--cygwin32-- ## IRIX 6.x ##--irix-- #LFLAGS=$(DEBUG) -Wl,-woff,84 -Wl,-woff,85 -Wl,-woff,134 #CC=gcc #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 #CHMOD = chmod #ETC = /etc #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-- Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/Makefile.dist =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/Makefile.dist (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/Makefile.dist (revision 131136) @@ -1,63 +1,68 @@ # Makefile.dist # -# Copyright (c) 1996-2002 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: +# Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") +# Copyright (c) 1995-2003 by Internet Software Consortium # -# http://www.isc.org/isc-license-1.0.html. +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. # -# 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. +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -# Support and other services are available for ISC products - see -# http://www.isc.org for more information. -# +# Internet Systems Consortium, Inc. +# 950 Charter Street +# Redwood City, CA 94063 +# +# http://www.isc.org/ + 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 install: @for dir in ${SUBDIRS}; do \ echo "Installing in $$dir"; \ (cd $$dir; $(MAKE) install) || exit 1; \ done depend: @for dir in ${SUBDIRS}; do \ echo "Making dependencies in $$dir"; \ (cd $$dir; $(MAKE) depend) || exit 1; \ done clean: @for dir in ${SUBDIRS}; do \ echo "Cleaning in $$dir"; \ (cd $$dir; $(MAKE) clean) || exit 1; \ done realclean: @for dir in ${SUBDIRS}; do \ echo "Really cleaning in $$dir"; \ (cd $$dir; $(MAKE) realclean) || exit 1; \ done distclean: @for dir in ${SUBDIRS}; do \ echo "Really, really cleaning in $$dir"; \ (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 Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/README =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/README (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/README (revision 131136) @@ -1,645 +1,642 @@ - Internet Software Consortium DHCP Distribution - Version 3.0.1 - Release Candidate 12 - April 28, 2002 + Internet Systems Consortium DHCP Distribution + Version 3.0.1rc14 + June 09, 2004 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. 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. 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. DHCP relay agent documentation is in the dhcrelay man page, the source for which is distributed in the relay/ subdirectory. 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). 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 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. 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. 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. RELEASE STATUS -This is the twelfth release candidate of version 3.0.1 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. +This is fourteenth release candidate of version 3.0.1 of the ISC DHCP +Distribution. 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. +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. 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. 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. 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''. BUILDING THE DHCP DISTRIBUTION UNPACKING IT To build the DHCP Distribution, unpack the compressed tar file using the tar utility and the gzip command - type something like: - zcat dhcp-3.0.1rc11.tar.gz |tar xvf - + zcat dhcp-3.0.1rc14.tar.gz |tar xvf - On BSD/OS, you have to type gzcat, not zcat, and you may run into similar problems on other operating systems. CONFIGURING IT -Now, cd to the dhcp-3.0.1rc11 subdirectory that you've just +Now, cd to the dhcp-3.0.1rc14 subdirectory that you've just created and configure the source tree by typing: ./configure 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. 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. 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 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. INSTALLING THE DHCP DISTRIBUTION 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''. 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. 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: 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.) 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. LINUX: PROTOCOL NOT CONFIGURED 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: Make sure CONFIG_PACKET (Packet socket) and CONFIG_FILTER (Socket Filtering) are enabled in your kernel configuration 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 see displayed on the menu or in the questionnaire. You can also edit your linux kernel .config file directly: set CONFIG_FILTER=y and CONFIG_PACKET=y. If you do this, make sure you run ``make oldconfig'' 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. If the preceding paragraph made no sense to you, ask your Linux vendor/guru for help - please don't ask us. 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. LINUX: BROADCAST 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. 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 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: route add -host 255.255.255.255 dev eth0 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: 255.255.255.255 all-ones Then, try: route add -host all-ones dev eth0 Another route that has worked for some users is: route add -net 255.255.255.0 dev eth0 If you are not using eth0 as your network interface, you should specify the network interface you *are* using in your route command. LINUX: IP BOOTP AGENT Some versions of the Linux 2.1 kernel apparently prevent dhcpd from working unless you enable it by doing the following: echo 1 >/proc/sys/net/ipv4/ip_bootp_agent 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 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. 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. 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. SCO 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. 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: ifconfig net0 alias 10.1.1.1 netmask 8.0.0.0 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. 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!). HP-UX 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): 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 ULTRIX 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. FreeBSD 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. Modern versions of FreeBSD include the ISC DHCP 3.0 client as part of the base system, and the full distribution (for the DHCP server and relay agent) is available from the Ports Collection in /usr/ports/net/isc-dhcp3, or as a package on FreeBSD installation CDROMs. NeXTSTEP 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. SOLARIS 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. 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, 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 ISC client, but in most cases it will be a lot easier for you to just 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 +on Internet Systems 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. SUPPORT -The Internet Software Consortium DHCP server is not a commercial +The Internet Systems 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. 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. 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. +version, though - for example, if you're running 3.0pl2, you don't have +to upgrade to a 3.0.1rc (release candidate) 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 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. +Please see http://www.isc.org/sw/dhcp/ for details on how to subscribe +to the ISC DHCP mailing lists. Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/RELNOTES =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/RELNOTES (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/RELNOTES (revision 131136) @@ -1,1227 +1,1276 @@ - Internet Software Consortium DHCP Distribution - Version 3.0.1 - Release Candidate 12 - June, 2002 + Internet Systems Consortium DHCP Distribution + Version 3.0.1rc14 + June 09, 2004 Release Notes 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. +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. 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. 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. + Changes since 3.0.1rc13 + +! CAN-2004-0460 - CERT VU#317350: Five stack overflow exploits were closed + in logging messages with excessively long hostnames provided by the + clients. It is highly probable that these could have been used by + attackers to gain arbitrary root access on systems using ISC DHCP 3.0.1 + release candidates 12 or 13. Special thanks to Gregory Duchemin for + both finding and solving the problem. + +! CAN-2004-0461 - CERT VU#654390: Once the above was closed, an opening + in log_*() functions was evidented, on some specific platforms where + vsnprintf() was not believed to be available and calls were wrapped to + sprintf() instead. Again, credit goes to Gregory Duchemin for finding + the problem. Calls to snprintf() are now linked to a distribution-local + snprintf implementation, only in those cases where the architecture is + not known to provide one (see includes/cf/[arch].h). If you experience + linking problems with snprintf/vsnprintf or 'isc_print_' functions, this + is where to look. This vulnerability did not exist in any previously + published version of ISC DHCP. + +- Compilation on hpux 11.11 was repaired. + +- 'The cross-compile bug fix' was backed out. + + Changes since 3.0.1rc12 + +- Fixed a bug in omapi lease lookup function, to form the hardware + address for the hash lookup correctly, thanks to a patch from + Richard Hirst. + +- Fixed a bug where dhcrelay was sending relayed responses back to the + broadcast address, but with the source's unicast mac address. Should + now conform to rfc2131 section 4.1. + +- Cross-compile bug fix; use $(AR) instead of ar. Thanks to Morten Brorup. + +- Fixed a crash bug in dhclient where dhcpd servers that do not provide + renewal times results in an FPE. As a side effect, dhclient can now + properly handle 0xFFFFFFFF (-1) expiry times supplied by servers. Thanks + to a patch from Burt Silverman. + +- The 'ping timeout' debugs from rc12 were removed to -DDEBUG only, + and reformatted to correct a compilation error on solaris platforms. + +- A patch was applied which fixes a case where leases read from the + leases database do not properly over-ride previously read leases. + +- dhcpctl.3 manpage was tweaked. + Changes since 3.0.1rc11 - A patch from Steve Campbell was applied with minor modifications to permit reverse dns PTR record updates with values containing spaces. - A patch from Florian Lohoff was applied with some modifications to dhcrelay. It now discards packets whose hop count exceeds 10 by default, and a command-line option (-c) can be used to set this threshold. - A failover bug relating to identifying peers by name length instead of by name was fixed. - Delcaring failover configs within shared-network statements should no longer result in error. - The -nw command line option to dhclient now works. - Thanks to a patch from Michael Richardson: - Some problems with long option processing have been fixed. - Some fixes to minires so that updates of KEY records will work. - contrib/ms2isc was updated by Shu-Min Chang of the Intel Corporation. see contrib/ms2isc/readme.txt for revision notes. - Dhclient no longer uses shell commands to kill another instance of itself, it sends the signal directly. Thanks to a patch from Martin Blapp. - The FreeBSD dhclient-script was changed so that a failure to write to /etc/resolv.conf does not prematurely end the script. This keeps dhclient from looping infinitely when this is the case. Thanks to a patch from Martin Blapp. - A patch from Bill Stephens was applied which resolves a problem with lease expiry times in failover configurations. - A memory leak in configuration parsing was closed thanks to a patch from Steve G. - The function which discovers interfaces will now skip non-broadcast or point-to-point interfaces, thanks to a patch from David Brownlee. - Options not yet known by the dhcpd or dhclient have had their names changed such that they do not contain # symbols, in case they should ever appear in a lease file. An option that might have been named "#144" is now "unknown-144". + +- Another patch from Bill Stephens which allows the ping-check timeout to + be configured as 'ping-timeout'. Defaults to 1. Changes since 3.0.1rc10 - Potential buffer overflows in minires repaired. - A change to the linux client script to use /bin/bash, since /bin/sh may not be bash. - Some missing va_end cleanups thanks to a patch from Thomas Klausner. - A correction of boolean parsing syntax validation - some illegal syntaxes that worked before are now detected and produce errs, some legal syntaxes that errored before will now work properly. - Some search-and-replace errors that caused some options to change their names was repaired. - Shu-min Chang of the Intel corporation has contributed a perl script and module that converts the MS NT4 DHCP configuration to a ISC DHCP3 configuration file. - Applied the remainder of the dhcpctl memory leak patch provided by Bill Squier at ReefEdge, Inc. (groo@reefedge.com). - Missing non-optional failover peer configurations will now result in a soft error rather than a null dereference. Changes since 3.0.1rc9 - A format string was corrected to fix compiler warnings. - A number of spelling corrections were made in the man pages. - The dhclient.conf.5 man page was changed to refer to do-forward-updates rather than a configuration option that doesn't exist. - A FreeBSD-specific bug in the interface removal handling was fixed. - A Linux-specific Token Ring detection problem was fixed. - Hashes removed from as-yet-unknown agent options, having those options appear in reality before we know about them will no longer produce self-corrupting lease databases. - dhclient will use the proper port numbers now when using the -g option. - A order-of-operations bug with 2 match clauses in 1 class statement is fixed thanks to a patch from Andrew Matheson. - Compilation problems on Solaris were fixed. - Compilation problems when built with DEBUG or DEBUG_PACKET were repaired. - A fix to the dhcp ack process which makes certain group options will be included in the first DHCPOFFER message was made thanks to a patch from Ling Gou. - A few memory leaks were repaired thanks to patches from Bill Squier at ReefEdge, Inc. (groo@reefedge.com). - A fix for shared-networks that sometimes give clients options for the wrong subnets (in particular, 'option routers') was applied, thanks to Ted Lemon for the patch. - Omshell's handling of dotted octets as values was changed such that dots one after the other produce zero values in the integer string. Changes since 3.0.1rc8 - Fix a format string vulnerability in the server that could lead to a remote root compromise (discovered by NGSEC Research Team, www.ngsec.com). - Add additional support for NetBSD/sparc64. - Fix a bug in the command-line parsing of the client. Also, resolve a memory leak. - Add better support for shells other than bash in the Linux client script. - Various build fixes for modern versions of FreeBSD and Linux. - Fix a bad bounds check when printing binding state names. - Clarify documentation about fixed-address and multiple addresses. - Fix a typo in the authoritative error message. - Make a log entry when we can't write a billing class. - Use conversion targets that are the right size on all architectures. - Increment the hop count when relaying. - Log a message when lease state is changed through OMAPI. - Don't rerun the shared_network when evaluating the pool. - Fix a reversed test in the parser. - Change the type of rbuf_max. - Make FTS_LAST a manifest constant to quiet warnings. Changes since 3.0.1rc7 - Fix two compiler warnings that are generated when compiling on Solaris with gcc. These stop the build, even though they weren't actually errors, because we prefer that our builds generate no warnings. Changes since 3.0.1rc6 - Don't allow a lease that's in the EXPIRED, RELEASED or RESET state to be renewed. - Implement lease stealing for cases where the primary has fewer leases than the secondary, as called for by the standard. - Add a fudge factor to the lease expiry acceptance code, (suggested by Kevin Miller of CMU). - Fix a bug in permit_list_match that made it much too willing to say that two permit lists matched. - Unless DEBUG_DNS_UPDATES is defined, print more user-friendly (and also more compact) messages about DNS updates. - Fix a bug in generating wire-format domain names for the FQDN option. - Fix a bug where the FQDN option would not be returned if the client requested it, contrary to the standard. - On Darwin, use the FreeBSD DHCP client script. - On NetBSD/sparc, don't check for casting warnings. - Add a flag in the DHCP client to disable updating the client's A record when sending an FQDN option indicating that the client is going to update its A record. - In the client, don't attempt a DNS update until one second after configuring the new IP address, and if the update times out, keep trying until a response, positive or negative, is received from the DNS server. - Fix an uninitialized memory bug in the DHCP client. - Apply some FreeBSD-specific bug fixes suggested by Murray Stokely. - Fix a bug in ns_parserr(), where it was returning the wrong sort of result code in some cases (suggested by Ben Harris of the NetBSD project). - Fix a bug in is_identifier(), where it was checking against EOF instead of the END_OF_FILE token (also suggested by Ben Harris). - Fix a bug where if an option universe contained no options, the DHCP server could dump core (Walter Steiner). - Fix a bug in the handling of encapsulated options. - Fix a bug that prevented NWIP suboptions from being processed. - Delete the FTS_BOOTP and FTS_RESERVED states and implement them as modifier flags to the FTS_ACTIVE state, as called for in the failover protocol standard. - Fix bugs in the pool merging code that resulted in references and dereferences of null pointers. This bug had no impact unless the POINTER_DEBUG flag was defined. - In the server, added a do-forward-updates flag that can be used to disable forward updates in all cases, so that sites that want the clients to take sole responsibility for updating their A record can do so. - Make it possible to disable optimization of PTR record updates. Changes since 3.0.1rc5 - Include some new documentation and changes provided by Karl Auer. - Add a workaround for some Lexmark printers that send a double-NUL- terminated host-name option, which would break DNS updates. - Fix an off-by-one error in the MAC-address checking code for DHCPRELEASE that was added in 3.0.1rc5. - 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. - 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. - 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. Changes since 3.0.1rc4 - Fix a bug that would cause the DHCP server to spin if asked to parse a certain kind of incorrect statement. - Fix a related bug that would prevent an error from being reported in the same case. - Additional documentation. - Make sure that the hardware address matches the lease when processing a DHCPRELEASE message. Changes since 3.0.1rc3 - A minor bug fix in the arguments to a logging function call. - Documentation update for dhcpd.conf. Changes since 3.0.1rc2 - 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. Changes since 3.0.1rc1 - 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. - Install defaults for failover maximum outstanding updates and maximum silent time. This prevents problems that might occur if these values were not configured. - Don't do DDNS deletes if ddns-update-style is none. - Return relay agent information options in DHCPNAK. This prevents DHCPNAK messages from being dropped when the relay agent information option contains routing information. - Fix a problem where coming up in recover wouldn't result in an update request being sent. - Add some more chatty messages when we start a recovery update and when it's done. - 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. - 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. - 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 since 3.0 - Make allocators for hash tables. As a side effect, this fixes a memory smash in the subclass allocation code. - Fix a small bug in omshell where if you try to close an object when no object is open, it dumps core. - Fix an obscure coredump that could occur on shutdown. - Fix a bug in the recording of host declaration rubouts in the lease file. - Fix two potential spins in the host deletion code. - Fix a core dump that would happen if an application tried to update a host object attribute with a null value. Changes since 3.0 Release Candidate 12 - Fix a memory leak in the evaluation code. - Fix an obscure core dump. - Print a couple of new warnings when parsing the configuration file when crucial information is left out. - Log "no free leases" as an error. - Documentation updates. Changes since 3.0 Release Candidate 11 - Always return a subnet selection option if one is sent. - Fix a warning that was being printed because an automatic data structure wasn't zeroed. - Fix some failover state transitions that were being handled incorrectly. - 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. Changes since 3.0 Release Candidate 10 - Fix a bug that was preventing released leases from changing state in failover-enabled pools. - Fix a core dump in the client identifier finder code (for host declarations). - Finish fixing a bug where bogus data would sometimes get logged to the dhclient.leases file because it was opened as descriptor 2. - Fix the Linux dhclient-script according to suggestions made by several people on the dhcp-client mailing list. - Log successful DNS updates at LOG_INFO, not LOG_ERROR. - Print an error message and refuse to run if a failover peer is defined but not referenced by any pools. - Correct a confusing error message in failover. Changes since 3.0 Release Candidate 9 - Fix a bug in lease allocation for Dynamic BOOTP clients. Changes since 3.0 Release Candidate 8 Patchlevel 2 - Fix a bug that prevented update-static-leases from working. - Document failover-state OMAPI object. - Fix a compilation error on SunOS 4. Changes since 3.0 Release Candidate 8 Patchlevel 1 - 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. - 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. - Clean up the omshell, dhcpctl and omapi man pages a bit. Changes since 3.0 Release Candidate 8 - Fix a bug that could cause the DHCP server to spin if one-lease-per-client was enabled. - Fix a bug that was causing core dumps on BSD/os in the presence of malformed packets. - In partner-down state, don't restrict lease lengths to MCLT. - 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. - Fix some compilation problems on BSD/os. - Fix a bunch of memory leaks. - Fix a couple of bugs in the option printer. - Fix an obscure error reporting bug in the dns update code, and also make the message clearer when a key algorithm isn't supported. - Fix a bug in the tracing code that prevented trace runs that used tcp connections from being played back. - Add some additional debugging capability for catching memory leaks on exit. - Make the client release the lease correctly on shutdown. - Add some configurability to the build system. - Install omshell manual page in man1, not man8. - 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. Changes since 3.0 Release Candidate 7 - Fix a bug in failover where we weren't sending updates after a transition from communications-interrupted to normal. - 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). - Add a control object in both client and server that allows either daemon to be shut down cleanly. - 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. - In the server, if the OMAPI listener port is occupied, keep trying to get it, rather than simply giving up and exiting. - Support fetching variables from leases and also updating and adding variables to leases via OMAPI. - If two failover peers have wildly different clocks, refuse to start doing failover. - Fix a bug in the DNS update code that could cause core dumps when running on alpha processors. - Fixed a bug in ddns updates for static lease entries, thanks to a patch from Andrey M Linkevitch. - Add support for Darwin/MacOS X - Install omshell (including new documentation). - Support DNS updates in the client (this is a very obscure feature that most DHCP client users probably will not be able to use). - Somewhat cleaner status logging in the client. - Make OMAPI key naming syntax compatible with the way keys are actually named (key names are domain names). - Fix a bug in the lease file writer. - Install DHCP ISC headers in a different place than BIND 9 ISC headers, to avoid causing trouble in BIND 9 builds. - Don't send updates for attributes on an object when the attributes haven't changed. Support deleting attributes on remote objects. - Fix a number of bugs in omshell, and add the unset and refresh statements. - Handle disconnects in OMAPI a little bit more intelligently (so that the caller gets ECONNRESET instead of EINVAL). - 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. Changes since 3.0 Release Candidate 6 - 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 a memory leak that could happen in certain obscure cases when using omapi to manipulate leases. - Fix some bugs and omissions in omshell. Changes since 3.0 Release Candidate 5 - Fix a bug in omapi_object_dereference that prevented objects in chains from having their reference counts decreased on dereference. - 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. - Add code in the OMAPI protocol handler to trace memory leakage. - Clean up the memory allocation/reference history printer. - Support input of dotted quads and colon-separated hex lists as attribute values in omshell. - Fix a typo in the Linux interface discovery code. - Conditionalize a piece of trace code that wasn't conditional. Changes since 3.0 Release Candidate 4 - Fix a bug that would prevent leases from being abandoned properly on DHCPDECLINE. - Fix failover peer OMAPI support. - In failover, correctly handle expiration of leases. Previously, leases would never be reclaimed because they couldn't make the transition from EXPIRED to FREE. - Fix some broken failover state transitions. - Documentation fixes. - Take out an unnecessary check in DHCP relay agent information option stashing code that was preventing REBINDING clients from rebinding. - Prevent failover peers from allocating leases in DHCPREQUEST processing if the lease belongs to the other server. - Record server version in lease file introductory comment. - Correctly report connection errors in OMAPI and failover. - Make authentication signature algorithm name comparisons in OMAPI case-insensitive. - Fix compile problem on SunOS 4.x - If a signature algorithm is not terminated with '.', terminate it so that comparisons between fully-qualified names will work consistently. - Different SIOCGIFCONF probe code, may "fix" problem on some Linux systems with the probe not working correctly. - Don't allow user to type omapi key on command line of omshell. Changes since 3.0 Release Candidate 3 - 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. - Document OMAPI server objects. Changes since 3.0 Release Candidate 2 Patchlevel 1 - Fix some problems in the DDNS update code. Thanks to Albert Herranz for figuring out the main problem. - Fix some reference counting errors on host entries that were causing core dumps. - Fix a byte-swap bug in the token ring code, thanks to Jochen Friedrich. - Fix a bug in lease billing, thanks to Jonas Bulow. Changes since 3.0 Release Candidate 2 - 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. - Fix a bug where lease updates would fail on Digital Unix (and maybe others) because malloc was called with a size of zero. - Fix a core dump that happens when the DHCP server can't create its trace file. Changes since 3.0 Release Candidate 1 Patchlevel 1 - 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 a case where the failover code was printing an error message when no error had occurred. - 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. - Be smart about going into recover_wait. - 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. - Fix a problem with billing classes where they would not be unbilled when the client lease expired. - 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. - Fix a bug in the relay agent where if you specified interfaces on the command line, it would fail. - Fix a couple of small bugs in the omapi connection object (no known user impact). - Add the missing 3.0 Beta 1 lease conversion script. - Read dhcp client script hooks if they exist, rather than only if they're executable. Changes since 3.0 Release Candidate 1 - 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! - Fix a small bug in binary-to-ascii, thanks to H. Peter Anvin of Transmeta. - 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. - 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. Changes since 3.0 Beta 2 Patchlevel 24 - Went over problematic failover state transitions and made them all work, so that failover should now much less fragile. - Add some dhcpctl and omapi documentation - Fix compile errors when compiling with unusual predefines. - Make Token Ring work on Linux 2.4 - Fix the Digital Unix BPF_WORDALIGN bug. - Fix some dhcp client documentation errors. - Update some parts of the README file. - Support GCC on SCO. Changes since 3.0 Beta 2 Patchlevel 23 - Fix a bug in the DNS update code where a status code was not being checked. This may have been causing core dumps. - 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. - When processing failover transactions, where acks will be deferred, process the state transition immediately. - Don't try to use the new SIOCGIFCONF buffer size detection code on Linux 2.0, which doesn't provide this functionality. - Apply a patch suggested by Tuan Uong for a problem in dlpi.c. - Fix a problem in using the which command in the configure script. - Fix a parse error in the client when setting up an omapi listener. - Document the -n and -g flags to the client. - 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. - If an interface is removed, the client will now notice that it is gone rather than spinning. This has only been tested on NetBSD. - The client will attempt to get an address even if it can't create a lease file. - Don't overwrite tracefiles. - Fix some memory allocation bugs in failover. Changes since 3.0 Beta 2 Patchlevel 22 - Apply some patches suggested by Cyrille Lefevre, who is maintaining the FreeBSD ISC DHCP Distribution port. - Fix a core dump in DHCPRELEASE. Changes since 3.0 Beta 2 Patchlevel 21 - This time for sure: fix the spin described in the changes for pl20. Changes since 3.0 Beta 2 Patchlevel 20 - Fix a problem with Linux detecting large numbers of interfaces (Ben) - Fix a memory smash in the quotify code, which was introduced in pl19. - 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. Changes since 3.0 Beta 2 Patchlevel 19 - Fix a bug that could cause the server to abort if compiled with POINTER_DEBUG enabled. - Fix a bug that could cause the server to spin when responding to a DHCPREQUEST. - Apply Joost Mulders' suggested patches for DLPI on x86. - Support NUL characters in quoted strings. - Install unformatted man pages on SunOS. Changes since 3.0 Beta 2 Patchlevel 18 - Allow the server to be placed in partner-down state using OMAPI. (Damien Neil) - Implement omshell, which can be used to do arbitrary things to the server (in theory). (Damien Neil) - 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) - 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. - 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. - Fix a problem where the server could write out a colon-separated 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. - Fix documentation for sending non-standard options. - 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: option option-nnn code nnn = string; You can use a descriptive name instead of option-nnn if you like. - 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 client script exit status check, according to a fix supplied by Hermann Lauer. - Fix an endianness bug in the tracefile support, regarding ICMP messages. - Fix a bug in the client where the medium would not work correctly if it contained quoted strings. ** there was no pl17 ** Changes since 3.0 Beta 2 Patchlevel 16 - 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. - 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 bug in DHCPREQUEST handling that resulted in DHCPNAK messages not being send in some cases when they were needed. - Make the lease structure somewhat more compact. - Make initial failover startup *much* faster. This was researched and implemented by Damien Neil. - Add a --version flag to all executables, which prints the program name and version to standard output. - Don't rewrite the lease file every thousand leases. - A bug in nit.c for older SunOS machines was fixed by a patch sent in by Takeshi Hagiwara. - Fix a memory corruption bug in the DHCP client. - Lots of documentation updates. - Add a feature allowing environment variables to be passed to the DHCP client script on the DHCP client command line. - Fix client medium support, which had been broken for some time. - Fix a bug in the DHCP client initial startup backoff interval, which would cause two DHCPDISCOVERS to be sent back-to-back on startup. Changes since 3.0 Beta 2 Patchlevel 15 - Some documentation tweaks. - Maybe fix a problem in the DLPI code. - Fix some error code space inconsistencies in ddns update code. - Support relay agents that intercept unicast DHCP messages to stuff agent options into them. - Fix a small memory leak in the relay agent option support code. - Fix a core dump that would occur if a packet was sent with no options. Changes since 3.0 Beta 2 Patchlevel 14 - 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 up documentation. - Fix a couple of small memory leaks that would have added up significantly in a high-demand situation. - Add a log-facility configuration parameter. - Fix a compile error on some older operating systems. - Add the ability in the client to execute certain statements before transmitting packets to the server. Handy for debugging; not much practical use otherwise. - Don't send faked-out giaddr when renewing or bound - again, useful for debugging. Changes since 3.0 Beta 2 Patchlevel 13 - 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. - Work around the Win98 DHCP client, which NUL-terminates the FQDN option. - 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. - Fix some log messages that can be printed when failover is operating that were not printing enough information. - It was possible for a DHCPDISCOVER to get an allocation even when the state machine said the server shouldn't be responding. - 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. - When we get a bogus state lease binding state transition, don't do the transition. Changes since 3.0 Beta 2 Patchlevel 12 - Fixed a couple of silly compile errors. Changes since 3.0 Beta 2 Patchlevel 11 - 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. - 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. - Fix a problem with alignment of the input buffer in bpf in cases where two packets arrive in the same bpf read. - Fix a problem where the relay agent would crash if you specified an interface name on the command line. - Add the ability to conditionalize client behaviour based on the client state. - 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. - 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 - 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. - Implement client- and server-side support for using the Client FQDN option. - 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. - 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. - 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! - 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. Changes since 3.0 Beta 2 Patchlevel 5 - Fix a bug in the recent enhancement to the interface discovery code to support arbitrary-length interface lists. - Support NUL-terminated DHCP options when initializing client-script environment. - 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. - Don't ever record a state of 'startup'. - Don't try to evaluate the local failover binding address if none was specified. Thanks to Joseph Breu for finding this. Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/client/Makefile.dist =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/client/Makefile.dist (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/client/Makefile.dist (revision 131136) @@ -1,129 +1,133 @@ # Makefile.dist # -# Copyright (c) 1996-2002 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: +# Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") +# Copyright (c) 1996-2003 by Internet Software Consortium # -# http://www.isc.org/isc-license-1.0.html. +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. # -# 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. +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -# Support and other services are available for ISC products - see -# http://www.isc.org for more information. -# +# Internet Systems Consortium, Inc. +# 950 Charter Street +# Redwood City, CA 94063 +# +# http://www.isc.org/ CATMANPAGES = dhclient.cat8 dhclient.conf.cat5 dhclient-script.cat8 \ dhclient.leases.cat5 SEDMANPAGES = dhclient.man8 dhclient.conf.man5 dhclient-script.man8 \ dhclient.leases.man5 SRCS = dhclient.c clparse.c OBJS = dhclient.o clparse.o PROG = dhclient MAN = dhclient.8 dhclient.conf.5 dhclient-script.8 dhclient.leases.5 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} all: $(PROG) $(CATMANPAGES) install: all for dir in $(CLIENTBINDIR) $(ETC) $(FFMANDIR) $(ADMMANDIR) $(VARDB); \ do \ foo=""; \ for bar in `echo $(DESTDIR)$${dir} |tr / ' '`; do \ foo=$${foo}/$$bar; \ if [ ! -d $$foo ]; then \ mkdir $$foo; \ chmod 755 $$foo; \ fi; \ done; \ done $(INSTALL) dhclient $(DESTDIR)$(CLIENTBINDIR) $(CHMOD) 755 $(DESTDIR)$(CLIENTBINDIR)/dhclient if [ x$(SCRIPT) = xnone ]; then \ echo "No client script available."; \ else \ $(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) $(MANINSTALL) $(MANFROM) dhclient-script.$(MANCAT)8 $(MANTO) \ $(DESTDIR)$(ADMMANDIR)/dhclient-script$(ADMMANEXT) $(MANINSTALL) $(MANFROM) dhclient.conf.$(MANCAT)5 $(MANTO) \ $(DESTDIR)$(FFMANDIR)/dhclient.conf$(FFMANEXT) $(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. dhclient.cat8: dhclient.man8 nroff -man dhclient.man8 >dhclient.cat8 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 nroff -man dhclient-script.man8 >dhclient-script.cat8 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 dhclient.conf.cat5: dhclient.conf.man5 nroff -man dhclient.conf.man5 >dhclient.conf.cat5 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) Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/client/clparse.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/client/clparse.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/client/clparse.c (revision 131136) @@ -1,1177 +1,1170 @@ /* clparse.c Parser for dhclient config and lease files... */ /* - * Copyright (c) 1996-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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.62.2.4 2003/02/10 00:39:57 dhankins Exp $ Copyright (c) 1996-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: clparse.c,v 1.62.2.6 2004/06/10 17:59:11 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" static TIME parsed_time; struct client_config top_level_config; 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 :== | client-declaration | client-declarations client-declaration */ isc_result_t read_client_conf () { struct client_config *config; struct client_state *state; struct interface_info *ip; isc_result_t status; /* Set up the initial dhcp option universe. */ initialize_common_option_spaces (); /* Initialize the top level client configuration. */ memset (&top_level_config, 0, sizeof top_level_config); /* Set some defaults... */ top_level_config.timeout = 60; top_level_config.select_interval = 0; top_level_config.reboot_timeout = 10; top_level_config.retry_interval = 300; top_level_config.backoff_cutoff = 15; top_level_config.initial_interval = 3; 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; top_level_config.do_forward_update = 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, (unsigned *)0, cfile); if (token == END_OF_FILE) break; parse_client_statement (cfile, (struct interface_info *)0, &top_level_config); } while (1); end_parse (&parse); #endif } /* Set up state and config structures for clients that don't 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 *) dmalloc (sizeof (struct client_state), MDL); if (!ip -> client) 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 *) dmalloc (sizeof (struct client_config), MDL); if (!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); 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 END_OF_FILE client-lease-statements :== | client-lease-statements LEASE client-lease-statement */ void read_client_leases () { int file; struct parse *cfile; const char *val; int token; /* Open the lease file. If we can't open it, just return - we can safely trust the server to remember our state. */ 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, (unsigned *)0, cfile); if (token == END_OF_FILE) break; if (token != LEASE) { 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 :== SEND option-decl | DEFAULT option-decl | SUPERSEDE option-decl | PREPEND option-decl | APPEND option-decl | hardware-declaration | REQUEST option-list | REQUIRE option-list | TIMEOUT number | RETRY number | REBOOT number | SELECT_TIMEOUT number | SCRIPT string | VENDOR_SPACE string | interface-declaration | LEASE client-lease-statement | ALIAS client-lease-statement | KEY key-definition */ void parse_client_statement (cfile, ip, config) struct parse *cfile; struct interface_info *ip; struct client_config *config; { int token; const char *val; struct option *option; 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 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; /* 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 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; 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 (cfile, "hardware address parameter %s", "not allowed here."); skip_to_semi (cfile); } return; case REQUEST: 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 DO_FORWARD_UPDATE: token = next_token (&val, (unsigned *)0, cfile); token = next_token (&val, (unsigned *)0, cfile); if (!strcasecmp (val, "on") || !strcasecmp (val, "true")) config -> do_forward_update = 1; else if (!strcasecmp (val, "off") || !strcasecmp (val, "false")) config -> do_forward_update = 0; else { parse_warn (cfile, "expecting boolean value."); skip_to_semi (cfile); return; } 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: 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 (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: 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); } } 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); } return; } break; } parse_semi (cfile); } /* option-list :== option_name | option_list COMMA option_name */ void parse_option_list (cfile, list) struct parse *cfile; u_int32_t **list; { int ix; int token; const char *val; pair p = (pair)0, q, r; struct option *option; ix = 0; do { token = peek_token (&val, (unsigned *)0, cfile); if (token == SEMI) { token = next_token (&val, (unsigned *)0, cfile); break; } if (!is_identifier (token)) { parse_warn (cfile, "%s: expected option name.", val); token = next_token (&val, (unsigned *)0, cfile); skip_to_semi (cfile); return; } option = parse_option_name (cfile, 0, NULL); if (!option) { parse_warn (cfile, "%s: expected option name.", val); return; } if (option -> universe != &dhcp_universe) { parse_warn (cfile, "%s.%s: Only global options allowed.", option -> universe -> name, option->name ); skip_to_semi (cfile); return; } r = new_pair (MDL); if (!r) log_fatal ("can't allocate pair for option code."); r -> car = (caddr_t)(long)option -> code; 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 (cfile, "expecting semicolon."); skip_to_semi (cfile); 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; } } } /* interface-declaration :== INTERFACE string LBRACE client-declarations RBRACE */ void parse_interface_declaration (cfile, outer_config, name) struct parse *cfile; struct client_config *outer_config; char *name; { int token; const char *val; struct client_state *client, **cp; struct interface_info *ip = (struct interface_info *)0; token = next_token (&val, (unsigned *)0, cfile); if (token != STRING) { parse_warn (cfile, "expecting interface name (in quotes)."); skip_to_semi (cfile); return; } if (!interface_or_dummy (&ip, val)) log_fatal ("Can't allocate interface %s.", val); /* 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 (!client -> config) make_client_config (client, outer_config); ip -> flags &= ~INTERFACE_AUTOMATIC; interfaces_requested = 1; token = next_token (&val, (unsigned *)0, cfile); if (token != LBRACE) { parse_warn (cfile, "expecting left brace."); skip_to_semi (cfile); return; } do { 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, client -> config); } while (1); token = next_token (&val, (unsigned *)0, cfile); } int interface_or_dummy (struct interface_info **pi, const char *name) { 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 (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)) { interface_reference (&ip, i, MDL); break; } } } /* If we didn't find an interface, make a dummy interface as a placeholder. */ if (!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); if (dummy_interfaces) { interface_reference (&ip -> next, dummy_interfaces, MDL); interface_dereference (&dummy_interfaces, MDL); } interface_reference (&dummy_interfaces, ip, MDL); } 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 (state) struct client_state **state; { *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 (client, config) struct client_state *client; struct client_config *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 :== RBRACE client-lease-declarations LBRACE client-lease-declarations :== | client-lease-declaration | client-lease-declarations client-lease-declaration */ void parse_client_lease_statement (cfile, is_static) struct parse *cfile; int is_static; { - struct client_lease *lease, *lp, *pl; + struct client_lease *lease, *lp, *pl, *next; struct interface_info *ip = (struct interface_info *)0; int token; const char *val; struct client_state *client = (struct client_state *)0; token = next_token (&val, (unsigned *)0, cfile); if (token != LBRACE) { parse_warn (cfile, "expecting left brace."); skip_to_semi (cfile); return; } lease = ((struct client_lease *) dmalloc (sizeof (struct client_lease), MDL)); if (!lease) log_fatal ("no memory for lease.\n"); memset (lease, 0, sizeof *lease); lease -> is_static = is_static; if (!option_state_allocate (&lease -> options, MDL)) log_fatal ("no memory for lease options.\n"); do { 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, &client); } while (1); 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) { destroy_client_lease (lease); return; } /* Make sure there's a client state structure... */ 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) { ip -> client -> alias = lease; return; } /* The new lease may supersede a lease that's not the active lease but is still on the lease list, so scan the lease list looking for a lease with the same address, and if we find it, toss it. */ pl = (struct client_lease *)0; - for (lp = client -> leases; lp; lp = lp -> next) { + for (lp = client -> leases; lp; lp = next) { + next = 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; + pl -> next = next; else - client -> leases = lp -> next; + client -> leases = next; destroy_client_lease (lp); break; - } + } else + pl = lp; } /* 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 = client -> leases; client -> leases = lease; return; } /* The last lease in the lease file on a particular interface is the active lease for that interface. Of course, we don't know what the last lease in the file is until we've parsed the whole file, so at this point, we assume that the lease we just parsed is the active lease for its interface. If there's already an active lease for the interface, and this lease is for the same ip address, then we just toss the old active lease and replace it with this one. If this lease is for a different address, 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 (client -> active) { if (client -> active -> expiry < cur_time) destroy_client_lease (client -> active); else if (client -> active -> address.len == lease -> address.len && !memcmp (client -> active -> address.iabuf, lease -> address.iabuf, lease -> address.len)) destroy_client_lease (client -> active); else { client -> active -> next = client -> leases; client -> leases = client -> active; } } client -> active = lease; /* phew. */ } /* client-lease-declaration :== BOOTP | INTERFACE string | FIXED_ADDR ip_address | FILENAME string | SERVER_NAME string | OPTION option-decl | RENEW time-decl | REBIND time-decl | EXPIRE time-decl | KEY id */ 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; const char *val; char *t, *n; struct interface_info *ip; 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, (unsigned *)0, cfile); if (token != STRING) { parse_warn (cfile, "expecting interface name (in quotes)."); skip_to_semi (cfile); break; } 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: if (!parse_ip_addr (cfile, &lease -> address)) return; break; case MEDIUM: parse_string_list (cfile, &lease -> medium, 0); return; case FILENAME: parse_string (cfile, &lease -> filename, (unsigned *)0); return; case SERVER_NAME: parse_string (cfile, &lease -> server_name, (unsigned *)0); return; case RENEW: lease -> renewal = parse_date (cfile); return; case REBIND: lease -> rebind = parse_date (cfile); return; case EXPIRE: lease -> expiry = parse_date (cfile); return; case OPTION: 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 (cfile, "expecting lease declaration."); skip_to_semi (cfile); break; } token = next_token (&val, (unsigned *)0, cfile); if (token != SEMI) { parse_warn (cfile, "expecting semicolon."); skip_to_semi (cfile); } } void parse_string_list (cfile, lp, multiple) struct parse *cfile; struct string_list **lp; int multiple; { int token; const char *val; struct string_list *cur, *tmp; /* Find the last medium in the media list. */ if (*lp) { for (cur = *lp; cur -> next; cur = cur -> next) ; } else { cur = (struct string_list *)0; } do { token = next_token (&val, (unsigned *)0, cfile); if (token != STRING) { parse_warn (cfile, "Expecting media options."); skip_to_semi (cfile); return; } tmp = ((struct string_list *) dmalloc (strlen (val) + sizeof (struct string_list), MDL)); if (!tmp) log_fatal ("no memory for string list entry."); strcpy (tmp -> string, val); tmp -> next = (struct string_list *)0; /* Store this medium at the end of the media list. */ if (cur) cur -> next = tmp; else *lp = tmp; cur = tmp; token = next_token (&val, (unsigned *)0, cfile); } while (multiple && token == COMMA); if (token != SEMI) { parse_warn (cfile, "expecting semicolon."); skip_to_semi (cfile); } } void parse_reject_statement (cfile, config) struct parse *cfile; struct client_config *config; { int token; const char *val; struct iaddr addr; struct iaddrlist *list; do { if (!parse_ip_addr (cfile, &addr)) { parse_warn (cfile, "expecting IP address."); skip_to_semi (cfile); return; } list = (struct iaddrlist *)dmalloc (sizeof (struct iaddrlist), MDL); if (!list) log_fatal ("no memory for reject list!"); list -> addr = addr; list -> next = config -> reject_list; config -> reject_list = list; token = next_token (&val, (unsigned *)0, cfile); } while (token == COMMA); if (token != SEMI) { 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; } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/client/dhclient-script.8 =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/client/dhclient-script.8 (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/client/dhclient-script.8 (revision 131136) @@ -1,228 +1,221 @@ .\" dhclient-script.8 .\" -.\" Copyright (c) 1996-2002 Internet Software Consortium. -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: +.\" Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (c) 1996-2003 by Internet Software Consortium .\" -.\" 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. +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. .\" -.\" 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. +.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +.\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.\" This software has been written for the Internet Software Consortium +.\" Internet Systems Consortium, Inc. +.\" 950 Charter Street +.\" Redwood City, CA 94063 +.\" +.\" http://www.isc.org/ +.\" +.\" This software has been written for Internet Systems Consortium .\" by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. -.\" To learn more about the Internet Software Consortium, see +.\" To learn more about Internet Systems 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''. .\" -.\" $Id: dhclient-script.8,v 1.8.2.4 2002/11/17 02:25:43 dhankins Exp $ +.\" $Id: dhclient-script.8,v 1.8.2.5 2004/06/10 17:59:12 dhankins Exp $ .\" .TH dhclient-script 8 .SH NAME dhclient-script - DHCP client network configuration script .SH DESCRIPTION The DHCP client network configuration script is invoked from time to time by \fBdhclient(8)\fR. This script is used by the dhcp client to set each interface's initial configuration prior to requesting an address, to test the address once it has been offered, and to set the 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. .PP This script is not meant to be customized by the end user. If local customizations are needed, they should be possible using the enter and exit hooks provided (see HOOKS for details). These hooks will allow the user to override the default behaviour of the client in creating a .B /etc/resolv.conf file. .PP No standard client script exists for some operating systems, even though the actual client may work, so a pioneering user may well need to create a new script or modify an existing one. In general, customizations specific 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 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, .B make_resolv_conf , which is later used to create the .B /etc/resolv.conf file. To override the default behaviour, redefine this function in the enter hook script. .PP On after defining the make_resolv_conf function, the client script checks for the presence of an executable .B ETCDIR/dhclient-enter-hooks script, and if present, it invokes the script inline, using the Bourne shell '.' command. The entire environment documented under OPERATION 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 CLIENTBINDIR/dhclient-script will exit with that error code immediately after the client script exits. .PP After all processing has completed, .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 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 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, BOUND, RENEW, REBIND, REBOOT, EXPIRE, FAIL and TIMEOUT. .PP .SH MEDIUM The DHCP client is requesting that an interface's media type be set. The interface name is passed in $interface, and the media type is passed in $medium. .SH PREINIT The DHCP client is requesting that an interface be configured as required in order to send packets prior to receiving an actual address. For clients which use the BSD socket library, this means configuring the interface with an IP address of 0.0.0.0 and a broadcast address of 255.255.255.255. For other clients, it may be possible to simply configure the interface up without actually giving it an IP address at all. The interface name is passed in $interface, and the media type in $medium. .PP 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 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 passed in $interface. The media type is passed in $medium. Any options acquired from the server are passed using the option name described in \fBdhcp-options\fR, except that dashes ('-') are replaced 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 $new_domain_name_servers (which may list more than one server, separated by spaces). A default route should be set using $new_routers, and static routes may need to be set up using $new_static_routes. .PP If an IP alias has been declared, it must be set up here. The alias IP address will be written as $alias_ip_address, and other DHCP options that are set for the alias (e.g., subnet mask) will be passed in variables named as described previously except starting with $alias_ instead of $new_. Care should be taken that the alias IP address not be used if it is identical to the bound IP address ($new_ip_address), since the other alias parameters may be incorrect in this case. .SH RENEW When a binding has been renewed, the script is called as in BOUND, except that in addition to all the variables starting with $new_, there is another set of variables starting with $old_. Persistent settings that may have changed need to be deleted - for example, if a local route to the bound address is being configured, the old local route should be deleted. If the default route has changed, the old default route should be deleted. If the static routes have changed, the old ones should be deleted. Otherwise, processing can be done as with BOUND. .SH REBIND The DHCP client has rebound to a new DHCP server. This can be handled as with RENEW, except that if the IP address has changed, the ARP table should be cleared. .SH REBOOT The DHCP client has successfully reacquired its old address after a reboot. This can be processed as with BOUND. .SH EXPIRE The DHCP client has failed to renew its lease or acquire a new one, and the lease has expired. The IP address must be relinquished, and all related parameters should be deleted, as in RENEW and REBIND. .SH FAIL The DHCP client has been unable to contact any DHCP servers, and any leases that have been tested have not proved to be valid. The parameters from the last lease tested should be deconfigured. This can be handled in the same way as EXPIRE. .SH TIMEOUT The DHCP client has been unable to contact any DHCP servers. However, an old lease has been identified, and its parameters have been passed in as with BOUND. The client configuration script should test these parameters and, if it has reason to believe they are valid, should exit with a value of zero. If not, it should exit with a nonzero value. .PP The usual way to test a lease is to set up the network as with REBIND (since this may be called to test more than one lease) and then ping the first router defined in $routers. If a response is received, the lease must be valid for the network to which the interface is currently connected. It would be more complete to try to ping all of the routers listed in $new_routers, as well as those listed in $new_static_routes, but current scripts do not do this. .SH FILES Each operating system should generally have its own script file, although the script files for similar operating systems may be similar -or even identical. The script files included in the Internet -Software Consortium DHCP distribution appear in the distribution tree +or even identical. The script files included in Internet +Systems Consortium DHCP distribution appear in the distribution tree under client/scripts, and bear the names of the operating systems on which they are intended to work. .SH BUGS If more than one interface is being used, there's no obvious way to avoid clashes between server-supplied configuration parameters - for example, the stock dhclient-script rewrites /etc/resolv.conf. If more than one interface is being configured, /etc/resolv.conf will be repeatedly initialized to the values provided by one server, and then the other. Assuming the information provided by both servers is valid, this shouldn't cause any real problems, but it could be confusing. .SH SEE ALSO dhclient(8), dhcpd(8), dhcrelay(8), dhclient.conf(5) and dhclient.leases(5). .SH AUTHOR .B dhclient-script(8) -has been written for the Internet Software Consortium +has been written for Internet Systems Consortium by Ted Lemon in cooperation with Vixie -Enterprises. To learn more about the Internet Software Consortium, +Enterprises. To learn more about Internet Systems Consortium, see .B http://www.isc.org. To learn more about Vixie Enterprises, see .B http://www.vix.com. Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/client/dhclient.8 =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/client/dhclient.8 (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/client/dhclient.8 (revision 131136) @@ -1,314 +1,319 @@ .\" dhclient.8 .\" -.\" Copyright (c) 1996-2002 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: +.\" Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (c) 1996-2003 by Internet Software Consortium .\" -.\" http://www.isc.org/isc-license-1.0.html. +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. .\" -.\" 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. +.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +.\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.\" Support and other services are available for ISC products - see -.\" http://www.isc.org for more information. +.\" Internet Systems Consortium, Inc. +.\" 950 Charter Street +.\" Redwood City, CA 94063 +.\" +.\" http://www.isc.org/ .\" -.\" $Id: dhclient.8,v 1.12.2.7 2002/11/17 02:25:43 dhankins Exp $ +.\" $Id: dhclient.8,v 1.12.2.8 2004/06/10 17:59:12 dhankins Exp $ .\" .TH dhclient 8 .SH NAME dhclient - Dynamic Host Configuration Protocol Client .SH SYNOPSIS .B dhclient [ .B -p .I port ] [ .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 ] ] .SH DESCRIPTION -The Internet Software Consortium DHCP Client, dhclient, provides a +The Internet Systems Consortium DHCP Client, dhclient, provides a means for configuring one or more network interfaces using the Dynamic Host Configuration Protocol, BOOTP protocol, or if these protocols fail, by statically assigning an address. .SH OPERATION .PP The DHCP protocol allows a host to contact a central server which maintains a list of IP addresses which may be assigned on one or more subnets. A DHCP client may request an address from this pool, and then use it on a temporary basis for communication on network. The DHCP protocol also provides a mechanism whereby a client can learn important details about the network to which it is attached, such as the location of a default router, the location of a name server, and so on. .PP On startup, dhclient reads the .IR dhclient.conf for configuration instructions. It then gets a list of all the network interfaces that are configured in the current system. For each interface, it attempts to configure the interface using the DHCP protocol. .PP In order to keep track of leases across system reboots and server restarts, dhclient keeps a list of leases it has been assigned in the dhclient.leases(5) file. On startup, after reading the dhclient.conf file, dhclient reads the dhclient.leases file to refresh its memory about what leases it has been assigned. .PP When a new lease is acquired, it is appended to the end of the 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 dhclient.leases~ until the next time dhclient rewrites the database. .PP Old leases are kept around in case the DHCP server is unavailable when dhclient is first invoked (generally during the initial system boot process). In that event, old leases from the dhclient.leases file which have not yet expired are tested, and if they are determined to be valid, they are used until either they expire or the DHCP server becomes available. .PP A mobile host which may sometimes need to access a network on which no DHCP server exists may be preloaded with a lease for a fixed address on that network. When all attempts to contact a DHCP server have failed, dhclient will try to validate the static lease, and if it succeeds, will use that lease until it is restarted. .PP A mobile host may also travel to some networks on which DHCP is not available but BOOTP is. In that case, it may be advantageous to arrange with the network administrator for an entry on the BOOTP database, so that the host can boot quickly on that network rather than cycling through the list of old leases. .SH COMMAND LINE .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 normally identify all network interfaces, eliminating non-broadcast interfaces if possible, and attempt to configure each interface. .PP 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 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 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 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(5) file is discussed separately. .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-script (8), dhclient.conf(5), dhclient.leases(5). .SH AUTHOR .B dhclient(8) -has been written for the Internet Software Consortium +has been written for Internet Systems Consortium by Ted Lemon in cooperation with Vixie -Enterprises. To learn more about the Internet Software Consortium, +Enterprises. To learn more about Internet Systems Consortium, see .B http://www.isc.org To learn more about Vixie Enterprises, see .B http://www.vix.com. .PP This client was substantially modified and enhanced by Elliot Poger for use on Linux while he was working on the MosquitoNet project at Stanford. .PP 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 +so as to use the same networking framework that the Internet Systems 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. .PP Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/client/dhclient.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/client/dhclient.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/client/dhclient.c (revision 131136) @@ -1,3149 +1,3155 @@ /* dhclient.c DHCP Client. */ /* - * Copyright (c) 1995-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * * 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.129.2.16 2003/04/26 21:51:39 dhankins Exp $ Copyright (c) 1995-2002 Internet Software Consortium. All rights reserved.\n"; +"$Id: dhclient.c,v 1.129.2.18 2004/06/10 17:59:12 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #include "version.h" TIME cur_time; TIME default_lease_time = 43200; /* 12 hours... */ TIME max_lease_time = 86400; /* 24 hours... */ 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 dhcp_max_agent_option_packet_length = 0; 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-2002 Internet Software Consortium."; +static char copyright[] = "Copyright 2004 Internet Systems Consortium."; static char arr [] = "All rights reserved."; -static char message [] = "Internet Software Consortium DHCP Client"; +static char message [] = "Internet Systems Consortium DHCP Client"; static char url [] = "For info, please visit http://www.isc.org/products/DHCP"; u_int16_t local_port=0; u_int16_t remote_port=0; int no_daemon=0; struct string_list *client_env=NULL; int client_env_count=0; int onetry=0; int quiet=0; int nowait=0; static void usage PROTO ((void)); void do_release(struct client_state *); int main (argc, argv, envp) int argc; char **argv, **envp; { int i; struct servent *ent; struct interface_info *ip; 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; /* 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); #ifdef SYSLOG_4_2 openlog ("dhclient", LOG_NDELAY); log_priority = LOG_DAEMON; #else 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], "-r")) { release_mode = 1; no_daemon = 1; } else if (!strcmp (argv [i], "-p")) { if (++i == argc) usage (); local_port = htons (atoi (argv [i])); 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], "-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 (); 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], "-nw")) { nowait = 1; } 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 (!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 (argv [i][0] == '-') { usage (); } else { 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]); if (interfaces) { interface_reference (&tmp -> next, interfaces, MDL); interface_dereference (&interfaces, MDL); } interface_reference (&interfaces, tmp, MDL); tmp -> flags = INTERFACE_REQUESTED; interfaces_requested = 1; } } 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) { FILE *pidfd; pid_t oldpid; long temp; int e; oldpid = 0; if ((pidfd = fopen(path_dhclient_pid, "r")) != NULL) { e = fscanf(pidfd, "%ld\n", &temp); oldpid = (pid_t)temp; if (e != 0 && e != EOF) { if (oldpid) { if (kill(oldpid, SIGTERM) == 0) unlink(path_dhclient_pid); } } fclose(pidfd); } } if (!quiet) { 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) { /* 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(67); } else { ent = getservbyname ("dhcpc", "udp"); if (!ent) local_port = htons (68); else local_port = ent -> s_port; #ifndef __CYGWIN32__ endservent (); #endif } } /* If we're faking a relay agent, and we're not using loopback, we're using the server port, not the client port. */ if (relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) { 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; 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. */ discover_interfaces (DISCOVER_UNCONFIGURED); /* Parse the dhclient.conf file. */ read_client_conf (); /* Parse the lease database. */ read_client_leases (); /* 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) { /* 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 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 interfaces that weren't specified! */ if (interfaces_requested && ((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); } } /* At this point, all the interfaces that the script thinks are relevant should be running, so now we once again call discover_interfaces(), and this time ask it to actually set up the interfaces. */ discover_interfaces (interfaces_requested ? DISCOVER_REQUESTED : DISCOVER_RUNNING); /* Make up a seed for the random number generator from current time plus the sum of the last four bytes of each 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; for (ip = interfaces; ip; ip = ip -> next) { int junk; memcpy (&junk, &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 -> 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 (); /*NOTREACHED*/ return 0; } 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 ] %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) { return 0; } 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: * * Each routine is called from the dhclient_state_machine() in one of * these conditions: * -> entering INIT state * -> recvpacket_flag == 0: timeout in this state * -> otherwise: received a packet in this state * * Return conditions as handled by dhclient_state_machine(): * Returns 1, sendpacket_flag = 1: send packet, reset timer. * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone). * Returns 0: finish the nap which was interrupted for no good reason. * * Several per-interface variables are used to keep track of the process: * active_lease: the lease that is being used on the interface * (null pointer if not configured yet). * offered_leases: leases corresponding to DHCPOFFER messages that have * been sent to us by DHCP servers. * acked_leases: leases corresponding to DHCPACK messages that have been * sent to us by DHCP servers. * sendpacket: DHCP packet we're trying to send. * destination: IP address to send sendpacket to * In addition, there are several relevant per-lease variables. * T1_expiry, T2_expiry, lease_expiry: lease milestones * In the active lease, these control the process of renewing the lease; * In leases on the acked_leases list, this simply determines when we * can no longer legitimately use the lease. */ void state_reboot (cpp) void *cpp; { struct client_state *client = cpp; /* If we don't remember an active lease, go straight to INIT. */ if (!client -> active || client -> active -> is_bootp || client -> active -> expiry <= cur_time) { state_init (client); return; } /* We are in the rebooting state. */ 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. */ client -> xid = random (); /* Make a DHCPREQUEST packet, and set appropriate per-interface flags. */ make_request (client, client -> active); 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 DHCPREQUEST packet. */ send_request (client); } /* Called when a lease has completely expired and we've been unable to renew it. */ void state_init (cpp) void *cpp; { struct client_state *client = cpp; ASSERT_STATE(state, S_INIT); /* Make a DHCPDISCOVER packet, and set appropriate per-interface flags. */ 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 (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 (cpp) void *cpp; { 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, 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 = 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) { picked = lp; picked -> next = (struct client_lease *)0; } else { freeit: destroy_client_lease (lp); } } client -> offered_leases = (struct client_lease *)0; /* If we just tossed all the leases we were offered, go back to square one. */ if (!picked) { client -> state = S_INIT; state_init (client); return; } /* If it was a BOOTREPLY, we can just take the address right now. */ if (picked -> is_bootp) { client -> new = picked; /* Make up some lease expiry times XXX these should be configurable. */ client -> new -> expiry = cur_time + 12000; client -> new -> renewal += cur_time + 8000; client -> new -> rebind += cur_time + 10000; client -> state = S_REQUESTING; /* Bind to the address we received. */ bind_lease (client); return; } /* Go to the REQUESTING state. */ 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 (client, picked); client -> xid = client -> packet.xid; /* Toss the lease we picked - we'll get it back in a DHCPACK. */ destroy_client_lease (picked); /* Add an immediate timeout to send the first DHCPREQUEST packet. */ send_request (client); } /* state_requesting is called when we receive a DHCPACK message after having sent out one or more DHCPREQUEST packets. */ 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. */ 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.hbuf [1], packet -> raw -> chaddr, packet -> raw -> hlen))) { #if defined (DEBUG) log_debug ("DHCPACK in wrong transaction."); #endif return; } if (client -> state != S_REBOOTING && client -> state != S_REQUESTING && client -> state != S_RENEWING && client -> state != S_REBINDING) { #if defined (DEBUG) log_debug ("DHCPACK in wrong state."); #endif return; } log_info ("DHCPACK from %s", piaddr (packet -> client_addr)); lease = packet_to_lease (packet, client); if (!lease) { log_info ("packet_to_lease failed."); return; } client -> new = lease; /* Stop resending DHCPREQUEST. */ cancel_timeout (send_request, client); /* Figure out the lease time. */ 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 (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; + client -> new -> renewal = client -> new -> expiry / 2 + 1; + if (client -> new -> renewal <= 0) + client -> new -> renewal = TIME_MAX; + /* Now introduce some randomness to the renewal time: */ - client -> new -> renewal = (((client -> new -> renewal + 3) * 3 / 4) + + if (client -> new -> renewal <= TIME_MAX / 3 - 3) + client -> new -> renewal = + (((client -> new -> renewal + 3) * 3 / 4) + (random () % /* XXX NUMS */ ((client -> new -> renewal + 3) / 4))); /* Same deal with the rebind time. */ 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 */ + if (client -> new -> rebind <= 0) { + if (client -> new -> expiry <= TIME_MAX / 7) + client -> new -> rebind = + client -> new -> expiry * 7 / 8; + else + client -> new -> rebind = + client -> new -> expiry / 8 * 7; + } /* 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; + if (client -> new -> renewal > client -> new -> rebind) { + if (client -> new -> rebind <= TIME_MAX / 3) + client -> new -> renewal = + client -> new -> rebind * 3 / 4; + else + client -> new -> renewal = + client -> new -> rebind / 4 * 3; + } client -> new -> expiry += cur_time; /* Lease lengths can never be negative. */ 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 (client) struct client_state *client; { struct interface_info *ip = client -> interface; /* Remember the medium. */ client -> new -> medium = client -> medium; /* Run the client script with the new parameters. */ script_init (client, (client -> state == S_REQUESTING ? "BOUND" : (client -> state == S_RENEWING ? "RENEW" : (client -> state == S_REBOOTING ? "REBOOT" : "REBIND"))), 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 (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 (client -> active -> renewal, state_bound, client, 0, 0); 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 (); if (client -> config -> do_forward_update) { client -> dns_update_timeout = 1; add_timeout (cur_time + 1, client_dns_update_timeout, client, 0, 0); } } /* state_bound is called when we've successfully bound to a particular lease, but the renewal time on that lease has expired. We are expected to unicast a DHCPREQUEST to the server that gave us our original lease. */ void state_bound (cpp) void *cpp; { 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 (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 client -> destination = iaddr_broadcast; client -> first_sending = cur_time; client -> interval = client -> config -> initial_interval; client -> state = S_RENEWING; /* Send the first packet immediately. */ 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 () { return 0; } int write_lease (lease) struct lease *lease; { return 0; } int write_host (host) struct host_decl *host; { return 0; } void db_startup (testp) int testp; { } void bootp (packet) struct packet *packet; { struct iaddrlist *ap; if (packet -> raw -> op != BOOTREPLY) return; /* If there's a reject list, make sure this packet's sender isn't on it. */ for (ap = packet -> interface -> client -> config -> reject_list; ap; ap = ap -> next) { if (addr_eq (packet -> client_addr, ap -> addr)) { log_info ("BOOTREPLY from %s rejected.", piaddr (ap -> addr)); return; } } dhcpoffer (packet); } void dhcp (packet) struct packet *packet; { struct iaddrlist *ap; void (*handler) PROTO ((struct packet *)); const char *type; switch (packet -> packet_type) { case DHCPOFFER: handler = dhcpoffer; type = "DHCPOFFER"; break; case DHCPNAK: handler = dhcpnak; type = "DHCPNACK"; break; case DHCPACK: handler = dhcpack; type = "DHCPACK"; break; default: return; } /* If there's a reject list, make sure this packet's sender isn't on it. */ for (ap = packet -> interface -> client -> config -> reject_list; ap; ap = ap -> next) { if (addr_eq (packet -> client_addr, ap -> addr)) { log_info ("%s from %s rejected.", type, piaddr (ap -> addr)); return; } } (*handler) (packet); } void dhcpoffer (packet) struct packet *packet; { struct interface_info *ip = packet -> interface; struct client_state *client; struct client_lease *lease, *lp; int i; 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 (!client || client -> state != S_SELECTING || (packet -> interface -> hw_address.hlen - 1 != packet -> raw -> hlen) || (memcmp (&packet -> interface -> hw_address.hbuf [1], packet -> raw -> chaddr, packet -> raw -> hlen))) { #if defined (DEBUG) log_debug ("%s in wrong transaction.", name); #endif return; } sprintf (obuf, "%s from %s", name, piaddr (packet -> client_addr)); /* If this lease doesn't supply the minimum required parameters, blow it off. */ 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 = 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)) { log_debug ("%s: already seen.", obuf); return; } } lease = packet_to_lease (packet, client); if (!lease) { log_info ("%s: packet_to_lease failed.", obuf); return; } /* If this lease was acquired through a BOOTREPLY, record that fact. */ if (!packet -> options_valid || !packet -> packet_type) lease -> is_bootp = 1; /* Record the medium under which this lease was offered. */ lease -> medium = client -> medium; /* Figure out when we're supposed to stop selecting. */ 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 == client -> requested_address.len && !memcmp (lease -> address.iabuf, client -> requested_address.iabuf, client -> requested_address.len)) { lease -> next = client -> offered_leases; client -> offered_leases = lease; } else { /* Put the lease at the end of the list. */ lease -> next = (struct client_lease *)0; if (!client -> offered_leases) client -> offered_leases = lease; else { for (lp = client -> offered_leases; lp -> next; lp = lp -> next) ; lp -> next = lease; } } /* 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 (client); else { 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, client) struct packet *packet; struct client_state *client; { struct client_lease *lease; unsigned i; struct option_cache *oc; struct data_string data; lease = (struct client_lease *)new_client_lease (MDL); if (!lease) { 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. */ 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); memset (&data, 0, sizeof data); 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); 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 (!(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 = dmalloc (len + 1, MDL); if (!lease -> server_name) { log_error ("dhcpoffer: no memory for filename.\n"); destroy_client_lease (lease); return (struct client_lease *)0; } else { memcpy (lease -> server_name, packet -> raw -> sname, len); lease -> server_name [len] = 0; } } /* Ditto for the filename. */ 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 = dmalloc (len + 1, MDL); if (!lease -> filename) { log_error ("dhcpoffer: no memory for filename.\n"); destroy_client_lease (lease); return (struct client_lease *)0; } else { memcpy (lease -> filename, packet -> raw -> file, len); 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; } 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 (!client || (packet -> interface -> hw_address.hlen - 1 != packet -> raw -> hlen) || (memcmp (&packet -> interface -> hw_address.hbuf [1], packet -> raw -> chaddr, packet -> raw -> hlen))) { #if defined (DEBUG) log_debug ("DHCPNAK in wrong transaction."); #endif return; } if (client -> state != S_REBOOTING && client -> state != S_REQUESTING && client -> state != S_RENEWING && client -> state != S_REBINDING) { #if defined (DEBUG) log_debug ("DHCPNAK in wrong state."); #endif return; } log_info ("DHCPNAK from %s", piaddr (packet -> client_addr)); if (!client -> active) { #if defined (DEBUG) log_info ("DHCPNAK with no active lease.\n"); #endif return; } destroy_client_lease (client -> active); client -> active = (struct client_lease *)0; /* Stop sending DHCPREQUEST packets... */ cancel_timeout (send_request, client); 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 (cpp) void *cpp; { 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 - 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 > 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 (!client -> offered_leases && client -> config -> media) { int fail = 0; again: if (client -> medium) { client -> medium = client -> medium -> next; increase = 0; } if (!client -> medium) { if (fail) log_fatal ("No valid media types for %s!", client -> interface -> name); client -> medium = client -> config -> media; increase = 1; } log_info ("Trying medium \"%s\" %d", client -> medium -> string, increase); script_init (client, "MEDIUM", client -> medium); if (script_go (client)) { fail = 1; goto again; } } /* If we're supposed to increase the interval, do so. If it's currently zero (i.e., we haven't sent any packets yet), set it to one; otherwise, add to it a random number between zero and two times itself. On average, this means that it will double with every transmission. */ if (increase) { if (!client -> interval) client -> interval = client -> config -> initial_interval; else client -> interval += ((random () >> 2) % (2 * client -> interval)); /* Don't backoff past cutoff. */ if (client -> interval > client -> config -> backoff_cutoff) client -> interval = ((client -> config -> backoff_cutoff / 2) + ((random () >> 2) % 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 + 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) client -> packet.secs = htons (interval); else client -> packet.secs = htons (65535); client -> secs = client -> packet.secs; 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), (long)(client -> interval)); /* Send out a packet. */ result = send_packet (client -> interface, (struct packet *)0, &client -> packet, client -> packet_length, inaddr_any, &sockaddr_broadcast, (struct hardware *)0); 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 amount of time. When this happens, we try to use existing leases that haven't yet expired, and failing that, we call the client script and hope it can do something. */ void state_panic (cpp) void *cpp; { struct client_state *client = cpp; struct client_lease *loop; struct client_lease *lp; 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 (!client -> active && client -> leases) goto activate_next; /* Run through the list of leases and see if one can be used. */ 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 (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 (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 (!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 = client -> leases; lp -> next; lp = lp -> next) ; lp -> next = client -> active; if (lp -> next) { lp -> next -> next = (struct client_lease *)0; } 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 (client -> active == loop) break; else if (!loop) 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. */ 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 (cpp) void *cpp; { struct client_state *client = cpp; int result; int interval; struct sockaddr_in destination; struct in_addr from; /* Figure out how long it's been since we started transmitting. */ 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 DISCOVER an address... */ /* XXX In the INIT-REBOOT state, if we don't get an ACK, it means either that we're on a network with no DHCP server, or that our server is down. In the latter case, assuming that there is a backup DHCP server, DHCPDISCOVER will get 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 ((client -> state == S_REBOOTING || client -> state == S_REQUESTING) && interval > client -> config -> reboot_timeout) { cancel: 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 (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 (client)) goto cancel; /* Record the medium. */ client -> medium = client -> active -> medium; } /* If the lease has expired, relinquish the address and go back to the INIT state. */ if (client -> state != S_REQUESTING && cur_time > client -> active -> expiry) { /* Run the client script with the new parameters. */ 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 (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 (!client -> interval) client -> interval = client -> config -> initial_interval; else { client -> interval += ((random () >> 2) % (2 * client -> interval)); } /* Don't backoff past cutoff. */ 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 (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 (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, 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 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 (client -> state == S_REQUESTING) client -> packet.secs = client -> secs; else { if (interval < 65536) client -> packet.secs = htons (interval); else client -> packet.secs = htons (65535); } 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)); if (destination.sin_addr.s_addr != INADDR_BROADCAST && 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); add_timeout (cur_time + client -> interval, send_request, client, 0, 0); } void send_decline (cpp) void *cpp; { struct client_state *client = cpp; int result; 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 (client -> interface, (struct packet *)0, &client -> packet, client -> packet_length, inaddr_any, &sockaddr_broadcast, (struct hardware *)0); } void send_release (cpp) void *cpp; { struct client_state *client = cpp; int result; struct sockaddr_in destination; struct in_addr from; 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 /* 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_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 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 { 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... */ client -> packet_length = cons_options ((struct packet *)0, &client -> packet, (struct lease *)0, client, /* maximum packet size */1500, (struct option_state *)0, options, /* scope */ &global_scope, /* overload */ 0, /* terminate */0, /* bootpp */0, (struct data_string *)0, client -> config -> vendor_space_name); option_state_dereference (&options, MDL); 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 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_raw ((unsigned char *)&client -> packet, client -> packet_length); #endif } void make_request (client, lease) struct client_state *client; struct client_lease *lease; { unsigned char request = DHCPREQUEST; int i, j; unsigned char *tmp, *digest; unsigned char *old_digest_loc; struct option_cache *oc; 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... */ client -> packet_length = cons_options ((struct packet *)0, &client -> packet, (struct lease *)0, client, /* maximum packet size */1500, (struct option_state *)0, client -> sent_options, /* scope */ &global_scope, /* overload */ 0, /* terminate */0, /* bootpp */0, (struct data_string *)0, client -> config -> vendor_space_name); option_state_dereference (&client -> sent_options, MDL); 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 (client -> state == S_BOUND || client -> state == S_RENEWING || client -> state == S_REBINDING) { memcpy (&client -> packet.ciaddr, lease -> address.iabuf, lease -> address.len); client -> packet.flags = 0; } else { memset (&client -> packet.ciaddr, 0, sizeof client -> packet.ciaddr); if (can_receive_unicast_unconfigured (client -> interface)) client -> packet.flags = 0; else client -> packet.flags = htons (BOOTP_BROADCAST); } 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_raw ((unsigned char *)&client -> packet, client -> packet_length); #endif } void make_decline (client, lease) struct client_state *client; struct client_lease *lease; { unsigned char decline = DHCPDECLINE; int i; struct option_cache *oc; 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... */ 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); option_state_dereference (&options, MDL); 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 (&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_raw ((unsigned char *)&client -> packet, client -> packet_length); #endif } 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; 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... */ client -> packet_length = cons_options ((struct packet *)0, &client -> packet, (struct lease *)0, client, /* maximum packet size */1500, (struct option_state *)0, options, /* scope */ &global_scope, /* overload */ 0, /* terminate */0, /* bootpp */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_raw ((unsigned char *)&client -> packet, client -> packet_length); #endif } void destroy_client_lease (lease) struct client_lease *lease; { int i; if (lease -> server_name) dfree (lease -> server_name, MDL); if (lease -> filename) dfree (lease -> filename, MDL); option_state_dereference (&lease -> options, MDL); free_client_lease (lease, MDL); } 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) { 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 (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); } } /* Write out any leases that are attached to interfaces that aren't currently configured. */ for (ip = dummy_interfaces; ip; ip = ip -> next) { 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); } } fflush (leaseFile); } 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) { rewrite_client_leases (); leases_written = 0; } } /* 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 1; if (!leaseFile) { /* XXX */ leaseFile = fopen (path_dhclient_db, "w"); if (!leaseFile) { log_error ("can't create %s: %m", path_dhclient_db); return 0; } } errno = 0; fprintf (leaseFile, "lease {\n"); if (lease -> is_bootp) { fprintf (leaseFile, " bootp;\n"); 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 (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 somebody invents a time machine, I think we can safely disregard it. */ t = gmtime (&lease -> renewal); fprintf (leaseFile, " renew %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 -> 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 script. Needless to say, this is not reentrant - only one script can be invoked at a time. */ char scriptName [256]; FILE *scriptFile; void script_init (client, reason, medium) struct client_state *client; const char *reason; struct string_list *medium; { struct string_list *sl, *next; if (client) { for (sl = client -> env; sl; sl = next) { next = sl -> next; dfree (sl, MDL); } client -> env = (struct string_list *)0; client -> envc = 0; 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 (client, "", "medium", "%s", medium -> string); client_envadd (client, "", "reason", "%s", reason); client_envadd (client, "", "pid", "%ld", (long int)getpid ()); } } 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; struct data_string data; struct option_cache *oc; pair *hash; char *s, *t; struct envadd_state es; 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 have similar needs), compute the network address based on the supplied ip address and netmask, if provided. Also compute the broadcast address (the host address all ones broadcast address, not the host address all zeroes broadcast address). */ 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 (client, prefix, "broadcast_address", "%s", piaddr (broadcast)); } } } } data_string_forget (&data, MDL); } if (lease -> filename) client_envadd (client, prefix, "filename", "%s", lease -> filename); if (lease -> server_name) client_envadd (client, prefix, "server_name", "%s", lease -> server_name); 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 (client, prefix, "expiry", "%d", (int)(lease -> expiry)); } int script_go (client) struct client_state *client; { int rval; char *scriptName; char *argv [2]; char **envp; char *epp [3]; char reason [] = "REASON=NBI"; static char client_path [] = CLIENT_PATH; int i; struct string_list *sp, *next; int pid, wpid, wstatus; 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; } } else { 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) { log_error ("fork: %m"); wstatus = 0; } else if (pid) { do { wpid = wait (&wstatus); } while (wpid != pid && wpid > 0); if (wpid < 0) { log_error ("wait: %m"); wstatus = 0; } } else { execve (scriptName, argv, envp); log_error ("execve (%s, ...): %m", scriptName); exit (0); } if (client) { for (sp = client -> env; sp; sp = next) { next = sp -> next; dfree (sp, MDL); } client -> env = (struct string_list *)0; client -> envc = 0; } dfree (envp, MDL); GET_TIME (&cur_time); return (WIFEXITED (wstatus) ? WEXITSTATUS (wstatus) : -WTERMSIG (wstatus)); } void client_envadd (struct client_state *client, const char *prefix, const char *name, const char *fmt, ...) { char spbuf [1024]; char *s; unsigned len, i; struct string_list *val; va_list list; va_start (list, fmt); len = vsnprintf (spbuf, sizeof spbuf, fmt, list); va_end (list); val = dmalloc (strlen (prefix) + strlen (name) + 1 /* = */ + len + sizeof *val, MDL); if (!val) return; s = val -> string; strcpy (s, prefix); strcat (s, name); s += strlen (s); *s++ = '='; if (len >= sizeof spbuf) { va_start (list, fmt); vsnprintf (s, len + 1, fmt, list); va_end (list); } else strcpy (s, spbuf); val -> next = client -> env; client -> env = val; client -> envc++; } int dhcp_option_ev_name (buf, buflen, option) char *buf; size_t buflen; struct option *option; { int i, j; const char *s; j = 0; if (option -> universe != &dhcp_universe) { s = option -> universe -> name; i = 0; } else { s = option -> name; i = 1; } 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) { write_client_pid_file (); return; } /* Only do it once. */ if (state) return; state = 1; /* Stop logging to stderr... */ log_perror = 0; /* Become a daemon... */ if ((pid = fork ()) < 0) log_fatal ("Can't fork daemon: %m"); else if (pid) exit (0); /* Become session leader and get pid... */ pid = setsid (); /* Close standard I/O descriptors. */ close(0); 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 (); } void write_client_pid_file () { FILE *pf; int pfdesc; pfdesc = open (path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY, 0644); if (pfdesc < 0) { log_error ("Can't create %s: %m", path_dhclient_pid); return; } pf = fdopen (pfdesc, "w"); if (!pf) 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) { if (client -> config -> do_forward_update) client_dns_update (client, 0, 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; } /* Called after a timeout if the DNS update failed on the previous try. Retries the update, and if it times out, schedules a retry after ten times as long of a wait. */ void client_dns_update_timeout (void *cp) { struct client_state *client = cp; isc_result_t status; if (client -> active) { status = client_dns_update (client, 1, (client -> active -> renewal - cur_time)); if (status == ISC_R_TIMEDOUT) { client -> dns_update_timeout *= 10; add_timeout (cur_time + client -> dns_update_timeout, client_dns_update_timeout, client, 0, 0); } } } /* See if we should do a DNS update, and if so, do it. */ isc_result_t client_dns_update (struct client_state *client, int addp, int ttl) { 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 ISC_R_SUCCESS; /* If we don't have a lease, we can't do an update. */ if (!client -> active) return ISC_R_SUCCESS; /* 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 ISC_R_SUCCESS; /* 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 ISC_R_SUCCESS; /* 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 ISC_R_SUCCESS; /* 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 ISC_R_SUCCESS; } /* 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, 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); return rcode; } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/client/dhclient.conf.5 =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/client/dhclient.conf.5 (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/client/dhclient.conf.5 (revision 131136) @@ -1,632 +1,622 @@ -.\" dhclient.conf.5 +.\" $Id: dhclient.conf.5,v 1.12.2.10 2004/06/10 17:59:13 dhankins Exp $ .\" -.\" Copyright (c) 1996-2002 Internet Software Consortium. -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: +.\" Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (c) 1996-2003 by Internet Software Consortium .\" -.\" 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. +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. .\" -.\" 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. +.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +.\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.\" This software has been written for the Internet Software Consortium +.\" Internet Systems Consortium, Inc. +.\" 950 Charter Street +.\" Redwood City, CA 94063 +.\" +.\" http://www.isc.org/ +.\" +.\" This software has been written for Internet Software Consortium .\" by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. -.\" To learn more about the Internet Software Consortium, see +.\" To learn more about 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''. -.\" -.\" $Id: dhclient.conf.5,v 1.12.2.9 2003/02/23 03:27:26 dhankins Exp $ -.\" .TH dhclient.conf 5 .SH NAME dhclient.conf - DHCP client configuration file .SH DESCRIPTION The dhclient.conf file contains configuration information for .IR dhclient, -the Internet Software Consortium DHCP Client. +the Internet Systems Consortium DHCP Client. .PP The dhclient.conf file is a free-form ASCII text file. It is parsed by the recursive-descent parser built into dhclient. The file may contain extra tabs and newlines for formatting purposes. Keywords in the file are case-insensitive. Comments may be placed anywhere within the file (except within quotes). Comments begin with the # character and end at the end of the line. .PP The dhclient.conf file can be used to configure the behaviour of the client in a wide variety of ways: protocol timing, information requested from the server, information required of the server, defaults to use if the server does not provide certain information, values with which to override information provided by the server, or values to prepend or append to information provided by the server. The configuration file can also be preinitialized with addresses to use on networks that don't have DHCP servers. .SH PROTOCOL TIMING The timing behaviour of the client need not be configured by the user. If no timing configuration is provided by the user, a fairly reasonable timing behaviour will be used by default - one which results in fairly timely updates without placing an inordinate load on the server. .PP The following statements can be used to adjust the timing behaviour of the DHCP client if required, however: .PP .I The .B timeout .I statement .PP .B timeout .I time .B ; .PP The .I timeout statement determines the amount of time that must pass between the time that the client begins to try to determine its address and the time that it decides that it's not going to be able to contact a server. By default, this timeout is sixty seconds. After the timeout has passed, if there are any static leases defined in the configuration file, or any leases remaining in the lease database that have not yet expired, the client will loop through these leases attempting to validate them, and if it finds one that appears to be valid, it will use that lease's address. If there are no valid static leases or unexpired leases in the lease database, the client will restart the protocol after the defined retry interval. .PP .I The .B retry .I statement .PP \fBretry \fItime\fR\fB;\fR .PP The .I retry statement determines the time that must pass after the client has determined that there is no DHCP server present before it tries again to contact a DHCP server. By default, this is five minutes. .PP .I The .B select-timeout .I statement .PP \fBselect-timeout \fItime\fR\fB;\fR .PP It is possible (some might say desirable) for there to be more than one DHCP server serving any given network. In this case, it is possible that a client may be sent more than one offer in response to its initial lease discovery message. It may be that one of these offers is preferable to the other (e.g., one offer may have the address the client previously used, and the other may not). .PP The .I select-timeout is the time after the client sends its first lease discovery request at which it stops waiting for offers from servers, assuming that it has received at least one such offer. If no offers have been received by the time the .I select-timeout has expired, the client will accept the first offer that arrives. .PP By default, the select-timeout is zero seconds - that is, the client will take the first offer it sees. .PP .I The .B reboot .I statement .PP \fBreboot \fItime\fR\fB;\fR .PP When the client is restarted, it first tries to reacquire the last address it had. This is called the INIT-REBOOT state. If it is still attached to the same network it was attached to when it last ran, this is the quickest way to get started. The .I reboot statement sets the time that must elapse after the client first tries to reacquire its old address before it gives up and tries to discover a new address. By default, the reboot timeout is ten seconds. .PP .I The .B backoff-cutoff .I statement .PP \fBbackoff-cutoff \fItime\fR\fB;\fR .PP The client uses an exponential backoff algorithm with some randomness, so that if many clients try to configure themselves at the same time, they will not make their requests in lockstep. The .I backoff-cutoff statement determines the maximum amount of time that the client is allowed to back off. It defaults to two minutes. .PP .I The .B initial-interval .I statement .PP \fBinitial-interval \fItime\fR\fB;\fR .PP The .I initial-interval statement sets the amount of time between the first attempt to reach a server and the second attempt to reach a server. Each time a message is sent, the interval between messages is incremented by twice the current interval multiplied by a random number between zero and one. If it is greater than the backoff-cutoff amount, it is set to that amount. It defaults to ten seconds. .SH LEASE REQUIREMENTS AND REQUESTS The DHCP protocol allows the client to request that the server send it specific information, and not send it other information that it is not prepared to accept. The protocol also allows the client to reject offers from servers if they don't contain information the client needs, or if the information provided is not satisfactory. .PP There is a variety of data contained in offers that DHCP servers send to DHCP clients. The data that can be specifically requested is what are called \fIDHCP Options\fR. DHCP Options are defined in \fBdhcp-options(5)\fR. .PP .I The .B request .I statement .PP \fBrequest [ \fIoption\fR ] [\fB,\fI ... \fIoption\fR ]\fB;\fR .PP 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. 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 .I statement .PP \fBrequire [ \fIoption\fR ] [\fB,\fI ... \fIoption ]\fB;\fR .PP The require statement lists options that must be sent in order for an offer to be accepted. Offers that do not contain all the listed options will be ignored. .PP .I The .B send .I statement .PP \fBsend { [ \fIoption declaration\fR ] [\fB,\fI ... \fIoption declaration\fR ]\fB}\fR .PP The send statement causes the client to send the specified options to the server with the specified values. These are full option declarations as described in \fBdhcp-options(5)\fR. Options that are always sent in the DHCP protocol should not be specified here, except that the client can specify a \fBrequested-lease-time\fR option other 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. .PP .I The .B do-forward-updates .I statement .PP \fBdo-forward-updates [ \fIflag\fR ] \fB;\fR .PP If you want to do DNS updates in the DHCP client script (see \fBdhclient-script(8)\fR) rather than having the DHCP client do the update directly (for example, if you want to use SIG(0) authentication, which is not supported directly by the DHCP client, you can instruct the client not to do the update using the \fBdo-forward-updates\fR statement. \fIFlag\fR should be \fBtrue\fR if you want the DHCP client to do the update, and \fBfalse\fR if you don't want the DHCP client to do the update. By default, the DHCP client will do the DNS update. .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 information that it needs, and for which a useful default value exists. It may also receive information which is useful, but which needs to be supplemented with local information. To handle these needs, several option modifiers are available. .PP .I The .B default .I statement .PP \fBdefault [ \fIoption declaration\fR ] \fB;\fR .PP 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 statement. .PP .I The .B supersede .I statement .PP \fBsupersede [ \fIoption declaration\fR ] \fB;\fR .PP 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 .I The .B prepend .I statement .PP \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 the server, if any, these values can be defined in the .B prepend 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 you ignore it, the behaviour will be unpredictable. .PP .I The .B append .I statement .PP \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 values can be defined in the .B append statement. The .B append statement can only be used for options which allow more than one value to be given. This restriction is not enforced - if you ignore it, the behaviour will be unpredictable. .SH LEASE DECLARATIONS .PP .I The .B lease .I declaration .PP \fBlease {\fR \fIlease-declaration\fR [ ... \fIlease-declaration ] \fB}\fR .PP The DHCP client may decide after some period of time (see \fBPROTOCOL TIMING\fR) that it is not going to succeed in contacting a server. At that time, it consults its own database of old leases and tests each one that has not yet timed out by pinging the listed router for that lease to see if that lease could work. It is possible to define one or more \fIfixed\fR leases in the client configuration file for networks where there is no DHCP or BOOTP service, so that the client can still automatically configure its address. This is done with the .B lease statement. .PP NOTE: the lease statement is also used in the dhclient.leases file in order to record leases that have been received from DHCP servers. Some of the syntax for leases as described below is only needed in the dhclient.leases file. Such syntax is documented here for completeness. .PP A lease statement consists of the lease keyword, followed by a left curly brace, followed by one or more lease declaration statements, followed by a right curly brace. The following lease declarations are possible: .PP \fBbootp;\fR .PP The .B bootp statement is used to indicate that the lease was acquired using the BOOTP protocol rather than the DHCP protocol. It is never necessary to specify this in the client configuration file. The client uses this syntax in its lease database file. .PP \fBinterface\fR \fB"\fR\fIstring\fR\fB";\fR .PP The .B interface lease statement is used to indicate the interface on which the lease is valid. If set, this lease will only be tried on a particular interface. When the client receives a lease from a server, it always records the interface number on which it received that lease. If predefined leases are specified in the dhclient.conf file, the interface should also be specified, although this is not required. .PP \fBfixed-address\fR \fIip-address\fR\fB;\fR .PP The .B fixed-address statement is used to set the ip address of a particular lease. This is required for all lease statements. The IP address must be specified as a dotted quad (e.g., 12.34.56.78). .PP \fBfilename "\fR\fIstring\fR\fB";\fR .PP The .B filename statement specifies the name of the boot filename to use. This is not used by the standard client configuration script, but is included for completeness. .PP \fBserver-name "\fR\fIstring\fR\fB";\fR .PP The .B server-name statement specifies the name of the boot server name to use. This is also not used by the standard client configuration script. .PP \fBoption\fR \fIoption-declaration\fR\fB;\fR .PP The .B option statement is used to specify the value of an option supplied by the server, or, in the case of predefined leases declared in dhclient.conf, the value that the user wishes the client configuration script to use if the predefined lease is used. .PP \fBscript "\fIscript-name\fB";\fR .PP The .B script statement is used to specify the pathname of the dhcp client configuration script. This script is used by the dhcp client to set each interface's initial configuration prior to requesting an address, to test the address once it has been offered, and to set the 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-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 The .B medium statement can be used on systems where network interfaces cannot automatically determine the type of network to which they are connected. The media setup string is a system-dependent parameter which is passed to the dhcp client configuration script when initializing the interface. On Unix and Unix-like systems, the argument is passed on the ifconfig command line when configuring the interface. .PP The dhcp client automatically declares this parameter if it uses a media type (see the .B media statement) when configuring the interface in order to obtain a lease. This statement should be used in predefined leases only if the network interface requires media type configuration. .PP \fBrenew\fR \fIdate\fB;\fR .PP \fBrebind\fR \fIdate\fB;\fR .PP \fBexpire\fR \fIdate\fB;\fR .PP The \fBrenew\fR statement defines the time at which the dhcp client should begin trying to contact its server to renew a lease that it is using. The \fBrebind\fR statement defines the time at which the dhcp client should begin to try to contact \fIany\fR dhcp server in order to renew its lease. The \fBexpire\fR statement defines the time at which the dhcp client must stop using a lease if it has not been able to contact a server in order to renew it. .PP These declarations are automatically set in leases acquired by the DHCP client, but must also be configured in predefined leases - a predefined lease whose expiry time has passed will not be used by the DHCP client. .PP Dates are specified as follows: .PP \fI \fB/\fI\fB/\fI \fB:\fI\fB:\fI\fR .PP The weekday is present to make it easy for a human to tell when a lease expires - it's specified as a number from zero to six, with zero being Sunday. When declaring a predefined lease, it can always be 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 59, and the second also a number between 0 and 59. .SH ALIAS DECLARATIONS \fBalias { \fI declarations ... \fB}\fR .PP Some DHCP clients running TCP/IP roaming protocols may require that in addition to the lease they may acquire via DHCP, their interface also be configured with a predefined IP alias so that they can have a -permanent IP address even while roaming. The Internet Software +permanent IP address even while roaming. The Internet Systems Consortium DHCP client doesn't support roaming with fixed addresses directly, but in order to facilitate such experimentation, the dhcp client can be set up to configure an IP alias using the .B alias declaration. .PP The alias declaration resembles a lease declaration, except that options other than the subnet-mask option are ignored by the standard client configuration script, and expiry times are ignored. A typical alias declaration includes an interface declaration, a fixed-address declaration for the IP alias address, and a subnet-mask option declaration. A medium statement should never be included in an alias declaration. .SH OTHER DECLARATIONS \fBreject \fIip-address\fB;\fR .PP The .B reject statement causes the DHCP client to reject offers from servers who use the specified address as a server identifier. This can be used to avoid being configured by rogue or misconfigured dhcp servers, although it should be a last resort - better to track down the bad DHCP server and fix it. .PP \fBinterface "\fIname\fB" { \fIdeclarations ... \fB } .PP A client with more than one network interface may require different behaviour depending on which interface is being configured. All timing parameters and declarations other than lease and alias declarations can be enclosed in an interface declaration, and those parameters will then be used only for the interface that matches the 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 separate 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 .B media statement defines one or more media configuration parameters which may be tried while attempting to acquire an IP address. The dhcp client will cycle through each media setup string on the list, configuring the interface using that setup and attempting to boot, and then trying the next one. This can be used for network interfaces which aren't capable of sensing the media type unaided - whichever media type succeeds in getting a request to the server and hearing the reply is probably right (no guarantees). .PP The media setup is only used for the initial phase of address acquisition (the DHCPDISCOVER and DHCPOFFER packets). Once an address has been acquired, the dhcp client will record it in its lease database and will record the media type used to acquire the address. Whenever the client tries to renew the lease, it will use that same media type. The lease must expire before the client will go back to cycling through media types. .SH SAMPLE The following configuration file is used on a laptop running NetBSD 1.3. The laptop has an IP alias of 192.5.5.213, and has one interface, ep0 (a 3com 3C589C). Booting intervals have been shortened somewhat from the default, because the client is known to spend most of its time on networks with little DHCP activity. The laptop does roam to multiple networks. .nf timeout 60; retry 60; reboot 10; select-timeout 5; initial-interval 2; reject 192.33.137.209; interface "ep0" { send host-name "andare.fugue.com"; send dhcp-client-identifier 1:0:a0:24:ab:fb:9c; send dhcp-lease-time 3600; supersede domain-name "fugue.com rc.vix.com home.vix.com"; prepend domain-name-servers 127.0.0.1; request subnet-mask, broadcast-address, time-offset, routers, domain-name, domain-name-servers, host-name; require subnet-mask, domain-name-servers; script "CLIENTBINDIR/dhclient-script"; media "media 10baseT/UTP", "media 10base2/BNC"; } alias { interface "ep0"; fixed-address 192.5.5.213; option subnet-mask 255.255.255.255; } .fi This is a very complicated dhclient.conf file - in general, yours should be much simpler. In many cases, it's sufficient to just create an empty dhclient.conf file - the defaults are usually fine. .SH SEE ALSO dhcp-options(5), dhclient.leases(5), dhcpd(8), dhcpd.conf(5), RFC2132, RFC2131. .SH AUTHOR .B dhclient(8) was written by Ted Lemon under a contract with Vixie Labs. Funding -for this project was provided by the Internet Software Consortium. -Information about the Internet Software Consortium can be found at +for this project was provided by Internet Systems Consortium. +Information about Internet Systems Consortium can be found at .B http://www.isc.org. Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/client/dhclient.leases.5 =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/client/dhclient.leases.5 (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/client/dhclient.leases.5 (revision 131136) @@ -1,65 +1,53 @@ -.\" dhclient.conf.5 +.\" $Id: dhclient.leases.5,v 1.2.4.4 2004/06/10 17:59:13 dhankins Exp $ .\" -.\" Copyright (c) 1997-2002 The Internet Software Consortium. -.\" All rights reserved. +.\" Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (c) 1997-2003 by Internet Software Consortium .\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. .\" -.\" 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. +.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +.\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.\" 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. +.\" Internet Systems Consortium, Inc. +.\" 950 Charter Street +.\" Redwood City, CA 94063 +.\" +.\" http://www.isc.org/ .\" -.\" This software has been written for the Internet Software Consortium +.\" This software has been written for Internet Systems Consortium .\" by Ted Lemon in cooperation with Vixie -.\" Enterprises. To learn more about the Internet Software Consortium, +.\" Enterprises. To learn more about Internet Systems Consortium, .\" see ``http://www.isc.org/isc''. To learn more about Vixie .\" Enterprises, see ``http://www.vix.com''. -.\" -.\" $Id: dhclient.leases.5,v 1.2.4.3 2002/11/17 02:25:44 dhankins Exp $ -.\" .TH dhclient.leases 5 .SH NAME dhclient.leases - DHCP client lease database .SH DESCRIPTION -The Internet Software Consortium DHCP client keeps a persistent +The Internet Systems Consortium DHCP client keeps a persistent database of leases that it has acquired that are still valid. The database is a free-form ASCII file containing one valid declaration per lease. If more than one declaration appears for a given lease, the last one in the file is used. The file is written as a log, so this is not an unusual occurrance. .PP The format of the lease declarations is described in .B dhclient.conf(5). .SH FILES .B DBDIR/dhclient.leases .SH SEE ALSO 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 under a contract with Vixie Labs. Funding -for this project was provided by the Internet Software Consortium. -Information about the Internet Software Consortium can be found at +for this project was provided by Internet Systems Consortium. +Information about Internet Systems Consortium can be found at .B http://www.isc.org. Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/client/scripts/freebsd =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/client/scripts/freebsd (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/client/scripts/freebsd (revision 131136) @@ -1,237 +1,237 @@ #!/bin/sh # -# $Id: freebsd,v 1.13.2.5 2003/04/27 19:44:01 dhankins Exp $ +# $Id: freebsd,v 1.13.2.6 2003/09/12 19:31:03 dhankins Exp $ # # $FreeBSD$ if [ -x /usr/bin/logger ]; then LOGGER="/usr/bin/logger -s -p user.notice -t dhclient" else LOGGER=echo fi make_resolv_conf() { if [ x"$new_domain_name_servers" != x ]; then if [ "x$new_domain_name" != x ]; then ( echo search $new_domain_name >/etc/resolv.conf ) exit_status=$? else - rm /etc/resolv.conf + ( rm /etc/resolv.conf ) exit_status=$? fi if [ $exit_status -ne 0 ]; then $LOGGER "WARNING: Unable to update resolv.conf: Error $exit_status" else for nameserver in $new_domain_name_servers; do ( echo nameserver $nameserver >>/etc/resolv.conf ) done fi fi } # Must be used on exit. Invokes the local dhcp client exit hooks, if any. exit_with_hooks() { exit_status=$1 if [ -f /etc/dhclient-exit-hooks ]; then . /etc/dhclient-exit-hooks fi # probably should do something with exit status of the local script exit $exit_status } # Invoke the local dhcp client enter hooks, if they exist. if [ -f /etc/dhclient-enter-hooks ]; then exit_status=0 . /etc/dhclient-enter-hooks # allow the local script to abort processing of this state # local script must set exit_status variable to nonzero. if [ $exit_status -ne 0 ]; then exit $exit_status fi fi if [ x$new_network_number != x ]; then $LOGGER New Network Number: $new_network_number fi if [ x$new_broadcast_address != x ]; then $LOGGER New Broadcast Address: $new_broadcast_address new_broadcast_arg="broadcast $new_broadcast_address" fi if [ x$old_broadcast_address != x ]; then old_broadcast_arg="broadcast $old_broadcast_address" fi if [ x$new_subnet_mask != x ]; then new_netmask_arg="netmask $new_subnet_mask" fi if [ x$old_subnet_mask != x ]; then old_netmask_arg="netmask $old_subnet_mask" fi if [ x$alias_subnet_mask != x ]; then alias_subnet_arg="netmask $alias_subnet_mask" fi if [ x$reason = xMEDIUM ]; then 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 if [ x$reason = xPREINIT ]; 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 ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 \ broadcast 255.255.255.255 up exit_with_hooks 0 fi if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then exit_with_hooks 0; fi if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then current_hostname=`/bin/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 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 [ -n "$old_static_routes" ]; then 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 -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 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 [ -n "$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 [ -n "$new_static_routes" ]; then $LOGGER "New Static Routes: $new_static_routes" set -- $new_static_routes while [ $# -gt 1 ]; do route add $1 $2 shift; shift done fi fi if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ]; then ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg route add $alias_ip_address 127.0.0.1 fi make_resolv_conf exit_with_hooks 0 fi 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 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 [ -n "$old_static_routes" ]; then 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 -d \1/p' \ |sh >/dev/null 2>&1 fi if [ x$alias_ip_address != x ]; then ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg route add $alias_ip_address 127.0.0.1 fi exit_with_hooks 0 fi if [ x$reason = xTIMEOUT ]; 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 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 [ -n "$new_routers" ]; then $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 ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg route add $alias_ip_address 127.0.0.1 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 set -- $new_static_routes while [ $# -gt 1 ]; do route add $1 $2 shift; shift done make_resolv_conf exit_with_hooks 0 fi fi 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 [ -n "$old_static_routes" ]; then 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 -d \1/p' \ |sh >/dev/null 2>&1 exit_with_hooks 1 fi exit_with_hooks 0 Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/Makefile.dist =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/Makefile.dist (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/Makefile.dist (revision 131136) @@ -1,75 +1,95 @@ # Makefile.dist +# +# Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# Internet Systems Consortium, Inc. +# 950 Charter Street +# Redwood City, CA 94063 +# +# http://www.isc.org/ 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 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 + lpf.c dlpi.c packet.c tr.c ethernet.c iscprint.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 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 + lpf.o dlpi.o packet.o tr.o ethernet.o iscprint.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 INCLUDES = -I$(TOP) $(BINDINC) -I$(TOP)/includes CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS) all: libdhcp.a $(CATMANPAGES) libdhcp.a: $(OBJ) rm -f libdhcp.a ar cruv libdhcp.a $(OBJ) $(RANLIB) libdhcp.a install: all for dir in $(FFMANDIR); do \ foo=""; \ for bar in `echo $(DESTDIR)$${dir} |tr / ' '`; do \ foo=$${foo}/$$bar; \ if [ ! -d $$foo ]; then \ mkdir $$foo; \ chmod 755 $$foo; \ fi; \ done; \ 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) *~ #* 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 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 dhcp-eval.cat5: dhcp-eval.man5 nroff -man dhcp-eval.man5 >dhcp-eval.cat5 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) Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/alloc.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/alloc.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/alloc.c (revision 131136) @@ -1,1326 +1,1317 @@ /* alloc.c Memory allocation... */ /* - * Copyright (c) 1996-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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.53.2.9 2002/11/17 02:26:56 dhankins Exp $ Copyright (c) 1996-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: alloc.c,v 1.53.2.10 2004/06/10 17:59:14 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #include struct dhcp_packet *dhcp_free_list; struct packet *packet_free_list; int option_chain_head_allocate (ptr, file, line) struct option_chain_head **ptr; const char *file; int line; { int size; 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; { 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; } int group_allocate (ptr, file, line) struct group **ptr; const char *file; int line; { int size; struct group *g; 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 } g = dmalloc (sizeof *g, file, line); if (g) { memset (g, 0, sizeof *g); return group_reference (ptr, g, file, line); } return 0; } int group_reference (ptr, bp, file, line) struct group **ptr; struct group *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 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 (file, line) const char *file; int line; { struct dhcp_packet *rval; rval = (struct dhcp_packet *)dmalloc (sizeof (struct dhcp_packet), 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; } 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 universe *rval = dmalloc (sizeof (struct universe), file, line); return rval; } 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; pair new_pair (file, line) const char *file; int line; { 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; } 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 expression), file, line); if (!rval) return 0; } memset (rval, 0, sizeof *rval); return expression_reference (cptr, rval, file, line); } int expression_reference (ptr, src, file, line) struct expression **ptr; struct expression *src; 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 expression *)0; #endif } *ptr = src; src -> refcnt++; rc_register (file, line, ptr, src, src -> refcnt, 0, RC_MISC); return 1; } void free_expression (expr, file, line) struct expression *expr; const char *file; int line; { expr -> data.not = free_expressions; free_expressions = expr; dmalloc_reuse (free_expressions, (char *)0, 0, 0); } #if defined (DEBUG_MEMORY_LEAKAGE) || \ defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) void relinquish_free_expressions () { 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 binding_value *free_binding_values; int binding_value_allocate (cptr, file, line) struct binding_value **cptr; const char *file; int line; { 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); } int binding_value_reference (ptr, src, file, line) struct binding_value **ptr; struct binding_value *src; 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 binding_value *)0; #endif } *ptr = src; src -> refcnt++; rc_register (file, line, ptr, src, src -> refcnt, 0, RC_MISC); return 1; } void free_binding_value (bv, file, line) struct binding_value *bv; const char *file; int line; { bv -> value.bv = free_binding_values; free_binding_values = bv; dmalloc_reuse (free_binding_values, (char *)0, 0, 0); } #if defined (DEBUG_MEMORY_LEAKAGE) || \ defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) void relinquish_free_binding_values () { 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 int fundef_allocate (cptr, file, line) struct fundef **cptr; const char *file; int line; { 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); } int fundef_reference (ptr, src, file, line) struct fundef **ptr; struct fundef *src; 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 fundef *)0; #endif } *ptr = src; src -> refcnt++; rc_register (file, line, ptr, src, src -> refcnt, 0, RC_MISC); return 1; } struct option_cache *free_option_caches; #if defined (DEBUG_MEMORY_LEAKAGE) || \ defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) void relinquish_free_option_caches () { struct option_cache *o, *n; 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 option_cache), file, line); if (!rval) return 0; } memset (rval, 0, sizeof *rval); return option_cache_reference (cptr, rval, file, line); } int option_cache_reference (ptr, src, file, line) struct option_cache **ptr; struct option_cache *src; 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_cache *)0; #endif } *ptr = src; src -> refcnt++; rc_register (file, line, ptr, src, src -> refcnt, 0, RC_MISC); return 1; } int buffer_allocate (ptr, len, file, line) struct buffer **ptr; unsigned len; const char *file; int line; { 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); } int buffer_reference (ptr, bp, file, line) struct buffer **ptr; struct buffer *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 buffer *)0; #endif } *ptr = bp; bp -> refcnt++; rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC); return 1; } int buffer_dereference (ptr, file, line) struct buffer **ptr; const char *file; int line; { 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; } int dns_host_entry_allocate (ptr, hostname, file, line) struct dns_host_entry **ptr; const char *hostname; const char *file; int line; { 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); } 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; { 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; } int executable_statement_allocate (ptr, file, line) struct executable_statement **ptr; const char *file; int line; { 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); } int executable_statement_reference (ptr, bp, file, line) struct executable_statement **ptr; struct executable_statement *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 executable_statement *)0; #endif } *ptr = bp; bp -> refcnt++; rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC); return 1; } static struct packet *free_packets; #if defined (DEBUG_MEMORY_LEAKAGE) || \ defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) void relinquish_free_packets () { 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 int packet_allocate (ptr, file, line) struct packet **ptr; const char *file; int line; { 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; } int packet_reference (ptr, bp, file, line) struct packet **ptr; struct packet *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 packet *)0; #endif } *ptr = bp; bp -> refcnt++; rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC); return 1; } int packet_dereference (ptr, file, line) struct packet **ptr; const char *file; int line; { 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; } int dns_zone_allocate (ptr, file, line) struct dns_zone **ptr; const char *file; int line; { 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; } int dns_zone_reference (ptr, bp, file, line) struct dns_zone **ptr; struct dns_zone *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_zone *)0; #endif } *ptr = bp; bp -> refcnt++; rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC); return 1; } int binding_scope_allocate (ptr, file, line) struct binding_scope **ptr; const char *file; int line; { 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; } int binding_scope_reference (ptr, bp, file, line) struct binding_scope **ptr; struct binding_scope *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 binding_scope *)0; #endif } *ptr = bp; bp -> refcnt++; rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC); return 1; } /* 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; { 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; } } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/bpf.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/bpf.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/bpf.c (revision 131136) @@ -1,564 +1,548 @@ /* bpf.c BPF socket interface code, originally contributed by Archie Cobbs. */ /* - * Copyright (c) 1996-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * 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''. + * This software was contributed to Internet Systems Consortium + * by Archie Cobbs. * * 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.48.2.3 2002/11/17 02:26:56 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: bpf.c,v 1.48.2.6 2004/06/17 20:54:38 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE) \ || defined (USE_LPF_RECEIVE) # if defined (USE_LPF_RECEIVE) # include # include # define bpf_insn sock_filter /* Linux: dare to be gratuitously different. */ # else # include # include # include # if defined (NEED_OSF_PFILT_HACKS) # include # endif # endif #include #include "includes/netinet/ip.h" #include "includes/netinet/udp.h" #include "includes/netinet/if_ether.h" #endif /* Reinitializes the specified interface after an address change. This is not required for packet-filter APIs. */ #ifdef USE_BPF_SEND void if_reinitialize_send (info) struct interface_info *info; { } #endif #ifdef USE_BPF_RECEIVE void if_reinitialize_receive (info) struct interface_info *info; { } #endif /* Called by get_interface_list for each interface that's discovered. Opens a packet filter for each interface and adds it to the select mask. */ #if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE) int if_register_bpf (info) struct interface_info *info; { int sock; char filename[50]; int b; /* Open a BPF device */ for (b = 0; 1; b++) { -#ifndef NO_SNPRINTF - snprintf(filename, sizeof(filename), BPF_FORMAT, b); -#else + /* %Audit% 31 bytes max. %2004.06.17,Safe% */ sprintf(filename, BPF_FORMAT, b); -#endif sock = open (filename, O_RDWR, 0); if (sock < 0) { if (errno == EBUSY) { continue; } else { if (!b) log_fatal ("No bpf devices.%s%s%s", " Please read the README", " section for your operating", " system."); log_fatal ("Can't find free bpf: %m"); } } else { break; } } /* Set the BPF device to point at this interface. */ if (ioctl (sock, BIOCSETIF, info -> ifp) < 0) log_fatal ("Can't attach interface %s to bpf device %s: %m", info -> name, filename); return sock; } #endif /* USE_BPF_SEND || USE_BPF_RECEIVE */ #ifdef USE_BPF_SEND void if_register_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 info -> wfdesc = if_register_bpf (info, interface); #else info -> wfdesc = info -> rfdesc; #endif if (!quiet_interface_discovery) 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.hbuf [0], info -> hw_address.hlen - 1, &info -> hw_address.hbuf [1]), (info -> shared_network ? "/" : ""), (info -> shared_network ? info -> shared_network -> name : "")); } #endif /* USE_BPF_SEND */ #if defined (USE_BPF_RECEIVE) || defined (USE_LPF_RECEIVE) /* Packet filter program... XXX Changes to the filter program may require changes to the constant offsets used in if_register_send to patch the BPF program! XXX */ struct bpf_insn dhcp_bpf_filter [] = { /* Make sure this is an IP packet... */ BPF_STMT (BPF_LD + BPF_H + BPF_ABS, 12), BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8), /* Make sure it's a UDP packet... */ BPF_STMT (BPF_LD + BPF_B + BPF_ABS, 23), BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6), /* Make sure this isn't a fragment... */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20), BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0), /* Get the IP header length... */ BPF_STMT (BPF_LDX + BPF_B + BPF_MSH, 14), /* Make sure it's to the right port... */ BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16), BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), /* patch */ /* If we passed all the tests, ask for the whole packet. */ BPF_STMT(BPF_RET+BPF_K, (u_int)-1), /* Otherwise, drop it. */ BPF_STMT(BPF_RET+BPF_K, 0), }; #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 */ /* If we passed all the tests, ask for the whole packet. */ BPF_STMT(BPF_RET+BPF_K, (u_int)-1), /* Otherwise, drop it. */ BPF_STMT(BPF_RET+BPF_K, 0), }; int dhcp_bpf_tr_filter_len = (sizeof dhcp_bpf_tr_filter / sizeof (struct bpf_insn)); #endif /* HAVE_TR_SUPPORT */ #endif /* USE_LPF_RECEIVE || USE_BPF_RECEIVE */ #if defined (USE_BPF_RECEIVE) void if_register_receive (info) struct interface_info *info; { int flag = 1; struct bpf_version v; 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) log_fatal ("Can't get BPF version: %m"); if (v.bv_major != BPF_MAJOR_VERSION || v.bv_minor < BPF_MINOR_VERSION) 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) 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) log_fatal ("Can't set ALLOWCOPYALL: %m"); /* Clear all the packet filter mode bits first... */ bits = 0; if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0) 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) 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) log_fatal ("Can't get bpf buffer length: %m"); info -> rbuf = dmalloc (info -> rbuf_max, MDL); if (!info -> rbuf) 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... XXX changes to filter program may require changes to the insn number(s) used below! XXX */ dhcp_bpf_filter [8].k = ntohs (local_port); if (ioctl (info -> rfdesc, BIOCSETF, &p) < 0) log_fatal ("Can't install packet filter program: %m"); if (!quiet_interface_discovery) log_info ("Listening 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_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 : "")); } #endif /* USE_BPF_RECEIVE */ #ifdef USE_BPF_SEND ssize_t send_packet (interface, packet, raw, len, from, to, hto) 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; { 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, (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 *)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) log_error ("send_packet: %m"); return result; } #endif /* USE_BPF_SEND */ #ifdef USE_BPF_RECEIVE ssize_t receive_packet (interface, buf, len, from, hfrom) struct interface_info *interface; unsigned char *buf; size_t len; struct sockaddr_in *from; struct hardware *hfrom; { int length = 0; int offset = 0; struct bpf_hdr hdr; /* All this complexity is because BPF doesn't guarantee that only one packet will be returned at a time. We're getting what we deserve, though - this is a terrible abuse of the BPF interface. Sigh. */ /* Process packets until we get one we can return or until we've done a read and gotten nothing we can return... */ do { /* If the buffer is empty, fill it. */ if (interface -> rbuf_offset == interface -> rbuf_len) { length = read (interface -> rfdesc, interface -> rbuf, (size_t)interface -> rbuf_max); if (length <= 0) { #ifdef __FreeBSD__ if (errno == ENXIO) { #else if (errno == EIO) { #endif dhcp_interface_remove ((omapi_object_t *)interface, (omapi_object_t *)0); } return length; } interface -> rbuf_offset = 0; interface -> rbuf_len = BPF_WORDALIGN (length); } /* If there isn't room for a whole bpf header, something went wrong, but we'll ignore it and hope it goes away... XXX */ if (interface -> rbuf_len - interface -> rbuf_offset < sizeof hdr) { interface -> rbuf_offset = interface -> rbuf_len; continue; } /* Copy out a bpf header... */ memcpy (&hdr, &interface -> rbuf [interface -> rbuf_offset], sizeof hdr); /* If the bpf header plus data doesn't fit in what's left of the buffer, stick head in sand yet again... */ if (interface -> rbuf_offset + hdr.bh_hdrlen + hdr.bh_caplen > interface -> rbuf_len) { interface -> rbuf_offset = interface -> rbuf_len; continue; } /* If the captured data wasn't the whole packet, or if 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 = BPF_WORDALIGN (interface -> rbuf_offset + hdr.bh_hdrlen + hdr.bh_caplen); continue; } /* Skip over the BPF header... */ interface -> rbuf_offset += hdr.bh_hdrlen; /* Decode the physical header... */ offset = decode_hw_header (interface, interface -> rbuf, interface -> rbuf_offset, hfrom); /* If a physical layer checksum failed (dunno of any physical layer that supports this, but WTH), skip this packet. */ if (offset < 0) { interface -> rbuf_offset = BPF_WORDALIGN (interface -> rbuf_offset + hdr.bh_caplen); continue; } interface -> rbuf_offset += offset; hdr.bh_caplen -= offset; /* Decode the IP and UDP headers... */ offset = decode_udp_ip_header (interface, interface -> rbuf, interface -> rbuf_offset, from, (unsigned char *)0, hdr.bh_caplen); /* If the IP or UDP checksum was bad, skip the packet... */ if (offset < 0) { interface -> rbuf_offset = BPF_WORDALIGN (interface -> rbuf_offset + hdr.bh_caplen); continue; } 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 = 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 = BPF_WORDALIGN (interface -> rbuf_offset + hdr.bh_caplen); return hdr.bh_caplen; } while (!length); return 0; } int can_unicast_without_arp (ip) struct interface_info *ip; { return 1; } int can_receive_unicast_unconfigured (ip) struct interface_info *ip; { return 1; } int supports_multiple_interfaces (ip) struct interface_info *ip; { return 1; } void maybe_setup_fallback () { isc_result_t status; struct interface_info *fbi = (struct interface_info *)0; if (setup_fallback (&fbi, MDL)) { if_register_fallback (fbi); 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 Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/comapi.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/comapi.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/comapi.c (revision 131136) @@ -1,958 +1,949 @@ /* omapi.c OMAPI object interfaces for the DHCP server. */ /* - * Copyright (c) 1999-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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.6 2002/11/17 02:26:56 dhankins Exp $ Copyright (c) 1999-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: comapi.c,v 1.9.2.7 2004/06/10 17:59:14 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #include 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; } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/conflex.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/conflex.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/conflex.c (revision 131136) @@ -1,1082 +1,1073 @@ /* conflex.c Lexical scanner for dhcpd config file... */ /* - * Copyright (c) 1995-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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.92.2.6 2002/11/17 02:26:56 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: conflex.c,v 1.92.2.7 2004/06/10 17:59:14 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #include 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)); 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; 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; } *cfile = tmp; return ISC_R_SUCCESS; } isc_result_t end_parse (cfile) struct parse **cfile; { if ((*cfile) -> bufsiz) dfree ((*cfile) -> inbuf, MDL); dfree (*cfile, MDL); *cfile = (struct parse *)0; return ISC_R_SUCCESS; } static int get_char (cfile) struct parse *cfile; { /* 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 (cfile -> cur_line == cfile -> line1) { cfile -> cur_line = cfile -> line2; cfile -> prev_line = cfile -> line1; } else { cfile -> cur_line = cfile -> line1; cfile -> prev_line = cfile -> line2; } cfile -> line++; cfile -> lpos = 1; cfile -> cur_line [0] = 0; } else if (c != EOF) { if (cfile -> lpos <= 80) { cfile -> cur_line [cfile -> lpos - 1] = c; cfile -> cur_line [cfile -> lpos] = 0; } cfile -> lpos++; } } else cfile -> ugflag = 0; return c; } static enum dhcp_token get_token (cfile) struct parse *cfile; { int c; enum dhcp_token ttok; static char tb [2]; int l, p, u; do { l = cfile -> line; p = cfile -> lpos; u = cfile -> ugflag; c = get_char (cfile); #ifdef OLD_LEXER if (c == '\n' && p == 1 && !u && cfile -> comment_index < sizeof cfile -> comments) cfile -> comments [cfile -> comment_index++] = '\n'; #endif if (!(c == '\n' && cfile -> eol_token) && isascii (c) && isspace (c)) continue; if (c == '#') { #ifdef OLD_LEXER if (cfile -> comment_index < sizeof cfile -> comments) cfile -> comments [cfile -> comment_index++] = '#'; #endif skip_to_eol (cfile); continue; } if (c == '"') { cfile -> lexline = l; cfile -> lexchar = p; ttok = read_string (cfile); break; } if ((isascii (c) && isdigit (c)) || c == '-') { cfile -> lexline = l; cfile -> lexchar = p; ttok = read_number (c, cfile); break; } else if (isascii (c) && isalpha (c)) { 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 { cfile -> lexline = l; cfile -> lexchar = p; tb [0] = c; tb [1] = 0; cfile -> tval = tb; cfile -> tlen = 1; ttok = c; break; } } while (1); return ttok; } enum dhcp_token next_token (rval, rlen, cfile) const char **rval; unsigned *rlen; struct parse *cfile; { int rv; 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); cfile -> token_line = cfile -> cur_line; } if (rval) *rval = cfile -> tval; if (rlen) *rlen = cfile -> tlen; #ifdef DEBUG_TOKENS fprintf (stderr, "%s:%d ", cfile -> tval, rv); #endif return rv; } enum dhcp_token peek_token (rval, rlen, cfile) const char **rval; unsigned int *rlen; struct parse *cfile; { int 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 = cfile -> tval; if (rlen) *rlen = cfile -> tlen; #ifdef DEBUG_TOKENS fprintf (stderr, "(%s:%d) ", cfile -> tval, cfile -> token); #endif return cfile -> token; } static void skip_to_eol (cfile) struct parse *cfile; { int c; do { c = get_char (cfile); if (c == EOF) return; #ifdef OLD_LEXER if (cfile -> comment_index < sizeof (cfile -> comments)) comments [cfile -> comment_index++] = c; #endif if (c == EOL) { return; } } while (1); } 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 cfile -> tokbuf; i++) { again: c = get_char (cfile); if (c == EOF) { parse_warn (cfile, "eof in string constant"); break; } 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; } 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; goto again; } else if (c == '"') break; else 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 cfile -> tokbuf) { parse_warn (cfile, "string constant larger than internal buffer"); --i; } cfile -> tokbuf [i] = 0; cfile -> tlen = i; cfile -> tval = cfile -> tokbuf; return STRING; } static enum dhcp_token read_number (c, cfile) int c; struct parse *cfile; { int seenx = 0; int i = 0; int token = NUMBER; cfile -> tokbuf [i++] = c; for (; i < sizeof cfile -> tokbuf; i++) { c = get_char (cfile); if (!seenx && c == 'x') { seenx = 1; #ifndef OLD_LEXER } else if (isascii (c) && !isxdigit (c) && (c == '-' || c == '_' || isalpha (c))) { token = NAME; } else if (isascii (c) && !isdigit (c) && isxdigit (c)) { token = NUMBER_OR_NAME; #endif } else if (!isascii (c) || !isxdigit (c)) { if (c != EOF) { cfile -> bufix--; cfile -> ugflag = 1; } break; } cfile -> tokbuf [i] = c; } if (i == sizeof cfile -> tokbuf) { parse_warn (cfile, "numeric token larger than internal buffer"); --i; } cfile -> tokbuf [i] = 0; cfile -> tlen = i; cfile -> tval = cfile -> tokbuf; return token; } static enum dhcp_token read_num_or_name (c, cfile) int c; struct parse *cfile; { int i = 0; 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))) { if (c != EOF) { cfile -> bufix--; cfile -> ugflag = 1; } break; } if (!isxdigit (c)) rv = NAME; cfile -> tokbuf [i] = c; } if (i == sizeof cfile -> tokbuf) { parse_warn (cfile, "token larger than internal buffer"); --i; } cfile -> tokbuf [i] = 0; cfile -> tlen = i; cfile -> tval = cfile -> tokbuf; return intern (cfile -> tval, rv); } static enum dhcp_token intern (atom, dfv) char *atom; 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 (!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 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, "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 (!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, "o-forward-update")) return DO_FORWARD_UPDATE; 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; if (!strcasecmp (atom + 7, "-lease-time")) return DEFAULT_LEASE_TIME; 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 (!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")) return GIADDR; if (!strcasecmp (atom + 1, "roup")) return GROUP; if (!strcasecmp (atom + 1, "et-lease-hostnames")) 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 (!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; if (!strcasecmp (atom + 4, "um")) 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")) return REBIND; if (!strcasecmp (atom + 1, "eboot")) 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, "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")) return TIMESTAMP; if (!strcasecmp (atom + 1, "imeout")) 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; if (!strcasecmp (atom + 3, "-host-decl-names")) return USE_HOST_DECL_NAMES; if (!strcasecmp (atom + 3, "-lease-addr-for-default-route")) return USE_LEASE_ADDR_FOR_DEFAULT_ROUTE; break; } 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; } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/ctrace.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/ctrace.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/ctrace.c (revision 131136) @@ -1,297 +1,293 @@ /* trace.c Subroutines that support dhcp tracing... */ /* - * Copyright (c) 2001-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2001-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems 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 + * about Internet Systems Consortium, see http://www.isc.org/. To * learn more about Nominum, Inc., see ``http://www.nominum.com''. */ + +#ifndef lint +static char copyright[] = +"$Id: ctrace.c,v 1.3.2.2 2004/06/10 17:59:15 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; +#endif /* not lint */ #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 */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/dhcp-eval.5 =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/dhcp-eval.5 (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/dhcp-eval.5 (revision 131136) @@ -1,484 +1,477 @@ -.\" dhcp-eval.5 +.\" $Id: dhcp-eval.5,v 1.17.2.7 2004/06/10 17:59:15 dhankins Exp $ .\" -.\" Copyright (c) 1996-2002 Internet Software Consortium. -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: +.\" Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (c) 1996-2003 by Internet Software Consortium .\" -.\" 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. +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. .\" -.\" 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. +.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +.\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.\" This software has been written for the Internet Software Consortium +.\" Internet Systems Consortium, Inc. +.\" 950 Charter Street +.\" Redwood City, CA 94063 +.\" +.\" http://www.isc.org/ +.\" +.\" This software has been written for Internet Systems Consortium .\" by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. -.\" To learn more about the Internet Software Consortium, see +.\" To learn more about Internet Systems 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 Internet Systems 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-separated hexadecimal list .PP .RS 0.25i A list of hexadecimal octet values, separated 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 separated 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 +The Internet Systems 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 +this project was provided through Internet Systems Consortium. +Information about Internet Systems Consortium can be found at .B http://www.isc.org. Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/dhcp-options.5 =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/dhcp-options.5 (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/dhcp-options.5 (revision 131136) @@ -1,1526 +1,1516 @@ -.\" dhcp-options.5 +.\" $Id: dhcp-options.5,v 1.19.2.11 2004/06/10 17:59:15 dhankins Exp $ .\" -.\" Copyright (c) 1996-2002 Internet Software Consortium. -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: +.\" Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (c) 1996-2003 by Internet Software Consortium .\" -.\" 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. +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. .\" -.\" 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. +.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +.\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.\" This software has been written for the Internet Software Consortium +.\" Internet Systems Consortium, Inc. +.\" 950 Charter Street +.\" Redwood City, CA 94063 +.\" +.\" http://www.isc.org/ +.\" +.\" This software has been written for Internet Systems Consortium .\" by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. -.\" To learn more about the Internet Software Consortium, see +.\" To learn more about Internet Systems 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''. -.\" -.\" $Id: dhcp-options.5,v 1.19.2.10 2003/02/23 03:27:42 dhankins Exp $ -.\" .TH dhcpd-options 5 .SH NAME dhcp-options - Dynamic Host Configuration Protocol options .SH DESCRIPTION The Dynamic Host Configuration protocol allows the client to receive .B options from the DHCP server describing the network configuration and various services that are available on the network. When configuring .B dhcpd(8) or .B dhclient(8) , options must often be declared. The syntax for declaring options, and the names and formats of the options that can be declared, are documented here. .SH REFERENCE: OPTION STATEMENTS .PP DHCP \fIoption\fR statements always start with the \fIoption\fR keyword, followed by an option name, followed by option data. The option names and data formats are described below. It is not necessary to exhaustively specify all DHCP options - only those options which are needed by clients must be specified. .PP Option data comes in a variety of formats, as defined below: .PP The .B ip-address data type can be entered either as an explicit IP address (e.g., 239.254.197.10) or as a domain name (e.g., haagen.isc.org). When entering a domain name, be sure that that domain name resolves to a single IP address. .PP The .B int32 data type specifies a signed 32-bit integer. The .B uint32 data type specifies an unsigned 32-bit integer. The .B int16 and .B uint16 data types specify signed and unsigned 16-bit integers. The .B int8 and .B uint8 data types specify signed and unsigned 8-bit integers. Unsigned 8-bit integers are also sometimes referred to as octets. .PP The .B text data type specifies an NVT ASCII string, which must be enclosed in double quotes - for example, to specify a root-path option, the syntax would be .nf .sp 1 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 string data type specifies either an NVT ASCII string enclosed in double quotes, or a series of octets specified in hexadecimal, separated by colons. For example: .nf .sp 1 option dhcp-client-identifier "CLIENT-FOO"; or 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 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 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 dhcp-client-identifier "\\0foo"; rather than: option dhcp-client-identifier "foo"; .fi .RE .PP .B option \fBdhcp-lease-time\fR \fIuint32\fR\fB;\fR .RS 0.25i .PP 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 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 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 \fBdhcp-message\fR \fItext\fR\fB;\fR .RS 0.25i .PP 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 \fBdhcp-message-type\fR \fIuint8\fR\fB;\fR .RS 0.25i .PP 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 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 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 \fBdhcp-rebinding-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 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... ]\fB;\fR .RS 0.25i .PP The domain-name-servers option specifies a list of Domain Name System (STD 13, RFC 1035) name servers available to the client. Servers should be listed in order of preference. .RE .PP .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 servers 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 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. This option is only honored by .B dhclient-script(8) if the hostname for the client machine is not set. .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 \fBimpress-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 available to the client. Servers should be listed in order of preference. .RE .PP .B option \fBinterface-mtu\fR \fIuint16\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. .RE .PP .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 servers 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 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 \fBlpr-servers\fR \fIip-address \fR [\fB,\fR \fIip-address\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. .RE .PP .B option \fBmask-supplier\fR \fIflag\fR\fB;\fR .RS 0.25i .PP 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 \fBmax-dgram-reassembly\fR \fIuint16\fR\fB;\fR .RS 0.25i .PP This option specifies the maximum size datagram that the client should be prepared to reassemble. The minimum legal value is 576. .RE .PP .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 core image should be dumped in the event the client crashes. The path is formatted as a character string consisting of characters from the NVT ASCII character set. .RE .PP .B option \fBmobile-ip-home-agent\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... ]\fB;\fR .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. .RE .PP .B option \fBnds-context\fR \fIstring\fR\fB;\fR .RS 0.25i .PP The nds-context option specifies the name of the initial Netware Directory Service for an NDS client. .RE .PP .B option \fBnds-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... ]\fB;\fR .RS 0.25i .PP The nds-servers option specifies a list of IP addresses of NDS servers. .RE .PP .B option \fBnds-tree-name\fR \fIstring\fR\fB;\fR .RS 0.25i .PP The nds-tree-name 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 servesr 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 .RS 0.25i .PP 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 false means disallow forwarding of such datagrams, and a value of true means allow forwarding. .RE .PP .B option \fBntp-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 NTP (RFC 1035) servers available to the client. Servers should be listed in order of preference. .RE .PP .B option \fBnwip-domain\fR \fIstring\fR\fB;\fR .RS 0.25i .PP The name of the NetWare/IP domain that a NetWare/IP client should use. .RE .PP .B option \fBnwip-suboptions\fR \fIstring\fR\fB;\fR .RS 0.25i .PP 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 .RS 0.25i .PP This option specifies the timeout (in seconds) to use when aging Path MTU values discovered by the mechanism defined in RFC 1191. .RE .PP .B option \fBpath-mtu-plateau-table\fR \fIuint16\fR [\fB,\fR \fIuint16\fR... ]\fB;\fR .RS 0.25i .PP This option specifies a table of MTU sizes to use when performing Path MTU Discovery as defined in RFC 1191. The table is formatted as a list of 16-bit unsigned integers, ordered from smallest to largest. The minimum MTU value cannot be smaller than 68. .RE .PP .B option \fBperform-mask-discovery\fR \fIflag\fR\fB;\fR .RS 0.25i .PP 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 .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 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 \fBpop-server\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... ]\fB;\fR .RS 0.25i .PP The POP3 server option specifies a list of POP3 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...]\fB;\fR .fi .RS 0.25i .PP 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 \fBroot-path\fR \fItext\fB;\fR\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. .RE .PP .B option \fBrouter-discovery\fR \fIflag\fR\fB;\fR .RS 0.25i .PP This option specifies whether or not the client should solicit routers using the Router Discovery mechanism defined in RFC 1256. 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 .B option \fBrouter-solicitation-address\fR \fIip-address\fR\fB;\fR .RS 0.25i .PP This option specifies the address to which the client should transmit router solicitation requests. .RE .PP .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-separated 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 priority. .PP The routes consist of a list of IP address pairs. The first address is the destination address, and the second address is the router for the destination. .PP 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. 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 .nf .B option \fBstreettalk-directory-assistance-server\fR \fIip-address\fR [\fB,\fR \fIip-address\fR...]\fB;\fR .fi .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. .RE .PP .B option \fBstreettalk-server\fR \fIip-address\fR [\fB,\fR \fIip-address\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. .RE .PP .B option subnet-mask \fIip-address\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. .RE .PP .B option \fBsubnet-selection\fR \fIstring\fR\fB;\fR .RS 0.25i .PP 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 whether or not the client should send TCP keepalive messages with an 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 .RS 0.25i .PP This option specifies the interval (in seconds) that the client TCP should wait before sending a keepalive message on a TCP connection. The time is specified as a 32-bit unsigned integer. A value of zero indicates that the client should not generate keepalive messages on connections unless specifically requested by an application. .RE .PP .B option \fBtftp-server-name\fR \fItext\fR\fB;\fR .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. .RE .PP .B option time-offset \fIint32\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). .RE .PP .B option time-servers \fIip-address\fR [, \fIip-address\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. .RE .PP .B option \fBtrailer-encapsulation\fR \fIflag\fR\fB;\fR .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 false 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 \fBuap-servers\fR \fItext\fR\fB;\fR .RS 0.25i .PP 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 separated by spaces. .RE .PP .B option \fBuser-class\fR \fIstring\fR\fB;\fR .RS 0.25i .PP 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 \fBvendor-class-identifier\fR \fIstring\fR\fB;\fR .RS 0.25i .PP 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 set vendor-class option vendor-class-identifier; .fi .PP 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 \fBvendor-encapsulated-options\fR \fIstring\fR\fB;\fR .RS 0.25i .PP 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 \fBwww-server\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... ]\fB;\fR .RS 0.25i .PP The WWW server option specifies a list of WWW servers 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... ]\fB;\fR .RS 0.25i .PP 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 .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 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 .PP .B option \fBagent.remote-id\fR \fIstring\fR\fB;\fR .RS 0.25i .PP 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 .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 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 fqdn.server-update \fIflag\fB; .RS 0.25i .PP 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 fqdn.encoded \fIflag\fB; .RS 0.25i .PP 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 fqdn.rcode1 \fIflag\fB; .PP .B option fqdn.rcode2 \fIflag\fB; .RS 0.25i .PP 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 fqdn.fqdn \fItext\fB; .RS 0.25i .PP 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 fqdn.hostname \fI--never set--\fB; .RS 0.25i .PP This option should never be set, but it can be read back using the \fBoption\fR and \fBconfig-option\fR operators in an expression, in which case it returns the first label in the \fBfqdn.fqdn\fR suboption - for example, if the value of \fBfqdn.fqdn\fR is "foo.example.com.", then \fBfqdn.hostname\fR will be "foo". .RE .PP .B option fqdn.domainname \fI--never set--\fB; .RS 0.25i .PP This option should never be set, but it can be read back using the \fBoption\fR and \fBconfig-option\fR operators in an expression, in which case it returns all labels after the first label in the \fBfqdn.fqdn\fR suboption - for example, if the value of \fBfqdn.fqdn\fR is "foo.example.com.", then \fBfqdn.hostname\fR will be "example.com.". If this suboption value is not set, it means that an unqualified name was sent in the fqdn option, or that no fqdn option was sent at all. .RE .PP 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 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 .RE .B option \fBnwip.preferred-dss\fR \fIip-address\fR [\fB,\fR \fIip-address\fR... ]\fR\fB;\fR .RS 0.25i .PP 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 \fBnwip.nearest-nwip-server\fR \fI\fIip-address\fR [\fB,\fR \fIip-address\fR...]\fR\fB;\fR .RS 0.25i .PP 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 \fBnwip.autoretries\fR \fIuint8\fR\fB;\fR .RS 0.25i .PP 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 \fBnwip.autoretry-secs\fR \fIuint8\fR\fB;\fR .RS 0.25i .PP 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 \fBnwip.nwip-1-1\fR \fIuint8\fR\fB;\fR .RS 0.25i .PP 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 \fBnwip.primary-dss\fR \fIip-address\fR\fB;\fR .RS 0.25i .PP 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 +The Internet Systems 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 separated 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-separated 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), dhcp-eval(5), dhcpd(8), dhclient(8), RFC2132, RFC2131, draft-ietf-dhc-agent-options-??.txt. .SH AUTHOR -The Internet Software Consortium DHCP Distribution was written by Ted +The Internet Systems 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 +this project was provided through Internet Systems Consortium. +Information about Internet Systems Consortium can be found at .B http://www.isc.org. Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/discover.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/discover.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/discover.c (revision 131136) @@ -1,1147 +1,1138 @@ /* dispatch.c Network input dispatcher... */ /* - * Copyright (c) 1995-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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.14 2003/07/25 19:44:15 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: discover.c,v 1.42.2.15 2004/06/10 17:59:16 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #include 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_addr.sa_len > sizeof (struct sockaddr)) i += (sizeof ifp -> ifr_name) + ifp -> ifr_addr.sa_len; else #endif i += sizeof *ifp; #ifdef ALIAS_NAMES_PERMUTED if ((s = strrchr (ifp -> ifr_name, ':'))) { *s = 0; } #endif #ifdef SKIP_DUMMY_INTERFACES if (!strncmp (ifp -> ifr_name, "dummy", 5)) continue; #endif /* See if this is the sort of interface we want to deal with. */ strcpy (ifr.ifr_name, ifp -> ifr_name); if (ioctl (sock, SIOCGIFFLAGS, &ifr) < 0) log_fatal ("Can't get interface flags for %s: %m", ifr.ifr_name); /* See if we've seen an interface that matches this one. */ for (tmp = interfaces; tmp; tmp = tmp -> next) if (!strcmp (tmp -> name, ifp -> ifr_name)) break; /* Skip non broadcast interfaces (plus loopback and point-to-point in case an OS incorrectly marks them as broadcast). Also skip down interfaces unless we're trying to get a list of configurable interfaces. */ if (((!(ifr.ifr_flags & IFF_BROADCAST) || ifr.ifr_flags & IFF_LOOPBACK || ifr.ifr_flags & IFF_POINTOPOINT) && !tmp) || (!(ifr.ifr_flags & IFF_UP) && state != DISCOVER_UNCONFIGURED)) continue; /* If there isn't already an interface by this name, allocate one. */ if (!tmp) { tmp = (struct interface_info *)0; status = interface_allocate (&tmp, MDL); if (status != ISC_R_SUCCESS) log_fatal ("Error allocating interface %s: %s", ifp -> ifr_name, isc_result_totext (status)); strcpy (tmp -> name, ifp -> ifr_name); interface_snorf (tmp, ir); interface_dereference (&tmp, MDL); tmp = interfaces; /* XXX */ } if (dhcp_interface_discovery_hook) (*dhcp_interface_discovery_hook) (tmp); /* If we have the capability, extract link information and record it in a linked list. */ #ifdef HAVE_AF_LINK if (ifp -> ifr_addr.sa_family == AF_LINK) { struct sockaddr_dl *foo = ((struct sockaddr_dl *) (&ifp -> ifr_addr)); #if defined (HAVE_SIN_LEN) tmp -> hw_address.hlen = foo -> sdl_alen; #else tmp -> hw_address.hlen = 6; /* XXX!!! */ #endif tmp -> hw_address.hbuf [0] = HTYPE_ETHER; /* XXX */ memcpy (&tmp -> hw_address.hbuf [1], LLADDR (foo), tmp -> hw_address.hlen); tmp -> hw_address.hlen++; /* for type. */ } else #endif /* AF_LINK */ if (ifp -> ifr_addr.sa_family == AF_INET) { struct iaddr addr; /* Get a pointer to the address... */ memcpy (&foo, &ifp -> ifr_addr, sizeof ifp -> ifr_addr); /* We don't want the loopback interface. */ if (foo.sin_addr.s_addr == htonl (INADDR_LOOPBACK) && ((tmp -> flags & INTERFACE_AUTOMATIC) && state == DISCOVER_SERVER)) continue; /* If this is the first real IP address we've found, keep a pointer to ifreq structure in which we found it. */ if (!tmp -> ifp) { #ifdef HAVE_SA_LEN unsigned len = ((sizeof ifp -> ifr_name) + ifp -> ifr_addr.sa_len); #else unsigned len = sizeof *ifp; #endif tif = (struct ifreq *)dmalloc (len, MDL); if (!tif) log_fatal ("no space for ifp."); memcpy (tif, ifp, len); tmp -> ifp = tif; tmp -> primary_address = foo.sin_addr; } /* Grab the address... */ addr.len = 4; memcpy (addr.iabuf, &foo.sin_addr.s_addr, addr.len); if (dhcp_interface_setup_hook) (*dhcp_interface_setup_hook) (tmp, &addr); } } /* If we allocated a buffer, free it. */ if (ic.ifc_ifcu.ifcu_buf != buf) dfree (ic.ifc_ifcu.ifcu_buf, MDL); #if defined (LINUX_SLASHPROC_DISCOVERY) /* On Linux, interfaces that don't have IP addresses don't show up in the SIOCGIFCONF syscall. This only matters for the DHCP client, of course - the relay agent and server should only care about interfaces that are configured with IP addresses anyway. The PROCDEV_DEVICE (/proc/net/dev) is a kernel-supplied file that, when read, prints a human readable network status. We extract the names of the network devices by skipping the first two lines (which are header) and then parsing off everything up to the colon in each subsequent line - these lines start with the interface name, then a colon, then a bunch of statistics. */ if (state == DISCOVER_UNCONFIGURED) { FILE *proc_dev; char buffer [256]; int skip = 2; proc_dev = fopen (PROCDEV_DEVICE, "r"); if (!proc_dev) log_fatal ("%s: %m", PROCDEV_DEVICE); while (fgets (buffer, sizeof buffer, proc_dev)) { char *name = buffer; char *sep; /* Skip the first two blocks, which are header lines. */ if (skip) { --skip; continue; } sep = strrchr (buffer, ':'); if (sep) *sep = '\0'; while (*name == ' ') name++; /* See if we've seen an interface that matches this one. */ for (tmp = interfaces; tmp; tmp = tmp -> next) if (!strcmp (tmp -> name, name)) break; /* If we found one, nothing more to do.. */ if (tmp) continue; /* Otherwise, allocate one. */ tmp = (struct interface_info *)0; status = interface_allocate (&tmp, MDL); if (status != ISC_R_SUCCESS) log_fatal ("Can't allocate interface %s: %s", name, isc_result_totext (status)); tmp -> flags = ir; strncpy (tmp -> name, name, IFNAMSIZ); if (interfaces) { interface_reference (&tmp -> next, interfaces, MDL); interface_dereference (&interfaces, MDL); } interface_reference (&interfaces, tmp, MDL); interface_dereference (&tmp, MDL); tmp = interfaces; if (dhcp_interface_discovery_hook) (*dhcp_interface_discovery_hook) (tmp); } fclose (proc_dev); } #endif /* Now cycle through all the interfaces we found, looking for hardware addresses. */ #if defined (HAVE_SIOCGIFHWADDR) && !defined (HAVE_AF_LINK) for (tmp = interfaces; tmp; tmp = tmp -> next) { struct ifreq ifr; struct sockaddr sa; int b, sk; if (!tmp -> ifp) { /* Make up an ifreq structure. */ tif = (struct ifreq *)dmalloc (sizeof (struct ifreq), MDL); if (!tif) log_fatal ("no space to remember ifp."); memset (tif, 0, sizeof (struct ifreq)); strcpy (tif -> ifr_name, tmp -> name); tmp -> ifp = tif; } /* Read the hardware address from this interface. */ ifr = *tmp -> ifp; if (ioctl (sock, SIOCGIFHWADDR, &ifr) < 0) continue; sa = *(struct sockaddr *)&ifr.ifr_hwaddr; switch (sa.sa_family) { #ifdef HAVE_ARPHRD_TUNNEL case ARPHRD_TUNNEL: /* ignore tunnel interfaces. */ #endif #ifdef HAVE_ARPHRD_ROSE case ARPHRD_ROSE: #endif #ifdef HAVE_ARPHRD_LOOPBACK case ARPHRD_LOOPBACK: /* ignore loopback interface */ break; #endif case ARPHRD_ETHER: tmp -> hw_address.hlen = 7; tmp -> hw_address.hbuf [0] = ARPHRD_ETHER; memcpy (&tmp -> hw_address.hbuf [1], sa.sa_data, 6); break; #ifndef HAVE_ARPHRD_IEEE802 # define ARPHRD_IEEE802 HTYPE_IEEE802 #endif #if defined (HAVE_ARPHRD_IEEE802_TR) case ARPHRD_IEEE802_TR: #endif case ARPHRD_IEEE802: tmp -> hw_address.hlen = 7; tmp -> hw_address.hbuf [0] = ARPHRD_IEEE802; memcpy (&tmp -> hw_address.hbuf [1], sa.sa_data, 6); break; #ifndef HAVE_ARPHRD_FDDI # define ARPHRD_FDDI HTYPE_FDDI #endif case ARPHRD_FDDI: tmp -> hw_address.hlen = 17; tmp -> hw_address.hbuf [0] = HTYPE_FDDI; /* XXX */ memcpy (&tmp -> hw_address.hbuf [1], sa.sa_data, 16); break; #ifdef HAVE_ARPHRD_METRICOM case ARPHRD_METRICOM: tmp -> hw_address.hlen = 7; tmp -> hw_address.hbuf [0] = ARPHRD_METRICOM; memcpy (&tmp -> hw_address.hbuf [0], sa.sa_data, 6); break; #endif #ifdef HAVE_ARPHRD_AX25 case ARPHRD_AX25: tmp -> hw_address.hlen = 7; tmp -> hw_address.hbuf [0] = ARPHRD_AX25; memcpy (&tmp -> hw_address.hbuf [1], sa.sa_data, 6); break; #endif #ifdef HAVE_ARPHRD_NETROM case ARPHRD_NETROM: tmp -> hw_address.hlen = 7; tmp -> hw_address.hbuf [0] = ARPHRD_NETROM; memcpy (&tmp -> hw_address.hbuf [1], sa.sa_data, 6); break; #endif default: log_error ("%s: unknown hardware address type %d", ifr.ifr_name, sa.sa_family); break; } } #endif /* defined (HAVE_SIOCGIFHWADDR) && !defined (HAVE_AF_LINK) */ /* If we're just trying to get a list of interfaces that we might be able to configure, we can quit now. */ if (state == DISCOVER_UNCONFIGURED) { close (sock); return; } /* Weed out the interfaces that did not have IP addresses. */ tmp = last = next = (struct interface_info *)0; if (interfaces) interface_reference (&tmp, interfaces, MDL); while (tmp) { if (next) interface_dereference (&next, MDL); if (tmp -> next) interface_reference (&next, tmp -> next, MDL); /* skip interfaces that are running already */ if (tmp -> flags & INTERFACE_RUNNING) { interface_dereference(&tmp, MDL); if(next) interface_reference(&tmp, next, MDL); continue; } if ((tmp -> flags & INTERFACE_AUTOMATIC) && state == DISCOVER_REQUESTED) tmp -> flags &= ~(INTERFACE_AUTOMATIC | INTERFACE_REQUESTED); if (!tmp -> ifp || !(tmp -> flags & INTERFACE_REQUESTED)) { if ((tmp -> flags & INTERFACE_REQUESTED) != ir) log_fatal ("%s: not found", tmp -> name); if (!last) { if (interfaces) interface_dereference (&interfaces, MDL); if (next) interface_reference (&interfaces, next, MDL); } else { interface_dereference (&last -> next, MDL); if (next) interface_reference (&last -> next, next, MDL); } if (tmp -> next) interface_dereference (&tmp -> next, MDL); /* Remember the interface in case we need to know about it later. */ if (dummy_interfaces) { interface_reference (&tmp -> next, dummy_interfaces, MDL); interface_dereference (&dummy_interfaces, MDL); } interface_reference (&dummy_interfaces, tmp, MDL); interface_dereference (&tmp, MDL); if (next) interface_reference (&tmp, next, MDL); continue; } last = tmp; memcpy (&foo, &tmp -> ifp -> ifr_addr, sizeof tmp -> ifp -> ifr_addr); /* We must have a subnet declaration for each interface. */ if (!tmp -> shared_network && (state == DISCOVER_SERVER)) { log_error ("%s", ""); log_error ("No subnet declaration for %s (%s).", tmp -> name, inet_ntoa (foo.sin_addr)); if (supports_multiple_interfaces (tmp)) { log_error ("** Ignoring requests on %s. %s", tmp -> name, "If this is not what"); log_error (" you want, please write %s", "a subnet declaration"); log_error (" in your dhcpd.conf file %s", "for the network segment"); log_error (" to %s %s %s", "which interface", tmp -> name, "is attached. **"); log_error ("%s", ""); goto next; } else { log_error ("You must write a subnet %s", " declaration for this"); log_error ("subnet. You cannot prevent %s", "the DHCP server"); log_error ("from listening on this subnet %s", "because your"); log_fatal ("operating system does not %s.", "support this capability"); } } /* Find subnets that don't have valid interface addresses... */ for (subnet = (tmp -> shared_network ? tmp -> shared_network -> subnets : (struct subnet *)0); subnet; subnet = subnet -> next_sibling) { if (!subnet -> interface_address.len) { /* Set the interface address for this subnet to the first address we found. */ subnet -> interface_address.len = 4; memcpy (subnet -> interface_address.iabuf, &foo.sin_addr.s_addr, 4); } } /* Flag the index as not having been set, so that the interface registerer can set it or not as it chooses. */ tmp -> index = -1; /* Register the interface... */ if_register_receive (tmp); if_register_send (tmp); interface_stash (tmp); wifcount++; #if defined (HAVE_SETFD) if (fcntl (tmp -> rfdesc, F_SETFD, 1) < 0) log_error ("Can't set close-on-exec on %s: %m", tmp -> name); if (tmp -> rfdesc != tmp -> wfdesc) { if (fcntl (tmp -> wfdesc, F_SETFD, 1) < 0) log_error ("Can't set close-on-exec on %s: %m", tmp -> name); } #endif next: interface_dereference (&tmp, MDL); if (next) interface_reference (&tmp, next, MDL); } /* Now register all the remaining interfaces as protocols. */ for (tmp = interfaces; tmp; tmp = tmp -> next) { /* not if it's been registered before */ if (tmp -> flags & INTERFACE_RUNNING) continue; if (tmp -> rfdesc == -1) continue; status = omapi_register_io_object ((omapi_object_t *)tmp, if_readsocket, 0, got_one, 0, 0); if (status != ISC_R_SUCCESS) log_fatal ("Can't register I/O handle for %s: %s", tmp -> name, isc_result_totext (status)); } close (sock); if (state == DISCOVER_SERVER && wifcount == 0) { log_info ("%s", ""); log_fatal ("Not configured to listen on any interfaces!"); } if (!setup_fallback) { setup_fallback = 1; maybe_setup_fallback (); } #if defined (HAVE_SETFD) if (fallback_interface) { if (fcntl (fallback_interface -> rfdesc, F_SETFD, 1) < 0) log_error ("Can't set close-on-exec on fallback: %m"); if (fallback_interface -> rfdesc != fallback_interface -> wfdesc) { if (fcntl (fallback_interface -> wfdesc, F_SETFD, 1) < 0) log_error ("Can't set close-on-exec on fallback: %m"); } } #endif } int if_readsocket (h) omapi_object_t *h; { struct interface_info *ip; if (h -> type != dhcp_type_interface) return -1; ip = (struct interface_info *)h; return ip -> rfdesc; } int setup_fallback (struct interface_info **fp, const char *file, int line) { isc_result_t status; status = interface_allocate (&fallback_interface, file, line); if (status != ISC_R_SUCCESS) log_fatal ("Error allocating fallback interface: %s", isc_result_totext (status)); strcpy (fallback_interface -> name, "fallback"); if (dhcp_interface_setup_hook) (*dhcp_interface_setup_hook) (fallback_interface, (struct iaddr *)0); status = interface_reference (fp, fallback_interface, file, line); fallback_interface -> index = -1; interface_stash (fallback_interface); return status == ISC_R_SUCCESS; } void reinitialize_interfaces () { struct interface_info *ip; for (ip = interfaces; ip; ip = ip -> next) { if_reinitialize_receive (ip); if_reinitialize_send (ip); } if (fallback_interface) if_reinitialize_send (fallback_interface); interfaces_invalidated = 1; } isc_result_t got_one (h) omapi_object_t *h; { struct sockaddr_in from; struct hardware hfrom; struct iaddr ifrom; int result; union { unsigned char packbuf [4095]; /* Packet input buffer. Must be as large as largest possible MTU. */ struct dhcp_packet packet; } u; struct interface_info *ip; if (h -> type != dhcp_type_interface) return ISC_R_INVALIDARG; ip = (struct interface_info *)h; again: if ((result = receive_packet (ip, u.packbuf, sizeof u, &from, &hfrom)) < 0) { log_error ("receive_packet failed on %s: %m", ip -> name); return ISC_R_UNEXPECTED; } if (result == 0) return ISC_R_UNEXPECTED; /* If we didn't at least get the fixed portion of the BOOTP packet, drop the packet. We're allowing packets with no sname or filename, because we're aware of at least one client that sends such packets, but this definitely falls into the category of being forgiving. */ if (result < DHCP_FIXED_NON_UDP - DHCP_SNAME_LEN - DHCP_FILE_LEN) return ISC_R_UNEXPECTED; if (bootp_packet_handler) { ifrom.len = 4; memcpy (ifrom.iabuf, &from.sin_addr, ifrom.len); (*bootp_packet_handler) (ip, &u.packet, (unsigned)result, from.sin_port, ifrom, &hfrom); } /* If there is buffered data, read again. This is for, e.g., bpf, which may return two packets at once. */ if (ip -> rbuf_offset != ip -> rbuf_len) goto again; return ISC_R_SUCCESS; } isc_result_t dhcp_interface_set_value (omapi_object_t *h, omapi_object_t *id, omapi_data_string_t *name, omapi_typed_data_t *value) { struct interface_info *interface; isc_result_t status; int foo; if (h -> type != dhcp_type_interface) return ISC_R_INVALIDARG; interface = (struct interface_info *)h; if (!omapi_ds_strcmp (name, "name")) { if ((value -> type == omapi_datatype_data || value -> type == omapi_datatype_string) && value -> u.buffer.len < sizeof interface -> name) { memcpy (interface -> name, value -> u.buffer.value, value -> u.buffer.len); interface -> name [value -> u.buffer.len] = 0; } else return ISC_R_INVALIDARG; return ISC_R_SUCCESS; } /* 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_interface_get_value (omapi_object_t *h, omapi_object_t *id, omapi_data_string_t *name, omapi_value_t **value) { return ISC_R_NOTIMPLEMENTED; } isc_result_t dhcp_interface_destroy (omapi_object_t *h, const char *file, int line) { struct interface_info *interface; isc_result_t status; if (h -> type != dhcp_type_interface) return ISC_R_INVALIDARG; interface = (struct interface_info *)h; if (interface -> ifp) { dfree (interface -> ifp, file, line); interface -> ifp = 0; } if (interface -> next) interface_dereference (&interface -> next, file, line); if (interface -> rbuf) { dfree (interface -> rbuf, file, line); interface -> rbuf = (unsigned char *)0; } if (interface -> client) interface -> client = (struct client_state *)0; if (interface -> shared_network) omapi_object_dereference ((omapi_object_t **) &interface -> shared_network, MDL); return ISC_R_SUCCESS; } isc_result_t dhcp_interface_signal_handler (omapi_object_t *h, const char *name, va_list ap) { struct interface_info *ip, *interface; struct client_config *config; struct client_state *client; isc_result_t status; if (h -> type != dhcp_type_interface) return ISC_R_INVALIDARG; interface = (struct interface_info *)h; /* If it's an update signal, see if the interface is dead right now, or isn't known at all, and if that's the case, revive it. */ if (!strcmp (name, "update")) { for (ip = dummy_interfaces; ip; ip = ip -> next) if (ip == interface) break; if (ip && dhcp_interface_startup_hook) return (*dhcp_interface_startup_hook) (ip); for (ip = interfaces; ip; ip = ip -> next) if (ip == interface) break; if (!ip && dhcp_interface_startup_hook) return (*dhcp_interface_startup_hook) (ip); } /* 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_interface_stuff_values (omapi_object_t *c, omapi_object_t *id, omapi_object_t *h) { struct interface_info *interface; isc_result_t status; if (h -> type != dhcp_type_interface) return ISC_R_INVALIDARG; interface = (struct interface_info *)h; /* Write out all the values. */ status = omapi_connection_put_name (c, "state"); if (status != ISC_R_SUCCESS) return status; if (interface -> flags && INTERFACE_REQUESTED) status = omapi_connection_put_string (c, "up"); else status = omapi_connection_put_string (c, "down"); 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_interface_lookup (omapi_object_t **ip, omapi_object_t *id, omapi_object_t *ref) { omapi_value_t *tv = (omapi_value_t *)0; isc_result_t status; struct interface_info *interface; 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 (ip, 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 ((*ip) -> type != dhcp_type_interface) { omapi_object_dereference (ip, MDL); return ISC_R_INVALIDARG; } } /* Now look for an interface name. */ status = omapi_get_value_str (ref, id, "name", &tv); if (status == ISC_R_SUCCESS) { char *s; unsigned len; for (interface = interfaces; interface; interface = interface -> next) { s = memchr (interface -> name, 0, IFNAMSIZ); if (s) len = s - &interface -> name [0]; else len = IFNAMSIZ; if ((tv -> value -> u.buffer.len == len && !memcmp (interface -> name, (char *)tv -> value -> u.buffer.value, len))) break; } if (!interface) { for (interface = dummy_interfaces; interface; interface = interface -> next) { s = memchr (interface -> name, 0, IFNAMSIZ); if (s) len = s - &interface -> name [0]; else len = IFNAMSIZ; if ((tv -> value -> u.buffer.len == len && !memcmp (interface -> name, (char *) tv -> value -> u.buffer.value, len))) break; } } omapi_value_dereference (&tv, MDL); if (*ip && *ip != (omapi_object_t *)interface) { omapi_object_dereference (ip, MDL); return ISC_R_KEYCONFLICT; } else if (!interface) { if (*ip) omapi_object_dereference (ip, MDL); return ISC_R_NOTFOUND; } else if (!*ip) omapi_object_reference (ip, (omapi_object_t *)interface, MDL); } /* If we get to here without finding an interface, no valid key was specified. */ if (!*ip) return ISC_R_NOKEYS; return ISC_R_SUCCESS; } /* actually just go discover the interface */ isc_result_t dhcp_interface_create (omapi_object_t **lp, omapi_object_t *id) { struct interface_info *hp; isc_result_t status; hp = (struct interface_info *)0; status = interface_allocate (&hp, MDL); if (status != ISC_R_SUCCESS) return status; hp -> flags = INTERFACE_REQUESTED; status = interface_reference ((struct interface_info **)lp, hp, MDL); interface_dereference (&hp, MDL); return status; } isc_result_t dhcp_interface_remove (omapi_object_t *lp, omapi_object_t *id) { struct interface_info *interface, *ip, *last; interface = (struct interface_info *)lp; /* remove from interfaces */ last = 0; for (ip = interfaces; ip; ip = ip -> next) { if (ip == interface) { if (last) { interface_dereference (&last -> next, MDL); if (ip -> next) interface_reference (&last -> next, ip -> next, MDL); } else { interface_dereference (&interfaces, MDL); if (ip -> next) interface_reference (&interfaces, ip -> next, MDL); } if (ip -> next) interface_dereference (&ip -> next, MDL); break; } last = ip; } if (!ip) return ISC_R_NOTFOUND; /* add the interface to the dummy_interface list */ if (dummy_interfaces) { interface_reference (&interface -> next, dummy_interfaces, MDL); interface_dereference (&dummy_interfaces, MDL); } interface_reference (&dummy_interfaces, interface, MDL); /* do a DHCPRELEASE */ if (dhcp_interface_shutdown_hook) (*dhcp_interface_shutdown_hook) (interface); /* remove the io object */ omapi_unregister_io_object ((omapi_object_t *)interface); if_deregister_send (interface); if_deregister_receive (interface); return ISC_R_SUCCESS; } void interface_stash (struct interface_info *tptr) { struct interface_info **vec; int delta; /* If the registerer didn't assign an index, assign one now. */ if (tptr -> index == -1) { tptr -> index = interface_count++; while (tptr -> index < interface_max && interface_vector [tptr -> index]) tptr -> index = interface_count++; } if (interface_max <= tptr -> index) { delta = tptr -> index - interface_max + 10; vec = dmalloc ((interface_max + delta) * sizeof (struct interface_info *), MDL); if (!vec) return; memset (&vec [interface_max], 0, (sizeof (struct interface_info *)) * delta); interface_max += delta; if (interface_vector) { memcpy (vec, interface_vector, (interface_count * sizeof (struct interface_info *))); dfree (interface_vector, MDL); } interface_vector = vec; } interface_reference (&interface_vector [tptr -> index], tptr, MDL); if (tptr -> index >= interface_count) interface_count = tptr -> index + 1; #if defined (TRACING) trace_interface_register (interface_trace, tptr); #endif } void interface_snorf (struct interface_info *tmp, int ir) { tmp -> circuit_id = (u_int8_t *)tmp -> name; tmp -> circuit_id_len = strlen (tmp -> name); tmp -> remote_id = 0; tmp -> remote_id_len = 0; tmp -> flags = ir; if (interfaces) { interface_reference (&tmp -> next, interfaces, MDL); interface_dereference (&interfaces, MDL); } interface_reference (&interfaces, tmp, MDL); } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/dispatch.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/dispatch.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/dispatch.c (revision 131136) @@ -1,228 +1,219 @@ /* dispatch.c Network input dispatcher... */ /* - * Copyright (c) 1995-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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: dispatch.c,v 1.63.2.3 2002/11/17 02:26:57 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: dispatch.c,v 1.63.2.4 2004/06/10 17:59:16 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" struct timeout *timeouts; static struct timeout *free_timeouts; void set_time (u_int32_t t) { /* Do any outstanding timeouts. */ if (cur_time != t) { cur_time = t; process_outstanding_timeouts ((struct timeval *)0); } } struct timeval *process_outstanding_timeouts (struct timeval *tvp) { /* Call any expired timeouts, and then if there's still a timeout registered, time out the select call then. */ another: if (timeouts) { struct timeout *t; if (timeouts -> when <= cur_time) { t = timeouts; timeouts = timeouts -> next; (*(t -> func)) (t -> what); if (t -> unref) (*t -> unref) (&t -> what, MDL); t -> next = free_timeouts; free_timeouts = t; goto another; } if (tvp) { tvp -> tv_sec = timeouts -> when; tvp -> tv_usec = 0; } return tvp; } else return (struct timeval *)0; } /* Wait for packets to come in using select(). When one does, call receive_packet to receive the packet and possibly strip hardware addressing information from it, and then call through the bootp_packet_handler hook to try to do something with it. */ void dispatch () { struct timeval tv, *tvp; isc_result_t status; /* Wait for a packet or a timeout... XXX */ do { tvp = process_outstanding_timeouts (&tv); status = omapi_one_dispatch (0, tvp); } while (status == ISC_R_TIMEDOUT || status == ISC_R_SUCCESS); log_fatal ("omapi_one_dispatch failed: %s -- exiting.", isc_result_totext (status)); } void add_timeout (when, where, what, ref, unref) TIME when; void (*where) PROTO ((void *)); void *what; tvref_t ref; tvunref_t unref; { struct timeout *t, *q; /* See if this timeout supersedes an existing timeout. */ t = (struct timeout *)0; for (q = timeouts; q; q = q -> next) { if ((where == NULL || q -> func == where) && q -> what == what) { if (t) t -> next = q -> next; else timeouts = q -> next; break; } t = q; } /* If we didn't supersede a timeout, allocate a timeout structure now. */ if (!q) { if (free_timeouts) { q = free_timeouts; free_timeouts = q -> next; } else { q = ((struct timeout *) dmalloc (sizeof (struct timeout), MDL)); if (!q) log_fatal ("add_timeout: no memory!"); } memset (q, 0, sizeof *q); q -> func = where; q -> ref = ref; q -> unref = unref; if (q -> ref) (*q -> ref)(&q -> what, what, MDL); else q -> what = what; } q -> when = when; /* Now sort this timeout into the timeout list. */ /* Beginning of list? */ if (!timeouts || timeouts -> when > q -> when) { q -> next = timeouts; timeouts = q; return; } /* Middle of list? */ for (t = timeouts; t -> next; t = t -> next) { if (t -> next -> when > q -> when) { q -> next = t -> next; t -> next = q; return; } } /* End of list. */ t -> next = q; q -> next = (struct timeout *)0; } void cancel_timeout (where, what) void (*where) PROTO ((void *)); void *what; { struct timeout *t, *q; /* Look for this timeout on the list, and unlink it if we find it. */ t = (struct timeout *)0; for (q = timeouts; q; q = q -> next) { if (q -> func == where && q -> what == what) { if (t) t -> next = q -> next; else timeouts = q -> next; break; } t = q; } /* If we found the timeout, put it on the free list. */ if (q) { if (q -> unref) (*q -> unref) (&q -> what, MDL); q -> next = free_timeouts; free_timeouts = q; } } #if defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) void cancel_all_timeouts () { struct timeout *t, *n; for (t = timeouts; t; t = n) { n = t -> next; if (t -> unref && t -> what) (*t -> unref) (&t -> what, MDL); t -> next = free_timeouts; free_timeouts = t; } } void relinquish_timeouts () { struct timeout *t, *n; for (t = free_timeouts; t; t = n) { n = t -> next; dfree (t, MDL); } } #endif Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/dlpi.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/dlpi.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/dlpi.c (revision 131136) @@ -1,1345 +1,1336 @@ /* dlpi.c Data Link Provider Interface (DLPI) network interface code. */ /* - * Copyright (c) 1996-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software was written for the Internet Software Consortium + * This software was written for Internet Systems Consortium * by Eric James Negaard, . To learn more about - * the Internet Software Consortium, see ``http://www.isc.org''. + * Internet Systems Consortium, see ``http://www.isc.org''. * * Joost Mulders has also done considerable work in debugging the DLPI API * support on Solaris and getting this code to work properly on a variety * of different Solaris platforms. */ /* * Based largely in part to the existing NIT code in nit.c. * * This code has been developed and tested on sparc-based machines running * SunOS 5.5.1, with le and hme network interfaces. It should be pretty * generic, though. */ /* * Implementation notes: * * I first tried to write this code to the "vanilla" DLPI 2.0 API. * It worked on a Sun Ultra-1 with a hme interface, but didn't work * on Sun SparcStation 5's with "le" interfaces (the packets sent out * via dlpiunitdatareq contained an Ethernet type of 0x0000 instead * of the expected 0x0800). * * Therefore I added the "DLPI_RAW" code which is a Sun extension to * the DLPI standard. This code works on both of the above machines. * This is configurable in the OS-dependent include file by defining * USE_DLPI_RAW. * * It quickly became apparant that I should also use the "pfmod" * STREAMS module to cut down on the amount of user level packet * processing. I don't know how widely available "pfmod" is, so it's * use is conditionally included. This is configurable in the * OS-dependent include file by defining USE_DLPI_PFMOD. * * A major quirk on the Sun's at least, is that no packets seem to get * sent out the interface until six seconds after the interface is * first "attached" to [per system reboot] (it's actually from when * the interface is attached, not when it is plumbed, so putting a * sleep into the dhclient-script at PREINIT time doesn't help). I * HAVE tried, without success to poll the fd to see when it is ready * for writing. This doesn't help at all. If the sleeps are not done, * the initial DHCPREQUEST or DHCPDISCOVER never gets sent out, so * I've put them here, when register_send and register_receive are * called (split up into two three-second sleeps between the notices, * so that it doesn't seem like so long when you're watching :-). The * amount of time to sleep is configurable in the OS-dependent include * file by defining DLPI_FIRST_SEND_WAIT to be the number of seconds * to sleep. */ #ifndef lint static char copyright[] = -"$Id: dlpi.c,v 1.28.2.1 2002/11/17 02:26:57 dhankins Exp $ Copyright (c) 1996-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: dlpi.c,v 1.28.2.2 2004/06/10 17:59:17 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #if defined (USE_DLPI_SEND) || defined (USE_DLPI_RECEIVE) # include # include # include # include # ifdef USE_DLPI_PFMOD # include # endif # ifdef USE_POLL # include # endif # include # include "includes/netinet/ip.h" # include "includes/netinet/udp.h" # include "includes/netinet/if_ether.h" # ifdef USE_DLPI_PFMOD # ifdef USE_DLPI_RAW # define DLPI_MODNAME "DLPI+RAW+PFMOD" # else # define DLPI_MODNAME "DLPI+PFMOD" # endif # else # ifdef USE_DLPI_RAW # define DLPI_MODNAME "DLPI+RAW" # else # define DLPI_MODNAME "DLPI" # endif # endif # ifndef ABS # define ABS(x) ((x) >= 0 ? (x) : 0-(x)) # endif static int strioctl PROTO ((int fd, int cmd, int timeout, int len, char *dp)); #define DLPI_MAXDLBUF 8192 /* Buffer size */ #define DLPI_MAXDLADDR 1024 /* Max address size */ #define DLPI_DEVDIR "/dev/" /* Device directory */ static int dlpiopen PROTO ((char *ifname)); static int dlpiunit PROTO ((char *ifname)); static int dlpiinforeq PROTO ((int fd)); static int dlpiphysaddrreq PROTO ((int fd, unsigned long addrtype)); static int dlpiattachreq PROTO ((int fd, unsigned long ppa)); static int dlpibindreq PROTO ((int fd, unsigned long sap, unsigned long max_conind, unsigned long service_mode, unsigned long conn_mgmt, unsigned long xidtest)); static int dlpidetachreq PROTO ((int fd)); static int dlpiunbindreq PROTO ((int fd)); static int dlpiokack PROTO ((int fd, char *bufp)); static int dlpiinfoack PROTO ((int fd, char *bufp)); static int dlpiphysaddrack PROTO ((int fd, char *bufp)); static int dlpibindack PROTO ((int fd, char *bufp)); static int dlpiunitdatareq PROTO ((int fd, unsigned char *addr, int addrlen, unsigned long minpri, unsigned long maxpri, unsigned char *data, int datalen)); static int dlpiunitdataind PROTO ((int fd, unsigned char *dstaddr, unsigned long *dstaddrlen, unsigned char *srcaddr, unsigned long *srcaddrlen, unsigned long *grpaddr, unsigned char *data, int datalen)); # ifndef USE_POLL static void sigalrm PROTO ((int sig)); # endif static int expected PROTO ((unsigned long prim, union DL_primitives *dlp, int msgflags)); static int strgetmsg PROTO ((int fd, struct strbuf *ctlp, struct strbuf *datap, int *flagsp, char *caller)); /* Reinitializes the specified interface after an address change. This is not required for packet-filter APIs. */ #ifdef USE_DLPI_SEND void if_reinitialize_send (info) struct interface_info *info; { } #endif #ifdef USE_DLPI_RECEIVE void if_reinitialize_receive (info) struct interface_info *info; { } #endif /* Called by get_interface_list for each interface that's discovered. Opens a packet filter for each interface and adds it to the select mask. */ int if_register_dlpi (info) struct interface_info *info; { int sock; int unit; long buf [DLPI_MAXDLBUF]; union DL_primitives *dlp; dlp = (union DL_primitives *)buf; /* Open a DLPI device */ if ((sock = dlpiopen (info -> name)) < 0) { log_fatal ("Can't open DLPI device for %s: %m", info -> name); } /* * Submit a DL_INFO_REQ request, to find the dl_mac_type and * dl_provider_style */ if (dlpiinforeq(sock) < 0 || dlpiinfoack(sock, (char *)buf) < 0) { log_fatal ("Can't get DLPI MAC type for %s: %m", info -> name); } else { switch (dlp -> info_ack.dl_mac_type) { case DL_CSMACD: /* IEEE 802.3 */ case DL_ETHER: info -> hw_address.hbuf [0] = HTYPE_ETHER; break; /* adding token ring 5/1999 - mayer@ping.at */ case DL_TPR: info -> hw_address.hbuf [0] = HTYPE_IEEE802; break; case DL_FDDI: info -> hw_address.hbuf [0] = HTYPE_FDDI; break; default: log_fatal ("%s: unsupported DLPI MAC type %ld", info -> name, dlp -> info_ack.dl_mac_type); break; } /* * copy the sap length and broadcast address of this interface * to interface_info. This fixes nothing but seemed nicer than to * assume -2 and ffffff. */ info -> dlpi_sap_length = dlp -> info_ack.dl_sap_length; info -> dlpi_broadcast_addr.hlen = dlp -> info_ack.dl_brdcst_addr_length; memcpy (info -> dlpi_broadcast_addr.hbuf, (char *)dlp + dlp -> info_ack.dl_brdcst_addr_offset, dlp -> info_ack.dl_brdcst_addr_length); } if (dlp -> info_ack.dl_provider_style == DL_STYLE2) { /* * Attach to the device. If this fails, the device * does not exist. */ unit = dlpiunit (info -> name); if (dlpiattachreq (sock, unit) < 0 || dlpiokack (sock, (char *)buf) < 0) { log_fatal ("Can't attach DLPI device for %s: %m", info -> name); } } /* * Bind to the IP service access point (SAP), connectionless (CLDLS). */ if (dlpibindreq (sock, ETHERTYPE_IP, 0, DL_CLDLS, 0, 0) < 0 || dlpibindack (sock, (char *)buf) < 0) { log_fatal ("Can't bind DLPI device for %s: %m", info -> name); } /* * Submit a DL_PHYS_ADDR_REQ request, to find * the hardware address */ if (dlpiphysaddrreq (sock, DL_CURR_PHYS_ADDR) < 0 || dlpiphysaddrack (sock, (char *)buf) < 0) { log_fatal ("Can't get DLPI hardware address for %s: %m", info -> name); } info -> hw_address.hlen = dlp -> physaddr_ack.dl_addr_length + 1; memcpy (&info -> hw_address.hbuf [1], (char *)buf + dlp -> physaddr_ack.dl_addr_offset, dlp -> physaddr_ack.dl_addr_length); #ifdef USE_DLPI_RAW if (strioctl (sock, DLIOCRAW, INFTIM, 0, 0) < 0) { log_fatal ("Can't set DLPI RAW mode for %s: %m", info -> name); } #endif #ifdef USE_DLPI_PFMOD if (ioctl (sock, I_PUSH, "pfmod") < 0) { log_fatal ("Can't push packet filter onto DLPI for %s: %m", info -> name); } #endif return sock; } static int strioctl (fd, cmd, timeout, len, dp) int fd; int cmd; int timeout; int len; char *dp; { struct strioctl sio; int rslt; sio.ic_cmd = cmd; sio.ic_timout = timeout; sio.ic_len = len; sio.ic_dp = dp; if ((rslt = ioctl (fd, I_STR, &sio)) < 0) { return rslt; } else { return sio.ic_len; } } #ifdef USE_DLPI_SEND void if_register_send (info) struct interface_info *info; { /* If we're using the DLPI API for sending and receiving, we don't need to register this interface twice. */ #ifndef USE_DLPI_RECEIVE # ifdef USE_DLPI_PFMOD struct packetfilt pf; # endif info -> wfdesc = if_register_dlpi (info); # ifdef USE_DLPI_PFMOD /* Set up an PFMOD filter that rejects everything... */ pf.Pf_Priority = 0; pf.Pf_FilterLen = 1; pf.Pf_Filter [0] = ENF_PUSHZERO; /* Install the filter */ if (strioctl (info -> wfdesc, PFIOCSETF, INFTIM, sizeof (pf), (char *)&pf) < 0) { log_fatal ("Can't set PFMOD send filter on %s: %m", info -> name); } # endif /* USE_DLPI_PFMOD */ #else /* !defined (USE_DLPI_RECEIVE) */ /* * If using DLPI for both send and receive, simply re-use * the read file descriptor that was set up earlier. */ info -> wfdesc = info -> rfdesc; #endif if (!quiet_interface_discovery) log_info ("Sending on DLPI/%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 : "")); #ifdef DLPI_FIRST_SEND_WAIT /* See the implementation notes at the beginning of this file */ # ifdef USE_DLPI_RECEIVE sleep (DLPI_FIRST_SEND_WAIT - (DLPI_FIRST_SEND_WAIT / 2)); # else sleep (DLPI_FIRST_SEND_WAIT); # endif #endif } void if_deregister_send (info) struct interface_info *info; { /* If we're using the DLPI API for sending and receiving, we don't need to register this interface twice. */ #ifndef USE_DLPI_RECEIVE close (info -> wfdesc); #endif info -> wfdesc = -1; if (!quiet_interface_discovery) log_info ("Disabling output on DLPI/%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 : "")); } #endif /* USE_DLPI_SEND */ #ifdef USE_DLPI_RECEIVE /* Packet filter program... XXX Changes to the filter program may require changes to the constant offsets used in if_register_send to patch the NIT program! XXX */ void if_register_receive (info) struct interface_info *info; { #ifdef USE_DLPI_PFMOD struct packetfilt pf; struct ip iphdr; u_int16_t offset; #endif /* Open a DLPI device and hang it on this interface... */ info -> rfdesc = if_register_dlpi (info); #ifdef USE_DLPI_PFMOD /* Set up the PFMOD filter program. */ /* XXX Unlike the BPF filter program, this one won't work if the XXX IP packet is fragmented or if there are options on the IP XXX header. */ pf.Pf_Priority = 0; pf.Pf_FilterLen = 0; #if defined (USE_DLPI_RAW) # define ETHER_H_PREFIX (14) /* sizeof (ethernet_header) */ /* * ethertype == ETHERTYPE_IP */ offset = 12; pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2); pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND; pf.Pf_Filter [pf.Pf_FilterLen++] = htons (ETHERTYPE_IP); # else # define ETHER_H_PREFIX (0) # endif /* USE_DLPI_RAW */ /* * The packets that will be received on this file descriptor * will be IP packets (due to the SAP that was specified in * the dlbind call). There will be no ethernet header. * Therefore, setup the packet filter to check the protocol * field for UDP, and the destination port number equal * to the local port. All offsets are relative to the start * of an IP packet. */ /* * BOOTPS destination port */ offset = ETHER_H_PREFIX + sizeof (iphdr) + sizeof (u_int16_t); pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2); pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND; pf.Pf_Filter [pf.Pf_FilterLen++] = local_port; /* * protocol should be udp. this is a byte compare, test for * endianess. */ offset = ETHER_H_PREFIX + ((u_int8_t *)&(iphdr.ip_p) - (u_int8_t *)&iphdr); pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2); pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_AND; pf.Pf_Filter [pf.Pf_FilterLen++] = htons (0x00FF); pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND; pf.Pf_Filter [pf.Pf_FilterLen++] = htons (IPPROTO_UDP); /* Install the filter... */ if (strioctl (info -> rfdesc, PFIOCSETF, INFTIM, sizeof (pf), (char *)&pf) < 0) { log_fatal ("Can't set PFMOD receive filter on %s: %m", info -> name); } #endif /* USE_DLPI_PFMOD */ if (!quiet_interface_discovery) log_info ("Listening on DLPI/%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 : "")); #ifdef DLPI_FIRST_SEND_WAIT /* See the implementation notes at the beginning of this file */ # ifdef USE_DLPI_SEND sleep (DLPI_FIRST_SEND_WAIT / 2); # else sleep (DLPI_FIRST_SEND_WAIT); # endif #endif } void if_deregister_receive (info) struct interface_info *info; { /* If we're using the DLPI API for sending and receiving, we don't need to register this interface twice. */ #ifndef USE_DLPI_SEND close (info -> rfdesc); #endif info -> rfdesc = -1; if (!quiet_interface_discovery) log_info ("Disabling input on DLPI/%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 : "")); } #endif /* USE_DLPI_RECEIVE */ #ifdef USE_DLPI_SEND ssize_t send_packet (interface, packet, raw, len, from, to, hto) 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; { unsigned hbufp = 0; double hh [32]; double ih [1536 / sizeof (double)]; unsigned char *dbuf = (unsigned char *)ih; unsigned dbuflen; unsigned char dstaddr [DLPI_MAXDLADDR]; unsigned addrlen; int result; int fudge; if (!strcmp (interface -> name, "fallback")) return send_fallback (interface, packet, raw, len, from, to, hto); dbuflen = 0; /* Assemble the headers... */ #ifdef USE_DLPI_RAW assemble_hw_header (interface, (unsigned char *)hh, &dbuflen, hto); if (dbuflen > sizeof hh) log_fatal ("send_packet: hh buffer too small.\n"); fudge = dbuflen % 4; /* IP header must be word-aligned. */ memcpy (dbuf + fudge, (unsigned char *)hh, dbuflen); dbuflen += fudge; #else fudge = 0; #endif assemble_udp_ip_header (interface, dbuf, &dbuflen, from.s_addr, to -> sin_addr.s_addr, to -> sin_port, (unsigned char *)raw, len); /* Copy the data into the buffer (yuk). */ memcpy (dbuf + dbuflen, raw, len); dbuflen += len; #ifdef USE_DLPI_RAW result = write (interface -> wfdesc, dbuf + fudge, dbuflen - fudge); #else /* * Setup the destination address (DLSAP) in dstaddr * * If sap_length < 0 we must deliver the DLSAP as phys+sap. * If sap_length > 0 we must deliver the DLSAP as sap+phys. * * sap = Service Access Point == ETHERTYPE_IP * sap + datalink address is called DLSAP in dlpi speak. */ { /* ENCODE DLSAP */ unsigned char phys [DLPI_MAXDLADDR]; unsigned char sap [4]; int sap_len = interface -> dlpi_sap_length; int phys_len = interface -> hw_address.hlen - 1; /* sap = htons (ETHERTYPE_IP) kludge */ memset (sap, 0, sizeof (sap)); # if (BYTE_ORDER == LITTLE_ENDIAN) sap [0] = 0x00; sap [1] = 0x08; # else sap [0] = 0x08; sap [1] = 0x00; # endif if (hto && hto -> hlen == interface -> hw_address.hlen) memcpy ( phys, (char *) &hto -> hbuf [1], phys_len); else memcpy ( phys, interface -> dlpi_broadcast_addr.hbuf, interface -> dlpi_broadcast_addr.hlen); if (sap_len < 0) { memcpy ( dstaddr, phys, phys_len); memcpy ( (char *) &dstaddr [phys_len], sap, ABS (sap_len)); } else { memcpy ( dstaddr, (void *) sap, sap_len); memcpy ( (char *) &dstaddr [sap_len], phys, phys_len); } addrlen = phys_len + ABS (sap_len); } /* ENCODE DLSAP */ result = dlpiunitdatareq (interface -> wfdesc, dstaddr, addrlen, 0, 0, dbuf, dbuflen); #endif /* USE_DLPI_RAW */ if (result < 0) log_error ("send_packet: %m"); return result; } #endif /* USE_DLPI_SEND */ #ifdef USE_DLPI_RECEIVE ssize_t receive_packet (interface, buf, len, from, hfrom) struct interface_info *interface; unsigned char *buf; size_t len; struct sockaddr_in *from; struct hardware *hfrom; { unsigned char dbuf [1536]; unsigned char srcaddr [DLPI_MAXDLADDR]; unsigned long srcaddrlen; int flags = 0; int length = 0; int offset = 0; int rslt; int bufix = 0; #ifdef USE_DLPI_RAW length = read (interface -> rfdesc, dbuf, sizeof (dbuf)); #else length = dlpiunitdataind (interface -> rfdesc, (unsigned char *)NULL, (unsigned long *)NULL, srcaddr, &srcaddrlen, (unsigned long *)NULL, dbuf, sizeof (dbuf)); #endif if (length <= 0) { return length; } # if !defined (USE_DLPI_RAW) /* * Copy the sender's hw address into hfrom * If sap_len < 0 the DLSAP is as phys+sap. * If sap_len > 0 the DLSAP is as sap+phys. * * sap is discarded here. */ { /* DECODE DLSAP */ int sap_len = interface -> dlpi_sap_length; int phys_len = interface -> hw_address.hlen - 1; if (hfrom && (srcaddrlen == ABS (sap_len) + phys_len )) { hfrom -> hbuf [0] = interface -> hw_address.hbuf [0]; hfrom -> hlen = interface -> hw_address.hlen; if (sap_len < 0) { memcpy ((char *) &hfrom -> hbuf [1], srcaddr, phys_len); } else { memcpy ((char *) &hfrom -> hbuf [1], (char *) &srcaddr [phys_len], phys_len); } } else if (hfrom) { memset (hfrom, '\0', sizeof *hfrom); } } /* DECODE_DLSAP */ # endif /* !defined (USE_DLPI_RAW) */ /* Decode the IP and UDP headers... */ bufix = 0; #ifdef USE_DLPI_RAW /* Decode the physical header... */ offset = decode_hw_header (interface, dbuf, bufix, hfrom); /* If a physical layer checksum failed (dunno of any physical layer that supports this, but WTH), skip this packet. */ if (offset < 0) { return 0; } bufix += offset; length -= offset; #endif offset = decode_udp_ip_header (interface, dbuf, bufix, from, (unsigned char *)0, length); /* If the IP or UDP checksum was bad, skip the packet... */ if (offset < 0) { return 0; } bufix += offset; length -= offset; /* Copy out the data in the packet... */ memcpy (buf, &dbuf [bufix], length); return length; } #endif /* Common DLPI routines ... * * Written by Eric James Negaard, * * Based largely in part to the example code contained in the document * "How to Use the STREAMS Data Link Provider Interface (DLPI)", written * by Neal Nuckolls of SunSoft Internet Engineering. * * This code has been developed and tested on sparc-based machines running * SunOS 5.5.1, with le and hme network interfaces. It should be pretty * generic, though. * * The usual disclaimers apply. This code works for me. Don't blame me * if it makes your machine or network go down in flames. That taken * into consideration, use this code as you wish. If you make usefull * modifications I'd appreciate hearing about it. */ #define DLPI_MAXWAIT 15 /* Max timeout */ /* * Parse an interface name and extract the unit number */ static int dlpiunit (ifname) char *ifname; { int fd; char *cp, *dp, *ep; int unit; if (!ifname) { return 0; } /* Advance to the end of the name */ cp = ifname; while (*cp) cp++; /* Back up to the start of the first digit */ while ((*(cp-1) >= '0' && *(cp-1) <= '9') || *(cp - 1) == ':') cp--; /* Convert the unit number */ unit = 0; while (*cp >= '0' && *cp <= '9') { unit *= 10; unit += (*cp++ - '0'); } return unit; } /* * dlpiopen - open the DLPI device for a given interface name */ static int dlpiopen (ifname) char *ifname; { char devname [50]; char *cp, *dp, *ep; if (!ifname) { return -1; } /* Open a DLPI device */ if (*ifname == '/') { dp = devname; } else { /* Prepend the device directory */ memcpy (devname, DLPI_DEVDIR, strlen (DLPI_DEVDIR)); dp = &devname [strlen (DLPI_DEVDIR)]; } /* Find the end of the interface name */ ep = cp = ifname; while (*ep) ep++; /* And back up to the first digit (unit number) */ while ((*(ep - 1) >= '0' && *(ep - 1) <= '9') || *(ep - 1) == ':') ep--; /* Copy everything up to the unit number */ while (cp < ep) { *dp++ = *cp++; } *dp = '\0'; return open (devname, O_RDWR, 0); } /* * dlpiinforeq - request information about the data link provider. */ static int dlpiinforeq (fd) int fd; { dl_info_req_t info_req; struct strbuf ctl; int flags; info_req.dl_primitive = DL_INFO_REQ; ctl.maxlen = 0; ctl.len = sizeof (info_req); ctl.buf = (char *)&info_req; flags = RS_HIPRI; return putmsg (fd, &ctl, (struct strbuf *)NULL, flags); } /* * dlpiphysaddrreq - request the current physical address. */ static int dlpiphysaddrreq (fd, addrtype) int fd; unsigned long addrtype; { dl_phys_addr_req_t physaddr_req; struct strbuf ctl; int flags; physaddr_req.dl_primitive = DL_PHYS_ADDR_REQ; physaddr_req.dl_addr_type = addrtype; ctl.maxlen = 0; ctl.len = sizeof (physaddr_req); ctl.buf = (char *)&physaddr_req; flags = RS_HIPRI; return putmsg (fd, &ctl, (struct strbuf *)NULL, flags); } /* * dlpiattachreq - send a request to attach to a specific unit. */ static int dlpiattachreq (fd, ppa) unsigned long ppa; int fd; { dl_attach_req_t attach_req; struct strbuf ctl; int flags; attach_req.dl_primitive = DL_ATTACH_REQ; attach_req.dl_ppa = ppa; ctl.maxlen = 0; ctl.len = sizeof (attach_req); ctl.buf = (char *)&attach_req; flags = 0; return putmsg (fd, &ctl, (struct strbuf*)NULL, flags); } /* * dlpibindreq - send a request to bind to a specific SAP address. */ static int dlpibindreq (fd, sap, max_conind, service_mode, conn_mgmt, xidtest) unsigned long sap; unsigned long max_conind; unsigned long service_mode; unsigned long conn_mgmt; unsigned long xidtest; int fd; { dl_bind_req_t bind_req; struct strbuf ctl; int flags; bind_req.dl_primitive = DL_BIND_REQ; bind_req.dl_sap = sap; bind_req.dl_max_conind = max_conind; bind_req.dl_service_mode = service_mode; bind_req.dl_conn_mgmt = conn_mgmt; bind_req.dl_xidtest_flg = xidtest; ctl.maxlen = 0; ctl.len = sizeof (bind_req); ctl.buf = (char *)&bind_req; flags = 0; return putmsg (fd, &ctl, (struct strbuf*)NULL, flags); } /* * dlpiunbindreq - send a request to unbind. */ static int dlpiunbindreq (fd) int fd; { dl_unbind_req_t unbind_req; struct strbuf ctl; int flags; unbind_req.dl_primitive = DL_UNBIND_REQ; ctl.maxlen = 0; ctl.len = sizeof (unbind_req); ctl.buf = (char *)&unbind_req; flags = 0; return putmsg (fd, &ctl, (struct strbuf*)NULL, flags); } /* * dlpidetachreq - send a request to detach. */ static int dlpidetachreq (fd) int fd; { dl_detach_req_t detach_req; struct strbuf ctl; int flags; detach_req.dl_primitive = DL_DETACH_REQ; ctl.maxlen = 0; ctl.len = sizeof (detach_req); ctl.buf = (char *)&detach_req; flags = 0; return putmsg (fd, &ctl, (struct strbuf*)NULL, flags); } /* * dlpibindack - receive an ack to a dlbindreq. */ static int dlpibindack (fd, bufp) char *bufp; int fd; { union DL_primitives *dlp; struct strbuf ctl; int flags; ctl.maxlen = DLPI_MAXDLBUF; ctl.len = 0; ctl.buf = bufp; if (strgetmsg (fd, &ctl, (struct strbuf*)NULL, &flags, "dlpibindack") < 0) { return -1; } dlp = (union DL_primitives *)ctl.buf; if (!expected (DL_BIND_ACK, dlp, flags) < 0) { return -1; } if (ctl.len < sizeof (dl_bind_ack_t)) { /* Returned structure is too short */ return -1; } return 0; } /* * dlpiokack - general acknowledgement reception. */ static int dlpiokack (fd, bufp) char *bufp; int fd; { union DL_primitives *dlp; struct strbuf ctl; int flags; ctl.maxlen = DLPI_MAXDLBUF; ctl.len = 0; ctl.buf = bufp; if (strgetmsg (fd, &ctl, (struct strbuf*)NULL, &flags, "dlpiokack") < 0) { return -1; } dlp = (union DL_primitives *)ctl.buf; if (!expected (DL_OK_ACK, dlp, flags) < 0) { return -1; } if (ctl.len < sizeof (dl_ok_ack_t)) { /* Returned structure is too short */ return -1; } return 0; } /* * dlpiinfoack - receive an ack to a dlinforeq. */ static int dlpiinfoack (fd, bufp) char *bufp; int fd; { union DL_primitives *dlp; struct strbuf ctl; int flags; ctl.maxlen = DLPI_MAXDLBUF; ctl.len = 0; ctl.buf = bufp; if (strgetmsg (fd, &ctl, (struct strbuf *)NULL, &flags, "dlpiinfoack") < 0) { return -1; } dlp = (union DL_primitives *) ctl.buf; if (!expected (DL_INFO_ACK, dlp, flags) < 0) { return -1; } if (ctl.len < sizeof (dl_info_ack_t)) { /* Returned structure is too short */ return -1; } return 0; } /* * dlpiphysaddrack - receive an ack to a dlpiphysaddrreq. */ int dlpiphysaddrack (fd, bufp) char *bufp; int fd; { union DL_primitives *dlp; struct strbuf ctl; int flags; ctl.maxlen = DLPI_MAXDLBUF; ctl.len = 0; ctl.buf = bufp; if (strgetmsg (fd, &ctl, (struct strbuf *)NULL, &flags, "dlpiphysaddrack") < 0) { return -1; } dlp = (union DL_primitives *)ctl.buf; if (!expected (DL_PHYS_ADDR_ACK, dlp, flags) < 0) { return -1; } if (ctl.len < sizeof (dl_phys_addr_ack_t)) { /* Returned structure is too short */ return -1; } return 0; } int dlpiunitdatareq (fd, addr, addrlen, minpri, maxpri, dbuf, dbuflen) int fd; unsigned char *addr; int addrlen; unsigned long minpri; unsigned long maxpri; unsigned char *dbuf; int dbuflen; { long buf [DLPI_MAXDLBUF]; union DL_primitives *dlp; struct strbuf ctl, data; /* Set up the control information... */ dlp = (union DL_primitives *)buf; dlp -> unitdata_req.dl_primitive = DL_UNITDATA_REQ; dlp -> unitdata_req.dl_dest_addr_length = addrlen; dlp -> unitdata_req.dl_dest_addr_offset = sizeof (dl_unitdata_req_t); dlp -> unitdata_req.dl_priority.dl_min = minpri; dlp -> unitdata_req.dl_priority.dl_max = maxpri; /* Append the destination address */ memcpy ((char *)buf + dlp -> unitdata_req.dl_dest_addr_offset, addr, addrlen); ctl.maxlen = 0; ctl.len = dlp -> unitdata_req.dl_dest_addr_offset + addrlen; ctl.buf = (char *)buf; data.maxlen = 0; data.buf = (char *)dbuf; data.len = dbuflen; /* Send the packet down the wire... */ return putmsg (fd, &ctl, &data, 0); } static int dlpiunitdataind (fd, daddr, daddrlen, saddr, saddrlen, grpaddr, dbuf, dlen) int fd; unsigned char *daddr; unsigned long *daddrlen; unsigned char *saddr; unsigned long *saddrlen; unsigned long *grpaddr; unsigned char *dbuf; int dlen; { long buf [DLPI_MAXDLBUF]; union DL_primitives *dlp; struct strbuf ctl, data; int flags = 0; int result; /* Set up the msg_buf structure... */ dlp = (union DL_primitives *)buf; dlp -> unitdata_ind.dl_primitive = DL_UNITDATA_IND; ctl.maxlen = DLPI_MAXDLBUF; ctl.len = 0; ctl.buf = (char *)buf; data.maxlen = dlen; data.len = 0; data.buf = (char *)dbuf; result = getmsg (fd, &ctl, &data, &flags); if (result != 0) { return -1; } if (ctl.len < sizeof (dl_unitdata_ind_t) || dlp -> unitdata_ind.dl_primitive != DL_UNITDATA_IND) { return -1; } if (data.len <= 0) { return data.len; } /* Copy sender info */ if (saddr) { memcpy (saddr, (char *)buf + dlp -> unitdata_ind.dl_src_addr_offset, dlp -> unitdata_ind.dl_src_addr_length); } if (saddrlen) { *saddrlen = dlp -> unitdata_ind.dl_src_addr_length; } /* Copy destination info */ if (daddr) { memcpy (daddr, (char *)buf + dlp -> unitdata_ind.dl_dest_addr_offset, dlp -> unitdata_ind.dl_dest_addr_length); } if (daddrlen) { *daddrlen = dlp -> unitdata_ind.dl_dest_addr_length; } if (grpaddr) { *grpaddr = dlp -> unitdata_ind.dl_group_address; } return data.len; } /* * expected - see if we got what we wanted. */ static int expected (prim, dlp, msgflags) unsigned long prim; union DL_primitives *dlp; int msgflags; { if (msgflags != RS_HIPRI) { /* Message was not M_PCPROTO */ return 0; } if (dlp -> dl_primitive != prim) { /* Incorrect/unexpected return message */ return 0; } return 1; } /* * strgetmsg - get a message from a stream, with timeout. */ static int strgetmsg (fd, ctlp, datap, flagsp, caller) struct strbuf *ctlp, *datap; char *caller; int *flagsp; int fd; { int result; #ifdef USE_POLL struct pollfd pfd; int count; time_t now; time_t starttime; int to_msec; #endif #ifdef USE_POLL pfd.fd = fd; pfd.events = POLLPRI; /* We're only interested in knowing * when we can receive the next high * priority message. */ pfd.revents = 0; now = time (&starttime); while (now <= starttime + DLPI_MAXWAIT) { to_msec = ((starttime + DLPI_MAXWAIT) - now) * 1000; count = poll (&pfd, 1, to_msec); if (count == 0) { /* log_fatal ("strgetmsg: timeout"); */ return -1; } else if (count < 0) { if (errno == EAGAIN || errno == EINTR) { time (&now); continue; } else { /* log_fatal ("poll: %m"); */ return -1; } } else { break; } } #else /* defined (USE_POLL) */ /* * Start timer. Can't use select, since it might return true if there * were non High-Priority data available on the stream. */ (void) sigset (SIGALRM, sigalrm); if (alarm (DLPI_MAXWAIT) < 0) { /* log_fatal ("alarm: %m"); */ return -1; } #endif /* !defined (USE_POLL) */ /* * Set flags argument and issue getmsg (). */ *flagsp = 0; if ((result = getmsg (fd, ctlp, datap, flagsp)) < 0) { return result; } #ifndef USE_POLL /* * Stop timer. */ if (alarm (0) < 0) { /* log_fatal ("alarm: %m"); */ return -1; } #endif /* * Check for MOREDATA and/or MORECTL. */ if (result & (MORECTL|MOREDATA)) { return -1; } /* * Check for at least sizeof (long) control data portion. */ if (ctlp -> len < sizeof (long)) { return -1; } return 0; } #ifndef USE_POLL /* * sigalrm - handle alarms. */ static void sigalrm (sig) int sig; { fprintf (stderr, "strgetmsg: timeout"); exit (1); } #endif /* !defined (USE_POLL) */ int can_unicast_without_arp (ip) struct interface_info *ip; { return 1; } int can_receive_unicast_unconfigured (ip) struct interface_info *ip; { return 1; } int supports_multiple_interfaces (ip) struct interface_info *ip; { return 1; } void maybe_setup_fallback () { isc_result_t status; struct interface_info *fbi = (struct interface_info *)0; if (setup_fallback (&fbi, MDL)) { if_register_fallback (fbi); 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 /* USE_DLPI */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/dns.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/dns.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/dns.c (revision 131136) @@ -1,972 +1,953 @@ /* dns.c Domain Name Service subroutines. */ /* - * Copyright (c) 2001-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2001-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems Consortium, see * ``http://www.isc.org/''. To learn more about Nominum, Inc., see * ``http://www.nominum.com''. */ #ifndef lint static char copyright[] = -"$Id: dns.c,v 1.35.2.13 2002/11/17 02:26:57 dhankins Exp $ Copyright (c) 2001-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: dns.c,v 1.35.2.16 2004/06/17 20:54:38 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #include "arpa/nameser.h" #include "dst/md5.h" /* This file is kind of a crutch for the BIND 8 nsupdate code, which has * itself been cruelly hacked from its original state. What this code * does is twofold: first, it maintains a database of zone cuts that can * be used to figure out which server should be contacted to update any * given domain name. Secondly, it maintains a set of named TSIG keys, * and associates those keys with zones. When an update is requested for * a particular zone, the key associated with that zone is used for the * update. * * The way this works is that you define the domain name to which an * SOA corresponds, and the addresses of some primaries for that domain name: * * zone FOO.COM { * primary 10.0.17.1; * secondary 10.0.22.1, 10.0.23.1; * key "FOO.COM Key"; * } * * If an update is requested for GAZANGA.TOPANGA.FOO.COM, then the name * server looks in its database for a zone record for "GAZANGA.TOPANGA.FOO.COM", * doesn't find it, looks for one for "TOPANGA.FOO.COM", doesn't find *that*, * looks for "FOO.COM", finds it. So it * attempts the update to the primary for FOO.COM. If that times out, it * tries the secondaries. You can list multiple primaries if you have some * kind of magic name server that supports that. You shouldn't list * secondaries that don't know how to forward updates (e.g., BIND 8 doesn't * support update forwarding, AFAIK). If no TSIG key is listed, the update * is attempted without TSIG. * * The DHCP server tries to find an existing zone for any given name by * trying to look up a local zone structure for each domain containing * that name, all the way up to '.'. If it finds one cached, it tries * to use that one to do the update. That's why it tries to update * "FOO.COM" above, even though theoretically it should try GAZANGA... * and TOPANGA... first. * * If the update fails with a predefined or cached zone (we'll get to * those in a second), then it tries to find a more specific zone. This * is done by looking first for an SOA for GAZANGA.TOPANGA.FOO.COM. Then * an SOA for TOPANGA.FOO.COM is sought. If during this search a predefined * or cached zone is found, the update fails - there's something wrong * somewhere. * * If a more specific zone _is_ found, that zone is cached for the length of * its TTL in the same database as that described above. TSIG updates are * never done for cached zones - if you want TSIG updates you _must_ * write a zone definition linking the key to the zone. In cases where you * know for sure what the key is but do not want to hardcode the IP addresses * of the primary or secondaries, a zone declaration can be made that doesn't * include any primary or secondary declarations. When the DHCP server * encounters this while hunting up a matching zone for a name, it looks up * the SOA, fills in the IP addresses, and uses that record for the update. * If the SOA lookup returns NXRRSET, a warning is printed and the zone is * discarded, TSIG key and all. The search for the zone then continues as if * the zone record hadn't been found. Zones without IP addresses don't * match when initially hunting for a predefined or cached zone to update. * * When an update is attempted and no predefined or cached zone is found * that matches any enclosing domain of the domain being updated, the DHCP * server goes through the same process that is done when the update to a * predefined or cached zone fails - starting with the most specific domain * name (GAZANGA.TOPANGA.FOO.COM) and moving to the least specific (the root), * it tries to look up an SOA record. When it finds one, it creates a cached * zone and attempts an update, and gives up if the update fails. * * TSIG keys are defined like this: * * key "FOO.COM Key" { * algorithm HMAC-MD5.SIG-ALG.REG.INT; * secret ; * } * * is a number expressed in base64 that represents the key. * It's also permissible to use a quoted string here - this will be * translated as the ASCII bytes making up the string, and will not * include any NUL termination. The key name can be any text string, * and the key type must be one of the key types defined in the draft * or by the IANA. Currently only the HMAC-MD5... key type is * supported. */ dns_zone_hash_t *dns_zone_hash; #if defined (NSUPDATE) isc_result_t find_tsig_key (ns_tsig_key **key, const char *zname, struct dns_zone *zone) { isc_result_t status; ns_tsig_key *tkey; if (!zone) return ISC_R_NOTFOUND; if (!zone -> key) { return ISC_R_KEY_UNKNOWN; } if ((!zone -> key -> name || strlen (zone -> key -> name) > NS_MAXDNAME) || (!zone -> key -> algorithm || strlen (zone -> key -> algorithm) > NS_MAXDNAME) || (!zone -> key) || (!zone -> key -> key) || (zone -> key -> key -> len == 0)) { return ISC_R_INVALIDKEY; } tkey = dmalloc (sizeof *tkey, MDL); if (!tkey) { nomem: return ISC_R_NOMEMORY; } memset (tkey, 0, sizeof *tkey); tkey -> data = dmalloc (zone -> key -> key -> len, MDL); if (!tkey -> data) { dfree (tkey, MDL); goto nomem; } strcpy (tkey -> name, zone -> key -> name); strcpy (tkey -> alg, zone -> key -> algorithm); memcpy (tkey -> data, zone -> key -> key -> value, zone -> key -> key -> len); tkey -> len = zone -> key -> key -> len; *key = tkey; return ISC_R_SUCCESS; } void tkey_free (ns_tsig_key **key) { if ((*key) -> data) dfree ((*key) -> data, MDL); dfree ((*key), MDL); *key = (ns_tsig_key *)0; } #endif isc_result_t enter_dns_zone (struct dns_zone *zone) { struct dns_zone *tz = (struct dns_zone *)0; if (dns_zone_hash) { dns_zone_hash_lookup (&tz, dns_zone_hash, zone -> name, 0, MDL); if (tz == zone) { dns_zone_dereference (&tz, MDL); return ISC_R_SUCCESS; } if (tz) { dns_zone_hash_delete (dns_zone_hash, zone -> name, 0, MDL); dns_zone_dereference (&tz, MDL); } } else { if (!dns_zone_new_hash (&dns_zone_hash, 1, MDL)) return ISC_R_NOMEMORY; } dns_zone_hash_add (dns_zone_hash, zone -> name, 0, zone, MDL); return ISC_R_SUCCESS; } isc_result_t dns_zone_lookup (struct dns_zone **zone, const char *name) { struct dns_zone *tz = (struct dns_zone *)0; int len; char *tname = (char *)0; isc_result_t status; if (!dns_zone_hash) return ISC_R_NOTFOUND; len = strlen (name); if (name [len - 1] != '.') { tname = dmalloc ((unsigned)len + 2, MDL); if (!tname) return ISC_R_NOMEMORY;; strcpy (tname, name); tname [len] = '.'; tname [len + 1] = 0; name = tname; } if (!dns_zone_hash_lookup (zone, dns_zone_hash, name, 0, MDL)) status = ISC_R_NOTFOUND; else status = ISC_R_SUCCESS; if (tname) dfree (tname, MDL); return status; } int dns_zone_dereference (ptr, file, line) struct dns_zone **ptr; const char *file; int line; { int i; struct dns_zone *dns_zone; if (!ptr || !*ptr) { log_error ("%s(%d): null pointer", file, line); #if defined (POINTER_DEBUG) abort (); #else return 0; #endif } dns_zone = *ptr; *ptr = (struct dns_zone *)0; --dns_zone -> refcnt; rc_register (file, line, ptr, dns_zone, dns_zone -> refcnt, 1, RC_MISC); if (dns_zone -> refcnt > 0) return 1; if (dns_zone -> refcnt < 0) { log_error ("%s(%d): negative refcnt!", file, line); #if defined (DEBUG_RC_HISTORY) dump_rc_history (dns_zone); #endif #if defined (POINTER_DEBUG) abort (); #else return 0; #endif } if (dns_zone -> name) dfree (dns_zone -> name, file, line); if (dns_zone -> key) omapi_auth_key_dereference (&dns_zone -> key, file, line); if (dns_zone -> primary) option_cache_dereference (&dns_zone -> primary, file, line); if (dns_zone -> secondary) option_cache_dereference (&dns_zone -> secondary, file, line); dfree (dns_zone, file, line); return 1; } #if defined (NSUPDATE) isc_result_t find_cached_zone (const char *dname, ns_class class, char *zname, size_t zsize, struct in_addr *addrs, int naddrs, int *naddrout, struct dns_zone **zcookie) { isc_result_t status = ISC_R_NOTFOUND; const char *np; struct dns_zone *zone = (struct dns_zone *)0; struct data_string nsaddrs; int ix; /* The absence of the zcookie pointer indicates that we succeeded previously, but the update itself failed, meaning that we shouldn't use the cached zone. */ if (!zcookie) return ISC_R_NOTFOUND; /* We can't look up a null zone. */ if (!dname || !*dname) return ISC_R_INVALIDARG; /* For each subzone, try to find a cached zone. */ for (np = dname; np; np = strchr (np, '.')) { np++; status = dns_zone_lookup (&zone, np); if (status == ISC_R_SUCCESS) break; } if (status != ISC_R_SUCCESS) return status; /* Make sure the zone is valid. */ if (zone -> timeout && zone -> timeout < cur_time) { dns_zone_dereference (&zone, MDL); return ISC_R_CANCELED; } /* Make sure the zone name will fit. */ if (strlen (zone -> name) > zsize) { dns_zone_dereference (&zone, MDL); return ISC_R_NOSPACE; } strcpy (zname, zone -> name); memset (&nsaddrs, 0, sizeof nsaddrs); ix = 0; if (zone -> primary) { if (evaluate_option_cache (&nsaddrs, (struct packet *)0, (struct lease *)0, (struct client_state *)0, (struct option_state *)0, (struct option_state *)0, &global_scope, zone -> primary, MDL)) { int ip = 0; while (ix < naddrs) { if (ip + 4 > nsaddrs.len) break; memcpy (&addrs [ix], &nsaddrs.data [ip], 4); ip += 4; ix++; } data_string_forget (&nsaddrs, MDL); } } if (zone -> secondary) { if (evaluate_option_cache (&nsaddrs, (struct packet *)0, (struct lease *)0, (struct client_state *)0, (struct option_state *)0, (struct option_state *)0, &global_scope, zone -> secondary, MDL)) { int ip = 0; while (ix < naddrs) { if (ip + 4 > nsaddrs.len) break; memcpy (&addrs [ix], &nsaddrs.data [ip], 4); ip += 4; ix++; } data_string_forget (&nsaddrs, MDL); } } /* It's not an error for zcookie to have a value here - actually, it's quite likely, because res_nupdate cycles through all the names in the update looking for their zones. */ if (!*zcookie) dns_zone_reference (zcookie, zone, MDL); dns_zone_dereference (&zone, MDL); if (naddrout) *naddrout = ix; return ISC_R_SUCCESS; } void forget_zone (struct dns_zone **zone) { dns_zone_dereference (zone, MDL); } void repudiate_zone (struct dns_zone **zone) { /* XXX Currently we're not differentiating between a cached XXX zone and a zone that's been repudiated, which means XXX that if we reap cached zones, we blow away repudiated XXX zones. This isn't a big problem since we're not yet XXX caching zones... :'} */ (*zone) -> timeout = cur_time - 1; dns_zone_dereference (zone, MDL); } void cache_found_zone (ns_class class, char *zname, struct in_addr *addrs, int naddrs) { isc_result_t status = ISC_R_NOTFOUND; struct dns_zone *zone = (struct dns_zone *)0; struct data_string nsaddrs; int ix = strlen (zname); if (zname [ix - 1] == '.') ix = 0; /* See if there's already such a zone. */ if (dns_zone_lookup (&zone, zname) == ISC_R_SUCCESS) { /* If it's not a dynamic zone, leave it alone. */ if (!zone -> timeout) return; /* Address may have changed, so just blow it away. */ if (zone -> primary) option_cache_dereference (&zone -> primary, MDL); if (zone -> secondary) option_cache_dereference (&zone -> secondary, MDL); } else if (!dns_zone_allocate (&zone, MDL)) return; if (!zone -> name) { zone -> name = dmalloc (strlen (zname) + 1 + (ix != 0), MDL); if (!zone -> name) { dns_zone_dereference (&zone, MDL); return; } strcpy (zone -> name, zname); /* Add a trailing '.' if it was missing. */ if (ix) { zone -> name [ix] = '.'; zone -> name [ix + 1] = 0; } } /* XXX Need to get the lower-level code to push the actual zone XXX TTL up to us. */ zone -> timeout = cur_time + 1800; if (!option_cache_allocate (&zone -> primary, MDL)) { dns_zone_dereference (&zone, MDL); return; } if (!buffer_allocate (&zone -> primary -> data.buffer, naddrs * sizeof (struct in_addr), MDL)) { dns_zone_dereference (&zone, MDL); return; } memcpy (zone -> primary -> data.buffer -> data, addrs, naddrs * sizeof *addrs); zone -> primary -> data.data = &zone -> primary -> data.buffer -> data [0]; zone -> primary -> data.len = naddrs * sizeof *addrs; enter_dns_zone (zone); } /* Have to use TXT records for now. */ #define T_DHCID T_TXT int get_dhcid (struct data_string *id, int type, const u_int8_t *data, unsigned len) { unsigned char buf[MD5_DIGEST_LENGTH]; MD5_CTX md5; int i; /* Types can only be 0..(2^16)-1. */ if (type < 0 || type > 65535) return 0; /* Hexadecimal MD5 digest plus two byte type and NUL. */ if (!buffer_allocate (&id -> buffer, (MD5_DIGEST_LENGTH * 2) + 3, MDL)) return 0; id -> data = id -> buffer -> data; /* * DHCP clients and servers should use the following forms of client * identification, starting with the most preferable, and finishing * with the least preferable. If the client does not send any of these * forms of identification, the DHCP/DDNS interaction is not defined by * this specification. The most preferable form of identification is * the Globally Unique Identifier Option [TBD]. Next is the DHCP * Client Identifier option. Last is the client's link-layer address, * as conveyed in its DHCPREQUEST message. Implementors should note * that the link-layer address cannot be used if there are no * significant bytes in the chaddr field of the DHCP client's request, * because this does not constitute a unique identifier. * -- "Interaction between DHCP and DNS" * * M. Stapp, Y. Rekhter */ /* Put the type in the first two bytes. */ id -> buffer -> data [0] = "0123456789abcdef" [type >> 4]; id -> buffer -> data [1] = "0123456789abcdef" [type % 15]; /* Mash together an MD5 hash of the identifier. */ MD5_Init (&md5); MD5_Update (&md5, data, len); MD5_Final (buf, &md5); /* Convert into ASCII. */ for (i = 0; i < MD5_DIGEST_LENGTH; i++) { id -> buffer -> data [i * 2 + 2] = "0123456789abcdef" [(buf [i] >> 4) & 0xf]; id -> buffer -> data [i * 2 + 3] = "0123456789abcdef" [buf [i] & 0xf]; } id -> len = MD5_DIGEST_LENGTH * 2 + 2; id -> buffer -> data [id -> len] = 0; id -> terminated = 1; return 1; } /* Now for the DDNS update code that is shared between client and server... */ isc_result_t ddns_update_a (struct data_string *ddns_fwd_name, struct iaddr ddns_addr, struct data_string *ddns_dhcid, unsigned long ttl, int rrsetp) { ns_updque updqueue; ns_updrec *updrec; isc_result_t result; char ddns_address [16]; if (ddns_addr.len != 4) return ISC_R_INVALIDARG; -#ifndef NO_SNPRINTF - snprintf (ddns_address, 16, "%d.%d.%d.%d", + + /* %Audit% Cannot exceed 16 bytes. %2004.06.17,Safe% */ + sprintf (ddns_address, "%u.%u.%u.%u", ddns_addr.iabuf[0], ddns_addr.iabuf[1], ddns_addr.iabuf[2], ddns_addr.iabuf[3]); -#else - sprintf (ddns_address, "%d.%d.%d.%d", - ddns_addr.iabuf[0], ddns_addr.iabuf[1], - ddns_addr.iabuf[2], ddns_addr.iabuf[3]); -#endif /* * When a DHCP client or server intends to update an A RR, it first * prepares a DNS UPDATE query which includes as a prerequisite the * assertion that the name does not exist. The update section of the * query attempts to add the new name and its IP address mapping (an A * RR), and the DHCID RR with its unique client-identity. * -- "Interaction between DHCP and DNS" */ ISC_LIST_INIT (updqueue); /* * A RR does not exist. */ updrec = minires_mkupdrec (S_PREREQ, (const char *)ddns_fwd_name -> data, C_IN, T_A, 0); if (!updrec) { result = ISC_R_NOMEMORY; goto error; } updrec -> r_data = (unsigned char *)0; updrec -> r_size = 0; updrec -> r_opcode = rrsetp ? NXRRSET : NXDOMAIN; ISC_LIST_APPEND (updqueue, updrec, r_link); /* * Add A RR. */ updrec = minires_mkupdrec (S_UPDATE, (const char *)ddns_fwd_name -> data, C_IN, T_A, ttl); if (!updrec) { result = ISC_R_NOMEMORY; goto error; } updrec -> r_data = (unsigned char *)ddns_address; updrec -> r_size = strlen (ddns_address); updrec -> r_opcode = ADD; ISC_LIST_APPEND (updqueue, updrec, r_link); /* * Add DHCID RR. */ updrec = minires_mkupdrec (S_UPDATE, (const char *)ddns_fwd_name -> data, C_IN, T_DHCID, ttl); if (!updrec) { result = ISC_R_NOMEMORY; goto error; } updrec -> r_data = ddns_dhcid -> data; updrec -> r_size = ddns_dhcid -> len; updrec -> r_opcode = ADD; ISC_LIST_APPEND (updqueue, updrec, r_link); /* * Attempt to perform the update. */ result = minires_nupdate (&resolver_state, ISC_LIST_HEAD (updqueue)); #ifdef DEBUG_DNS_UPDATES print_dns_status ((int)result, &updqueue); #endif /* * If this update operation succeeds, the updater can conclude that it * has added a new name whose only RRs are the A and DHCID RR records. * The A RR update is now complete (and a client updater is finished, * while a server might proceed to perform a PTR RR update). * -- "Interaction between DHCP and DNS" */ if (result == ISC_R_SUCCESS) { log_info ("Added new forward map from %.*s to %s", (int)ddns_fwd_name -> len, (const char *)ddns_fwd_name -> data, ddns_address); goto error; } /* * If the first update operation fails with YXDOMAIN, the updater can * conclude that the intended name is in use. The updater then * attempts to confirm that the DNS name is not being used by some * other host. The updater prepares a second UPDATE query in which the * prerequisite is that the desired name has attached to it a DHCID RR * whose contents match the client identity. The update section of * this query deletes the existing A records on the name, and adds the * A record that matches the DHCP binding and the DHCID RR with the * client identity. * -- "Interaction between DHCP and DNS" */ if (result != (rrsetp ? ISC_R_YXRRSET : ISC_R_YXDOMAIN)) { log_error ("Unable to add forward map from %.*s to %s: %s", (int)ddns_fwd_name -> len, (const char *)ddns_fwd_name -> data, ddns_address, isc_result_totext (result)); goto error; } while (!ISC_LIST_EMPTY (updqueue)) { updrec = ISC_LIST_HEAD (updqueue); ISC_LIST_UNLINK (updqueue, updrec, r_link); minires_freeupdrec (updrec); } /* * DHCID RR exists, and matches client identity. */ updrec = minires_mkupdrec (S_PREREQ, (const char *)ddns_fwd_name -> data, C_IN, T_DHCID, 0); if (!updrec) { result = ISC_R_NOMEMORY; goto error; } updrec -> r_data = ddns_dhcid -> data; updrec -> r_size = ddns_dhcid -> len; updrec -> r_opcode = YXRRSET; ISC_LIST_APPEND (updqueue, updrec, r_link); /* * Delete A RRset. */ updrec = minires_mkupdrec (S_UPDATE, (const char *)ddns_fwd_name -> data, C_IN, T_A, 0); if (!updrec) { result = ISC_R_NOMEMORY; goto error; } updrec -> r_data = (unsigned char *)0; updrec -> r_size = 0; updrec -> r_opcode = DELETE; ISC_LIST_APPEND (updqueue, updrec, r_link); /* * Add A RR. */ updrec = minires_mkupdrec (S_UPDATE, (const char *)ddns_fwd_name -> data, C_IN, T_A, ttl); if (!updrec) { result = ISC_R_NOMEMORY; goto error; } updrec -> r_data = (unsigned char *)ddns_address; updrec -> r_size = strlen (ddns_address); updrec -> r_opcode = ADD; ISC_LIST_APPEND (updqueue, updrec, r_link); /* * Attempt to perform the update. */ result = minires_nupdate (&resolver_state, ISC_LIST_HEAD (updqueue)); if (result != ISC_R_SUCCESS) { if (result == YXRRSET || result == YXDOMAIN || result == NXRRSET || result == NXDOMAIN) log_error ("Forward map from %.*s to %s already in use", (int)ddns_fwd_name -> len, (const char *)ddns_fwd_name -> data, ddns_address); else log_error ("Can't update forward map %.*s to %s: %s", (int)ddns_fwd_name -> len, (const char *)ddns_fwd_name -> data, ddns_address, isc_result_totext (result)); } else { log_info ("Added new forward map from %.*s to %s", (int)ddns_fwd_name -> len, (const char *)ddns_fwd_name -> data, ddns_address); } #if defined (DEBUG_DNS_UPDATES) print_dns_status ((int)result, &updqueue); #endif /* * If this query succeeds, the updater can conclude that the current * client was the last client associated with the domain name, and that * the name now contains the updated A RR. The A RR update is now * complete (and a client updater is finished, while a server would * then proceed to perform a PTR RR update). * -- "Interaction between DHCP and DNS" */ /* * If the second query fails with NXRRSET, the updater must conclude * that the client's desired name is in use by another host. At this * juncture, the updater can decide (based on some administrative * configuration outside of the scope of this document) whether to let * the existing owner of the name keep that name, and to (possibly) * perform some name disambiguation operation on behalf of the current * client, or to replace the RRs on the name with RRs that represent * the current client. If the configured policy allows replacement of * existing records, the updater submits a query that deletes the * existing A RR and the existing DHCID RR, adding A and DHCID RRs that * represent the IP address and client-identity of the new client. * -- "Interaction between DHCP and DNS" */ error: while (!ISC_LIST_EMPTY (updqueue)) { updrec = ISC_LIST_HEAD (updqueue); ISC_LIST_UNLINK (updqueue, updrec, r_link); minires_freeupdrec (updrec); } return result; } isc_result_t ddns_remove_a (struct data_string *ddns_fwd_name, struct iaddr ddns_addr, struct data_string *ddns_dhcid) { ns_updque updqueue; ns_updrec *updrec; isc_result_t result = SERVFAIL; char ddns_address [16]; if (ddns_addr.len != 4) return ISC_R_INVALIDARG; -#ifndef NO_SNPRINTF - snprintf (ddns_address, 16, "%d.%d.%d.%d", + /* %Audit% Cannot exceed 16 bytes. %2004.06.17,Safe% */ + sprintf (ddns_address, "%u.%u.%u.%u", ddns_addr.iabuf[0], ddns_addr.iabuf[1], ddns_addr.iabuf[2], ddns_addr.iabuf[3]); -#else - sprintf (ddns_address, "%d.%d.%d.%d", - ddns_addr.iabuf[0], ddns_addr.iabuf[1], - ddns_addr.iabuf[2], ddns_addr.iabuf[3]); -#endif - /* * The entity chosen to handle the A record for this client (either the * client or the server) SHOULD delete the A record that was added when * the lease was made to the client. * * In order to perform this delete, the updater prepares an UPDATE * query which contains two prerequisites. The first prerequisite * asserts that the DHCID RR exists whose data is the client identity * described in Section 4.3. The second prerequisite asserts that the * data in the A RR contains the IP address of the lease that has * expired or been released. * -- "Interaction between DHCP and DNS" */ ISC_LIST_INIT (updqueue); /* * DHCID RR exists, and matches client identity. */ updrec = minires_mkupdrec (S_PREREQ, (const char *)ddns_fwd_name -> data, C_IN, T_DHCID,0); if (!updrec) { result = ISC_R_NOMEMORY; goto error; } updrec -> r_data = ddns_dhcid -> data; updrec -> r_size = ddns_dhcid -> len; updrec -> r_opcode = YXRRSET; ISC_LIST_APPEND (updqueue, updrec, r_link); /* * A RR matches the expiring lease. */ updrec = minires_mkupdrec (S_PREREQ, (const char *)ddns_fwd_name -> data, C_IN, T_A, 0); if (!updrec) { result = ISC_R_NOMEMORY; goto error; } updrec -> r_data = (unsigned char *)ddns_address; updrec -> r_size = strlen (ddns_address); updrec -> r_opcode = YXRRSET; ISC_LIST_APPEND (updqueue, updrec, r_link); /* * Delete appropriate A RR. */ updrec = minires_mkupdrec (S_UPDATE, (const char *)ddns_fwd_name -> data, C_IN, T_A, 0); if (!updrec) { result = ISC_R_NOMEMORY; goto error; } updrec -> r_data = (unsigned char *)ddns_address; updrec -> r_size = strlen (ddns_address); updrec -> r_opcode = DELETE; ISC_LIST_APPEND (updqueue, updrec, r_link); /* * Attempt to perform the update. */ result = minires_nupdate (&resolver_state, ISC_LIST_HEAD (updqueue)); print_dns_status ((int)result, &updqueue); /* * If the query fails, the updater MUST NOT delete the DNS name. It * may be that the host whose lease on the server has expired has moved * to another network and obtained a lease from a different server, * which has caused the client's A RR to be replaced. It may also be * that some other client has been configured with a name that matches * the name of the DHCP client, and the policy was that the last client * to specify the name would get the name. In this case, the DHCID RR * will no longer match the updater's notion of the client-identity of * the host pointed to by the DNS name. * -- "Interaction between DHCP and DNS" */ if (result != ISC_R_SUCCESS) { /* If the rrset isn't there, we didn't need to do the delete, which is success. */ if (result == ISC_R_NXRRSET || result == ISC_R_NXDOMAIN) result = ISC_R_SUCCESS; goto error; } while (!ISC_LIST_EMPTY (updqueue)) { updrec = ISC_LIST_HEAD (updqueue); ISC_LIST_UNLINK (updqueue, updrec, r_link); minires_freeupdrec (updrec); } /* If the deletion of the A succeeded, and there are no A records left for this domain, then we can blow away the DHCID record as well. We can't blow away the DHCID record above because it's possible that more than one A has been added to this domain name. */ ISC_LIST_INIT (updqueue); /* * A RR does not exist. */ updrec = minires_mkupdrec (S_PREREQ, (const char *)ddns_fwd_name -> data, C_IN, T_A, 0); if (!updrec) { result = ISC_R_NOMEMORY; goto error; } updrec -> r_data = (unsigned char *)0; updrec -> r_size = 0; updrec -> r_opcode = NXRRSET; ISC_LIST_APPEND (updqueue, updrec, r_link); /* * Delete appropriate DHCID RR. */ updrec = minires_mkupdrec (S_UPDATE, (const char *)ddns_fwd_name -> data, C_IN, T_DHCID, 0); if (!updrec) { result = ISC_R_NOMEMORY; goto error; } updrec -> r_data = ddns_dhcid -> data; updrec -> r_size = ddns_dhcid -> len; updrec -> r_opcode = DELETE; ISC_LIST_APPEND (updqueue, updrec, r_link); /* * Attempt to perform the update. */ result = minires_nupdate (&resolver_state, ISC_LIST_HEAD (updqueue)); print_dns_status ((int)result, &updqueue); /* Fall through. */ error: while (!ISC_LIST_EMPTY (updqueue)) { updrec = ISC_LIST_HEAD (updqueue); ISC_LIST_UNLINK (updqueue, updrec, r_link); minires_freeupdrec (updrec); } return result; } #endif /* NSUPDATE */ HASH_FUNCTIONS (dns_zone, const char *, struct dns_zone, dns_zone_hash_t, dns_zone_reference, dns_zone_dereference) Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/ethernet.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/ethernet.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/ethernet.c (revision 131136) @@ -1,107 +1,98 @@ /* ethernet.c Packet assembly code, originally contributed by Archie Cobbs. */ /* - * Copyright (c) 1996-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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: ethernet.c,v 1.6.2.2 2002/11/17 02:26:57 dhankins Exp $ Copyright (c) 1996-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: ethernet.c,v 1.6.2.3 2004/06/10 17:59:17 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #if defined (PACKET_ASSEMBLY) || defined (PACKET_DECODING) #include "includes/netinet/if_ether.h" #endif /* PACKET_ASSEMBLY || PACKET_DECODING */ #if defined (PACKET_ASSEMBLY) /* Assemble an hardware header... */ void assemble_ethernet_header (interface, buf, bufix, to) struct interface_info *interface; unsigned char *buf; unsigned *bufix; struct hardware *to; { struct isc_ether_header eh; if (to && to -> hlen == 7) /* XXX */ memcpy (eh.ether_dhost, &to -> hbuf [1], sizeof eh.ether_dhost); else memset (eh.ether_dhost, 0xff, sizeof (eh.ether_dhost)); if (interface -> hw_address.hlen - 1 == sizeof (eh.ether_shost)) memcpy (eh.ether_shost, &interface -> hw_address.hbuf [1], sizeof (eh.ether_shost)); else memset (eh.ether_shost, 0x00, sizeof (eh.ether_shost)); eh.ether_type = htons (ETHERTYPE_IP); memcpy (&buf [*bufix], &eh, ETHER_HEADER_SIZE); *bufix += ETHER_HEADER_SIZE; } #endif /* PACKET_ASSEMBLY */ #ifdef PACKET_DECODING /* Decode a hardware header... */ ssize_t decode_ethernet_header (interface, buf, bufix, from) struct interface_info *interface; unsigned char *buf; unsigned bufix; struct hardware *from; { struct isc_ether_header eh; memcpy (&eh, buf + bufix, ETHER_HEADER_SIZE); #ifdef USERLAND_FILTER if (ntohs (eh.ether_type) != ETHERTYPE_IP) return -1; #endif memcpy (&from -> hbuf [1], eh.ether_shost, sizeof (eh.ether_shost)); from -> hbuf [0] = ARPHRD_ETHER; from -> hlen = (sizeof eh.ether_shost) + 1; return ETHER_HEADER_SIZE; } #endif /* PACKET_DECODING */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/execute.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/execute.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/execute.c (revision 131136) @@ -1,1061 +1,1052 @@ /* execute.c Support for executable statements. */ /* - * Copyright (c) 1998-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1998-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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: execute.c,v 1.44.2.9 2002/11/17 02:26:58 dhankins Exp $ Copyright (c) 1998-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: execute.c,v 1.44.2.10 2004/06/10 17:59:17 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #include int execute_statements (result, packet, lease, client_state, in_options, out_options, scope, statements) struct binding_value **result; struct packet *packet; struct lease *lease; struct client_state *client_state; struct option_state *in_options; struct option_state *out_options; struct binding_scope **scope; struct executable_statement *statements; { struct executable_statement *r, *e, *next; int rc; int status; unsigned long num; struct binding_scope *outer; struct binding *binding; struct data_string ds; struct binding_scope *ns; if (!statements) return 1; r = (struct executable_statement *)0; next = (struct executable_statement *)0; e = (struct executable_statement *)0; executable_statement_reference (&r, statements, MDL); while (r && !(result && *result)) { if (r -> next) executable_statement_reference (&next, r -> next, MDL); switch (r -> op) { case statements_statement: #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: statements"); #endif status = execute_statements (result, packet, lease, client_state, in_options, out_options, scope, r -> data.statements); #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: statements returns %d", status); #endif if (!status) return 0; break; case on_statement: if (lease) { if (r -> data.on.evtypes & ON_EXPIRY) { #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: on expiry"); #endif if (lease -> on_expiry) executable_statement_dereference (&lease -> on_expiry, MDL); if (r -> data.on.statements) executable_statement_reference (&lease -> on_expiry, r -> data.on.statements, MDL); } if (r -> data.on.evtypes & ON_RELEASE) { #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: on release"); #endif if (lease -> on_release) executable_statement_dereference (&lease -> on_release, MDL); if (r -> data.on.statements) executable_statement_reference (&lease -> on_release, r -> data.on.statements, MDL); } if (r -> data.on.evtypes & ON_COMMIT) { #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: on commit"); #endif if (lease -> on_commit) executable_statement_dereference (&lease -> on_commit, MDL); if (r -> data.on.statements) executable_statement_reference (&lease -> on_commit, r -> data.on.statements, MDL); } } break; case switch_statement: #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: switch"); #endif status = (find_matching_case (&e, packet, lease, client_state, in_options, out_options, scope, r -> data.s_switch.expr, r -> data.s_switch.statements)); #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: switch: case %lx", (unsigned long)e); #endif if (status) { if (!(execute_statements (result, packet, lease, client_state, in_options, out_options, scope, e))) { executable_statement_dereference (&e, MDL); return 0; } executable_statement_dereference (&e, MDL); } break; /* These have no effect when executed. */ case case_statement: case default_statement: break; case if_statement: status = (evaluate_boolean_expression (&rc, packet, lease, client_state, in_options, out_options, scope, r -> data.ie.expr)); #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: if %s", (status ? (rc ? "true" : "false") : "NULL")); #endif /* XXX Treat NULL as false */ if (!status) rc = 0; if (!execute_statements (result, packet, lease, client_state, in_options, out_options, scope, rc ? r -> data.ie.tc : r -> data.ie.fc)) return 0; break; case eval_statement: status = evaluate_expression ((struct binding_value **)0, packet, lease, client_state, in_options, out_options, scope, r -> data.eval, MDL); #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: evaluate: %s", (status ? "succeeded" : "failed")); #endif break; case return_statement: status = evaluate_expression (result, packet, lease, client_state, in_options, out_options, scope, r -> data.retval, MDL); #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: return: %s", (status ? "succeeded" : "failed")); #endif break; case add_statement: #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: add %s", (r -> data.add -> name ? r -> data.add -> name : "")); #endif classify (packet, r -> data.add); break; case break_statement: #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: break"); #endif return 1; case supersede_option_statement: case send_option_statement: #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: %s option %s.%s", (r -> op == supersede_option_statement ? "supersede" : "send"), r -> data.option -> option -> universe -> name, r -> data.option -> option -> name); goto option_statement; #endif case default_option_statement: #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: default option %s.%s", r -> data.option -> option -> universe -> name, r -> data.option -> option -> name); goto option_statement; #endif case append_option_statement: #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: append option %s.%s", r -> data.option -> option -> universe -> name, r -> data.option -> option -> name); goto option_statement; #endif case prepend_option_statement: #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: prepend option %s.%s", r -> data.option -> option -> universe -> name, r -> data.option -> option -> name); option_statement: #endif set_option (r -> data.option -> option -> universe, out_options, r -> data.option, r -> op); break; case set_statement: case define_statement: if (!scope) { log_error ("set %s: no scope", r -> data.set.name); status = 0; break; } if (!*scope) { if (!binding_scope_allocate (scope, MDL)) { log_error ("set %s: can't allocate scope", r -> data.set.name); status = 0; break; } } binding = find_binding (*scope, r -> data.set.name); #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: set %s", r -> data.set.name); #endif if (!binding) { binding = dmalloc (sizeof *binding, MDL); if (binding) { memset (binding, 0, sizeof *binding); binding -> name = dmalloc (strlen (r -> data.set.name) + 1, MDL); if (binding -> name) { strcpy (binding -> name, r -> data.set.name); binding -> next = (*scope) -> bindings; (*scope) -> bindings = binding; } else { badalloc: dfree (binding, MDL); binding = (struct binding *)0; } } } if (binding) { if (binding -> value) binding_value_dereference (&binding -> value, MDL); if (r -> op == set_statement) { status = (evaluate_expression (&binding -> value, packet, lease, client_state, in_options, out_options, scope, r -> data.set.expr, MDL)); } else { if (!(binding_value_allocate (&binding -> value, MDL))) { dfree (binding, MDL); binding = (struct binding *)0; } if (binding -> value) { binding -> value -> type = binding_function; (fundef_reference (&binding -> value -> value.fundef, r -> data.set.expr -> data.func, MDL)); } } } #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: set %s%s", r -> data.set.name, (binding && status ? "" : " (failed)")); #endif break; case unset_statement: if (!scope || !*scope) { status = 0; break; } binding = find_binding (*scope, r -> data.unset); if (binding) { if (binding -> value) binding_value_dereference (&binding -> value, MDL); status = 1; } else status = 0; #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: unset %s: %s", r -> data.unset, (status ? "found" : "not found")); #endif break; case let_statement: #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: let %s", r -> data.let.name); #endif ns = (struct binding_scope *)0; binding_scope_allocate (&ns, MDL); e = r; next_let: if (ns) { binding = dmalloc (sizeof *binding, MDL); memset (binding, 0, sizeof *binding); if (!binding) { blb: binding_scope_dereference (&ns, MDL); } else { binding -> name = dmalloc (strlen (e -> data.let.name + 1), MDL); if (binding -> name) strcpy (binding -> name, e -> data.let.name); else { dfree (binding, MDL); binding = (struct binding *)0; goto blb; } } } if (ns && binding) { status = (evaluate_expression (&binding -> value, packet, lease, client_state, in_options, out_options, scope, e -> data.set.expr, MDL)); binding -> next = ns -> bindings; ns -> bindings = binding; } #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: let %s%s", e -> data.let.name, (binding && status ? "" : "failed")); #endif if (!e -> data.let.statements) { } else if (e -> data.let.statements -> op == let_statement) { e = e -> data.let.statements; goto next_let; } else if (ns) { if (scope && *scope) binding_scope_reference (&ns -> outer, *scope, MDL); execute_statements (result, packet, lease, client_state, in_options, out_options, &ns, e -> data.let.statements); } if (ns) binding_scope_dereference (&ns, MDL); break; case log_statement: memset (&ds, 0, sizeof ds); status = (evaluate_data_expression (&ds, packet, lease, client_state, in_options, out_options, scope, r -> data.log.expr, MDL)); #if defined (DEBUG_EXPRESSIONS) log_debug ("exec: log"); #endif if (status) { switch (r -> data.log.priority) { case log_priority_fatal: log_fatal ("%.*s", (int)ds.len, ds.buffer -> data); break; case log_priority_error: log_error ("%.*s", (int)ds.len, ds.buffer -> data); break; case log_priority_debug: log_debug ("%.*s", (int)ds.len, ds.buffer -> data); break; case log_priority_info: log_info ("%.*s", (int)ds.len, ds.buffer -> data); break; } data_string_forget (&ds, MDL); } break; default: log_error ("bogus statement type %d", r -> op); break; } executable_statement_dereference (&r, MDL); if (next) { executable_statement_reference (&r, next, MDL); executable_statement_dereference (&next, MDL); } } return 1; } /* Execute all the statements in a particular scope, and all statements in scopes outer from that scope, but if a particular limiting scope is reached, do not execute statements in that scope or in scopes outer from it. More specific scopes need to take precedence over less specific scopes, so we recursively traverse the scope list, executing the most outer scope first. */ void execute_statements_in_scope (result, packet, lease, client_state, in_options, out_options, scope, group, limiting_group) struct binding_value **result; struct packet *packet; struct lease *lease; struct client_state *client_state; struct option_state *in_options; struct option_state *out_options; struct binding_scope **scope; struct group *group; struct group *limiting_group; { struct group *limit; /* If we've recursed as far as we can, return. */ if (!group) return; /* As soon as we get to a scope that is outer than the limiting scope, we are done. This is so that if somebody does something like this, it does the expected thing: domain-name "fugue.com"; shared-network FOO { host bar { domain-name "othello.fugue.com"; fixed-address 10.20.30.40; } subnet 10.20.30.0 netmask 255.255.255.0 { domain-name "manhattan.fugue.com"; } } The problem with the above arrangement is that the host's group nesting will be host -> shared-network -> top-level, and the limiting scope when we evaluate the host's scope will be the subnet -> shared-network -> top-level, so we need to know when we evaluate the host's scope to stop before we evaluate the shared-networks scope, because it's outer than the limiting scope, which means we've already evaluated it. */ for (limit = limiting_group; limit; limit = limit -> next) { if (group == limit) return; } if (group -> next) execute_statements_in_scope (result, packet, lease, client_state, in_options, out_options, scope, group -> next, limiting_group); execute_statements (result, packet, lease, client_state, in_options, out_options, scope, group -> statements); } /* Dereference or free any subexpressions of a statement being freed. */ int executable_statement_dereference (ptr, file, line) struct executable_statement **ptr; const char *file; int line; { struct executable_statement *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 > 0) { *ptr = (struct executable_statement *)0; return 1; } 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 } if ((*ptr) -> next) executable_statement_dereference (&(*ptr) -> next, file, line); switch ((*ptr) -> op) { case statements_statement: if ((*ptr) -> data.statements) executable_statement_dereference (&(*ptr) -> data.statements, file, line); break; case on_statement: if ((*ptr) -> data.on.statements) executable_statement_dereference (&(*ptr) -> data.on.statements, file, line); break; case switch_statement: if ((*ptr) -> data.s_switch.statements) executable_statement_dereference (&(*ptr) -> data.on.statements, file, line); if ((*ptr) -> data.s_switch.expr) expression_dereference (&(*ptr) -> data.s_switch.expr, file, line); break; case case_statement: if ((*ptr) -> data.s_switch.expr) expression_dereference (&(*ptr) -> data.c_case, file, line); break; case if_statement: if ((*ptr) -> data.ie.expr) expression_dereference (&(*ptr) -> data.ie.expr, file, line); if ((*ptr) -> data.ie.tc) executable_statement_dereference (&(*ptr) -> data.ie.tc, file, line); if ((*ptr) -> data.ie.fc) executable_statement_dereference (&(*ptr) -> data.ie.fc, file, line); break; case eval_statement: if ((*ptr) -> data.eval) expression_dereference (&(*ptr) -> data.eval, file, line); break; case return_statement: if ((*ptr) -> data.eval) expression_dereference (&(*ptr) -> data.eval, file, line); break; case set_statement: if ((*ptr)->data.set.name) dfree ((*ptr)->data.set.name, file, line); if ((*ptr)->data.set.expr) expression_dereference (&(*ptr) -> data.set.expr, file, line); break; case unset_statement: if ((*ptr)->data.unset) dfree ((*ptr)->data.unset, file, line); break; case supersede_option_statement: case send_option_statement: case default_option_statement: case append_option_statement: case prepend_option_statement: if ((*ptr) -> data.option) option_cache_dereference (&(*ptr) -> data.option, file, line); break; default: /* Nothing to do. */ break; } dfree ((*ptr), file, line); *ptr = (struct executable_statement *)0; return 1; } void write_statements (file, statements, indent) FILE *file; struct executable_statement *statements; int indent; { struct executable_statement *r, *x; int result; int status; const char *s, *t, *dot; int col; if (!statements) return; for (r = statements; r; r = r -> next) { switch (r -> op) { case statements_statement: write_statements (file, r -> data.statements, indent); break; case on_statement: indent_spaces (file, indent); fprintf (file, "on "); s = ""; if (r -> data.on.evtypes & ON_EXPIRY) { fprintf (file, "%sexpiry", s); s = " or "; } if (r -> data.on.evtypes & ON_COMMIT) { fprintf (file, "%scommit", s); s = "or"; } if (r -> data.on.evtypes & ON_RELEASE) { fprintf (file, "%srelease", s); s = "or"; } if (r -> data.on.statements) { fprintf (file, " {"); write_statements (file, r -> data.on.statements, indent + 2); indent_spaces (file, indent); fprintf (file, "}"); } else { fprintf (file, ";"); } break; case switch_statement: indent_spaces (file, indent); fprintf (file, "switch ("); col = write_expression (file, r -> data.s_switch.expr, indent + 7, indent + 7, 1); col = token_print_indent (file, col, indent + 7, "", "", ")"); token_print_indent (file, col, indent, " ", "", "{"); write_statements (file, r -> data.s_switch.statements, indent + 2); indent_spaces (file, indent); fprintf (file, "}"); break; case case_statement: indent_spaces (file, indent - 1); fprintf (file, "case "); col = write_expression (file, r -> data.s_switch.expr, indent + 5, indent + 5, 1); token_print_indent (file, col, indent + 5, "", "", ":"); break; case default_statement: indent_spaces (file, indent - 1); fprintf (file, "default: "); break; case if_statement: indent_spaces (file, indent); fprintf (file, "if "); x = r; col = write_expression (file, x -> data.ie.expr, indent + 3, indent + 3, 1); else_if: token_print_indent (file, col, indent, " ", "", "{"); write_statements (file, x -> data.ie.tc, indent + 2); if (x -> data.ie.fc && x -> data.ie.fc -> op == if_statement && !x -> data.ie.fc -> next) { indent_spaces (file, indent); fprintf (file, "} elsif "); x = x -> data.ie.fc; col = write_expression (file, x -> data.ie.expr, indent + 6, indent + 6, 1); goto else_if; } if (x -> data.ie.fc) { indent_spaces (file, indent); fprintf (file, "} else {"); write_statements (file, x -> data.ie.fc, indent + 2); } indent_spaces (file, indent); fprintf (file, "}"); break; case eval_statement: indent_spaces (file, indent); fprintf (file, "eval "); col = write_expression (file, r -> data.eval, indent + 5, indent + 5, 1); fprintf (file, ";"); break; case return_statement: indent_spaces (file, indent); fprintf (file, "return;"); break; case add_statement: indent_spaces (file, indent); fprintf (file, "add \"%s\"", r -> data.add -> name); break; case break_statement: indent_spaces (file, indent); fprintf (file, "break;"); break; case supersede_option_statement: case send_option_statement: s = "supersede"; goto option_statement; case default_option_statement: s = "default"; goto option_statement; case append_option_statement: s = "append"; goto option_statement; case prepend_option_statement: s = "prepend"; option_statement: /* Note: the reason we don't try to pretty print the option here is that the format of the option may change in dhcpd.conf, and then when this statement was read back, it would cause a syntax error. */ if (r -> data.option -> option -> universe == &dhcp_universe) { t = ""; dot = ""; } else { t = (r -> data.option -> option -> universe -> name); dot = "."; } indent_spaces (file, indent); fprintf (file, "%s %s%s%s = ", s, t, dot, r -> data.option -> option -> name); col = (indent + strlen (s) + strlen (t) + strlen (dot) + strlen (r -> data.option -> option -> name) + 4); if (r -> data.option -> expression) write_expression (file, r -> data.option -> expression, col, indent + 8, 1); else token_indent_data_string (file, col, indent + 8, "", "", &r -> data.option -> data); fprintf (file, ";"); /* XXX */ break; case set_statement: indent_spaces (file, indent); fprintf (file, "set "); col = token_print_indent (file, indent + 4, indent + 4, "", "", r -> data.set.name); col = token_print_indent (file, col, indent + 4, " ", " ", "="); col = write_expression (file, r -> data.set.expr, indent + 3, indent + 3, 0); col = token_print_indent (file, col, indent + 4, " ", "", ";"); break; case unset_statement: indent_spaces (file, indent); fprintf (file, "unset "); col = token_print_indent (file, indent + 6, indent + 6, "", "", r -> data.set.name); col = token_print_indent (file, col, indent + 6, " ", "", ";"); break; case log_statement: indent_spaces (file, indent); fprintf (file, "log "); col = token_print_indent (file, col, indent + 4, "", "", "("); switch (r -> data.log.priority) { case log_priority_fatal: col = token_print_indent (file, col, indent + 4, "", " ", "fatal,"); break; case log_priority_error: col = token_print_indent (file, col, indent + 4, "", " ", "error,"); break; case log_priority_debug: col = token_print_indent (file, col, indent + 4, "", " ", "debug,"); break; case log_priority_info: col = token_print_indent (file, col, indent + 4, "", " ", "info,"); break; } col = write_expression (file, r -> data.log.expr, indent + 4, indent + 4, 0); col = token_print_indent (file, col, indent + 4, "", "", ");"); break; default: log_fatal ("bogus statement type %d\n", r -> op); } } } /* Find a case statement in the sequence of executable statements that matches the expression, and if found, return the following statement. If no case statement matches, try to find a default statement and return that (the default statement can precede all the case statements). Otherwise, return the null statement. */ int find_matching_case (struct executable_statement **ep, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *out_options, struct binding_scope **scope, struct expression *expr, struct executable_statement *stmt) { int status, sub; struct executable_statement *s; unsigned long foo; if (is_data_expression (expr)) { struct executable_statement *e; struct data_string cd, ds; memset (&ds, 0, sizeof ds); memset (&cd, 0, sizeof cd); status = (evaluate_data_expression (&ds, packet, lease, client_state, in_options, out_options, scope, expr, MDL)); if (status) { for (s = stmt; s; s = s -> next) { if (s -> op == case_statement) { sub = (evaluate_data_expression (&cd, packet, lease, client_state, in_options, out_options, scope, s -> data.c_case, MDL)); if (sub && cd.len == ds.len && !memcmp (cd.data, ds.data, cd.len)) { data_string_forget (&cd, MDL); data_string_forget (&ds, MDL); executable_statement_reference (ep, s -> next, MDL); return 1; } data_string_forget (&cd, MDL); } } data_string_forget (&ds, MDL); } } else { unsigned long n, c; status = evaluate_numeric_expression (&n, packet, lease, client_state, in_options, out_options, scope, expr); if (status) { for (s = stmt; s; s = s -> next) { if (s -> op == case_statement) { sub = (evaluate_numeric_expression (&c, packet, lease, client_state, in_options, out_options, scope, s -> data.c_case)); if (sub && n == c) { executable_statement_reference (ep, s -> next, MDL); return 1; } } } } } /* If we didn't find a matching case statement, look for a default statement and return the statement following it. */ for (s = stmt; s; s = s -> next) if (s -> op == default_statement) break; if (s) { executable_statement_reference (ep, s -> next, MDL); return 1; } return 0; } int executable_statement_foreach (struct executable_statement *stmt, int (*callback) (struct executable_statement *, void *, int), void *vp, int condp) { struct executable_statement *foo; int ok = 0; int result; for (foo = stmt; foo; foo = foo -> next) { if ((*callback) (foo, vp, condp) != 0) ok = 1; switch (foo -> op) { case null_statement: break; case if_statement: if (executable_statement_foreach (foo -> data.ie.tc, callback, vp, 1)) ok = 1; if (executable_statement_foreach (foo -> data.ie.fc, callback, vp, 1)) ok = 1; break; case add_statement: break; case eval_statement: break; case break_statement: break; case default_option_statement: break; case supersede_option_statement: break; case append_option_statement: break; case prepend_option_statement: break; case send_option_statement: break; case statements_statement: if ((executable_statement_foreach (foo -> data.statements, callback, vp, condp))) ok = 1; break; case on_statement: if ((executable_statement_foreach (foo -> data.on.statements, callback, vp, 1))) ok = 1; break; case switch_statement: if ((executable_statement_foreach (foo -> data.s_switch.statements, callback, vp, 1))) ok = 1; break; case case_statement: break; case default_statement: break; case set_statement: break; case unset_statement: break; case let_statement: if ((executable_statement_foreach (foo -> data.let.statements, callback, vp, 0))) ok = 1; break; case define_statement: break; case log_statement: case return_statement: break; } } return ok; } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/fddi.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/fddi.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/fddi.c (revision 131136) @@ -1,106 +1,97 @@ /* fddi.c Packet assembly code, originally contributed by Archie Cobbs. */ /* - * Copyright (c) 1996-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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: fddi.c,v 1.3.2.1 2002/11/17 02:26:58 dhankins Exp $ Copyright (c) 1996-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: fddi.c,v 1.3.2.2 2004/06/10 17:59:18 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #if defined (DEC_FDDI) #include #include #if defined (PACKET_ASSEMBLY) || defined (PACKET_DECODING) #include "includes/netinet/if_ether.h" #endif /* PACKET_ASSEMBLY || PACKET_DECODING */ #if defined (PACKET_ASSEMBLY) /* Assemble an hardware header... */ void assemble_fddi_header (interface, buf, bufix, to) struct interface_info *interface; unsigned char *buf; unsigned *bufix; struct hardware *to; { struct fddi_header fh; struct llc lh; if (to && to -> hlen == 7) memcpy (fh.fddi_dhost, &to -> hbuf [1], sizeof (fh.fddi_dhost)); memcpy (fh.fddi_shost, &interface -> hw_address.hbuf [1], sizeof (fh.fddi_shost)); fh.fddi_fc = FDDIFC_LLC_ASYNC; memcpy (&buf [*bufix], &fh, sizeof fh); *bufix += sizeof fh; lh.llc_dsap = LLC_SNAP_LSAP; lh.llc_ssap = LLC_SNAP_LSAP; lh.llc_un.type_snap.control = LLC_UI; lh.llc_un.type_snap.ether_type = htons (ETHERTYPE_IP); memcpy (&buf [*bufix], &lh, LLC_SNAP_LEN); *bufix += LLC_SNAP_LEN; } #endif /* PACKET_ASSEMBLY */ #ifdef PACKET_DECODING /* Decode a hardware header... */ ssize_t decode_fddi_header (interface, buf, bufix, from) struct interface_info *interface; unsigned char *buf; unsigned bufix; struct hardware *from; { struct fddi_header fh; struct llc lh; from -> hbuf [0] = HTYPE_FDDI; memcpy (&from -> hbuf [1], fh.fddi_shost, sizeof fh.fddi_shost); return FDDI_HEADER_SIZE + LLC_SNAP_LEN; } #endif /* PACKET_DECODING */ #endif /* DEC_FDDI */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/icmp.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/icmp.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/icmp.c (revision 131136) @@ -1,326 +1,317 @@ /* dhcp.c ICMP Protocol engine - for sending out pings and receiving responses. */ /* - * Copyright (c) 1996-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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: icmp.c,v 1.30.2.5 2002/11/17 02:26:58 dhankins Exp $ Copyright (c) 1996-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: icmp.c,v 1.30.2.6 2004/06/10 17:59:18 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #include "netinet/ip.h" #include "netinet/ip_icmp.h" struct icmp_state *icmp_state; static omapi_object_type_t *dhcp_type_icmp; static int no_icmp; OMAPI_OBJECT_ALLOC (icmp_state, struct icmp_state, dhcp_type_icmp) #if defined (TRACING) trace_type_t *trace_icmp_input; trace_type_t *trace_icmp_output; #endif /* Initialize the ICMP protocol. */ void icmp_startup (routep, handler) int routep; void (*handler) PROTO ((struct iaddr, u_int8_t *, int)); { struct protoent *proto; int protocol = 1; struct sockaddr_in from; int fd; int state; struct icmp_state *new; omapi_object_t *h; isc_result_t result; /* Only initialize icmp once. */ if (dhcp_type_icmp) log_fatal ("attempted to reinitialize icmp protocol"); result = omapi_object_type_register (&dhcp_type_icmp, "icmp", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, sizeof (struct icmp_state), 0, RC_MISC); if (result != ISC_R_SUCCESS) log_fatal ("Can't register icmp object type: %s", isc_result_totext (result)); icmp_state_allocate (&icmp_state, MDL); icmp_state -> icmp_handler = handler; #if defined (TRACING) trace_icmp_input = trace_type_register ("icmp-input", (void *)0, trace_icmp_input_input, trace_icmp_input_stop, MDL); trace_icmp_output = trace_type_register ("icmp-output", (void *)0, trace_icmp_output_input, trace_icmp_output_stop, MDL); /* If we're playing back a trace file, don't create the socket or set up the callback. */ if (!trace_playback ()) { #endif /* Get the protocol number (should be 1). */ proto = getprotobyname ("icmp"); if (proto) protocol = proto -> p_proto; /* Get a raw socket for the ICMP protocol. */ icmp_state -> socket = socket (AF_INET, SOCK_RAW, protocol); if (icmp_state -> socket < 0) { no_icmp = 1; log_error ("unable to create icmp socket: %m"); return; } #if defined (HAVE_SETFD) if (fcntl (icmp_state -> socket, F_SETFD, 1) < 0) log_error ("Can't set close-on-exec on icmp: %m"); #endif /* Make sure it does routing... */ state = 0; if (setsockopt (icmp_state -> socket, SOL_SOCKET, SO_DONTROUTE, (char *)&state, sizeof state) < 0) log_fatal ("Can't disable SO_DONTROUTE on ICMP: %m"); result = (omapi_register_io_object ((omapi_object_t *)icmp_state, icmp_readsocket, 0, icmp_echoreply, 0, 0)); if (result != ISC_R_SUCCESS) log_fatal ("Can't register icmp handle: %s", isc_result_totext (result)); #if defined (TRACING) } #endif } int icmp_readsocket (h) omapi_object_t *h; { struct icmp_state *state; state = (struct icmp_state *)h; return state -> socket; } int icmp_echorequest (addr) struct iaddr *addr; { struct sockaddr_in to; struct icmp icmp; int status; #if defined (TRACING) trace_iov_t iov [2]; #endif if (no_icmp) return 1; if (!icmp_state) log_fatal ("ICMP protocol used before initialization."); memset (&to, 0, sizeof(to)); #ifdef HAVE_SA_LEN to.sin_len = sizeof to; #endif to.sin_family = AF_INET; to.sin_port = 0; /* unused. */ memcpy (&to.sin_addr, addr -> iabuf, sizeof to.sin_addr); /* XXX */ icmp.icmp_type = ICMP_ECHO; icmp.icmp_code = 0; icmp.icmp_cksum = 0; icmp.icmp_seq = 0; #ifdef PTRSIZE_64BIT icmp.icmp_id = (((u_int32_t)(u_int64_t)addr) ^ (u_int32_t)(((u_int64_t)addr) >> 32)); #else icmp.icmp_id = (u_int32_t)addr; #endif memset (&icmp.icmp_dun, 0, sizeof icmp.icmp_dun); icmp.icmp_cksum = wrapsum (checksum ((unsigned char *)&icmp, sizeof icmp, 0)); #if defined (TRACING) if (trace_playback ()) { char *buf = (char *)0; unsigned buflen = 0; /* Consume the ICMP event. */ status = trace_get_packet (&trace_icmp_output, &buflen, &buf); if (status != ISC_R_SUCCESS) log_error ("icmp_echorequest: %s", isc_result_totext (status)); if (buf) dfree (buf, MDL); } else { if (trace_record ()) { iov [0].buf = (char *)addr; iov [0].len = sizeof *addr; iov [1].buf = (char *)&icmp; iov [1].len = sizeof icmp; trace_write_packet_iov (trace_icmp_output, 2, iov, MDL); } #endif /* Send the ICMP packet... */ status = sendto (icmp_state -> socket, (char *)&icmp, sizeof icmp, 0, (struct sockaddr *)&to, sizeof to); if (status < 0) log_error ("icmp_echorequest %s: %m", inet_ntoa(to.sin_addr)); if (status != sizeof icmp) return 0; #if defined (TRACING) } #endif return 1; } isc_result_t icmp_echoreply (h) omapi_object_t *h; { struct icmp *icfrom; struct ip *ip; struct sockaddr_in from; u_int8_t icbuf [1500]; int status; SOCKLEN_T sl; int hlen, len; struct iaddr ia; struct icmp_state *state; #if defined (TRACING) trace_iov_t iov [2]; #endif state = (struct icmp_state *)h; sl = sizeof from; status = recvfrom (state -> socket, (char *)icbuf, sizeof icbuf, 0, (struct sockaddr *)&from, &sl); if (status < 0) { log_error ("icmp_echoreply: %m"); return ISC_R_UNEXPECTED; } /* Find the IP header length... */ ip = (struct ip *)icbuf; hlen = IP_HL (ip); /* Short packet? */ if (status < hlen + (sizeof *icfrom)) { return ISC_R_SUCCESS; } len = status - hlen; icfrom = (struct icmp *)(icbuf + hlen); /* Silently discard ICMP packets that aren't echoreplies. */ if (icfrom -> icmp_type != ICMP_ECHOREPLY) { return ISC_R_SUCCESS; } /* If we were given a second-stage handler, call it. */ if (state -> icmp_handler) { memcpy (ia.iabuf, &from.sin_addr, sizeof from.sin_addr); ia.len = sizeof from.sin_addr; #if defined (TRACING) if (trace_record ()) { ia.len = htonl(ia.len); iov [0].buf = (char *)&ia; iov [0].len = sizeof ia; iov [1].buf = (char *)icbuf; iov [1].len = len; trace_write_packet_iov (trace_icmp_input, 2, iov, MDL); ia.len = ntohl(ia.len); } #endif (*state -> icmp_handler) (ia, icbuf, len); } return ISC_R_SUCCESS; } #if defined (TRACING) void trace_icmp_input_input (trace_type_t *ttype, unsigned length, char *buf) { struct iaddr *ia; unsigned len; u_int8_t *icbuf; ia = (struct iaddr *)buf; ia->len = ntohl(ia->len); icbuf = (u_int8_t *)(ia + 1); if (icmp_state -> icmp_handler) (*icmp_state -> icmp_handler) (*ia, icbuf, (int)(length - sizeof ia)); } void trace_icmp_input_stop (trace_type_t *ttype) { } void trace_icmp_output_input (trace_type_t *ttype, unsigned length, char *buf) { struct icmp *icmp; struct iaddr ia; if (length != (sizeof (*icmp) + (sizeof ia))) { log_error ("trace_icmp_output_input: data size mismatch %d:%d", length, (int)((sizeof (*icmp)) + (sizeof ia))); return; } ia.len = 4; memcpy (ia.iabuf, buf, 4); icmp = (struct icmp *)(buf + 1); log_error ("trace_icmp_output_input: unsent ping to %s", piaddr (ia)); } void trace_icmp_output_stop (trace_type_t *ttype) { } #endif /* TRACING */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/inet.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/inet.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/inet.c (revision 131136) @@ -1,242 +1,233 @@ /* inet.c Subroutines to manipulate internet addresses in a safely portable way... */ /* - * Copyright (c) 1995-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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: inet.c,v 1.8.2.4 2002/11/17 02:26:58 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: inet.c,v 1.8.2.5 2004/06/10 17:59:18 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" /* Return just the network number of an internet address... */ struct iaddr subnet_number (addr, mask) struct iaddr addr; struct iaddr mask; { int i; struct iaddr rv; rv.len = 0; /* Both addresses must have the same length... */ if (addr.len != mask.len) return rv; rv.len = addr.len; for (i = 0; i < rv.len; i++) rv.iabuf [i] = addr.iabuf [i] & mask.iabuf [i]; return rv; } /* Combine a network number and a integer to produce an internet address. This won't work for subnets with more than 32 bits of host address, but maybe this isn't a problem. */ struct iaddr ip_addr (subnet, mask, host_address) struct iaddr subnet; struct iaddr mask; u_int32_t host_address; { int i, j, k; u_int32_t swaddr; struct iaddr rv; unsigned char habuf [sizeof swaddr]; swaddr = htonl (host_address); memcpy (habuf, &swaddr, sizeof swaddr); /* Combine the subnet address and the host address. If the host address is bigger than can fit in the subnet, return a zero-length iaddr structure. */ rv = subnet; j = rv.len - sizeof habuf; for (i = sizeof habuf - 1; i >= 0; i--) { if (mask.iabuf [i + j]) { if (habuf [i] > (mask.iabuf [i + j] ^ 0xFF)) { rv.len = 0; return rv; } for (k = i - 1; k >= 0; k--) { if (habuf [k]) { rv.len = 0; return rv; } } rv.iabuf [i + j] |= habuf [i]; break; } else rv.iabuf [i + j] = habuf [i]; } return rv; } /* Given a subnet number and netmask, return the address on that subnet for which the host portion of the address is all ones (the standard broadcast address). */ struct iaddr broadcast_addr (subnet, mask) struct iaddr subnet; struct iaddr mask; { int i, j, k; struct iaddr rv; if (subnet.len != mask.len) { rv.len = 0; return rv; } for (i = 0; i < subnet.len; i++) { rv.iabuf [i] = subnet.iabuf [i] | (~mask.iabuf [i] & 255); } rv.len = subnet.len; return rv; } u_int32_t host_addr (addr, mask) struct iaddr addr; struct iaddr mask; { int i; u_int32_t swaddr; struct iaddr rv; rv.len = 0; /* Mask out the network bits... */ rv.len = addr.len; for (i = 0; i < rv.len; i++) rv.iabuf [i] = addr.iabuf [i] & ~mask.iabuf [i]; /* Copy out up to 32 bits... */ memcpy (&swaddr, &rv.iabuf [rv.len - sizeof swaddr], sizeof swaddr); /* Swap it and return it. */ return ntohl (swaddr); } int addr_eq (addr1, addr2) struct iaddr addr1, addr2; { if (addr1.len != addr2.len) return 0; return memcmp (addr1.iabuf, addr2.iabuf, addr1.len) == 0; } char *piaddr (addr) struct iaddr addr; { static char pbuf [4 * 16]; char *s = pbuf; int i; if (addr.len == 0) { strcpy (s, ""); } for (i = 0; i < addr.len; i++) { sprintf (s, "%s%d", i ? "." : "", addr.iabuf [i]); s += strlen (s); } return pbuf; } char *piaddr1 (addr) struct iaddr addr; { static char pbuf [4 * 16]; char *s = pbuf; int i; if (addr.len == 0) { strcpy (s, ""); } for (i = 0; i < addr.len; i++) { sprintf (s, "%s%d", i ? "." : "", addr.iabuf [i]); s += strlen (s); } return pbuf; } char *piaddrmask (struct iaddr addr, struct iaddr mask, const char *file, int line) { char *s, *t; int i, mw; unsigned len; for (i = 0; i < 32; i++) { if (!mask.iabuf [3 - i / 8]) i += 7; else if (mask.iabuf [3 - i / 8] & (1 << (i % 8))) break; } mw = 32 - i; len = mw > 9 ? 2 : 1; len += 4; /* three dots and a slash. */ for (i = 0; i < (mw / 8) + 1; i++) { if (addr.iabuf [i] > 99) len += 3; else if (addr.iabuf [i] > 9) len += 2; else len++; } s = dmalloc (len + 1, file, line); if (!s) return s; t = s; sprintf (t, "%d", addr.iabuf [0]); t += strlen (t); for (i = 1; i < (mw / 8) + 1; i++) { sprintf (t, ".%d", addr.iabuf [i]); t += strlen (t); } *t++ = '/'; sprintf (t, "%d", mw); return s; } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/iscprint.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/iscprint.c (nonexistent) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/iscprint.c (revision 131136) @@ -0,0 +1,539 @@ +/* + * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1999-2001, 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: iscprint.c,v 1.1.2.1 2004/06/14 21:09:22 dhankins Exp $ */ + +#include "dhcpd.h" + +#ifdef NO_SNPRINTF + +#ifndef LINT +static char copyright[] = +"$Id: iscprint.c,v 1.1.2.1 2004/06/14 21:09:22 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium, Inc. All rights reserved."; +#endif + +#define INSIST(cond) REQUIRE(cond) +#define REQUIRE(cond) if (!(cond)) { return 0; } + +/* + * Return length of string that would have been written if not truncated. + */ + +int +isc_print_snprintf(char *str, size_t size, const char *format, ...) { + va_list ap; + int ret; + + va_start(ap, format); + ret = vsnprintf(str, size, format, ap); + va_end(ap); + return (ret); +} + +/* + * Return length of string that would have been written if not truncated. + */ + +int +isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { + int h; + int l; + int q; + int alt; + int zero; + int left; + int plus; + int space; + int neg; + isc_int64_t tmpi; + isc_uint64_t tmpui; + unsigned long width; + unsigned long precision; + unsigned int length; + char buf[1024]; + char c; + void *v; + char *save = str; + const char *cp; + const char *head; + int count = 0; + int pad; + int zeropad; + int dot; + double dbl; +#ifdef HAVE_LONG_DOUBLE + long double ldbl; +#endif + char fmt[32]; + + INSIST(str != NULL); + INSIST(format != NULL); + + while (*format != '\0') { + if (*format != '%') { + if (size > 1) { + *str++ = *format; + size--; + } + count++; + format++; + continue; + } + format++; + + /* + * Reset flags. + */ + dot = neg = space = plus = left = zero = alt = h = l = q = 0; + width = precision = 0; + head = ""; + length = pad = zeropad = 0; + + do { + if (*format == '#') { + alt = 1; + format++; + } else if (*format == '-') { + left = 1; + zero = 0; + format++; + } else if (*format == ' ') { + if (!plus) + space = 1; + format++; + } else if (*format == '+') { + plus = 1; + space = 0; + format++; + } else if (*format == '0') { + if (!left) + zero = 1; + format++; + } else + break; + } while (1); + + /* + * Width. + */ + if (*format == '*') { + width = va_arg(ap, int); + format++; + } else if (isdigit((unsigned char)*format)) { + char *e; + width = strtoul(format, &e, 10); + format = e; + } + + /* + * Precision. + */ + if (*format == '.') { + format++; + dot = 1; + if (*format == '*') { + precision = va_arg(ap, int); + format++; + } else if (isdigit((unsigned char)*format)) { + char *e; + precision = strtoul(format, &e, 10); + format = e; + } + } + + switch (*format) { + case '\0': + continue; + case '%': + if (size > 1) { + *str++ = *format; + size--; + } + count++; + break; + case 'q': + q = 1; + format++; + goto doint; + case 'h': + h = 1; + format++; + goto doint; + case 'l': + l = 1; + format++; + if (*format == 'l') { + q = 1; + format++; + } + goto doint; + case 'n': + case 'i': + case 'd': + case 'o': + case 'u': + case 'x': + case 'X': + doint: + if (precision != 0) + zero = 0; + switch (*format) { + case 'n': + if (h) { + short int *p; + p = va_arg(ap, short *); + REQUIRE(p != NULL); + *p = str - save; + } else if (l) { + long int *p; + p = va_arg(ap, long *); + REQUIRE(p != NULL); + *p = str - save; + } else { + int *p; + p = va_arg(ap, int *); + REQUIRE(p != NULL); + *p = str - save; + } + break; + case 'i': + case 'd': + if (q) + tmpi = va_arg(ap, isc_int64_t); + else if (l) + tmpi = va_arg(ap, long int); + else + tmpi = va_arg(ap, int); + if (tmpi < 0) { + head = "-"; + tmpui = -tmpi; + } else { + if (plus) + head = "+"; + else if (space) + head = " "; + else + head = ""; + tmpui = tmpi; + } + sprintf(buf, "%u", tmpui); + goto printint; + case 'o': + if (q) + tmpui = va_arg(ap, isc_uint64_t); + else if (l) + tmpui = va_arg(ap, long int); + else + tmpui = va_arg(ap, int); + sprintf(buf, alt ? "%#o" + : "%o", tmpui); + goto printint; + case 'u': + if (q) + tmpui = va_arg(ap, isc_uint64_t); + else if (l) + tmpui = va_arg(ap, unsigned long int); + else + tmpui = va_arg(ap, unsigned int); + sprintf(buf, "%u", tmpui); + goto printint; + case 'x': + if (q) + tmpui = va_arg(ap, isc_uint64_t); + else if (l) + tmpui = va_arg(ap, unsigned long int); + else + tmpui = va_arg(ap, unsigned int); + if (alt) { + head = "0x"; + if (precision > 2) + precision -= 2; + } + sprintf(buf, "%x", tmpui); + goto printint; + case 'X': + if (q) + tmpui = va_arg(ap, isc_uint64_t); + else if (l) + tmpui = va_arg(ap, unsigned long int); + else + tmpui = va_arg(ap, unsigned int); + if (alt) { + head = "0X"; + if (precision > 2) + precision -= 2; + } + sprintf(buf, "%X", tmpui); + goto printint; + printint: + if (precision != 0 || width != 0) { + length = strlen(buf); + if (length < precision) + zeropad = precision - length; + else if (length < width && zero) + zeropad = width - length; + if (width != 0) { + pad = width - length - + zeropad - strlen(head); + if (pad < 0) + pad = 0; + } + } + count += strlen(head) + strlen(buf) + pad + + zeropad; + if (!left) { + while (pad > 0 && size > 1) { + *str++ = ' '; + size--; + pad--; + } + } + cp = head; + while (*cp != '\0' && size > 1) { + *str++ = *cp++; + size--; + } + while (zeropad > 0 && size > 1) { + *str++ = '0'; + size--; + zeropad--; + } + cp = buf; + while (*cp != '\0' && size > 1) { + *str++ = *cp++; + size--; + } + while (pad > 0 && size > 1) { + *str++ = ' '; + size--; + pad--; + } + break; + default: + break; + } + break; + case 's': + cp = va_arg(ap, char *); + REQUIRE(cp != NULL); + + if (precision != 0) { + /* + * cp need not be NULL terminated. + */ + const char *tp; + unsigned long n; + + n = precision; + tp = cp; + while (n != 0 && *tp != '\0') + n--, tp++; + length = precision - n; + } else { + length = strlen(cp); + } + if (width != 0) { + pad = width - length; + if (pad < 0) + pad = 0; + } + count += pad + length; + if (!left) + while (pad > 0 && size > 1) { + *str++ = ' '; + size--; + pad--; + } + if (precision != 0) + while (precision > 0 && *cp != '\0' && + size > 1) { + *str++ = *cp++; + size--; + precision--; + } + else + while (*cp != '\0' && size > 1) { + *str++ = *cp++; + size--; + } + while (pad > 0 && size > 1) { + *str++ = ' '; + size--; + pad--; + } + break; + case 'c': + c = va_arg(ap, int); + if (width > 0) { + count += width; + width--; + if (left) { + *str++ = c; + size--; + } + while (width-- > 0 && size > 1) { + *str++ = ' '; + size--; + } + if (!left && size > 1) { + *str++ = c; + size--; + } + } else { + count++; + if (size > 1) { + *str++ = c; + size--; + } + } + break; + case 'p': + v = va_arg(ap, void *); + sprintf(buf, "%p", v); + length = strlen(buf); + if (precision > length) + zeropad = precision - length; + if (width > 0) { + pad = width - length - zeropad; + if (pad < 0) + pad = 0; + } + count += length + pad + zeropad; + if (!left) + while (pad > 0 && size > 1) { + *str++ = ' '; + size--; + pad--; + } + cp = buf; + if (zeropad > 0 && buf[0] == '0' && + (buf[1] == 'x' || buf[1] == 'X')) { + if (size > 1) { + *str++ = *cp++; + size--; + } + if (size > 1) { + *str++ = *cp++; + size--; + } + while (zeropad > 0 && size > 1) { + *str++ = '0'; + size--; + zeropad--; + } + } + while (*cp != '\0' && size > 1) { + *str++ = *cp++; + size--; + } + while (pad > 0 && size > 1) { + *str++ = ' '; + size--; + pad--; + } + break; + case 'D': /*deprecated*/ + INSIST("use %ld instead of %D" == NULL); + case 'O': /*deprecated*/ + INSIST("use %lo instead of %O" == NULL); + case 'U': /*deprecated*/ + INSIST("use %lu instead of %U" == NULL); + + case 'L': +#ifdef HAVE_LONG_DOUBLE + l = 1; +#else + INSIST("long doubles are not supported" == NULL); +#endif + /*FALLTHROUGH*/ + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + if (!dot) + precision = 6; + /* + * IEEE floating point. + * MIN 2.2250738585072014E-308 + * MAX 1.7976931348623157E+308 + * VAX floating point has a smaller range than IEEE. + * + * precisions > 324 don't make much sense. + * if we cap the precision at 512 we will not + * overflow buf. + */ + if (precision > 512) + precision = 512; + sprintf(fmt, "%%%s%s.%lu%s%c", alt ? "#" : "", + plus ? "+" : space ? " " : "", + precision, l ? "L" : "", *format); + switch (*format) { + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': +#ifdef HAVE_LONG_DOUBLE + if (l) { + ldbl = va_arg(ap, long double); + sprintf(buf, fmt, ldbl); + } else +#endif + { + dbl = va_arg(ap, double); + sprintf(buf, fmt, dbl); + } + length = strlen(buf); + if (width > 0) { + pad = width - length; + if (pad < 0) + pad = 0; + } + count += length + pad; + if (!left) + while (pad > 0 && size > 1) { + *str++ = ' '; + size--; + pad--; + } + cp = buf; + while (*cp != ' ' && size > 1) { + *str++ = *cp++; + size--; + } + while (pad > 0 && size > 1) { + *str++ = ' '; + size--; + pad--; + } + break; + default: + continue; + } + break; + default: + continue; + } + format++; + } + if (size > 0) + *str = '\0'; + return (count); +} + +#endif Property changes on: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/iscprint.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/lpf.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/lpf.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/lpf.c (revision 131136) @@ -1,419 +1,410 @@ /* lpf.c Linux packet filter code, contributed by Brian Murrel at Interlinx Support Services in Vancouver, B.C. */ /* - * Copyright (c) 1996-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ */ #ifndef lint static char copyright[] = -"$Id: lpf.c,v 1.29.2.1 2002/11/17 02:26:58 dhankins Exp $ Copyright (c) 1996-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: lpf.c,v 1.29.2.2 2004/06/10 17:59:19 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE) #include #include #include #include #include #include #include "includes/netinet/ip.h" #include "includes/netinet/udp.h" #include "includes/netinet/if_ether.h" /* Reinitializes the specified interface after an address change. This is not required for packet-filter APIs. */ #ifdef USE_LPF_SEND void if_reinitialize_send (info) struct interface_info *info; { } #endif #ifdef USE_LPF_RECEIVE void if_reinitialize_receive (info) struct interface_info *info; { } #endif /* Called by get_interface_list for each interface that's discovered. Opens a packet filter for each interface and adds it to the select mask. */ int if_register_lpf (info) struct interface_info *info; { int sock; char filename[50]; int b; struct sockaddr sa; /* Make an LPF socket. */ if ((sock = socket(PF_PACKET, SOCK_PACKET, htons((short)ETH_P_ALL))) < 0) { if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT || errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT || errno == EAFNOSUPPORT || errno == EINVAL) { log_error ("socket: %m - make sure"); log_error ("CONFIG_PACKET (Packet socket) %s", "and CONFIG_FILTER"); log_error ("(Socket Filtering) are enabled %s", "in your kernel"); log_fatal ("configuration!"); } log_fatal ("Open a socket for LPF: %m"); } /* Bind to the interface name */ memset (&sa, 0, sizeof sa); sa.sa_family = AF_PACKET; strncpy (sa.sa_data, (const char *)info -> ifp, sizeof sa.sa_data); if (bind (sock, &sa, sizeof sa)) { if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT || errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT || errno == EAFNOSUPPORT || errno == EINVAL) { log_error ("socket: %m - make sure"); log_error ("CONFIG_PACKET (Packet socket) %s", "and CONFIG_FILTER"); log_error ("(Socket Filtering) are enabled %s", "in your kernel"); log_fatal ("configuration!"); } log_fatal ("Bind socket to interface: %m"); } return sock; } #endif /* USE_LPF_SEND || USE_LPF_RECEIVE */ #ifdef USE_LPF_SEND void if_register_send (info) struct interface_info *info; { /* If we're using the lpf API for sending and receiving, we don't need to register this interface twice. */ #ifndef USE_LPF_RECEIVE info -> wfdesc = if_register_lpf (info); #else info -> wfdesc = info -> rfdesc; #endif if (!quiet_interface_discovery) log_info ("Sending on LPF/%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; { /* don't need to close twice if we are using lpf for sending and receiving */ #ifndef USE_LPF_RECEIVE /* for LPF this is simple, packet filters are removed when sockets are closed */ close (info -> wfdesc); #endif info -> wfdesc = -1; if (!quiet_interface_discovery) log_info ("Disabling output on LPF/%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 : "")); } #endif /* USE_LPF_SEND */ #ifdef USE_LPF_RECEIVE /* Defined in bpf.c. We can't extern these in dhcpd.h without pulling in bpf includes... */ extern struct sock_filter dhcp_bpf_filter []; extern int dhcp_bpf_filter_len; #if defined (HAVE_TR_SUPPORT) extern struct sock_filter dhcp_bpf_tr_filter []; extern int dhcp_bpf_tr_filter_len; static void lpf_tr_filter_setup (struct interface_info *); #endif static void lpf_gen_filter_setup (struct interface_info *); void if_register_receive (info) struct interface_info *info; { /* Open a LPF device and hang it on this interface... */ info -> rfdesc = if_register_lpf (info); #if defined (HAVE_TR_SUPPORT) if (info -> hw_address.hbuf [0] == HTYPE_IEEE802) lpf_tr_filter_setup (info); else #endif lpf_gen_filter_setup (info); if (!quiet_interface_discovery) log_info ("Listening on LPF/%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_receive (info) struct interface_info *info; { /* for LPF this is simple, packet filters are removed when sockets are closed */ close (info -> rfdesc); info -> rfdesc = -1; if (!quiet_interface_discovery) log_info ("Disabling input on LPF/%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 : "")); } static void lpf_gen_filter_setup (info) struct interface_info *info; { struct sock_fprog p; /* Set up the bpf filter program structure. This is defined in bpf.c */ p.len = dhcp_bpf_filter_len; p.filter = dhcp_bpf_filter; /* Patch the server port into the LPF program... XXX changes to filter program may require changes to the insn number(s) used below! XXX */ dhcp_bpf_filter [8].k = ntohs ((short)local_port); if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p, sizeof p) < 0) { if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT || errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT || errno == EAFNOSUPPORT) { log_error ("socket: %m - make sure"); log_error ("CONFIG_PACKET (Packet socket) %s", "and CONFIG_FILTER"); log_error ("(Socket Filtering) are enabled %s", "in your kernel"); log_fatal ("configuration!"); } log_fatal ("Can't install packet filter program: %m"); } } #if defined (HAVE_TR_SUPPORT) static void lpf_tr_filter_setup (info) struct interface_info *info; { struct sock_fprog p; /* Set up the bpf filter program structure. This is defined in bpf.c */ p.len = dhcp_bpf_tr_filter_len; p.filter = dhcp_bpf_tr_filter; /* Patch the server port into the LPF program... XXX changes to filter program may require changes XXX to the insn number(s) used below! XXX Token ring filter is null - when/if we have a filter XXX that's not, we'll need this code. XXX dhcp_bpf_filter [?].k = ntohs (local_port); */ if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p, sizeof p) < 0) { if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT || errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT || errno == EAFNOSUPPORT) { log_error ("socket: %m - make sure"); log_error ("CONFIG_PACKET (Packet socket) %s", "and CONFIG_FILTER"); log_error ("(Socket Filtering) are enabled %s", "in your kernel"); log_fatal ("configuration!"); } log_fatal ("Can't install packet filter program: %m"); } } #endif /* HAVE_TR_SUPPORT */ #endif /* USE_LPF_RECEIVE */ #ifdef USE_LPF_SEND ssize_t send_packet (interface, packet, raw, len, from, to, hto) 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; { unsigned hbufp = 0, ibufp = 0; double hh [16]; double ih [1536 / sizeof (double)]; unsigned char *buf = (unsigned char *)ih; struct sockaddr sa; 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, (unsigned char *)hh, &hbufp, hto); fudge = hbufp % 4; /* IP header must be word-aligned. */ memcpy (buf + fudge, (unsigned char *)hh, hbufp); ibufp = hbufp + fudge; assemble_udp_ip_header (interface, buf, &ibufp, from.s_addr, to -> sin_addr.s_addr, to -> sin_port, (unsigned char *)raw, len); memcpy (buf + ibufp, raw, len); /* For some reason, SOCK_PACKET sockets can't be connected, so we have to do a sentdo every time. */ memset (&sa, 0, sizeof sa); sa.sa_family = AF_PACKET; strncpy (sa.sa_data, (const char *)interface -> ifp, sizeof sa.sa_data); result = sendto (interface -> wfdesc, buf + fudge, ibufp + len - fudge, 0, &sa, sizeof sa); if (result < 0) log_error ("send_packet: %m"); return result; } #endif /* USE_LPF_SEND */ #ifdef USE_LPF_RECEIVE ssize_t receive_packet (interface, buf, len, from, hfrom) struct interface_info *interface; unsigned char *buf; size_t len; struct sockaddr_in *from; struct hardware *hfrom; { int nread; int length = 0; int offset = 0; unsigned char ibuf [1536]; unsigned bufix = 0; length = read (interface -> rfdesc, ibuf, sizeof ibuf); if (length <= 0) return length; bufix = 0; /* Decode the physical header... */ offset = decode_hw_header (interface, ibuf, bufix, hfrom); /* If a physical layer checksum failed (dunno of any physical layer that supports this, but WTH), skip this packet. */ if (offset < 0) { return 0; } bufix += offset; length -= offset; /* Decode the IP and UDP headers... */ offset = decode_udp_ip_header (interface, ibuf, bufix, from, (unsigned char *)0, (unsigned)length); /* If the IP or UDP checksum was bad, skip the packet... */ if (offset < 0) return 0; bufix += offset; length -= offset; /* Copy out the data in the packet... */ memcpy (buf, &ibuf [bufix], length); return length; } int can_unicast_without_arp (ip) struct interface_info *ip; { return 1; } int can_receive_unicast_unconfigured (ip) struct interface_info *ip; { return 1; } int supports_multiple_interfaces (ip) struct interface_info *ip; { return 1; } void maybe_setup_fallback () { isc_result_t status; struct interface_info *fbi = (struct interface_info *)0; if (setup_fallback (&fbi, MDL)) { if_register_fallback (fbi); 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 Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/memory.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/memory.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/memory.c (revision 131136) @@ -1,170 +1,161 @@ /* memory.c Memory-resident database... */ /* - * Copyright (c) 1995-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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: memory.c,v 1.66.2.4 2002/11/17 02:26:58 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: memory.c,v 1.66.2.5 2004/06/10 17:59:19 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" struct group *root_group; group_hash_t *group_name_hash; int (*group_write_hook) (struct group_object *); isc_result_t delete_group (struct group_object *group, int writep) { struct group_object *d; /* The group should exist and be hashed - if not, it's invalid. */ if (group_name_hash) { d = (struct group_object *)0; group_hash_lookup (&d, group_name_hash, group -> name, strlen (group -> name), MDL); } else return ISC_R_INVALIDARG; if (!d) return ISC_R_INVALIDARG; /* Also not okay to delete a group that's not the one in the hash table. */ if (d != group) return ISC_R_INVALIDARG; /* If it's dynamic, and we're deleting it, we can just blow away the hash table entry. */ if ((group -> flags & GROUP_OBJECT_DYNAMIC) && !(group -> flags & GROUP_OBJECT_STATIC)) { group_hash_delete (group_name_hash, group -> name, strlen (group -> name), MDL); } else { group -> flags |= GROUP_OBJECT_DELETED; if (group -> group) group_dereference (&group -> group, MDL); } /* Store the group declaration in the lease file. */ if (writep && group_write_hook) { if (!(*group_write_hook) (group)) return ISC_R_IOERROR; } return ISC_R_SUCCESS; } isc_result_t supersede_group (struct group_object *group, int writep) { struct group_object *t, *u; isc_result_t status; /* Register the group in the group name hash table, so we can look it up later. */ if (group_name_hash) { t = (struct group_object *)0; group_hash_lookup (&t, group_name_hash, group -> name, strlen (group -> name), MDL); if (t && t != group) { /* If this isn't a dynamic entry, then we need to flag the replacement as not dynamic either - otherwise, if the dynamic entry is deleted later, the static entry will come back next time the server is stopped and restarted. */ if (!(t -> flags & GROUP_OBJECT_DYNAMIC)) group -> flags |= GROUP_OBJECT_STATIC; /* Delete the old object if it hasn't already been deleted. If it has already been deleted, get rid of the hash table entry. This is a legitimate situation - a deleted static object needs to be kept around so we remember it's deleted. */ if (!(t -> flags & GROUP_OBJECT_DELETED)) delete_group (t, 0); else { group_hash_delete (group_name_hash, group -> name, strlen (group -> name), MDL); group_object_dereference (&t, MDL); } } } else { group_new_hash (&group_name_hash, 0, MDL); t = (struct group_object *)0; } /* Add the group to the group name hash if it's not already there, and also thread it into the list of dynamic groups if appropriate. */ if (!t) { group_hash_add (group_name_hash, group -> name, strlen (group -> name), group, MDL); } /* Store the group declaration in the lease file. */ if (writep && group_write_hook) { if (!(*group_write_hook) (group)) return ISC_R_IOERROR; } return ISC_R_SUCCESS; } int clone_group (struct group **gp, struct group *group, const char *file, int line) { isc_result_t status; struct group *g = (struct group *)0; /* Normally gp should contain the null pointer, but for convenience it's permissible to clone a group into itself. */ if (*gp && *gp != group) return 0; if (!group_allocate (&g, file, line)) return 0; if (group == *gp) *gp = (struct group *)0; group_reference (gp, g, file, line); g -> authoritative = group -> authoritative; group_reference (&g -> next, group, file, line); group_dereference (&g, file, line); return 1; } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/nit.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/nit.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/nit.c (revision 131136) @@ -1,429 +1,420 @@ /* nit.c Network Interface Tap (NIT) network interface code, by Ted Lemon with one crucial tidbit of help from Stu Grossmen. */ /* - * Copyright (c) 1996-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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: nit.c,v 1.34.2.1 2002/11/17 02:26:58 dhankins Exp $ Copyright (c) 1996-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: nit.c,v 1.34.2.2 2004/06/10 17:59:19 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #if defined (USE_NIT_SEND) || defined (USE_NIT_RECEIVE) #include #include #include #include #include #include #include #include #include #include #include "includes/netinet/ip.h" #include "includes/netinet/udp.h" #include "includes/netinet/if_ether.h" /* Reinitializes the specified interface after an address change. This is not required for packet-filter APIs. */ #ifdef USE_NIT_SEND void if_reinitialize_send (info) struct interface_info *info; { } #endif #ifdef USE_NIT_RECEIVE void if_reinitialize_receive (info) struct interface_info *info; { } #endif /* Called by get_interface_list for each interface that's discovered. Opens a packet filter for each interface and adds it to the select mask. */ int if_register_nit (info) struct interface_info *info; { int sock; char filename[50]; struct ifreq ifr; struct strioctl sio; /* Open a NIT device */ sock = open ("/dev/nit", O_RDWR); if (sock < 0) log_fatal ("Can't open NIT device for %s: %m", info -> name); /* Set the NIT device to point at this interface. */ sio.ic_cmd = NIOCBIND; sio.ic_len = sizeof *(info -> ifp); sio.ic_dp = (char *)(info -> ifp); sio.ic_timout = INFTIM; if (ioctl (sock, I_STR, &sio) < 0) log_fatal ("Can't attach interface %s to nit device: %m", info -> name); /* Get the low-level address... */ sio.ic_cmd = SIOCGIFADDR; sio.ic_len = sizeof ifr; sio.ic_dp = (char *)𝔦 sio.ic_timout = INFTIM; if (ioctl (sock, I_STR, &sio) < 0) log_fatal ("Can't get physical layer address for %s: %m", info -> name); /* XXX code below assumes ethernet interface! */ info -> hw_address.hlen = 7; info -> hw_address.hbuf [0] = ARPHRD_ETHER; memcpy (&info -> hw_address.hbuf [1], ifr.ifr_ifru.ifru_addr.sa_data, 6); if (ioctl (sock, I_PUSH, "pf") < 0) log_fatal ("Can't push packet filter onto NIT for %s: %m", info -> name); return sock; } #endif /* USE_NIT_SEND || USE_NIT_RECEIVE */ #ifdef USE_NIT_SEND void if_register_send (info) struct interface_info *info; { /* If we're using the nit API for sending and receiving, we don't need to register this interface twice. */ #ifndef USE_NIT_RECEIVE struct packetfilt pf; struct strioctl sio; info -> wfdesc = if_register_nit (info); pf.Pf_Priority = 0; pf.Pf_FilterLen = 1; pf.Pf_Filter [0] = ENF_PUSHZERO; /* Set up an NIT filter that rejects everything... */ sio.ic_cmd = NIOCSETF; sio.ic_len = sizeof pf; sio.ic_dp = (char *)&pf; sio.ic_timout = INFTIM; if (ioctl (info -> wfdesc, I_STR, &sio) < 0) log_fatal ("Can't set NIT filter: %m"); #else info -> wfdesc = info -> rfdesc; #endif if (!quiet_interface_discovery) log_info ("Sending on NIT/%s%s%s", 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 nit API for sending and receiving, we don't need to register this interface twice. */ #ifndef USE_NIT_RECEIVE close (info -> wfdesc); #endif info -> wfdesc = -1; if (!quiet_interface_discovery) log_info ("Disabling output on NIT/%s%s%s", 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 : "")); } #endif /* USE_NIT_SEND */ #ifdef USE_NIT_RECEIVE /* Packet filter program... XXX Changes to the filter program may require changes to the constant offsets used in if_register_send to patch the NIT program! XXX */ void if_register_receive (info) struct interface_info *info; { int flag = 1; u_int32_t x; struct packetfilt pf; struct strioctl sio; u_int16_t addr [2]; struct timeval t; /* Open a NIT device and hang it on this interface... */ info -> rfdesc = if_register_nit (info); /* Set the snap length to 0, which means always take the whole packet. */ x = 0; if (ioctl (info -> rfdesc, NIOCSSNAP, &x) < 0) log_fatal ("Can't set NIT snap length on %s: %m", info -> name); /* Set the stream to byte stream mode */ if (ioctl (info -> rfdesc, I_SRDOPT, RMSGN) != 0) log_info ("I_SRDOPT failed on %s: %m", info -> name); #if 0 /* Push on the chunker... */ if (ioctl (info -> rfdesc, I_PUSH, "nbuf") < 0) log_fatal ("Can't push chunker onto NIT STREAM: %m"); /* Set the timeout to zero. */ t.tv_sec = 0; t.tv_usec = 0; if (ioctl (info -> rfdesc, NIOCSTIME, &t) < 0) log_fatal ("Can't set chunk timeout: %m"); #endif /* Ask for no header... */ x = 0; if (ioctl (info -> rfdesc, NIOCSFLAGS, &x) < 0) log_fatal ("Can't set NIT flags on %s: %m", info -> name); /* Set up the NIT filter program. */ /* XXX Unlike the BPF filter program, this one won't work if the XXX IP packet is fragmented or if there are options on the IP XXX header. */ pf.Pf_Priority = 0; pf.Pf_FilterLen = 0; pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + 6; pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT + ENF_CAND; pf.Pf_Filter [pf.Pf_FilterLen++] = htons (ETHERTYPE_IP); pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT; pf.Pf_Filter [pf.Pf_FilterLen++] = htons (IPPROTO_UDP); pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + 11; pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT + ENF_AND; pf.Pf_Filter [pf.Pf_FilterLen++] = htons (0xFF); pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_CAND; pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + 18; pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT + ENF_CAND; pf.Pf_Filter [pf.Pf_FilterLen++] = local_port; /* Install the filter... */ sio.ic_cmd = NIOCSETF; sio.ic_len = sizeof pf; sio.ic_dp = (char *)&pf; sio.ic_timout = INFTIM; if (ioctl (info -> rfdesc, I_STR, &sio) < 0) log_fatal ("Can't set NIT filter on %s: %m", info -> name); if (!quiet_interface_discovery) log_info ("Listening on NIT/%s%s%s", 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; { /* If we're using the nit API for sending and receiving, we don't need to register this interface twice. */ close (info -> rfdesc); info -> rfdesc = -1; if (!quiet_interface_discovery) log_info ("Disabling input on NIT/%s%s%s", 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 : "")); } #endif /* USE_NIT_RECEIVE */ #ifdef USE_NIT_SEND ssize_t send_packet (interface, packet, raw, len, from, to, hto) 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; { unsigned hbufp, ibufp; double hh [16]; double ih [1536 / sizeof (double)]; unsigned char *buf = (unsigned char *)ih; struct sockaddr *junk; struct strbuf ctl, data; struct sockaddr_in foo; int result; if (!strcmp (interface -> name, "fallback")) return send_fallback (interface, packet, raw, len, from, to, hto); /* Start with the sockaddr struct... */ junk = (struct sockaddr *)&hh [0]; hbufp = (((unsigned char *)&junk -> sa_data [0]) - (unsigned char *)&hh[0]); ibufp = 0; /* Assemble the headers... */ assemble_hw_header (interface, (unsigned char *)junk, &hbufp, hto); assemble_udp_ip_header (interface, buf, &ibufp, from.s_addr, to -> sin_addr.s_addr, to -> sin_port, (unsigned char *)raw, len); /* Copy the data into the buffer (yuk). */ memcpy (buf + ibufp, raw, len); /* Set up the sockaddr structure... */ #if USE_SIN_LEN junk -> sa_len = hbufp - 2; /* XXX */ #endif junk -> sa_family = AF_UNSPEC; /* Set up the msg_buf structure... */ ctl.buf = (char *)&hh [0]; ctl.maxlen = ctl.len = hbufp; data.buf = (char *)&ih [0]; data.maxlen = data.len = ibufp + len; result = putmsg (interface -> wfdesc, &ctl, &data, 0); if (result < 0) log_error ("send_packet: %m"); return result; } #endif /* USE_NIT_SEND */ #ifdef USE_NIT_RECEIVE ssize_t receive_packet (interface, buf, len, from, hfrom) struct interface_info *interface; unsigned char *buf; size_t len; struct sockaddr_in *from; struct hardware *hfrom; { int nread; int length = 0; int offset = 0; unsigned char ibuf [1536]; int bufix = 0; length = read (interface -> rfdesc, ibuf, sizeof ibuf); if (length <= 0) return length; /* Decode the physical header... */ offset = decode_hw_header (interface, ibuf, bufix, hfrom); /* If a physical layer checksum failed (dunno of any physical layer that supports this, but WTH), skip this packet. */ if (offset < 0) { return 0; } bufix += offset; length -= offset; /* Decode the IP and UDP headers... */ offset = decode_udp_ip_header (interface, ibuf, bufix, from, (unsigned char *)0, length); /* If the IP or UDP checksum was bad, skip the packet... */ if (offset < 0) return 0; bufix += offset; length -= offset; /* Copy out the data in the packet... */ memcpy (buf, &ibuf [bufix], length); return length; } int can_unicast_without_arp (ip) struct interface_info *ip; { return 1; } int can_receive_unicast_unconfigured (ip) struct interface_info *ip; { return 1; } int supports_multiple_interfaces (ip) struct interface_info *ip; { return 1; } void maybe_setup_fallback () { isc_result_t status; struct interface_info *fbi = (struct interface_info *)0; if (setup_fallback (&fbi, MDL)) { if_register_fallback (fbi); 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 Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/options.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/options.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/options.c (revision 131136) @@ -1,2257 +1,2248 @@ /* options.c DHCP options parsing and reassembly. */ /* - * Copyright (c) 1995-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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: options.c,v 1.85.2.12 2003/03/31 03:06:55 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: options.c,v 1.85.2.13 2004/06/10 17:59:19 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #define DHCP_OPTION_DATA #include "dhcpd.h" #include struct option *vendor_cfg_option; static void do_option_set PROTO ((pair *, struct option_cache *, enum statement_op)); /* Parse all available options out of the specified packet. */ int parse_options (packet) struct packet *packet; { int i; struct option_cache *op = (struct option_cache *)0; /* Allocate a new option state. */ if (!option_state_allocate (&packet -> options, MDL)) { packet -> options_valid = 0; return 0; } /* If we don't see the magic cookie, there's nothing to parse. */ if (memcmp (packet -> raw -> options, DHCP_OPTIONS_COOKIE, 4)) { packet -> options_valid = 0; return 1; } /* Go through the options field, up to the end of the packet or the End field. */ if (!parse_option_buffer (packet -> options, &packet -> raw -> options [4], (packet -> packet_length - DHCP_FIXED_NON_UDP - 4), &dhcp_universe)) return 0; /* If we parsed a DHCP Option Overload option, parse more options out of the buffer(s) containing them. */ if (packet -> options_valid && (op = lookup_option (&dhcp_universe, packet -> options, DHO_DHCP_OPTION_OVERLOAD))) { if (op -> data.data [0] & 1) { if (!parse_option_buffer (packet -> options, (unsigned char *)packet -> raw -> file, sizeof packet -> raw -> file, &dhcp_universe)) return 0; } if (op -> data.data [0] & 2) { if (!parse_option_buffer (packet -> options, (unsigned char *)packet -> raw -> sname, sizeof packet -> raw -> sname, &dhcp_universe)) return 0; } } packet -> options_valid = 1; return 1; } /* Parse options out of the specified buffer, storing addresses of option values in packet -> options and setting packet -> options_valid if no errors are encountered. */ int parse_option_buffer (options, buffer, length, universe) struct option_state *options; const unsigned char *buffer; unsigned length; struct universe *universe; { unsigned char *t; const unsigned char *end = buffer + length; unsigned len, offset; int code; struct option_cache *op = (struct option_cache *)0; struct buffer *bp = (struct buffer *)0; if (!buffer_allocate (&bp, length, MDL)) { log_error ("no memory for option buffer."); return 0; } memcpy (bp -> data, buffer, length); for (offset = 0; buffer [offset] != DHO_END && offset < length; ) { code = buffer [offset]; /* Pad options don't have a length - just skip them. */ if (code == DHO_PAD) { ++offset; continue; } /* Don't look for length if the buffer isn't that big. */ if (offset + 2 > length) { len = 65536; goto bogus; } /* All other fields (except end, see above) have a one-byte length. */ len = buffer [offset + 1]; /* If the length is outrageous, the options are bad. */ if (offset + len + 2 > length) { bogus: log_error ("parse_option_buffer: option %s (%d) %s.", dhcp_options [code].name, len, "larger than buffer"); buffer_dereference (&bp, MDL); return 0; } /* If the option contains an encapsulation, parse it. If the parse fails, or the option isn't an encapsulation (by far the most common case), or the option isn't entirely an encapsulation, keep the raw data as well. */ if (universe -> options [code] && !((universe -> options [code] -> format [0] == 'e' || universe -> options [code] -> format [0] == 'E') && (parse_encapsulated_suboptions (options, universe -> options [code], buffer + offset + 2, len, universe, (const char *)0)))) { op = lookup_option (universe, options, code); if (op) { struct data_string new; memset (&new, 0, sizeof new); if (!buffer_allocate (&new.buffer, op -> data.len + len, MDL)) { log_error ("parse_option_buffer: No memory."); return 0; } memcpy (new.buffer -> data, op -> data.data, op -> data.len); memcpy (&new.buffer -> data [op -> data.len], &bp -> data [offset + 2], len); new.len = op -> data.len + len; new.data = new.buffer -> data; data_string_forget (&op -> data, MDL); data_string_copy (&op -> data, &new, MDL); data_string_forget (&new, MDL); } else { save_option_buffer (universe, options, bp, &bp -> data [offset + 2], len, universe -> options [code], 1); } } offset += len + 2; } buffer_dereference (&bp, MDL); return 1; } /* If an option in an option buffer turns out to be an encapsulation, figure out what to do. If we don't know how to de-encapsulate it, or it's not well-formed, return zero; otherwise, return 1, indicating that we succeeded in de-encapsulating it. */ struct universe *find_option_universe (struct option *eopt, const char *uname) { int i; char *s, *t; struct universe *universe = (struct universe *)0; /* Look for the E option in the option format. */ s = strchr (eopt -> format, 'E'); if (!s) { log_error ("internal encapsulation format error 1."); return 0; } /* Look for the universe name in the option format. */ t = strchr (++s, '.'); /* If there was no trailing '.', or there's something after the trailing '.', the option is bogus and we can't use it. */ if (!t || t [1]) { log_error ("internal encapsulation format error 2."); return 0; } if (t == s && uname) { for (i = 0; i < universe_count; i++) { if (!strcmp (universes [i] -> name, uname)) { universe = universes [i]; break; } } } else if (t != s) { for (i = 0; i < universe_count; i++) { if (strlen (universes [i] -> name) == t - s && !memcmp (universes [i] -> name, s, (unsigned)(t - s))) { universe = universes [i]; break; } } } return universe; } /* If an option in an option buffer turns out to be an encapsulation, figure out what to do. If we don't know how to de-encapsulate it, or it's not well-formed, return zero; otherwise, return 1, indicating that we succeeded in de-encapsulating it. */ int parse_encapsulated_suboptions (struct option_state *options, struct option *eopt, const unsigned char *buffer, unsigned len, struct universe *eu, const char *uname) { int i; struct universe *universe = find_option_universe (eopt, uname); /* If we didn't find the universe, we can't do anything with it right now (e.g., we can't decode vendor options until we've decoded the packet and executed the scopes that it matches). */ if (!universe) return 0; /* If we don't have a decoding function for it, we can't decode it. */ if (!universe -> decode) return 0; i = (*universe -> decode) (options, buffer, len, universe); /* If there is stuff before the suboptions, we have to keep it. */ if (eopt -> format [0] != 'E') return 0; /* Otherwise, return the status of the decode function. */ return i; } int fqdn_universe_decode (struct option_state *options, const unsigned char *buffer, unsigned length, struct universe *u) { char *name; struct buffer *bp = (struct buffer *)0; /* FQDN options have to be at least four bytes long. */ if (length < 3) return 0; /* Save the contents of the option in a buffer. */ if (!buffer_allocate (&bp, length + 4, MDL)) { log_error ("no memory for option buffer."); return 0; } memcpy (&bp -> data [3], buffer + 1, length - 1); if (buffer [0] & 4) /* encoded */ bp -> data [0] = 1; else bp -> data [0] = 0; if (!save_option_buffer (&fqdn_universe, options, bp, &bp -> data [0], 1, &fqdn_options [FQDN_ENCODED], 0)) { bad: buffer_dereference (&bp, MDL); return 0; } if (buffer [0] & 1) /* server-update */ bp -> data [2] = 1; else bp -> data [2] = 0; if (buffer [0] & 2) /* no-client-update */ bp -> data [1] = 1; else bp -> data [1] = 0; /* XXX Ideally we should store the name in DNS format, so if the XXX label isn't in DNS format, we convert it to DNS format, XXX rather than converting labels specified in DNS format to XXX the plain ASCII representation. But that's hard, so XXX not now. */ /* Not encoded using DNS format? */ if (!bp -> data [0]) { unsigned i; /* Some broken clients NUL-terminate this option. */ if (buffer [length - 1] == 0) { --length; bp -> data [1] = 1; } /* Determine the length of the hostname component of the name. If the name contains no '.' character, it represents a non-qualified label. */ for (i = 3; i < length && buffer [i] != '.'; i++); i -= 3; /* Note: If the client sends a FQDN, the first '.' will be used as a NUL terminator for the hostname. */ if (i) if (!save_option_buffer (&fqdn_universe, options, bp, &bp -> data[5], i, &fqdn_options [FQDN_HOSTNAME], 0)) goto bad; /* Note: If the client sends a single label, the FQDN_DOMAINNAME option won't be set. */ if (length > 4 + i && !save_option_buffer (&fqdn_universe, options, bp, &bp -> data[6 + i], length - 4 - i, &fqdn_options [FQDN_DOMAINNAME], 1)) goto bad; /* Also save the whole name. */ if (length > 3) if (!save_option_buffer (&fqdn_universe, options, bp, &bp -> data [5], length - 3, &fqdn_options [FQDN_FQDN], 1)) goto bad; } else { unsigned len; unsigned total_len = 0; unsigned first_len = 0; int terminated = 0; unsigned char *s; s = &bp -> data[5]; while (s < &bp -> data[0] + length + 2) { len = *s; if (len > 63) { log_info ("fancy bits in fqdn option"); return 0; } if (len == 0) { terminated = 1; break; } if (s + len > &bp -> data [0] + length + 3) { log_info ("fqdn tag longer than buffer"); return 0; } if (first_len == 0) { first_len = len; } *s = '.'; s += len + 1; total_len += len + 1; } /* We wind up with a length that's one too many because we shouldn't increment for the last label, but there's no way to tell we're at the last label until we exit the loop. :'*/ if (total_len > 0) total_len--; if (!terminated) { first_len = total_len; } if (first_len > 0 && !save_option_buffer (&fqdn_universe, options, bp, &bp -> data[6], first_len, &fqdn_options [FQDN_HOSTNAME], 0)) goto bad; if (total_len > 0 && first_len != total_len) { if (!save_option_buffer (&fqdn_universe, options, bp, &bp -> data[6 + first_len], total_len - first_len, &fqdn_options [FQDN_DOMAINNAME], 1)) goto bad; } if (total_len > 0) if (!save_option_buffer (&fqdn_universe, options, bp, &bp -> data [6], total_len, &fqdn_options [FQDN_FQDN], 1)) goto bad; } if (!save_option_buffer (&fqdn_universe, options, bp, &bp -> data [1], 1, &fqdn_options [FQDN_NO_CLIENT_UPDATE], 0)) goto bad; if (!save_option_buffer (&fqdn_universe, options, bp, &bp -> data [2], 1, &fqdn_options [FQDN_SERVER_UPDATE], 0)) goto bad; if (!save_option_buffer (&fqdn_universe, options, bp, &bp -> data [3], 1, &fqdn_options [FQDN_RCODE1], 0)) goto bad; if (!save_option_buffer (&fqdn_universe, options, bp, &bp -> data [4], 1, &fqdn_options [FQDN_RCODE2], 0)) goto bad; buffer_dereference (&bp, MDL); return 1; } /* cons options into a big buffer, and then split them out into the three seperate buffers if needed. This allows us to cons up a set of vendor options using the same routine. */ int cons_options (inpacket, outpacket, lease, client_state, mms, in_options, cfg_options, scope, overload, terminate, bootpp, prl, vuname) struct packet *inpacket; struct dhcp_packet *outpacket; struct lease *lease; struct client_state *client_state; int mms; struct option_state *in_options; struct option_state *cfg_options; struct binding_scope **scope; int overload; /* Overload flags that may be set. */ int terminate; int bootpp; struct data_string *prl; const char *vuname; { #define PRIORITY_COUNT 300 unsigned priority_list [PRIORITY_COUNT]; int priority_len; unsigned char buffer [4096]; /* Really big buffer... */ unsigned main_buffer_size; unsigned mainbufix, bufix, agentix; unsigned option_size; unsigned length; int i; struct option_cache *op; struct data_string ds; pair pp, *hash; int need_endopt = 0; int have_sso = 0; memset (&ds, 0, sizeof ds); /* If there's a Maximum Message Size option in the incoming packet and no alternate maximum message size has been specified, take the one in the packet. */ if (inpacket && (op = lookup_option (&dhcp_universe, inpacket -> options, DHO_DHCP_MAX_MESSAGE_SIZE))) { evaluate_option_cache (&ds, inpacket, lease, client_state, in_options, cfg_options, scope, op, MDL); if (ds.len >= sizeof (u_int16_t)) { i = getUShort (ds.data); if(!mms || (i < mms)) mms = i; } data_string_forget (&ds, MDL); } /* If the client has provided a maximum DHCP message size, use that; otherwise, if it's BOOTP, only 64 bytes; otherwise use up to the minimum IP MTU size (576 bytes). */ /* XXX if a BOOTP client specifies a max message size, we will honor it. */ if (mms) { main_buffer_size = mms - DHCP_FIXED_LEN; /* Enforce a minimum packet size... */ if (main_buffer_size < (576 - DHCP_FIXED_LEN)) main_buffer_size = 576 - DHCP_FIXED_LEN; } else if (bootpp) { if (inpacket) { main_buffer_size = inpacket -> packet_length - DHCP_FIXED_LEN; if (main_buffer_size < 64) main_buffer_size = 64; } else main_buffer_size = 64; } else main_buffer_size = 576 - DHCP_FIXED_LEN; /* Set a hard limit at the size of the output buffer. */ if (main_buffer_size > sizeof buffer) main_buffer_size = sizeof buffer; /* Preload the option priority list with mandatory options. */ priority_len = 0; priority_list [priority_len++] = DHO_DHCP_MESSAGE_TYPE; priority_list [priority_len++] = DHO_DHCP_SERVER_IDENTIFIER; priority_list [priority_len++] = DHO_DHCP_LEASE_TIME; priority_list [priority_len++] = DHO_DHCP_MESSAGE; priority_list [priority_len++] = DHO_DHCP_REQUESTED_ADDRESS; priority_list [priority_len++] = DHO_FQDN; if (prl && prl -> len > 0) { if ((op = lookup_option (&dhcp_universe, cfg_options, DHO_SUBNET_SELECTION))) { if (priority_len < PRIORITY_COUNT) priority_list [priority_len++] = DHO_SUBNET_SELECTION; } data_string_truncate (prl, (PRIORITY_COUNT - priority_len)); for (i = 0; i < prl -> len; i++) { /* Prevent client from changing order of delivery of relay agent information option. */ if (prl -> data [i] != DHO_DHCP_AGENT_OPTIONS) priority_list [priority_len++] = prl -> data [i]; } } else { /* First, hardcode some more options that ought to be sent first... */ priority_list [priority_len++] = DHO_SUBNET_MASK; priority_list [priority_len++] = DHO_ROUTERS; priority_list [priority_len++] = DHO_DOMAIN_NAME_SERVERS; priority_list [priority_len++] = DHO_HOST_NAME; /* Append a list of the standard DHCP options from the standard DHCP option space. Actually, if a site option space hasn't been specified, we wind up treating the dhcp option space as the site option space, and the first for loop is skipped, because it's slightly more general to do it this way, taking the 1Q99 DHCP futures work into account. */ if (cfg_options -> site_code_min) { for (i = 0; i < OPTION_HASH_SIZE; i++) { hash = cfg_options -> universes [dhcp_universe.index]; if (hash) { for (pp = hash [i]; pp; pp = pp -> cdr) { op = (struct option_cache *)(pp -> car); if (op -> option -> code < cfg_options -> site_code_min && priority_len < PRIORITY_COUNT && (op -> option -> code != DHO_DHCP_AGENT_OPTIONS)) priority_list [priority_len++] = op -> option -> code; } } } } /* Now cycle through the site option space, or if there is no site option space, we'll be cycling through the dhcp option space. */ for (i = 0; i < OPTION_HASH_SIZE; i++) { hash = (cfg_options -> universes [cfg_options -> site_universe]); if (hash) for (pp = hash [i]; pp; pp = pp -> cdr) { op = (struct option_cache *)(pp -> car); if (op -> option -> code >= cfg_options -> site_code_min && priority_len < PRIORITY_COUNT && (op -> option -> code != DHO_DHCP_AGENT_OPTIONS)) priority_list [priority_len++] = op -> option -> code; } } /* Now go through all the universes for which options were set and see if there are encapsulations for them; if there are, put the encapsulation options on the priority list as well. */ for (i = 0; i < cfg_options -> universe_count; i++) { if (cfg_options -> universes [i] && universes [i] -> enc_opt && priority_len < PRIORITY_COUNT && universes [i] -> enc_opt -> universe == &dhcp_universe) { if (universes [i] -> enc_opt -> code != DHO_DHCP_AGENT_OPTIONS) priority_list [priority_len++] = universes [i] -> enc_opt -> code; } } /* The vendor option space can't stand on its own, so always add it to the list. */ if (priority_len < PRIORITY_COUNT) priority_list [priority_len++] = DHO_VENDOR_ENCAPSULATED_OPTIONS; } /* Copy the options into the big buffer... */ option_size = store_options (buffer, (main_buffer_size - 7 + ((overload & 1) ? DHCP_FILE_LEN : 0) + ((overload & 2) ? DHCP_SNAME_LEN : 0)), inpacket, lease, client_state, in_options, cfg_options, scope, priority_list, priority_len, main_buffer_size, (main_buffer_size + ((overload & 1) ? DHCP_FILE_LEN : 0)), terminate, vuname); /* Put the cookie up front... */ memcpy (outpacket -> options, DHCP_OPTIONS_COOKIE, 4); mainbufix = 4; /* If we're going to have to overload, store the overload option at the beginning. If we can, though, just store the whole thing in the packet's option buffer and leave it at that. */ if (option_size <= main_buffer_size - mainbufix) { memcpy (&outpacket -> options [mainbufix], buffer, option_size); mainbufix += option_size; agentix = mainbufix; if (mainbufix < main_buffer_size) need_endopt = 1; length = DHCP_FIXED_NON_UDP + mainbufix; } else { outpacket -> options [mainbufix++] = DHO_DHCP_OPTION_OVERLOAD; outpacket -> options [mainbufix++] = 1; if (option_size > main_buffer_size - mainbufix + DHCP_FILE_LEN) outpacket -> options [mainbufix++] = 3; else outpacket -> options [mainbufix++] = 1; memcpy (&outpacket -> options [mainbufix], buffer, main_buffer_size - mainbufix); length = DHCP_FIXED_NON_UDP + main_buffer_size; agentix = main_buffer_size; bufix = main_buffer_size - mainbufix; if (overload & 1) { if (option_size - bufix <= DHCP_FILE_LEN) { memcpy (outpacket -> file, &buffer [bufix], option_size - bufix); mainbufix = option_size - bufix; if (mainbufix < DHCP_FILE_LEN) outpacket -> file [mainbufix++] = DHO_END; while (mainbufix < DHCP_FILE_LEN) outpacket -> file [mainbufix++] = DHO_PAD; } else { memcpy (outpacket -> file, &buffer [bufix], DHCP_FILE_LEN); bufix += DHCP_FILE_LEN; } } if ((overload & 2) && option_size < bufix) { memcpy (outpacket -> sname, &buffer [bufix], option_size - bufix); mainbufix = option_size - bufix; if (mainbufix < DHCP_SNAME_LEN) outpacket -> file [mainbufix++] = DHO_END; while (mainbufix < DHCP_SNAME_LEN) outpacket -> file [mainbufix++] = DHO_PAD; } } /* Now hack in the agent options if there are any. */ priority_list [0] = DHO_DHCP_AGENT_OPTIONS; priority_len = 1; agentix += store_options (&outpacket -> options [agentix], 1500 - DHCP_FIXED_LEN - agentix, inpacket, lease, client_state, in_options, cfg_options, scope, priority_list, priority_len, 1500 - DHCP_FIXED_LEN - agentix, 1500 - DHCP_FIXED_LEN - agentix, 0, (char *)0); /* Tack a DHO_END option onto the packet if we need to. */ if (agentix < 1500 - DHCP_FIXED_LEN && need_endopt) outpacket -> options [agentix++] = DHO_END; /* Figure out the length. */ length = DHCP_FIXED_NON_UDP + agentix; return length; } /* Store all the requested options into the requested buffer. */ int store_options (buffer, buflen, packet, lease, client_state, in_options, cfg_options, scope, priority_list, priority_len, first_cutoff, second_cutoff, terminate, vuname) unsigned char *buffer; unsigned buflen; 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; unsigned *priority_list; int priority_len; unsigned first_cutoff, second_cutoff; int terminate; const char *vuname; { int bufix = 0; int i; int ix; int tto; struct data_string od; struct option_cache *oc; unsigned code; int optstart; memset (&od, 0, sizeof od); /* Eliminate duplicate options in the parameter request list. There's got to be some clever knuthian way to do this: Eliminate all but the first occurance of a value in an array of values without otherwise disturbing the order of the array. */ for (i = 0; i < priority_len - 1; i++) { tto = 0; for (ix = i + 1; ix < priority_len + tto; ix++) { if (tto) priority_list [ix - tto] = priority_list [ix]; if (priority_list [i] == priority_list [ix]) { tto++; priority_len--; } } } /* Copy out the options in the order that they appear in the priority list... */ for (i = 0; i < priority_len; i++) { /* Number of bytes left to store (some may already have been stored by a previous pass). */ unsigned length; int optstart; struct universe *u; int have_encapsulation = 0; struct data_string encapsulation; memset (&encapsulation, 0, sizeof encapsulation); /* Code for next option to try to store. */ code = priority_list [i]; /* Look up the option in the site option space if the code is above the cutoff, otherwise in the DHCP option space. */ if (code >= cfg_options -> site_code_min) u = universes [cfg_options -> site_universe]; else u = &dhcp_universe; oc = lookup_option (u, cfg_options, code); /* It's an encapsulation, try to find the universe to be encapsulated first, except that if it's a straight encapsulation and the user has provided a value for the encapsulation option, use the user-provided value. */ if (u -> options [code] && ((u -> options [code] -> format [0] == 'E' && !oc) || u -> options [code] -> format [0] == 'e')) { int uix; static char *s, *t; struct option_cache *tmp; struct data_string name; s = strchr (u -> options [code] -> format, 'E'); if (s) t = strchr (++s, '.'); if (s && t) { memset (&name, 0, sizeof name); /* A zero-length universe name means the vendor option space, if one is defined. */ if (t == s) { if (vendor_cfg_option) { tmp = lookup_option (vendor_cfg_option -> universe, cfg_options, vendor_cfg_option -> code); if (tmp) evaluate_option_cache (&name, packet, lease, client_state, in_options, cfg_options, scope, tmp, MDL); } else if (vuname) { name.data = (unsigned char *)s; name.len = strlen (s); } } else { name.data = (unsigned char *)s; name.len = t - s; } /* If we found a universe, and there are options configured for that universe, try to encapsulate it. */ if (name.len) { have_encapsulation = (option_space_encapsulate (&encapsulation, packet, lease, client_state, in_options, cfg_options, scope, &name)); data_string_forget (&name, MDL); } } } /* In order to avoid memory leaks, we have to get to here with any option cache that we allocated in tmp not being referenced by tmp, and whatever option cache is referenced by oc being an actual reference. lookup_option doesn't generate a reference (this needs to be fixed), so the preceding goop ensures that if we *didn't* generate a new option cache, oc still winds up holding an actual reference. */ /* If no data is available for this option, skip it. */ if (!oc && !have_encapsulation) { continue; } /* Find the value of the option... */ if (oc) { evaluate_option_cache (&od, packet, lease, client_state, in_options, cfg_options, scope, oc, MDL); if (!od.len) { data_string_forget (&encapsulation, MDL); data_string_forget (&od, MDL); have_encapsulation = 0; continue; } } /* We should now have a constant length for the option. */ length = od.len; if (have_encapsulation) { length += encapsulation.len; if (!od.len) { data_string_copy (&od, &encapsulation, MDL); data_string_forget (&encapsulation, MDL); } else { struct buffer *bp = (struct buffer *)0; if (!buffer_allocate (&bp, length, MDL)) { option_cache_dereference (&oc, MDL); data_string_forget (&od, MDL); data_string_forget (&encapsulation, MDL); continue; } memcpy (&bp -> data [0], od.data, od.len); memcpy (&bp -> data [od.len], encapsulation.data, encapsulation.len); data_string_forget (&od, MDL); data_string_forget (&encapsulation, MDL); od.data = &bp -> data [0]; buffer_reference (&od.buffer, bp, MDL); buffer_dereference (&bp, MDL); od.len = length; od.terminated = 0; } } /* Do we add a NUL? */ if (terminate && dhcp_options [code].format [0] == 't') { length++; tto = 1; } else { tto = 0; } /* Try to store the option. */ /* If the option's length is more than 255, we must store it in multiple hunks. Store 255-byte hunks first. However, in any case, if the option data will cross a buffer boundary, split it across that boundary. */ ix = 0; optstart = bufix; while (length) { unsigned char incr = length > 255 ? 255 : length; int consumed = 0; /* If this hunk of the buffer will cross a boundary, only go up to the boundary in this pass. */ if (bufix < first_cutoff && bufix + incr > first_cutoff) incr = first_cutoff - bufix; else if (bufix < second_cutoff && bufix + incr > second_cutoff) incr = second_cutoff - bufix; /* If this option is going to overflow the buffer, skip it. */ if (bufix + 2 + incr > buflen) { bufix = optstart; break; } /* Everything looks good - copy it in! */ buffer [bufix] = code; buffer [bufix + 1] = incr; if (tto && incr == length) { memcpy (buffer + bufix + 2, od.data + ix, (unsigned)(incr - 1)); buffer [bufix + 2 + incr - 1] = 0; } else { memcpy (buffer + bufix + 2, od.data + ix, (unsigned)incr); } length -= incr; ix += incr; bufix += 2 + incr; } data_string_forget (&od, MDL); } return bufix; } /* Format the specified option so that a human can easily read it. */ const char *pretty_print_option (option, data, len, emit_commas, emit_quotes) struct option *option; const unsigned char *data; unsigned len; int emit_commas; int emit_quotes; { static char optbuf [32768]; /* XXX */ int hunksize = 0; int opthunk = 0; int hunkinc = 0; int numhunk = -1; int numelem = 0; char fmtbuf [32]; struct enumeration *enumbuf [32]; int i, j, k, l; char *op = optbuf; const unsigned char *dp = data; struct in_addr foo; char comma; unsigned long tval; if (emit_commas) comma = ','; else comma = ' '; memset (enumbuf, 0, sizeof enumbuf); /* Figure out the size of the data. */ for (l = i = 0; option -> format [i]; i++, l++) { if (!numhunk) { log_error ("%s: Extra codes in format string: %s", option -> name, &(option -> format [i])); break; } numelem++; fmtbuf [l] = option -> format [i]; switch (option -> format [i]) { case 'a': --numelem; fmtbuf [l] = 0; numhunk = 0; break; case 'A': --numelem; fmtbuf [l] = 0; numhunk = 0; break; case 'E': /* Skip the universe name. */ while (option -> format [i] && option -> format [i] != '.') i++; case 'X': for (k = 0; k < len; k++) { if (!isascii (data [k]) || !isprint (data [k])) break; } /* If we found no bogus characters, or the bogus character we found is a trailing NUL, it's okay to print this option as text. */ if (k == len || (k + 1 == len && data [k] == 0)) { fmtbuf [l] = 't'; numhunk = -2; } else { fmtbuf [l] = 'x'; hunksize++; comma = ':'; numhunk = 0; } fmtbuf [l + 1] = 0; break; case 'd': case 't': fmtbuf [l] = 't'; fmtbuf [l + 1] = 0; numhunk = -2; break; case 'N': k = i; while (option -> format [i] && option -> format [i] != '.') i++; enumbuf [l] = find_enumeration (&option -> format [k] + 1, i - k - 1); hunksize += 1; hunkinc = 1; break; case 'I': case 'l': case 'L': case 'T': hunksize += 4; hunkinc = 4; break; case 's': case 'S': hunksize += 2; hunkinc = 2; break; case 'b': case 'B': case 'f': hunksize++; hunkinc = 1; break; case 'e': break; case 'o': opthunk += hunkinc; break; default: log_error ("%s: garbage in format string: %s", option -> name, &(option -> format [i])); break; } } /* Check for too few bytes... */ if (hunksize - opthunk > len) { log_error ("%s: expecting at least %d bytes; got %d", option -> name, hunksize, len); return ""; } /* Check for too many bytes... */ if (numhunk == -1 && hunksize < len) log_error ("%s: %d extra bytes", option -> name, len - hunksize); /* If this is an array, compute its size. */ if (!numhunk) numhunk = len / hunksize; /* See if we got an exact number of hunks. */ if (numhunk > 0 && numhunk * hunksize < len) log_error ("%s: %d extra bytes at end of array\n", option -> name, len - numhunk * hunksize); /* A one-hunk array prints the same as a single hunk. */ if (numhunk < 0) numhunk = 1; /* Cycle through the array (or hunk) printing the data. */ for (i = 0; i < numhunk; i++) { for (j = 0; j < numelem; j++) { switch (fmtbuf [j]) { case 't': if (emit_quotes) *op++ = '"'; for (; dp < data + len; dp++) { if (!isascii (*dp) || !isprint (*dp)) { /* Skip trailing NUL. */ if (dp + 1 != data + len || *dp != 0) { sprintf (op, "\\%03o", *dp); op += 4; } } else if (*dp == '"' || *dp == '\'' || *dp == '$' || *dp == '`' || *dp == '\\') { *op++ = '\\'; *op++ = *dp; } else *op++ = *dp; } if (emit_quotes) *op++ = '"'; *op = 0; break; /* pretty-printing an array of enums is going to get ugly. */ case 'N': if (!enumbuf [j]) goto enum_as_num; for (i = 0; ;i++) { if (!enumbuf [j] -> values [i].name) goto enum_as_num; if (enumbuf [j] -> values [i].value == *dp) break; } strcpy (op, enumbuf [j] -> values [i].name); op += strlen (op); break; case 'I': foo.s_addr = htonl (getULong (dp)); strcpy (op, inet_ntoa (foo)); dp += 4; break; case 'l': sprintf (op, "%ld", (long)getLong (dp)); dp += 4; break; case 'T': tval = getULong (dp); if (tval == -1) sprintf (op, "%s", "infinite"); else sprintf (op, "%ld", tval); break; case 'L': sprintf (op, "%ld", (unsigned long)getULong (dp)); dp += 4; break; case 's': sprintf (op, "%d", (int)getShort (dp)); dp += 2; break; case 'S': sprintf (op, "%d", (unsigned)getUShort (dp)); dp += 2; break; case 'b': sprintf (op, "%d", *(const char *)dp++); break; case 'B': enum_as_num: sprintf (op, "%d", *dp++); break; case 'x': sprintf (op, "%x", *dp++); break; case 'f': strcpy (op, *dp++ ? "true" : "false"); break; default: log_error ("Unexpected format code %c", fmtbuf [j]); } op += strlen (op); if (dp == data + len) break; if (j + 1 < numelem && comma != ':') *op++ = ' '; } if (i + 1 < numhunk) { *op++ = comma; } if (dp == data + len) break; } return optbuf; } int get_option (result, universe, packet, lease, client_state, in_options, cfg_options, options, scope, code, file, line) struct data_string *result; struct universe *universe; struct packet *packet; struct lease *lease; struct client_state *client_state; struct option_state *in_options; struct option_state *cfg_options; struct option_state *options; struct binding_scope **scope; unsigned code; const char *file; int line; { struct option_cache *oc; if (!universe -> lookup_func) return 0; oc = ((*universe -> lookup_func) (universe, options, code)); if (!oc) return 0; if (!evaluate_option_cache (result, packet, lease, client_state, in_options, cfg_options, scope, oc, file, line)) return 0; return 1; } void set_option (universe, options, option, op) struct universe *universe; struct option_state *options; struct option_cache *option; enum statement_op op; { struct option_cache *oc, *noc; switch (op) { case if_statement: case add_statement: case eval_statement: case break_statement: default: log_error ("bogus statement type in do_option_set."); break; case default_option_statement: oc = lookup_option (universe, options, option -> option -> code); if (oc) break; save_option (universe, options, option); break; case supersede_option_statement: case send_option_statement: /* Install the option, replacing any existing version. */ save_option (universe, options, option); break; case append_option_statement: case prepend_option_statement: oc = lookup_option (universe, options, option -> option -> code); if (!oc) { save_option (universe, options, option); break; } /* If it's not an expression, make it into one. */ if (!oc -> expression && oc -> data.len) { if (!expression_allocate (&oc -> expression, MDL)) { log_error ("Can't allocate const expression."); break; } oc -> expression -> op = expr_const_data; data_string_copy (&oc -> expression -> data.const_data, &oc -> data, MDL); data_string_forget (&oc -> data, MDL); } noc = (struct option_cache *)0; if (!option_cache_allocate (&noc, MDL)) break; if (op == append_option_statement) { if (!make_concat (&noc -> expression, oc -> expression, option -> expression)) { option_cache_dereference (&noc, MDL); break; } } else { if (!make_concat (&noc -> expression, option -> expression, oc -> expression)) { option_cache_dereference (&noc, MDL); break; } } noc -> option = oc -> option; save_option (universe, options, noc); option_cache_dereference (&noc, MDL); break; } } struct option_cache *lookup_option (universe, options, code) struct universe *universe; struct option_state *options; unsigned code; { if (!options) return (struct option_cache *)0; if (universe -> lookup_func) return (*universe -> lookup_func) (universe, options, code); else log_error ("can't look up options in %s space.", universe -> name); return (struct option_cache *)0; } struct option_cache *lookup_hashed_option (universe, options, code) struct universe *universe; struct option_state *options; unsigned code; { int hashix; pair bptr; pair *hash; /* Make sure there's a hash table. */ if (universe -> index >= options -> universe_count || !(options -> universes [universe -> index])) return (struct option_cache *)0; hash = options -> universes [universe -> index]; hashix = compute_option_hash (code); for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) { if (((struct option_cache *)(bptr -> car)) -> option -> code == code) return (struct option_cache *)(bptr -> car); } return (struct option_cache *)0; } int save_option_buffer (struct universe *universe, struct option_state *options, struct buffer *bp, unsigned char *buffer, unsigned length, struct option *option, int tp) { struct buffer *lbp = (struct buffer *)0; struct option_cache *op = (struct option_cache *)0; if (!option_cache_allocate (&op, MDL)) { log_error ("No memory for option %s.%s.", universe -> name, option -> name); return 0; } /* If we weren't passed a buffer in which the data are saved and refcounted, allocate one now. */ if (!bp) { if (!buffer_allocate (&lbp, length, MDL)) { log_error ("no memory for option buffer."); option_cache_dereference (&op, MDL); return 0; } memcpy (lbp -> data, buffer, length + tp); bp = lbp; buffer = &bp -> data [0]; /* Refer to saved buffer. */ } /* Reference buffer copy to option cache. */ op -> data.buffer = (struct buffer *)0; buffer_reference (&op -> data.buffer, bp, MDL); /* Point option cache into buffer. */ op -> data.data = buffer; op -> data.len = length; if (tp) { /* NUL terminate (we can get away with this because we (or the caller!) allocated one more than the buffer size, and because the byte following the end of an option is always the code of the next option, which the caller is getting out of the *original* buffer. */ buffer [length] = 0; op -> data.terminated = 1; } else op -> data.terminated = 0; op -> option = option; /* Now store the option. */ save_option (universe, options, op); /* And let go of our reference. */ option_cache_dereference (&op, MDL); return 1; } void save_option (struct universe *universe, struct option_state *options, struct option_cache *oc) { if (universe -> save_func) (*universe -> save_func) (universe, options, oc); else log_error ("can't store options in %s space.", universe -> name); } void save_hashed_option (universe, options, oc) struct universe *universe; struct option_state *options; struct option_cache *oc; { int hashix; pair bptr; pair *hash = options -> universes [universe -> index]; if (oc -> refcnt == 0) abort (); /* Compute the hash. */ hashix = compute_option_hash (oc -> option -> code); /* If there's no hash table, make one. */ if (!hash) { hash = (pair *)dmalloc (OPTION_HASH_SIZE * sizeof *hash, MDL); if (!hash) { log_error ("no memory to store %s.%s", universe -> name, oc -> option -> name); return; } memset (hash, 0, OPTION_HASH_SIZE * sizeof *hash); options -> universes [universe -> index] = (VOIDPTR)hash; } else { /* Try to find an existing option matching the new one. */ for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) { if (((struct option_cache *) (bptr -> car)) -> option -> code == oc -> option -> code) break; } /* If we find one, dereference it and put the new one in its place. */ if (bptr) { option_cache_dereference ((struct option_cache **)&bptr -> car, MDL); option_cache_reference ((struct option_cache **)&bptr -> car, oc, MDL); return; } } /* Otherwise, just put the new one at the head of the list. */ bptr = new_pair (MDL); if (!bptr) { log_error ("No memory for option_cache reference."); return; } bptr -> cdr = hash [hashix]; bptr -> car = 0; option_cache_reference ((struct option_cache **)&bptr -> car, oc, MDL); hash [hashix] = bptr; } void delete_option (universe, options, code) struct universe *universe; struct option_state *options; int code; { if (universe -> delete_func) (*universe -> delete_func) (universe, options, code); else log_error ("can't delete options from %s space.", universe -> name); } void delete_hashed_option (universe, options, code) struct universe *universe; struct option_state *options; int code; { int hashix; pair bptr, prev = (pair)0; pair *hash = options -> universes [universe -> index]; /* There may not be any options in this space. */ if (!hash) return; /* Try to find an existing option matching the new one. */ hashix = compute_option_hash (code); for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) { if (((struct option_cache *)(bptr -> car)) -> option -> code == code) break; prev = bptr; } /* If we found one, wipe it out... */ if (bptr) { if (prev) prev -> cdr = bptr -> cdr; else hash [hashix] = bptr -> cdr; option_cache_dereference ((struct option_cache **)(&bptr -> car), MDL); free_pair (bptr, MDL); } } extern struct option_cache *free_option_caches; /* XXX */ int option_cache_dereference (ptr, file, line) struct option_cache **ptr; const char *file; int line; { if (!ptr || !*ptr) { log_error ("Null pointer in option_cache_dereference: %s(%d)", 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) { if ((*ptr) -> data.buffer) data_string_forget (&(*ptr) -> data, file, line); if ((*ptr) -> expression) expression_dereference (&(*ptr) -> expression, file, line); if ((*ptr) -> next) option_cache_dereference (&((*ptr) -> next), file, line); /* Put it back on the free list... */ (*ptr) -> expression = (struct expression *)free_option_caches; free_option_caches = *ptr; dmalloc_reuse (free_option_caches, (char *)0, 0, 0); } 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 *ptr = (struct option_cache *)0; return 0; #endif } *ptr = (struct option_cache *)0; return 1; } int hashed_option_state_dereference (universe, state, file, line) struct universe *universe; struct option_state *state; const char *file; int line; { pair *heads; pair cp, next; int i; /* Get the pointer to the array of hash table bucket heads. */ heads = (pair *)(state -> universes [universe -> index]); if (!heads) return 0; /* For each non-null head, loop through all the buckets dereferencing the attached option cache structures and freeing the buckets. */ for (i = 0; i < OPTION_HASH_SIZE; i++) { for (cp = heads [i]; cp; cp = next) { next = cp -> cdr; option_cache_dereference ((struct option_cache **)&cp -> car, file, line); free_pair (cp, file, line); } } dfree (heads, file, line); state -> universes [universe -> index] = (void *)0; return 1; } int store_option (result, universe, packet, lease, client_state, in_options, cfg_options, scope, oc) struct data_string *result; struct universe *universe; 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 option_cache *oc; { struct data_string d1, d2; memset (&d1, 0, sizeof d1); memset (&d2, 0, sizeof d2); if (evaluate_option_cache (&d2, packet, lease, client_state, in_options, cfg_options, scope, oc, MDL)) { if (!buffer_allocate (&d1.buffer, (result -> len + universe -> length_size + universe -> tag_size + d2.len), MDL)) { data_string_forget (result, MDL); data_string_forget (&d2, MDL); return 0; } d1.data = &d1.buffer -> data [0]; if (result -> len) memcpy (d1.buffer -> data, result -> data, result -> len); d1.len = result -> len; (*universe -> store_tag) (&d1.buffer -> data [d1.len], oc -> option -> code); d1.len += universe -> tag_size; (*universe -> store_length) (&d1.buffer -> data [d1.len], d2.len); d1.len += universe -> length_size; memcpy (&d1.buffer -> data [d1.len], d2.data, d2.len); d1.len += d2.len; data_string_forget (&d2, MDL); data_string_forget (result, MDL); data_string_copy (result, &d1, MDL); data_string_forget (&d1, MDL); return 1; } return 0; } int option_space_encapsulate (result, packet, lease, client_state, in_options, cfg_options, scope, name) struct data_string *result; 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 data_string *name; { struct universe *u; u = (struct universe *)0; universe_hash_lookup (&u, universe_hash, (const char *)name -> data, name -> len, MDL); if (!u) return 0; if (u -> encapsulate) return (*u -> encapsulate) (result, packet, lease, client_state, in_options, cfg_options, scope, u); log_error ("encapsulation requested for %s with no support.", name -> data); return 0; } int hashed_option_space_encapsulate (result, packet, lease, client_state, in_options, cfg_options, scope, universe) struct data_string *result; 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 *universe; { pair p, *hash; int status; int i; if (universe -> index >= cfg_options -> universe_count) return 0; hash = cfg_options -> universes [universe -> index]; if (!hash) return 0; status = 0; for (i = 0; i < OPTION_HASH_SIZE; i++) { for (p = hash [i]; p; p = p -> cdr) { if (store_option (result, universe, packet, lease, client_state, in_options, cfg_options, scope, (struct option_cache *)p -> car)) status = 1; } } return status; } int nwip_option_space_encapsulate (result, packet, lease, client_state, in_options, cfg_options, scope, universe) struct data_string *result; 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 *universe; { pair ocp; int status; int i; static struct option_cache *no_nwip; struct data_string ds; struct option_chain_head *head; if (universe -> index >= cfg_options -> universe_count) return 0; head = ((struct option_chain_head *) cfg_options -> universes [fqdn_universe.index]); if (!head) return 0; status = 0; for (ocp = head -> first; ocp; ocp = ocp -> cdr) { struct option_cache *oc = (struct option_cache *)(ocp -> car); if (store_option (result, universe, packet, lease, client_state, in_options, cfg_options, scope, (struct option_cache *)ocp -> car)) status = 1; } /* If there's no data, the nwip suboption is supposed to contain a suboption saying there's no data. */ if (!status) { if (!no_nwip) { static unsigned char nni [] = { 1, 0 }; memset (&ds, 0, sizeof ds); ds.data = nni; ds.len = 2; if (option_cache_allocate (&no_nwip, MDL)) data_string_copy (&no_nwip -> data, &ds, MDL); no_nwip -> option = nwip_universe.options [1]; } if (no_nwip) { if (store_option (result, universe, packet, lease, client_state, in_options, cfg_options, scope, no_nwip)) status = 1; } } else { memset (&ds, 0, sizeof ds); /* If we have nwip options, the first one has to be the nwip-exists-in-option-area option. */ if (!buffer_allocate (&ds.buffer, result -> len + 2, MDL)) { data_string_forget (result, MDL); return 0; } ds.data = &ds.buffer -> data [0]; ds.buffer -> data [0] = 2; ds.buffer -> data [1] = 0; memcpy (&ds.buffer -> data [2], result -> data, result -> len); data_string_forget (result, MDL); data_string_copy (result, &ds, MDL); data_string_forget (&ds, MDL); } return status; } int fqdn_option_space_encapsulate (result, packet, lease, client_state, in_options, cfg_options, scope, universe) struct data_string *result; 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 *universe; { pair ocp; struct data_string results [FQDN_SUBOPTION_COUNT + 1]; unsigned i; unsigned len; struct buffer *bp = (struct buffer *)0; struct option_chain_head *head; /* If there's no FQDN universe, don't encapsulate. */ if (fqdn_universe.index >= cfg_options -> universe_count) return 0; head = ((struct option_chain_head *) cfg_options -> universes [fqdn_universe.index]); if (!head) return 0; /* Figure out the values of all the suboptions. */ memset (results, 0, sizeof results); for (ocp = head -> first; ocp; ocp = ocp -> cdr) { struct option_cache *oc = (struct option_cache *)(ocp -> car); if (oc -> option -> code > FQDN_SUBOPTION_COUNT) continue; evaluate_option_cache (&results [oc -> option -> code], packet, lease, client_state, in_options, cfg_options, scope, oc, MDL); } len = 4 + results [FQDN_FQDN].len; /* Save the contents of the option in a buffer. */ if (!buffer_allocate (&bp, len, MDL)) { log_error ("no memory for option buffer."); return 0; } buffer_reference (&result -> buffer, bp, MDL); result -> len = 3; result -> data = &bp -> data [0]; memset (&bp -> data [0], 0, len); if (results [FQDN_NO_CLIENT_UPDATE].len && results [FQDN_NO_CLIENT_UPDATE].data [0]) bp -> data [0] |= 2; if (results [FQDN_SERVER_UPDATE].len && results [FQDN_SERVER_UPDATE].data [0]) bp -> data [0] |= 1; if (results [FQDN_RCODE1].len) bp -> data [1] = results [FQDN_RCODE1].data [0]; if (results [FQDN_RCODE2].len) bp -> data [2] = results [FQDN_RCODE2].data [0]; if (results [FQDN_ENCODED].len && results [FQDN_ENCODED].data [0]) { unsigned char *out; int i; bp -> data [0] |= 4; out = &bp -> data [3]; if (results [FQDN_FQDN].len) { i = 0; while (i < results [FQDN_FQDN].len) { int j; for (j = i; ('.' != results [FQDN_FQDN].data [j]) && j < results [FQDN_FQDN].len; j++) ; *out++ = j - i; memcpy (out, &results [FQDN_FQDN].data [i], (unsigned)(j - i)); out += j - i; i = j; if (results [FQDN_FQDN].data [j] == '.') i++; } if ((results [FQDN_FQDN].data [results [FQDN_FQDN].len - 1] == '.')) *out++ = 0; result -> len = out - result -> data; result -> terminated = 0; } } else { if (results [FQDN_FQDN].len) { memcpy (&bp -> data [3], results [FQDN_FQDN].data, results [FQDN_FQDN].len); result -> len += results [FQDN_FQDN].len; result -> terminated = 0; } } for (i = 1; i <= FQDN_SUBOPTION_COUNT; i++) { if (results [i].len) data_string_forget (&results [i], MDL); } buffer_dereference (&bp, MDL); return 1; } void option_space_foreach (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, void (*func) (struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *)) { if (u -> foreach) (*u -> foreach) (packet, lease, client_state, in_options, cfg_options, scope, u, stuff, func); } void suboption_foreach (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, void (*func) (struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *), struct option_cache *oc, const char *vsname) { struct universe *universe = find_option_universe (oc -> option, vsname); int i; if (universe -> foreach) (*universe -> foreach) (packet, lease, client_state, in_options, cfg_options, scope, universe, stuff, func); } void hashed_option_space_foreach (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, void (*func) (struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *)) { pair *hash; int i; struct option_cache *oc; if (cfg_options -> universe_count <= u -> index) return; hash = cfg_options -> universes [u -> index]; if (!hash) return; for (i = 0; i < OPTION_HASH_SIZE; i++) { pair p; /* XXX save _all_ options! XXX */ for (p = hash [i]; p; p = p -> cdr) { oc = (struct option_cache *)p -> car; (*func) (oc, packet, lease, client_state, in_options, cfg_options, scope, u, stuff); } } } void save_linked_option (universe, options, oc) struct universe *universe; struct option_state *options; struct option_cache *oc; { pair *tail; pair np = (pair )0; struct option_chain_head *head; if (universe -> index >= options -> universe_count) return; head = ((struct option_chain_head *) options -> universes [universe -> index]); if (!head) { if (!option_chain_head_allocate (((struct option_chain_head **) &options -> universes [universe -> index]), MDL)) return; head = ((struct option_chain_head *) options -> universes [universe -> index]); } /* Find the tail of the list. */ for (tail = &head -> first; *tail; tail = &((*tail) -> cdr)) { if (oc -> option == ((struct option_cache *)((*tail) -> car)) -> option) { option_cache_dereference ((struct option_cache **) (&(*tail) -> car), MDL); option_cache_reference ((struct option_cache **) (&(*tail) -> car), oc, MDL); return; } } *tail = cons (0, 0); if (*tail) { option_cache_reference ((struct option_cache **) (&(*tail) -> car), oc, MDL); } } int linked_option_space_encapsulate (result, packet, lease, client_state, in_options, cfg_options, scope, universe) struct data_string *result; 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 *universe; { int status; pair oc; struct option_chain_head *head; if (universe -> index >= cfg_options -> universe_count) return 0; head = ((struct option_chain_head *) cfg_options -> universes [universe -> index]); if (!head) return 0; status = 0; for (oc = head -> first; oc; oc = oc -> cdr) { if (store_option (result, universe, packet, lease, client_state, in_options, cfg_options, scope, (struct option_cache *)(oc -> car))) status = 1; } return status; } void delete_linked_option (universe, options, code) struct universe *universe; struct option_state *options; int code; { pair *tail, tmp = (pair)0; struct option_chain_head *head; if (universe -> index >= options -> universe_count) return; head = ((struct option_chain_head *) options -> universes [universe -> index]); if (!head) return; for (tail = &head -> first; *tail; tail = &((*tail) -> cdr)) { if (code == ((struct option_cache *)(*tail) -> car) -> option -> code) { tmp = (*tail) -> cdr; option_cache_dereference ((struct option_cache **) (&(*tail) -> car), MDL); dfree (*tail, MDL); (*tail) = tmp; break; } } } struct option_cache *lookup_linked_option (universe, options, code) struct universe *universe; struct option_state *options; unsigned code; { pair oc; struct option_chain_head *head; if (universe -> index >= options -> universe_count) return 0; head = ((struct option_chain_head *) options -> universes [universe -> index]); if (!head) return 0; for (oc = head -> first; oc; oc = oc -> cdr) { if (code == ((struct option_cache *)(oc -> car)) -> option -> code) { return (struct option_cache *)(oc -> car); } } return (struct option_cache *)0; } int linked_option_state_dereference (universe, state, file, line) struct universe *universe; struct option_state *state; const char *file; int line; { return (option_chain_head_dereference ((struct option_chain_head **) (&state -> universes [universe -> index]), MDL)); } void linked_option_space_foreach (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, void (*func) (struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *)) { pair car; struct option_chain_head *head; if (u -> index >= cfg_options -> universe_count) return; head = ((struct option_chain_head *) cfg_options -> universes [u -> index]); if (!head) return; for (car = head -> first; car; car = car -> cdr) { (*func) ((struct option_cache *)(car -> car), packet, lease, client_state, in_options, cfg_options, scope, u, stuff); } } void do_packet (interface, packet, len, from_port, from, hfrom) struct interface_info *interface; struct dhcp_packet *packet; unsigned len; unsigned int from_port; struct iaddr from; struct hardware *hfrom; { int i; struct option_cache *op; struct packet *decoded_packet; #if defined (DEBUG_MEMORY_LEAKAGE) unsigned long previous_outstanding = dmalloc_outstanding; #endif #if defined (TRACING) trace_inpacket_stash (interface, packet, len, from_port, from, hfrom); #endif decoded_packet = (struct packet *)0; if (!packet_allocate (&decoded_packet, MDL)) { log_error ("do_packet: no memory for incoming packet!"); return; } decoded_packet -> raw = packet; decoded_packet -> packet_length = len; decoded_packet -> client_port = from_port; decoded_packet -> client_addr = from; interface_reference (&decoded_packet -> interface, interface, MDL); decoded_packet -> haddr = hfrom; if (packet -> hlen > sizeof packet -> chaddr) { packet_dereference (&decoded_packet, MDL); log_info ("Discarding packet with bogus hlen."); return; } /* If there's an option buffer, try to parse it. */ if (decoded_packet -> packet_length >= DHCP_FIXED_NON_UDP + 4) { if (!parse_options (decoded_packet)) { if (decoded_packet -> options) option_state_dereference (&decoded_packet -> options, MDL); packet_dereference (&decoded_packet, MDL); return; } if (decoded_packet -> options_valid && (op = lookup_option (&dhcp_universe, decoded_packet -> options, DHO_DHCP_MESSAGE_TYPE))) { struct data_string dp; memset (&dp, 0, sizeof dp); evaluate_option_cache (&dp, decoded_packet, (struct lease *)0, (struct client_state *)0, decoded_packet -> options, (struct option_state *)0, (struct binding_scope **)0, op, MDL); if (dp.len > 0) decoded_packet -> packet_type = dp.data [0]; else decoded_packet -> packet_type = 0; data_string_forget (&dp, MDL); } } if (decoded_packet -> packet_type) dhcp (decoded_packet); else bootp (decoded_packet); /* If the caller kept the packet, they'll have upped the refcnt. */ packet_dereference (&decoded_packet, MDL); #if defined (DEBUG_MEMORY_LEAKAGE) log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term", dmalloc_generation, dmalloc_outstanding - previous_outstanding, dmalloc_outstanding, dmalloc_longterm); #endif #if defined (DEBUG_MEMORY_LEAKAGE) dmalloc_dump_outstanding (); #endif #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY) dump_rc_history (0); #endif } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/packet.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/packet.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/packet.c (revision 131136) @@ -1,348 +1,339 @@ /* packet.c Packet assembly code, originally contributed by Archie Cobbs. */ /* - * Copyright (c) 1996-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * * This code was originally contributed by Archie Cobbs, and is still * very similar to that contribution, although the packet checksum code * has been hacked significantly with the help of quite a few ISC DHCP * users, without whose gracious and thorough help the checksum code would * still be disabled. */ #ifndef lint static char copyright[] = -"$Id: packet.c,v 1.40.2.2 2002/11/17 02:26:59 dhankins Exp $ Copyright (c) 1996-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: packet.c,v 1.40.2.3 2004/06/10 17:59:19 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #if defined (PACKET_ASSEMBLY) || defined (PACKET_DECODING) #include "includes/netinet/ip.h" #include "includes/netinet/udp.h" #include "includes/netinet/if_ether.h" #endif /* PACKET_ASSEMBLY || PACKET_DECODING */ /* Compute the easy part of the checksum on a range of bytes. */ u_int32_t checksum (buf, nbytes, sum) unsigned char *buf; unsigned nbytes; u_int32_t sum; { unsigned i; #ifdef DEBUG_CHECKSUM log_debug ("checksum (%x %d %x)", buf, nbytes, sum); #endif /* Checksum all the pairs of bytes first... */ for (i = 0; i < (nbytes & ~1U); i += 2) { #ifdef DEBUG_CHECKSUM_VERBOSE log_debug ("sum = %x", sum); #endif sum += (u_int16_t) ntohs(*((u_int16_t *)(buf + i))); /* Add carry. */ if (sum > 0xFFFF) sum -= 0xFFFF; } /* If there's a single byte left over, checksum it, too. Network byte order is big-endian, so the remaining byte is the high byte. */ if (i < nbytes) { #ifdef DEBUG_CHECKSUM_VERBOSE log_debug ("sum = %x", sum); #endif sum += buf [i] << 8; /* Add carry. */ if (sum > 0xFFFF) sum -= 0xFFFF; } return sum; } /* Finish computing the checksum, and then put it into network byte order. */ u_int32_t wrapsum (sum) u_int32_t sum; { #ifdef DEBUG_CHECKSUM log_debug ("wrapsum (%x)", sum); #endif sum = ~sum & 0xFFFF; #ifdef DEBUG_CHECKSUM_VERBOSE log_debug ("sum = %x", sum); #endif #ifdef DEBUG_CHECKSUM log_debug ("wrapsum returns %x", htons (sum)); #endif return htons(sum); } #ifdef PACKET_ASSEMBLY void assemble_hw_header (interface, buf, bufix, to) struct interface_info *interface; unsigned char *buf; unsigned *bufix; struct hardware *to; { #if defined (HAVE_TR_SUPPORT) if (interface -> hw_address.hbuf [0] == HTYPE_IEEE802) assemble_tr_header (interface, buf, bufix, to); else #endif #if defined (DEC_FDDI) if (interface -> hw_address.hbuf [0] == HTYPE_FDDI) assemble_fddi_header (interface, buf, bufix, to); else #endif assemble_ethernet_header (interface, buf, bufix, to); } /* UDP header and IP header assembled together for convenience. */ void assemble_udp_ip_header (interface, buf, bufix, from, to, port, data, len) struct interface_info *interface; unsigned char *buf; unsigned *bufix; u_int32_t from; u_int32_t to; u_int32_t port; unsigned char *data; unsigned len; { struct ip ip; struct udphdr udp; /* Fill out the IP header */ IP_V_SET (&ip, 4); IP_HL_SET (&ip, 20); ip.ip_tos = IPTOS_LOWDELAY; ip.ip_len = htons(sizeof(ip) + sizeof(udp) + len); ip.ip_id = 0; ip.ip_off = 0; ip.ip_ttl = 16; ip.ip_p = IPPROTO_UDP; ip.ip_sum = 0; ip.ip_src.s_addr = from; ip.ip_dst.s_addr = to; /* Checksum the IP header... */ ip.ip_sum = wrapsum (checksum ((unsigned char *)&ip, sizeof ip, 0)); /* Copy the ip header into the buffer... */ memcpy (&buf [*bufix], &ip, sizeof ip); *bufix += sizeof ip; /* Fill out the UDP header */ udp.uh_sport = local_port; /* XXX */ udp.uh_dport = port; /* XXX */ udp.uh_ulen = htons(sizeof(udp) + len); memset (&udp.uh_sum, 0, sizeof udp.uh_sum); /* Compute UDP checksums, including the ``pseudo-header'', the UDP header and the data. */ udp.uh_sum = wrapsum (checksum ((unsigned char *)&udp, sizeof udp, checksum (data, len, checksum ((unsigned char *) &ip.ip_src, 2 * sizeof ip.ip_src, IPPROTO_UDP + (u_int32_t) ntohs (udp.uh_ulen))))); /* Copy the udp header into the buffer... */ memcpy (&buf [*bufix], &udp, sizeof udp); *bufix += sizeof udp; } #endif /* PACKET_ASSEMBLY */ #ifdef PACKET_DECODING /* Decode a hardware header... */ /* XXX currently only supports ethernet; doesn't check for other types. */ ssize_t decode_hw_header (interface, buf, bufix, from) struct interface_info *interface; unsigned char *buf; unsigned bufix; struct hardware *from; { #if defined (HAVE_TR_SUPPORT) if (interface -> hw_address.hbuf [0] == HTYPE_IEEE802) return decode_tr_header (interface, buf, bufix, from); else #endif #if defined (DEC_FDDI) if (interface -> hw_address.hbuf [0] == HTYPE_FDDI) return decode_fddi_header (interface, buf, bufix, from); else #endif return decode_ethernet_header (interface, buf, bufix, from); } /* UDP header and IP header decoded together for convenience. */ ssize_t decode_udp_ip_header (interface, buf, bufix, from, data, buflen) struct interface_info *interface; unsigned char *buf; unsigned bufix; struct sockaddr_in *from; unsigned char *data; unsigned buflen; { struct ip *ip; struct udphdr *udp; u_int32_t ip_len = (buf [bufix] & 0xf) << 2; u_int32_t sum, usum; static int ip_packets_seen; static int ip_packets_bad_checksum; static int udp_packets_seen; static int udp_packets_bad_checksum; static int udp_packets_length_checked; static int udp_packets_length_overflow; unsigned len; unsigned ulen; int ignore = 0; ip = (struct ip *)(buf + bufix); udp = (struct udphdr *)(buf + bufix + ip_len); #ifdef USERLAND_FILTER /* Is it a UDP packet? */ if (ip -> ip_p != IPPROTO_UDP) return -1; /* Is it to the port we're serving? */ if (udp -> uh_dport != local_port) return -1; #endif /* USERLAND_FILTER */ ulen = ntohs (udp -> uh_ulen); if (ulen < sizeof *udp || ((unsigned char *)udp) + ulen > buf + bufix + buflen) { log_info ("bogus UDP packet length: %d", ulen); return -1; } /* Check the IP header checksum - it should be zero. */ ++ip_packets_seen; if (wrapsum (checksum (buf + bufix, ip_len, 0))) { ++ip_packets_bad_checksum; if (ip_packets_seen > 4 && (ip_packets_seen / ip_packets_bad_checksum) < 2) { log_info ("%d bad IP checksums seen in %d packets", ip_packets_bad_checksum, ip_packets_seen); ip_packets_seen = ip_packets_bad_checksum = 0; } return -1; } /* Check the IP packet length. */ if (ntohs (ip -> ip_len) != buflen) { if ((ntohs (ip -> ip_len + 2) & ~1) == buflen) ignore = 1; else log_debug ("ip length %d disagrees with bytes received %d.", ntohs (ip -> ip_len), buflen); } /* Copy out the IP source address... */ memcpy (&from -> sin_addr, &ip -> ip_src, 4); /* Compute UDP checksums, including the ``pseudo-header'', the UDP header and the data. If the UDP checksum field is zero, we're not supposed to do a checksum. */ if (!data) { data = buf + bufix + ip_len + sizeof *udp; len = ulen - sizeof *udp; ++udp_packets_length_checked; if (len + data > buf + bufix + buflen) { ++udp_packets_length_overflow; if (udp_packets_length_checked > 4 && (udp_packets_length_checked / udp_packets_length_overflow) < 2) { log_info ("%d udp packets in %d too long - dropped", udp_packets_length_overflow, udp_packets_length_checked); udp_packets_length_overflow = udp_packets_length_checked = 0; } return -1; } if (len + data < buf + bufix + buflen && len + data != buf + bufix + buflen && !ignore) log_debug ("accepting packet with data after udp payload."); if (len + data > buf + bufix + buflen) { log_debug ("dropping packet with bogus uh_ulen %ld", (long)(len + sizeof *udp)); return -1; } } usum = udp -> uh_sum; udp -> uh_sum = 0; sum = wrapsum (checksum ((unsigned char *)udp, sizeof *udp, checksum (data, len, checksum ((unsigned char *) &ip -> ip_src, 2 * sizeof ip -> ip_src, IPPROTO_UDP + (u_int32_t)ulen)))); udp_packets_seen++; if (usum && usum != sum) { udp_packets_bad_checksum++; if (udp_packets_seen > 4 && (udp_packets_seen / udp_packets_bad_checksum) < 2) { log_info ("%d bad udp checksums in %d packets", udp_packets_bad_checksum, udp_packets_seen); udp_packets_seen = udp_packets_bad_checksum = 0; } return -1; } /* Copy out the port... */ memcpy (&from -> sin_port, &udp -> uh_sport, sizeof udp -> uh_sport); return ip_len + sizeof *udp; } #endif /* PACKET_DECODING */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/parse.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/parse.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/parse.c (revision 131136) @@ -1,4853 +1,4842 @@ /* parse.c Common parser code for dhcpd and dhclient. */ /* - * Copyright (c) 1995-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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: parse.c,v 1.104.2.14 2003/07/25 19:36:11 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: parse.c,v 1.104.2.17 2004/06/17 20:54:38 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" /* Enumerations can be specified in option formats, and are used for parsing, so we define the routines that manage them here. */ struct enumeration *enumerations; void add_enumeration (struct enumeration *enumeration) { enumeration -> next = enumerations; enumerations = enumeration; } struct enumeration *find_enumeration (const char *name, int length) { struct enumeration *e; for (e = enumerations; e; e = e -> next) if (strlen (e -> name) == length && !memcmp (e -> name, name, (unsigned)length)) return e; return (struct enumeration *)0; } struct enumeration_value *find_enumeration_value (const char *name, int length, const char *value) { struct enumeration *e; int i; e = find_enumeration (name, length); if (e) { for (i = 0; e -> values [i].name; i++) { if (!strcmp (value, e -> values [i].name)) return &e -> values [i]; } } return (struct enumeration_value *)0; } /* Skip to the semicolon ending the current statement. If we encounter braces, the matching closing brace terminates the statement. If we encounter a right brace but haven't encountered a left brace, return leaving the brace in the token buffer for the caller. If we see a semicolon and haven't seen a left brace, return. This lets us skip over: statement; statement foo bar { } statement foo bar { statement { } } statement} ...et cetera. */ void skip_to_semi (cfile) struct parse *cfile; { skip_to_rbrace (cfile, 0); } void skip_to_rbrace (cfile, brace_count) struct parse *cfile; int brace_count; { enum dhcp_token token; const char *val; #if defined (DEBUG_TOKEN) log_error ("skip_to_rbrace: %d\n", brace_count); #endif do { token = peek_token (&val, (unsigned *)0, cfile); if (token == RBRACE) { token = next_token (&val, (unsigned *)0, cfile); if (brace_count) { if (!--brace_count) return; } else return; } else if (token == LBRACE) { brace_count++; } else if (token == SEMI && !brace_count) { token = next_token (&val, (unsigned *)0, cfile); return; } else if (token == EOL) { /* EOL only happens when parsing /etc/resolv.conf, and we treat it like a semicolon because the resolv.conf file is line-oriented. */ token = next_token (&val, (unsigned *)0, cfile); return; } token = next_token (&val, (unsigned *)0, cfile); } while (token != END_OF_FILE); } int parse_semi (cfile) struct parse *cfile; { enum dhcp_token token; const char *val; token = next_token (&val, (unsigned *)0, cfile); if (token != SEMI) { parse_warn (cfile, "semicolon expected."); skip_to_semi (cfile); return 0; } return 1; } /* string-parameter :== STRING SEMI */ int parse_string (cfile, sptr, lptr) struct parse *cfile; char **sptr; unsigned *lptr; { const char *val; enum dhcp_token token; char *s; unsigned len; token = next_token (&val, &len, cfile); if (token != STRING) { parse_warn (cfile, "expecting a string"); skip_to_semi (cfile); return 0; } s = (char *)dmalloc (len + 1, MDL); if (!s) log_fatal ("no memory for string %s.", val); memcpy (s, val, len + 1); if (!parse_semi (cfile)) { dfree (s, MDL); return 0; } if (sptr) *sptr = s; else dfree (s, MDL); if (lptr) *lptr = len; return 1; } /* * hostname :== IDENTIFIER * | IDENTIFIER DOT * | hostname DOT IDENTIFIER */ char *parse_host_name (cfile) struct parse *cfile; { const char *val; enum dhcp_token token; unsigned len = 0; char *s; char *t; pair c = (pair)0; int ltid = 0; /* Read a dotted hostname... */ do { /* Read a token, which should be an identifier. */ token = peek_token (&val, (unsigned *)0, cfile); if (!is_identifier (token) && token != NUMBER) break; token = next_token (&val, (unsigned *)0, cfile); /* Store this identifier... */ if (!(s = (char *)dmalloc (strlen (val) + 1, MDL))) log_fatal ("can't allocate temp space for hostname."); strcpy (s, val); c = cons ((caddr_t)s, c); len += strlen (s) + 1; /* Look for a dot; if it's there, keep going, otherwise we're done. */ token = peek_token (&val, (unsigned *)0, cfile); if (token == DOT) { token = next_token (&val, (unsigned *)0, cfile); ltid = 1; } else ltid = 0; } while (token == DOT); /* Should be at least one token. */ if (!len) return (char *)0; /* Assemble the hostname together into a string. */ if (!(s = (char *)dmalloc (len + ltid, MDL))) log_fatal ("can't allocate space for hostname."); t = s + len + ltid; *--t = 0; if (ltid) *--t = '.'; while (c) { pair cdr = c -> cdr; unsigned l = strlen ((char *)(c -> car)); t -= l; memcpy (t, (char *)(c -> car), l); /* Free up temp space. */ dfree (c -> car, MDL); dfree (c, MDL); c = cdr; if (t != s) *--t = '.'; } return s; } /* ip-addr-or-hostname :== ip-address | hostname ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER Parse an ip address or a hostname. If uniform is zero, put in an expr_substring node to limit hostnames that evaluate to more than one IP address. */ int parse_ip_addr_or_hostname (expr, cfile, uniform) struct expression **expr; struct parse *cfile; int uniform; { const char *val; enum dhcp_token token; unsigned char addr [4]; unsigned len = sizeof addr; char *name; struct expression *x = (struct expression *)0; token = peek_token (&val, (unsigned *)0, cfile); if (is_identifier (token)) { name = parse_host_name (cfile); if (!name) return 0; if (!make_host_lookup (expr, name)) { dfree(name, MDL); return 0; } dfree(name, MDL); if (!uniform) { if (!make_limit (&x, *expr, 4)) return 0; expression_dereference (expr, MDL); *expr = x; } } else if (token == NUMBER) { if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) return 0; return make_const_data (expr, addr, len, 0, 1, MDL); } else { if (token != RBRACE && token != LBRACE) token = next_token (&val, (unsigned *)0, cfile); parse_warn (cfile, "%s (%d): expecting IP address or hostname", val, token); if (token != SEMI) skip_to_semi (cfile); return 0; } return 1; } /* * ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER */ int parse_ip_addr (cfile, addr) struct parse *cfile; struct iaddr *addr; { const char *val; enum dhcp_token token; addr -> len = 4; if (parse_numeric_aggregate (cfile, addr -> iabuf, &addr -> len, DOT, 10, 8)) return 1; return 0; } /* * hardware-parameter :== HARDWARE hardware-type colon-seperated-hex-list SEMI * hardware-type :== ETHERNET | TOKEN_RING | FDDI */ void parse_hardware_param (cfile, hardware) struct parse *cfile; struct hardware *hardware; { const char *val; enum dhcp_token token; unsigned hlen; unsigned char *t; token = next_token (&val, (unsigned *)0, cfile); switch (token) { case ETHERNET: hardware -> hbuf [0] = HTYPE_ETHER; break; case TOKEN_RING: hardware -> hbuf [0] = HTYPE_IEEE802; break; case FDDI: hardware -> hbuf [0] = HTYPE_FDDI; break; default: if (!strncmp (val, "unknown-", 8)) { hardware -> hbuf [0] = atoi (&val [8]); } else { parse_warn (cfile, "expecting a network hardware type"); skip_to_semi (cfile); return; } } /* Parse the hardware address information. Technically, it would make a lot of sense to restrict the length of the data we'll accept here to the length of a particular hardware address type. Unfortunately, there are some broken clients out there that put bogus data in the chaddr buffer, and we accept that data in the lease file rather than simply failing on such clients. Yuck. */ hlen = 0; token = peek_token (&val, (unsigned *)0, cfile); if (token == SEMI) { hardware -> hlen = 1; goto out; } t = parse_numeric_aggregate (cfile, (unsigned char *)0, &hlen, COLON, 16, 8); if (!t) { hardware -> hlen = 1; return; } if (hlen + 1 > sizeof hardware -> hbuf) { dfree (t, MDL); parse_warn (cfile, "hardware address too long"); } else { hardware -> hlen = hlen + 1; memcpy ((unsigned char *)&hardware -> hbuf [1], t, hlen); if (hlen + 1 < sizeof hardware -> hbuf) memset (&hardware -> hbuf [hlen + 1], 0, (sizeof hardware -> hbuf) - hlen - 1); dfree (t, MDL); } out: token = next_token (&val, (unsigned *)0, cfile); if (token != SEMI) { parse_warn (cfile, "expecting semicolon."); skip_to_semi (cfile); } } /* lease-time :== NUMBER SEMI */ void parse_lease_time (cfile, timep) struct parse *cfile; TIME *timep; { const char *val; enum dhcp_token token; token = next_token (&val, (unsigned *)0, cfile); if (token != NUMBER) { parse_warn (cfile, "Expecting numeric lease time"); skip_to_semi (cfile); return; } convert_num (cfile, (unsigned char *)timep, val, 10, 32); /* Unswap the number - convert_num returns stuff in NBO. */ *timep = ntohl (*timep); /* XXX */ parse_semi (cfile); } /* No BNF for numeric aggregates - that's defined by the caller. What this function does is to parse a sequence of numbers seperated by the token specified in seperator. If max is zero, any number of numbers will be parsed; otherwise, exactly max numbers are expected. Base and size tell us how to internalize the numbers once they've been tokenized. */ unsigned char *parse_numeric_aggregate (cfile, buf, max, seperator, base, size) struct parse *cfile; unsigned char *buf; unsigned *max; int seperator; int base; unsigned size; { const char *val; enum dhcp_token token; unsigned char *bufp = buf, *s, *t; unsigned count = 0; pair c = (pair)0; if (!bufp && *max) { bufp = (unsigned char *)dmalloc (*max * size / 8, MDL); if (!bufp) log_fatal ("no space for numeric aggregate"); s = 0; } else s = bufp; do { if (count) { token = peek_token (&val, (unsigned *)0, cfile); if (token != seperator) { if (!*max) break; if (token != RBRACE && token != LBRACE) token = next_token (&val, (unsigned *)0, cfile); parse_warn (cfile, "too few numbers."); if (token != SEMI) skip_to_semi (cfile); return (unsigned char *)0; } token = next_token (&val, (unsigned *)0, cfile); } token = next_token (&val, (unsigned *)0, cfile); if (token == END_OF_FILE) { parse_warn (cfile, "unexpected end of file"); break; } /* Allow NUMBER_OR_NAME if base is 16. */ if (token != NUMBER && (base != 16 || token != NUMBER_OR_NAME)) { parse_warn (cfile, "expecting numeric value."); skip_to_semi (cfile); return (unsigned char *)0; } /* If we can, convert the number now; otherwise, build a linked list of all the numbers. */ if (s) { convert_num (cfile, s, val, base, size); s += size / 8; } else { t = (unsigned char *)dmalloc (strlen (val) + 1, MDL); if (!t) log_fatal ("no temp space for number."); strcpy ((char *)t, val); c = cons ((caddr_t)t, c); } } while (++count != *max); /* If we had to cons up a list, convert it now. */ if (c) { bufp = (unsigned char *)dmalloc (count * size / 8, MDL); if (!bufp) log_fatal ("no space for numeric aggregate."); s = bufp + count - size / 8; *max = count; } while (c) { pair cdr = c -> cdr; convert_num (cfile, s, (char *)(c -> car), base, size); s -= size / 8; /* Free up temp space. */ dfree (c -> car, MDL); dfree (c, MDL); c = cdr; } return bufp; } void convert_num (cfile, buf, str, base, size) struct parse *cfile; unsigned char *buf; const char *str; int base; unsigned size; { const char *ptr = str; int negative = 0; u_int32_t val = 0; int tval; int max; if (*ptr == '-') { negative = 1; ++ptr; } /* If base wasn't specified, figure it out from the data. */ if (!base) { if (ptr [0] == '0') { if (ptr [1] == 'x') { base = 16; ptr += 2; } else if (isascii (ptr [1]) && isdigit (ptr [1])) { base = 8; ptr += 1; } else { base = 10; } } else { base = 10; } } do { tval = *ptr++; /* XXX assumes ASCII... */ if (tval >= 'a') tval = tval - 'a' + 10; else if (tval >= 'A') tval = tval - 'A' + 10; else if (tval >= '0') tval -= '0'; else { parse_warn (cfile, "Bogus number: %s.", str); break; } if (tval >= base) { parse_warn (cfile, "Bogus number %s: digit %d not in base %d", str, tval, base); break; } val = val * base + tval; } while (*ptr); if (negative) max = (1 << (size - 1)); else max = (1 << (size - 1)) + ((1 << (size - 1)) - 1); if (val > max) { switch (base) { case 8: parse_warn (cfile, "%s%lo exceeds max (%d) for precision.", negative ? "-" : "", (unsigned long)val, max); break; case 16: parse_warn (cfile, "%s%lx exceeds max (%d) for precision.", negative ? "-" : "", (unsigned long)val, max); break; default: parse_warn (cfile, "%s%lu exceeds max (%d) for precision.", negative ? "-" : "", (unsigned long)val, max); break; } } if (negative) { switch (size) { case 8: *buf = -(unsigned long)val; break; case 16: putShort (buf, -(long)val); break; case 32: putLong (buf, -(long)val); break; default: parse_warn (cfile, "Unexpected integer size: %d\n", size); break; } } else { switch (size) { case 8: *buf = (u_int8_t)val; break; case 16: putUShort (buf, (u_int16_t)val); break; case 32: putULong (buf, val); break; default: parse_warn (cfile, "Unexpected integer size: %d\n", size); break; } } } /* * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER * NUMBER COLON NUMBER COLON NUMBER SEMI | * NUMBER NUMBER SLASH NUMBER SLASH NUMBER * NUMBER COLON NUMBER COLON NUMBER NUMBER SEMI | * NEVER * * Dates are stored in GMT or with a timezone offset; first number is day * of week; next is year/month/day; next is hours:minutes:seconds on a * 24-hour clock, followed by the timezone offset in seconds, which is * optional. */ TIME parse_date (cfile) struct parse *cfile; { struct tm tm; int guess; int tzoff, wday, year, mon, mday, hour, min, sec; const char *val; enum dhcp_token token; static int months [11] = { 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; /* Day of week, or "never"... */ token = next_token (&val, (unsigned *)0, cfile); if (token == NEVER) { if (!parse_semi (cfile)) return 0; return MAX_TIME; } if (token != NUMBER) { parse_warn (cfile, "numeric day of week expected."); if (token != SEMI) skip_to_semi (cfile); return (TIME)0; } wday = atoi (val); /* Year... */ token = next_token (&val, (unsigned *)0, cfile); if (token != NUMBER) { parse_warn (cfile, "numeric year expected."); if (token != SEMI) skip_to_semi (cfile); return (TIME)0; } /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until somebody invents a time machine, I think we can safely disregard it. This actually works around a stupid Y2K bug that was present in a very early beta release of dhcpd. */ year = atoi (val); if (year > 1900) year -= 1900; /* Slash seperating year from month... */ token = next_token (&val, (unsigned *)0, cfile); if (token != SLASH) { parse_warn (cfile, "expected slash seperating year from month."); if (token != SEMI) skip_to_semi (cfile); return (TIME)0; } /* Month... */ token = next_token (&val, (unsigned *)0, cfile); if (token != NUMBER) { parse_warn (cfile, "numeric month expected."); if (token != SEMI) skip_to_semi (cfile); return (TIME)0; } mon = atoi (val) - 1; /* Slash seperating month from day... */ token = next_token (&val, (unsigned *)0, cfile); if (token != SLASH) { parse_warn (cfile, "expected slash seperating month from day."); if (token != SEMI) skip_to_semi (cfile); return (TIME)0; } /* Month... */ token = next_token (&val, (unsigned *)0, cfile); if (token != NUMBER) { parse_warn (cfile, "numeric day of month expected."); if (token != SEMI) skip_to_semi (cfile); return (TIME)0; } mday = atoi (val); /* Hour... */ token = next_token (&val, (unsigned *)0, cfile); if (token != NUMBER) { parse_warn (cfile, "numeric hour expected."); if (token != SEMI) skip_to_semi (cfile); return (TIME)0; } hour = atoi (val); /* Colon seperating hour from minute... */ token = next_token (&val, (unsigned *)0, cfile); if (token != COLON) { parse_warn (cfile, "expected colon seperating hour from minute."); if (token != SEMI) skip_to_semi (cfile); return (TIME)0; } /* Minute... */ token = next_token (&val, (unsigned *)0, cfile); if (token != NUMBER) { parse_warn (cfile, "numeric minute expected."); if (token != SEMI) skip_to_semi (cfile); return (TIME)0; } min = atoi (val); /* Colon seperating minute from second... */ token = next_token (&val, (unsigned *)0, cfile); if (token != COLON) { parse_warn (cfile, "expected colon seperating hour from minute."); if (token != SEMI) skip_to_semi (cfile); return (TIME)0; } /* Minute... */ token = next_token (&val, (unsigned *)0, cfile); if (token != NUMBER) { parse_warn (cfile, "numeric minute expected."); if (token != SEMI) skip_to_semi (cfile); return (TIME)0; } sec = atoi (val); token = peek_token (&val, (unsigned *)0, cfile); if (token == NUMBER) { token = next_token (&val, (unsigned *)0, cfile); tzoff = atoi (val); } else tzoff = 0; /* Make sure the date ends in a semicolon... */ if (!parse_semi (cfile)) return 0; /* Guess the time value... */ guess = ((((((365 * (year - 70) + /* Days in years since '70 */ (year - 69) / 4 + /* Leap days since '70 */ (mon /* Days in months this year */ ? months [mon - 1] : 0) + (mon > 1 && /* Leap day this year */ !((year - 72) & 3)) + mday - 1) * 24) + /* Day of month */ hour) * 60) + min) * 60) + sec + tzoff; /* This guess could be wrong because of leap seconds or other weirdness we don't know about that the system does. For now, we're just going to accept the guess, but at some point it might be nice to do a successive approximation here to get an exact value. Even if the error is small, if the server is restarted frequently (and thus the lease database is reread), the error could accumulate into something significant. */ return guess; } /* * option-name :== IDENTIFIER | IDENTIFIER . IDENTIFIER */ struct option *parse_option_name (cfile, allocate, known) struct parse *cfile; int allocate; int *known; { const char *val; enum dhcp_token token; char *uname; struct universe *universe; struct option *option; token = next_token (&val, (unsigned *)0, cfile); if (!is_identifier (token)) { parse_warn (cfile, "expecting identifier after option keyword."); if (token != SEMI) skip_to_semi (cfile); return (struct option *)0; } uname = dmalloc (strlen (val) + 1, MDL); if (!uname) log_fatal ("no memory for uname information."); strcpy (uname, val); token = peek_token (&val, (unsigned *)0, cfile); if (token == DOT) { /* Go ahead and take the DOT token... */ token = next_token (&val, (unsigned *)0, cfile); /* The next token should be an identifier... */ token = next_token (&val, (unsigned *)0, cfile); if (!is_identifier (token)) { parse_warn (cfile, "expecting identifier after '.'"); if (token != SEMI) skip_to_semi (cfile); return (struct option *)0; } /* Look up the option name hash table for the specified uname. */ universe = (struct universe *)0; if (!universe_hash_lookup (&universe, universe_hash, uname, 0, MDL)) { parse_warn (cfile, "no option space named %s.", uname); skip_to_semi (cfile); return (struct option *)0; } } else { /* Use the default hash table, which contains all the standard dhcp option names. */ val = uname; universe = &dhcp_universe; } /* Look up the actual option info... */ option = (struct option *)0; option_hash_lookup (&option, universe -> hash, val, 0, MDL); /* If we didn't get an option structure, it's an undefined option. */ if (option) { if (known) *known = 1; } else { /* If we've been told to allocate, that means that this (might) be an option code definition, so we'll create an option structure just in case. */ if (allocate) { option = new_option (MDL); if (val == uname) option -> name = val; else { char *s; dfree (uname, MDL); s = dmalloc (strlen (val) + 1, MDL); if (!s) log_fatal ("no memory for option %s.%s", universe -> name, val); strcpy (s, val); option -> name = s; } option -> universe = universe; option -> code = 0; return option; } if (val == uname) parse_warn (cfile, "no option named %s", val); else parse_warn (cfile, "no option named %s in space %s", val, uname); skip_to_semi (cfile); return (struct option *)0; } /* Free the initial identifier token. */ dfree (uname, MDL); return option; } /* IDENTIFIER SEMI */ void parse_option_space_decl (cfile) struct parse *cfile; { int token; const char *val; struct universe **ua, *nu; char *s; next_token (&val, (unsigned *)0, cfile); /* Discard the SPACE token, which was checked by the caller. */ token = next_token (&val, (unsigned *)0, cfile); if (!is_identifier (token)) { parse_warn (cfile, "expecting identifier."); skip_to_semi (cfile); return; } nu = new_universe (MDL); if (!nu) log_fatal ("No memory for new option space."); /* Set up the server option universe... */ s = dmalloc (strlen (val) + 1, MDL); if (!s) log_fatal ("No memory for new option space name."); strcpy (s, val); nu -> name = s; nu -> lookup_func = lookup_hashed_option; nu -> option_state_dereference = hashed_option_state_dereference; nu -> foreach = hashed_option_space_foreach; nu -> save_func = save_hashed_option; nu -> delete_func = delete_hashed_option; nu -> encapsulate = hashed_option_space_encapsulate; nu -> decode = parse_option_buffer; nu -> length_size = 1; nu -> tag_size = 1; nu -> store_tag = putUChar; nu -> store_length = putUChar; nu -> index = universe_count++; if (nu -> index >= universe_max) { ua = dmalloc (universe_max * 2 * sizeof *ua, MDL); if (!ua) log_fatal ("No memory to expand option space array."); memcpy (ua, universes, universe_max * sizeof *ua); universe_max *= 2; dfree (universes, MDL); universes = ua; } universes [nu -> index] = nu; option_new_hash (&nu -> hash, 1, MDL); if (!nu -> hash) log_fatal ("Can't allocate %s option hash table.", nu -> name); universe_hash_add (universe_hash, nu -> name, 0, nu, MDL); parse_semi (cfile); } /* This is faked up to look good right now. Ideally, this should do a recursive parse and allow arbitrary data structure definitions, but for now it just allows you to specify a single type, an array of single types, a sequence of types, or an array of sequences of types. ocd :== NUMBER EQUALS ocsd SEMI ocsd :== ocsd_type | ocsd_type_sequence | ARRAY OF ocsd_simple_type_sequence ocsd_type_sequence :== LBRACE ocsd_types RBRACE ocsd_simple_type_sequence :== LBRACE ocsd_simple_types RBRACE ocsd_types :== ocsd_type | ocsd_types ocsd_type ocsd_type :== ocsd_simple_type | ARRAY OF ocsd_simple_type ocsd_simple_types :== ocsd_simple_type | ocsd_simple_types ocsd_simple_type ocsd_simple_type :== BOOLEAN | INTEGER NUMBER | SIGNED INTEGER NUMBER | UNSIGNED INTEGER NUMBER | IP-ADDRESS | TEXT | STRING | ENCAPSULATE identifier */ int parse_option_code_definition (cfile, option) struct parse *cfile; struct option *option; { const char *val; enum dhcp_token token; unsigned arrayp = 0; int recordp = 0; int no_more_in_record = 0; char tokbuf [128]; unsigned tokix = 0; char type; int code; int is_signed; char *s; int has_encapsulation = 0; /* Parse the option code. */ token = next_token (&val, (unsigned *)0, cfile); if (token != NUMBER) { parse_warn (cfile, "expecting option code number."); skip_to_semi (cfile); return 0; } option -> code = atoi (val); token = next_token (&val, (unsigned *)0, cfile); if (token != EQUAL) { parse_warn (cfile, "expecting \"=\""); skip_to_semi (cfile); return 0; } /* See if this is an array. */ token = next_token (&val, (unsigned *)0, cfile); if (token == ARRAY) { token = next_token (&val, (unsigned *)0, cfile); if (token != OF) { parse_warn (cfile, "expecting \"of\"."); skip_to_semi (cfile); return 0; } arrayp = 1; token = next_token (&val, (unsigned *)0, cfile); } if (token == LBRACE) { recordp = 1; token = next_token (&val, (unsigned *)0, cfile); } /* At this point we're expecting a data type. */ next_type: if (has_encapsulation) { parse_warn (cfile, "encapsulate must always be the last item."); skip_to_semi (cfile); return 0; } switch (token) { case ARRAY: if (arrayp) { parse_warn (cfile, "no nested arrays."); skip_to_rbrace (cfile, recordp); if (recordp) skip_to_semi (cfile); return 0; } token = next_token (&val, (unsigned *)0, cfile); if (token != OF) { parse_warn (cfile, "expecting \"of\"."); skip_to_semi (cfile); return 0; } arrayp = recordp + 1; token = next_token (&val, (unsigned *)0, cfile); if ((recordp) && (token == LBRACE)) { parse_warn (cfile, "only uniform array inside record."); skip_to_rbrace (cfile, recordp + 1); skip_to_semi (cfile); return 0; } goto next_type; case BOOLEAN: type = 'f'; break; case INTEGER: is_signed = 1; parse_integer: token = next_token (&val, (unsigned *)0, cfile); if (token != NUMBER) { parse_warn (cfile, "expecting number."); skip_to_rbrace (cfile, recordp); if (recordp) skip_to_semi (cfile); return 0; } switch (atoi (val)) { case 8: type = is_signed ? 'b' : 'B'; break; case 16: type = is_signed ? 's' : 'S'; break; case 32: type = is_signed ? 'l' : 'L'; break; default: parse_warn (cfile, "%s bit precision is not supported.", val); skip_to_rbrace (cfile, recordp); if (recordp) skip_to_semi (cfile); return 0; } break; case SIGNED: is_signed = 1; parse_signed: token = next_token (&val, (unsigned *)0, cfile); if (token != INTEGER) { parse_warn (cfile, "expecting \"integer\" keyword."); skip_to_rbrace (cfile, recordp); if (recordp) skip_to_semi (cfile); return 0; } goto parse_integer; case UNSIGNED: is_signed = 0; goto parse_signed; case IP_ADDRESS: type = 'I'; break; case DOMAIN_NAME: type = 'd'; goto no_arrays; case TEXT: type = 't'; no_arrays: if (arrayp) { parse_warn (cfile, "arrays of text strings not %s", "yet supported."); skip_to_rbrace (cfile, recordp); if (recordp) skip_to_semi (cfile); return 0; } no_more_in_record = 1; break; case STRING_TOKEN: type = 'X'; goto no_arrays; case ENCAPSULATE: token = next_token (&val, (unsigned *)0, cfile); if (!is_identifier (token)) { parse_warn (cfile, "expecting option space identifier"); skip_to_semi (cfile); return 0; } if (strlen (val) + tokix + 2 > sizeof (tokbuf)) goto toobig; tokbuf [tokix++] = 'E'; strcpy (&tokbuf [tokix], val); tokix += strlen (val); type = '.'; has_encapsulation = 1; break; default: parse_warn (cfile, "unknown data type %s", val); skip_to_rbrace (cfile, recordp); if (recordp) skip_to_semi (cfile); return 0; } if (tokix == sizeof tokbuf) { toobig: parse_warn (cfile, "too many types in record."); skip_to_rbrace (cfile, recordp); if (recordp) skip_to_semi (cfile); return 0; } tokbuf [tokix++] = type; if (recordp) { token = next_token (&val, (unsigned *)0, cfile); if (arrayp > recordp) { if (tokix == sizeof tokbuf) { parse_warn (cfile, "too many types in record."); skip_to_rbrace (cfile, 1); skip_to_semi (cfile); return 0; } arrayp = 0; tokbuf[tokix++] = 'a'; } if (token == COMMA) { if (no_more_in_record) { parse_warn (cfile, "%s must be at end of record.", type == 't' ? "text" : "string"); skip_to_rbrace (cfile, 1); if (recordp) skip_to_semi (cfile); return 0; } token = next_token (&val, (unsigned *)0, cfile); goto next_type; } if (token != RBRACE) { parse_warn (cfile, "expecting right brace."); skip_to_rbrace (cfile, 1); if (recordp) skip_to_semi (cfile); return 0; } } if (!parse_semi (cfile)) { parse_warn (cfile, "semicolon expected."); skip_to_semi (cfile); if (recordp) skip_to_semi (cfile); return 0; } if (has_encapsulation && arrayp) { parse_warn (cfile, "Arrays of encapsulations don't make sense."); return 0; } if (has_encapsulation && tokbuf [0] == 'E') has_encapsulation = 0; s = dmalloc (tokix + (arrayp ? 1 : 0) + (has_encapsulation ? 1 : 0) + 1, MDL); if (!s) log_fatal ("no memory for option format."); if (has_encapsulation) s [0] = 'e'; memcpy (s + has_encapsulation, tokbuf, tokix); tokix += has_encapsulation; if (arrayp) s [tokix++] = (arrayp > recordp) ? 'a' : 'A'; s [tokix] = 0; option -> format = s; if (option -> universe -> options [option -> code]) { /* XXX Free the option, but we can't do that now because they XXX may start out static. */ } option -> universe -> options [option -> code] = option; option_hash_add (option -> universe -> hash, (const char *)option -> name, 0, option, MDL); return 1; } /* * base64 :== NUMBER_OR_STRING */ int parse_base64 (data, cfile) struct data_string *data; struct parse *cfile; { enum dhcp_token token; const char *val; int i, j, k; unsigned acc = 0; static unsigned char from64 [] = {64, 64, 64, 64, 64, 64, 64, 64, /* \"#$%&' */ 64, 64, 64, 62, 64, 64, 64, 63, /* ()*+,-./ */ 52, 53, 54, 55, 56, 57, 58, 59, /* 01234567 */ 60, 61, 64, 64, 64, 64, 64, 64, /* 89:;<=>? */ 64, 0, 1, 2, 3, 4, 5, 6, /* @ABCDEFG */ 7, 8, 9, 10, 11, 12, 13, 14, /* HIJKLMNO */ 15, 16, 17, 18, 19, 20, 21, 22, /* PQRSTUVW */ 23, 24, 25, 64, 64, 64, 64, 64, /* XYZ[\]^_ */ 64, 26, 27, 28, 29, 30, 31, 32, /* 'abcdefg */ 33, 34, 35, 36, 37, 38, 39, 40, /* hijklmno */ 41, 42, 43, 44, 45, 46, 47, 48, /* pqrstuvw */ 49, 50, 51, 64, 64, 64, 64, 64}; /* xyz{|}~ */ struct string_list *bufs = (struct string_list *)0, *last = (struct string_list *)0, *t; int cc = 0; int terminated = 0; /* It's possible for a + or a / to cause a base64 quantity to be tokenized into more than one token, so we have to parse them all in before decoding. */ do { unsigned l; token = next_token (&val, &l, cfile); t = dmalloc (l + sizeof *t, MDL); if (!t) log_fatal ("no memory for base64 buffer."); memset (t, 0, (sizeof *t) - 1); memcpy (t -> string, val, l + 1); cc += l; if (last) last -> next = t; else bufs = t; last = t; token = peek_token (&val, (unsigned *)0, cfile); } while (token == NUMBER_OR_NAME || token == NAME || token == EQUAL || token == NUMBER || token == PLUS || token == SLASH || token == STRING); data -> len = cc; data -> len = (data -> len * 3) / 4; if (!buffer_allocate (&data -> buffer, data -> len, MDL)) { parse_warn (cfile, "can't allocate buffer for base64 data."); data -> len = 0; data -> data = (unsigned char *)0; return 0; } j = k = 0; for (t = bufs; t; t = t -> next) { for (i = 0; t -> string [i]; i++) { unsigned foo = t -> string [i]; if (terminated && foo != '=') { parse_warn (cfile, "stuff after base64 '=' terminator: %s.", &t -> string [i]); goto bad; } if (foo < ' ' || foo > 'z') { bad64: parse_warn (cfile, "invalid base64 character %d.", t -> string [i]); bad: data_string_forget (data, MDL); goto out; } if (foo == '=') terminated = 1; else { foo = from64 [foo - ' ']; if (foo == 64) goto bad64; acc = (acc << 6) + foo; switch (k % 4) { case 0: break; case 1: data -> buffer -> data [j++] = (acc >> 4); acc = acc & 0x0f; break; case 2: data -> buffer -> data [j++] = (acc >> 2); acc = acc & 0x03; break; case 3: data -> buffer -> data [j++] = acc; acc = 0; break; } } k++; } } if (k % 4) { if (acc) { parse_warn (cfile, "partial base64 value left over: %d.", acc); } } data -> len = j; data -> data = data -> buffer -> data; out: for (t = bufs; t; t = last) { last = t -> next; dfree (t, MDL); } if (data -> len) return 1; else return 0; } /* * colon-seperated-hex-list :== NUMBER | * NUMBER COLON colon-seperated-hex-list */ int parse_cshl (data, cfile) struct data_string *data; struct parse *cfile; { u_int8_t ibuf [128]; unsigned ilen = 0; unsigned tlen = 0; struct option_tag *sl = (struct option_tag *)0; struct option_tag *next, **last = &sl; enum dhcp_token token; const char *val; unsigned char *rvp; do { token = next_token (&val, (unsigned *)0, cfile); if (token != NUMBER && token != NUMBER_OR_NAME) { parse_warn (cfile, "expecting hexadecimal number."); skip_to_semi (cfile); for (; sl; sl = next) { next = sl -> next; dfree (sl, MDL); } return 0; } if (ilen == sizeof ibuf) { next = (struct option_tag *) dmalloc (ilen - 1 + sizeof (struct option_tag), MDL); if (!next) log_fatal ("no memory for string list."); memcpy (next -> data, ibuf, ilen); *last = next; last = &next -> next; tlen += ilen; ilen = 0; } convert_num (cfile, &ibuf [ilen++], val, 16, 8); token = peek_token (&val, (unsigned *)0, cfile); if (token != COLON) break; token = next_token (&val, (unsigned *)0, cfile); } while (1); if (!buffer_allocate (&data -> buffer, tlen + ilen, MDL)) log_fatal ("no memory to store octet data."); data -> data = &data -> buffer -> data [0]; data -> len = tlen + ilen; data -> terminated = 0; rvp = &data -> buffer -> data [0]; while (sl) { next = sl -> next; memcpy (rvp, sl -> data, sizeof ibuf); rvp += sizeof ibuf; dfree (sl, MDL); sl = next; } memcpy (rvp, ibuf, ilen); return 1; } /* * executable-statements :== executable-statement executable-statements | * executable-statement * * executable-statement :== * IF if-statement | * ADD class-name SEMI | * BREAK SEMI | * OPTION option-parameter SEMI | * SUPERSEDE option-parameter SEMI | * PREPEND option-parameter SEMI | * APPEND option-parameter SEMI */ int parse_executable_statements (statements, cfile, lose, case_context) struct executable_statement **statements; struct parse *cfile; int *lose; enum expression_context case_context; { struct executable_statement **next; next = statements; while (parse_executable_statement (next, cfile, lose, case_context)) next = &((*next) -> next); if (!*lose) return 1; return 0; } int parse_executable_statement (result, cfile, lose, case_context) struct executable_statement **result; struct parse *cfile; int *lose; enum expression_context case_context; { enum dhcp_token token; const char *val; struct executable_statement base; struct class *cta; struct option *option; struct option_cache *cache; int known; int flag; int i; struct dns_zone *zone; isc_result_t status; char *s; token = peek_token (&val, (unsigned *)0, cfile); switch (token) { case IF: next_token (&val, (unsigned *)0, cfile); return parse_if_statement (result, cfile, lose); case TOKEN_ADD: token = next_token (&val, (unsigned *)0, cfile); token = next_token (&val, (unsigned *)0, cfile); if (token != STRING) { parse_warn (cfile, "expecting class name."); skip_to_semi (cfile); *lose = 1; return 0; } cta = (struct class *)0; status = find_class (&cta, val, MDL); if (status != ISC_R_SUCCESS) { parse_warn (cfile, "class %s: %s", val, isc_result_totext (status)); skip_to_semi (cfile); *lose = 1; return 0; } if (!parse_semi (cfile)) { *lose = 1; return 0; } if (!executable_statement_allocate (result, MDL)) log_fatal ("no memory for new statement."); (*result) -> op = add_statement; (*result) -> data.add = cta; break; case BREAK: token = next_token (&val, (unsigned *)0, cfile); if (!parse_semi (cfile)) { *lose = 1; return 0; } if (!executable_statement_allocate (result, MDL)) log_fatal ("no memory for new statement."); (*result) -> op = break_statement; break; case SEND: token = next_token (&val, (unsigned *)0, cfile); known = 0; option = parse_option_name (cfile, 0, &known); if (!option) { *lose = 1; return 0; } return parse_option_statement (result, cfile, 1, option, send_option_statement); case SUPERSEDE: case OPTION: token = next_token (&val, (unsigned *)0, cfile); known = 0; option = parse_option_name (cfile, 0, &known); if (!option) { *lose = 1; return 0; } return parse_option_statement (result, cfile, 1, option, supersede_option_statement); case ALLOW: flag = 1; goto pad; case DENY: flag = 0; goto pad; case IGNORE: flag = 2; pad: token = next_token (&val, (unsigned *)0, cfile); cache = (struct option_cache *)0; if (!parse_allow_deny (&cache, cfile, flag)) return 0; if (!executable_statement_allocate (result, MDL)) log_fatal ("no memory for new statement."); (*result) -> op = supersede_option_statement; (*result) -> data.option = cache; break; case DEFAULT: token = next_token (&val, (unsigned *)0, cfile); token = peek_token (&val, (unsigned *)0, cfile); if (token == COLON) goto switch_default; known = 0; option = parse_option_name (cfile, 0, &known); if (!option) { *lose = 1; return 0; } return parse_option_statement (result, cfile, 1, option, default_option_statement); case PREPEND: token = next_token (&val, (unsigned *)0, cfile); known = 0; option = parse_option_name (cfile, 0, &known); if (!option) { *lose = 1; return 0; } return parse_option_statement (result, cfile, 1, option, prepend_option_statement); case APPEND: token = next_token (&val, (unsigned *)0, cfile); known = 0; option = parse_option_name (cfile, 0, &known); if (!option) { *lose = 1; return 0; } return parse_option_statement (result, cfile, 1, option, append_option_statement); case ON: token = next_token (&val, (unsigned *)0, cfile); return parse_on_statement (result, cfile, lose); case SWITCH: token = next_token (&val, (unsigned *)0, cfile); return parse_switch_statement (result, cfile, lose); case CASE: token = next_token (&val, (unsigned *)0, cfile); if (case_context == context_any) { parse_warn (cfile, "case statement in inappropriate scope."); *lose = 1; skip_to_semi (cfile); return 0; } return parse_case_statement (result, cfile, lose, case_context); switch_default: token = next_token (&val, (unsigned *)0, cfile); if (case_context == context_any) { parse_warn (cfile, "switch default statement in %s", "inappropriate scope."); *lose = 1; return 0; } else { if (!executable_statement_allocate (result, MDL)) log_fatal ("no memory for default statement."); (*result) -> op = default_statement; return 1; } case DEFINE: case TOKEN_SET: token = next_token (&val, (unsigned *)0, cfile); if (token == DEFINE) flag = 1; else flag = 0; token = next_token (&val, (unsigned *)0, cfile); if (token != NAME && token != NUMBER_OR_NAME) { parse_warn (cfile, "%s can't be a variable name", val); badset: skip_to_semi (cfile); *lose = 1; return 0; } if (!executable_statement_allocate (result, MDL)) log_fatal ("no memory for set statement."); (*result) -> op = flag ? define_statement : set_statement; (*result) -> data.set.name = dmalloc (strlen (val) + 1, MDL); if (!(*result)->data.set.name) log_fatal ("can't allocate variable name"); strcpy ((*result) -> data.set.name, val); token = next_token (&val, (unsigned *)0, cfile); if (token == LPAREN) { struct string_list *head, *cur, *new; struct expression *expr; head = cur = (struct string_list *)0; do { token = next_token (&val, (unsigned *)0, cfile); if (token == RPAREN) break; if (token != NAME && token != NUMBER_OR_NAME) { parse_warn (cfile, "expecting argument name"); skip_to_rbrace (cfile, 0); *lose = 1; executable_statement_dereference (result, MDL); return 0; } new = ((struct string_list *) dmalloc (sizeof (struct string_list) + strlen (val), MDL)); if (!new) log_fatal ("can't allocate string."); memset (new, 0, sizeof *new); strcpy (new -> string, val); if (cur) { cur -> next = new; cur = new; } else { head = cur = new; } token = next_token (&val, (unsigned *)0, cfile); } while (token == COMMA); if (token != RPAREN) { parse_warn (cfile, "expecting right paren."); badx: skip_to_semi (cfile); *lose = 1; executable_statement_dereference (result, MDL); return 0; } token = next_token (&val, (unsigned *)0, cfile); if (token != LBRACE) { parse_warn (cfile, "expecting left brace."); goto badx; } expr = (struct expression *)0; if (!(expression_allocate (&expr, MDL))) log_fatal ("can't allocate expression."); expr -> op = expr_function; if (!fundef_allocate (&expr -> data.func, MDL)) log_fatal ("can't allocate fundef."); expr -> data.func -> args = head; (*result) -> data.set.expr = expr; if (!(parse_executable_statements (&expr -> data.func -> statements, cfile, lose, case_context))) { if (*lose) goto badx; } token = next_token (&val, (unsigned *)0, cfile); if (token != RBRACE) { parse_warn (cfile, "expecting rigt brace."); goto badx; } } else { if (token != EQUAL) { parse_warn (cfile, "expecting '=' in %s statement.", flag ? "define" : "set"); goto badset; } if (!parse_expression (&(*result) -> data.set.expr, cfile, lose, context_any, (struct expression **)0, expr_none)) { if (!*lose) parse_warn (cfile, "expecting expression."); else *lose = 1; skip_to_semi (cfile); executable_statement_dereference (result, MDL); return 0; } if (!parse_semi (cfile)) { *lose = 1; executable_statement_dereference (result, MDL); return 0; } } break; case UNSET: token = next_token (&val, (unsigned *)0, cfile); token = next_token (&val, (unsigned *)0, cfile); if (token != NAME && token != NUMBER_OR_NAME) { parse_warn (cfile, "%s can't be a variable name", val); badunset: skip_to_semi (cfile); *lose = 1; return 0; } if (!executable_statement_allocate (result, MDL)) log_fatal ("no memory for set statement."); (*result) -> op = unset_statement; (*result) -> data.unset = dmalloc (strlen (val) + 1, MDL); if (!(*result)->data.unset) log_fatal ("can't allocate variable name"); strcpy ((*result) -> data.unset, val); if (!parse_semi (cfile)) { *lose = 1; executable_statement_dereference (result, MDL); return 0; } break; case EVAL: token = next_token (&val, (unsigned *)0, cfile); if (!executable_statement_allocate (result, MDL)) log_fatal ("no memory for eval statement."); (*result) -> op = eval_statement; if (!parse_expression (&(*result) -> data.eval, cfile, lose, context_data, /* XXX */ (struct expression **)0, expr_none)) { if (!*lose) parse_warn (cfile, "expecting data expression."); else *lose = 1; skip_to_semi (cfile); executable_statement_dereference (result, MDL); return 0; } if (!parse_semi (cfile)) { *lose = 1; executable_statement_dereference (result, MDL); } break; case RETURN: token = next_token (&val, (unsigned *)0, cfile); if (!executable_statement_allocate (result, MDL)) log_fatal ("no memory for return statement."); (*result) -> op = return_statement; if (!parse_expression (&(*result) -> data.retval, cfile, lose, context_data, (struct expression **)0, expr_none)) { if (!*lose) parse_warn (cfile, "expecting data expression."); else *lose = 1; skip_to_semi (cfile); executable_statement_dereference (result, MDL); return 0; } if (!parse_semi (cfile)) { *lose = 1; executable_statement_dereference (result, MDL); return 0; } break; case LOG: token = next_token (&val, (unsigned *)0, cfile); if (!executable_statement_allocate (result, MDL)) log_fatal ("no memory for log statement."); (*result) -> op = log_statement; token = next_token (&val, (unsigned *)0, cfile); if (token != LPAREN) { parse_warn (cfile, "left parenthesis expected."); skip_to_semi (cfile); *lose = 1; return 0; } token = peek_token (&val, (unsigned *)0, cfile); i = 1; if (token == FATAL) { (*result) -> data.log.priority = log_priority_fatal; } else if (token == ERROR) { (*result) -> data.log.priority = log_priority_error; } else if (token == TOKEN_DEBUG) { (*result) -> data.log.priority = log_priority_debug; } else if (token == INFO) { (*result) -> data.log.priority = log_priority_info; } else { (*result) -> data.log.priority = log_priority_debug; i = 0; } if (i) { token = next_token (&val, (unsigned *)0, cfile); token = next_token (&val, (unsigned *)0, cfile); if (token != COMMA) { parse_warn (cfile, "comma expected."); skip_to_semi (cfile); *lose = 1; return 0; } } if (!(parse_data_expression (&(*result) -> data.log.expr, cfile, lose))) { skip_to_semi (cfile); *lose = 1; return 0; } token = next_token (&val, (unsigned *)0, cfile); if (token != RPAREN) { parse_warn (cfile, "right parenthesis expected."); skip_to_semi (cfile); *lose = 1; return 0; } token = next_token (&val, (unsigned *)0, cfile); if (token != SEMI) { parse_warn (cfile, "semicolon expected."); skip_to_semi (cfile); *lose = 1; return 0; } break; /* Not really a statement, but we parse it here anyway because it's appropriate for all DHCP agents with parsers. */ case ZONE: token = next_token (&val, (unsigned *)0, cfile); zone = (struct dns_zone *)0; if (!dns_zone_allocate (&zone, MDL)) log_fatal ("no memory for new zone."); zone -> name = parse_host_name (cfile); if (!zone -> name) { parse_warn (cfile, "expecting hostname."); badzone: *lose = 1; skip_to_semi (cfile); dns_zone_dereference (&zone, MDL); return 0; } i = strlen (zone -> name); if (zone -> name [i - 1] != '.') { s = dmalloc ((unsigned)i + 2, MDL); if (!s) { parse_warn (cfile, "no trailing '.' on zone"); goto badzone; } strcpy (s, zone -> name); s [i] = '.'; s [i + 1] = 0; dfree (zone -> name, MDL); zone -> name = s; } if (!parse_zone (zone, cfile)) goto badzone; status = enter_dns_zone (zone); if (status != ISC_R_SUCCESS) { parse_warn (cfile, "dns zone key %s: %s", zone -> name, isc_result_totext (status)); dns_zone_dereference (&zone, MDL); return 0; } dns_zone_dereference (&zone, MDL); return 1; /* Also not really a statement, but same idea as above. */ case KEY: token = next_token (&val, (unsigned *)0, cfile); if (!parse_key (cfile)) { *lose = 1; return 0; } return 1; default: if (config_universe && is_identifier (token)) { option = (struct option *)0; option_hash_lookup (&option, config_universe -> hash, val, 0, MDL); if (option) { token = next_token (&val, (unsigned *)0, cfile); return parse_option_statement (result, cfile, 1, option, supersede_option_statement); } } if (token == NUMBER_OR_NAME || token == NAME) { /* This is rather ugly. Since function calls are data expressions, fake up an eval statement. */ if (!executable_statement_allocate (result, MDL)) log_fatal ("no memory for eval statement."); (*result) -> op = eval_statement; if (!parse_expression (&(*result) -> data.eval, cfile, lose, context_data, (struct expression **)0, expr_none)) { if (!*lose) parse_warn (cfile, "expecting " "function call."); else *lose = 1; skip_to_semi (cfile); executable_statement_dereference (result, MDL); return 0; } if (!parse_semi (cfile)) { *lose = 1; executable_statement_dereference (result, MDL); return 0; } break; } *lose = 0; return 0; } return 1; } /* zone-statements :== zone-statement | zone-statement zone-statements zone-statement :== PRIMARY ip-addresses SEMI | SECONDARY ip-addresses SEMI | key-reference SEMI ip-addresses :== ip-addr-or-hostname | ip-addr-or-hostname COMMA ip-addresses key-reference :== KEY STRING | KEY identifier */ int parse_zone (struct dns_zone *zone, struct parse *cfile) { int token; const char *val; char *key_name; struct option_cache *oc; int done = 0; token = next_token (&val, (unsigned *)0, cfile); if (token != LBRACE) { parse_warn (cfile, "expecting left brace"); return 0; } do { token = peek_token (&val, (unsigned *)0, cfile); switch (token) { case PRIMARY: if (zone -> primary) { parse_warn (cfile, "more than one primary."); skip_to_semi (cfile); return 0; } if (!option_cache_allocate (&zone -> primary, MDL)) log_fatal ("can't allocate primary option cache."); oc = zone -> primary; goto consemup; case SECONDARY: if (zone -> secondary) { parse_warn (cfile, "more than one secondary."); skip_to_semi (cfile); return 0; } if (!option_cache_allocate (&zone -> secondary, MDL)) log_fatal ("can't allocate secondary."); oc = zone -> secondary; consemup: token = next_token (&val, (unsigned *)0, cfile); do { struct expression *expr = (struct expression *)0; if (!parse_ip_addr_or_hostname (&expr, cfile, 0)) { parse_warn (cfile, "expecting IP addr or hostname."); skip_to_semi (cfile); return 0; } if (oc -> expression) { struct expression *old = (struct expression *)0; expression_reference (&old, oc -> expression, MDL); expression_dereference (&oc -> expression, MDL); if (!make_concat (&oc -> expression, old, expr)) log_fatal ("no memory for concat."); expression_dereference (&expr, MDL); expression_dereference (&old, MDL); } else { expression_reference (&oc -> expression, expr, MDL); expression_dereference (&expr, MDL); } token = next_token (&val, (unsigned *)0, cfile); } while (token == COMMA); if (token != SEMI) { parse_warn (cfile, "expecting semicolon."); skip_to_semi (cfile); return 0; } break; case KEY: token = next_token (&val, (unsigned *)0, cfile); token = peek_token (&val, (unsigned *)0, cfile); if (token == STRING) { token = next_token (&val, (unsigned *)0, cfile); key_name = (char *)0; } else { key_name = parse_host_name (cfile); if (!key_name) { parse_warn (cfile, "expecting key name."); skip_to_semi (cfile); return 0; } val = key_name; } if (omapi_auth_key_lookup_name (&zone -> key, val) != ISC_R_SUCCESS) parse_warn (cfile, "unknown key %s", val); if (key_name) dfree (key_name, MDL); if (!parse_semi (cfile)) return 0; break; default: done = 1; break; } } while (!done); token = next_token (&val, (unsigned *)0, cfile); if (token != RBRACE) { parse_warn (cfile, "expecting right brace."); return 0; } return 1; } /* key-statements :== key-statement | key-statement key-statements key-statement :== ALGORITHM host-name SEMI | secret-definition SEMI secret-definition :== SECRET base64val | SECRET STRING */ int parse_key (struct parse *cfile) { int token; const char *val; int done = 0; struct auth_key *key; struct data_string ds; isc_result_t status; char *s; key = (struct auth_key *)0; if (omapi_auth_key_new (&key, MDL) != ISC_R_SUCCESS) log_fatal ("no memory for key"); token = peek_token (&val, (unsigned *)0, cfile); if (token == STRING) { token = next_token (&val, (unsigned *)0, cfile); key -> name = dmalloc (strlen (val) + 1, MDL); if (!key -> name) log_fatal ("no memory for key name."); strcpy (key -> name, val); } else { key -> name = parse_host_name (cfile); if (!key -> name) { parse_warn (cfile, "expecting key name."); skip_to_semi (cfile); goto bad; } } token = next_token (&val, (unsigned *)0, cfile); if (token != LBRACE) { parse_warn (cfile, "expecting left brace"); goto bad; } do { token = next_token (&val, (unsigned *)0, cfile); switch (token) { case ALGORITHM: if (key -> algorithm) { parse_warn (cfile, "key %s: too many algorithms", key -> name); goto rbad; } key -> algorithm = parse_host_name (cfile); if (!key -> algorithm) { parse_warn (cfile, "expecting key algorithm name."); goto rbad; } if (!parse_semi (cfile)) goto rbad; /* If the algorithm name isn't an FQDN, tack on the .SIG-ALG.REG.NET. domain. */ s = strrchr (key -> algorithm, '.'); if (!s) { static char add [] = ".SIG-ALG.REG.INT."; s = dmalloc (strlen (key -> algorithm) + sizeof (add), MDL); if (!s) { log_error ("no memory for key %s.", "algorithm"); goto rbad; } strcpy (s, key -> algorithm); strcat (s, add); dfree (key -> algorithm, MDL); key -> algorithm = s; } else if (s [1]) { /* If there is no trailing '.', hack one in. */ s = dmalloc (strlen (key -> algorithm) + 2, MDL); if (!s) { log_error ("no memory for key %s.", key -> algorithm); goto rbad; } strcpy (s, key -> algorithm); strcat (s, "."); dfree (key -> algorithm, MDL); key -> algorithm = s; } break; case SECRET: if (key -> key) { parse_warn (cfile, "key %s: too many secrets", key -> name); goto rbad; } memset (&ds, 0, sizeof(ds)); if (!parse_base64 (&ds, cfile)) goto rbad; status = omapi_data_string_new (&key -> key, ds.len, MDL); if (status != ISC_R_SUCCESS) goto rbad; memcpy (key -> key -> value, ds.buffer -> data, ds.len); data_string_forget (&ds, MDL); if (!parse_semi (cfile)) goto rbad; break; default: done = 1; break; } } while (!done); if (token != RBRACE) { parse_warn (cfile, "expecting right brace."); goto rbad; } /* Allow the BIND 8 syntax, which has a semicolon after each closing brace. */ token = peek_token (&val, (unsigned *)0, cfile); if (token == SEMI) token = next_token (&val, (unsigned *)0, cfile); /* Remember the key. */ status = omapi_auth_key_enter (key); if (status != ISC_R_SUCCESS) { parse_warn (cfile, "tsig key %s: %s", key -> name, isc_result_totext (status)); goto bad; } omapi_auth_key_dereference (&key, MDL); return 1; rbad: skip_to_rbrace (cfile, 1); bad: omapi_auth_key_dereference (&key, MDL); return 0; } /* * on-statement :== event-types LBRACE executable-statements RBRACE * event-types :== event-type OR event-types | * event-type * event-type :== EXPIRY | COMMIT | RELEASE */ int parse_on_statement (result, cfile, lose) struct executable_statement **result; struct parse *cfile; int *lose; { enum dhcp_token token; const char *val; if (!executable_statement_allocate (result, MDL)) log_fatal ("no memory for new statement."); (*result) -> op = on_statement; do { token = next_token (&val, (unsigned *)0, cfile); switch (token) { case EXPIRY: (*result) -> data.on.evtypes |= ON_EXPIRY; break; case COMMIT: (*result) -> data.on.evtypes |= ON_COMMIT; break; case RELEASE: (*result) -> data.on.evtypes |= ON_RELEASE; break; case TRANSMISSION: (*result) -> data.on.evtypes |= ON_TRANSMISSION; break; default: parse_warn (cfile, "expecting a lease event type"); skip_to_semi (cfile); *lose = 1; executable_statement_dereference (result, MDL); return 0; } token = next_token (&val, (unsigned *)0, cfile); } while (token == OR); /* Semicolon means no statements. */ if (token == SEMI) return 1; if (token != LBRACE) { parse_warn (cfile, "left brace expected."); skip_to_semi (cfile); *lose = 1; executable_statement_dereference (result, MDL); return 0; } if (!parse_executable_statements (&(*result) -> data.on.statements, cfile, lose, context_any)) { if (*lose) { /* Try to even things up. */ do { token = next_token (&val, (unsigned *)0, cfile); } while (token != END_OF_FILE && token != RBRACE); executable_statement_dereference (result, MDL); return 0; } } token = next_token (&val, (unsigned *)0, cfile); if (token != RBRACE) { parse_warn (cfile, "right brace expected."); skip_to_semi (cfile); *lose = 1; executable_statement_dereference (result, MDL); return 0; } return 1; } /* * switch-statement :== LPAREN expr RPAREN LBRACE executable-statements RBRACE * */ int parse_switch_statement (result, cfile, lose) struct executable_statement **result; struct parse *cfile; int *lose; { enum dhcp_token token; const char *val; if (!executable_statement_allocate (result, MDL)) log_fatal ("no memory for new statement."); (*result) -> op = switch_statement; token = next_token (&val, (unsigned *)0, cfile); if (token != LPAREN) { parse_warn (cfile, "expecting left brace."); pfui: *lose = 1; skip_to_semi (cfile); gnorf: executable_statement_dereference (result, MDL); return 0; } if (!parse_expression (&(*result) -> data.s_switch.expr, cfile, lose, context_data_or_numeric, (struct expression **)0, expr_none)) { if (!*lose) { parse_warn (cfile, "expecting data or numeric expression."); goto pfui; } goto gnorf; } token = next_token (&val, (unsigned *)0, cfile); if (token != RPAREN) { parse_warn (cfile, "right paren expected."); goto pfui; } token = next_token (&val, (unsigned *)0, cfile); if (token != LBRACE) { parse_warn (cfile, "left brace expected."); goto pfui; } if (!(parse_executable_statements (&(*result) -> data.s_switch.statements, cfile, lose, (is_data_expression ((*result) -> data.s_switch.expr) ? context_data : context_numeric)))) { if (*lose) { skip_to_rbrace (cfile, 1); executable_statement_dereference (result, MDL); return 0; } } token = next_token (&val, (unsigned *)0, cfile); if (token != RBRACE) { parse_warn (cfile, "right brace expected."); goto pfui; } return 1; } /* * case-statement :== CASE expr COLON * */ int parse_case_statement (result, cfile, lose, case_context) struct executable_statement **result; struct parse *cfile; int *lose; enum expression_context case_context; { enum dhcp_token token; const char *val; if (!executable_statement_allocate (result, MDL)) log_fatal ("no memory for new statement."); (*result) -> op = case_statement; if (!parse_expression (&(*result) -> data.c_case, cfile, lose, case_context, (struct expression **)0, expr_none)) { if (!*lose) { parse_warn (cfile, "expecting %s expression.", (case_context == context_data ? "data" : "numeric")); } pfui: *lose = 1; skip_to_semi (cfile); executable_statement_dereference (result, MDL); return 0; } token = next_token (&val, (unsigned *)0, cfile); if (token != COLON) { parse_warn (cfile, "colon expected."); goto pfui; } return 1; } /* * if-statement :== boolean-expression LBRACE executable-statements RBRACE * else-statement * * else-statement :== | * ELSE LBRACE executable-statements RBRACE | * ELSE IF if-statement | * ELSIF if-statement */ int parse_if_statement (result, cfile, lose) struct executable_statement **result; struct parse *cfile; int *lose; { enum dhcp_token token; const char *val; int parenp; if (!executable_statement_allocate (result, MDL)) log_fatal ("no memory for if statement."); (*result) -> op = if_statement; token = peek_token (&val, (unsigned *)0, cfile); if (token == LPAREN) { parenp = 1; next_token (&val, (unsigned *)0, cfile); } else parenp = 0; if (!parse_boolean_expression (&(*result) -> data.ie.expr, cfile, lose)) { if (!*lose) parse_warn (cfile, "boolean expression expected."); executable_statement_dereference (result, MDL); *lose = 1; return 0; } #if defined (DEBUG_EXPRESSION_PARSE) print_expression ("if condition", (*result) -> data.ie.expr); #endif if (parenp) { token = next_token (&val, (unsigned *)0, cfile); if (token != RPAREN) { parse_warn (cfile, "expecting right paren."); *lose = 1; executable_statement_dereference (result, MDL); return 0; } } token = next_token (&val, (unsigned *)0, cfile); if (token != LBRACE) { parse_warn (cfile, "left brace expected."); skip_to_semi (cfile); *lose = 1; executable_statement_dereference (result, MDL); return 0; } if (!parse_executable_statements (&(*result) -> data.ie.tc, cfile, lose, context_any)) { if (*lose) { /* Try to even things up. */ do { token = next_token (&val, (unsigned *)0, cfile); } while (token != END_OF_FILE && token != RBRACE); executable_statement_dereference (result, MDL); return 0; } } token = next_token (&val, (unsigned *)0, cfile); if (token != RBRACE) { parse_warn (cfile, "right brace expected."); skip_to_semi (cfile); *lose = 1; executable_statement_dereference (result, MDL); return 0; } token = peek_token (&val, (unsigned *)0, cfile); if (token == ELSE) { token = next_token (&val, (unsigned *)0, cfile); token = peek_token (&val, (unsigned *)0, cfile); if (token == IF) { token = next_token (&val, (unsigned *)0, cfile); if (!parse_if_statement (&(*result) -> data.ie.fc, cfile, lose)) { if (!*lose) parse_warn (cfile, "expecting if statement"); executable_statement_dereference (result, MDL); *lose = 1; return 0; } } else if (token != LBRACE) { parse_warn (cfile, "left brace or if expected."); skip_to_semi (cfile); *lose = 1; executable_statement_dereference (result, MDL); return 0; } else { token = next_token (&val, (unsigned *)0, cfile); if (!(parse_executable_statements (&(*result) -> data.ie.fc, cfile, lose, context_any))) { executable_statement_dereference (result, MDL); return 0; } token = next_token (&val, (unsigned *)0, cfile); if (token != RBRACE) { parse_warn (cfile, "right brace expected."); skip_to_semi (cfile); *lose = 1; executable_statement_dereference (result, MDL); return 0; } } } else if (token == ELSIF) { token = next_token (&val, (unsigned *)0, cfile); if (!parse_if_statement (&(*result) -> data.ie.fc, cfile, lose)) { if (!*lose) parse_warn (cfile, "expecting conditional."); executable_statement_dereference (result, MDL); *lose = 1; return 0; } } else (*result) -> data.ie.fc = (struct executable_statement *)0; return 1; } /* * boolean_expression :== CHECK STRING | * NOT boolean-expression | * data-expression EQUAL data-expression | * data-expression BANG EQUAL data-expression | * boolean-expression AND boolean-expression | * boolean-expression OR boolean-expression * EXISTS OPTION-NAME */ int parse_boolean_expression (expr, cfile, lose) struct expression **expr; struct parse *cfile; int *lose; { /* Parse an expression... */ if (!parse_expression (expr, cfile, lose, context_boolean, (struct expression **)0, expr_none)) return 0; if (!is_boolean_expression (*expr) && (*expr) -> op != expr_variable_reference && (*expr) -> op != expr_funcall) { parse_warn (cfile, "Expecting a boolean expression."); *lose = 1; expression_dereference (expr, MDL); return 0; } return 1; } /* * data_expression :== SUBSTRING LPAREN data-expression COMMA * numeric-expression COMMA * numeric-expression RPAREN | * CONCAT LPAREN data-expression COMMA data-expression RPAREN * SUFFIX LPAREN data_expression COMMA * numeric-expression RPAREN | * OPTION option_name | * HARDWARE | * PACKET LPAREN numeric-expression COMMA * numeric-expression RPAREN | * STRING | * colon_seperated_hex_list */ int parse_data_expression (expr, cfile, lose) struct expression **expr; struct parse *cfile; int *lose; { /* Parse an expression... */ if (!parse_expression (expr, cfile, lose, context_data, (struct expression **)0, expr_none)) return 0; if (!is_data_expression (*expr) && (*expr) -> op != expr_variable_reference && (*expr) -> op != expr_funcall) { parse_warn (cfile, "Expecting a data expression."); *lose = 1; return 0; } return 1; } /* * numeric-expression :== EXTRACT_INT LPAREN data-expression * COMMA number RPAREN | * NUMBER */ int parse_numeric_expression (expr, cfile, lose) struct expression **expr; struct parse *cfile; int *lose; { /* Parse an expression... */ if (!parse_expression (expr, cfile, lose, context_numeric, (struct expression **)0, expr_none)) return 0; if (!is_numeric_expression (*expr) && (*expr) -> op != expr_variable_reference && (*expr) -> op != expr_funcall) { parse_warn (cfile, "Expecting a numeric expression."); *lose = 1; return 0; } return 1; } /* * dns-expression :== * UPDATE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA * data-expression COMMA numeric-expression RPAREN * DELETE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA * data-expression RPAREN * EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA * data-expression RPAREN * NOT EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA * data-expression RPAREN * ns-class :== IN | CHAOS | HS | NUMBER * ns-type :== A | PTR | MX | TXT | NUMBER */ int parse_dns_expression (expr, cfile, lose) struct expression **expr; struct parse *cfile; int *lose; { /* Parse an expression... */ if (!parse_expression (expr, cfile, lose, context_dns, (struct expression **)0, expr_none)) return 0; if (!is_dns_expression (*expr) && (*expr) -> op != expr_variable_reference && (*expr) -> op != expr_funcall) { parse_warn (cfile, "Expecting a dns update subexpression."); *lose = 1; return 0; } return 1; } /* Parse a subexpression that does not contain a binary operator. */ int parse_non_binary (expr, cfile, lose, context) struct expression **expr; struct parse *cfile; int *lose; enum expression_context context; { enum dhcp_token token; const char *val; struct collection *col; struct option *option; struct expression *nexp, **ep; int known; enum expr_op opcode; const char *s; char *cptr; struct executable_statement *stmt; int i; unsigned long u; isc_result_t status, code; unsigned len; token = peek_token (&val, (unsigned *)0, cfile); /* Check for unary operators... */ switch (token) { case CHECK: token = next_token (&val, (unsigned *)0, cfile); token = next_token (&val, (unsigned *)0, cfile); if (token != STRING) { parse_warn (cfile, "string expected."); skip_to_semi (cfile); *lose = 1; return 0; } for (col = collections; col; col = col -> next) if (!strcmp (col -> name, val)) break; if (!col) { parse_warn (cfile, "unknown collection."); *lose = 1; return 0; } if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_check; (*expr) -> data.check = col; break; case TOKEN_NOT: token = next_token (&val, (unsigned *)0, cfile); if (context == context_dns) { token = peek_token (&val, (unsigned *)0, cfile); goto not_exists; } if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_not; if (!parse_non_binary (&(*expr) -> data.not, cfile, lose, context_boolean)) { if (!*lose) { parse_warn (cfile, "expression expected"); skip_to_semi (cfile); } *lose = 1; expression_dereference (expr, MDL); return 0; } if (!is_boolean_expression ((*expr) -> data.not)) { *lose = 1; parse_warn (cfile, "boolean expression expected"); skip_to_semi (cfile); expression_dereference (expr, MDL); return 0; } break; case LPAREN: token = next_token (&val, (unsigned *)0, cfile); if (!parse_expression (expr, cfile, lose, context, (struct expression **)0, expr_none)) { if (!*lose) { parse_warn (cfile, "expression expected"); skip_to_semi (cfile); } *lose = 1; return 0; } token = next_token (&val, (unsigned *)0, cfile); if (token != RPAREN) { *lose = 1; parse_warn (cfile, "right paren expected"); skip_to_semi (cfile); return 0; } break; case EXISTS: if (context == context_dns) goto ns_exists; token = next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_exists; known = 0; (*expr) -> data.option = parse_option_name (cfile, 0, &known); if (!(*expr) -> data.option) { *lose = 1; expression_dereference (expr, MDL); return 0; } break; case STATIC: token = next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_static; break; case KNOWN: token = next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_known; break; case SUBSTRING: token = next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_substring; token = next_token (&val, (unsigned *)0, cfile); if (token != LPAREN) { nolparen: expression_dereference (expr, MDL); parse_warn (cfile, "left parenthesis expected."); *lose = 1; return 0; } if (!parse_data_expression (&(*expr) -> data.substring.expr, cfile, lose)) { nodata: expression_dereference (expr, MDL); if (!*lose) { parse_warn (cfile, "expecting data expression."); skip_to_semi (cfile); *lose = 1; } return 0; } token = next_token (&val, (unsigned *)0, cfile); if (token != COMMA) { nocomma: expression_dereference (expr, MDL); parse_warn (cfile, "comma expected."); *lose = 1; return 0; } if (!parse_numeric_expression (&(*expr) -> data.substring.offset,cfile, lose)) { nonum: if (!*lose) { parse_warn (cfile, "expecting numeric expression."); skip_to_semi (cfile); *lose = 1; } expression_dereference (expr, MDL); return 0; } token = next_token (&val, (unsigned *)0, cfile); if (token != COMMA) goto nocomma; if (!parse_numeric_expression (&(*expr) -> data.substring.len, cfile, lose)) goto nonum; token = next_token (&val, (unsigned *)0, cfile); if (token != RPAREN) { norparen: parse_warn (cfile, "right parenthesis expected."); *lose = 1; expression_dereference (expr, MDL); return 0; } break; case SUFFIX: token = next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_suffix; token = next_token (&val, (unsigned *)0, cfile); if (token != LPAREN) goto nolparen; if (!parse_data_expression (&(*expr) -> data.suffix.expr, cfile, lose)) goto nodata; token = next_token (&val, (unsigned *)0, cfile); if (token != COMMA) goto nocomma; if (!parse_numeric_expression (&(*expr) -> data.suffix.len, cfile, lose)) goto nonum; token = next_token (&val, (unsigned *)0, cfile); if (token != RPAREN) goto norparen; break; case CONCAT: token = next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_concat; token = next_token (&val, (unsigned *)0, cfile); if (token != LPAREN) goto nolparen; if (!parse_data_expression (&(*expr) -> data.concat [0], cfile, lose)) goto nodata; token = next_token (&val, (unsigned *)0, cfile); if (token != COMMA) goto nocomma; concat_another: if (!parse_data_expression (&(*expr) -> data.concat [1], cfile, lose)) goto nodata; token = next_token (&val, (unsigned *)0, cfile); if (token == COMMA) { nexp = (struct expression *)0; if (!expression_allocate (&nexp, MDL)) log_fatal ("can't allocate at CONCAT2"); nexp -> op = expr_concat; expression_reference (&nexp -> data.concat [0], *expr, MDL); expression_dereference (expr, MDL); expression_reference (expr, nexp, MDL); expression_dereference (&nexp, MDL); goto concat_another; } if (token != RPAREN) goto norparen; break; case BINARY_TO_ASCII: token = next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_binary_to_ascii; token = next_token (&val, (unsigned *)0, cfile); if (token != LPAREN) goto nolparen; if (!parse_numeric_expression (&(*expr) -> data.b2a.base, cfile, lose)) goto nodata; token = next_token (&val, (unsigned *)0, cfile); if (token != COMMA) goto nocomma; if (!parse_numeric_expression (&(*expr) -> data.b2a.width, cfile, lose)) goto nodata; token = next_token (&val, (unsigned *)0, cfile); if (token != COMMA) goto nocomma; if (!parse_data_expression (&(*expr) -> data.b2a.seperator, cfile, lose)) goto nodata; token = next_token (&val, (unsigned *)0, cfile); if (token != COMMA) goto nocomma; if (!parse_data_expression (&(*expr) -> data.b2a.buffer, cfile, lose)) goto nodata; token = next_token (&val, (unsigned *)0, cfile); if (token != RPAREN) goto norparen; break; case REVERSE: token = next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_reverse; token = next_token (&val, (unsigned *)0, cfile); if (token != LPAREN) goto nolparen; if (!(parse_numeric_expression (&(*expr) -> data.reverse.width, cfile, lose))) goto nodata; token = next_token (&val, (unsigned *)0, cfile); if (token != COMMA) goto nocomma; if (!(parse_data_expression (&(*expr) -> data.reverse.buffer, cfile, lose))) goto nodata; token = next_token (&val, (unsigned *)0, cfile); if (token != RPAREN) goto norparen; break; case PICK: /* pick (a, b, c) actually produces an internal representation that looks like pick (a, pick (b, pick (c, nil))). */ token = next_token (&val, (unsigned *)0, cfile); if (!(expression_allocate (expr, MDL))) log_fatal ("can't allocate expression"); token = next_token (&val, (unsigned *)0, cfile); if (token != LPAREN) goto nolparen; nexp = (struct expression *)0; expression_reference (&nexp, *expr, MDL); do { nexp -> op = expr_pick_first_value; if (!(parse_data_expression (&nexp -> data.pick_first_value.car, cfile, lose))) goto nodata; token = next_token (&val, (unsigned *)0, cfile); if (token == COMMA) { struct expression *foo = (struct expression *)0; if (!expression_allocate (&foo, MDL)) log_fatal ("can't allocate expr"); expression_reference (&nexp -> data.pick_first_value.cdr, foo, MDL); expression_dereference (&nexp, MDL); expression_reference (&nexp, foo, MDL); expression_dereference (&foo, MDL); } } while (token == COMMA); expression_dereference (&nexp, MDL); if (token != RPAREN) goto norparen; break; /* dns-update and dns-delete are present for historical purposes, but are deprecated in favor of ns-update in combination with update, delete, exists and not exists. */ case DNS_UPDATE: case DNS_DELETE: #if !defined (NSUPDATE) parse_warn (cfile, "Please rebuild dhcpd with --with-nsupdate."); #endif token = next_token (&val, (unsigned *)0, cfile); if (token == DNS_UPDATE) opcode = expr_ns_add; else opcode = expr_ns_delete; token = next_token (&val, (unsigned *)0, cfile); if (token != LPAREN) goto nolparen; token = next_token (&val, (unsigned *)0, cfile); if (token != STRING) { parse_warn (cfile, "parse_expression: expecting string."); badnsupdate: skip_to_semi (cfile); *lose = 1; return 0; } if (!strcasecmp (val, "a")) u = T_A; else if (!strcasecmp (val, "ptr")) u = T_PTR; else if (!strcasecmp (val, "mx")) u = T_MX; else if (!strcasecmp (val, "cname")) u = T_CNAME; else if (!strcasecmp (val, "TXT")) u = T_TXT; else { parse_warn (cfile, "unexpected rrtype: %s", val); goto badnsupdate; } s = (opcode == expr_ns_add ? "old-dns-update" : "old-dns-delete"); cptr = dmalloc (strlen (s) + 1, MDL); if (!cptr) log_fatal ("can't allocate name for %s", s); strcpy (cptr, s); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_funcall; (*expr) -> data.funcall.name = cptr; /* Fake up a function call. */ ep = &(*expr) -> data.funcall.arglist; if (!expression_allocate (ep, MDL)) log_fatal ("can't allocate expression"); (*ep) -> op = expr_arg; if (!make_const_int (&(*ep) -> data.arg.val, u)) log_fatal ("can't allocate rrtype value."); token = next_token (&val, (unsigned *)0, cfile); if (token != COMMA) goto nocomma; ep = &((*ep) -> data.arg.next); if (!expression_allocate (ep, MDL)) log_fatal ("can't allocate expression"); (*ep) -> op = expr_arg; if (!(parse_data_expression (&(*ep) -> data.arg.val, cfile, lose))) goto nodata; token = next_token (&val, (unsigned *)0, cfile); if (token != COMMA) goto nocomma; ep = &((*ep) -> data.arg.next); if (!expression_allocate (ep, MDL)) log_fatal ("can't allocate expression"); (*ep) -> op = expr_arg; if (!(parse_data_expression (&(*ep) -> data.arg.val, cfile, lose))) goto nodata; if (opcode == expr_ns_add) { token = next_token (&val, (unsigned *)0, cfile); if (token != COMMA) goto nocomma; ep = &((*ep) -> data.arg.next); if (!expression_allocate (ep, MDL)) log_fatal ("can't allocate expression"); (*ep) -> op = expr_arg; if (!(parse_numeric_expression (&(*ep) -> data.arg.val, cfile, lose))) { parse_warn (cfile, "expecting numeric expression."); goto badnsupdate; } } token = next_token (&val, (unsigned *)0, cfile); if (token != RPAREN) goto norparen; break; case NS_UPDATE: #if !defined (NSUPDATE) parse_warn (cfile, "Please rebuild dhcpd with --with-nsupdate."); #endif token = next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); token = next_token (&val, (unsigned *)0, cfile); if (token != LPAREN) goto nolparen; nexp = *expr; do { nexp -> op = expr_dns_transaction; if (!(parse_dns_expression (&nexp -> data.dns_transaction.car, cfile, lose))) { if (!*lose) parse_warn (cfile, "expecting dns expression."); badnstrans: expression_dereference (expr, MDL); *lose = 1; return 0; } token = next_token (&val, (unsigned *)0, cfile); if (token == COMMA) { if (!(expression_allocate (&nexp -> data.dns_transaction.cdr, MDL))) log_fatal ("can't allocate expression"); nexp = nexp -> data.dns_transaction.cdr; } } while (token == COMMA); if (token != RPAREN) goto norparen; break; /* NOT EXISTS is special cased above... */ not_exists: token = peek_token (&val, (unsigned *)0, cfile); if (token != EXISTS) { parse_warn (cfile, "expecting DNS prerequisite."); *lose = 1; return 0; } opcode = expr_ns_not_exists; goto nsupdatecode; case TOKEN_ADD: opcode = expr_ns_add; goto nsupdatecode; case TOKEN_DELETE: opcode = expr_ns_delete; goto nsupdatecode; ns_exists: opcode = expr_ns_exists; nsupdatecode: token = next_token (&val, (unsigned *)0, cfile); #if !defined (NSUPDATE) parse_warn (cfile, "Please rebuild dhcpd with --with-nsupdate."); #endif if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = opcode; token = next_token (&val, (unsigned *)0, cfile); if (token != LPAREN) goto nolparen; token = next_token (&val, (unsigned *)0, cfile); if (!is_identifier (token) && token != NUMBER) { parse_warn (cfile, "expecting identifier or number."); badnsop: expression_dereference (expr, MDL); skip_to_semi (cfile); *lose = 1; return 0; } if (token == NUMBER) (*expr) -> data.ns_add.rrclass = atoi (val); else if (!strcasecmp (val, "in")) (*expr) -> data.ns_add.rrclass = C_IN; else if (!strcasecmp (val, "chaos")) (*expr) -> data.ns_add.rrclass = C_CHAOS; else if (!strcasecmp (val, "hs")) (*expr) -> data.ns_add.rrclass = C_HS; else { parse_warn (cfile, "unexpected rrclass: %s", val); goto badnsop; } token = next_token (&val, (unsigned *)0, cfile); if (token != COMMA) goto nocomma; token = next_token (&val, (unsigned *)0, cfile); if (!is_identifier (token) && token != NUMBER) { parse_warn (cfile, "expecting identifier or number."); goto badnsop; } if (token == NUMBER) (*expr) -> data.ns_add.rrtype = atoi (val); else if (!strcasecmp (val, "a")) (*expr) -> data.ns_add.rrtype = T_A; else if (!strcasecmp (val, "ptr")) (*expr) -> data.ns_add.rrtype = T_PTR; else if (!strcasecmp (val, "mx")) (*expr) -> data.ns_add.rrtype = T_MX; else if (!strcasecmp (val, "cname")) (*expr) -> data.ns_add.rrtype = T_CNAME; else if (!strcasecmp (val, "TXT")) (*expr) -> data.ns_add.rrtype = T_TXT; else { parse_warn (cfile, "unexpected rrtype: %s", val); goto badnsop; } token = next_token (&val, (unsigned *)0, cfile); if (token != COMMA) goto nocomma; if (!(parse_data_expression (&(*expr) -> data.ns_add.rrname, cfile, lose))) goto nodata; token = next_token (&val, (unsigned *)0, cfile); if (token != COMMA) goto nocomma; if (!(parse_data_expression (&(*expr) -> data.ns_add.rrdata, cfile, lose))) goto nodata; if (opcode == expr_ns_add) { token = next_token (&val, (unsigned *)0, cfile); if (token != COMMA) goto nocomma; if (!(parse_numeric_expression (&(*expr) -> data.ns_add.ttl, cfile, lose))) { if (!*lose) parse_warn (cfile, "expecting numeric expression."); goto badnsupdate; } } token = next_token (&val, (unsigned *)0, cfile); if (token != RPAREN) goto norparen; break; case OPTION: case CONFIG_OPTION: if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = (token == OPTION ? expr_option : expr_config_option); token = next_token (&val, (unsigned *)0, cfile); known = 0; (*expr) -> data.option = parse_option_name (cfile, 0, &known); if (!(*expr) -> data.option) { *lose = 1; expression_dereference (expr, MDL); return 0; } break; case HARDWARE: token = next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_hardware; break; case LEASED_ADDRESS: token = next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_leased_address; break; case CLIENT_STATE: token = next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_client_state; break; case FILENAME: token = next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_filename; break; case SERVER_NAME: token = next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_sname; break; case LEASE_TIME: token = next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_lease_time; break; case TOKEN_NULL: token = next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_null; break; case HOST_DECL_NAME: token = next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_host_decl_name; break; case UPDATED_DNS_RR: token = next_token (&val, (unsigned *)0, cfile); token = next_token (&val, (unsigned *)0, cfile); if (token != LPAREN) goto nolparen; token = next_token (&val, (unsigned *)0, cfile); if (token != STRING) { parse_warn (cfile, "expecting string."); bad_rrtype: *lose = 1; return 0; } if (!strcasecmp (val, "a")) s = "ddns-fwd-name"; else if (!strcasecmp (val, "ptr")) s = "ddns-rev-name"; else { parse_warn (cfile, "invalid DNS rrtype: %s", val); goto bad_rrtype; } token = next_token (&val, (unsigned *)0, cfile); if (token != RPAREN) goto norparen; if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_variable_reference; (*expr) -> data.variable = dmalloc (strlen (s) + 1, MDL); if (!(*expr) -> data.variable) log_fatal ("can't allocate variable name."); strcpy ((*expr) -> data.variable, s); break; case PACKET: token = next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_packet; token = next_token (&val, (unsigned *)0, cfile); if (token != LPAREN) goto nolparen; if (!parse_numeric_expression (&(*expr) -> data.packet.offset, cfile, lose)) goto nonum; token = next_token (&val, (unsigned *)0, cfile); if (token != COMMA) goto nocomma; if (!parse_numeric_expression (&(*expr) -> data.packet.len, cfile, lose)) goto nonum; token = next_token (&val, (unsigned *)0, cfile); if (token != RPAREN) goto norparen; break; case STRING: token = next_token (&val, &len, cfile); if (!make_const_data (expr, (const unsigned char *)val, len, 1, 1, MDL)) log_fatal ("can't make constant string expression."); break; case EXTRACT_INT: token = next_token (&val, (unsigned *)0, cfile); token = next_token (&val, (unsigned *)0, cfile); if (token != LPAREN) { parse_warn (cfile, "left parenthesis expected."); *lose = 1; return 0; } if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); if (!parse_data_expression (&(*expr) -> data.extract_int, cfile, lose)) { if (!*lose) { parse_warn (cfile, "expecting data expression."); skip_to_semi (cfile); *lose = 1; } expression_dereference (expr, MDL); return 0; } token = next_token (&val, (unsigned *)0, cfile); if (token != COMMA) { parse_warn (cfile, "comma expected."); *lose = 1; expression_dereference (expr, MDL); return 0; } token = next_token (&val, (unsigned *)0, cfile); if (token != NUMBER) { parse_warn (cfile, "number expected."); *lose = 1; expression_dereference (expr, MDL); return 0; } switch (atoi (val)) { case 8: (*expr) -> op = expr_extract_int8; break; case 16: (*expr) -> op = expr_extract_int16; break; case 32: (*expr) -> op = expr_extract_int32; break; default: parse_warn (cfile, "unsupported integer size %d", atoi (val)); *lose = 1; skip_to_semi (cfile); expression_dereference (expr, MDL); return 0; } token = next_token (&val, (unsigned *)0, cfile); if (token != RPAREN) { parse_warn (cfile, "right parenthesis expected."); *lose = 1; expression_dereference (expr, MDL); return 0; } break; case ENCODE_INT: token = next_token (&val, (unsigned *)0, cfile); token = next_token (&val, (unsigned *)0, cfile); if (token != LPAREN) { parse_warn (cfile, "left parenthesis expected."); *lose = 1; return 0; } if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); if (!parse_numeric_expression (&(*expr) -> data.encode_int, cfile, lose)) { parse_warn (cfile, "expecting numeric expression."); skip_to_semi (cfile); *lose = 1; expression_dereference (expr, MDL); return 0; } token = next_token (&val, (unsigned *)0, cfile); if (token != COMMA) { parse_warn (cfile, "comma expected."); *lose = 1; expression_dereference (expr, MDL); return 0; } token = next_token (&val, (unsigned *)0, cfile); if (token != NUMBER) { parse_warn (cfile, "number expected."); *lose = 1; expression_dereference (expr, MDL); return 0; } switch (atoi (val)) { case 8: (*expr) -> op = expr_encode_int8; break; case 16: (*expr) -> op = expr_encode_int16; break; case 32: (*expr) -> op = expr_encode_int32; break; default: parse_warn (cfile, "unsupported integer size %d", atoi (val)); *lose = 1; skip_to_semi (cfile); expression_dereference (expr, MDL); return 0; } token = next_token (&val, (unsigned *)0, cfile); if (token != RPAREN) { parse_warn (cfile, "right parenthesis expected."); *lose = 1; expression_dereference (expr, MDL); return 0; } break; case NUMBER: /* If we're in a numeric context, this should just be a number, by itself. */ if (context == context_numeric || context == context_data_or_numeric) { next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_const_int; (*expr) -> data.const_int = atoi (val); break; } case NUMBER_OR_NAME: if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_const_data; if (!parse_cshl (&(*expr) -> data.const_data, cfile)) { expression_dereference (expr, MDL); return 0; } break; case NS_FORMERR: known = FORMERR; goto ns_const; ns_const: token = next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_const_int; (*expr) -> data.const_int = known; break; case NS_NOERROR: known = ISC_R_SUCCESS; goto ns_const; case NS_NOTAUTH: known = ISC_R_NOTAUTH; goto ns_const; case NS_NOTIMP: known = ISC_R_NOTIMPLEMENTED; goto ns_const; case NS_NOTZONE: known = ISC_R_NOTZONE; goto ns_const; case NS_NXDOMAIN: known = ISC_R_NXDOMAIN; goto ns_const; case NS_NXRRSET: known = ISC_R_NXRRSET; goto ns_const; case NS_REFUSED: known = ISC_R_REFUSED; goto ns_const; case NS_SERVFAIL: known = ISC_R_SERVFAIL; goto ns_const; case NS_YXDOMAIN: known = ISC_R_YXDOMAIN; goto ns_const; case NS_YXRRSET: known = ISC_R_YXRRSET; goto ns_const; case BOOTING: known = S_INIT; goto ns_const; case REBOOT: known = S_REBOOTING; goto ns_const; case SELECT: known = S_SELECTING; goto ns_const; case REQUEST: known = S_REQUESTING; goto ns_const; case BOUND: known = S_BOUND; goto ns_const; case RENEW: known = S_RENEWING; goto ns_const; case REBIND: known = S_REBINDING; goto ns_const; case DEFINED: token = next_token (&val, (unsigned *)0, cfile); token = next_token (&val, (unsigned *)0, cfile); if (token != LPAREN) goto nolparen; token = next_token (&val, (unsigned *)0, cfile); if (token != NAME && token != NUMBER_OR_NAME) { parse_warn (cfile, "%s can't be a variable name", val); skip_to_semi (cfile); *lose = 1; return 0; } if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_variable_exists; (*expr) -> data.variable = dmalloc (strlen (val) + 1, MDL); if (!(*expr)->data.variable) log_fatal ("can't allocate variable name"); strcpy ((*expr) -> data.variable, val); token = next_token (&val, (unsigned *)0, cfile); if (token != RPAREN) goto norparen; break; /* Not a valid start to an expression... */ default: if (token != NAME && token != NUMBER_OR_NAME) return 0; token = next_token (&val, (unsigned *)0, cfile); /* Save the name of the variable being referenced. */ cptr = dmalloc (strlen (val) + 1, MDL); if (!cptr) log_fatal ("can't allocate variable name"); strcpy (cptr, val); /* Simple variable reference, as far as we can tell. */ token = peek_token (&val, (unsigned *)0, cfile); if (token != LPAREN) { if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_variable_reference; (*expr) -> data.variable = cptr; break; } token = next_token (&val, (unsigned *)0, cfile); if (!expression_allocate (expr, MDL)) log_fatal ("can't allocate expression"); (*expr) -> op = expr_funcall; (*expr) -> data.funcall.name = cptr; /* Now parse the argument list. */ ep = &(*expr) -> data.funcall.arglist; do { if (!expression_allocate (ep, MDL)) log_fatal ("can't allocate expression"); (*ep) -> op = expr_arg; if (!parse_expression (&(*ep) -> data.arg.val, cfile, lose, context_any, (struct expression **)0, expr_none)) { if (!*lose) { parse_warn (cfile, "expecting expression."); *lose = 1; } skip_to_semi (cfile); expression_dereference (expr, MDL); return 0; } ep = &((*ep) -> data.arg.next); token = next_token (&val, (unsigned *)0, cfile); } while (token == COMMA); if (token != RPAREN) { parse_warn (cfile, "Right parenthesis expected."); skip_to_semi (cfile); *lose = 1; expression_dereference (expr, MDL); return 0; } break; } return 1; } /* Parse an expression. */ int parse_expression (expr, cfile, lose, context, plhs, binop) struct expression **expr; struct parse *cfile; int *lose; enum expression_context context; struct expression **plhs; enum expr_op binop; { enum dhcp_token token; const char *val; struct expression *rhs = (struct expression *)0, *tmp; struct expression *lhs = (struct expression *)0; enum expr_op next_op; enum expression_context lhs_context = context_any, rhs_context = context_any; /* Consume the left hand side we were passed. */ if (plhs) { expression_reference (&lhs, *plhs, MDL); expression_dereference (plhs, MDL); } new_rhs: if (!parse_non_binary (&rhs, cfile, lose, context)) { /* If we already have a left-hand side, then it's not okay for there not to be a right-hand side here, so we need to flag it as an error. */ if (lhs) { if (!*lose) { parse_warn (cfile, "expecting right-hand side."); *lose = 1; skip_to_semi (cfile); } expression_dereference (&lhs, MDL); } return 0; } /* At this point, rhs contains either an entire subexpression, or at least a left-hand-side. If we do not see a binary token as the next token, we're done with the expression. */ token = peek_token (&val, (unsigned *)0, cfile); switch (token) { case BANG: token = next_token (&val, (unsigned *)0, cfile); token = peek_token (&val, (unsigned *)0, cfile); if (token != EQUAL) { parse_warn (cfile, "! in boolean context without ="); *lose = 1; skip_to_semi (cfile); if (lhs) expression_dereference (&lhs, MDL); return 0; } next_op = expr_not_equal; context = expression_context (rhs); break; case EQUAL: next_op = expr_equal; context = expression_context (rhs); break; case AND: next_op = expr_and; context = expression_context (rhs); break; case OR: next_op = expr_or; context = expression_context (rhs); break; case PLUS: next_op = expr_add; context = expression_context (rhs); break; case MINUS: next_op = expr_subtract; context = expression_context (rhs); break; case SLASH: next_op = expr_divide; context = expression_context (rhs); break; case ASTERISK: next_op = expr_multiply; context = expression_context (rhs); break; case PERCENT: next_op = expr_remainder; context = expression_context (rhs); break; case AMPERSAND: next_op = expr_binary_and; context = expression_context (rhs); break; case PIPE: next_op = expr_binary_or; context = expression_context (rhs); break; case CARET: next_op = expr_binary_xor; context = expression_context (rhs); break; default: next_op = expr_none; } /* If we have no lhs yet, we just parsed it. */ if (!lhs) { /* If there was no operator following what we just parsed, then we're done - return it. */ if (next_op == expr_none) { *expr = rhs; return 1; } lhs = rhs; rhs = (struct expression *)0; binop = next_op; next_token (&val, (unsigned *)0, cfile); goto new_rhs; } if (binop != expr_none) { rhs_context = expression_context(rhs); lhs_context = expression_context(lhs); if ((rhs_context != context_any) && (lhs_context != context_any) && (rhs_context != lhs_context)) { parse_warn (cfile, "illegal expression relating different types"); skip_to_semi (cfile); expression_dereference (&rhs, MDL); expression_dereference (&lhs, MDL); *lose = 1; return 0; } switch(binop) { case expr_not_equal: case expr_equal: if ((rhs_context != context_data_or_numeric) && (rhs_context != context_data) && (rhs_context != context_numeric) && (rhs_context != context_any)) { parse_warn (cfile, "expecting data/numeric expression"); skip_to_semi (cfile); expression_dereference (&rhs, MDL); *lose = 1; return 0; } break; case expr_and: case expr_or: if ((rhs_context != context_boolean) && (rhs_context != context_any)) { parse_warn (cfile, "expecting boolean expressions"); skip_to_semi (cfile); expression_dereference (&rhs, MDL); *lose = 1; return 0; } break; case expr_add: case expr_subtract: case expr_divide: case expr_multiply: case expr_remainder: case expr_binary_and: case expr_binary_or: case expr_binary_xor: if ((rhs_context != context_numeric) && (rhs_context != context_any)) { parse_warn (cfile, "expecting numeric expressions"); skip_to_semi (cfile); expression_dereference (&rhs, MDL); *lose = 1; return 0; } break; default: break; } } /* Now, if we didn't find a binary operator, we're done parsing this subexpression, so combine it with the preceding binary operator and return the result. */ if (next_op == expr_none) { if (!expression_allocate (expr, MDL)) log_fatal ("Can't allocate expression!"); (*expr) -> op = binop; /* All the binary operators' data union members are the same, so we'll cheat and use the member for the equals operator. */ (*expr) -> data.equal [0] = lhs; (*expr) -> data.equal [1] = rhs; return 1; } /* Eat the operator token - we now know it was a binary operator... */ token = next_token (&val, (unsigned *)0, cfile); /* If the binary operator we saw previously has a lower precedence than the next operator, then the rhs we just parsed for that operator is actually the lhs of the operator with the higher precedence - to get the real rhs, we need to recurse on the new operator. */ if (binop != expr_none && op_precedence (binop, next_op) < 0) { tmp = rhs; rhs = (struct expression *)0; if (!parse_expression (&rhs, cfile, lose, op_context (next_op), &tmp, next_op)) { if (!*lose) { parse_warn (cfile, "expecting a subexpression"); *lose = 1; } return 0; } next_op = expr_none; } /* Now combine the LHS and the RHS using binop. */ tmp = (struct expression *)0; if (!expression_allocate (&tmp, MDL)) log_fatal ("No memory for equal precedence combination."); /* Store the LHS and RHS. */ tmp -> data.equal [0] = lhs; tmp -> data.equal [1] = rhs; tmp -> op = binop; lhs = tmp; tmp = (struct expression *)0; rhs = (struct expression *)0; /* Recursions don't return until we have parsed the end of the expression, so if we recursed earlier, we can now return what we got. */ if (next_op == expr_none) { *expr = lhs; return 1; } binop = next_op; goto new_rhs; } /* option-statement :== identifier DOT identifier SEMI | identifier SEMI Option syntax is handled specially through format strings, so it would be painful to come up with BNF for it. However, it always starts as above and ends in a SEMI. */ int parse_option_statement (result, cfile, lookups, option, op) struct executable_statement **result; struct parse *cfile; int lookups; struct option *option; enum statement_op op; { const char *val; enum dhcp_token token; const char *fmt = NULL; struct expression *expr = (struct expression *)0; struct expression *tmp; int lose; struct executable_statement *stmt; int ftt = 1; token = peek_token (&val, (unsigned *)0, cfile); if (token == SEMI) { /* Eat the semicolon... */ token = next_token (&val, (unsigned *)0, cfile); goto done; } if (token == EQUAL) { /* Eat the equals sign. */ token = next_token (&val, (unsigned *)0, cfile); /* Parse a data expression and use its value for the data. */ if (!parse_data_expression (&expr, cfile, &lose)) { /* In this context, we must have an executable statement, so if we found something else, it's still an error. */ if (!lose) { parse_warn (cfile, "expecting a data expression."); skip_to_semi (cfile); } return 0; } /* We got a valid expression, so use it. */ goto done; } /* Parse the option data... */ do { /* Set a flag if this is an array of a simple type (i.e., not an array of pairs of IP addresses, or something like that. */ int uniform = option -> format [1] == 'A'; and_again: /* Set fmt to start of format for 'A' and one char back for 'a' */ if ((fmt != NULL) && (fmt != option -> format) && (*fmt == 'a')) fmt -= 1; else fmt = ((fmt == NULL) || (*fmt == 'A')) ? option -> format : fmt; /* 'a' means always uniform */ uniform |= (fmt [1] == 'a'); for ( ; *fmt; fmt++) { if ((*fmt == 'A') || (*fmt == 'a')) break; if (*fmt == 'o') continue; tmp = expr; expr = (struct expression *)0; if (!parse_option_token (&expr, cfile, &fmt, tmp, uniform, lookups)) { if (fmt [1] != 'o') { if (tmp) expression_dereference (&tmp, MDL); return 0; } expr = tmp; tmp = (struct expression *)0; } if (tmp) expression_dereference (&tmp, MDL); } if ((*fmt == 'A') || (*fmt == 'a')) { token = peek_token (&val, (unsigned *)0, cfile); /* Comma means: continue with next element in array */ if (token == COMMA) { token = next_token (&val, (unsigned *)0, cfile); continue; } /* no comma: end of array. 'A' or end of string means: leave the loop */ if ((*fmt == 'A') || (fmt[1] == '\0')) break; /* 'a' means: go on with next char */ if (*fmt == 'a') { fmt++; goto and_again; } } } while ((*fmt == 'A') || (*fmt == 'a')); done: if (!parse_semi (cfile)) return 0; if (!executable_statement_allocate (result, MDL)) log_fatal ("no memory for option statement."); (*result) -> op = op; if (expr && !option_cache (&(*result) -> data.option, (struct data_string *)0, expr, option, MDL)) log_fatal ("no memory for option cache"); if (expr) expression_dereference (&expr, MDL); return 1; } int parse_option_token (rv, cfile, fmt, expr, uniform, lookups) struct expression **rv; struct parse *cfile; const char **fmt; struct expression *expr; int uniform; int lookups; { const char *val; enum dhcp_token token; struct expression *t = (struct expression *)0; unsigned char buf [4]; unsigned len; unsigned char *ob; struct iaddr addr; int num; const char *f, *g; struct enumeration_value *e; switch (**fmt) { case 'U': token = peek_token (&val, (unsigned *)0, cfile); if (!is_identifier (token)) { if ((*fmt) [1] != 'o') { parse_warn (cfile, "expecting identifier."); skip_to_semi (cfile); } return 0; } token = next_token (&val, &len, cfile); if (!make_const_data (&t, (const unsigned char *)val, len, 1, 1, MDL)) log_fatal ("No memory for %s", val); break; case 'E': g = strchr (*fmt, '.'); if (!g) { parse_warn (cfile, "malformed encapsulation format (bug!)"); skip_to_semi (cfile); return 0; } *fmt = g; case 'X': token = peek_token (&val, (unsigned *)0, cfile); if (token == NUMBER_OR_NAME || token == NUMBER) { if (!expression_allocate (&t, MDL)) return 0; if (!parse_cshl (&t -> data.const_data, cfile)) { expression_dereference (&t, MDL); return 0; } t -> op = expr_const_data; } else if (token == STRING) { token = next_token (&val, &len, cfile); if (!make_const_data (&t, (const unsigned char *)val, len, 1, 1, MDL)) log_fatal ("No memory for \"%s\"", val); } else { if ((*fmt) [1] != 'o') { parse_warn (cfile, "expecting string %s.", "or hexadecimal data"); skip_to_semi (cfile); } return 0; } break; case 'd': /* Domain name... */ val = parse_host_name (cfile); if (!val) { parse_warn (cfile, "not a valid domain name."); skip_to_semi (cfile); return 0; } len = strlen (val); goto make_string; case 't': /* Text string... */ token = peek_token (&val, (unsigned *)0, cfile); if (token != STRING && !is_identifier (token)) { if ((*fmt) [1] != 'o') { parse_warn (cfile, "expecting string."); if (token != SEMI) skip_to_semi (cfile); } return 0; } token = next_token (&val, &len, cfile); make_string: if (!make_const_data (&t, (const unsigned char *)val, len, 1, 1, MDL)) log_fatal ("No memory for concatenation"); break; case 'N': f = (*fmt) + 1; g = strchr (*fmt, '.'); if (!g) { parse_warn (cfile, "malformed %s (bug!)", "enumeration format"); foo: skip_to_semi (cfile); return 0; } *fmt = g; token = next_token (&val, (unsigned *)0, cfile); if (!is_identifier (token)) { parse_warn (cfile, "identifier expected"); goto foo; } e = find_enumeration_value (f, (*fmt) - f, val); if (!e) { parse_warn (cfile, "unknown value"); goto foo; } if (!make_const_data (&t, &e -> value, 1, 0, 1, MDL)) return 0; break; case 'I': /* IP address or hostname. */ if (lookups) { if (!parse_ip_addr_or_hostname (&t, cfile, uniform)) return 0; } else { if (!parse_ip_addr (cfile, &addr)) return 0; if (!make_const_data (&t, addr.iabuf, addr.len, 0, 1, MDL)) return 0; } break; case 'T': /* Lease interval. */ token = peek_token (&val, (unsigned *)0, cfile); if (token != INFINITE) goto check_number; token = next_token (&val, (unsigned *)0, cfile); putLong (buf, -1); if (!make_const_data (&t, buf, 4, 0, 1, MDL)) return 0; break; case 'L': /* Unsigned 32-bit integer... */ case 'l': /* Signed 32-bit integer... */ token = peek_token (&val, (unsigned *)0, cfile); check_number: if (token != NUMBER) { need_number: if ((*fmt) [1] != 'o') { parse_warn (cfile, "expecting number."); if (token != SEMI) skip_to_semi (cfile); } return 0; } token = next_token (&val, (unsigned *)0, cfile); convert_num (cfile, buf, val, 0, 32); if (!make_const_data (&t, buf, 4, 0, 1, MDL)) return 0; break; case 's': /* Signed 16-bit integer. */ case 'S': /* Unsigned 16-bit integer. */ token = peek_token (&val, (unsigned *)0, cfile); if (token != NUMBER) goto need_number; token = next_token (&val, (unsigned *)0, cfile); convert_num (cfile, buf, val, 0, 16); if (!make_const_data (&t, buf, 2, 0, 1, MDL)) return 0; break; case 'b': /* Signed 8-bit integer. */ case 'B': /* Unsigned 8-bit integer. */ token = peek_token (&val, (unsigned *)0, cfile); if (token != NUMBER) goto need_number; token = next_token (&val, (unsigned *)0, cfile); convert_num (cfile, buf, val, 0, 8); if (!make_const_data (&t, buf, 1, 0, 1, MDL)) return 0; break; case 'f': /* Boolean flag. */ token = peek_token (&val, (unsigned *)0, cfile); if (!is_identifier (token)) { if ((*fmt) [1] != 'o') parse_warn (cfile, "expecting identifier."); bad_flag: if ((*fmt) [1] != 'o') { if (token != SEMI) skip_to_semi (cfile); } return 0; } if (!strcasecmp (val, "true") || !strcasecmp (val, "on")) buf [0] = 1; else if (!strcasecmp (val, "false") || !strcasecmp (val, "off")) buf [0] = 0; else if (!strcasecmp (val, "ignore")) buf [0] = 2; else { if ((*fmt) [1] != 'o') parse_warn (cfile, "expecting boolean."); goto bad_flag; } token = next_token (&val, (unsigned *)0, cfile); if (!make_const_data (&t, buf, 1, 0, 1, MDL)) return 0; break; default: parse_warn (cfile, "Bad format %c in parse_option_token.", **fmt); skip_to_semi (cfile); return 0; } if (expr) { if (!make_concat (rv, expr, t)) return 0; } else expression_reference (rv, t, MDL); expression_dereference (&t, MDL); return 1; } int parse_option_decl (oc, cfile) struct option_cache **oc; struct parse *cfile; { const char *val; int token; u_int8_t buf [4]; u_int8_t hunkbuf [1024]; unsigned hunkix = 0; const char *fmt, *f; struct option *option; struct iaddr ip_addr; u_int8_t *dp; unsigned len; int nul_term = 0; struct buffer *bp; int known = 0; struct enumeration_value *e; option = parse_option_name (cfile, 0, &known); if (!option) return 0; /* Parse the option data... */ do { /* Set a flag if this is an array of a simple type (i.e., not an array of pairs of IP addresses, or something like that. */ int uniform = option -> format [1] == 'A'; for (fmt = option -> format; *fmt; fmt++) { if (*fmt == 'A') break; switch (*fmt) { case 'E': fmt = strchr (fmt, '.'); if (!fmt) { parse_warn (cfile, "malformed %s (bug!)", "encapsulation format"); skip_to_semi (cfile); return 0; } case 'X': len = parse_X (cfile, &hunkbuf [hunkix], sizeof hunkbuf - hunkix); hunkix += len; break; case 't': /* Text string... */ token = next_token (&val, &len, cfile); if (token != STRING) { parse_warn (cfile, "expecting string."); skip_to_semi (cfile); return 0; } if (hunkix + len + 1 > sizeof hunkbuf) { parse_warn (cfile, "option data buffer %s", "overflow"); skip_to_semi (cfile); return 0; } memcpy (&hunkbuf [hunkix], val, len + 1); nul_term = 1; hunkix += len; break; case 'N': f = fmt; fmt = strchr (fmt, '.'); if (!fmt) { parse_warn (cfile, "malformed %s (bug!)", "enumeration format"); foo: skip_to_semi (cfile); return 0; } token = next_token (&val, (unsigned *)0, cfile); if (!is_identifier (token)) { parse_warn (cfile, "identifier expected"); goto foo; } e = find_enumeration_value (f, fmt - f, val); if (!e) { parse_warn (cfile, "unknown value"); goto foo; } len = 1; dp = &e -> value; goto alloc; case 'I': /* IP address. */ if (!parse_ip_addr (cfile, &ip_addr)) return 0; len = ip_addr.len; dp = ip_addr.iabuf; alloc: if (hunkix + len > sizeof hunkbuf) { parse_warn (cfile, "option data buffer %s", "overflow"); skip_to_semi (cfile); return 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, (unsigned *)0, cfile); if (token != NUMBER) { need_number: parse_warn (cfile, "expecting number."); if (token != SEMI) skip_to_semi (cfile); return 0; } convert_num (cfile, 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, (unsigned *)0, cfile); if (token != NUMBER) goto need_number; convert_num (cfile, 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, (unsigned *)0, cfile); if (token != NUMBER) goto need_number; convert_num (cfile, buf, val, 0, 8); len = 1; dp = buf; goto alloc; case 'f': /* Boolean flag. */ token = next_token (&val, (unsigned *)0, cfile); if (!is_identifier (token)) { parse_warn (cfile, "expecting identifier."); bad_flag: if (token != SEMI) skip_to_semi (cfile); return 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 (cfile, "expecting boolean."); goto bad_flag; } len = 1; dp = buf; goto alloc; default: log_error ("parse_option_param: Bad format %c", *fmt); skip_to_semi (cfile); return 0; } } token = next_token (&val, (unsigned *)0, cfile); } while (*fmt == 'A' && token == COMMA); if (token != SEMI) { parse_warn (cfile, "semicolon expected."); skip_to_semi (cfile); return 0; } bp = (struct buffer *)0; if (!buffer_allocate (&bp, hunkix + nul_term, MDL)) log_fatal ("no memory to store option declaration."); if (!bp -> data) log_fatal ("out of memory allocating option data."); memcpy (bp -> data, hunkbuf, hunkix + nul_term); if (!option_cache_allocate (oc, MDL)) log_fatal ("out of memory allocating option cache."); (*oc) -> data.buffer = bp; (*oc) -> data.data = &bp -> data [0]; (*oc) -> data.terminated = nul_term; (*oc) -> data.len = hunkix; (*oc) -> option = option; return 1; } /* Consider merging parse_cshl into this. */ int parse_X (cfile, buf, max) struct parse *cfile; u_int8_t *buf; unsigned max; { int token; const char *val; unsigned len; u_int8_t *s; token = peek_token (&val, (unsigned *)0, cfile); if (token == NUMBER_OR_NAME || token == NUMBER) { len = 0; do { token = next_token (&val, (unsigned *)0, cfile); if (token != NUMBER && token != NUMBER_OR_NAME) { parse_warn (cfile, "expecting hexadecimal constant."); skip_to_semi (cfile); return 0; } convert_num (cfile, &buf [len], val, 16, 8); if (len++ > max) { parse_warn (cfile, "hexadecimal constant too long."); skip_to_semi (cfile); return 0; } token = peek_token (&val, (unsigned *)0, cfile); if (token == COLON) token = next_token (&val, (unsigned *)0, cfile); } while (token == COLON); val = (char *)buf; } else if (token == STRING) { token = next_token (&val, &len, cfile); if (len + 1 > max) { parse_warn (cfile, "string constant too long."); skip_to_semi (cfile); return 0; } memcpy (buf, val, len + 1); } else { parse_warn (cfile, "expecting string or hexadecimal data"); skip_to_semi (cfile); return 0; } return len; } int parse_warn (struct parse *cfile, const char *fmt, ...) { va_list list; char lexbuf [256]; char mbuf [1024]; char fbuf [1024]; unsigned i, lix; do_percentm (mbuf, fmt); -#ifndef NO_SNPRINTF + /* %Audit% This is log output. %2004.06.17,Safe% + * If we truncate we hope the user can get a hint from the log. + */ snprintf (fbuf, sizeof fbuf, "%s line %d: %s", cfile -> tlname, cfile -> lexline, mbuf); -#else - sprintf (fbuf, "%s line %d: %s", - cfile -> tlname, cfile -> lexline, mbuf); -#endif va_start (list, fmt); vsnprintf (mbuf, sizeof mbuf, fbuf, list); va_end (list); lix = 0; for (i = 0; cfile -> token_line [i] && i < (cfile -> lexchar - 1); i++) { if (lix < (sizeof lexbuf) - 1) lexbuf [lix++] = ' '; if (cfile -> token_line [i] == '\t') { for (lix; lix < (sizeof lexbuf) - 1 && (lix & 7); lix++) lexbuf [lix] = ' '; } } lexbuf [lix] = 0; #ifndef DEBUG syslog (log_priority | LOG_ERR, "%s", mbuf); syslog (log_priority | LOG_ERR, "%s", cfile -> token_line); if (cfile -> lexchar < 81) syslog (log_priority | LOG_ERR, "%s^", lexbuf); #endif if (log_perror) { write (2, mbuf, strlen (mbuf)); write (2, "\n", 1); write (2, cfile -> token_line, strlen (cfile -> token_line)); write (2, "\n", 1); if (cfile -> lexchar < 81) write (2, lexbuf, lix); write (2, "^\n", 2); } cfile -> warnings_occurred = 1; return 0; } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/print.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/print.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/print.c (revision 131136) @@ -1,1409 +1,1405 @@ /* print.c Turn data structures into printable text. */ /* - * Copyright (c) 1995-2003 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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: print.c,v 1.53.2.9 2003/03/31 03:06:56 dhankins Exp $ Copyright (c) 1995-2003 The Internet Software Consortium. All rights reserved.\n"; +"$Id: print.c,v 1.53.2.11 2004/06/17 20:54:39 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" char *quotify_string (const char *s, const char *file, int line) { unsigned len = 0; const char *sp; char *buf, *nsp; for (sp = s; sp && *sp; sp++) { if (*sp == ' ') len++; else if (!isascii (*sp) || !isprint (*sp)) len += 4; else if (*sp == '"' || *sp == '\\') len += 2; else len++; } buf = dmalloc (len + 1, file, line); if (buf) { nsp = buf; for (sp = s; sp && *sp; sp++) { if (*sp == ' ') *nsp++ = ' '; else if (!isascii (*sp) || !isprint (*sp)) { sprintf (nsp, "\\%03o", *(const unsigned char *)sp); nsp += 4; } else if (*sp == '"' || *sp == '\\') { *nsp++ = '\\'; *nsp++ = *sp; } else *nsp++ = *sp; } *nsp++ = 0; } return buf; } char *quotify_buf (const unsigned char *s, unsigned len, const char *file, int line) { unsigned nulen = 0; char *buf, *nsp; int i; for (i = 0; i < len; i++) { if (s [i] == ' ') nulen++; else if (!isascii (s [i]) || !isprint (s [i])) nulen += 4; else if (s [i] == '"' || s [i] == '\\') nulen += 2; else nulen++; } buf = dmalloc (nulen + 1, MDL); if (buf) { nsp = buf; for (i = 0; i < len; i++) { if (s [i] == ' ') *nsp++ = ' '; else if (!isascii (s [i]) || !isprint (s [i])) { sprintf (nsp, "\\%03o", s [i]); nsp += 4; } else if (s [i] == '"' || s [i] == '\\') { *nsp++ = '\\'; *nsp++ = s [i]; } else *nsp++ = s [i]; } *nsp++ = 0; } return buf; } char *print_base64 (const unsigned char *buf, unsigned len, const char *file, int line) { char *s, *b; unsigned bl; int i; unsigned val, extra; static char to64 [] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; bl = ((len * 4 + 2) / 3) + 1; b = dmalloc (bl + 1, file, line); if (!b) return (char *)0; i = 0; s = b; while (i != len) { val = buf [i++]; extra = val & 3; val = val >> 2; *s++ = to64 [val]; if (i == len) { *s++ = to64 [extra << 4]; *s++ = '='; break; } val = (extra << 8) + buf [i++]; extra = val & 15; val = val >> 4; *s++ = to64 [val]; if (i == len) { *s++ = to64 [extra << 2]; *s++ = '='; break; } val = (extra << 8) + buf [i++]; extra = val & 0x3f; val = val >> 6; *s++ = to64 [val]; *s++ = to64 [extra]; } if (!len) *s++ = '='; *s++ = 0; if (s > b + bl + 1) abort (); return b; } char *print_hw_addr (htype, hlen, data) int htype; int hlen; unsigned char *data; { static char habuf [49]; char *s; int i; if (hlen <= 0) habuf [0] = 0; else { s = habuf; for (i = 0; i < hlen; i++) { sprintf (s, "%02x", data [i]); s += strlen (s); *s++ = ':'; } *--s = 0; } return habuf; } void print_lease (lease) struct lease *lease; { struct tm *t; char tbuf [32]; log_debug (" Lease %s", piaddr (lease -> ip_addr)); t = gmtime (&lease -> starts); strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t); log_debug (" start %s", tbuf); t = gmtime (&lease -> ends); strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t); log_debug (" end %s", tbuf); if (lease -> hardware_addr.hlen) log_debug (" hardware addr = %s", print_hw_addr (lease -> hardware_addr.hbuf [0], lease -> hardware_addr.hlen - 1, &lease -> hardware_addr.hbuf [1])); log_debug (" host %s ", lease -> host ? lease -> host -> name : ""); } #if defined (DEBUG_PACKET) void dump_packet_option (struct option_cache *oc, struct packet *packet, struct lease *lease, struct client_state *client, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct universe *u, void *foo) { const char *name, *dot; struct data_string ds; memset (&ds, 0, sizeof ds); if (u != &dhcp_universe) { name = u -> name; dot = "."; } else { name = ""; dot = ""; } if (evaluate_option_cache (&ds, packet, lease, client, in_options, cfg_options, scope, oc, MDL)) { log_debug (" 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); } } void dump_packet (tp) struct packet *tp; { struct dhcp_packet *tdp = tp -> raw; log_debug ("packet length %d", tp -> packet_length); log_debug ("op = %d htype = %d hlen = %d hops = %d", tdp -> op, tdp -> htype, tdp -> hlen, tdp -> hops); log_debug ("xid = %x secs = %ld flags = %x", tdp -> xid, (unsigned long)tdp -> secs, tdp -> flags); log_debug ("ciaddr = %s", inet_ntoa (tdp -> ciaddr)); log_debug ("yiaddr = %s", inet_ntoa (tdp -> yiaddr)); log_debug ("siaddr = %s", inet_ntoa (tdp -> siaddr)); log_debug ("giaddr = %s", inet_ntoa (tdp -> giaddr)); log_debug ("chaddr = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", ((unsigned char *)(tdp -> chaddr)) [0], ((unsigned char *)(tdp -> chaddr)) [1], ((unsigned char *)(tdp -> chaddr)) [2], ((unsigned char *)(tdp -> chaddr)) [3], ((unsigned char *)(tdp -> chaddr)) [4], ((unsigned char *)(tdp -> chaddr)) [5]); log_debug ("filename = %s", tdp -> file); log_debug ("server_name = %s", tdp -> sname); if (tp -> options_valid) { int i; for (i = 0; i < tp -> options -> universe_count; i++) { if (tp -> options -> universes [i]) { option_space_foreach (tp, (struct lease *)0, (struct client_state *)0, (struct option_state *)0, tp -> options, &global_scope, universes [i], 0, dump_packet_option); } } } log_debug ("%s", ""); } #endif void dump_raw (buf, len) const unsigned char *buf; unsigned len; { int i; char lbuf [80]; int lbix = 0; /* 1 2 3 4 5 6 7 01234567890123456789012345678901234567890123456789012345678901234567890123 280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................. */ memset(lbuf, ' ', 79); lbuf [79] = 0; for (i = 0; i < len; i++) { if ((i & 15) == 0) { if (lbix) { lbuf[53]=' '; lbuf[54]=' '; lbuf[55]=' '; lbuf[73]='\0'; log_info (lbuf); } memset(lbuf, ' ', 79); lbuf [79] = 0; sprintf (lbuf, "%03x:", i); lbix = 4; } else if ((i & 7) == 0) lbuf [lbix++] = ' '; if(isprint(buf[i])) { lbuf[56+(i%16)]=buf[i]; } else { lbuf[56+(i%16)]='.'; } sprintf (&lbuf [lbix], " %02x", buf [i]); lbix += 3; lbuf[lbix]=' '; } lbuf[53]=' '; lbuf[54]=' '; lbuf[55]=' '; lbuf[73]='\0'; log_info (lbuf); } void hash_dump (table) struct hash_table *table; { int i; struct hash_bucket *bp; if (!table) return; for (i = 0; i < table -> hash_count; i++) { if (!table -> buckets [i]) continue; log_info ("hash bucket %d:", i); for (bp = table -> buckets [i]; bp; bp = bp -> next) { if (bp -> len) dump_raw (bp -> name, bp -> len); else log_info ("%s", (const char *)bp -> name); } } } #define HBLEN 60 #define DECLARE_HEX_PRINTER(x) \ char *print_hex##x (len, data, limit) \ unsigned len; \ const u_int8_t *data; \ unsigned limit; \ { \ \ static char hex_buf##x [HBLEN + 1]; \ unsigned i; \ \ if (limit > HBLEN) \ limit = HBLEN; \ \ for (i = 0; i < (limit - 2) && i < len; i++) { \ if (!isascii (data [i]) || !isprint (data [i])) { \ for (i = 0; i < limit / 3 && i < len; i++) { \ sprintf (&hex_buf##x [i * 3], \ "%02x:", data [i]); \ } \ hex_buf##x [i * 3 - 1] = 0; \ return hex_buf##x; \ } \ } \ hex_buf##x [0] = '"'; \ i = len; \ if (i > limit - 2) \ i = limit - 2; \ memcpy (&hex_buf##x [1], data, i); \ hex_buf##x [i + 1] = '"'; \ hex_buf##x [i + 2] = 0; \ return hex_buf##x; \ } DECLARE_HEX_PRINTER (_1) DECLARE_HEX_PRINTER (_2) DECLARE_HEX_PRINTER (_3) #define DQLEN 80 char *print_dotted_quads (len, data) unsigned len; const u_int8_t *data; { static char dq_buf [DQLEN + 1]; int i; char *s, *last; s = &dq_buf [0]; last = s; i = 0; + /* %Audit% Loop bounds checks to 21 bytes. %2004.06.17,Safe% + * The sprintf can't exceed 18 bytes, and since the loop enforces + * 21 bytes of space per iteration at no time can we exit the + * loop without at least 3 bytes spare. + */ do { - sprintf (s, "%d.%d.%d.%d, ", + sprintf (s, "%u.%u.%u.%u, ", data [i], data [i + 1], data [i + 2], data [i + 3]); s += strlen (s); i += 4; } while ((s - &dq_buf [0] > DQLEN - 21) && i + 3 < len); if (i == len) s [-2] = 0; else strcpy (s, "..."); return dq_buf; } char *print_dec_1 (val) unsigned long val; { static char vbuf [32]; sprintf (vbuf, "%lu", val); return vbuf; } char *print_dec_2 (val) unsigned long val; { static char vbuf [32]; sprintf (vbuf, "%lu", val); return vbuf; } static unsigned print_subexpression PROTO ((struct expression *, char *, unsigned)); static unsigned print_subexpression (expr, buf, len) struct expression *expr; char *buf; unsigned len; { unsigned rv, left; const char *s; switch (expr -> op) { case expr_none: if (len > 3) { strcpy (buf, "nil"); return 3; } break; case expr_match: if (len > 7) { strcpy (buf, "(match)"); return 7; } break; case expr_check: rv = 10 + strlen (expr -> data.check -> name); if (len > rv) { sprintf (buf, "(check %s)", expr -> data.check -> name); return rv; } break; case expr_equal: if (len > 6) { rv = 4; strcpy (buf, "(eq "); rv += print_subexpression (expr -> data.equal [0], buf + rv, len - rv - 2); buf [rv++] = ' '; rv += print_subexpression (expr -> data.equal [1], buf + rv, len - rv - 1); buf [rv++] = ')'; buf [rv] = 0; return rv; } break; case expr_not_equal: if (len > 7) { rv = 5; strcpy (buf, "(neq "); rv += print_subexpression (expr -> data.equal [0], buf + rv, len - rv - 2); buf [rv++] = ' '; rv += print_subexpression (expr -> data.equal [1], buf + rv, len - rv - 1); buf [rv++] = ')'; buf [rv] = 0; return rv; } break; case expr_substring: if (len > 11) { rv = 8; strcpy (buf, "(substr "); rv += print_subexpression (expr -> data.substring.expr, buf + rv, len - rv - 3); buf [rv++] = ' '; rv += print_subexpression (expr -> data.substring.offset, buf + rv, len - rv - 2); buf [rv++] = ' '; rv += print_subexpression (expr -> data.substring.len, buf + rv, len - rv - 1); buf [rv++] = ')'; buf [rv] = 0; return rv; } break; case expr_suffix: if (len > 10) { rv = 8; strcpy (buf, "(suffix "); rv += print_subexpression (expr -> data.suffix.expr, buf + rv, len - rv - 2); if (len > rv) buf [rv++] = ' '; rv += print_subexpression (expr -> data.suffix.len, buf + rv, len - rv - 1); if (len > rv) buf [rv++] = ')'; buf [rv] = 0; return rv; } break; case expr_concat: if (len > 10) { rv = 8; strcpy (buf, "(concat "); rv += print_subexpression (expr -> data.concat [0], buf + rv, len - rv - 2); buf [rv++] = ' '; rv += print_subexpression (expr -> data.concat [1], buf + rv, len - rv - 1); buf [rv++] = ')'; buf [rv] = 0; return rv; } break; case expr_pick_first_value: if (len > 8) { rv = 6; strcpy (buf, "(pick1st "); rv += print_subexpression (expr -> data.pick_first_value.car, buf + rv, len - rv - 2); buf [rv++] = ' '; rv += print_subexpression (expr -> data.pick_first_value.cdr, buf + rv, len - rv - 1); buf [rv++] = ')'; buf [rv] = 0; return rv; } break; case expr_host_lookup: rv = 15 + strlen (expr -> data.host_lookup -> hostname); if (len > rv) { sprintf (buf, "(dns-lookup %s)", expr -> data.host_lookup -> hostname); return rv; } break; case expr_and: s = "and"; binop: rv = strlen (s); if (len > rv + 4) { buf [0] = '('; strcpy (&buf [1], s); rv += 1; buf [rv++] = ' '; rv += print_subexpression (expr -> data.and [0], buf + rv, len - rv - 2); buf [rv++] = ' '; rv += print_subexpression (expr -> data.and [1], buf + rv, len - rv - 1); buf [rv++] = ')'; buf [rv] = 0; return rv; } break; case expr_or: s = "or"; goto binop; case expr_add: s = "+"; goto binop; case expr_subtract: s = "-"; goto binop; case expr_multiply: s = "*"; goto binop; case expr_divide: s = "/"; goto binop; case expr_remainder: s = "%"; goto binop; case expr_binary_and: s = "&"; goto binop; case expr_binary_or: s = "|"; goto binop; case expr_binary_xor: s = "^"; goto binop; case expr_not: if (len > 6) { rv = 5; strcpy (buf, "(not "); rv += print_subexpression (expr -> data.not, buf + rv, len - rv - 1); buf [rv++] = ')'; buf [rv] = 0; return rv; } break; case expr_config_option: s = "cfg-option"; goto dooption; case expr_option: s = "option"; dooption: rv = strlen (s) + 2 + (strlen (expr -> data.option -> name) + strlen (expr -> data.option -> universe -> name)); if (len > rv) { sprintf (buf, "(option %s.%s)", expr -> data.option -> universe -> name, expr -> data.option -> name); return rv; } break; case expr_hardware: if (len > 10) { strcpy (buf, "(hardware)"); return 10; } break; case expr_packet: if (len > 10) { rv = 8; strcpy (buf, "(substr "); rv += print_subexpression (expr -> data.packet.offset, buf + rv, len - rv - 2); buf [rv++] = ' '; rv += print_subexpression (expr -> data.packet.len, buf + rv, len - rv - 1); buf [rv++] = ')'; buf [rv] = 0; return rv; } break; case expr_const_data: s = print_hex_1 (expr -> data.const_data.len, expr -> data.const_data.data, len); rv = strlen (s); if (rv >= len) rv = len - 1; strncpy (buf, s, rv); buf [rv] = 0; return rv; case expr_encapsulate: rv = 13; strcpy (buf, "(encapsulate "); rv += expr -> data.encapsulate.len; if (rv + 2 > len) rv = len - 2; strncpy (buf, (const char *)expr -> data.encapsulate.data, rv - 13); buf [rv++] = ')'; buf [rv++] = 0; break; case expr_extract_int8: if (len > 7) { rv = 6; strcpy (buf, "(int8 "); rv += print_subexpression (expr -> data.extract_int, buf + rv, len - rv - 1); buf [rv++] = ')'; buf [rv] = 0; return rv; } break; case expr_extract_int16: if (len > 8) { rv = 7; strcpy (buf, "(int16 "); rv += print_subexpression (expr -> data.extract_int, buf + rv, len - rv - 1); buf [rv++] = ')'; buf [rv] = 0; return rv; } break; case expr_extract_int32: if (len > 8) { rv = 7; strcpy (buf, "(int32 "); rv += print_subexpression (expr -> data.extract_int, buf + rv, len - rv - 1); buf [rv++] = ')'; buf [rv] = 0; return rv; } break; case expr_encode_int8: if (len > 7) { rv = 6; strcpy (buf, "(to-int8 "); rv += print_subexpression (expr -> data.encode_int, buf + rv, len - rv - 1); buf [rv++] = ')'; buf [rv] = 0; return rv; } break; case expr_encode_int16: if (len > 8) { rv = 7; strcpy (buf, "(to-int16 "); rv += print_subexpression (expr -> data.encode_int, buf + rv, len - rv - 1); buf [rv++] = ')'; buf [rv] = 0; return rv; } break; case expr_encode_int32: if (len > 8) { rv = 7; strcpy (buf, "(to-int32 "); rv += print_subexpression (expr -> data.encode_int, buf + rv, len - rv - 1); buf [rv++] = ')'; buf [rv] = 0; return rv; } break; case expr_const_int: s = print_dec_1 (expr -> data.const_int); rv = strlen (s); if (len > rv) { strcpy (buf, s); return rv; } break; case expr_exists: rv = 10 + (strlen (expr -> data.option -> name) + strlen (expr -> data.option -> universe -> name)); if (len > rv) { sprintf (buf, "(exists %s.%s)", expr -> data.option -> universe -> name, expr -> data.option -> name); return rv; } break; case expr_variable_exists: rv = 10 + strlen (expr -> data.variable); if (len > rv) { sprintf (buf, "(defined %s)", expr -> data.variable); return rv; } break; case expr_variable_reference: rv = strlen (expr -> data.variable); if (len > rv) { sprintf (buf, "%s", expr -> data.variable); return rv; } break; case expr_known: s = "known"; astring: rv = strlen (s); if (len > rv) { strcpy (buf, s); return rv; } break; case expr_leased_address: s = "leased-address"; goto astring; case expr_client_state: s = "client-state"; goto astring; case expr_host_decl_name: s = "host-decl-name"; goto astring; case expr_lease_time: s = "lease-time"; goto astring; case expr_static: s = "static"; goto astring; case expr_filename: s = "filename"; goto astring; case expr_sname: s = "server-name"; goto astring; case expr_reverse: if (len > 11) { rv = 13; strcpy (buf, "(reverse "); rv += print_subexpression (expr -> data.reverse.width, buf + rv, len - rv - 2); buf [rv++] = ' '; rv += print_subexpression (expr -> data.reverse.buffer, buf + rv, len - rv - 1); buf [rv++] = ')'; buf [rv] = 0; return rv; } break; case expr_binary_to_ascii: if (len > 5) { rv = 9; strcpy (buf, "(b2a "); rv += print_subexpression (expr -> data.b2a.base, buf + rv, len - rv - 4); buf [rv++] = ' '; rv += print_subexpression (expr -> data.b2a.width, buf + rv, len - rv - 3); buf [rv++] = ' '; rv += print_subexpression (expr -> data.b2a.seperator, buf + rv, len - rv - 2); buf [rv++] = ' '; rv += print_subexpression (expr -> data.b2a.buffer, buf + rv, len - rv - 1); buf [rv++] = ')'; buf [rv] = 0; return rv; } break; case expr_dns_transaction: rv = 10; if (len < rv + 2) { buf [0] = '('; strcpy (&buf [1], "ns-update "); while (len < rv + 2) { rv += print_subexpression (expr -> data.dns_transaction.car, buf + rv, len - rv - 2); buf [rv++] = ' '; expr = expr -> data.dns_transaction.cdr; } buf [rv - 1] = ')'; buf [rv] = 0; return rv; } return 0; case expr_ns_delete: s = "delete"; left = 4; goto dodnsupd; case expr_ns_exists: s = "exists"; left = 4; goto dodnsupd; case expr_ns_not_exists: s = "not_exists"; left = 4; goto dodnsupd; case expr_ns_add: s = "update"; left = 5; dodnsupd: rv = strlen (s); if (len > strlen (s) + 1) { buf [0] = '('; strcpy (buf + 1, s); rv++; buf [rv++] = ' '; s = print_dec_1 (expr -> data.ns_add.rrclass); if (len > rv + strlen (s) + left) { strcpy (&buf [rv], s); rv += strlen (&buf [rv]); } buf [rv++] = ' '; left--; s = print_dec_1 (expr -> data.ns_add.rrtype); if (len > rv + strlen (s) + left) { strcpy (&buf [rv], s); rv += strlen (&buf [rv]); } buf [rv++] = ' '; left--; rv += print_subexpression (expr -> data.ns_add.rrname, buf + rv, len - rv - left); buf [rv++] = ' '; left--; rv += print_subexpression (expr -> data.ns_add.rrdata, buf + rv, len - rv - left); buf [rv++] = ' '; left--; rv += print_subexpression (expr -> data.ns_add.ttl, buf + rv, len - rv - left); buf [rv++] = ')'; buf [rv] = 0; return rv; } break; case expr_null: if (len > 6) { strcpy (buf, "(null)"); return 6; } break; case expr_funcall: rv = 12 + strlen (expr -> data.funcall.name); if (len > rv + 1) { strcpy (buf, "(funcall "); strcpy (buf + 9, expr -> data.funcall.name); buf [rv++] = ' '; rv += print_subexpression (expr -> data.funcall.arglist, buf + rv, len - rv - 1); buf [rv++] = ')'; buf [rv] = 0; return rv; } break; case expr_arg: rv = print_subexpression (expr -> data.arg.val, buf, len); if (expr -> data.arg.next && rv + 2 < len) { buf [rv++] = ' '; rv += print_subexpression (expr -> data.arg.next, buf, len); if (rv + 1 < len) buf [rv++] = 0; return rv; } break; case expr_function: rv = 9; if (len > rv + 1) { struct string_list *foo; strcpy (buf, "(function"); for (foo = expr -> data.func -> args; foo; foo = foo -> next) { if (len > rv + 2 + strlen (foo -> string)) { buf [rv - 1] = ' '; strcpy (&buf [rv], foo -> string); rv += strlen (foo -> string); } } buf [rv] = ')'; buf [rv++] = 0; return rv; } } return 0; } void print_expression (name, expr) const char *name; struct expression *expr; { char buf [1024]; print_subexpression (expr, buf, sizeof buf); log_info ("%s: %s", name, buf); } int token_print_indent_concat (FILE *file, int col, int indent, const char *prefix, const char *suffix, ...) { va_list list; char *buf; unsigned len; char *s, *t, *u; va_start (list, suffix); s = va_arg (list, char *); len = 0; while (s) { len += strlen (s); s = va_arg (list, char *); } va_end (list); t = dmalloc (len + 1, MDL); if (!t) log_fatal ("token_print_indent: no memory for copy buffer"); va_start (list, suffix); s = va_arg (list, char *); u = t; while (s) { len = strlen (s); strcpy (u, s); u += len; } va_end (list); len = token_print_indent (file, col, indent, prefix, suffix, t); dfree (t, MDL); return col; } int token_indent_data_string (FILE *file, int col, int indent, const char *prefix, const char *suffix, struct data_string *data) { int i; char *buf; char obuf [3]; /* See if this is just ASCII. */ for (i = 0; i < data -> len; i++) if (!isascii (data -> data [i]) || !isprint (data -> data [i])) break; /* If we have a purely ASCII string, output it as text. */ if (i == data -> len) { char *buf = dmalloc (data -> len + 3, MDL); if (buf) { buf [0] = '"'; memcpy (buf + 1, data -> data, data -> len); buf [data -> len + 1] = '"'; buf [data -> len + 2] = 0; i = token_print_indent (file, col, indent, prefix, suffix, buf); dfree (buf, MDL); return i; } } for (i = 0; i < data -> len; i++) { sprintf (obuf, "%2.2x", data -> data [i]); col = token_print_indent (file, col, indent, i == 0 ? prefix : "", (i + 1 == data -> len ? suffix : ""), obuf); if (i + 1 != data -> len) col = token_print_indent (file, col, indent, prefix, suffix, ":"); } return col; } int token_print_indent (FILE *file, int col, int indent, const char *prefix, const char *suffix, const char *buf) { int len = strlen (buf) + strlen (prefix); if (col + len > 79) { if (indent + len < 79) { indent_spaces (file, indent); col = indent; } else { indent_spaces (file, col); col = len > 79 ? 0 : 79 - len - 1; } } else if (prefix && *prefix) { fputs (prefix, file); col += strlen (prefix); } fputs (buf, file); col += len; if (suffix && *suffix) { if (col + strlen (suffix) > 79) { indent_spaces (file, indent); col = indent; } else { fputs (suffix, file); col += strlen (suffix); } } return col; } void indent_spaces (FILE *file, int indent) { int i; fputc ('\n', file); for (i = 0; i < indent; i++) fputc (' ', file); } #if defined (NSUPDATE) void print_dns_status (int status, ns_updque *uq) { char obuf [1024]; char *s = &obuf [0], *end = &obuf [1022]; ns_updrec *u; int position; int ttlp; const char *predicate = "if", *en, *op; int errorp; for (u = ISC_LIST_HEAD (*uq); u; u = ISC_LIST_NEXT (u, r_link)) { ttlp = 0; switch (u -> r_opcode) { case NXRRSET: op = "rrset doesn't exist"; position = 1; break; case YXRRSET: op = "rrset exists"; position = 1; break; case NXDOMAIN: op = "domain doesn't exist"; position = 1; break; case YXDOMAIN: op = "domain exists"; position = 1; break; case ADD: op = "add"; position = 0; ttlp = 1; break; case DELETE: op = "delete"; position = 0; break; default: op = "unknown"; position = 0; break; } if (!position) { if (s != &obuf [0] && s + 1 < end) *s++ = ' '; if (s + strlen (op) < end) { strcpy (s, op); s += strlen (s); } } else { if (s != &obuf [0] && s + 1 < end) *s++ = ' '; if (s + strlen (predicate) < end) { strcpy (s, predicate); s += strlen (s); } predicate = "and"; } if (u -> r_dname) { if (s + 1 < end) *s++ = ' '; if (s + strlen (u -> r_dname) < end) { strcpy (s, u -> r_dname); s += strlen (s); } } if (ttlp) { if (s + 1 < end) *s++ = ' '; /* 27 is as big as a ttl can get. */ if (s + 27 < end) { sprintf (s, "%lu", (unsigned long)(u -> r_ttl)); s += strlen (s); } } switch (u -> r_class) { case C_IN: en = "IN"; break; case C_CHAOS: en = "CHAOS"; break; case C_HS: en = "HS"; break; default: en = "UNKNOWN"; break; } if (s + strlen (en) < end) { if (s + 1 < end) *s++ = ' '; strcpy (s, en); s += strlen (en); } switch (u -> r_type) { case T_A: en = "A"; break; case T_PTR: en = "PTR"; break; case T_MX: en = "MX"; break; case T_TXT: en = "TXT"; break; case T_KEY: en = "KEY"; break; case T_CNAME: en = "CNAME"; break; default: en = "UNKNOWN"; break; } if (s + strlen (en) < end) { if (s + 1 < end) *s++ = ' '; strcpy (s, en); s += strlen (en); } if (u -> r_data) { if (s + 1 < end) *s++ = ' '; if (u -> r_type == T_TXT) { if (s + 1 < end) *s++ = '"'; } if(u->r_type == T_KEY) { strcat(s, ""); s+=strlen(""); } else { if (s + u -> r_size < end) { memcpy (s, u -> r_data, u -> r_size); s += u -> r_size; if (u -> r_type == T_TXT) { if (s + 1 < end) *s++ = '"'; } } } } if (position) { if (s + 1 < end) *s++ = ' '; if (s + strlen (op) < end) { strcpy (s, op); s += strlen (s); } } if (u == ISC_LIST_TAIL (*uq)) break; } if (s == &obuf [0]) { strcpy (s, "empty update"); s += strlen (s); } if (status == NOERROR) errorp = 0; else errorp = 1; en = isc_result_totext (status); #if 0 switch (status) { case -1: en = "resolver failed"; break; case FORMERR: en = "format error"; break; case NOERROR: en = "succeeded"; errorp = 0; break; case NOTAUTH: en = "not authorized"; break; case NOTIMP: en = "not implemented"; break; case NOTZONE: en = "not a single valid zone"; break; case NXDOMAIN: en = "no such domain"; break; case NXRRSET: en = "no such record"; break; case REFUSED: en = "refused"; break; case SERVFAIL: en = "server failed"; break; case YXDOMAIN: en = "domain exists"; break; case YXRRSET: en = "record exists"; break; default: en = "unknown error"; break; } #endif if (s + 2 < end) { *s++ = ':'; *s++ = ' '; } if (s + strlen (en) < end) { strcpy (s, en); s += strlen (en); } if (s + 1 < end) *s++ = '.'; *s++ = 0; if (errorp) log_error ("%s", obuf); else log_info ("%s", obuf); } #endif /* NSUPDATE */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/raw.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/raw.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/raw.c (revision 131136) @@ -1,153 +1,144 @@ /* socket.c BSD raw socket interface code... */ /* XXX It's not clear how this should work, and that lack of clarity is terribly detrimental to the NetBSD 1.1 kernel - it crashes and burns. Using raw sockets ought to be a big win over using BPF or something like it, because you don't need to deal with the complexities of the physical layer, but it appears not to be possible with existing raw socket implementations. This may be worth revisiting in the future. For now, this code can probably be considered a curiosity. Sigh. */ /* - * Copyright (c) 1995-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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: raw.c,v 1.17.2.1 2002/11/17 02:26:59 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: raw.c,v 1.17.2.2 2004/06/10 17:59:20 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #if defined (USE_RAW_SEND) #include /* Generic interface registration routine... */ void if_register_send (info) struct interface_info *info; { struct sockaddr_in name; int sock; struct socklist *tmp; int flag; /* Set up the address we're going to connect to. */ name.sin_family = AF_INET; name.sin_port = local_port; name.sin_addr.s_addr = htonl (INADDR_BROADCAST); memset (name.sin_zero, 0, sizeof (name.sin_zero)); /* List addresses on which we're listening. */ if (!quiet_interface_discovery) log_info ("Sending on %s, port %d", piaddr (info -> address), htons (local_port)); if ((sock = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) log_fatal ("Can't create dhcp socket: %m"); /* Set the BROADCAST option so that we can broadcast DHCP responses. */ flag = 1; if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST, &flag, sizeof flag) < 0) log_fatal ("Can't set SO_BROADCAST option on dhcp socket: %m"); /* Set the IP_HDRINCL flag so that we can supply our own IP headers... */ if (setsockopt (sock, IPPROTO_IP, IP_HDRINCL, &flag, sizeof flag) < 0) log_fatal ("Can't set IP_HDRINCL flag: %m"); info -> wfdesc = sock; if (!quiet_interface_discovery) log_info ("Sending on Raw/%s%s%s", info -> name, (info -> shared_network ? "/" : ""), (info -> shared_network ? info -> shared_network -> name : "")); } void if_deregister_send (info) struct interface_info *info; { close (info -> wfdesc); info -> wfdesc = -1; if (!quiet_interface_discovery) log_info ("Disabling output on Raw/%s%s%s", info -> name, (info -> shared_network ? "/" : ""), (info -> shared_network ? info -> shared_network -> name : "")); } size_t send_packet (interface, packet, raw, len, from, to, hto) 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; { unsigned char buf [256]; int bufp = 0; struct iovec iov [2]; int result; /* Assemble the headers... */ assemble_udp_ip_header (interface, buf, &bufp, 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); if (result < 0) log_error ("send_packet: %m"); return result; } #endif /* USE_SOCKET_SEND */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/resolv.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/resolv.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/resolv.c (revision 131136) @@ -1,212 +1,203 @@ /* resolv.c Parser for /etc/resolv.conf file. */ /* - * Copyright (c) 1996-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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: resolv.c,v 1.16.2.1 2002/11/17 02:26:59 dhankins Exp $ Copyright (c) 1996-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: resolv.c,v 1.16.2.2 2004/06/10 17:59:20 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" struct name_server *name_servers; struct domain_search_list *domains; char path_resolv_conf [] = _PATH_RESOLV_CONF; void read_resolv_conf (parse_time) TIME parse_time; { int file; struct parse *cfile; const char *val; int token; int declaration = 0; struct name_server *sp, *sl, *ns; struct domain_search_list *dp, *dl, *nd; struct iaddr *iaddr; if ((file = open (path_resolv_conf, O_RDONLY)) < 0) { log_error ("Can't open %s: %m", path_resolv_conf); return; } cfile = (struct parse *)0; new_parse (&cfile, file, (char *)0, 0, path_resolv_conf, 1); do { token = next_token (&val, (unsigned *)0, cfile); if (token == END_OF_FILE) break; else if (token == EOL) continue; else if (token == DOMAIN || token == SEARCH) { do { struct domain_search_list *nd, **dp; char *dn; dn = parse_host_name (cfile); if (!dn) break; dp = &domains; for (nd = domains; nd; nd = nd -> next) { dp = &nd -> next; if (!strcmp (nd -> domain, dn)) break; } if (!nd) { nd = new_domain_search_list (MDL); if (!nd) log_fatal ("No memory for %s", dn); nd -> next = (struct domain_search_list *)0; *dp = nd; nd -> domain = dn; dn = (char *)0; } nd -> rcdate = parse_time; token = peek_token (&val, (unsigned *)0, cfile); } while (token != EOL); if (token != EOL) { parse_warn (cfile, "junk after domain declaration"); skip_to_semi (cfile); } token = next_token (&val, (unsigned *)0, cfile); } else if (token == NAMESERVER) { struct name_server *ns, **sp; struct iaddr iaddr; parse_ip_addr (cfile, &iaddr); sp = &name_servers; for (ns = name_servers; ns; ns = ns -> next) { sp = &ns -> next; if (!memcmp (&ns -> addr.sin_addr, iaddr.iabuf, iaddr.len)) break; } if (!ns) { ns = new_name_server (MDL); if (!ns) log_fatal ("No memory for nameserver %s", piaddr (iaddr)); ns -> next = (struct name_server *)0; *sp = ns; memcpy (&ns -> addr.sin_addr, iaddr.iabuf, iaddr.len); #ifdef HAVE_SA_LEN ns -> addr.sin_len = sizeof ns -> addr; #endif ns -> addr.sin_family = AF_INET; ns -> addr.sin_port = htons (53); memset (ns -> addr.sin_zero, 0, sizeof ns -> addr.sin_zero); } ns -> rcdate = parse_time; skip_to_semi (cfile); } else skip_to_semi (cfile); /* Ignore what we don't grok. */ } while (1); token = next_token (&val, (unsigned *)0, cfile); /* Lose servers that are no longer in /etc/resolv.conf. */ sl = (struct name_server *)0; for (sp = name_servers; sp; sp = ns) { ns = sp -> next; if (sp -> rcdate != parse_time) { if (sl) sl -> next = sp -> next; else name_servers = sp -> next; /* We can't actually free the name server structure, because somebody might be hanging on to it. If your /etc/resolv.conf file changes a lot, this could be a noticable memory leak. */ } else sl = sp; } /* Lose domains that are no longer in /etc/resolv.conf. */ dl = (struct domain_search_list *)0; for (dp = domains; dp; dp = nd) { nd = dp -> next; if (dp -> rcdate != parse_time) { if (dl) dl -> next = dp -> next; else domains = dp -> next; free_domain_search_list (dp, MDL); } else dl = dp; } close (file); end_parse (&cfile); } /* Pick a name server from the /etc/resolv.conf file. */ struct name_server *first_name_server () { FILE *rc; static TIME rcdate; struct stat st; /* Check /etc/resolv.conf and reload it if it's changed. */ if (cur_time > rcdate) { if (stat (path_resolv_conf, &st) < 0) { log_error ("Can't stat %s", path_resolv_conf); return (struct name_server *)0; } if (st.st_mtime > rcdate) { char rcbuf [512]; char *s, *t, *u; rcdate = cur_time + 1; read_resolv_conf (rcdate); } } return name_servers; } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/socket.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/socket.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/socket.c (revision 131136) @@ -1,380 +1,371 @@ /* socket.c BSD socket interface code... */ /* - * Copyright (c) 1995-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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''. */ /* SO_BINDTODEVICE support added by Elliot Poger (poger@leland.stanford.edu). * This sockopt allows a socket to be bound to a particular interface, * thus enabling the use of DHCPD on a multihomed host. * If SO_BINDTODEVICE is defined in your system header files, the use of * this sockopt will be automatically enabled. * I have implemented it under Linux; other systems should be doable also. */ #ifndef lint static char copyright[] = -"$Id: socket.c,v 1.55.2.3 2002/11/17 02:26:59 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: socket.c,v 1.55.2.4 2004/06/10 17:59:21 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #ifdef USE_SOCKET_FALLBACK # if !defined (USE_SOCKET_SEND) # define if_register_send if_register_fallback # define send_packet send_fallback # define if_reinitialize_send if_reinitialize_fallback # endif #endif static int once = 0; /* Reinitializes the specified interface after an address change. This is not required for packet-filter APIs. */ #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK) void if_reinitialize_send (info) struct interface_info *info; { #if 0 #ifndef USE_SOCKET_RECEIVE once = 0; close (info -> wfdesc); #endif if_register_send (info); #endif } #endif #ifdef USE_SOCKET_RECEIVE void if_reinitialize_receive (info) struct interface_info *info; { #if 0 once = 0; close (info -> rfdesc); if_register_receive (info); #endif } #endif #if defined (USE_SOCKET_SEND) || \ defined (USE_SOCKET_RECEIVE) || \ defined (USE_SOCKET_FALLBACK) /* Generic interface registration routine... */ int if_register_socket (info) struct interface_info *info; { struct sockaddr_in name; int sock; int flag; #if !defined (HAVE_SO_BINDTODEVICE) && !defined (USE_FALLBACK) /* Make sure only one interface is registered. */ if (once) log_fatal ("The standard socket API can only support %s", "hosts with a single network interface."); once = 1; #endif memset (&name, 0, sizeof (name)); /* Set up the address we're going to bind to. */ name.sin_family = AF_INET; name.sin_port = local_port; name.sin_addr = local_address; /* Make a socket... */ if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) log_fatal ("Can't create dhcp socket: %m"); /* Set the REUSEADDR option so that we don't fail to start if we're being restarted. */ flag = 1; if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof flag) < 0) log_fatal ("Can't set SO_REUSEADDR option on dhcp socket: %m"); /* Set the BROADCAST option so that we can broadcast DHCP responses. We shouldn't do this for fallback devices, and we can detect that a device is a fallback because it has no ifp structure. */ if (info -> ifp && (setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *)&flag, sizeof flag) < 0)) log_fatal ("Can't set SO_BROADCAST option on dhcp socket: %m"); /* Bind the socket to this interface's IP address. */ if (bind (sock, (struct sockaddr *)&name, sizeof name) < 0) { log_error ("Can't bind to dhcp address: %m"); log_error ("Please make sure there is no other dhcp server"); log_error ("running and that there's no entry for dhcp or"); log_error ("bootp in /etc/inetd.conf. Also make sure you"); log_error ("are not running HP JetAdmin software, which"); log_fatal ("includes a bootp server."); } #if defined (HAVE_SO_BINDTODEVICE) /* Bind this socket to this interface. */ if (info -> ifp && setsockopt (sock, SOL_SOCKET, SO_BINDTODEVICE, (char *)(info -> ifp), sizeof *(info -> ifp)) < 0) { log_fatal ("setsockopt: SO_BINDTODEVICE: %m"); } #endif return sock; } #endif /* USE_SOCKET_SEND || USE_SOCKET_RECEIVE || USE_SOCKET_FALLBACK */ #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK) void if_register_send (info) struct interface_info *info; { #ifndef USE_SOCKET_RECEIVE info -> wfdesc = if_register_socket (info); #if defined (USE_SOCKET_FALLBACK) /* Fallback only registers for send, but may need to receive as well. */ info -> rfdesc = info -> wfdesc; #endif #else info -> wfdesc = info -> rfdesc; #endif if (!quiet_interface_discovery) log_info ("Sending on Socket/%s%s%s", info -> name, (info -> shared_network ? "/" : ""), (info -> shared_network ? info -> shared_network -> name : "")); } #if defined (USE_SOCKET_SEND) void if_deregister_send (info) struct interface_info *info; { #ifndef USE_SOCKET_RECEIVE close (info -> wfdesc); #endif info -> wfdesc = -1; if (!quiet_interface_discovery) log_info ("Disabling output on Socket/%s%s%s", info -> name, (info -> shared_network ? "/" : ""), (info -> shared_network ? info -> shared_network -> name : "")); } #endif /* USE_SOCKET_SEND */ #endif /* USE_SOCKET_SEND || USE_SOCKET_FALLBACK */ #ifdef USE_SOCKET_RECEIVE void if_register_receive (info) struct interface_info *info; { /* If we're using the socket API for sending and receiving, we don't need to register this interface twice. */ info -> rfdesc = if_register_socket (info); if (!quiet_interface_discovery) log_info ("Listening on Socket/%s%s%s", info -> name, (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 Socket/%s%s%s", info -> name, (info -> shared_network ? "/" : ""), (info -> shared_network ? info -> shared_network -> name : "")); } #endif /* USE_SOCKET_RECEIVE */ #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK) ssize_t send_packet (interface, packet, raw, len, from, to, hto) 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; { int result; #ifdef IGNORE_HOSTUNREACH int retry = 0; do { #endif result = sendto (interface -> wfdesc, (char *)raw, len, 0, (struct sockaddr *)to, sizeof *to); #ifdef IGNORE_HOSTUNREACH } while (to -> sin_addr.s_addr == htonl (INADDR_BROADCAST) && result < 0 && (errno == EHOSTUNREACH || errno == ECONNREFUSED) && retry++ < 10); #endif if (result < 0) { log_error ("send_packet: %m"); if (errno == ENETUNREACH) log_error ("send_packet: please consult README file%s", " regarding broadcast address."); } return result; } #endif /* USE_SOCKET_SEND || USE_SOCKET_FALLBACK */ #ifdef USE_SOCKET_RECEIVE ssize_t receive_packet (interface, buf, len, from, hfrom) struct interface_info *interface; unsigned char *buf; size_t len; struct sockaddr_in *from; struct hardware *hfrom; { SOCKLEN_T flen = sizeof *from; int result; #ifdef IGNORE_HOSTUNREACH int retry = 0; do { #endif result = recvfrom (interface -> rfdesc, (char *)buf, len, 0, (struct sockaddr *)from, &flen); #ifdef IGNORE_HOSTUNREACH } while (result < 0 && (errno == EHOSTUNREACH || errno == ECONNREFUSED) && retry++ < 10); #endif return result; } #endif /* USE_SOCKET_RECEIVE */ #if defined (USE_SOCKET_FALLBACK) /* This just reads in a packet and silently discards it. */ isc_result_t fallback_discard (object) omapi_object_t *object; { char buf [1540]; struct sockaddr_in from; SOCKLEN_T flen = sizeof from; int status; struct interface_info *interface; if (object -> type != dhcp_type_interface) return ISC_R_INVALIDARG; interface = (struct interface_info *)object; status = recvfrom (interface -> wfdesc, buf, sizeof buf, 0, (struct sockaddr *)&from, &flen); #if defined (DEBUG) /* Only report fallback discard errors if we're debugging. */ if (status < 0) { log_error ("fallback_discard: %m"); return ISC_R_UNEXPECTED; } #endif return ISC_R_SUCCESS; } #endif /* USE_SOCKET_FALLBACK */ #if defined (USE_SOCKET_SEND) int can_unicast_without_arp (ip) struct interface_info *ip; { return 0; } int can_receive_unicast_unconfigured (ip) struct interface_info *ip; { #if defined (SOCKET_CAN_RECEIVE_UNICAST_UNCONFIGURED) return 1; #else return 0; #endif } int supports_multiple_interfaces (ip) struct interface_info *ip; { #if defined (SO_BINDTODEVICE) return 1; #else return 0; #endif } /* If we have SO_BINDTODEVICE, set up a fallback interface; otherwise, do not. */ void maybe_setup_fallback () { #if defined (USE_SOCKET_FALLBACK) isc_result_t status; struct interface_info *fbi = (struct interface_info *)0; if (setup_fallback (&fbi, MDL)) { fbi -> wfdesc = if_register_socket (fbi); fbi -> rfdesc = fbi -> wfdesc; log_info ("Sending on Socket/%s%s%s", fbi -> name, (fbi -> shared_network ? "/" : ""), (fbi -> shared_network ? fbi -> shared_network -> name : "")); 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 } #endif /* USE_SOCKET_SEND */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/tables.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/tables.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/tables.c (revision 131136) @@ -1,1249 +1,1240 @@ /* tables.c Tables of information... */ /* - * Copyright (c) 1995-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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: tables.c,v 1.51.2.7 2003/07/25 22:53:38 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: tables.c,v 1.51.2.8 2004/06/10 17:59:21 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" /* XXXDPN: Moved here from hash.c, when it moved to libomapi. Not sure where these really belong. */ HASH_FUNCTIONS (group, const char *, struct group_object, group_hash_t, group_reference, group_dereference) HASH_FUNCTIONS (universe, const char *, struct universe, universe_hash_t, 0, 0) HASH_FUNCTIONS (option, const char *, struct option, option_hash_t, 0, 0) /* DHCP Option names, formats and codes, from RFC1533. Format codes: I - IP address l - 32-bit signed integer L - 32-bit unsigned integer s - 16-bit signed integer S - 16-bit unsigned integer b - 8-bit signed integer B - 8-bit unsigned integer t - ASCII text f - flag (true or false) A - array of whatever precedes (e.g., IA means array of IP addresses) a - array of the preceding character (e.g., IIa means two or more IP addresses) U - name of an option space (universe) F - implicit flag - the presence of the option indicates that the flag is true. o - the preceding value is optional. E - encapsulation, string or colon-seperated hex list (the latter two for parsing). E is followed by a text string containing the name of the option space to encapsulate, followed by a '.'. If the E is immediately followed by '.', the applicable vendor option space is used if one is defined. e - If an encapsulation directive is not the first thing in the string, the option scanner requires an efficient way to find the encapsulation. This is done by placing a 'e' at the beginning of the option. The 'e' has no other purpose, and is not required if 'E' is the first thing in the option. X - either an ASCII string or binary data. On output, the string is scanned to see if it's printable ASCII and, if so, output as a quoted string. If not, it's output as colon-seperated hex. On input, the option can be specified either as a quoted string or as a colon-seperated hex list. N - enumeration. N is followed by a text string containing the name of the set of enumeration values to parse or emit, followed by a '.'. The width of the data is specified in the named enumeration. Named enumerations are tracked in parse.c. d - Domain name (i.e., FOO or FOO.BAR). */ struct universe dhcp_universe; struct option dhcp_options [256] = { { "pad", "", &dhcp_universe, 0 }, { "subnet-mask", "I", &dhcp_universe, 1 }, { "time-offset", "l", &dhcp_universe, 2 }, { "routers", "IA", &dhcp_universe, 3 }, { "time-servers", "IA", &dhcp_universe, 4 }, { "ien116-name-servers", "IA", &dhcp_universe, 5 }, { "domain-name-servers", "IA", &dhcp_universe, 6 }, { "log-servers", "IA", &dhcp_universe, 7 }, { "cookie-servers", "IA", &dhcp_universe, 8 }, { "lpr-servers", "IA", &dhcp_universe, 9 }, { "impress-servers", "IA", &dhcp_universe, 10 }, { "resource-location-servers", "IA", &dhcp_universe, 11 }, { "host-name", "X", &dhcp_universe, 12 }, { "boot-size", "S", &dhcp_universe, 13 }, { "merit-dump", "t", &dhcp_universe, 14 }, { "domain-name", "t", &dhcp_universe, 15 }, { "swap-server", "I", &dhcp_universe, 16 }, { "root-path", "t", &dhcp_universe, 17 }, { "extensions-path", "t", &dhcp_universe, 18 }, { "ip-forwarding", "f", &dhcp_universe, 19 }, { "non-local-source-routing", "f", &dhcp_universe, 20 }, { "policy-filter", "IIA", &dhcp_universe, 21 }, { "max-dgram-reassembly", "S", &dhcp_universe, 22 }, { "default-ip-ttl", "B", &dhcp_universe, 23 }, { "path-mtu-aging-timeout", "L", &dhcp_universe, 24 }, { "path-mtu-plateau-table", "SA", &dhcp_universe, 25 }, { "interface-mtu", "S", &dhcp_universe, 26 }, { "all-subnets-local", "f", &dhcp_universe, 27 }, { "broadcast-address", "I", &dhcp_universe, 28 }, { "perform-mask-discovery", "f", &dhcp_universe, 29 }, { "mask-supplier", "f", &dhcp_universe, 30 }, { "router-discovery", "f", &dhcp_universe, 31 }, { "router-solicitation-address", "I", &dhcp_universe, 32 }, { "static-routes", "IIA", &dhcp_universe, 33 }, { "trailer-encapsulation", "f", &dhcp_universe, 34 }, { "arp-cache-timeout", "L", &dhcp_universe, 35 }, { "ieee802-3-encapsulation", "f", &dhcp_universe, 36 }, { "default-tcp-ttl", "B", &dhcp_universe, 37 }, { "tcp-keepalive-interval", "L", &dhcp_universe, 38 }, { "tcp-keepalive-garbage", "f", &dhcp_universe, 39 }, { "nis-domain", "t", &dhcp_universe, 40 }, { "nis-servers", "IA", &dhcp_universe, 41 }, { "ntp-servers", "IA", &dhcp_universe, 42 }, { "vendor-encapsulated-options", "E.", &dhcp_universe, 43 }, { "netbios-name-servers", "IA", &dhcp_universe, 44 }, { "netbios-dd-server", "IA", &dhcp_universe, 45 }, { "netbios-node-type", "B", &dhcp_universe, 46 }, { "netbios-scope", "t", &dhcp_universe, 47 }, { "font-servers", "IA", &dhcp_universe, 48 }, { "x-display-manager", "IA", &dhcp_universe, 49 }, { "dhcp-requested-address", "I", &dhcp_universe, 50 }, { "dhcp-lease-time", "L", &dhcp_universe, 51 }, { "dhcp-option-overload", "B", &dhcp_universe, 52 }, { "dhcp-message-type", "B", &dhcp_universe, 53 }, { "dhcp-server-identifier", "I", &dhcp_universe, 54 }, { "dhcp-parameter-request-list", "BA", &dhcp_universe, 55 }, { "dhcp-message", "t", &dhcp_universe, 56 }, { "dhcp-max-message-size", "S", &dhcp_universe, 57 }, { "dhcp-renewal-time", "L", &dhcp_universe, 58 }, { "dhcp-rebinding-time", "L", &dhcp_universe, 59 }, { "vendor-class-identifier", "X", &dhcp_universe, 60 }, { "dhcp-client-identifier", "X", &dhcp_universe, 61 }, { "nwip-domain", "X", &dhcp_universe, 62 }, { "nwip-suboptions", "Enwip.", &dhcp_universe, 63 }, { "nisplus-domain", "t", &dhcp_universe, 64 }, { "nisplus-servers", "IA", &dhcp_universe, 65 }, { "tftp-server-name", "t", &dhcp_universe, 66 }, { "bootfile-name", "t", &dhcp_universe, 67 }, { "mobile-ip-home-agent", "IA", &dhcp_universe, 68 }, { "smtp-server", "IA", &dhcp_universe, 69 }, { "pop-server", "IA", &dhcp_universe, 70 }, { "nntp-server", "IA", &dhcp_universe, 71 }, { "www-server", "IA", &dhcp_universe, 72 }, { "finger-server", "IA", &dhcp_universe, 73 }, { "irc-server", "IA", &dhcp_universe, 74 }, { "streettalk-server", "IA", &dhcp_universe, 75 }, { "streettalk-directory-assistance-server", "IA", &dhcp_universe, 76 }, { "user-class", "t", &dhcp_universe, 77 }, { "slp-directory-agent", "fIa", &dhcp_universe, 78 }, { "slp-service-scope", "fto", &dhcp_universe, 79 }, { "unknown-80", "X", &dhcp_universe, 80 }, { "fqdn", "Efqdn.", &dhcp_universe, 81 }, { "relay-agent-information", "Eagent.", &dhcp_universe, 82 }, { "unknown-83", "X", &dhcp_universe, 83 }, { "unknown-84", "X", &dhcp_universe, 84 }, { "nds-servers", "IA", &dhcp_universe, 85 }, { "nds-tree-name", "X", &dhcp_universe, 86 }, { "nds-context", "X", &dhcp_universe, 87 }, { "unknown-88", "X", &dhcp_universe, 88 }, { "unknown-89", "X", &dhcp_universe, 89 }, { "unknown-90", "X", &dhcp_universe, 90 }, { "unknown-91", "X", &dhcp_universe, 91 }, { "unknown-92", "X", &dhcp_universe, 92 }, { "unknown-93", "X", &dhcp_universe, 93 }, { "unknown-94", "X", &dhcp_universe, 94 }, { "unknown-95", "X", &dhcp_universe, 95 }, { "unknown-96", "X", &dhcp_universe, 96 }, { "unknown-97", "X", &dhcp_universe, 97 }, { "uap-servers", "t", &dhcp_universe, 98 }, { "unknown-99", "X", &dhcp_universe, 99 }, { "unknown-100", "X", &dhcp_universe, 100 }, { "unknown-101", "X", &dhcp_universe, 101 }, { "unknown-102", "X", &dhcp_universe, 102 }, { "unknown-103", "X", &dhcp_universe, 103 }, { "unknown-104", "X", &dhcp_universe, 104 }, { "unknown-105", "X", &dhcp_universe, 105 }, { "unknown-106", "X", &dhcp_universe, 106 }, { "unknown-107", "X", &dhcp_universe, 107 }, { "unknown-108", "X", &dhcp_universe, 108 }, { "unknown-109", "X", &dhcp_universe, 109 }, { "unknown-110", "X", &dhcp_universe, 110 }, { "unknown-111", "X", &dhcp_universe, 111 }, { "unknown-112", "X", &dhcp_universe, 112 }, { "unknown-113", "X", &dhcp_universe, 113 }, { "unknown-114", "X", &dhcp_universe, 114 }, { "unknown-115", "X", &dhcp_universe, 115 }, { "unknown-116", "X", &dhcp_universe, 116 }, { "unknown-117", "X", &dhcp_universe, 117 }, { "subnet-selection", "X", &dhcp_universe, 118 }, { "unknown-119", "X", &dhcp_universe, 119 }, { "unknown-120", "X", &dhcp_universe, 120 }, { "unknown-121", "X", &dhcp_universe, 121 }, { "unknown-122", "X", &dhcp_universe, 122 }, { "unknown-123", "X", &dhcp_universe, 123 }, { "unknown-124", "X", &dhcp_universe, 124 }, { "unknown-125", "X", &dhcp_universe, 125 }, { "unknown-126", "X", &dhcp_universe, 126 }, { "unknown-127", "X", &dhcp_universe, 127 }, { "unknown-128", "X", &dhcp_universe, 128 }, { "unknown-129", "X", &dhcp_universe, 129 }, { "unknown-130", "X", &dhcp_universe, 130 }, { "unknown-131", "X", &dhcp_universe, 131 }, { "unknown-132", "X", &dhcp_universe, 132 }, { "unknown-133", "X", &dhcp_universe, 133 }, { "unknown-134", "X", &dhcp_universe, 134 }, { "unknown-135", "X", &dhcp_universe, 135 }, { "unknown-136", "X", &dhcp_universe, 136 }, { "unknown-137", "X", &dhcp_universe, 137 }, { "unknown-138", "X", &dhcp_universe, 138 }, { "unknown-139", "X", &dhcp_universe, 139 }, { "unknown-140", "X", &dhcp_universe, 140 }, { "unknown-141", "X", &dhcp_universe, 141 }, { "unknown-142", "X", &dhcp_universe, 142 }, { "unknown-143", "X", &dhcp_universe, 143 }, { "unknown-144", "X", &dhcp_universe, 144 }, { "unknown-145", "X", &dhcp_universe, 145 }, { "unknown-146", "X", &dhcp_universe, 146 }, { "unknown-147", "X", &dhcp_universe, 147 }, { "unknown-148", "X", &dhcp_universe, 148 }, { "unknown-149", "X", &dhcp_universe, 149 }, { "unknown-150", "X", &dhcp_universe, 150 }, { "unknown-151", "X", &dhcp_universe, 151 }, { "unknown-152", "X", &dhcp_universe, 152 }, { "unknown-153", "X", &dhcp_universe, 153 }, { "unknown-154", "X", &dhcp_universe, 154 }, { "unknown-155", "X", &dhcp_universe, 155 }, { "unknown-156", "X", &dhcp_universe, 156 }, { "unknown-157", "X", &dhcp_universe, 157 }, { "unknown-158", "X", &dhcp_universe, 158 }, { "unknown-159", "X", &dhcp_universe, 159 }, { "unknown-160", "X", &dhcp_universe, 160 }, { "unknown-161", "X", &dhcp_universe, 161 }, { "unknown-162", "X", &dhcp_universe, 162 }, { "unknown-163", "X", &dhcp_universe, 163 }, { "unknown-164", "X", &dhcp_universe, 164 }, { "unknown-165", "X", &dhcp_universe, 165 }, { "unknown-166", "X", &dhcp_universe, 166 }, { "unknown-167", "X", &dhcp_universe, 167 }, { "unknown-168", "X", &dhcp_universe, 168 }, { "unknown-169", "X", &dhcp_universe, 169 }, { "unknown-170", "X", &dhcp_universe, 170 }, { "unknown-171", "X", &dhcp_universe, 171 }, { "unknown-172", "X", &dhcp_universe, 172 }, { "unknown-173", "X", &dhcp_universe, 173 }, { "unknown-174", "X", &dhcp_universe, 174 }, { "unknown-175", "X", &dhcp_universe, 175 }, { "unknown-176", "X", &dhcp_universe, 176 }, { "unknown-177", "X", &dhcp_universe, 177 }, { "unknown-178", "X", &dhcp_universe, 178 }, { "unknown-179", "X", &dhcp_universe, 179 }, { "unknown-180", "X", &dhcp_universe, 180 }, { "unknown-181", "X", &dhcp_universe, 181 }, { "unknown-182", "X", &dhcp_universe, 182 }, { "unknown-183", "X", &dhcp_universe, 183 }, { "unknown-184", "X", &dhcp_universe, 184 }, { "unknown-185", "X", &dhcp_universe, 185 }, { "unknown-186", "X", &dhcp_universe, 186 }, { "unknown-187", "X", &dhcp_universe, 187 }, { "unknown-188", "X", &dhcp_universe, 188 }, { "unknown-189", "X", &dhcp_universe, 189 }, { "unknown-190", "X", &dhcp_universe, 190 }, { "unknown-191", "X", &dhcp_universe, 191 }, { "unknown-192", "X", &dhcp_universe, 192 }, { "unknown-193", "X", &dhcp_universe, 193 }, { "unknown-194", "X", &dhcp_universe, 194 }, { "unknown-195", "X", &dhcp_universe, 195 }, { "unknown-196", "X", &dhcp_universe, 196 }, { "unknown-197", "X", &dhcp_universe, 197 }, { "unknown-198", "X", &dhcp_universe, 198 }, { "unknown-199", "X", &dhcp_universe, 199 }, { "unknown-200", "X", &dhcp_universe, 200 }, { "unknown-201", "X", &dhcp_universe, 201 }, { "unknown-202", "X", &dhcp_universe, 202 }, { "unknown-203", "X", &dhcp_universe, 203 }, { "unknown-204", "X", &dhcp_universe, 204 }, { "unknown-205", "X", &dhcp_universe, 205 }, { "unknown-206", "X", &dhcp_universe, 206 }, { "unknown-207", "X", &dhcp_universe, 207 }, { "unknown-208", "X", &dhcp_universe, 208 }, { "unknown-209", "X", &dhcp_universe, 209 }, { "authenticate", "X", &dhcp_universe, 210 }, { "unknown-211", "X", &dhcp_universe, 211 }, { "unknown-212", "X", &dhcp_universe, 212 }, { "unknown-213", "X", &dhcp_universe, 213 }, { "unknown-214", "X", &dhcp_universe, 214 }, { "unknown-215", "X", &dhcp_universe, 215 }, { "unknown-216", "X", &dhcp_universe, 216 }, { "unknown-217", "X", &dhcp_universe, 217 }, { "unknown-218", "X", &dhcp_universe, 218 }, { "unknown-219", "X", &dhcp_universe, 219 }, { "unknown-220", "X", &dhcp_universe, 220 }, { "unknown-221", "X", &dhcp_universe, 221 }, { "unknown-222", "X", &dhcp_universe, 222 }, { "unknown-223", "X", &dhcp_universe, 223 }, { "unknown-224", "X", &dhcp_universe, 224 }, { "unknown-225", "X", &dhcp_universe, 225 }, { "unknown-226", "X", &dhcp_universe, 226 }, { "unknown-227", "X", &dhcp_universe, 227 }, { "unknown-228", "X", &dhcp_universe, 228 }, { "unknown-229", "X", &dhcp_universe, 229 }, { "unknown-230", "X", &dhcp_universe, 230 }, { "unknown-231", "X", &dhcp_universe, 231 }, { "unknown-232", "X", &dhcp_universe, 232 }, { "unknown-233", "X", &dhcp_universe, 233 }, { "unknown-234", "X", &dhcp_universe, 234 }, { "unknown-235", "X", &dhcp_universe, 235 }, { "unknown-236", "X", &dhcp_universe, 236 }, { "unknown-237", "X", &dhcp_universe, 237 }, { "unknown-238", "X", &dhcp_universe, 238 }, { "unknown-239", "X", &dhcp_universe, 239 }, { "unknown-240", "X", &dhcp_universe, 240 }, { "unknown-241", "X", &dhcp_universe, 241 }, { "unknown-242", "X", &dhcp_universe, 242 }, { "unknown-243", "X", &dhcp_universe, 243 }, { "unknown-244", "X", &dhcp_universe, 244 }, { "unknown-245", "X", &dhcp_universe, 245 }, { "unknown-246", "X", &dhcp_universe, 246 }, { "unknown-247", "X", &dhcp_universe, 247 }, { "unknown-248", "X", &dhcp_universe, 248 }, { "unknown-249", "X", &dhcp_universe, 249 }, { "unknown-250", "X", &dhcp_universe, 250 }, { "unknown-251", "X", &dhcp_universe, 251 }, { "unknown-252", "X", &dhcp_universe, 252 }, { "unknown-253", "X", &dhcp_universe, 253 }, { "unknown-254", "X", &dhcp_universe, 254 }, { "option-end", "e", &dhcp_universe, 255 }, }; struct universe nwip_universe; struct option nwip_options [256] = { { "pad", "", &nwip_universe, 0 }, { "illegal-1", "", &nwip_universe, 1 }, { "illegal-2", "", &nwip_universe, 2 }, { "illegal-3", "", &nwip_universe, 3 }, { "illegal-4", "", &nwip_universe, 4 }, { "nsq-broadcast", "f", &nwip_universe, 5 }, { "preferred-dss", "IA", &nwip_universe, 6 }, { "nearest-nwip-server", "IA", &nwip_universe, 7 }, { "autoretries", "B", &nwip_universe, 8 }, { "autoretry-secs", "B", &nwip_universe, 9 }, { "nwip-1-1", "f", &nwip_universe, 10 }, { "primary-dss", "I", &nwip_universe, 11 }, { "unknown-12", "X", &nwip_universe, 12 }, { "unknown-13", "X", &nwip_universe, 13 }, { "unknown-14", "X", &nwip_universe, 14 }, { "unknown-15", "X", &nwip_universe, 15 }, { "unknown-16", "X", &nwip_universe, 16 }, { "unknown-17", "X", &nwip_universe, 17 }, { "unknown-18", "X", &nwip_universe, 18 }, { "unknown-19", "X", &nwip_universe, 19 }, { "unknown-20", "X", &nwip_universe, 20 }, { "unknown-21", "X", &nwip_universe, 21 }, { "unknown-22", "X", &nwip_universe, 22 }, { "unknown-23", "X", &nwip_universe, 23 }, { "unknown-24", "X", &nwip_universe, 24 }, { "unknown-25", "X", &nwip_universe, 25 }, { "unknown-26", "X", &nwip_universe, 26 }, { "unknown-27", "X", &nwip_universe, 27 }, { "unknown-28", "X", &nwip_universe, 28 }, { "unknown-29", "X", &nwip_universe, 29 }, { "unknown-30", "X", &nwip_universe, 30 }, { "unknown-31", "X", &nwip_universe, 31 }, { "unknown-32", "X", &nwip_universe, 32 }, { "unknown-33", "X", &nwip_universe, 33 }, { "unknown-34", "X", &nwip_universe, 34 }, { "unknown-35", "X", &nwip_universe, 35 }, { "unknown-36", "X", &nwip_universe, 36 }, { "unknown-37", "X", &nwip_universe, 37 }, { "unknown-38", "X", &nwip_universe, 38 }, { "unknown-39", "X", &nwip_universe, 39 }, { "unknown-40", "X", &nwip_universe, 40 }, { "unknown-41", "X", &nwip_universe, 41 }, { "unknown-42", "X", &nwip_universe, 42 }, { "unknown-43", "X", &nwip_universe, 43 }, { "unknown-44", "X", &nwip_universe, 44 }, { "unknown-45", "X", &nwip_universe, 45 }, { "unknown-46", "X", &nwip_universe, 46 }, { "unknown-47", "X", &nwip_universe, 47 }, { "unknown-48", "X", &nwip_universe, 48 }, { "unknown-49", "X", &nwip_universe, 49 }, { "unknown-50", "X", &nwip_universe, 50 }, { "unknown-51", "X", &nwip_universe, 51 }, { "unknown-52", "X", &nwip_universe, 52 }, { "unknown-53", "X", &nwip_universe, 53 }, { "unknown-54", "X", &nwip_universe, 54 }, { "unknown-55", "X", &nwip_universe, 55 }, { "unknown-56", "X", &nwip_universe, 56 }, { "unknown-57", "X", &nwip_universe, 57 }, { "unknown-58", "X", &nwip_universe, 58 }, { "unknown-59", "X", &nwip_universe, 59 }, { "unknown-60", "X", &nwip_universe, 60 }, { "unknown-61", "X", &nwip_universe, 61 }, { "unknown-62", "X", &nwip_universe, 62 }, { "unknown-63", "X", &nwip_universe, 63 }, { "unknown-64", "X", &nwip_universe, 64 }, { "unknown-65", "X", &nwip_universe, 65 }, { "unknown-66", "X", &nwip_universe, 66 }, { "unknown-67", "X", &nwip_universe, 67 }, { "unknown-68", "X", &nwip_universe, 68 }, { "unknown-69", "X", &nwip_universe, 69 }, { "unknown-70", "X", &nwip_universe, 70 }, { "unknown-71", "X", &nwip_universe, 71 }, { "unknown-72", "X", &nwip_universe, 72 }, { "unknown-73", "X", &nwip_universe, 73 }, { "unknown-74", "X", &nwip_universe, 74 }, { "unknown-75", "X", &nwip_universe, 75 }, { "unknown-76", "X", &nwip_universe, 76 }, { "unknown-77", "X", &nwip_universe, 77 }, { "unknown-78", "X", &nwip_universe, 78 }, { "unknown-79", "X", &nwip_universe, 79 }, { "unknown-80", "X", &nwip_universe, 80 }, { "unknown-81", "X", &nwip_universe, 81 }, { "unknown-82", "X", &nwip_universe, 82 }, { "unknown-83", "X", &nwip_universe, 83 }, { "unknown-84", "X", &nwip_universe, 84 }, { "unknown-85", "X", &nwip_universe, 85 }, { "unknown-86", "X", &nwip_universe, 86 }, { "unknown-87", "X", &nwip_universe, 87 }, { "unknown-88", "X", &nwip_universe, 88 }, { "unknown-89", "X", &nwip_universe, 89 }, { "unknown-90", "X", &nwip_universe, 90 }, { "unknown-91", "X", &nwip_universe, 91 }, { "unknown-92", "X", &nwip_universe, 92 }, { "unknown-93", "X", &nwip_universe, 93 }, { "unknown-94", "X", &nwip_universe, 94 }, { "unknown-95", "X", &nwip_universe, 95 }, { "unknown-96", "X", &nwip_universe, 96 }, { "unknown-97", "X", &nwip_universe, 97 }, { "unknown-98", "X", &nwip_universe, 98 }, { "unknown-99", "X", &nwip_universe, 99 }, { "unknown-100", "X", &nwip_universe, 100 }, { "unknown-101", "X", &nwip_universe, 101 }, { "unknown-102", "X", &nwip_universe, 102 }, { "unknown-103", "X", &nwip_universe, 103 }, { "unknown-104", "X", &nwip_universe, 104 }, { "unknown-105", "X", &nwip_universe, 105 }, { "unknown-106", "X", &nwip_universe, 106 }, { "unknown-107", "X", &nwip_universe, 107 }, { "unknown-108", "X", &nwip_universe, 108 }, { "unknown-109", "X", &nwip_universe, 109 }, { "unknown-110", "X", &nwip_universe, 110 }, { "unknown-111", "X", &nwip_universe, 111 }, { "unknown-112", "X", &nwip_universe, 112 }, { "unknown-113", "X", &nwip_universe, 113 }, { "unknown-114", "X", &nwip_universe, 114 }, { "unknown-115", "X", &nwip_universe, 115 }, { "unknown-116", "X", &nwip_universe, 116 }, { "unknown-117", "X", &nwip_universe, 117 }, { "unknown-118", "X", &nwip_universe, 118 }, { "unknown-119", "X", &nwip_universe, 119 }, { "unknown-120", "X", &nwip_universe, 120 }, { "unknown-121", "X", &nwip_universe, 121 }, { "unknown-122", "X", &nwip_universe, 122 }, { "unknown-123", "X", &nwip_universe, 123 }, { "unknown-124", "X", &nwip_universe, 124 }, { "unknown-125", "X", &nwip_universe, 125 }, { "unknown-126", "X", &nwip_universe, 126 }, { "unknown-127", "X", &nwip_universe, 127 }, { "unknown-128", "X", &nwip_universe, 128 }, { "unknown-129", "X", &nwip_universe, 129 }, { "unknown-130", "X", &nwip_universe, 130 }, { "unknown-131", "X", &nwip_universe, 131 }, { "unknown-132", "X", &nwip_universe, 132 }, { "unknown-133", "X", &nwip_universe, 133 }, { "unknown-134", "X", &nwip_universe, 134 }, { "unknown-135", "X", &nwip_universe, 135 }, { "unknown-136", "X", &nwip_universe, 136 }, { "unknown-137", "X", &nwip_universe, 137 }, { "unknown-138", "X", &nwip_universe, 138 }, { "unknown-139", "X", &nwip_universe, 139 }, { "unknown-140", "X", &nwip_universe, 140 }, { "unknown-141", "X", &nwip_universe, 141 }, { "unknown-142", "X", &nwip_universe, 142 }, { "unknown-143", "X", &nwip_universe, 143 }, { "unknown-144", "X", &nwip_universe, 144 }, { "unknown-145", "X", &nwip_universe, 145 }, { "unknown-146", "X", &nwip_universe, 146 }, { "unknown-147", "X", &nwip_universe, 147 }, { "unknown-148", "X", &nwip_universe, 148 }, { "unknown-149", "X", &nwip_universe, 149 }, { "unknown-150", "X", &nwip_universe, 150 }, { "unknown-151", "X", &nwip_universe, 151 }, { "unknown-152", "X", &nwip_universe, 152 }, { "unknown-153", "X", &nwip_universe, 153 }, { "unknown-154", "X", &nwip_universe, 154 }, { "unknown-155", "X", &nwip_universe, 155 }, { "unknown-156", "X", &nwip_universe, 156 }, { "unknown-157", "X", &nwip_universe, 157 }, { "unknown-158", "X", &nwip_universe, 158 }, { "unknown-159", "X", &nwip_universe, 159 }, { "unknown-160", "X", &nwip_universe, 160 }, { "unknown-161", "X", &nwip_universe, 161 }, { "unknown-162", "X", &nwip_universe, 162 }, { "unknown-163", "X", &nwip_universe, 163 }, { "unknown-164", "X", &nwip_universe, 164 }, { "unknown-165", "X", &nwip_universe, 165 }, { "unknown-166", "X", &nwip_universe, 166 }, { "unknown-167", "X", &nwip_universe, 167 }, { "unknown-168", "X", &nwip_universe, 168 }, { "unknown-169", "X", &nwip_universe, 169 }, { "unknown-170", "X", &nwip_universe, 170 }, { "unknown-171", "X", &nwip_universe, 171 }, { "unknown-172", "X", &nwip_universe, 172 }, { "unknown-173", "X", &nwip_universe, 173 }, { "unknown-174", "X", &nwip_universe, 174 }, { "unknown-175", "X", &nwip_universe, 175 }, { "unknown-176", "X", &nwip_universe, 176 }, { "unknown-177", "X", &nwip_universe, 177 }, { "unknown-178", "X", &nwip_universe, 178 }, { "unknown-179", "X", &nwip_universe, 179 }, { "unknown-180", "X", &nwip_universe, 180 }, { "unknown-181", "X", &nwip_universe, 181 }, { "unknown-182", "X", &nwip_universe, 182 }, { "unknown-183", "X", &nwip_universe, 183 }, { "unknown-184", "X", &nwip_universe, 184 }, { "unknown-185", "X", &nwip_universe, 185 }, { "unknown-186", "X", &nwip_universe, 186 }, { "unknown-187", "X", &nwip_universe, 187 }, { "unknown-188", "X", &nwip_universe, 188 }, { "unknown-189", "X", &nwip_universe, 189 }, { "unknown-190", "X", &nwip_universe, 190 }, { "unknown-191", "X", &nwip_universe, 191 }, { "unknown-192", "X", &nwip_universe, 192 }, { "unknown-193", "X", &nwip_universe, 193 }, { "unknown-194", "X", &nwip_universe, 194 }, { "unknown-195", "X", &nwip_universe, 195 }, { "unknown-196", "X", &nwip_universe, 196 }, { "unknown-197", "X", &nwip_universe, 197 }, { "unknown-198", "X", &nwip_universe, 198 }, { "unknown-199", "X", &nwip_universe, 199 }, { "unknown-200", "X", &nwip_universe, 200 }, { "unknown-201", "X", &nwip_universe, 201 }, { "unknown-202", "X", &nwip_universe, 202 }, { "unknown-203", "X", &nwip_universe, 203 }, { "unknown-204", "X", &nwip_universe, 204 }, { "unknown-205", "X", &nwip_universe, 205 }, { "unknown-206", "X", &nwip_universe, 206 }, { "unknown-207", "X", &nwip_universe, 207 }, { "unknown-208", "X", &nwip_universe, 208 }, { "unknown-209", "X", &nwip_universe, 209 }, { "unknown-210", "X", &nwip_universe, 210 }, { "unknown-211", "X", &nwip_universe, 211 }, { "unknown-212", "X", &nwip_universe, 212 }, { "unknown-213", "X", &nwip_universe, 213 }, { "unknown-214", "X", &nwip_universe, 214 }, { "unknown-215", "X", &nwip_universe, 215 }, { "unknown-216", "X", &nwip_universe, 216 }, { "unknown-217", "X", &nwip_universe, 217 }, { "unknown-218", "X", &nwip_universe, 218 }, { "unknown-219", "X", &nwip_universe, 219 }, { "unknown-220", "X", &nwip_universe, 220 }, { "unknown-221", "X", &nwip_universe, 221 }, { "unknown-222", "X", &nwip_universe, 222 }, { "unknown-223", "X", &nwip_universe, 223 }, { "unknown-224", "X", &nwip_universe, 224 }, { "unknown-225", "X", &nwip_universe, 225 }, { "unknown-226", "X", &nwip_universe, 226 }, { "unknown-227", "X", &nwip_universe, 227 }, { "unknown-228", "X", &nwip_universe, 228 }, { "unknown-229", "X", &nwip_universe, 229 }, { "unknown-230", "X", &nwip_universe, 230 }, { "unknown-231", "X", &nwip_universe, 231 }, { "unknown-232", "X", &nwip_universe, 232 }, { "unknown-233", "X", &nwip_universe, 233 }, { "unknown-234", "X", &nwip_universe, 234 }, { "unknown-235", "X", &nwip_universe, 235 }, { "unknown-236", "X", &nwip_universe, 236 }, { "unknown-237", "X", &nwip_universe, 237 }, { "unknown-238", "X", &nwip_universe, 238 }, { "unknown-239", "X", &nwip_universe, 239 }, { "unknown-240", "X", &nwip_universe, 240 }, { "unknown-241", "X", &nwip_universe, 241 }, { "unknown-242", "X", &nwip_universe, 242 }, { "unknown-243", "X", &nwip_universe, 243 }, { "unknown-244", "X", &nwip_universe, 244 }, { "unknown-245", "X", &nwip_universe, 245 }, { "unknown-246", "X", &nwip_universe, 246 }, { "unknown-247", "X", &nwip_universe, 247 }, { "unknown-248", "X", &nwip_universe, 248 }, { "unknown-249", "X", &nwip_universe, 249 }, { "unknown-250", "X", &nwip_universe, 250 }, { "unknown-251", "X", &nwip_universe, 251 }, { "unknown-252", "X", &nwip_universe, 252 }, { "unknown-253", "X", &nwip_universe, 253 }, { "unknown-254", "X", &nwip_universe, 254 }, { "unknown-end", "e", &nwip_universe, 255 }, }; struct universe fqdn_universe; struct option fqdn_options [256] = { { "pad", "", &fqdn_universe, 0 }, { "no-client-update", "f", &fqdn_universe, 1 }, { "server-update", "f", &fqdn_universe, 2 }, { "encoded", "f", &fqdn_universe, 3 }, { "rcode1", "B", &fqdn_universe, 4 }, { "rcode2", "B", &fqdn_universe, 5 }, { "hostname", "t", &fqdn_universe, 6 }, { "domainname", "t", &fqdn_universe, 7 }, { "fqdn", "t", &fqdn_universe, 8 }, { "unknown-9", "X", &fqdn_universe, 9 }, { "unknown-10", "X", &fqdn_universe, 10 }, { "unknown-11", "X", &fqdn_universe, 11 }, { "unknown-12", "X", &fqdn_universe, 12 }, { "unknown-13", "X", &fqdn_universe, 13 }, { "unknown-14", "X", &fqdn_universe, 14 }, { "unknown-15", "X", &fqdn_universe, 15 }, { "unknown-16", "X", &fqdn_universe, 16 }, { "unknown-17", "X", &fqdn_universe, 17 }, { "unknown-18", "X", &fqdn_universe, 18 }, { "unknown-19", "X", &fqdn_universe, 19 }, { "unknown-20", "X", &fqdn_universe, 20 }, { "unknown-21", "X", &fqdn_universe, 21 }, { "unknown-22", "X", &fqdn_universe, 22 }, { "unknown-23", "X", &fqdn_universe, 23 }, { "unknown-24", "X", &fqdn_universe, 24 }, { "unknown-25", "X", &fqdn_universe, 25 }, { "unknown-26", "X", &fqdn_universe, 26 }, { "unknown-27", "X", &fqdn_universe, 27 }, { "unknown-28", "X", &fqdn_universe, 28 }, { "unknown-29", "X", &fqdn_universe, 29 }, { "unknown-30", "X", &fqdn_universe, 30 }, { "unknown-31", "X", &fqdn_universe, 31 }, { "unknown-32", "X", &fqdn_universe, 32 }, { "unknown-33", "X", &fqdn_universe, 33 }, { "unknown-34", "X", &fqdn_universe, 34 }, { "unknown-35", "X", &fqdn_universe, 35 }, { "unknown-36", "X", &fqdn_universe, 36 }, { "unknown-37", "X", &fqdn_universe, 37 }, { "unknown-38", "X", &fqdn_universe, 38 }, { "unknown-39", "X", &fqdn_universe, 39 }, { "unknown-40", "X", &fqdn_universe, 40 }, { "unknown-41", "X", &fqdn_universe, 41 }, { "unknown-42", "X", &fqdn_universe, 42 }, { "unknown-43", "X", &fqdn_universe, 43 }, { "unknown-44", "X", &fqdn_universe, 44 }, { "unknown-45", "X", &fqdn_universe, 45 }, { "unknown-46", "X", &fqdn_universe, 46 }, { "unknown-47", "X", &fqdn_universe, 47 }, { "unknown-48", "X", &fqdn_universe, 48 }, { "unknown-49", "X", &fqdn_universe, 49 }, { "unknown-50", "X", &fqdn_universe, 50 }, { "unknown-51", "X", &fqdn_universe, 51 }, { "unknown-52", "X", &fqdn_universe, 52 }, { "unknown-53", "X", &fqdn_universe, 53 }, { "unknown-54", "X", &fqdn_universe, 54 }, { "unknown-55", "X", &fqdn_universe, 55 }, { "unknown-56", "X", &fqdn_universe, 56 }, { "unknown-57", "X", &fqdn_universe, 57 }, { "unknown-58", "X", &fqdn_universe, 58 }, { "unknown-59", "X", &fqdn_universe, 59 }, { "unknown-60", "X", &fqdn_universe, 60 }, { "unknown-61", "X", &fqdn_universe, 61 }, { "unknown-62", "X", &fqdn_universe, 62 }, { "unknown-63", "X", &fqdn_universe, 63 }, { "unknown-64", "X", &fqdn_universe, 64 }, { "unknown-65", "X", &fqdn_universe, 65 }, { "unknown-66", "X", &fqdn_universe, 66 }, { "unknown-67", "X", &fqdn_universe, 67 }, { "unknown-68", "X", &fqdn_universe, 68 }, { "unknown-69", "X", &fqdn_universe, 69 }, { "unknown-70", "X", &fqdn_universe, 70 }, { "unknown-71", "X", &fqdn_universe, 71 }, { "unknown-72", "X", &fqdn_universe, 72 }, { "unknown-73", "X", &fqdn_universe, 73 }, { "unknown-74", "X", &fqdn_universe, 74 }, { "unknown-75", "X", &fqdn_universe, 75 }, { "unknown-76", "X", &fqdn_universe, 76 }, { "unknown-77", "X", &fqdn_universe, 77 }, { "unknown-78", "X", &fqdn_universe, 78 }, { "unknown-79", "X", &fqdn_universe, 79 }, { "unknown-80", "X", &fqdn_universe, 80 }, { "unknown-81", "X", &fqdn_universe, 81 }, { "unknown-82", "X", &fqdn_universe, 82 }, { "unknown-83", "X", &fqdn_universe, 83 }, { "unknown-84", "X", &fqdn_universe, 84 }, { "unknown-85", "X", &fqdn_universe, 85 }, { "unknown-86", "X", &fqdn_universe, 86 }, { "unknown-87", "X", &fqdn_universe, 87 }, { "unknown-88", "X", &fqdn_universe, 88 }, { "unknown-89", "X", &fqdn_universe, 89 }, { "unknown-90", "X", &fqdn_universe, 90 }, { "unknown-91", "X", &fqdn_universe, 91 }, { "unknown-92", "X", &fqdn_universe, 92 }, { "unknown-93", "X", &fqdn_universe, 93 }, { "unknown-94", "X", &fqdn_universe, 94 }, { "unknown-95", "X", &fqdn_universe, 95 }, { "unknown-96", "X", &fqdn_universe, 96 }, { "unknown-97", "X", &fqdn_universe, 97 }, { "unknown-98", "X", &fqdn_universe, 98 }, { "unknown-99", "X", &fqdn_universe, 99 }, { "unknown-100", "X", &fqdn_universe, 100 }, { "unknown-101", "X", &fqdn_universe, 101 }, { "unknown-102", "X", &fqdn_universe, 102 }, { "unknown-103", "X", &fqdn_universe, 103 }, { "unknown-104", "X", &fqdn_universe, 104 }, { "unknown-105", "X", &fqdn_universe, 105 }, { "unknown-106", "X", &fqdn_universe, 106 }, { "unknown-107", "X", &fqdn_universe, 107 }, { "unknown-108", "X", &fqdn_universe, 108 }, { "unknown-109", "X", &fqdn_universe, 109 }, { "unknown-110", "X", &fqdn_universe, 110 }, { "unknown-111", "X", &fqdn_universe, 111 }, { "unknown-112", "X", &fqdn_universe, 112 }, { "unknown-113", "X", &fqdn_universe, 113 }, { "unknown-114", "X", &fqdn_universe, 114 }, { "unknown-115", "X", &fqdn_universe, 115 }, { "unknown-116", "X", &fqdn_universe, 116 }, { "unknown-117", "X", &fqdn_universe, 117 }, { "unknown-118", "X", &fqdn_universe, 118 }, { "unknown-119", "X", &fqdn_universe, 119 }, { "unknown-120", "X", &fqdn_universe, 120 }, { "unknown-121", "X", &fqdn_universe, 121 }, { "unknown-122", "X", &fqdn_universe, 122 }, { "unknown-123", "X", &fqdn_universe, 123 }, { "unknown-124", "X", &fqdn_universe, 124 }, { "unknown-125", "X", &fqdn_universe, 125 }, { "unknown-126", "X", &fqdn_universe, 126 }, { "unknown-127", "X", &fqdn_universe, 127 }, { "unknown-128", "X", &fqdn_universe, 128 }, { "unknown-129", "X", &fqdn_universe, 129 }, { "unknown-130", "X", &fqdn_universe, 130 }, { "unknown-131", "X", &fqdn_universe, 131 }, { "unknown-132", "X", &fqdn_universe, 132 }, { "unknown-133", "X", &fqdn_universe, 133 }, { "unknown-134", "X", &fqdn_universe, 134 }, { "unknown-135", "X", &fqdn_universe, 135 }, { "unknown-136", "X", &fqdn_universe, 136 }, { "unknown-137", "X", &fqdn_universe, 137 }, { "unknown-138", "X", &fqdn_universe, 138 }, { "unknown-139", "X", &fqdn_universe, 139 }, { "unknown-140", "X", &fqdn_universe, 140 }, { "unknown-141", "X", &fqdn_universe, 141 }, { "unknown-142", "X", &fqdn_universe, 142 }, { "unknown-143", "X", &fqdn_universe, 143 }, { "unknown-144", "X", &fqdn_universe, 144 }, { "unknown-145", "X", &fqdn_universe, 145 }, { "unknown-146", "X", &fqdn_universe, 146 }, { "unknown-147", "X", &fqdn_universe, 147 }, { "unknown-148", "X", &fqdn_universe, 148 }, { "unknown-149", "X", &fqdn_universe, 149 }, { "unknown-150", "X", &fqdn_universe, 150 }, { "unknown-151", "X", &fqdn_universe, 151 }, { "unknown-152", "X", &fqdn_universe, 152 }, { "unknown-153", "X", &fqdn_universe, 153 }, { "unknown-154", "X", &fqdn_universe, 154 }, { "unknown-155", "X", &fqdn_universe, 155 }, { "unknown-156", "X", &fqdn_universe, 156 }, { "unknown-157", "X", &fqdn_universe, 157 }, { "unknown-158", "X", &fqdn_universe, 158 }, { "unknown-159", "X", &fqdn_universe, 159 }, { "unknown-160", "X", &fqdn_universe, 160 }, { "unknown-161", "X", &fqdn_universe, 161 }, { "unknown-162", "X", &fqdn_universe, 162 }, { "unknown-163", "X", &fqdn_universe, 163 }, { "unknown-164", "X", &fqdn_universe, 164 }, { "unknown-165", "X", &fqdn_universe, 165 }, { "unknown-166", "X", &fqdn_universe, 166 }, { "unknown-167", "X", &fqdn_universe, 167 }, { "unknown-168", "X", &fqdn_universe, 168 }, { "unknown-169", "X", &fqdn_universe, 169 }, { "unknown-170", "X", &fqdn_universe, 170 }, { "unknown-171", "X", &fqdn_universe, 171 }, { "unknown-172", "X", &fqdn_universe, 172 }, { "unknown-173", "X", &fqdn_universe, 173 }, { "unknown-174", "X", &fqdn_universe, 174 }, { "unknown-175", "X", &fqdn_universe, 175 }, { "unknown-176", "X", &fqdn_universe, 176 }, { "unknown-177", "X", &fqdn_universe, 177 }, { "unknown-178", "X", &fqdn_universe, 178 }, { "unknown-179", "X", &fqdn_universe, 179 }, { "unknown-180", "X", &fqdn_universe, 180 }, { "unknown-181", "X", &fqdn_universe, 181 }, { "unknown-182", "X", &fqdn_universe, 182 }, { "unknown-183", "X", &fqdn_universe, 183 }, { "unknown-184", "X", &fqdn_universe, 184 }, { "unknown-185", "X", &fqdn_universe, 185 }, { "unknown-186", "X", &fqdn_universe, 186 }, { "unknown-187", "X", &fqdn_universe, 187 }, { "unknown-188", "X", &fqdn_universe, 188 }, { "unknown-189", "X", &fqdn_universe, 189 }, { "unknown-190", "X", &fqdn_universe, 190 }, { "unknown-191", "X", &fqdn_universe, 191 }, { "unknown-192", "X", &fqdn_universe, 192 }, { "unknown-193", "X", &fqdn_universe, 193 }, { "unknown-194", "X", &fqdn_universe, 194 }, { "unknown-195", "X", &fqdn_universe, 195 }, { "unknown-196", "X", &fqdn_universe, 196 }, { "unknown-197", "X", &fqdn_universe, 197 }, { "unknown-198", "X", &fqdn_universe, 198 }, { "unknown-199", "X", &fqdn_universe, 199 }, { "unknown-200", "X", &fqdn_universe, 200 }, { "unknown-201", "X", &fqdn_universe, 201 }, { "unknown-202", "X", &fqdn_universe, 202 }, { "unknown-203", "X", &fqdn_universe, 203 }, { "unknown-204", "X", &fqdn_universe, 204 }, { "unknown-205", "X", &fqdn_universe, 205 }, { "unknown-206", "X", &fqdn_universe, 206 }, { "unknown-207", "X", &fqdn_universe, 207 }, { "unknown-208", "X", &fqdn_universe, 208 }, { "unknown-209", "X", &fqdn_universe, 209 }, { "unknown-210", "X", &fqdn_universe, 210 }, { "unknown-211", "X", &fqdn_universe, 211 }, { "unknown-212", "X", &fqdn_universe, 212 }, { "unknown-213", "X", &fqdn_universe, 213 }, { "unknown-214", "X", &fqdn_universe, 214 }, { "unknown-215", "X", &fqdn_universe, 215 }, { "unknown-216", "X", &fqdn_universe, 216 }, { "unknown-217", "X", &fqdn_universe, 217 }, { "unknown-218", "X", &fqdn_universe, 218 }, { "unknown-219", "X", &fqdn_universe, 219 }, { "unknown-220", "X", &fqdn_universe, 220 }, { "unknown-221", "X", &fqdn_universe, 221 }, { "unknown-222", "X", &fqdn_universe, 222 }, { "unknown-223", "X", &fqdn_universe, 223 }, { "unknown-224", "X", &fqdn_universe, 224 }, { "unknown-225", "X", &fqdn_universe, 225 }, { "unknown-226", "X", &fqdn_universe, 226 }, { "unknown-227", "X", &fqdn_universe, 227 }, { "unknown-228", "X", &fqdn_universe, 228 }, { "unknown-229", "X", &fqdn_universe, 229 }, { "unknown-230", "X", &fqdn_universe, 230 }, { "unknown-231", "X", &fqdn_universe, 231 }, { "unknown-232", "X", &fqdn_universe, 232 }, { "unknown-233", "X", &fqdn_universe, 233 }, { "unknown-234", "X", &fqdn_universe, 234 }, { "unknown-235", "X", &fqdn_universe, 235 }, { "unknown-236", "X", &fqdn_universe, 236 }, { "unknown-237", "X", &fqdn_universe, 237 }, { "unknown-238", "X", &fqdn_universe, 238 }, { "unknown-239", "X", &fqdn_universe, 239 }, { "unknown-240", "X", &fqdn_universe, 240 }, { "unknown-241", "X", &fqdn_universe, 241 }, { "unknown-242", "X", &fqdn_universe, 242 }, { "unknown-243", "X", &fqdn_universe, 243 }, { "unknown-244", "X", &fqdn_universe, 244 }, { "unknown-245", "X", &fqdn_universe, 245 }, { "unknown-246", "X", &fqdn_universe, 246 }, { "unknown-247", "X", &fqdn_universe, 247 }, { "unknown-248", "X", &fqdn_universe, 248 }, { "unknown-249", "X", &fqdn_universe, 249 }, { "unknown-250", "X", &fqdn_universe, 250 }, { "unknown-251", "X", &fqdn_universe, 251 }, { "unknown-252", "X", &fqdn_universe, 252 }, { "unknown-253", "X", &fqdn_universe, 253 }, { "unknown-254", "X", &fqdn_universe, 254 }, { "unknown-end", "e", &fqdn_universe, 255 }, }; const char *hardware_types [] = { "unknown-0", "ethernet", "unknown-2", "unknown-3", "unknown-4", "unknown-5", "token-ring", "unknown-7", "fddi", "unknown-9", "unknown-10", "unknown-11", "unknown-12", "unknown-13", "unknown-14", "unknown-15", "unknown-16", "unknown-17", "unknown-18", "unknown-19", "unknown-20", "unknown-21", "unknown-22", "unknown-23", "unknown-24", "unknown-25", "unknown-26", "unknown-27", "unknown-28", "unknown-29", "unknown-30", "unknown-31", "unknown-32", "unknown-33", "unknown-34", "unknown-35", "unknown-36", "unknown-37", "unknown-38", "unknown-39", "unknown-40", "unknown-41", "unknown-42", "unknown-43", "unknown-44", "unknown-45", "unknown-46", "unknown-47", "unknown-48", "unknown-49", "unknown-50", "unknown-51", "unknown-52", "unknown-53", "unknown-54", "unknown-55", "unknown-56", "unknown-57", "unknown-58", "unknown-59", "unknown-60", "unknown-61", "unknown-62", "unknown-63", "unknown-64", "unknown-65", "unknown-66", "unknown-67", "unknown-68", "unknown-69", "unknown-70", "unknown-71", "unknown-72", "unknown-73", "unknown-74", "unknown-75", "unknown-76", "unknown-77", "unknown-78", "unknown-79", "unknown-80", "unknown-81", "unknown-82", "unknown-83", "unknown-84", "unknown-85", "unknown-86", "unknown-87", "unknown-88", "unknown-89", "unknown-90", "unknown-91", "unknown-92", "unknown-93", "unknown-94", "unknown-95", "unknown-96", "unknown-97", "unknown-98", "unknown-99", "unknown-100", "unknown-101", "unknown-102", "unknown-103", "unknown-104", "unknown-105", "unknown-106", "unknown-107", "unknown-108", "unknown-109", "unknown-110", "unknown-111", "unknown-112", "unknown-113", "unknown-114", "unknown-115", "unknown-116", "unknown-117", "unknown-118", "unknown-119", "unknown-120", "unknown-121", "unknown-122", "unknown-123", "unknown-124", "unknown-125", "unknown-126", "unknown-127", "unknown-128", "unknown-129", "unknown-130", "unknown-131", "unknown-132", "unknown-133", "unknown-134", "unknown-135", "unknown-136", "unknown-137", "unknown-138", "unknown-139", "unknown-140", "unknown-141", "unknown-142", "unknown-143", "unknown-144", "unknown-145", "unknown-146", "unknown-147", "unknown-148", "unknown-149", "unknown-150", "unknown-151", "unknown-152", "unknown-153", "unknown-154", "unknown-155", "unknown-156", "unknown-157", "unknown-158", "unknown-159", "unknown-160", "unknown-161", "unknown-162", "unknown-163", "unknown-164", "unknown-165", "unknown-166", "unknown-167", "unknown-168", "unknown-169", "unknown-170", "unknown-171", "unknown-172", "unknown-173", "unknown-174", "unknown-175", "unknown-176", "unknown-177", "unknown-178", "unknown-179", "unknown-180", "unknown-181", "unknown-182", "unknown-183", "unknown-184", "unknown-185", "unknown-186", "unknown-187", "unknown-188", "unknown-189", "unknown-190", "unknown-191", "unknown-192", "unknown-193", "unknown-194", "unknown-195", "unknown-196", "unknown-197", "unknown-198", "unknown-199", "unknown-200", "unknown-201", "unknown-202", "unknown-203", "unknown-204", "unknown-205", "unknown-206", "unknown-207", "unknown-208", "unknown-209", "unknown-210", "unknown-211", "unknown-212", "unknown-213", "unknown-214", "unknown-215", "unknown-216", "unknown-217", "unknown-218", "unknown-219", "unknown-220", "unknown-221", "unknown-222", "unknown-223", "unknown-224", "unknown-225", "unknown-226", "unknown-227", "unknown-228", "unknown-229", "unknown-230", "unknown-231", "unknown-232", "unknown-233", "unknown-234", "unknown-235", "unknown-236", "unknown-237", "unknown-238", "unknown-239", "unknown-240", "unknown-241", "unknown-242", "unknown-243", "unknown-244", "unknown-245", "unknown-246", "unknown-247", "unknown-248", "unknown-249", "unknown-250", "unknown-251", "unknown-252", "unknown-253", "unknown-254", "unknown-255" }; universe_hash_t *universe_hash; struct universe **universes; int universe_count, universe_max; /* Universe containing names of configuration options, which, rather than writing "option universe-name.option-name ...;", can be set by writing "option-name ...;". */ struct universe *config_universe; void initialize_common_option_spaces() { int i; universe_max = 10; universes = ((struct universe **) dmalloc (universe_max * sizeof (struct universe *), MDL)); if (!universes) log_fatal ("Can't allocate option space table."); memset (universes, 0, universe_max * sizeof (struct universe *)); /* Set up the DHCP option universe... */ dhcp_universe.name = "dhcp"; dhcp_universe.lookup_func = lookup_hashed_option; dhcp_universe.option_state_dereference = hashed_option_state_dereference; dhcp_universe.save_func = save_hashed_option; dhcp_universe.delete_func = delete_hashed_option; dhcp_universe.encapsulate = hashed_option_space_encapsulate; dhcp_universe.foreach = hashed_option_space_foreach; dhcp_universe.decode = parse_option_buffer; dhcp_universe.length_size = 1; dhcp_universe.tag_size = 1; dhcp_universe.store_tag = putUChar; dhcp_universe.store_length = putUChar; dhcp_universe.index = universe_count++; universes [dhcp_universe.index] = &dhcp_universe; if (!option_new_hash (&dhcp_universe.hash, 1, MDL)) log_fatal ("Can't allocate dhcp option hash table."); for (i = 0; i < 256; i++) { dhcp_universe.options [i] = &dhcp_options [i]; option_hash_add (dhcp_universe.hash, dhcp_options [i].name, 0, &dhcp_options [i], MDL); } /* Set up the Novell option universe (for option 63)... */ nwip_universe.name = "nwip"; nwip_universe.lookup_func = lookup_linked_option; nwip_universe.option_state_dereference = linked_option_state_dereference; nwip_universe.save_func = save_linked_option; nwip_universe.delete_func = delete_linked_option; nwip_universe.encapsulate = nwip_option_space_encapsulate; nwip_universe.foreach = linked_option_space_foreach; nwip_universe.decode = parse_option_buffer; nwip_universe.length_size = 1; nwip_universe.tag_size = 1; nwip_universe.store_tag = putUChar; nwip_universe.store_length = putUChar; nwip_universe.enc_opt = &dhcp_options [DHO_NWIP_SUBOPTIONS]; nwip_universe.index = universe_count++; universes [nwip_universe.index] = &nwip_universe; option_new_hash (&nwip_universe.hash, 1, MDL); if (!nwip_universe.hash) log_fatal ("Can't allocate nwip option hash table."); for (i = 0; i < 256; i++) { nwip_universe.options [i] = &nwip_options [i]; option_hash_add (nwip_universe.hash, nwip_options [i].name, 0, &nwip_options [i], MDL); } /* Set up the FQDN option universe... */ fqdn_universe.name = "fqdn"; fqdn_universe.lookup_func = lookup_linked_option; fqdn_universe.option_state_dereference = linked_option_state_dereference; fqdn_universe.save_func = save_linked_option; fqdn_universe.delete_func = delete_linked_option; fqdn_universe.encapsulate = fqdn_option_space_encapsulate; fqdn_universe.foreach = linked_option_space_foreach; fqdn_universe.decode = fqdn_universe_decode; fqdn_universe.length_size = 1; fqdn_universe.tag_size = 1; fqdn_universe.store_tag = putUChar; fqdn_universe.store_length = putUChar; fqdn_universe.index = universe_count++; fqdn_universe.enc_opt = &dhcp_options [DHO_FQDN]; universes [fqdn_universe.index] = &fqdn_universe; option_new_hash (&fqdn_universe.hash, 1, MDL); if (!fqdn_universe.hash) log_fatal ("Can't allocate fqdn option hash table."); for (i = 0; i < 256; i++) { fqdn_universe.options [i] = &fqdn_options [i]; option_hash_add (fqdn_universe.hash, fqdn_options [i].name, 0, &fqdn_options [i], MDL); } /* Set up the hash of universes. */ universe_new_hash (&universe_hash, 1, MDL); universe_hash_add (universe_hash, dhcp_universe.name, 0, &dhcp_universe, MDL); universe_hash_add (universe_hash, nwip_universe.name, 0, &nwip_universe, MDL); universe_hash_add (universe_hash, fqdn_universe.name, 0, &fqdn_universe, MDL); } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/tr.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/tr.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/tr.c (revision 131136) @@ -1,344 +1,335 @@ /* tr.c token ring interface support Contributed in May of 1999 by Andrew Chittenden */ /* - * Copyright (c) 1996-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ */ #ifndef lint static char copyright[] = -"$Id: tr.c,v 1.7.2.1 2002/11/17 02:27:00 dhankins Exp $ Copyright (c) 1996-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: tr.c,v 1.7.2.2 2004/06/10 17:59:21 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #if defined (HAVE_TR_SUPPORT) && \ (defined (PACKET_ASSEMBLY) || defined (PACKET_DECODING)) #include "includes/netinet/ip.h" #include "includes/netinet/udp.h" #include "includes/netinet/if_ether.h" #include "netinet/if_tr.h" #include /* * token ring device handling subroutines. These are required as token-ring * does not have a simple on-the-wire header but requires the use of * source routing */ static int insert_source_routing PROTO ((struct trh_hdr *trh, struct interface_info* interface)); static void save_source_routing PROTO ((struct trh_hdr *trh, struct interface_info* interface)); static void expire_routes PROTO ((void)); /* * As we keep a list of interesting routing information only, a singly * linked list is all we need */ struct routing_entry { struct routing_entry *next; unsigned char addr[TR_ALEN]; unsigned char iface[5]; __u16 rcf; /* route control field */ __u16 rseg[8]; /* routing registers */ unsigned long access_time; /* time we last used this entry */ }; static struct routing_entry *routing_info = NULL; static int routing_timeout = 10; static struct timeval routing_timer; void assemble_tr_header (interface, buf, bufix, to) struct interface_info *interface; unsigned char *buf; unsigned *bufix; struct hardware *to; { struct trh_hdr *trh; int hdr_len; struct trllc *llc; /* set up the token header */ trh = (struct trh_hdr *) &buf[*bufix]; if (interface -> hw_address.hlen - 1 == sizeof (trh->saddr)) memcpy (trh->saddr, &interface -> hw_address.hbuf [1], sizeof (trh->saddr)); else memset (trh->saddr, 0x00, sizeof (trh->saddr)); if (to && to -> hlen == 7) /* XXX */ memcpy (trh->daddr, &to -> hbuf [1], sizeof trh->daddr); else memset (trh->daddr, 0xff, sizeof (trh->daddr)); hdr_len = insert_source_routing (trh, interface); trh->ac = AC; trh->fc = LLC_FRAME; /* set up the llc header for snap encoding after the tr header */ llc = (struct trllc *)(buf + *bufix + hdr_len); llc->dsap = EXTENDED_SAP; llc->ssap = EXTENDED_SAP; llc->llc = UI_CMD; llc->protid[0] = 0; llc->protid[1] = 0; llc->protid[2] = 0; llc->ethertype = htons(ETHERTYPE_IP); hdr_len += sizeof(struct trllc); *bufix += hdr_len; } static unsigned char tr_broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; /* * decoding the token header is a bit complex as you can see here. It is * further complicated by the linux kernel stripping off some valuable * information (see comment below) even though we've asked for the raw * packets. */ ssize_t decode_tr_header (interface, buf, bufix, from) struct interface_info *interface; unsigned char *buf; unsigned bufix; struct hardware *from; { struct trh_hdr *trh = (struct trh_hdr *) buf + bufix; struct trllc *llc; struct ip *ip; struct udphdr *udp; unsigned int route_len = 0; ssize_t hdr_len; struct timeval now; /* see whether any source routing information has expired */ gettimeofday(&now, NULL); if (routing_timer.tv_sec == 0) routing_timer.tv_sec = now.tv_sec + routing_timeout; else if ((now.tv_sec - routing_timer.tv_sec) > 0) expire_routes(); /* the kernel might have stripped off the source * routing bit. We try a heuristic to determine whether * this is the case and put it back on if so */ route_len = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8; llc = (struct trllc *)(buf + bufix + sizeof(struct trh_hdr)-TR_MAXRIFLEN+route_len); if (llc->dsap == EXTENDED_SAP && llc->ssap == EXTENDED_SAP && llc->llc == UI_CMD && llc->protid[0] == 0 && llc->protid[1] == 0 && llc->protid[2] == 0) { /* say there is source routing information present */ trh->saddr[0] |= TR_RII; } if (trh->saddr[0] & TR_RII) route_len = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8; else route_len = 0; hdr_len = sizeof (struct trh_hdr) - TR_MAXRIFLEN + route_len; /* now filter out unwanted packets: this is based on the packet * filter code in bpf.c */ llc = (struct trllc *)(buf + bufix + hdr_len); ip = (struct ip *) (llc + 1); udp = (struct udphdr *) ((unsigned char*) ip + IP_HL (ip)); /* make sure it is a snap encoded, IP, UDP, unfragmented packet sent * to our port */ if (llc->dsap != EXTENDED_SAP || ntohs(llc->ethertype) != ETHERTYPE_IP || ip->ip_p != IPPROTO_UDP || (ntohs (ip->ip_off) & IP_OFFMASK) != 0 || udp->uh_dport != local_port) return -1; /* only save source routing information for packets from valued hosts */ save_source_routing(trh, interface); return hdr_len + sizeof (struct trllc); } /* insert_source_routing inserts source route information into the token ring * header */ static int insert_source_routing (trh, interface) struct trh_hdr *trh; struct interface_info* interface; { struct routing_entry *rover; struct timeval now; unsigned int route_len = 0; gettimeofday(&now, NULL); /* single route broadcasts as per rfc 1042 */ if (memcmp(trh->daddr, tr_broadcast,TR_ALEN) == 0) { trh->saddr[0] |= TR_RII; trh->rcf = ((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK; trh->rcf |= (TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST); trh->rcf = htons(trh->rcf); } else { /* look for a routing entry */ for (rover = routing_info; rover != NULL; rover = rover->next) { if (memcmp(rover->addr, trh->daddr, TR_ALEN) == 0) break; } if (rover != NULL) { /* success: route that frame */ if ((rover->rcf & TR_RCF_LEN_MASK) >> 8) { __u16 rcf = rover->rcf; memcpy(trh->rseg,rover->rseg,sizeof(trh->rseg)); rcf ^= TR_RCF_DIR_BIT; rcf &= ~TR_RCF_BROADCAST_MASK; trh->rcf = htons(rcf); trh->saddr[0] |= TR_RII; } rover->access_time = now.tv_sec; } else { /* we don't have any routing information so send a * limited broadcast */ trh->saddr[0] |= TR_RII; trh->rcf = ((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK; trh->rcf |= (TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST); trh->rcf = htons(trh->rcf); } } /* return how much of the header we've actually used */ if (trh->saddr[0] & TR_RII) route_len = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8; else route_len = 0; return sizeof (struct trh_hdr) - TR_MAXRIFLEN + route_len; } /* * save any source routing information */ static void save_source_routing(trh, interface) struct trh_hdr *trh; struct interface_info *interface; { struct routing_entry *rover; struct timeval now; unsigned char saddr[TR_ALEN]; __u16 rcf = 0; gettimeofday(&now, NULL); memcpy(saddr, trh->saddr, sizeof(saddr)); saddr[0] &= 0x7f; /* strip off source routing present flag */ /* scan our table to see if we've got it */ for (rover = routing_info; rover != NULL; rover = rover->next) { if (memcmp(&rover->addr[0], &saddr[0], TR_ALEN) == 0) break; } /* found an entry so update it with fresh information */ if (rover != NULL) { if ((trh->saddr[0] & TR_RII) && ((ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8) > 2) { rcf = ntohs(trh->rcf); rcf &= ~TR_RCF_BROADCAST_MASK; memcpy(rover->rseg, trh->rseg, sizeof(rover->rseg)); } rover->rcf = rcf; rover->access_time = now.tv_sec; return; /* that's all folks */ } /* no entry found, so create one */ rover = dmalloc (sizeof (struct routing_entry), MDL); if (rover == NULL) { fprintf(stderr, "%s: unable to save source routing information\n", __FILE__); return; } memcpy(rover->addr, saddr, sizeof(rover->addr)); memcpy(rover->iface, interface->name, 5); rover->access_time = now.tv_sec; if (trh->saddr[0] & TR_RII) { if (((ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8) > 2) { rcf = ntohs(trh->rcf); rcf &= ~TR_RCF_BROADCAST_MASK; memcpy(rover->rseg, trh->rseg, sizeof(rover->rseg)); } rover->rcf = rcf; } /* insert into list */ rover->next = routing_info; routing_info = rover; return; } /* * get rid of old routes */ static void expire_routes() { struct routing_entry *rover; struct routing_entry **prover = &routing_info; struct timeval now; gettimeofday(&now, NULL); while((rover = *prover) != NULL) { if ((now.tv_sec - rover->access_time) > routing_timeout) { *prover = rover->next; dfree (rover, MDL); } else prover = &rover->next; } /* Reset the timer */ routing_timer.tv_sec = now.tv_sec + routing_timeout; routing_timer.tv_usec = now.tv_usec; } #endif Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/tree.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/tree.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/tree.c (revision 131136) @@ -1,4101 +1,4095 @@ /* tree.c Routines for manipulating parse trees... */ /* - * Copyright (c) 1995-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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: tree.c,v 1.101.2.7 2002/11/17 02:27:00 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: tree.c,v 1.101.2.9 2004/06/17 20:54:39 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #include struct binding_scope *global_scope; static int do_host_lookup PROTO ((struct data_string *, struct dns_host_entry *)); #ifdef NSUPDATE struct __res_state resolver_state; int resolver_inited = 0; #endif pair cons (car, cdr) caddr_t car; pair cdr; { pair foo = (pair)dmalloc (sizeof *foo, MDL); if (!foo) log_fatal ("no memory for cons."); foo -> car = car; foo -> cdr = cdr; return foo; } int make_const_option_cache (oc, buffer, data, len, option, file, line) struct option_cache **oc; struct buffer **buffer; u_int8_t *data; unsigned len; struct option *option; const char *file; int line; { struct buffer *bp; if (buffer) { bp = *buffer; *buffer = 0; } else { bp = (struct buffer *)0; if (!buffer_allocate (&bp, len, file, line)) { log_error ("%s(%d): can't allocate buffer.", file, line); return 0; } } if (!option_cache_allocate (oc, file, line)) { log_error ("%s(%d): can't allocate option cache.", file, line); buffer_dereference (&bp, file, line); return 0; } (*oc) -> data.len = len; (*oc) -> data.buffer = bp; (*oc) -> data.data = &bp -> data [0]; (*oc) -> data.terminated = 0; if (data) memcpy (&bp -> data [0], data, len); (*oc) -> option = option; return 1; } int make_host_lookup (expr, name) struct expression **expr; const char *name; { if (!expression_allocate (expr, MDL)) { log_error ("No memory for host lookup tree node."); return 0; } (*expr) -> op = expr_host_lookup; if (!enter_dns_host (&((*expr) -> data.host_lookup), name)) { expression_dereference (expr, MDL); return 0; } return 1; } int enter_dns_host (dh, name) struct dns_host_entry **dh; const char *name; { /* XXX This should really keep a hash table of hostnames XXX and just add a new reference to a hostname that XXX already exists, if possible, rather than creating XXX a new structure. */ if (!dns_host_entry_allocate (dh, name, MDL)) { log_error ("Can't allocate space for new host."); return 0; } return 1; } int make_const_data (struct expression **expr, const unsigned char *data, unsigned len, int terminated, int allocate, const char *file, int line) { struct expression *nt; if (!expression_allocate (expr, file, line)) { log_error ("No memory for make_const_data tree node."); return 0; } nt = *expr; if (len) { if (allocate) { if (!buffer_allocate (&nt -> data.const_data.buffer, len + terminated, file, line)) { log_error ("Can't allocate const_data buffer"); expression_dereference (expr, file, line); return 0; } nt -> data.const_data.data = &nt -> data.const_data.buffer -> data [0]; memcpy (nt -> data.const_data.buffer -> data, data, len + terminated); } else nt -> data.const_data.data = data; nt -> data.const_data.terminated = terminated; } else nt -> data.const_data.data = 0; nt -> op = expr_const_data; nt -> data.const_data.len = len; return 1; } int make_const_int (expr, val) struct expression **expr; unsigned long val; { if (!expression_allocate (expr, MDL)) { log_error ("No memory for make_const_int tree node."); return 0; } (*expr) -> op = expr_const_int; (*expr) -> data.const_int = val; return 1; } int make_concat (expr, left, right) struct expression **expr; struct expression *left, *right; { /* If we're concatenating a null tree to a non-null tree, just return the non-null tree; if both trees are null, return a null tree. */ if (!left) { if (!right) return 0; expression_reference (expr, right, MDL); return 1; } if (!right) { expression_reference (expr, left, MDL); return 1; } /* Otherwise, allocate a new node to concatenate the two. */ if (!expression_allocate (expr, MDL)) { log_error ("No memory for concatenation expression node."); return 0; } (*expr) -> op = expr_concat; expression_reference (&(*expr) -> data.concat [0], left, MDL); expression_reference (&(*expr) -> data.concat [1], right, MDL); return 1; } int make_encapsulation (expr, name) struct expression **expr; struct data_string *name; { /* Allocate a new node to store the encapsulation. */ if (!expression_allocate (expr, MDL)) { log_error ("No memory for encapsulation expression node."); return 0; } (*expr) -> op = expr_encapsulate; data_string_copy (&(*expr) -> data.encapsulate, name, MDL); return 1; } int make_substring (new, expr, offset, length) struct expression **new; struct expression *expr; struct expression *offset; struct expression *length; { /* Allocate an expression node to compute the substring. */ if (!expression_allocate (new, MDL)) { log_error ("no memory for substring expression."); return 0; } (*new) -> op = expr_substring; expression_reference (&(*new) -> data.substring.expr, expr, MDL); expression_reference (&(*new) -> data.substring.offset, offset, MDL); expression_reference (&(*new) -> data.substring.len, length, MDL); return 1; } int make_limit (new, expr, limit) struct expression **new; struct expression *expr; int limit; { struct expression *rv; /* Allocate a node to enforce a limit on evaluation. */ if (!expression_allocate (new, MDL)) log_error ("no memory for limit expression"); (*new) -> op = expr_substring; expression_reference (&(*new) -> data.substring.expr, expr, MDL); /* Offset is a constant 0. */ if (!expression_allocate (&(*new) -> data.substring.offset, MDL)) { log_error ("no memory for limit offset expression"); expression_dereference (new, MDL); return 0; } (*new) -> data.substring.offset -> op = expr_const_int; (*new) -> data.substring.offset -> data.const_int = 0; /* Length is a constant: the specified limit. */ if (!expression_allocate (&(*new) -> data.substring.len, MDL)) { log_error ("no memory for limit length expression"); expression_dereference (new, MDL); return 0; } (*new) -> data.substring.len -> op = expr_const_int; (*new) -> data.substring.len -> data.const_int = limit; return 1; } int option_cache (struct option_cache **oc, struct data_string *dp, struct expression *expr, struct option *option, const char *file, int line) { if (!option_cache_allocate (oc, file, line)) return 0; if (dp) data_string_copy (&(*oc) -> data, dp, file, line); if (expr) expression_reference (&(*oc) -> expression, expr, file, line); (*oc) -> option = option; return 1; } int make_let (result, name) struct executable_statement **result; const char *name; { if (!(executable_statement_allocate (result, MDL))) return 0; (*result) -> op = let_statement; (*result) -> data.let.name = dmalloc (strlen (name) + 1, MDL); if (!(*result) -> data.let.name) { executable_statement_dereference (result, MDL); return 0; } strcpy ((*result) -> data.let.name, name); return 1; } static int do_host_lookup (result, dns) struct data_string *result; struct dns_host_entry *dns; { struct hostent *h; unsigned i, count; unsigned new_len; #ifdef DEBUG_EVAL log_debug ("time: now = %d dns = %d diff = %d", cur_time, dns -> timeout, cur_time - dns -> timeout); #endif /* If the record hasn't timed out, just copy the data and return. */ if (cur_time <= dns -> timeout) { #ifdef DEBUG_EVAL log_debug ("easy copy: %d %s", dns -> data.len, (dns -> data.len > 4 ? inet_ntoa (*(struct in_addr *)(dns -> data.data)) : 0)); #endif data_string_copy (result, &dns -> data, MDL); return 1; } #ifdef DEBUG_EVAL log_debug ("Looking up %s", dns -> hostname); #endif /* Otherwise, look it up... */ h = gethostbyname (dns -> hostname); if (!h) { #ifndef NO_H_ERRNO switch (h_errno) { case HOST_NOT_FOUND: #endif log_error ("%s: host unknown.", dns -> hostname); #ifndef NO_H_ERRNO break; case TRY_AGAIN: log_error ("%s: temporary name server failure", dns -> hostname); break; case NO_RECOVERY: log_error ("%s: name server failed", dns -> hostname); break; case NO_DATA: log_error ("%s: no A record associated with address", dns -> hostname); } #endif /* !NO_H_ERRNO */ /* Okay to try again after a minute. */ dns -> timeout = cur_time + 60; data_string_forget (&dns -> data, MDL); return 0; } #ifdef DEBUG_EVAL log_debug ("Lookup succeeded; first address is %s", inet_ntoa (h -> h_addr_list [0])); #endif /* Count the number of addresses we got... */ for (count = 0; h -> h_addr_list [count]; count++) ; /* Dereference the old data, if any. */ data_string_forget (&dns -> data, MDL); /* Do we need to allocate more memory? */ new_len = count * h -> h_length; if (!buffer_allocate (&dns -> data.buffer, new_len, MDL)) { log_error ("No memory for %s.", dns -> hostname); return 0; } dns -> data.data = &dns -> data.buffer -> data [0]; dns -> data.len = new_len; dns -> data.terminated = 0; /* Addresses are conveniently stored one to the buffer, so we have to copy them out one at a time... :'( */ for (i = 0; i < count; i++) { memcpy (&dns -> data.buffer -> data [h -> h_length * i], h -> h_addr_list [i], (unsigned)(h -> h_length)); } #ifdef DEBUG_EVAL log_debug ("dns -> data: %x h -> h_addr_list [0]: %x", *(int *)(dns -> buffer), h -> h_addr_list [0]); #endif /* XXX Set the timeout for an hour from now. XXX This should really use the time on the DNS reply. */ dns -> timeout = cur_time + 3600; #ifdef DEBUG_EVAL log_debug ("hard copy: %d %s", dns -> data.len, (dns -> data.len > 4 ? inet_ntoa (*(struct in_addr *)(dns -> data.data)) : 0)); #endif data_string_copy (result, &dns -> data, MDL); return 1; } int evaluate_expression (result, packet, lease, client_state, in_options, cfg_options, scope, expr, file, line) struct binding_value **result; 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 expression *expr; const char *file; int line; { struct binding_value *bv; int status; struct binding *binding; bv = (struct binding_value *)0; if (expr -> op == expr_variable_reference) { if (!scope || !*scope) return 0; binding = find_binding (*scope, expr -> data.variable); if (binding && binding -> value) { if (result) binding_value_reference (result, binding -> value, file, line); return 1; } else return 0; } else if (expr -> op == expr_funcall) { struct string_list *s; struct expression *arg; struct binding_scope *ns; struct binding *nb; if (!scope || !*scope) { log_error ("%s: no such function.", expr -> data.funcall.name); return 0; } binding = find_binding (*scope, expr -> data.funcall.name); if (!binding || !binding -> value) { log_error ("%s: no such function.", expr -> data.funcall.name); return 0; } if (binding -> value -> type != binding_function) { log_error ("%s: not a function.", expr -> data.funcall.name); return 0; } /* Create a new binding scope in which to define the arguments to the function. */ ns = (struct binding_scope *)0; if (!binding_scope_allocate (&ns, MDL)) { log_error ("%s: can't allocate argument scope.", expr -> data.funcall.name); return 0; } arg = expr -> data.funcall.arglist; s = binding -> value -> value.fundef -> args; while (arg && s) { nb = dmalloc (sizeof *nb, MDL); if (!nb) { blb: binding_scope_dereference (&ns, MDL); return 0; } else { memset (nb, 0, sizeof *nb); nb -> name = dmalloc (strlen (s -> string) + 1, MDL); if (nb -> name) strcpy (nb -> name, s -> string); else { dfree (nb, MDL); nb = (struct binding *)0; goto blb; } } evaluate_expression (&nb -> value, packet, lease, client_state, in_options, cfg_options, scope, arg -> data.arg.val, file, line); nb -> next = ns -> bindings; ns -> bindings = nb; arg = arg -> data.arg.next; s = s -> next; } if (arg) { log_error ("%s: too many arguments.", expr -> data.funcall.name); binding_scope_dereference (&ns, MDL); return 0; } if (s) { log_error ("%s: too few arguments.", expr -> data.funcall.name); binding_scope_dereference (&ns, MDL); return 0; } if (scope && *scope) binding_scope_reference (&ns -> outer, *scope, MDL); status = (execute_statements (&bv, packet, lease, client_state, in_options, cfg_options, &ns, binding -> value -> value.fundef -> statements)); binding_scope_dereference (&ns, MDL); if (!bv) return 1; } else if (is_boolean_expression (expr)) { if (!binding_value_allocate (&bv, MDL)) return 0; bv -> type = binding_boolean; status = (evaluate_boolean_expression (&bv -> value.boolean, packet, lease, client_state, in_options, cfg_options, scope, expr)); } else if (is_numeric_expression (expr)) { if (!binding_value_allocate (&bv, MDL)) return 0; bv -> type = binding_numeric; status = (evaluate_numeric_expression (&bv -> value.intval, packet, lease, client_state, in_options, cfg_options, scope, expr)); } else if (is_data_expression (expr)) { if (!binding_value_allocate (&bv, MDL)) return 0; bv -> type = binding_data; status = (evaluate_data_expression (&bv -> value.data, packet, lease, client_state, in_options, cfg_options, scope, expr, MDL)); } else if (is_dns_expression (expr)) { #if defined (NSUPDATE) if (!binding_value_allocate (&bv, MDL)) return 0; bv -> type = binding_dns; status = (evaluate_dns_expression (&bv -> value.dns, packet, lease, client_state, in_options, cfg_options, scope, expr)); #endif } else { log_error ("%s: invalid expression type: %d", "evaluate_expression", expr -> op); return 0; } if (result && status) binding_value_reference (result, bv, file, line); binding_value_dereference (&bv, MDL); return status; } int binding_value_dereference (struct binding_value **v, const char *file, int line) { struct binding_value *bv = *v; *v = (struct binding_value *)0; /* Decrement the reference count. If it's nonzero, we're done. */ --(bv -> refcnt); rc_register (file, line, v, bv, bv -> refcnt, 1, RC_MISC); if (bv -> refcnt > 0) return 1; if (bv -> refcnt < 0) { log_error ("%s(%d): negative refcnt!", file, line); #if defined (DEBUG_RC_HISTORY) dump_rc_history (bv); #endif #if defined (POINTER_DEBUG) abort (); #else return 0; #endif } switch (bv -> type) { case binding_boolean: case binding_numeric: break; case binding_data: if (bv -> value.data.buffer) data_string_forget (&bv -> value.data, file, line); break; case binding_dns: #if defined (NSUPDATE) if (bv -> value.dns) { if (bv -> value.dns -> r_data) { dfree (bv -> value.dns -> r_data_ephem, MDL); bv -> value.dns -> r_data = (unsigned char *)0; bv -> value.dns -> r_data_ephem = (unsigned char *)0; } minires_freeupdrec (bv -> value.dns); } break; #endif default: log_error ("%s(%d): invalid binding type: %d", file, line, bv -> type); return 0; } dfree (bv, file, line); return 1; } #if defined (NSUPDATE) int evaluate_dns_expression (result, packet, lease, client_state, in_options, cfg_options, scope, expr) ns_updrec **result; 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 expression *expr; { ns_updrec *foo; unsigned long ttl = 0; char *tname; struct data_string name, data; int r0, r1, r2, r3; if (!result || *result) { log_error ("evaluate_dns_expression called with non-null %s", "result pointer"); #if defined (POINTER_DEBUG) abort (); #else return 0; #endif } switch (expr -> op) { #if defined (NSUPDATE) case expr_ns_add: r0 = evaluate_numeric_expression (&ttl, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.ns_add.ttl); goto nsfinish; case expr_ns_exists: ttl = 1; case expr_ns_delete: case expr_ns_not_exists: r0 = 1; nsfinish: memset (&name, 0, sizeof name); r1 = evaluate_data_expression (&name, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.ns_add.rrname, MDL); if (r1) { /* The result of the evaluation may or may not be NUL-terminated, but we need it terminated for sure, so we have to allocate a buffer and terminate it. */ tname = dmalloc (name.len + 1, MDL); if (!tname) { r2 = 0; r1 = 0; data_string_forget (&name, MDL); } else { memcpy (tname, name.data, name.len); tname [name.len] = 0; memset (&data, 0, sizeof data); r2 = evaluate_data_expression (&data, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.ns_add.rrdata, MDL); } } else r2 = 0; if (r0 && r1 && (r2 || expr -> op != expr_ns_add)) { *result = minires_mkupdrec (((expr -> op == expr_ns_add || expr -> op == expr_ns_delete) ? S_UPDATE : S_PREREQ), tname, expr -> data.ns_add.rrclass, expr -> data.ns_add.rrtype, ttl); if (!*result) { ngood: if (r2) { data_string_forget (&data, MDL); r2 = 0; } } else { if (data.len) { /* As a special case, if we get exactly four bytes of data, it's an IP address represented as a 32-bit quantity, which is actually what we *should* be getting here. Because res_mkupdrec is currently broken and expects a dotted quad, convert it. This should be fixed when the new resolver is merged. */ if (data.len == 4) { (*result) -> r_data_ephem = dmalloc (16, MDL); if (!(*result) -> r_data_ephem) goto dpngood; (*result) -> r_data = (*result) -> r_data_ephem; + /*%Audit% 16 bytes max. %2004.06.17,Safe%*/ sprintf ((char *)(*result) -> r_data_ephem, - "%d.%d.%d.%d", - data.data [0], data.data [1], - data.data [2], data.data [3]); + "%u.%u.%u.%u", + data.data [0] & 0xff, + data.data [1] & 0xff, + data.data [2] & 0xff, + data.data [3] & 0xff); (*result) -> r_size = strlen ((const char *) (*result) -> r_data); } else { (*result) -> r_size = data.len; (*result) -> r_data_ephem = dmalloc (data.len, MDL); if (!(*result) -> r_data_ephem) { dpngood: /* double plus ungood. */ minires_freeupdrec (*result); *result = 0; goto ngood; } (*result) -> r_data = (*result) -> r_data_ephem; memcpy ((*result) -> r_data_ephem, data.data, data.len); } } else { (*result) -> r_data = 0; (*result) -> r_size = 0; } switch (expr -> op) { case expr_ns_add: (*result) -> r_opcode = ADD; break; case expr_ns_delete: (*result) -> r_opcode = DELETE; break; case expr_ns_exists: (*result) -> r_opcode = YXRRSET; break; case expr_ns_not_exists: (*result) -> r_opcode = NXRRSET; break; /* Can't happen, but satisfy gcc. */ default: break; } } } if (r1) { data_string_forget (&name, MDL); dfree (tname, MDL); } if (r2) data_string_forget (&data, MDL); /* One flaw in the thinking here: an IP address and an ASCII string both look like data expressions, but for A records, we want an ASCII string, not a binary IP address. Do I need to turn binary IP addresses into a seperate type? */ return (r0 && r1 && (r2 || expr -> op != expr_ns_add) && *result); #else case expr_ns_add: case expr_ns_delete: case expr_ns_exists: case expr_ns_not_exists: return 0; #endif case expr_funcall: log_error ("%s: dns values for functions not supported.", expr -> data.funcall.name); break; case expr_variable_reference: log_error ("%s: dns values for variables not supported.", expr -> data.variable); break; case expr_check: case expr_equal: case expr_not_equal: case expr_and: case expr_or: case expr_not: case expr_match: case expr_static: case expr_known: case expr_exists: case expr_variable_exists: log_error ("Boolean opcode in evaluate_dns_expression: %d", expr -> op); return 0; case expr_none: case expr_substring: case expr_suffix: case expr_option: case expr_hardware: case expr_const_data: case expr_packet: case expr_concat: case expr_encapsulate: case expr_host_lookup: case expr_encode_int8: case expr_encode_int16: case expr_encode_int32: case expr_binary_to_ascii: case expr_reverse: case expr_filename: case expr_sname: case expr_pick_first_value: case expr_host_decl_name: case expr_config_option: case expr_leased_address: case expr_null: log_error ("Data opcode in evaluate_dns_expression: %d", expr -> op); return 0; case expr_extract_int8: case expr_extract_int16: case expr_extract_int32: case expr_const_int: case expr_lease_time: case expr_dns_transaction: case expr_add: case expr_subtract: case expr_multiply: case expr_divide: case expr_remainder: case expr_binary_and: case expr_binary_or: case expr_binary_xor: case expr_client_state: log_error ("Numeric opcode in evaluate_dns_expression: %d", expr -> op); return 0; case expr_function: log_error ("Function opcode in evaluate_dns_expression: %d", expr -> op); return 0; case expr_arg: break; } log_error ("Bogus opcode in evaluate_dns_expression: %d", expr -> op); return 0; } #endif /* defined (NSUPDATE) */ int evaluate_boolean_expression (result, packet, lease, client_state, in_options, cfg_options, scope, expr) int *result; 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 expression *expr; { struct data_string left, right; struct data_string rrtype, rrname, rrdata; unsigned long ttl; int srrtype, srrname, srrdata, sttl; int bleft, bright; int sleft, sright; struct binding *binding; struct binding_value *bv, *obv; switch (expr -> op) { case expr_check: *result = check_collection (packet, lease, expr -> data.check); #if defined (DEBUG_EXPRESSIONS) log_debug ("bool: check (%s) returns %s", expr -> data.check -> name, *result ? "true" : "false"); #endif return 1; case expr_equal: case expr_not_equal: bv = obv = (struct binding_value *)0; sleft = evaluate_expression (&bv, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.equal [0], MDL); sright = evaluate_expression (&obv, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.equal [1], MDL); if (sleft && sright) { if (bv -> type != obv -> type) *result = expr -> op == expr_not_equal; else { switch (obv -> type) { case binding_boolean: if (bv -> value.boolean == obv -> value.boolean) *result = expr -> op == expr_equal; else *result = expr -> op == expr_not_equal; break; case binding_data: if ((bv -> value.data.len == obv -> value.data.len) && !memcmp (bv -> value.data.data, obv -> value.data.data, obv -> value.data.len)) *result = expr -> op == expr_equal; else *result = expr -> op == expr_not_equal; break; case binding_numeric: if (bv -> value.intval == obv -> value.intval) *result = expr -> op == expr_equal; else *result = expr -> op == expr_not_equal; break; case binding_dns: #if defined (NSUPDATE) /* XXX This should be a comparison for equal XXX values, not for identity. */ if (bv -> value.dns == obv -> value.dns) *result = expr -> op == expr_equal; else *result = expr -> op == expr_not_equal; #else *result = expr -> op == expr_not_equal; #endif break; case binding_function: if (bv -> value.fundef == obv -> value.fundef) *result = expr -> op == expr_equal; else *result = expr -> op == expr_not_equal; break; default: *result = expr -> op == expr_not_equal; break; } } } else if (!sleft && !sright) *result = expr -> op == expr_equal; else *result = expr -> op == expr_not_equal; #if defined (DEBUG_EXPRESSIONS) log_debug ("bool: %sequal = %s", expr -> op == expr_not_equal ? "not" : "", (*result ? "true" : "false")); #endif if (sleft) binding_value_dereference (&bv, MDL); if (sright) binding_value_dereference (&obv, MDL); return 1; case expr_and: sleft = evaluate_boolean_expression (&bleft, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.and [0]); if (sleft && bleft) sright = evaluate_boolean_expression (&bright, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.and [1]); else sright = bright = 0; #if defined (DEBUG_EXPRESSIONS) log_debug ("bool: and (%s, %s) = %s", sleft ? (bleft ? "true" : "false") : "NULL", sright ? (bright ? "true" : "false") : "NULL", ((sleft && sright) ? (bleft && bright ? "true" : "false") : "NULL")); #endif if (sleft && sright) { *result = bleft && bright; return 1; } return 0; case expr_or: bleft = bright = 0; sleft = evaluate_boolean_expression (&bleft, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.or [0]); if (!sleft || !bleft) sright = evaluate_boolean_expression (&bright, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.or [1]); else sright = 0; #if defined (DEBUG_EXPRESSIONS) log_debug ("bool: or (%s, %s) = %s", sleft ? (bleft ? "true" : "false") : "NULL", sright ? (bright ? "true" : "false") : "NULL", ((sleft || sright) ? (bleft || bright ? "true" : "false") : "NULL")); #endif if (sleft || sright) { *result = bleft || bright; return 1; } return 0; case expr_not: sleft = evaluate_boolean_expression (&bleft, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.not); #if defined (DEBUG_EXPRESSIONS) log_debug ("bool: not (%s) = %s", sleft ? (bleft ? "true" : "false") : "NULL", ((sleft && sright) ? (!bleft ? "true" : "false") : "NULL")); #endif if (sleft) { *result = !bleft; return 1; } return 0; case expr_exists: memset (&left, 0, sizeof left); if (!in_options || !get_option (&left, expr -> data.exists -> universe, packet, lease, client_state, in_options, cfg_options, in_options, scope, expr -> data.exists -> code, MDL)) *result = 0; else { *result = 1; data_string_forget (&left, MDL); } #if defined (DEBUG_EXPRESSIONS) log_debug ("bool: exists %s.%s = %s", expr -> data.option -> universe -> name, expr -> data.option -> name, *result ? "true" : "false"); #endif return 1; case expr_known: if (!packet) { #if defined (DEBUG_EXPRESSIONS) log_debug ("bool: known = NULL"); #endif return 0; } #if defined (DEBUG_EXPRESSIONS) log_debug ("bool: known = %s", packet -> known ? "true" : "false"); #endif *result = packet -> known; return 1; case expr_static: if (!lease || !(lease -> flags & STATIC_LEASE)) { #if defined (DEBUG_EXPRESSIONS) log_debug ("bool: static = false (%s %s %s %d)", lease ? "y" : "n", (lease && (lease -> flags & STATIC_LEASE) ? "y" : "n"), piaddr (lease -> ip_addr), lease ? lease -> flags : 0); #endif *result = 0; return 1; } #if defined (DEBUG_EXPRESSIONS) log_debug ("bool: static = true"); #endif *result = 1; return 1; case expr_variable_exists: if (scope && *scope) { binding = find_binding (*scope, expr -> data.variable); if (binding) { if (binding -> value) *result = 1; else *result = 0; } else *result = 0; } else *result = 0; #if defined (DEBUG_EXPRESSIONS) log_debug ("boolean: %s? = %s", expr -> data.variable, *result ? "true" : "false"); #endif return 1; case expr_variable_reference: if (scope && *scope) { binding = find_binding (*scope, expr -> data.variable); if (binding && binding -> value) { if (binding -> value -> type == binding_boolean) { *result = binding -> value -> value.boolean; sleft = 1; } else { log_error ("binding type %d in %s.", binding -> value -> type, "evaluate_boolean_expression"); sleft = 0; } } else sleft = 0; } else sleft = 0; #if defined (DEBUG_EXPRESSIONS) log_debug ("boolean: %s = %s", expr -> data.variable, sleft ? (*result ? "true" : "false") : "NULL"); #endif return sleft; case expr_funcall: bv = (struct binding_value *)0; sleft = evaluate_expression (&bv, packet, lease, client_state, in_options, cfg_options, scope, expr, MDL); if (sleft) { if (bv -> type != binding_boolean) log_error ("%s() returned type %d in %s.", expr -> data.funcall.name, bv -> type, "evaluate_boolean_expression"); else *result = bv -> value.boolean; binding_value_dereference (&bv, MDL); } #if defined (DEBUG_EXPRESSIONS) log_debug ("boolean: %s() = %s", expr -> data.funcall.name, sleft ? (*result ? "true" : "false") : "NULL"); #endif break; case expr_none: case expr_match: case expr_substring: case expr_suffix: case expr_option: case expr_hardware: case expr_const_data: case expr_packet: case expr_concat: case expr_encapsulate: case expr_host_lookup: case expr_encode_int8: case expr_encode_int16: case expr_encode_int32: case expr_binary_to_ascii: case expr_reverse: case expr_pick_first_value: case expr_host_decl_name: case expr_config_option: case expr_leased_address: case expr_null: case expr_filename: case expr_sname: log_error ("Data opcode in evaluate_boolean_expression: %d", expr -> op); return 0; case expr_extract_int8: case expr_extract_int16: case expr_extract_int32: case expr_const_int: case expr_lease_time: case expr_dns_transaction: case expr_add: case expr_subtract: case expr_multiply: case expr_divide: case expr_remainder: case expr_binary_and: case expr_binary_or: case expr_binary_xor: case expr_client_state: log_error ("Numeric opcode in evaluate_boolean_expression: %d", expr -> op); return 0; case expr_ns_add: case expr_ns_delete: case expr_ns_exists: case expr_ns_not_exists: log_error ("dns opcode in evaluate_boolean_expression: %d", expr -> op); return 0; case expr_function: log_error ("function definition in evaluate_boolean_expr"); return 0; case expr_arg: break; } log_error ("Bogus opcode in evaluate_boolean_expression: %d", expr -> op); return 0; } int evaluate_data_expression (result, packet, lease, client_state, in_options, cfg_options, scope, expr, file, line) struct data_string *result; 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 expression *expr; const char *file; int line; { struct data_string data, other; unsigned long offset, len, i; int s0, s1, s2, s3; int status; struct binding *binding; char *s; struct binding_value *bv; switch (expr -> op) { /* Extract N bytes starting at byte M of a data string. */ case expr_substring: memset (&data, 0, sizeof data); s0 = evaluate_data_expression (&data, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.substring.expr, MDL); /* Evaluate the offset and length. */ s1 = evaluate_numeric_expression (&offset, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.substring.offset); s2 = evaluate_numeric_expression (&len, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.substring.len); if (s0 && s1 && s2) { /* If the offset is after end of the string, return an empty string. Otherwise, do the adjustments and return what's left. */ if (data.len > offset) { data_string_copy (result, &data, file, line); result -> len -= offset; if (result -> len > len) { result -> len = len; result -> terminated = 0; } result -> data += offset; } s3 = 1; } else s3 = 0; #if defined (DEBUG_EXPRESSIONS) log_debug ("data: substring (%s, %s, %s) = %s", s0 ? print_hex_1 (data.len, data.data, 30) : "NULL", s1 ? print_dec_1 (offset) : "NULL", s2 ? print_dec_2 (len) : "NULL", (s3 ? print_hex_2 (result -> len, result -> data, 30) : "NULL")); #endif if (s0) data_string_forget (&data, MDL); if (s3) return 1; return 0; /* Extract the last N bytes of a data string. */ case expr_suffix: memset (&data, 0, sizeof data); s0 = evaluate_data_expression (&data, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.suffix.expr, MDL); /* Evaluate the length. */ s1 = evaluate_numeric_expression (&len, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.suffix.len); if (s0 && s1) { data_string_copy (result, &data, file, line); /* If we are returning the last N bytes of a string whose length is <= N, just return the string - otherwise, compute a new starting address and decrease the length. */ if (data.len > len) { result -> data += data.len - len; result -> len = len; } data_string_forget (&data, MDL); } #if defined (DEBUG_EXPRESSIONS) log_debug ("data: suffix (%s, %s) = %s", s0 ? print_hex_1 (data.len, data.data, 30) : "NULL", s1 ? print_dec_1 (len) : "NULL", ((s0 && s1) ? print_hex_2 (result -> len, result -> data, 30) : "NULL")); #endif return s0 && s1; /* Extract an option. */ case expr_option: if (in_options) s0 = get_option (result, expr -> data.option -> universe, packet, lease, client_state, in_options, cfg_options, in_options, scope, expr -> data.option -> code, file, line); else s0 = 0; #if defined (DEBUG_EXPRESSIONS) log_debug ("data: option %s.%s = %s", expr -> data.option -> universe -> name, expr -> data.option -> name, s0 ? print_hex_1 (result -> len, result -> data, 60) : "NULL"); #endif return s0; case expr_config_option: if (cfg_options) s0 = get_option (result, expr -> data.option -> universe, packet, lease, client_state, in_options, cfg_options, cfg_options, scope, expr -> data.option -> code, file, line); else s0 = 0; #if defined (DEBUG_EXPRESSIONS) log_debug ("data: config-option %s.%s = %s", expr -> data.option -> universe -> name, expr -> data.option -> name, s0 ? print_hex_1 (result -> len, result -> data, 60) : "NULL"); #endif return s0; /* Combine the hardware type and address. */ case expr_hardware: /* On the client, hardware is our hardware. */ if (client_state) { memset (result, 0, sizeof *result); result -> data = client_state -> interface -> hw_address.hbuf; result -> len = client_state -> interface -> hw_address.hlen; #if defined (DEBUG_EXPRESSIONS) log_debug ("data: hardware = %s", print_hex_1 (result -> len, result -> data, 60)); #endif return 1; } /* The server cares about the client's hardware address, so only in the case where we are examining a packet can we return anything. */ if (!packet || !packet -> raw) { log_error ("data: hardware: raw packet not available"); return 0; } if (packet -> raw -> hlen > sizeof packet -> raw -> chaddr) { log_error ("data: hardware: invalid hlen (%d)\n", packet -> raw -> hlen); return 0; } result -> len = packet -> raw -> hlen + 1; if (buffer_allocate (&result -> buffer, result -> len, file, line)) { result -> data = &result -> buffer -> data [0]; result -> buffer -> data [0] = packet -> raw -> htype; memcpy (&result -> buffer -> data [1], packet -> raw -> chaddr, packet -> raw -> hlen); result -> terminated = 0; } else { log_error ("data: hardware: no memory for buffer."); return 0; } #if defined (DEBUG_EXPRESSIONS) log_debug ("data: hardware = %s", print_hex_1 (result -> len, result -> data, 60)); #endif return 1; /* Extract part of the raw packet. */ case expr_packet: if (!packet || !packet -> raw) { log_error ("data: packet: raw packet not available"); return 0; } s0 = evaluate_numeric_expression (&offset, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.packet.offset); s1 = evaluate_numeric_expression (&len, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.packet.len); if (s0 && s1 && offset < packet -> packet_length) { if (offset + len > packet -> packet_length) result -> len = packet -> packet_length - offset; else result -> len = len; if (buffer_allocate (&result -> buffer, result -> len, file, line)) { result -> data = &result -> buffer -> data [0]; memcpy (result -> buffer -> data, (((unsigned char *)(packet -> raw)) + offset), result -> len); result -> terminated = 0; } else { log_error ("data: packet: no buffer memory."); return 0; } s2 = 1; } else s2 = 0; #if defined (DEBUG_EXPRESSIONS) log_debug ("data: packet (%ld, %ld) = %s", offset, len, s2 ? print_hex_1 (result -> len, result -> data, 60) : NULL); #endif return s2; /* The encapsulation of all defined options in an option space... */ case expr_encapsulate: if (cfg_options) s0 = option_space_encapsulate (result, packet, lease, client_state, in_options, cfg_options, scope, &expr -> data.encapsulate); else s0 = 0; #if defined (DEBUG_EXPRESSIONS) log_debug ("data: encapsulate (%s) = %s", expr -> data.encapsulate.data, s0 ? print_hex_1 (result -> len, result -> data, 60) : "NULL"); #endif return s0; /* Some constant data... */ case expr_const_data: #if defined (DEBUG_EXPRESSIONS) log_debug ("data: const = %s", print_hex_1 (expr -> data.const_data.len, expr -> data.const_data.data, 60)); #endif data_string_copy (result, &expr -> data.const_data, file, line); return 1; /* Hostname lookup... */ case expr_host_lookup: s0 = do_host_lookup (result, expr -> data.host_lookup); #if defined (DEBUG_EXPRESSIONS) log_debug ("data: DNS lookup (%s) = %s", expr -> data.host_lookup -> hostname, (s0 ? print_dotted_quads (result -> len, result -> data) : "NULL")); #endif return s0; /* Concatenation... */ case expr_concat: memset (&data, 0, sizeof data); s0 = evaluate_data_expression (&data, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.concat [0], MDL); memset (&other, 0, sizeof other); s1 = evaluate_data_expression (&other, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.concat [1], MDL); if (s0 && s1) { result -> len = data.len + other.len; if (!buffer_allocate (&result -> buffer, (result -> len + other.terminated), file, line)) { log_error ("data: concat: no memory"); result -> len = 0; data_string_forget (&data, MDL); data_string_forget (&other, MDL); return 0; } result -> data = &result -> buffer -> data [0]; memcpy (result -> buffer -> data, data.data, data.len); memcpy (&result -> buffer -> data [data.len], other.data, other.len + other.terminated); } if (s0) data_string_forget (&data, MDL); if (s1) data_string_forget (&other, MDL); #if defined (DEBUG_EXPRESSIONS) log_debug ("data: concat (%s, %s) = %s", s0 ? print_hex_1 (data.len, data.data, 20) : "NULL", s1 ? print_hex_2 (other.len, other.data, 20) : "NULL", ((s0 && s1) ? print_hex_3 (result -> len, result -> data, 30) : "NULL")); #endif return s0 && s1; case expr_encode_int8: s0 = evaluate_numeric_expression (&len, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.encode_int); if (s0) { result -> len = 1; if (!buffer_allocate (&result -> buffer, 1, file, line)) { log_error ("data: encode_int8: no memory"); result -> len = 0; s0 = 0; } else { result -> data = &result -> buffer -> data [0]; result -> buffer -> data [0] = len; } } else result -> len = 0; #if defined (DEBUG_EXPRESSIONS) if (!s0) log_debug ("data: encode_int8 (NULL) = NULL"); else log_debug ("data: encode_int8 (%ld) = %s", len, print_hex_2 (result -> len, result -> data, 20)); #endif return s0; case expr_encode_int16: s0 = evaluate_numeric_expression (&len, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.encode_int); if (s0) { result -> len = 2; if (!buffer_allocate (&result -> buffer, 2, file, line)) { log_error ("data: encode_int16: no memory"); result -> len = 0; s0 = 0; } else { result -> data = &result -> buffer -> data [0]; putUShort (result -> buffer -> data, len); } } else result -> len = 0; #if defined (DEBUG_EXPRESSIONS) if (!s0) log_debug ("data: encode_int16 (NULL) = NULL"); else log_debug ("data: encode_int16 (%ld) = %s", len, print_hex_2 (result -> len, result -> data, 20)); #endif return s0; case expr_encode_int32: s0 = evaluate_numeric_expression (&len, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.encode_int); if (s0) { result -> len = 4; if (!buffer_allocate (&result -> buffer, 4, file, line)) { log_error ("data: encode_int32: no memory"); result -> len = 0; s0 = 0; } else { result -> data = &result -> buffer -> data [0]; putULong (result -> buffer -> data, len); } } else result -> len = 0; #if defined (DEBUG_EXPRESSIONS) if (!s0) log_debug ("data: encode_int32 (NULL) = NULL"); else log_debug ("data: encode_int32 (%ld) = %s", len, print_hex_2 (result -> len, result -> data, 20)); #endif return s0; case expr_binary_to_ascii: /* Evaluate the base (offset) and width (len): */ s0 = evaluate_numeric_expression (&offset, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.b2a.base); s1 = evaluate_numeric_expression (&len, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.b2a.width); /* Evaluate the seperator string. */ memset (&data, 0, sizeof data); s2 = evaluate_data_expression (&data, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.b2a.seperator, MDL); /* Evaluate the data to be converted. */ memset (&other, 0, sizeof other); s3 = evaluate_data_expression (&other, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.b2a.buffer, MDL); if (s0 && s1 && s2 && s3) { unsigned buflen, i; if (len != 8 && len != 16 && len != 32) { log_info ("binary_to_ascii: %s %ld!", "invalid width", len); goto b2a_out; } len /= 8; /* The buffer must be a multiple of the number's width. */ if (other.len % len) { log_info ("binary-to-ascii: %s %d %s %ld!", "length of buffer", other.len, "not a multiple of width", len); status = 0; goto b2a_out; } /* Count the width of the output. */ buflen = 0; for (i = 0; i < other.len; i += len) { if (len == 1) { if (offset == 8) { if (other.data [i] < 8) buflen++; else if (other.data [i] < 64) buflen += 2; else buflen += 3; } else if (offset == 10) { if (other.data [i] < 10) buflen++; else if (other.data [i] < 100) buflen += 2; else buflen += 3; } else if (offset == 16) { if (other.data [i] < 16) buflen++; else buflen += 2; } else buflen += (converted_length (&other.data [i], offset, 1)); } else buflen += (converted_length (&other.data [i], offset, len)); if (i + len != other.len) buflen += data.len; } if (!buffer_allocate (&result -> buffer, buflen + 1, file, line)) { log_error ("data: binary-to-ascii: no memory"); status = 0; goto b2a_out; } result -> data = &result -> buffer -> data [0]; result -> len = buflen; result -> terminated = 1; buflen = 0; for (i = 0; i < other.len; i += len) { buflen += (binary_to_ascii (&result -> buffer -> data [buflen], &other.data [i], offset, len)); if (i + len != other.len) { memcpy (&result -> buffer -> data [buflen], data.data, data.len); buflen += data.len; } } /* NUL terminate. */ result -> buffer -> data [buflen] = 0; status = 1; } else status = 0; b2a_out: #if defined (DEBUG_EXPRESSIONS) log_debug ("data: binary-to-ascii (%s, %s, %s, %s) = %s", s0 ? print_dec_1 (offset) : "NULL", s1 ? print_dec_2 (len) : "NULL", s2 ? print_hex_1 (data.len, data.data, 30) : "NULL", s3 ? print_hex_2 (other.len, other.data, 30) : "NULL", (status ? print_hex_3 (result -> len, result -> data, 30) : "NULL")); #endif if (s2) data_string_forget (&data, MDL); if (s3) data_string_forget (&other, MDL); if (status) return 1; return 0; case expr_reverse: /* Evaluate the width (len): */ s0 = evaluate_numeric_expression (&len, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.reverse.width); /* Evaluate the data. */ memset (&data, 0, sizeof data); s1 = evaluate_data_expression (&data, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.reverse.buffer, MDL); if (s0 && s1) { char *upper; int i; /* The buffer must be a multiple of the number's width. */ if (data.len % len) { log_info ("reverse: %s %d %s %ld!", "length of buffer", data.len, "not a multiple of width", len); status = 0; goto reverse_out; } /* XXX reverse in place? I don't think we can. */ if (!buffer_allocate (&result -> buffer, data.len, file, line)) { log_error ("data: reverse: no memory"); status = 0; goto reverse_out; } result -> data = &result -> buffer -> data [0]; result -> len = data.len; result -> terminated = 0; for (i = 0; i < data.len; i += len) { memcpy (&result -> buffer -> data [i], &data.data [data.len - i - len], len); } status = 1; } else status = 0; reverse_out: #if defined (DEBUG_EXPRESSIONS) log_debug ("data: reverse (%s, %s) = %s", s0 ? print_dec_1 (len) : "NULL", s1 ? print_hex_1 (data.len, data.data, 30) : "NULL", (status ? print_hex_3 (result -> len, result -> data, 30) : "NULL")); #endif if (s0) data_string_forget (&data, MDL); if (status) return 1; return 0; case expr_leased_address: if (!lease) { log_error ("data: leased_address: not available"); return 0; } result -> len = lease -> ip_addr.len; if (buffer_allocate (&result -> buffer, result -> len, file, line)) { result -> data = &result -> buffer -> data [0]; memcpy (&result -> buffer -> data [0], lease -> ip_addr.iabuf, lease -> ip_addr.len); result -> terminated = 0; } else { log_error ("data: leased-address: no memory."); return 0; } #if defined (DEBUG_EXPRESSIONS) log_debug ("data: leased-address = %s", print_hex_1 (result -> len, result -> data, 60)); #endif return 1; case expr_pick_first_value: memset (&data, 0, sizeof data); if ((evaluate_data_expression (result, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.pick_first_value.car, MDL))) { #if defined (DEBUG_EXPRESSIONS) log_debug ("data: pick_first_value (%s, xxx)", print_hex_1 (result -> len, result -> data, 40)); #endif return 1; } if (expr -> data.pick_first_value.cdr && (evaluate_data_expression (result, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.pick_first_value.cdr, MDL))) { #if defined (DEBUG_EXPRESSIONS) log_debug ("data: pick_first_value (NULL, %s)", print_hex_1 (result -> len, result -> data, 40)); #endif return 1; } #if defined (DEBUG_EXPRESSIONS) log_debug ("data: pick_first_value (NULL, NULL) = NULL"); #endif return 0; case expr_host_decl_name: if (!lease || !lease -> host) { log_error ("data: host_decl_name: not available"); return 0; } result -> len = strlen (lease -> host -> name); if (buffer_allocate (&result -> buffer, result -> len + 1, file, line)) { result -> data = &result -> buffer -> data [0]; strcpy ((char *)&result -> buffer -> data [0], lease -> host -> name); result -> terminated = 1; } else { log_error ("data: host-decl-name: no memory."); return 0; } #if defined (DEBUG_EXPRESSIONS) log_debug ("data: host-decl-name = %s", lease -> host -> name); #endif return 1; case expr_null: #if defined (DEBUG_EXPRESSIONS) log_debug ("data: null = NULL"); #endif return 0; case expr_variable_reference: if (scope && *scope) { binding = find_binding (*scope, expr -> data.variable); if (binding && binding -> value) { if (binding -> value -> type == binding_data) { data_string_copy (result, &binding -> value -> value.data, file, line); s0 = 1; } else if (binding -> value -> type != binding_data) { log_error ("binding type %d in %s.", binding -> value -> type, "evaluate_data_expression"); s0 = 0; } else s0 = 0; } else s0 = 0; } else s0 = 0; #if defined (DEBUG_EXPRESSIONS) log_debug ("data: %s = %s", expr -> data.variable, s0 ? print_hex_1 (result -> len, result -> data, 50) : "NULL"); #endif return s0; case expr_funcall: bv = (struct binding_value *)0; s0 = evaluate_expression (&bv, packet, lease, client_state, in_options, cfg_options, scope, expr, MDL); if (s0) { if (bv -> type != binding_data) log_error ("%s() returned type %d in %s.", expr -> data.funcall.name, bv -> type, "evaluate_data_expression"); else data_string_copy (result, &bv -> value.data, file, line); binding_value_dereference (&bv, MDL); } #if defined (DEBUG_EXPRESSIONS) log_debug ("data: %s = %s", expr -> data.funcall.name, s0 ? print_hex_1 (result -> len, result -> data, 50) : "NULL"); #endif break; /* Extract the filename. */ case expr_filename: if (packet && packet -> raw -> file [0]) { char *fn = memchr (packet -> raw -> file, 0, sizeof packet -> raw -> file); if (!fn) fn = ((char *)packet -> raw -> file + sizeof packet -> raw -> file); result -> len = fn - &(packet -> raw -> file [0]); if (buffer_allocate (&result -> buffer, result -> len + 1, file, line)) { result -> data = &result -> buffer -> data [0]; memcpy (&result -> buffer -> data [0], packet -> raw -> file, result -> len); result -> buffer -> data [result -> len] = 0; result -> terminated = 1; s0 = 1; } else { log_error ("data: filename: no memory."); s0 = 0; } } else s0 = 0; #if defined (DEBUG_EXPRESSIONS) log_info ("data: filename = \"%s\"", s0 ? (const char *)(result -> data) : "NULL"); #endif return s0; /* Extract the server name. */ case expr_sname: if (packet && packet -> raw -> sname [0]) { char *fn = memchr (packet -> raw -> sname, 0, sizeof packet -> raw -> sname); if (!fn) fn = ((char *)packet -> raw -> sname + sizeof packet -> raw -> sname); result -> len = fn - &packet -> raw -> sname [0]; if (buffer_allocate (&result -> buffer, result -> len + 1, file, line)) { result -> data = &result -> buffer -> data [0]; memcpy (&result -> buffer -> data [0], packet -> raw -> sname, result -> len); result -> buffer -> data [result -> len] = 0; result -> terminated = 1; s0 = 1; } else { log_error ("data: sname: no memory."); s0 = 0; } } else s0 = 0; #if defined (DEBUG_EXPRESSIONS) log_info ("data: sname = \"%s\"", s0 ? (const char *)(result -> data) : "NULL"); #endif return s0; case expr_check: case expr_equal: case expr_not_equal: case expr_and: case expr_or: case expr_not: case expr_match: case expr_static: case expr_known: case expr_none: case expr_exists: case expr_variable_exists: log_error ("Boolean opcode in evaluate_data_expression: %d", expr -> op); return 0; case expr_extract_int8: case expr_extract_int16: case expr_extract_int32: case expr_const_int: case expr_lease_time: case expr_dns_transaction: case expr_add: case expr_subtract: case expr_multiply: case expr_divide: case expr_remainder: case expr_binary_and: case expr_binary_or: case expr_binary_xor: case expr_client_state: log_error ("Numeric opcode in evaluate_data_expression: %d", expr -> op); return 0; case expr_ns_add: case expr_ns_delete: case expr_ns_exists: case expr_ns_not_exists: log_error ("dns update opcode in evaluate_data_expression: %d", expr -> op); return 0; case expr_function: log_error ("function definition in evaluate_data_expression"); return 0; case expr_arg: break; } log_error ("Bogus opcode in evaluate_data_expression: %d", expr -> op); return 0; } int evaluate_numeric_expression (result, packet, lease, client_state, in_options, cfg_options, scope, expr) unsigned long *result; 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 expression *expr; { struct data_string data; int status, sleft, sright; #if defined (NSUPDATE) ns_updrec *nut; ns_updque uq; #endif struct expression *cur, *next; struct binding *binding; struct binding_value *bv; unsigned long ileft, iright; switch (expr -> op) { case expr_check: case expr_equal: case expr_not_equal: case expr_and: case expr_or: case expr_not: case expr_match: case expr_static: case expr_known: case expr_none: case expr_exists: case expr_variable_exists: log_error ("Boolean opcode in evaluate_numeric_expression: %d", expr -> op); return 0; case expr_substring: case expr_suffix: case expr_option: case expr_hardware: case expr_const_data: case expr_packet: case expr_concat: case expr_encapsulate: case expr_host_lookup: case expr_encode_int8: case expr_encode_int16: case expr_encode_int32: case expr_binary_to_ascii: case expr_reverse: case expr_filename: case expr_sname: case expr_pick_first_value: case expr_host_decl_name: case expr_config_option: case expr_leased_address: case expr_null: log_error ("Data opcode in evaluate_numeric_expression: %d", expr -> op); return 0; case expr_extract_int8: memset (&data, 0, sizeof data); status = evaluate_data_expression (&data, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.extract_int, MDL); if (status) *result = data.data [0]; #if defined (DEBUG_EXPRESSIONS) log_debug ("num: extract_int8 (%s) = %s", status ? print_hex_1 (data.len, data.data, 60) : "NULL", status ? print_dec_1 (*result) : "NULL" ); #endif if (status) data_string_forget (&data, MDL); return status; case expr_extract_int16: memset (&data, 0, sizeof data); status = (evaluate_data_expression (&data, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.extract_int, MDL)); if (status && data.len >= 2) *result = getUShort (data.data); #if defined (DEBUG_EXPRESSIONS) log_debug ("num: extract_int16 (%s) = %ld", ((status && data.len >= 2) ? print_hex_1 (data.len, data.data, 60) : "NULL"), *result); #endif if (status) data_string_forget (&data, MDL); return (status && data.len >= 2); case expr_extract_int32: memset (&data, 0, sizeof data); status = (evaluate_data_expression (&data, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.extract_int, MDL)); if (status && data.len >= 4) *result = getULong (data.data); #if defined (DEBUG_EXPRESSIONS) log_debug ("num: extract_int32 (%s) = %ld", ((status && data.len >= 4) ? print_hex_1 (data.len, data.data, 60) : "NULL"), *result); #endif if (status) data_string_forget (&data, MDL); return (status && data.len >= 4); case expr_const_int: *result = expr -> data.const_int; #if defined (DEBUG_EXPRESSIONS) log_debug ("number: CONSTANT = %ld", *result); #endif return 1; case expr_lease_time: if (!lease) { log_error ("data: leased_lease: not available"); return 0; } if (lease -> ends < cur_time) { log_error ("%s %lu when it is now %lu", "data: lease_time: lease ends at", (long)(lease -> ends), (long)cur_time); return 0; } *result = lease -> ends - cur_time; #if defined (DEBUG_EXPRESSIONS) log_debug ("number: lease-time = (%lu - %lu) = %ld", lease -> ends, cur_time, *result); #endif return 1; case expr_dns_transaction: #if !defined (NSUPDATE) return 0; #else if (!resolver_inited) { minires_ninit (&resolver_state); resolver_inited = 1; resolver_state.retrans = 1; resolver_state.retry = 1; } ISC_LIST_INIT (uq); cur = expr; do { next = cur -> data.dns_transaction.cdr; nut = 0; status = (evaluate_dns_expression (&nut, packet, lease, client_state, in_options, cfg_options, scope, cur -> data.dns_transaction.car)); if (!status) goto dns_bad; ISC_LIST_APPEND (uq, nut, r_link); cur = next; } while (next); /* Do the update and record the error code, if there was an error; otherwise set it to NOERROR. */ *result = minires_nupdate (&resolver_state, ISC_LIST_HEAD (uq)); status = 1; print_dns_status ((int)*result, &uq); dns_bad: while (!ISC_LIST_EMPTY (uq)) { ns_updrec *tmp = ISC_LIST_HEAD (uq); ISC_LIST_UNLINK (uq, tmp, r_link); if (tmp -> r_data_ephem) { dfree (tmp -> r_data_ephem, MDL); tmp -> r_data = (unsigned char *)0; tmp -> r_data_ephem = (unsigned char *)0; } minires_freeupdrec (tmp); } return status; #endif /* NSUPDATE */ case expr_variable_reference: if (scope && *scope) { binding = find_binding (*scope, expr -> data.variable); if (binding && binding -> value) { if (binding -> value -> type == binding_numeric) { *result = binding -> value -> value.intval; status = 1; } else { log_error ("binding type %d in %s.", binding -> value -> type, "evaluate_numeric_expression"); status = 0; } } else status = 0; } else status = 0; #if defined (DEBUG_EXPRESSIONS) if (status) log_debug ("numeric: %s = %ld", expr -> data.variable, *result); else log_debug ("numeric: %s = NULL", expr -> data.variable); #endif return status; case expr_funcall: bv = (struct binding_value *)0; status = evaluate_expression (&bv, packet, lease, client_state, in_options, cfg_options, scope, expr, MDL); if (status) { if (bv -> type != binding_numeric) log_error ("%s() returned type %d in %s.", expr -> data.funcall.name, bv -> type, "evaluate_numeric_expression"); else *result = bv -> value.intval; binding_value_dereference (&bv, MDL); } #if defined (DEBUG_EXPRESSIONS) log_debug ("data: %s = %ld", expr -> data.funcall.name, status ? *result : 0); #endif break; case expr_add: sleft = evaluate_numeric_expression (&ileft, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.and [0]); sright = evaluate_numeric_expression (&iright, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.and [1]); #if defined (DEBUG_EXPRESSIONS) if (sleft && sright) log_debug ("num: %ld + %ld = %ld", ileft, iright, ileft + iright); else if (sleft) log_debug ("num: %ld + NULL = NULL", ileft); else log_debug ("num: NULL + %ld = NULL", iright); #endif if (sleft && sright) { *result = ileft + iright; return 1; } return 0; case expr_subtract: sleft = evaluate_numeric_expression (&ileft, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.and [0]); sright = evaluate_numeric_expression (&iright, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.and [1]); #if defined (DEBUG_EXPRESSIONS) if (sleft && sright) log_debug ("num: %ld - %ld = %ld", ileft, iright, ileft - iright); else if (sleft) log_debug ("num: %ld - NULL = NULL", ileft); else log_debug ("num: NULL - %ld = NULL", iright); #endif if (sleft && sright) { *result = ileft - iright; return 1; } return 0; case expr_multiply: sleft = evaluate_numeric_expression (&ileft, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.and [0]); sright = evaluate_numeric_expression (&iright, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.and [1]); #if defined (DEBUG_EXPRESSIONS) if (sleft && sright) log_debug ("num: %ld * %ld = %ld", ileft, iright, ileft * iright); else if (sleft) log_debug ("num: %ld * NULL = NULL", ileft); else log_debug ("num: NULL * %ld = NULL", iright); #endif if (sleft && sright) { *result = ileft * iright; return 1; } return 0; case expr_divide: sleft = evaluate_numeric_expression (&ileft, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.and [0]); sright = evaluate_numeric_expression (&iright, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.and [1]); #if defined (DEBUG_EXPRESSIONS) if (sleft && sright) { if (iright != 0) log_debug ("num: %ld / %ld = %ld", ileft, iright, ileft / iright); else log_debug ("num: %ld / %ld = NULL", ileft, iright); } else if (sleft) log_debug ("num: %ld / NULL = NULL", ileft); else log_debug ("num: NULL / %ld = NULL", iright); #endif if (sleft && sright && iright) { *result = ileft / iright; return 1; } return 0; case expr_remainder: sleft = evaluate_numeric_expression (&ileft, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.and [0]); sright = evaluate_numeric_expression (&iright, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.and [1]); #if defined (DEBUG_EXPRESSIONS) if (sleft && sright) { if (iright != 0) log_debug ("num: %ld %% %ld = %ld", ileft, iright, ileft % iright); else log_debug ("num: %ld %% %ld = NULL", ileft, iright); } else if (sleft) log_debug ("num: %ld %% NULL = NULL", ileft); else log_debug ("num: NULL %% %ld = NULL", iright); #endif if (sleft && sright && iright) { *result = ileft % iright; return 1; } return 0; case expr_binary_and: sleft = evaluate_numeric_expression (&ileft, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.and [0]); sright = evaluate_numeric_expression (&iright, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.and [1]); #if defined (DEBUG_EXPRESSIONS) if (sleft && sright) log_debug ("num: %ld | %ld = %ld", ileft, iright, ileft & iright); else if (sleft) log_debug ("num: %ld & NULL = NULL", ileft); else log_debug ("num: NULL & %ld = NULL", iright); #endif if (sleft && sright) { *result = ileft & iright; return 1; } return 0; case expr_binary_or: sleft = evaluate_numeric_expression (&ileft, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.and [0]); sright = evaluate_numeric_expression (&iright, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.and [1]); #if defined (DEBUG_EXPRESSIONS) if (sleft && sright) log_debug ("num: %ld | %ld = %ld", ileft, iright, ileft | iright); else if (sleft) log_debug ("num: %ld | NULL = NULL", ileft); else log_debug ("num: NULL | %ld = NULL", iright); #endif if (sleft && sright) { *result = ileft | iright; return 1; } return 0; case expr_binary_xor: sleft = evaluate_numeric_expression (&ileft, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.and [0]); sright = evaluate_numeric_expression (&iright, packet, lease, client_state, in_options, cfg_options, scope, expr -> data.and [1]); #if defined (DEBUG_EXPRESSIONS) if (sleft && sright) log_debug ("num: %ld ^ %ld = %ld", ileft, iright, ileft ^ iright); else if (sleft) log_debug ("num: %ld ^ NULL = NULL", ileft); else log_debug ("num: NULL ^ %ld = NULL", iright); #endif if (sleft && sright) { *result = ileft ^ iright; return 1; } return 0; case expr_client_state: if (client_state) { #if defined (DEBUG_EXPRESSIONS) log_debug ("num: client-state = %d", client_state -> state); #endif *result = client_state -> state; return 1; } else { #if defined (DEBUG_EXPRESSIONS) log_debug ("num: client-state = NULL"); #endif return 0; } case expr_ns_add: case expr_ns_delete: case expr_ns_exists: case expr_ns_not_exists: log_error ("dns opcode in evaluate_numeric_expression: %d", expr -> op); return 0; case expr_function: log_error ("function definition in evaluate_numeric_expr"); return 0; case expr_arg: break; } log_error ("evaluate_numeric_expression: bogus opcode %d", expr -> op); return 0; } /* Return data hanging off of an option cache structure, or if there isn't any, evaluate the expression hanging off of it and return the result of that evaluation. There should never be both an expression and a valid data_string. */ int evaluate_option_cache (result, packet, lease, client_state, in_options, cfg_options, scope, oc, file, line) struct data_string *result; 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 option_cache *oc; const char *file; int line; { if (oc -> data.len) { data_string_copy (result, &oc -> data, file, line); return 1; } if (!oc -> expression) return 0; return evaluate_data_expression (result, packet, lease, client_state, in_options, cfg_options, scope, oc -> expression, file, line); } /* Evaluate an option cache and extract a boolean from the result, returning the boolean. Return false if there is no data. */ int evaluate_boolean_option_cache (ignorep, packet, lease, client_state, in_options, cfg_options, scope, oc, file, line) int *ignorep; 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 option_cache *oc; const char *file; int line; { struct data_string ds; int result; /* So that we can be called with option_lookup as an argument. */ if (!oc || !in_options) return 0; memset (&ds, 0, sizeof ds); if (!evaluate_option_cache (&ds, packet, lease, client_state, in_options, cfg_options, scope, oc, file, line)) return 0; if (ds.len) { result = ds.data [0]; if (result == 2) { result = 0; *ignorep = 1; } else *ignorep = 0; } else result = 0; data_string_forget (&ds, MDL); return result; } /* Evaluate a boolean expression and return the result of the evaluation, or FALSE if it failed. */ int evaluate_boolean_expression_result (ignorep, packet, lease, client_state, in_options, cfg_options, scope, expr) int *ignorep; 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 expression *expr; { int result; /* So that we can be called with option_lookup as an argument. */ if (!expr) return 0; if (!evaluate_boolean_expression (&result, packet, lease, client_state, in_options, cfg_options, scope, expr)) return 0; if (result == 2) { *ignorep = 1; result = 0; } else *ignorep = 0; return result; } /* Dereference an expression node, and if the reference count goes to zero, dereference any data it refers to, and then free it. */ void expression_dereference (eptr, file, line) struct expression **eptr; const char *file; int line; { struct expression *expr = *eptr; /* Zero the pointer. */ *eptr = (struct expression *)0; /* Decrement the reference count. If it's nonzero, we're done. */ --(expr -> refcnt); rc_register (file, line, eptr, expr, expr -> refcnt, 1, RC_MISC); if (expr -> refcnt > 0) return; if (expr -> refcnt < 0) { log_error ("%s(%d): negative refcnt!", file, line); #if defined (DEBUG_RC_HISTORY) dump_rc_history (expr); #endif #if defined (POINTER_DEBUG) abort (); #else return; #endif } /* Dereference subexpressions. */ switch (expr -> op) { /* All the binary operators can be handled the same way. */ case expr_equal: case expr_not_equal: case expr_concat: case expr_and: case expr_or: case expr_add: case expr_subtract: case expr_multiply: case expr_divide: case expr_remainder: case expr_binary_and: case expr_binary_or: case expr_binary_xor: case expr_client_state: if (expr -> data.equal [0]) expression_dereference (&expr -> data.equal [0], file, line); if (expr -> data.equal [1]) expression_dereference (&expr -> data.equal [1], file, line); break; case expr_substring: if (expr -> data.substring.expr) expression_dereference (&expr -> data.substring.expr, file, line); if (expr -> data.substring.offset) expression_dereference (&expr -> data.substring.offset, file, line); if (expr -> data.substring.len) expression_dereference (&expr -> data.substring.len, file, line); break; case expr_suffix: if (expr -> data.suffix.expr) expression_dereference (&expr -> data.suffix.expr, file, line); if (expr -> data.suffix.len) expression_dereference (&expr -> data.suffix.len, file, line); break; case expr_not: if (expr -> data.not) expression_dereference (&expr -> data.not, file, line); break; case expr_packet: if (expr -> data.packet.offset) expression_dereference (&expr -> data.packet.offset, file, line); if (expr -> data.packet.len) expression_dereference (&expr -> data.packet.len, file, line); break; case expr_extract_int8: case expr_extract_int16: case expr_extract_int32: if (expr -> data.extract_int) expression_dereference (&expr -> data.extract_int, file, line); break; case expr_encode_int8: case expr_encode_int16: case expr_encode_int32: if (expr -> data.encode_int) expression_dereference (&expr -> data.encode_int, file, line); break; case expr_encapsulate: case expr_const_data: data_string_forget (&expr -> data.const_data, file, line); break; case expr_host_lookup: if (expr -> data.host_lookup) dns_host_entry_dereference (&expr -> data.host_lookup, file, line); break; case expr_binary_to_ascii: if (expr -> data.b2a.base) expression_dereference (&expr -> data.b2a.base, file, line); if (expr -> data.b2a.width) expression_dereference (&expr -> data.b2a.width, file, line); if (expr -> data.b2a.seperator) expression_dereference (&expr -> data.b2a.seperator, file, line); if (expr -> data.b2a.buffer) expression_dereference (&expr -> data.b2a.buffer, file, line); break; case expr_pick_first_value: if (expr -> data.pick_first_value.car) expression_dereference (&expr -> data.pick_first_value.car, file, line); if (expr -> data.pick_first_value.cdr) expression_dereference (&expr -> data.pick_first_value.cdr, file, line); break; case expr_reverse: if (expr -> data.reverse.width) expression_dereference (&expr -> data.reverse.width, file, line); if (expr -> data.reverse.buffer) expression_dereference (&expr -> data.reverse.buffer, file, line); break; case expr_dns_transaction: if (expr -> data.dns_transaction.car) expression_dereference (&expr -> data.dns_transaction.car, file, line); if (expr -> data.dns_transaction.cdr) expression_dereference (&expr -> data.dns_transaction.cdr, file, line); break; case expr_ns_add: if (expr -> data.ns_add.rrname) expression_dereference (&expr -> data.ns_add.rrname, file, line); if (expr -> data.ns_add.rrdata) expression_dereference (&expr -> data.ns_add.rrdata, file, line); if (expr -> data.ns_add.ttl) expression_dereference (&expr -> data.ns_add.ttl, file, line); break; case expr_ns_delete: case expr_ns_exists: case expr_ns_not_exists: if (expr -> data.ns_delete.rrname) expression_dereference (&expr -> data.ns_delete.rrname, file, line); if (expr -> data.ns_delete.rrdata) expression_dereference (&expr -> data.ns_delete.rrdata, file, line); break; case expr_variable_reference: case expr_variable_exists: if (expr -> data.variable) dfree (expr -> data.variable, file, line); break; case expr_funcall: if (expr -> data.funcall.name) dfree (expr -> data.funcall.name, file, line); if (expr -> data.funcall.arglist) expression_dereference (&expr -> data.funcall.arglist, file, line); break; case expr_arg: if (expr -> data.arg.val) expression_dereference (&expr -> data.arg.val, file, line); if (expr -> data.arg.next) expression_dereference (&expr -> data.arg.next, file, line); break; case expr_function: fundef_dereference (&expr -> data.func, file, line); break; /* No subexpressions. */ case expr_leased_address: case expr_lease_time: case expr_filename: case expr_sname: case expr_const_int: case expr_check: case expr_option: case expr_hardware: case expr_exists: case expr_known: case expr_null: break; default: break; } free_expression (expr, MDL); } int is_dns_expression (expr) struct expression *expr; { return (expr -> op == expr_ns_add || expr -> op == expr_ns_delete || expr -> op == expr_ns_exists || expr -> op == expr_ns_not_exists); } int is_boolean_expression (expr) struct expression *expr; { return (expr -> op == expr_check || expr -> op == expr_exists || expr -> op == expr_variable_exists || expr -> op == expr_equal || expr -> op == expr_not_equal || expr -> op == expr_and || expr -> op == expr_or || expr -> op == expr_not || expr -> op == expr_known || expr -> op == expr_static); } int is_data_expression (expr) struct expression *expr; { return (expr -> op == expr_substring || expr -> op == expr_suffix || expr -> op == expr_option || expr -> op == expr_hardware || expr -> op == expr_const_data || expr -> op == expr_packet || expr -> op == expr_concat || expr -> op == expr_encapsulate || expr -> op == expr_encode_int8 || expr -> op == expr_encode_int16 || expr -> op == expr_encode_int32 || expr -> op == expr_host_lookup || expr -> op == expr_binary_to_ascii || expr -> op == expr_filename || expr -> op == expr_sname || expr -> op == expr_reverse || expr -> op == expr_pick_first_value || expr -> op == expr_host_decl_name || expr -> op == expr_leased_address || expr -> op == expr_config_option || expr -> op == expr_null); } int is_numeric_expression (expr) struct expression *expr; { return (expr -> op == expr_extract_int8 || expr -> op == expr_extract_int16 || expr -> op == expr_extract_int32 || expr -> op == expr_const_int || expr -> op == expr_lease_time || expr -> op == expr_dns_transaction || expr -> op == expr_add || expr -> op == expr_subtract || expr -> op == expr_multiply || expr -> op == expr_divide || expr -> op == expr_remainder || expr -> op == expr_binary_and || expr -> op == expr_binary_or || expr -> op == expr_binary_xor || expr -> op == expr_client_state); } int is_compound_expression (expr) struct expression *expr; { return (expr -> op == expr_ns_add || expr -> op == expr_ns_delete || expr -> op == expr_ns_exists || expr -> op == expr_ns_not_exists || expr -> op == expr_substring || expr -> op == expr_suffix || expr -> op == expr_option || expr -> op == expr_concat || expr -> op == expr_encode_int8 || expr -> op == expr_encode_int16 || expr -> op == expr_encode_int32 || expr -> op == expr_binary_to_ascii || expr -> op == expr_reverse || expr -> op == expr_pick_first_value || expr -> op == expr_config_option || expr -> op == expr_extract_int8 || expr -> op == expr_extract_int16 || expr -> op == expr_extract_int32 || expr -> op == expr_dns_transaction); } static int op_val PROTO ((enum expr_op)); static int op_val (op) enum expr_op op; { switch (op) { case expr_none: case expr_match: case expr_static: case expr_check: case expr_substring: case expr_suffix: case expr_concat: case expr_encapsulate: case expr_host_lookup: case expr_not: case expr_option: case expr_hardware: case expr_packet: case expr_const_data: case expr_extract_int8: case expr_extract_int16: case expr_extract_int32: case expr_encode_int8: case expr_encode_int16: case expr_encode_int32: case expr_const_int: case expr_exists: case expr_variable_exists: case expr_known: case expr_binary_to_ascii: case expr_reverse: case expr_filename: case expr_sname: case expr_pick_first_value: case expr_host_decl_name: case expr_config_option: case expr_leased_address: case expr_lease_time: case expr_dns_transaction: case expr_null: case expr_variable_reference: case expr_ns_add: case expr_ns_delete: case expr_ns_exists: case expr_ns_not_exists: case expr_arg: case expr_funcall: case expr_function: /* XXXDPN: Need to assign sane precedences to these. */ case expr_binary_and: case expr_binary_or: case expr_binary_xor: case expr_client_state: return 100; case expr_equal: case expr_not_equal: return 3; case expr_and: case expr_multiply: case expr_divide: case expr_remainder: return 1; case expr_or: case expr_add: case expr_subtract: return 2; } return 100; } int op_precedence (op1, op2) enum expr_op op1, op2; { int ov1, ov2; return op_val (op1) - op_val (op2); } enum expression_context expression_context (struct expression *expr) { if (is_data_expression (expr)) return context_data; if (is_numeric_expression (expr)) return context_numeric; if (is_boolean_expression (expr)) return context_boolean; if (is_dns_expression (expr)) return context_dns; return context_any; } enum expression_context op_context (op) enum expr_op op; { switch (op) { /* XXX Why aren't these specific? */ case expr_none: case expr_match: case expr_static: case expr_check: case expr_substring: case expr_suffix: case expr_concat: case expr_encapsulate: case expr_host_lookup: case expr_not: case expr_option: case expr_hardware: case expr_packet: case expr_const_data: case expr_extract_int8: case expr_extract_int16: case expr_extract_int32: case expr_encode_int8: case expr_encode_int16: case expr_encode_int32: case expr_const_int: case expr_exists: case expr_variable_exists: case expr_known: case expr_binary_to_ascii: case expr_reverse: case expr_filename: case expr_sname: case expr_pick_first_value: case expr_host_decl_name: case expr_config_option: case expr_leased_address: case expr_lease_time: case expr_null: case expr_variable_reference: case expr_ns_add: case expr_ns_delete: case expr_ns_exists: case expr_ns_not_exists: case expr_dns_transaction: case expr_arg: case expr_funcall: case expr_function: return context_any; case expr_equal: case expr_not_equal: return context_data; case expr_and: return context_boolean; case expr_or: return context_boolean; case expr_add: case expr_subtract: case expr_multiply: case expr_divide: case expr_remainder: case expr_binary_and: case expr_binary_or: case expr_binary_xor: case expr_client_state: return context_numeric; } return context_any; } int write_expression (file, expr, col, indent, firstp) FILE *file; struct expression *expr; int col; int indent; int firstp; { struct expression *e; const char *s; char obuf [65]; int scol; int width; /* If this promises to be a fat expression, start a new line. */ if (!firstp && is_compound_expression (expr)) { indent_spaces (file, indent); col = indent; } switch (expr -> op) { case expr_none: col = token_print_indent (file, col, indent, "", "", "null"); break; case expr_check: col = token_print_indent (file, col, indent, "", "", "check"); col = token_print_indent_concat (file, col, indent, " ", "", "\"", expr -> data.check -> name, "\"", (char *)0); break; case expr_not_equal: s = "!="; goto binary; case expr_equal: s = "="; binary: col = write_expression (file, expr -> data.equal [0], col, indent, 1); col = token_print_indent (file, col, indent, " ", " ", s); col = write_expression (file, expr -> data.equal [1], col, indent + 2, 0); break; case expr_substring: col = token_print_indent (file, col, indent, "", "", "substring"); col = token_print_indent (file, col, indent, " ", "", "("); scol = col; col = write_expression (file, expr -> data.substring.expr, col, scol, 1); col = token_print_indent (file, col, indent, "", " ", ","); col = write_expression (file, expr -> data.substring.offset, col, indent, 0); col = token_print_indent (file, col, scol, "", " ", ","); col = write_expression (file, expr -> data.substring.len, col, scol, 0); col = token_print_indent (file, col, indent, "", "", ")"); break; case expr_suffix: col = token_print_indent (file, col, indent, "", "", "suffix"); col = token_print_indent (file, col, indent, " ", "", "("); scol = col; col = write_expression (file, expr -> data.suffix.expr, col, scol, 1); col = token_print_indent (file, col, scol, "", " ", ","); col = write_expression (file, expr -> data.suffix.len, col, scol, 0); col = token_print_indent (file, col, indent, "", "", ")"); break; case expr_concat: e = expr; col = token_print_indent (file, col, indent, "", "", "concat"); col = token_print_indent (file, col, indent, " ", "", "("); scol = col; firstp = 1; concat_again: col = write_expression (file, e -> data.concat [0], col, scol, firstp); firstp = 0; if (!e -> data.concat [1]) goto no_concat_cdr; col = token_print_indent (file, col, scol, "", " ", ","); if (e -> data.concat [1] -> op == expr_concat) { e = e -> data.concat [1]; goto concat_again; } col = write_expression (file, e -> data.concat [1], col, scol, 0); no_concat_cdr: col = token_print_indent (file, col, indent, "", "", ")"); break; case expr_host_lookup: col = token_print_indent (file, col, indent, "", "", "gethostbyname"); col = token_print_indent (file, col, indent, " ", "", "("); col = token_print_indent_concat (file, col, indent, "", "", "\"", expr -> data.host_lookup -> hostname, "\"", (char *)0); col = token_print_indent (file, col, indent, "", "", ")"); break; case expr_add: s = "+"; goto binary; case expr_subtract: s = "-"; goto binary; case expr_multiply: s = "*"; goto binary; case expr_divide: s = "/"; goto binary; case expr_remainder: s = "%"; goto binary; case expr_binary_and: s = "&"; goto binary; case expr_binary_or: s = "|"; goto binary; case expr_binary_xor: s = "^"; goto binary; case expr_and: s = "and"; goto binary; case expr_or: s = "or"; goto binary; case expr_not: col = token_print_indent (file, col, indent, "", " ", "not"); col = write_expression (file, expr -> data.not, col, indent + 2, 1); break; case expr_option: s = "option"; print_option_name: col = token_print_indent (file, col, indent, "", "", s); if (expr -> data.option -> universe != &dhcp_universe) { col = token_print_indent (file, col, indent, " ", "", (expr -> data.option -> universe -> name)); col = token_print_indent (file, col, indent, "", "", "."); col = token_print_indent (file, col, indent, "", "", expr -> data.option -> name); } else { col = token_print_indent (file, col, indent, " ", "", expr -> data.option -> name); } break; case expr_hardware: col = token_print_indent (file, col, indent, "", "", "hardware"); break; case expr_packet: col = token_print_indent (file, col, indent, "", "", "packet"); col = token_print_indent (file, col, indent, " ", "", "("); scol = col; col = write_expression (file, expr -> data.packet.offset, col, indent, 1); col = token_print_indent (file, col, scol, "", " ", ","); col = write_expression (file, expr -> data.packet.len, col, scol, 0); col = token_print_indent (file, col, indent, "", "", ")"); break; case expr_const_data: col = token_indent_data_string (file, col, indent, "", "", &expr -> data.const_data); break; case expr_extract_int8: width = 8; extract_int: col = token_print_indent (file, col, indent, "", "", "extract-int"); col = token_print_indent (file, col, indent, " ", "", "("); scol = col; col = write_expression (file, expr -> data.extract_int, col, indent, 1); col = token_print_indent (file, col, scol, "", " ", ","); sprintf (obuf, "%d", width); col = token_print_indent (file, col, scol, " ", "", obuf); col = token_print_indent (file, col, indent, "", "", ")"); break; case expr_extract_int16: width = 16; goto extract_int; case expr_extract_int32: width = 32; goto extract_int; case expr_encode_int8: width = 8; encode_int: col = token_print_indent (file, col, indent, "", "", "encode-int"); col = token_print_indent (file, col, indent, " ", "", "("); scol = col; col = write_expression (file, expr -> data.extract_int, col, indent, 1); col = token_print_indent (file, col, scol, "", " ", ","); sprintf (obuf, "%d", width); col = token_print_indent (file, col, scol, " ", "", obuf); col = token_print_indent (file, col, indent, "", "", ")"); break; case expr_encode_int16: width = 16; goto encode_int; case expr_encode_int32: width = 32; goto encode_int; case expr_const_int: sprintf (obuf, "%lu", expr -> data.const_int); col = token_print_indent (file, col, indent, "", "", obuf); break; case expr_exists: s = "exists"; goto print_option_name; case expr_encapsulate: col = token_print_indent (file, col, indent, "", "", "encapsulate"); col = token_indent_data_string (file, col, indent, " ", "", &expr -> data.encapsulate); break; case expr_known: col = token_print_indent (file, col, indent, "", "", "known"); break; case expr_reverse: col = token_print_indent (file, col, indent, "", "", "reverse"); col = token_print_indent (file, col, indent, " ", "", "("); scol = col; col = write_expression (file, expr -> data.reverse.width, col, scol, 1); col = token_print_indent (file, col, scol, "", " ", ","); col = write_expression (file, expr -> data.reverse.buffer, col, scol, 0); col = token_print_indent (file, col, indent, "", "", ")"); break; case expr_leased_address: col = token_print_indent (file, col, indent, "", "", "leased-address"); break; case expr_client_state: col = token_print_indent (file, col, indent, "", "", "client-state"); break; case expr_binary_to_ascii: col = token_print_indent (file, col, indent, "", "", "binary-to-ascii"); col = token_print_indent (file, col, indent, " ", "", "("); scol = col; col = write_expression (file, expr -> data.b2a.base, col, scol, 1); col = token_print_indent (file, col, scol, "", " ", ","); col = write_expression (file, expr -> data.b2a.width, col, scol, 0); col = token_print_indent (file, col, scol, "", " ", ","); col = write_expression (file, expr -> data.b2a.seperator, col, scol, 0); col = token_print_indent (file, col, scol, "", " ", ","); col = write_expression (file, expr -> data.b2a.buffer, col, scol, 0); col = token_print_indent (file, col, indent, "", "", ")"); break; case expr_config_option: s = "config-option"; goto print_option_name; case expr_host_decl_name: col = token_print_indent (file, col, indent, "", "", "host-decl-name"); break; case expr_pick_first_value: e = expr; col = token_print_indent (file, col, indent, "", "", "concat"); col = token_print_indent (file, col, indent, " ", "", "("); scol = col; firstp = 1; pick_again: col = write_expression (file, e -> data.pick_first_value.car, col, scol, firstp); firstp = 0; /* We're being very lisp-like right now - instead of representing this expression as (first middle . last) we're representing it as (first middle last), which means that the tail cdr is always nil. Apologies to non-wisp-lizards - may this obscure way of describing the problem motivate you to learn more about the one true computing language. */ if (!e -> data.pick_first_value.cdr) goto no_pick_cdr; col = token_print_indent (file, col, scol, "", " ", ","); if (e -> data.pick_first_value.cdr -> op == expr_pick_first_value) { e = e -> data.pick_first_value.cdr; goto pick_again; } col = write_expression (file, e -> data.pick_first_value.cdr, col, scol, 0); no_pick_cdr: col = token_print_indent (file, col, indent, "", "", ")"); break; case expr_lease_time: col = token_print_indent (file, col, indent, "", "", "lease-time"); break; case expr_dns_transaction: col = token_print_indent (file, col, indent, "", "", "ns-update"); col = token_print_indent (file, col, indent, " ", "", "("); scol = 0; for (e = expr; e && e -> op == expr_dns_transaction; e = e -> data.dns_transaction.cdr) { if (!scol) { scol = col; firstp = 1; } else firstp = 0; col = write_expression (file, e -> data.dns_transaction.car, col, scol, firstp); if (e -> data.dns_transaction.cdr) col = token_print_indent (file, col, scol, "", " ", ","); } if (e) col = write_expression (file, e, col, scol, 0); col = token_print_indent (file, col, indent, "", "", ")"); break; case expr_ns_add: col = token_print_indent (file, col, indent, "", "", "update"); col = token_print_indent (file, col, indent, " ", "", "("); scol = col; sprintf (obuf, "%d", expr -> data.ns_add.rrclass); col = token_print_indent (file, col, scol, "", "", obuf); col = token_print_indent (file, col, scol, "", " ", ","); sprintf (obuf, "%d", expr -> data.ns_add.rrtype); col = token_print_indent (file, col, scol, "", "", obuf); col = token_print_indent (file, col, scol, "", " ", ","); col = write_expression (file, expr -> data.ns_add.rrname, col, scol, 0); col = token_print_indent (file, col, scol, "", " ", ","); col = write_expression (file, expr -> data.ns_add.rrdata, col, scol, 0); col = token_print_indent (file, col, scol, "", " ", ","); col = write_expression (file, expr -> data.ns_add.ttl, col, scol, 0); col = token_print_indent (file, col, indent, "", "", ")"); break; case expr_ns_delete: col = token_print_indent (file, col, indent, "", "", "delete"); col = token_print_indent (file, col, indent, " ", "", "("); finish_ns_small: scol = col; sprintf (obuf, "%d", expr -> data.ns_add.rrclass); col = token_print_indent (file, col, scol, "", "", obuf); col = token_print_indent (file, col, scol, "", " ", ","); sprintf (obuf, "%d", expr -> data.ns_add.rrtype); col = token_print_indent (file, col, scol, "", "", obuf); col = token_print_indent (file, col, scol, "", " ", ","); col = write_expression (file, expr -> data.ns_add.rrname, col, scol, 0); col = token_print_indent (file, col, scol, "", " ", ","); col = write_expression (file, expr -> data.ns_add.rrdata, col, scol, 0); col = token_print_indent (file, col, indent, "", "", ")"); break; case expr_ns_exists: col = token_print_indent (file, col, indent, "", "", "exists"); col = token_print_indent (file, col, indent, " ", "", "("); goto finish_ns_small; case expr_ns_not_exists: col = token_print_indent (file, col, indent, "", "", "not exists"); col = token_print_indent (file, col, indent, " ", "", "("); goto finish_ns_small; case expr_static: col = token_print_indent (file, col, indent, "", "", "static"); break; case expr_null: col = token_print_indent (file, col, indent, "", "", "null"); break; case expr_variable_reference: col = token_print_indent (file, indent, indent, "", "", expr -> data.variable); break; case expr_variable_exists: col = token_print_indent (file, indent, indent, "", "", "defined"); col = token_print_indent (file, col, indent, " ", "", "("); col = token_print_indent (file, col, indent, "", "", expr -> data.variable); col = token_print_indent (file, col, indent, "", "", ")"); break; default: log_fatal ("invalid expression type in print_expression: %d", expr -> op); } return col; } struct binding *find_binding (struct binding_scope *scope, const char *name) { struct binding *bp; struct binding_scope *s; for (s = scope; s; s = s -> outer) { for (bp = s -> bindings; bp; bp = bp -> next) { if (!strcasecmp (name, bp -> name)) { return bp; } } } return (struct binding *)0; } int free_bindings (struct binding_scope *scope, const char *file, int line) { struct binding *bp, *next; for (bp = scope -> bindings; bp; bp = next) { next = bp -> next; if (bp -> name) dfree (bp -> name, file, line); if (bp -> value) binding_value_dereference (&bp -> value, file, line); dfree (bp, file, line); } scope -> bindings = (struct binding *)0; return 1; } int binding_scope_dereference (ptr, file, line) struct binding_scope **ptr; const char *file; int line; { int i; struct binding_scope *binding_scope; if (!ptr || !*ptr) { log_error ("%s(%d): null pointer", file, line); #if defined (POINTER_DEBUG) abort (); #else return 0; #endif } binding_scope = *ptr; *ptr = (struct binding_scope *)0; --binding_scope -> refcnt; rc_register (file, line, ptr, binding_scope, binding_scope -> refcnt, 1, RC_MISC); if (binding_scope -> refcnt > 0) return 1; if (binding_scope -> refcnt < 0) { log_error ("%s(%d): negative refcnt!", file, line); #if defined (DEBUG_RC_HISTORY) dump_rc_history (binding_scope); #endif #if defined (POINTER_DEBUG) abort (); #else return 0; #endif } free_bindings (binding_scope, file, line); if (binding_scope -> outer) binding_scope_dereference (&binding_scope -> outer, MDL); dfree (binding_scope, file, line); return 1; } int fundef_dereference (ptr, file, line) struct fundef **ptr; const char *file; int line; { struct fundef *bp = *ptr; struct string_list *sp, *next; if (!ptr) { log_error ("%s(%d): null pointer", file, line); #if defined (POINTER_DEBUG) abort (); #else return 0; #endif } if (!bp) { log_error ("%s(%d): null pointer", file, line); #if defined (POINTER_DEBUG) abort (); #else return 0; #endif } bp -> refcnt--; rc_register (file, line, ptr, bp, bp -> refcnt, 1, RC_MISC); if (bp -> refcnt < 0) { log_error ("%s(%d): negative refcnt!", file, line); #if defined (DEBUG_RC_HISTORY) dump_rc_history (bp); #endif #if defined (POINTER_DEBUG) abort (); #else return 0; #endif } if (!bp -> refcnt) { for (sp = bp -> args; sp; sp = next) { next = sp -> next; dfree (sp, file, line); } if (bp -> statements) executable_statement_dereference (&bp -> statements, file, line); dfree (bp, file, line); } *ptr = (struct fundef *)0; return 1; } #if defined (NOTYET) /* Post 3.0 final. */ int data_subexpression_length (int *rv, struct expression *expr) { int crhs, clhs, llhs, lrhs; switch (expr -> op) { case expr_substring: if (expr -> data.substring.len && expr -> data.substring.len -> op == expr_const_int) { (*rv = (int)expr -> data.substring.len -> data.const_int); return 1; } return 0; case expr_packet: case expr_suffix: if (expr -> data.suffix.len && expr -> data.suffix.len -> op == expr_const_int) { (*rv = (int)expr -> data.suffix.len -> data.const_int); return 1; } return 0; case expr_concat: clhs = data_subexpression_length (&llhs, expr -> data.concat [0]); crhs = data_subexpression_length (&lrhs, expr -> data.concat [1]); if (crhs == 0 || clhs == 0) return 0; *rv = llhs + lrhs; return 1; break; case expr_hardware: return 0; case expr_const_data: *rv = expr -> data.const_data.len; return 2; case expr_reverse: return data_subexpression_length (rv, expr -> data.reverse.buffer); case expr_leased_address: case expr_lease_time: *rv = 4; return 2; case expr_pick_first_value: clhs = data_subexpression_length (&llhs, expr -> data.concat [0]); crhs = data_subexpression_length (&lrhs, expr -> data.concat [1]); if (crhs == 0 || clhs == 0) return 0; if (llhs > lrhs) *rv = llhs; else *rv = lrhs; return 1; case expr_binary_to_ascii: case expr_config_option: case expr_host_decl_name: case expr_encapsulate: case expr_filename: case expr_sname: case expr_host_lookup: case expr_option: case expr_none: case expr_match: case expr_check: case expr_equal: case expr_and: case expr_or: case expr_not: case expr_extract_int8: case expr_extract_int16: case expr_extract_int32: case expr_encode_int8: case expr_encode_int16: case expr_encode_int32: case expr_const_int: case expr_exists: case expr_known: case expr_dns_transaction: case expr_static: case expr_ns_add: case expr_ns_delete: case expr_ns_exists: case expr_ns_not_exists: case expr_not_equal: case expr_null: case expr_variable_exists: case expr_variable_reference: case expr_arg: case expr_funcall: case expr_function: case expr_add: case expr_subtract: case expr_multiply: case expr_divide: case expr_remainder: case expr_binary_and: case expr_binary_or: case expr_binary_xor: case expr_client_state: return 0; } return 0; } int expr_valid_for_context (struct expression *expr, enum expression_context context) { /* We don't know at parse time what type of value a function may return, so we can't flag an error on it. */ if (expr -> op == expr_funcall || expr -> op == expr_variable_reference) return 1; switch (context) { case context_any: return 1; case context_boolean: if (is_boolean_expression (expr)) return 1; return 0; case context_data: if (is_data_expression (expr)) return 1; return 0; case context_numeric: if (is_numeric_expression (expr)) return 1; return 0; case context_dns: if (is_dns_expression (expr)) { return 1; } return 0; case context_data_or_numeric: if (is_numeric_expression (expr) || is_data_expression (expr)) { return 1; } return 0; case context_function: if (expr -> op == expr_function) return 1; return 0; } return 0; } #endif /* NOTYET */ struct binding *create_binding (struct binding_scope **scope, const char *name) { struct binding *binding; if (!*scope) { if (!binding_scope_allocate (scope, MDL)) return (struct binding *)0; } binding = find_binding (*scope, name); if (!binding) { binding = dmalloc (sizeof *binding, MDL); if (!binding) return (struct binding *)0; memset (binding, 0, sizeof *binding); binding -> name = dmalloc (strlen (name) + 1, MDL); if (!binding -> name) { dfree (binding, MDL); return (struct binding *)0; } strcpy (binding -> name, name); binding -> next = (*scope) -> bindings; (*scope) -> bindings = binding; } return binding; } int bind_ds_value (struct binding_scope **scope, const char *name, struct data_string *value) { struct binding *binding; binding = create_binding (scope, name); if (!binding) return 0; if (binding -> value) binding_value_dereference (&binding -> value, MDL); if (!binding_value_allocate (&binding -> value, MDL)) return 0; data_string_copy (&binding -> value -> value.data, value, MDL); binding -> value -> type = binding_data; return 1; } int find_bound_string (struct data_string *value, struct binding_scope *scope, const char *name) { struct binding *binding; binding = find_binding (scope, name); if (!binding || !binding -> value || binding -> value -> type != binding_data) return 0; if (binding -> value -> value.data.terminated) { data_string_copy (value, &binding -> value -> value.data, MDL); } else { buffer_allocate (&value -> buffer, binding -> value -> value.data.len, MDL); if (!value -> buffer) return 0; memcpy (value -> buffer -> data, binding -> value -> value.data.data, binding -> value -> value.data.len); value -> data = value -> buffer -> data; value -> len = binding -> value -> value.data.len; } return 1; } int unset (struct binding_scope *scope, const char *name) { struct binding *binding; binding = find_binding (scope, name); if (binding) { if (binding -> value) binding_value_dereference (&binding -> value, MDL); return 1; } return 0; } /* vim: set tabstop=8: */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/common/upf.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/common/upf.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/common/upf.c (revision 131136) @@ -1,382 +1,371 @@ /* upf.c Ultrix PacketFilter interface code. */ /* - * Copyright (c) 1996-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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: upf.c,v 1.21.2.1 2002/11/17 02:27:00 dhankins Exp $ Copyright (c) 1996-2002 The Internet Software Consortium. All rights reserved.\n"; +"$Id: upf.c,v 1.21.2.4 2004/06/17 20:54:39 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" #if defined (USE_UPF_SEND) || defined (USE_UPF_RECEIVE) #include #include #include #include #include "includes/netinet/ip.h" #include "includes/netinet/udp.h" #include "includes/netinet/if_ether.h" /* Reinitializes the specified interface after an address change. This is not required for packet-filter APIs. */ #ifdef USE_UPF_SEND void if_reinitialize_send (info) struct interface_info *info; { } #endif #ifdef USE_UPF_RECEIVE void if_reinitialize_receive (info) struct interface_info *info; { } #endif /* Called by get_interface_list for each interface that's discovered. Opens a packet filter for each interface and adds it to the select mask. */ int if_register_upf (info) struct interface_info *info; { int sock; char filename[50]; int b; struct endevp param; /* Open a UPF device */ for (b = 0; 1; b++) { -#ifndef NO_SNPRINTF - snprintf(filename, sizeof(filename), "/dev/pf/pfilt%d", b); -#else + /* %Audit% Cannot exceed 36 bytes. %2004.06.17,Safe% */ sprintf(filename, "/dev/pf/pfilt%d", b); -#endif + sock = open (filename, O_RDWR, 0); if (sock < 0) { if (errno == EBUSY) { continue; } else { log_fatal ("Can't find free upf: %m"); } } else { break; } } /* Set the UPF device to point at this interface. */ if (ioctl (sock, EIOCSETIF, info -> ifp) < 0) log_fatal ("Can't attach interface %s to upf device %s: %m", info -> name, filename); /* Get the hardware address. */ if (ioctl (sock, EIOCDEVP, ¶m) < 0) log_fatal ("Can't get interface %s hardware address: %m", info -> name); /* We only know how to do ethernet. */ if (param.end_dev_type != ENDT_10MB) log_fatal ("Invalid device type on network interface %s: %d", info -> name, param.end_dev_type); if (param.end_addr_len != 6) log_fatal ("Invalid hardware address length on %s: %d", info -> name, param.end_addr_len); info -> hw_address.hlen = 7; info -> hw_address.hbuf [0] = ARPHRD_ETHER; memcpy (&info -> hw_address.hbuf [1], param.end_addr, 6); return sock; } #endif /* USE_UPF_SEND || USE_UPF_RECEIVE */ #ifdef USE_UPF_SEND void if_register_send (info) struct interface_info *info; { /* If we're using the upf API for sending and receiving, we don't need to register this interface twice. */ #ifndef USE_UPF_RECEIVE info -> wfdesc = if_register_upf (info, interface); #else info -> wfdesc = info -> rfdesc; #endif if (!quiet_interface_discovery) log_info ("Sending on UPF/%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; { #ifndef USE_UPF_RECEIVE close (info -> wfdesc); #endif info -> wfdesc = -1; if (!quiet_interface_discovery) log_info ("Disabling output on UPF/%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 : "")); } #endif /* USE_UPF_SEND */ #ifdef USE_UPF_RECEIVE /* Packet filter program... XXX Changes to the filter program may require changes to the constant offsets used in if_register_send to patch the UPF program! XXX */ void if_register_receive (info) struct interface_info *info; { int flag = 1; u_int32_t addr; struct enfilter pf; u_int32_t bits; /* Open a UPF device and hang it on this interface... */ info -> rfdesc = if_register_upf (info); /* Allow the copyall flag to be set... */ if (ioctl(info -> rfdesc, EIOCALLOWCOPYALL, &flag) < 0) log_fatal ("Can't set ALLOWCOPYALL: %m"); /* Clear all the packet filter mode bits first... */ flag = (ENHOLDSIG | ENBATCH | ENTSTAMP | ENPROMISC | ENNONEXCL | ENCOPYALL); if (ioctl (info -> rfdesc, EIOCMBIC, &flag) < 0) log_fatal ("Can't clear pfilt bits: %m"); /* Set the ENBATCH and ENCOPYALL bits... */ bits = ENBATCH | ENCOPYALL; if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0) log_fatal ("Can't set ENBATCH|ENCOPYALL: %m"); /* Set up the UPF filter program. */ /* XXX Unlike the BPF filter program, this one won't work if the XXX IP packet is fragmented or if there are options on the IP XXX header. */ pf.enf_Priority = 0; pf.enf_FilterLen = 0; pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHWORD + 6; pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHLIT + ENF_CAND; pf.enf_Filter [pf.enf_FilterLen++] = htons (ETHERTYPE_IP); pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHLIT; pf.enf_Filter [pf.enf_FilterLen++] = htons (IPPROTO_UDP); pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHWORD + 11; pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHLIT + ENF_AND; pf.enf_Filter [pf.enf_FilterLen++] = htons (0xFF); pf.enf_Filter [pf.enf_FilterLen++] = ENF_CAND; pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHWORD + 18; pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHLIT + ENF_CAND; pf.enf_Filter [pf.enf_FilterLen++] = local_port; if (ioctl (info -> rfdesc, EIOCSETF, &pf) < 0) log_fatal ("Can't install packet filter program: %m"); if (!quiet_interface_discovery) log_info ("Listening on UPF/%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_receive (info) struct interface_info *info; { close (info -> rfdesc); info -> rfdesc = -1; if (!quiet_interface_discovery) log_info ("Disabling input on UPF/%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 : "")); } #endif /* USE_UPF_RECEIVE */ #ifdef USE_UPF_SEND ssize_t send_packet (interface, packet, raw, len, from, to, hto) 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; { 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, (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 *)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) log_error ("send_packet: %m"); return result; } #endif /* USE_UPF_SEND */ #ifdef USE_UPF_RECEIVE ssize_t receive_packet (interface, buf, len, from, hfrom) struct interface_info *interface; unsigned char *buf; size_t len; struct sockaddr_in *from; struct hardware *hfrom; { int nread; int length = 0; int offset = 0; unsigned char ibuf [1500 + sizeof (struct enstamp)]; int bufix = 0; length = read (interface -> rfdesc, ibuf, sizeof ibuf); if (length <= 0) return length; bufix = sizeof (struct enstamp); /* Decode the physical header... */ offset = decode_hw_header (interface, ibuf, bufix, hfrom); /* If a physical layer checksum failed (dunno of any physical layer that supports this, but WTH), skip this packet. */ if (offset < 0) { return 0; } bufix += offset; length -= offset; /* Decode the IP and UDP headers... */ offset = decode_udp_ip_header (interface, ibuf, bufix, from, (unsigned char *)0, length); /* If the IP or UDP checksum was bad, skip the packet... */ if (offset < 0) return 0; bufix += offset; length -= offset; /* Copy out the data in the packet... */ memcpy (buf, &ibuf [bufix], length); return length; } int can_unicast_without_arp (ip) struct interface_info *ip; { return 1; } int can_receive_unicast_unconfigured (ip) struct interface_info *ip; { return 1; } int supports_multiple_interfaces (ip) struct interface_info *ip; { return 1; } void maybe_setup_fallback () { isc_result_t status; struct interface_info *fbi = (struct interface_info *)0; if (setup_fallback (&fbi, MDL)) { if_register_fallback (fbi); 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 Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/Makefile.dist =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/Makefile.dist (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/Makefile.dist (revision 131136) @@ -1,106 +1,111 @@ # Makefile.dist # -# Copyright (c) 1996-2002 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: +# Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") +# Copyright (c) 1996-2003 by Internet Software Consortium # -# http://www.isc.org/isc-license-1.0.html. +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. # -# 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. +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -# Support and other services are available for ISC products - see -# http://www.isc.org for more information. +# Internet Systems Consortium, Inc. +# 950 Charter Street +# Redwood City, CA 94063 +# +# http://www.isc.org/ # CATMANPAGES = dhcpctl.cat3 omshell.cat1 SEDMANPAGES = dhcpctl.man3 omshell.man1 SRC = dhcpctl.c callback.c remote.c OBJ = dhcpctl.o callback.o remote.o MAN = dhcpctl.3 omshell.1 HDRS = dhcpctl.h INCLUDES = $(BINDINC) -I$(TOP)/includes CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS) DHCPCTLLIBS = libdhcpctl.a ../common/libdhcp.a $(BINDLIB) \ ../omapip/libomapi.a ../dst/libdst.a all: libdhcpctl.a omshell cltest $(CATMANPAGES) omshell: omshell.o $(DHCPCTLLIBS) $(CC) $(DEBUG) $(LFLAGS) -o omshell omshell.o $(DHCPCTLLIBS) $(LIBS) cltest: cltest.o $(DHCPCTLLIBS) $(CC) $(DEBUG) $(LFLAGS) -o cltest cltest.o $(DHCPCTLLIBS) $(LIBS) libdhcpctl.a: $(OBJ) rm -f libdhcpctl.a ar cruv libdhcpctl.a $(OBJ) $(RANLIB) libdhcpctl.a install: all $(CATMANPAGES) for dir in $(LIBDIR) $(LIBMANDIR) $(INCDIR) $(USRMANDIR) \ $(USERBINDIR); do \ foo=""; \ for bar in `echo $(DESTDIR)$${dir} |tr / ' '`; do \ foo=$${foo}/$$bar; \ if [ ! -d $$foo ]; then \ mkdir $$foo; \ chmod 755 $$foo; \ fi; \ done; \ done $(INSTALL) libdhcpctl.a $(DESTDIR)$(LIBDIR) $(CHMOD) 644 $(DESTDIR)$(LIBDIR)/libdhcpctl.a $(INSTALL) dhcpctl.h $(DESTDIR)$(INCDIR) $(CHMOD) 644 $(DESTDIR)$(INCDIR)/dhcpctl.h for man in $(MAN); do \ prefix=`echo $$man |sed -e 's/\.[0-9]$$//'`; \ suffix=`echo $$man |sed -e 's/.*\.\([0-9]\)$$/\1/'`; \ $(MANINSTALL) $(MANFROM) $${prefix}.$(MANCAT)$${suffix} $(MANTO) \ $(DESTDIR)$(LIBMANDIR)/$${prefix}$(LIBMANEXT); \ done $(INSTALL) omshell $(DESTDIR)$(USERBINDIR) $(CHMOD) 755 $(DESTDIR)$(USERBINDIR)/omshell $(MANINSTALL) $(MANFROM) omshell.$(MANCAT)1 $(MANTO) \ $(DESTDIR)$(USRMANDIR)/omshell$(USRMANEXT) depend: $(MKDEP) $(INCLUDES) $(PREDEFINES) $(SRC) clean: -rm -f $(OBJ) test.o svtest cltest.o cltest realclean: clean -rm -f libdhcpctl.a *~ $(CATMANPAGES) $(SEDMANPAGES) distclean: realclean -rm -f Makefile links: @for foo in $(SRC) $(MAN) omshell.c cltest.c $(HDRS); do \ if [ ! -b $$foo ]; then \ rm -f $$foo; \ fi; \ ln -s $(TOP)/dhcpctl/$$foo $$foo; \ done dhcpctl.cat3: dhcpctl.man3 nroff -man dhcpctl.man3 >dhcpctl.cat3 dhcpctl.man3: dhcpctl.3 sed -e "s#ETCDIR#$(ETC)#g" -e "s#DBDIR#$(VARDB)#g" \ -e "s#RUNDIR#$(VARRUN)#g" < dhcpctl.3 >dhcpctl.man3 omshell.cat1: omshell.man1 nroff -man omshell.man1 >omshell.cat1 omshell.man1: omshell.1 sed -e "s#ETCDIR#$(ETC)#g" -e "s#DBDIR#$(VARDB)#g" \ -e "s#RUNDIR#$(VARRUN)#g" < omshell.1 >omshell.man1 # Dependencies (semi-automatically-generated) Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/callback.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/callback.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/callback.c (revision 131136) @@ -1,179 +1,175 @@ /* callback.c The dhcpctl callback object. */ /* - * Copyright (c) 1999-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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: callback.c,v 1.5.2.2 2004/06/10 17:59:23 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; +#endif /* not lint */ #include #include "dhcpctl.h" /* dhcpctl_set_callback synchronous, with asynchronous aftereffect handle is some object upon which some kind of process has been started - e.g., an open, an update or a refresh. data is an anonymous pointer containing some information that the callback will use to figure out what event completed. return value of 0 means callback was successfully set, a nonzero status code is returned otherwise. Upon completion of whatever task is in process, the callback will be passed the handle to the object, a status code indicating what happened, and the anonymous pointer passed to */ dhcpctl_status dhcpctl_set_callback (dhcpctl_handle h, void *data, void (*func) (dhcpctl_handle, dhcpctl_status, void *)) { dhcpctl_callback_object_t *callback; omapi_object_t *inner; isc_result_t status; callback = dmalloc (sizeof *callback, MDL); if (!callback) return ISC_R_NOMEMORY; /* Tie the callback object to the innermost object in the chain. */ for (inner = h; inner -> inner; inner = inner -> inner) ; omapi_object_reference (&inner -> inner, (omapi_object_t *)callback, MDL); omapi_object_reference ((omapi_object_t **)&callback -> outer, inner, MDL); /* Save the actual handle pointer we were passed for the callback. */ omapi_object_reference (&callback -> object, h, MDL); callback -> data = data; callback -> callback = func; return ISC_R_SUCCESS; } /* Callback methods (not meant to be called directly) */ isc_result_t dhcpctl_callback_set_value (omapi_object_t *h, omapi_object_t *id, omapi_data_string_t *name, omapi_typed_data_t *value) { if (h -> type != dhcpctl_callback_type) return ISC_R_INVALIDARG; if (h -> inner && h -> inner -> type -> set_value) return (*(h -> inner -> type -> set_value)) (h -> inner, id, name, value); return ISC_R_NOTFOUND; } isc_result_t dhcpctl_callback_get_value (omapi_object_t *h, omapi_object_t *id, omapi_data_string_t *name, omapi_value_t **value) { if (h -> type != dhcpctl_callback_type) return ISC_R_INVALIDARG; if (h -> inner && h -> inner -> type -> get_value) return (*(h -> inner -> type -> get_value)) (h -> inner, id, name, value); return ISC_R_NOTFOUND; } isc_result_t dhcpctl_callback_signal_handler (omapi_object_t *o, const char *name, va_list ap) { dhcpctl_callback_object_t *p; isc_result_t waitstatus; if (o -> type != dhcpctl_callback_type) return ISC_R_INVALIDARG; p = (dhcpctl_callback_object_t *)o; /* Not a signal we recognize? */ if (strcmp (name, "ready")) { if (p -> inner && p -> inner -> type -> signal_handler) return (*(p -> inner -> type -> signal_handler)) (p -> inner, name, ap); return ISC_R_NOTFOUND; } if (p -> object -> type == dhcpctl_remote_type) { waitstatus = (((dhcpctl_remote_object_t *) (p -> object)) -> waitstatus); } else waitstatus = ISC_R_SUCCESS; /* Do the callback. */ if (p -> callback) (*(p -> callback)) (p -> object, waitstatus, p -> data); return ISC_R_SUCCESS; } isc_result_t dhcpctl_callback_destroy (omapi_object_t *h, const char *file, int line) { dhcpctl_callback_object_t *p; if (h -> type != dhcpctl_callback_type) return ISC_R_INVALIDARG; p = (dhcpctl_callback_object_t *)h; if (p -> handle) omapi_object_dereference ((omapi_object_t **)&p -> handle, file, line); return ISC_R_SUCCESS; } /* Write all the published values associated with the object through the specified connection. */ isc_result_t dhcpctl_callback_stuff_values (omapi_object_t *c, omapi_object_t *id, omapi_object_t *p) { int i; if (p -> type != dhcpctl_callback_type) return ISC_R_INVALIDARG; if (p -> inner && p -> inner -> type -> stuff_values) return (*(p -> inner -> type -> stuff_values)) (c, id, p -> inner); return ISC_R_SUCCESS; } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/cltest.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/cltest.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/cltest.c (revision 131136) @@ -1,188 +1,185 @@ /* cltest.c Example program that uses the dhcpctl library. */ -/* Copyright (C) 2000-2002 Internet Software Consortium - * All rights reserved. +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2000-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software was contributed to the Internet Software Consortium + * This software was contributed to Internet Systems Consortium * by Brian Murrell. */ + +#ifndef lint +static char ocopyright[] = +"$Id: cltest.c,v 1.11.2.3 2004/06/10 17:59:23 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; +#endif /* not lint */ #include #include #include #include #include #include #include #include "dhcpctl.h" int main (int, char **); enum modes { up, down, undefined }; static void usage (char *s) { fprintf (stderr, "Usage: %s [-n ] [-p ] [-a ]" "(-u | -d) \n", s); exit (1); } int main (argc, argv) int argc; char **argv; { isc_result_t status, waitstatus; dhcpctl_handle authenticator; dhcpctl_handle connection; dhcpctl_handle host_handle, group_handle, interface_handle; dhcpctl_data_string cid; dhcpctl_data_string result, groupname, identifier; int i; int mode = undefined; const char *interface = 0; const char *action; for (i = 1; i < argc; i++) { if (!strcmp (argv[i], "-u")) { mode = up; } else if (!strcmp (argv [i], "-d")) { mode = down; } else if (argv[i][0] == '-') { usage(argv[0]); } else { interface = argv[i]; } } if (!interface) usage(argv[0]); if (mode == undefined) usage(argv[0]); status = dhcpctl_initialize (); if (status != ISC_R_SUCCESS) { fprintf (stderr, "dhcpctl_initialize: %s\n", isc_result_totext (status)); exit (1); } authenticator = dhcpctl_null_handle; connection = dhcpctl_null_handle; status = dhcpctl_connect (&connection, "127.0.0.1", 7911, authenticator); if (status != ISC_R_SUCCESS) { fprintf (stderr, "dhcpctl_connect: %s\n", isc_result_totext (status)); exit (1); } interface_handle = dhcpctl_null_handle; status = dhcpctl_new_object (&interface_handle, connection, "interface"); if (status != ISC_R_SUCCESS) { fprintf (stderr, "dhcpctl_new_object: %s\n", isc_result_totext (status)); exit (1); } status = dhcpctl_set_string_value (interface_handle, interface, "name"); if (status != ISC_R_SUCCESS) { fprintf (stderr, "dhcpctl_set_value: %s\n", isc_result_totext (status)); exit (1); } if (mode == up) { /* "up" the interface */ printf ("upping interface %s\n", interface); action = "create"; status = dhcpctl_open_object (interface_handle, connection, DHCPCTL_CREATE | DHCPCTL_EXCL); if (status != ISC_R_SUCCESS) { fprintf (stderr, "dhcpctl_open_object: %s\n", isc_result_totext (status)); exit (1); } } else { /* down the interface */ printf ("downing interface %s\n", interface); action = "remove"; status = dhcpctl_open_object (interface_handle, connection, 0); if (status != ISC_R_SUCCESS) { fprintf (stderr, "dhcpctl_open_object: %s\n", isc_result_totext (status)); exit (1); } status = dhcpctl_wait_for_completion (interface_handle, &waitstatus); if (status != ISC_R_SUCCESS) { fprintf (stderr, "dhcpctl_wait_for_completion: %s\n", isc_result_totext (status)); exit (1); } if (waitstatus != ISC_R_SUCCESS) { fprintf (stderr, "dhcpctl_wait_for_completion: %s\n", isc_result_totext (waitstatus)); exit (1); } status = dhcpctl_object_remove (connection, interface_handle); if (status != ISC_R_SUCCESS) { fprintf (stderr, "dhcpctl_open_object: %s\n", isc_result_totext (status)); exit (1); } } status = dhcpctl_wait_for_completion (interface_handle, &waitstatus); if (status != ISC_R_SUCCESS) { fprintf (stderr, "dhcpctl_wait_for_completion: %s\n", isc_result_totext (status)); exit (1); } if (waitstatus != ISC_R_SUCCESS) { fprintf (stderr, "interface object %s: %s\n", action, isc_result_totext (waitstatus)); exit (1); } memset (&result, 0, sizeof result); status = dhcpctl_get_value (&result, interface_handle, "state"); if (status != ISC_R_SUCCESS) { fprintf (stderr, "dhcpctl_get_value: %s\n", isc_result_totext (status)); exit (1); } exit (0); } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/dhcpctl.3 =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/dhcpctl.3 (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/dhcpctl.3 (revision 131136) @@ -1,470 +1,486 @@ .\" -*- nroff -*- .\" .\" Project: DHCP .\" File: dhcpctl.3 -.\" RCSId: $Id: dhcpctl.3,v 1.3.2.1 2001/06/26 18:35:35 mellon Exp $ +.\" RCSId: $Id: dhcpctl.3,v 1.3.2.4 2004/06/10 17:59:23 dhankins Exp $ .\" -.\" Copyright (C) 2000 Nominum, Inc. +.\" Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (c) 2000-2003 by Internet Software Consortium +.\" Copyright (c) 2000 Nominum, Inc. +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +.\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.\" Internet Systems Consortium, Inc. +.\" 950 Charter Street +.\" Redwood City, CA 94063 +.\" +.\" http://www.isc.org/ .\" .\" Description: dhcpctl man page. .\" .\" .Dd Nov 15, 2000 .Dt DHCPCTL 3 .Os DHCP 3 .ds vT DHCP Programmer's Manual .\" .\" .\" .Sh NAME .Nm dhcpctl_initialize .Nd dhcpctl library initialization. .\" .\" .\" .Sh SYNOPSIS .Fd #include -.Fd .Ft dhcpctl_status .Fo dhcpctl_initialize .Fa void .Fc .\" .Ft dhcpctl_status .Fo dhcpctl_connect .Fa "dhcpctl_handle *cxn" .Fa "const char *host" .Fa "int port" .Fa "dhcpctl_handle auth" .Fc .\" .\" .\" .Ft dhcpctl_status .Fo dhcpctl_wait_for_completion .Fa "dhcpctl_handle object" .Fa "dhcpctl_status *status" .Fc .\" .\" .\" .Ft dhcpctl_status .Fo dhcpctl_get_value .Fa "dhcpctl_data_string *value" .Fa "dhcpctl_handle object" .Fa "const char *name" .Fc .\" .\" .\" .Ft dhcpctl_status .Fo dhcpctl_get_boolean .Fa "int *value" .Fa "dhcpctl_handle object" .Fa "const char *name" .Fc .\" .\" .\" .Ft dhcpctl_status .Fo dhcpctl_set_value .Fa "dhcpctl_handle object" .Fa "dhcpctl_data_string value" .Fa "const char *name" .Fc .\" .\" .\" .Ft dhcpctl_status .Fo dhcpctl_set_string_value .Fa "dhcpctl_handle object" .Fa "const char *value" .Fa "const char *name" .Fc .\" .\" .\" .Ft dhcpctl_status .Fo dhcpctl_set_boolean_value .Fa "dhcpctl_handle object" .Fa "int value" .Fa "const char *name" .Fc .\" .\" .\" .Ft dhcpctl_status .Fo dhcpctl_set_int_value .Fa "dhcpctl_handle object" .Fa "int value" .Fa "const char *name" .Fc .\" .\" .\" .Ft dhcpctl_status .Fo dhcpctl_object_update .Fa "dhcpctl_handle connection" .Fa "dhcpctl_handle object" .Fc .\" .\" .\" .Ft dhcpctl_status .Fo dhcpctl_object_refresh .Fa "dhcpctl_handle connection" .Fa "dhcpctl_handle object" .Fc .\" .\" .\" .Ft dhcpctl_status .Fo dhcpctl_object_remove .Fa "dhcpctl_handle connection" .Fa "dhcpctl_handle object" .Fc .\" .\" .\" .Ft dhcpctl_status .Fo dhcpctl_set_callback .Fa "dhcpctl_handle object" .Fa "void *data" .Fa "void (*function) (dhcpctl_handle, dhcpctl_status, void *)" .Fc .\" .\" .\" .Ft dhcpctl_status .Fo dhcpctl_new_authenticator .Fa "dhcpctl_handle *object" .Fa "const char *name" .Fa "const char *algorithm" .Fa "const char *secret" .Fa "unsigned secret_len" .Fc .\" .\" .\" .Ft dhcpctl_status .Fo dhcpctl_new_object .Fa "dhcpctl_handle *object" .Fa "dhcpctl_handle connection" .Fa "const char *object_type" .Fc .\" .\" .\" .Ft dhcpctl_status .Fo dhcpctl_open_object .Fa "dhcpctl_handle object" .Fa "dhcpctl_handle connection" .Fa "int flags" .Fc .\" .\" .\" .Ft isc_result_t .Fo omapi_data_string_new .Fa dhcpctl_data_string *data .Fa unsigned int length .Fa const char *filename, .Fa int lineno .Fc .\" .\" .\" .Ft isc_result_t .Fo dhcpctl_data_string_dereference .Fa "dhcpctl_data_string *" .Fa "const char *" .Fa "int" .Fc .Sh DESCRIPTION The dhcpctl set of functions provide an API that can be used to communicate with and manipulate a running ISC DHCP server. All functions return a value of .Dv isc_result_t . The return values reflects the result of operations to local data structures. If an operation fails on the server for any reason, then the error result will be returned through the second parameter of the .Fn dhcpctl_wait_for_completion call. .\" .\" .\" .Pp .Fn dhcpctl_initialize sets up the data structures the library needs to do its work. This function must be called once before any other. .Pp .Fn dhcpctl_connect opens a connection to the DHCP server at the given host and port. If an authenticator has been created for the connection, then it is given as the 4th argument. On a successful return the address pointed at by the first argument will have a new connection object assigned to it. .Pp For example: .Bd -literal -offset indent s = dhcpctl_connect(&cxn, "127.0.0.1", 7911, NULL); .Ed .Pp connects to the DHCP server on the localhost via port 7911 (the standard OMAPI port). No authentication is used for the connection. .\" .\" .\" .Pp .Fn dhcpctl_wait_for_completion flushes a pending message to the server and waits for the response. The result of the request as processed on the server is returned via the second parameter. .Bd -literal -offset indent s = dhcpctl_wait_for_completion(cxn, &wv); if (s != ISC_R_SUCCESS) local_failure(s); else if (wv != ISC_R_SUCCESS) server_failure(wc); .Ed .Pp The call to .Fn dhcpctl_wait_for_completion won't return until the remote message processing completes or the connection to the server is lost. .\" .\" .\" .Pp .Fn dhcpctl_get_value extracts a value of an attribute from the handle. The value can be of any length and is treated as a sequence of bytes. The handle must have been created first with .Fn dhcpctl_new_object and opened with .Fn dhcpctl_open_object . The value is returned via the parameter named .Dq value . The last parameter is the name of attribute to retrieve. .Bd -literal -offset indent dhcpctl_data_string value = NULL; dhcpctl_handle lease; time_t thetime; s = dhcpctl_get_value (&value, lease, "ends"); assert(s == ISC_R_SUCCESS && value->len == sizeof(thetime)); memcpy(&thetime, value->value, value->len); .Ed .\" .\" .\" .Pp .Fn dhcpctl_get_boolean extracts a boolean valued attribute from the object handle. .\" .\" .\" .Pp The .Fn dhcpctl_set_value , .Fn dhcpctl_set_string_value , .Fn dhcpctl_set_boolean_value , and .Fn dhcpctl_set_int_value functions all set a value on the object handle. .\" .\" .\" .Pp .Fn dhcpctl_object_update function queues a request for all the changes made to the object handle be be sent to the remote for processing. The changes made to the atributes on the handle will be applied to remote object if permitted. .\" .\" .\" .Pp .Fn dhcpctl_object_refresh queues up a request for a fresh copy of all the attribute values to be sent from the remote to refresh the values in the local object handle. .\" .\" .\" .Pp .Fn dhcpctl_object_remove queues a request for the removal on the server of the object referenced by the handle. .\" .\" .\" .Pp The .Fn dhcpctl_set_callback function sets up a user-defined function to be called when an event completes on the given object handle. This is needed for asynchronous handling of events, versus the synchronous handling given by .Fn dhcpctl_wait_for_completion . When the function is called the first parameter is the object the event arrived for, the second is the status of the message that was processed, the third is the same value as the second parameter given to .Fn dhcpctl_set_callback . .\" .\" .\" .Pp The .Fn dhcpctl_new_authenticator creates a new authenticator object to be used for signing the messages that cross over the network. The .Dq name , .Dq algorithm , and .Dq secret values must all match what the server uses and are defined in its configuration file. The created object is returned through the first parameter and must be used as the 4th parameter to .Fn dhcpctl_connect . .\" .\" .\" .Pp .Fn dhcpctl_new_object creates a local handle for an object on the the server. The .Dq object_type parameter is the ascii name of the type of object being accessed. e.g. .Qq lease . This function only sets up local data structures, it does not queue any messages to be sent to the remote side, .Fn dhcpctl_open_object does that. .\" .\" .\" .Pp .Fn dhcpctl_open_object builds and queues the request to the remote side. This function is used with handle created via .Fn dhcpctl_new_object . The flags argument is a bit mask with the following values available for setting: .Bl -tag -offset indent -width 20 .It DHCPCTL_CREATE if the object does not exist then the remote will create it .It DHCPCTL_UPDATE update the object on the remote side using the attributes already set in the handle. .It DHCPCTL_EXCL return and error if the object exists and DHCPCTL_CREATE was also specified .El .\" .\" .\" .Pp The .Fn omapi_data_string_new function allocates a new .Ft dhcpctl_data_string object. The data string will be large enough to hold .Dq length bytes of data. The .Dq file and .Dq lineno arguments are the source file location the call is made from, typically by using the .Dv __FILE__ and .Dv __LINE__ macros or the .Dv MDL macro defined in . .\" .\" .\" .Pp .Fn dhcpctl_data_string_dereference deallocates a data string created by .Fn omapi_data_string_new . The memory for the object won't be freed until the last reference is released. .Sh EXAMPLES .Pp The following program will connect to the DHCP server running on the local host and will get the details of the existing lease for IP address 10.0.0.101. It will then print out the time the lease is due to expire. Note that most error checking has been ommitted for brevity. .Bd -literal -offset indent #include #include #include #include #include #include #include int main (int argc, char **argv) { dhcpctl_data_string ipaddrstring = NULL; dhcpctl_data_string value = NULL; dhcpctl_handle connection = NULL; dhcpctl_handle lease = NULL; isc_result_t waitstatus; struct in_addr convaddr; time_t thetime; dhcpctl_initialize (); dhcpctl_connect (&connection, "127.0.0.1", 7911, 0); dhcpctl_new_object (&lease, connection, "lease"); memset (&ipaddrstring, 0, sizeof ipaddrstring); inet_pton(AF_INET, "10.0.0.101", &convaddr); omapi_data_string_new (&ipaddrstring, 4, MDL); memcpy(ipaddrstring->value, &convaddr.s_addr, 4); dhcpctl_set_value (lease, ipaddrstring, "ip-address"); dhcpctl_open_object (lease, connection, 0); dhcpctl_wait_for_completion (lease, &waitstatus); if (waitstatus != ISC_R_SUCCESS) { /* server not authoritative */ exit (0); } dhcpctl_data_string_dereference(&ipaddrstring, MDL); dhcpctl_get_value (&value, lease, "ends"); memcpy(&thetime, value->value, value->len); dhcpctl_data_string_dereference(&value, MDL); fprintf (stdout, "ending time is %s", ctime(&thetime)); } .Ed .Sh SEE ALSO -.SH SEE ALSO omapi(3), omshell(3), dhcpd(8), dhclient(8), dhcpd.conf(5), dhclient.conf(5). -.SH AUTHOR -.B dhcpctl -was written by Ted Lemon of Nominum, Inc. Information about Nominum -and support contracts for DHCP and BIND can be found at -.B http://www.nominum.com. This preliminary documentation was -written by James Brister of Nominum, Inc. +.Sh AUTHOR +.Em dhcpctl +was written by Ted Lemon of Nominum, Inc. +This preliminary documentation was written by James Brister of Nominum, Inc. Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/dhcpctl.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/dhcpctl.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/dhcpctl.c (revision 131136) @@ -1,599 +1,595 @@ /* dhcpctl.c Subroutines providing general support for objects. */ /* - * Copyright (c) 1999-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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: dhcpctl.c,v 1.22.2.7 2004/06/10 17:59:24 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; +#endif /* not lint */ #include #include "dhcpctl.h" omapi_object_type_t *dhcpctl_callback_type; omapi_object_type_t *dhcpctl_remote_type; /* dhcpctl_initialize () Must be called before any other dhcpctl function. */ dhcpctl_status dhcpctl_initialize () { isc_result_t status; status = omapi_init(); if (status != ISC_R_SUCCESS) return status; status = omapi_object_type_register (&dhcpctl_callback_type, "dhcpctl-callback", dhcpctl_callback_set_value, dhcpctl_callback_get_value, dhcpctl_callback_destroy, dhcpctl_callback_signal_handler, dhcpctl_callback_stuff_values, 0, 0, 0, 0, 0, 0, sizeof (dhcpctl_callback_object_t), 0, RC_MISC); if (status != ISC_R_SUCCESS) return status; status = omapi_object_type_register (&dhcpctl_remote_type, "dhcpctl-remote", dhcpctl_remote_set_value, dhcpctl_remote_get_value, dhcpctl_remote_destroy, dhcpctl_remote_signal_handler, dhcpctl_remote_stuff_values, 0, 0, 0, 0, 0, 0, sizeof (dhcpctl_remote_object_t), 0, RC_MISC); if (status != ISC_R_SUCCESS) return status; return ISC_R_SUCCESS; } /* dhcpctl_connect synchronous returns nonzero status code if it didn't connect, zero otherwise stores connection handle through connection, which can be used for subsequent access to the specified server. server_name is the name of the server, and port is the TCP port on which it is listening. authinfo is the handle to an object containing authentication information. */ dhcpctl_status dhcpctl_connect (dhcpctl_handle *connection, const char *server_name, int port, dhcpctl_handle authinfo) { isc_result_t status; dhcpctl_status waitstatus; status = omapi_generic_new (connection, MDL); if (status != ISC_R_SUCCESS) { return status; } status = omapi_protocol_connect (*connection, server_name, (unsigned)port, authinfo); if (status == ISC_R_SUCCESS) return status; if (status != ISC_R_INCOMPLETE) { omapi_object_dereference (connection, MDL); return status; } status = omapi_wait_for_completion (*connection, 0); if (status != ISC_R_SUCCESS) { omapi_object_dereference (connection, MDL); return status; } return status; } /* dhcpctl_wait_for_completion synchronous returns zero if the callback completes, a nonzero status if there was some problem relating to the wait operation. The status of the queued request will be stored through s, and will also be either zero for success or nonzero for some kind of failure. Never returns until completion or until the connection to the server is lost. This performs the same function as dhcpctl_set_callback and the subsequent callback, for programs that want to do inline execution instead of using callbacks. */ dhcpctl_status dhcpctl_wait_for_completion (dhcpctl_handle h, dhcpctl_status *s) { isc_result_t status; status = omapi_wait_for_completion (h, 0); if (status != ISC_R_SUCCESS) return status; if (h -> type == dhcpctl_remote_type) *s = ((dhcpctl_remote_object_t *)h) -> waitstatus; return ISC_R_SUCCESS; } /* dhcpctl_get_value synchronous returns zero if the call succeeded, a nonzero status code if it didn't. result is the address of an empty data string (initialized with bzero or cleared with data_string_forget). On successful completion, the addressed data string will contain the value that was fetched. dhcpctl_handle refers to some dhcpctl item value_name refers to some value related to that item - e.g., for a handle associated with a completed host lookup, value could be one of "hardware-address", "dhcp-client-identifier", "known" or "client-hostname". */ dhcpctl_status dhcpctl_get_value (dhcpctl_data_string *result, dhcpctl_handle h, const char *value_name) { isc_result_t status; omapi_value_t *tv = (omapi_value_t *)0; omapi_data_string_t *value = (omapi_data_string_t *)0; unsigned len; int ip; status = omapi_get_value_str (h, (omapi_object_t *)0, value_name, &tv); if (status != ISC_R_SUCCESS) return status; switch (tv -> value -> type) { case omapi_datatype_int: len = sizeof (int); break; case omapi_datatype_string: case omapi_datatype_data: len = tv -> value -> u.buffer.len; break; case omapi_datatype_object: len = sizeof (omapi_handle_t); break; default: omapi_typed_data_dereference (&tv -> value, MDL); return ISC_R_UNEXPECTED; } status = omapi_data_string_new (result, len, MDL); if (status != ISC_R_SUCCESS) { omapi_typed_data_dereference (&tv -> value, MDL); return status; } switch (tv -> value -> type) { case omapi_datatype_int: ip = htonl (tv -> value -> u.integer); memcpy ((*result) -> value, &ip, sizeof ip); break; case omapi_datatype_string: case omapi_datatype_data: memcpy ((*result) -> value, tv -> value -> u.buffer.value, tv -> value -> u.buffer.len); break; case omapi_datatype_object: ip = htonl (tv -> value -> u.object -> handle); memcpy ((*result) -> value, &ip, sizeof ip); break; } omapi_value_dereference (&tv, MDL); return ISC_R_SUCCESS; } /* dhcpctl_get_boolean like dhcpctl_get_value, but more convenient for boolean values, since no data_string needs to be dealt with. */ dhcpctl_status dhcpctl_get_boolean (int *result, dhcpctl_handle h, const char *value_name) { isc_result_t status; dhcpctl_data_string data = (dhcpctl_data_string)0; int rv; status = dhcpctl_get_value (&data, h, value_name); if (status != ISC_R_SUCCESS) return status; if (data -> len != sizeof rv) { omapi_data_string_dereference (&data, MDL); return ISC_R_UNEXPECTED; } memcpy (&rv, data -> value, sizeof rv); *result = ntohl (rv); return ISC_R_SUCCESS; } /* dhcpctl_set_value Sets a value on an object referred to by a dhcpctl_handle. The opposite of dhcpctl_get_value. Does not update the server - just sets the value on the handle. */ dhcpctl_status dhcpctl_set_value (dhcpctl_handle h, dhcpctl_data_string value, const char *value_name) { isc_result_t status; omapi_typed_data_t *tv = (omapi_typed_data_t *)0; omapi_data_string_t *name = (omapi_data_string_t *)0; int len; status = omapi_data_string_new (&name, strlen (value_name), MDL); if (status != ISC_R_SUCCESS) return status; memcpy (name -> value, value_name, strlen (value_name)); status = omapi_typed_data_new (MDL, &tv, omapi_datatype_data, value -> len); if (status != ISC_R_SUCCESS) { omapi_data_string_dereference (&name, MDL); return status; } memcpy (tv -> u.buffer.value, value -> value, value -> len); status = omapi_set_value (h, (omapi_object_t *)0, name, tv); omapi_data_string_dereference (&name, MDL); omapi_typed_data_dereference (&tv, MDL); return status; } /* dhcpctl_set_string_value Sets a NUL-terminated ASCII value on an object referred to by a dhcpctl_handle. like dhcpctl_set_value, but saves the trouble of creating a data_string for a NUL-terminated string. Does not update the server - just sets the value on the handle. */ dhcpctl_status dhcpctl_set_string_value (dhcpctl_handle h, const char *value, const char *value_name) { isc_result_t status; omapi_typed_data_t *tv = (omapi_typed_data_t *)0; omapi_data_string_t *name = (omapi_data_string_t *)0; int len; status = omapi_data_string_new (&name, strlen (value_name), MDL); if (status != ISC_R_SUCCESS) return status; memcpy (name -> value, value_name, strlen (value_name)); status = omapi_typed_data_new (MDL, &tv, omapi_datatype_string, value); if (status != ISC_R_SUCCESS) { omapi_data_string_dereference (&name, MDL); return status; } status = omapi_set_value (h, (omapi_object_t *)0, name, tv); omapi_data_string_dereference (&name, MDL); omapi_typed_data_dereference (&tv, MDL); return status; } /* dhcpctl_set_buffer_value Sets a value on an object referred to by a dhcpctl_handle. like dhcpctl_set_value, but saves the trouble of creating a data_string for string for which we have a buffer and length. Does not update the server - just sets the value on the handle. */ dhcpctl_status dhcpctl_set_data_value (dhcpctl_handle h, const char *value, unsigned len, const char *value_name) { isc_result_t status; omapi_typed_data_t *tv = (omapi_typed_data_t *)0; omapi_data_string_t *name = (omapi_data_string_t *)0; unsigned ll; ll = strlen (value_name); status = omapi_data_string_new (&name, ll, MDL); if (status != ISC_R_SUCCESS) return status; memcpy (name -> value, value_name, ll); status = omapi_typed_data_new (MDL, &tv, omapi_datatype_data, len, value); if (status != ISC_R_SUCCESS) { omapi_data_string_dereference (&name, MDL); return status; } memcpy (tv -> u.buffer.value, value, len); status = omapi_set_value (h, (omapi_object_t *)0, name, tv); omapi_data_string_dereference (&name, MDL); omapi_typed_data_dereference (&tv, MDL); return status; } /* dhcpctl_set_null_value Sets a null value on an object referred to by a dhcpctl_handle. */ dhcpctl_status dhcpctl_set_null_value (dhcpctl_handle h, const char *value_name) { isc_result_t status; omapi_data_string_t *name = (omapi_data_string_t *)0; unsigned ll; ll = strlen (value_name); status = omapi_data_string_new (&name, ll, MDL); if (status != ISC_R_SUCCESS) return status; memcpy (name -> value, value_name, ll); status = omapi_set_value (h, (omapi_object_t *)0, name, (omapi_typed_data_t *)0); omapi_data_string_dereference (&name, MDL); return status; } /* dhcpctl_set_boolean_value Sets a boolean value on an object - like dhcpctl_set_value, only more convenient for booleans. */ dhcpctl_status dhcpctl_set_boolean_value (dhcpctl_handle h, int value, const char *value_name) { isc_result_t status; omapi_typed_data_t *tv = (omapi_typed_data_t *)0; omapi_data_string_t *name = (omapi_data_string_t *)0; int len; status = omapi_data_string_new (&name, strlen (value_name), MDL); if (status != ISC_R_SUCCESS) return status; memcpy (name -> value, value_name, strlen (value_name)); status = omapi_typed_data_new (MDL, &tv, omapi_datatype_int, value); if (status != ISC_R_SUCCESS) { omapi_data_string_dereference (&name, MDL); return status; } status = omapi_set_value (h, (omapi_object_t *)0, name, tv); omapi_data_string_dereference (&name, MDL); omapi_typed_data_dereference (&tv, MDL); return status; } /* dhcpctl_set_int_value Sets a boolean value on an object - like dhcpctl_set_value, only more convenient for booleans. */ dhcpctl_status dhcpctl_set_int_value (dhcpctl_handle h, int value, const char *value_name) { isc_result_t status; omapi_typed_data_t *tv = (omapi_typed_data_t *)0; omapi_data_string_t *name = (omapi_data_string_t *)0; int len; status = omapi_data_string_new (&name, strlen (value_name), MDL); if (status != ISC_R_SUCCESS) return status; memcpy (name -> value, value_name, strlen (value_name)); status = omapi_typed_data_new (MDL, &tv, omapi_datatype_int, value); if (status != ISC_R_SUCCESS) { omapi_data_string_dereference (&name, MDL); return status; } status = omapi_set_value (h, (omapi_object_t *)0, name, tv); omapi_data_string_dereference (&name, MDL); omapi_typed_data_dereference (&tv, MDL); return status; } /* dhcpctl_object_update Queues an update on the object referenced by the handle (there can't be any other work in progress on the handle). An update means local parameters will be sent to the server. */ dhcpctl_status dhcpctl_object_update (dhcpctl_handle connection, dhcpctl_handle h) { isc_result_t status; omapi_object_t *message = (omapi_object_t *)0; dhcpctl_remote_object_t *ro; if (h -> type != dhcpctl_remote_type) return ISC_R_INVALIDARG; ro = (dhcpctl_remote_object_t *)h; status = omapi_message_new (&message, MDL); if (status != ISC_R_SUCCESS) { omapi_object_dereference (&message, MDL); return status; } status = omapi_set_int_value (message, (omapi_object_t *)0, "op", OMAPI_OP_UPDATE); if (status != ISC_R_SUCCESS) { omapi_object_dereference (&message, MDL); return status; } status = omapi_set_object_value (message, (omapi_object_t *)0, "object", h); if (status != ISC_R_SUCCESS) { omapi_object_dereference (&message, MDL); return status; } status = omapi_set_int_value (message, (omapi_object_t *)0, "handle", (int)(ro -> remote_handle)); if (status != ISC_R_SUCCESS) { omapi_object_dereference (&message, MDL); return status; } omapi_message_register (message); status = omapi_protocol_send_message (connection -> outer, (omapi_object_t *)0, message, (omapi_object_t *)0); omapi_object_dereference (&message, MDL); return status; } /* Requests a refresh on the object referenced by the handle (there can't be any other work in progress on the handle). A refresh means local parameters are updated from the server. */ dhcpctl_status dhcpctl_object_refresh (dhcpctl_handle connection, dhcpctl_handle h) { isc_result_t status; omapi_object_t *message = (omapi_object_t *)0; dhcpctl_remote_object_t *ro; if (h -> type != dhcpctl_remote_type) return ISC_R_INVALIDARG; ro = (dhcpctl_remote_object_t *)h; status = omapi_message_new (&message, MDL); if (status != ISC_R_SUCCESS) { omapi_object_dereference (&message, MDL); return status; } status = omapi_set_int_value (message, (omapi_object_t *)0, "op", OMAPI_OP_REFRESH); if (status != ISC_R_SUCCESS) { omapi_object_dereference (&message, MDL); return status; } status = omapi_set_int_value (message, (omapi_object_t *)0, "handle", (int)(ro -> remote_handle)); if (status != ISC_R_SUCCESS) { omapi_object_dereference (&message, MDL); return status; } omapi_message_register (message); status = omapi_protocol_send_message (connection -> outer, (omapi_object_t *)0, message, (omapi_object_t *)0); /* We don't want to send the contents of the object down the wire, but we do need to reference it so that we know what to do with the update. */ status = omapi_set_object_value (message, (omapi_object_t *)0, "object", h); if (status != ISC_R_SUCCESS) { omapi_object_dereference (&message, MDL); return status; } omapi_object_dereference (&message, MDL); return status; } /* Requests the removal of the object referenced by the handle (there can't be any other work in progress on the handle). A removal means that all searchable references to the object on the server are deleted. */ dhcpctl_status dhcpctl_object_remove (dhcpctl_handle connection, dhcpctl_handle h) { isc_result_t status; omapi_object_t *message = (omapi_object_t *)0; dhcpctl_remote_object_t *ro; if (h -> type != dhcpctl_remote_type) return ISC_R_INVALIDARG; ro = (dhcpctl_remote_object_t *)h; status = omapi_message_new (&message, MDL); if (status != ISC_R_SUCCESS) { omapi_object_dereference (&message, MDL); return status; } status = omapi_set_int_value (message, (omapi_object_t *)0, "op", OMAPI_OP_DELETE); if (status != ISC_R_SUCCESS) { omapi_object_dereference (&message, MDL); return status; } status = omapi_set_int_value (message, (omapi_object_t *)0, "handle", (int)(ro -> remote_handle)); if (status != ISC_R_SUCCESS) { omapi_object_dereference (&message, MDL); return status; } status = omapi_set_object_value (message, (omapi_object_t *)0, "notify-object", h); if (status != ISC_R_SUCCESS) { omapi_object_dereference (&message, MDL); return status; } omapi_message_register (message); status = omapi_protocol_send_message (connection -> outer, (omapi_object_t *)0, message, (omapi_object_t *)0); omapi_object_dereference (&message, MDL); return status; } isc_result_t dhcpctl_data_string_dereference (dhcpctl_data_string *vp, const char *file, int line) { return omapi_data_string_dereference (vp, file, line); } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/dhcpctl.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/dhcpctl.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/dhcpctl.h (revision 131136) @@ -1,134 +1,125 @@ -/* dhcpctl.h +/* $Id: dhcpctl.h,v 1.13.2.4 2004/06/10 17:59:24 dhankins Exp $ Subroutines providing general support for objects. */ /* - * Copyright (c) 1999-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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 _DHCPCTL_H_ #define _DHCPCTL_H_ #include typedef isc_result_t dhcpctl_status; typedef omapi_object_t *dhcpctl_handle; typedef omapi_data_string_t *dhcpctl_data_string; #define dhcpctl_null_handle ((dhcpctl_handle) 0) #define DHCPCTL_CREATE OMAPI_CREATE #define DHCPCTL_UPDATE OMAPI_UPDATE #define DHCPCTL_EXCL OMAPI_EXCL typedef struct { OMAPI_OBJECT_PREAMBLE; omapi_object_t *object; void *data; void (*callback) (dhcpctl_handle, dhcpctl_status, void *); } dhcpctl_callback_object_t; typedef struct { OMAPI_OBJECT_PREAMBLE; omapi_typed_data_t *rtype; isc_result_t waitstatus; omapi_typed_data_t *message; omapi_handle_t remote_handle; } dhcpctl_remote_object_t; extern omapi_object_type_t *dhcpctl_callback_type; extern omapi_object_type_t *dhcpctl_remote_type; dhcpctl_status dhcpctl_initialize (void); dhcpctl_status dhcpctl_connect (dhcpctl_handle *, const char *, int, dhcpctl_handle); dhcpctl_status dhcpctl_wait_for_completion (dhcpctl_handle, dhcpctl_status *); dhcpctl_status dhcpctl_get_value (dhcpctl_data_string *, dhcpctl_handle, const char *); dhcpctl_status dhcpctl_get_boolean (int *, dhcpctl_handle, const char *); dhcpctl_status dhcpctl_set_value (dhcpctl_handle, dhcpctl_data_string, const char *); dhcpctl_status dhcpctl_set_string_value (dhcpctl_handle, const char *, const char *); dhcpctl_status dhcpctl_set_data_value (dhcpctl_handle, const char *, unsigned, const char *); dhcpctl_status dhcpctl_set_null_value (dhcpctl_handle, const char *); dhcpctl_status dhcpctl_set_boolean_value (dhcpctl_handle, int, const char *); dhcpctl_status dhcpctl_set_int_value (dhcpctl_handle, int, const char *); dhcpctl_status dhcpctl_object_update (dhcpctl_handle, dhcpctl_handle); dhcpctl_status dhcpctl_object_refresh (dhcpctl_handle, dhcpctl_handle); dhcpctl_status dhcpctl_object_remove (dhcpctl_handle, dhcpctl_handle); dhcpctl_status dhcpctl_set_callback (dhcpctl_handle, void *, void (*) (dhcpctl_handle, dhcpctl_status, void *)); isc_result_t dhcpctl_callback_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t dhcpctl_callback_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t dhcpctl_callback_destroy (omapi_object_t *, const char *, int); isc_result_t dhcpctl_callback_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t dhcpctl_callback_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); dhcpctl_status dhcpctl_new_authenticator (dhcpctl_handle *, const char *, const char *, const unsigned char *, unsigned); dhcpctl_status dhcpctl_open_object (dhcpctl_handle, dhcpctl_handle, int); dhcpctl_status dhcpctl_new_object (dhcpctl_handle *, dhcpctl_handle, const char *); isc_result_t dhcpctl_remote_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t dhcpctl_remote_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t dhcpctl_remote_destroy (omapi_object_t *, const char *, int); isc_result_t dhcpctl_remote_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t dhcpctl_remote_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t dhcpctl_data_string_dereference (dhcpctl_data_string *, const char *, int); #endif /* _DHCPCTL_H_ */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/omshell.1 =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/omshell.1 (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/omshell.1 (revision 131136) @@ -1,341 +1,334 @@ -.\" omshell.1 +.\" $Id: omshell.1,v 1.1.2.5 2004/06/10 17:59:24 dhankins Exp $ .\" -.\" Copyright (c) 2001-2002 Internet Software Consortium. -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: +.\" Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (c) 2001-2003 by Internet Software Consortium .\" -.\" 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. +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. .\" -.\" 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. +.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +.\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.\" This software has been written for the Internet Software Consortium +.\" Internet Systems Consortium, Inc. +.\" 950 Charter Street +.\" Redwood City, CA 94063 +.\" +.\" http://www.isc.org/ +.\" +.\" This software has been written for Internet Systems Consortium .\" by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. -.\" To learn more about the Internet Software Consortium, see +.\" To learn more about Internet Systems 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 omshell 1 .SH NAME omshell - OMAPI Command Shell .SH SYNOPSIS .B omshell .SH DESCRIPTION The OMAPI Command Shell, omshell, provides an interactive way to connect to, query, and possibly change, the ISC DHCP Server's state via OMAPI, the Object Management API. By using OMAPI and omshell, you do not have to stop, make changes, and then restart the DHCP server, but can make the changes while the server is running. Omshell provides a way of accessing OMAPI. .PP OMAPI is simply a communications mechanism that allows you to manipulate objects. In order to actually \fIuse\fR omshell, you .I must understand what objects are available and how to use them. Documentation for OMAPI objects can be found in the documentation for the server that provides them - for example, in the \fBdhcpd(1)\fR manual page and the \fBdhclient(1)\fR manual page. .SH CONTRIBUTIONS .PP This software is free software. At various times its development has been underwritten by various organizations, including the ISC and Vixie Enterprises. The development of 3.0 has been funded almost entirely by Nominum, Inc. .PP At this point development is being shepherded by Ted Lemon, and hosted by the ISC, but the future of this project depends on you. If you have features you want, please consider implementing them. .SH LOCAL AND REMOTE OBJECTS .PP Throughout this document, there are references to local and remote objects. Local objects are ones created in omshell with the \fBnew\fR command. Remote objects are ones on the server: leases, hosts, and groups that the DHCP server knows about. Local and remote objects are associated together to enable viewing and modification of object attributes. Also, new remote objects can be created to match local objects. .SH OPENING A CONNECTION .PP omshell is started from the command line. Once omshell is started, there are several commands that can be issued: .PP .B server \fIaddress\fR .RS 0.5i where address is the IP address of the DHCP server to connect to. If this is not specified, the default server is 127.0.0.1 (localhost). .RE .PP .B port \fInumber\fR .RS 0.5i where number is the port that OMAPI listens on. By default, this is 7911. .RE .PP .B key \fIname secret\fR .RS 0.5i This specifies the TSIG key to use to authenticate the OMAPI transactions. \fIname\fR is the name of a key defined in \fIdhcpd.conf\fR with the \fBomapi-key\fR statement. The \fIsecret\fR is the secret generated from \fBdnssec-keygen\fR or another key generation program. .RE .PP .B connect .RS 0.5i This starts the OMAPI connection to the server as specified by the \fIserver\fR statement. .SH CREATING LOCAL OBJECTS .PP Any object defined in OMAPI can be created, queried, and/or modified. The object types available to OMAPI are defined in \fBdhcpd(8)\fR and \fBdhclient\fR. When using omshell, objects are first defined locally, manipulated as desired, and then associated with an object on the server. Only one object can be manipulated at a time. To create a local object, use .PP .B new \fIobject-type\fR .RS 0.5i \fIobject-type\fR is one of group, host, or lease. .RE .PP At this point, you now have an object that you can set properties on. For example, if a new lease object was created with \fInew lease\fR, any of a lease's attributes can be set as follows: .PP .B set \fIattribute-name = value\fR .RS 0.5i \fBAttribute names are defined in \fBdhcpd(8)\fR and \fBdhclient(8)\fR. Values should be quoted if they are strings. So, to set a lease's IP address, you would do the following: \fB set ip-address = 192.168.4.50\fR .SH ASSOCIATING LOCAL AND REMOTE OBJECTS .PP At this point, you can query the server for information about this lease, by .PP .B open .PP Now, the local lease object you created and set the IP address for is associated with the corresponding lease object on the DHCP server. All of the lease attributes from the DHCP server are now also the attributes on the local object, and will be shown in omshell. .SH VIEWING A REMOTE OBJECT .PP To query a lease of address 192.168.4.50, and find out its attributes, after connecting to the server, take the following steps: .PP .B new "lease" .PP This creates a new local lease object. .PP .B set ip-address = 192.168.4.50 .PP This sets the \fIlocal\fR object's IP address to be 192.168.4.50 .PP .B open .PP Now, if a lease with that IP address exists, you will see all the information the DHCP server has about that particular lease. Any data that isn't readily printable text will show up in colon-separated hexadecimal values. In this example, output back from the server for the entire transaction might look like this: .nf .sp 1 > new "lease" obj: lease > set ip-address = 192.168.4.50 obj: lease ip-address = c0:a8:04:32 > open obj: lease ip-address = c0:a8:04:32 state = 00:00:00:02 dhcp-client-identifier = 01:00:10:a4:b2:36:2c client-hostname = "wendelina" subnet = 00:00:00:06 pool = 00:00:00:07 hardware-address = 00:10:a4:b2:36:2c hardware-type = 00:00:00:01 ends = dc:d9:0d:3b starts = 5c:9f:04:3b tstp = 00:00:00:00 tsfp = 00:00:00:00 cltt = 00:00:00:00 .fi .PP As you can see here, the IP address is represented in hexadecimal, as are the starting and ending times of the lease. .SH MODIFYING A REMOTE OBJECT .PP Attributes of remote objects are updated by using the \fBset\fR command as before, and then issuing an \fBupdate\fR command. The \fBset\fR command sets the attributes on the current local object, and the \fBupdate\fR command pushes those changes out to the server. .PP Continuing with the previous example, if a \fBset client-hostname = "something-else"\fR was issued, followed by an \fBupdate\fR command, the output would look about like this: .nf .sp 1 > set client-hostname = "something-else" obj: lease ip-address = c0:a8:04:32 state = 00:00:00:02 dhcp-client-identifier = 01:00:10:a4:b2:36:2c client-hostname = "something-else" subnet = 00:00:00:06 pool = 00:00:00:07 hardware-address = 00:10:a4:b2:36:2c hardware-type = 00:00:00:01 ends = dc:d9:0d:3b starts = 5c:9f:04:3b tstp = 00:00:00:00 tsfp = 00:00:00:00 cltt = 00:00:00:00 > update obj: lease ip-address = c0:a8:04:32 state = 00:00:00:02 dhcp-client-identifier = 01:00:10:a4:b2:36:2c client-hostname = "something-else" subnet = 00:00:00:06 pool = 00:00:00:07 hardware-address = 00:10:a4:b2:36:2c hardware-type = 00:00:00:01 ends = dc:d9:0d:3b starts = 5c:9f:04:3b tstp = 00:00:00:00 tsfp = 00:00:00:00 cltt = 00:00:00:00 .fi .SH NEW REMOTE OBJECTS .PP New remote objects are created much in the same way that existing server objects are modified. Create a local object using \fBnew\fR, set the attributes as you'd wish them to be, and then create the remote object with the same properties by using .PP .B create .PP Now a new object exists on the DHCP server which matches the properties that you gave your local object. Objects created via OMAPI are saved into the dhcpd.leases file. .PP For example, if a new host with the IP address of 192.168.4.40 needs to be created it would be done as follows: .nf .sp 1 > new host obj: host > set name = "some-host" obj: host name = "some-host" > set hardware-address = 00:80:c7:84:b1:94 obj: host name = "some-host" hardware-address = 00:80:c7:84:b1:94 > set hardware-type = 1 obj: host name = "some-host" hardware-address = 00:80:c7:84:b1:94 hardware-type = 1 > set ip-address = 192.168.4.40 obj: host name = "some-host" hardware-address = 00:80:c7:84:b1:94 hardware-type = 1 ip-address = c0:a8:04:28 > create obj: host name = "some-host" hardware-address = 00:80:c7:84:b1:94 hardware-type = 00:00:00:01 ip-address = c0:a8:04:28 > .fi .PP Your dhcpd.leases file would then have an entry like this in it: .nf .sp 1 host some-host { dynamic; hardware ethernet 00:80:c7:84:b1:94; fixed-address 192.168.4.40; } .fi .PP The \fIdynamic;\fR line is to denote that this host entry did not come from dhcpd.conf, but was created dynamically via OMAPI. .SH RESETTING ATTRIBUTES .PP If you want to remove an attribute from an object, you can do this with the \fBunset\fR command. Once you have unset an attribute, you must use the \fBupdate\fR command to update the remote object. So, if the host "some-host" from the previous example will not have a static IP address anymore, the commands in omshell would look like this: .nf .sp 1 obj: host name = "some-host" hardware-address = 00:80:c7:84:b1:94 hardware-type = 00:00:00:01 ip-address = c0:a8:04:28 > unset ip-address obj: host name = "some-host" hardware-address = 00:80:c7:84:b1:94 hardware-type = 00:00:00:01 ip-address = > .fi .SH REFRESHING OBJECTS .PP A local object may be refreshed with the current remote object properties using the \fBrefresh\fR command. This is useful for object that change periodically, like leases, to see if they have been updated. This isn't particularly useful for hosts. .SH DELETING OBJECTS .PP Any remote object that can be created can also be destroyed. This is done by creating a new local object, setting attributes, associating the local and remote object using \fBopen\fI, and then using the \fBremove\fR command. If the host "some-host" from before was created in error, this could be corrected as follows: .nf .sp 1 obj: host name = "some-host" hardware-address = 00:80:c7:84:b1:94 hardware-type = 00:00:00:01 ip-address = c0:a8:04:28 > remove obj: > .fi .SH HELP .PP The \fBhelp\fR command will print out all of the commands available in omshell, with some syntax pointers. .SH SEE ALSO dhcpctl(3), omapi(3), dhcpd(8), dhclient(8), dhcpd.conf(5), dhclient.conf(5). .SH AUTHOR .B omshell was written by Ted Lemon of Nominum, Inc. Information about Nominum and support contracts for DHCP and BIND can be found at .B http://www.nominum.com. This preliminary documentation was written by Wendy Verschoor of Nominum, Inc., while she was testing omshell. Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/omshell.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/omshell.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/omshell.c (revision 131136) @@ -1,728 +1,724 @@ /* omshell.c Examine and modify omapi objects. */ /* - * Copyright (c) 2001-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2001-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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: omshell.c,v 1.7.2.16 2004/06/10 17:59:24 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; +#endif /* not lint */ #include #include #include #include #include #include #include #include "dhcpctl.h" #include "dhcpd.h" /* Fixups */ isc_result_t find_class (struct class **c, const char *n, const char *f, int l) { return 0; } int parse_allow_deny (struct option_cache **oc, struct parse *cfile, int flag) { return 0; } void dhcp (struct packet *packet) { } void bootp (struct packet *packet) { } int check_collection (struct packet *p, struct lease *l, struct collection *c) { return 0; } void classify (struct packet *packet, struct class *class) { } static void usage (char *s) { fprintf (stderr, "Usage: %s\n", s); exit (1); } static void check (isc_result_t status, const char *func) { if (status != ISC_R_SUCCESS) { fprintf (stderr, "%s: %s\n", func, isc_result_totext (status)); exit (1); } } int main (int argc, char **argv, char **envp) { isc_result_t status, waitstatus; dhcpctl_handle connection; dhcpctl_handle authenticator; dhcpctl_handle oh; dhcpctl_data_string cid, ip_addr; dhcpctl_data_string result, groupname, identifier; struct data_string secret; const char *name = 0, *algorithm = "hmac-md5"; int i, j; int port = 7911; const char *server = "127.0.0.1"; struct parse *cfile; enum dhcp_token token; const char *val; char *s; char buf[1024]; char s1[1024]; int connected = 0; for (i = 1; i < argc; i++) { usage(argv[0]); } /* Initially, log errors to stderr as well as to syslogd. */ #ifdef SYSLOG_4_2 openlog ("omshell", LOG_NDELAY); log_priority = DHCPD_LOG_FACILITY; #else openlog ("omshell", LOG_NDELAY, DHCPD_LOG_FACILITY); #endif status = dhcpctl_initialize (); if (status != ISC_R_SUCCESS) { fprintf (stderr, "dhcpctl_initialize: %s\n", isc_result_totext (status)); exit (1); } memset (&oh, 0, sizeof oh); do { if (!connected) { } else if (oh == NULL) { printf ("obj: \n"); } else { dhcpctl_remote_object_t *r = (dhcpctl_remote_object_t *)oh; omapi_generic_object_t *g = (omapi_generic_object_t *)(r -> inner); printf ("obj: "); if (r -> rtype -> type != omapi_datatype_string) { printf ("?\n"); } else { printf ("%.*s\n", (int)(r -> rtype -> u . buffer . len), r -> rtype -> u . buffer . value); } for (i = 0; i < g -> nvalues; i++) { omapi_value_t *v = g -> values [i]; if (!g -> values [i]) continue; printf ("%.*s = ", (int)v -> name -> len, v -> name -> value); if (!v -> value) { printf ("\n"); continue; } switch (v -> value -> type) { case omapi_datatype_int: printf ("%d\n", v -> value -> u . integer); break; case omapi_datatype_string: printf ("\"%.*s\"\n", (int) v -> value -> u.buffer.len, v -> value -> u.buffer.value); break; case omapi_datatype_data: printf ("%s\n", print_hex_1 (v -> value -> u.buffer.len, v -> value -> u.buffer.value, 60)); break; case omapi_datatype_object: printf ("\n"); break; } } } fputs ("> ", stdout); fflush (stdout); if (fgets (buf, sizeof(buf), stdin) == NULL) break; status = new_parse (&cfile, 0, buf, strlen(buf), "", 1); check(status, "new_parse()"); token = next_token (&val, (unsigned *)0, cfile); switch (token) { default: parse_warn (cfile, "unknown token: %s", val); skip_to_semi (cfile); break; case END_OF_FILE: case EOL: break; case TOKEN_HELP: case '?': printf ("Commands:\n"); printf (" port \n"); printf (" server \n"); printf (" key \n"); printf (" connect\n"); printf (" new \n"); printf (" set = \n"); printf (" create\n"); printf (" open\n"); printf (" update\n"); printf (" unset \n"); printf (" refresh\n"); printf (" remove\n"); skip_to_semi (cfile); break; case PORT: token = next_token (&val, (unsigned *)0, cfile); if (is_identifier (token)) { struct servent *se; se = getservbyname (val, "tcp"); if (se) port = ntohs (se -> s_port); else { printf ("unknown service name: %s\n", val); break; } } else if (token == NUMBER) { port = atoi (val); } else { skip_to_semi (cfile); printf ("usage: port \n"); break; } token = next_token (&val, (unsigned *)0, cfile); if (token != END_OF_FILE && token != EOL) { printf ("usage: port \n"); skip_to_semi (cfile); break; } break; case SERVER: token = next_token (&val, (unsigned *)0, cfile); if (token == NUMBER) { int alen = (sizeof buf) - 1; int len; s = &buf [0]; len = strlen (val); if (len + 1 > alen) { baddq: printf ("usage: server \n"); skip_to_semi (cfile); break; } strcpy (buf, val); s += len; token = next_token (&val, (unsigned *)0, cfile); if (token != DOT) goto baddq; *s++ = '.'; token = next_token (&val, (unsigned *)0, cfile); if (token != NUMBER) goto baddq; len = strlen (val); if (len + 1 > alen) goto baddq; strcpy (s, val); s += len; token = next_token (&val, (unsigned *)0, cfile); if (token != DOT) goto baddq; *s++ = '.'; token = next_token (&val, (unsigned *)0, cfile); if (token != NUMBER) goto baddq; len = strlen (val); if (len + 1 > alen) goto baddq; strcpy (s, val); s += len; token = next_token (&val, (unsigned *)0, cfile); if (token != DOT) goto baddq; *s++ = '.'; token = next_token (&val, (unsigned *)0, cfile); if (token != NUMBER) goto baddq; len = strlen (val); if (len + 1 > alen) goto baddq; strcpy (s, val); val = &buf [0]; } else if (is_identifier (token)) { /* Use val directly. */ } else { printf ("usage: server \n"); skip_to_semi (cfile); break; } s = dmalloc (strlen (val) + 1, MDL); if (!server) { printf ("no memory to store server name.\n"); skip_to_semi (cfile); break; } strcpy (s, val); server = s; token = next_token (&val, (unsigned *)0, cfile); if (token != END_OF_FILE && token != EOL) { printf ("usage: server \n"); skip_to_semi (cfile); break; } break; case KEY: token = next_token (&val, (unsigned *)0, cfile); if (!is_identifier (token)) { printf ("usage: key \n"); skip_to_semi (cfile); break; } s = dmalloc (strlen (val) + 1, MDL); if (!s) { printf ("no memory for key name.\n"); skip_to_semi (cfile); break; } strcpy (s, val); name = s; memset (&secret, 0, sizeof secret); if (!parse_base64 (&secret, cfile)) { skip_to_semi (cfile); break; } token = next_token (&val, (unsigned *)0, cfile); if (token != END_OF_FILE && token != EOL) { printf ("usage: key \n"); skip_to_semi (cfile); break; } break; case CONNECT: token = next_token (&val, (unsigned *)0, cfile); if (token != END_OF_FILE && token != EOL) { printf ("usage: connect\n"); skip_to_semi (cfile); break; } authenticator = dhcpctl_null_handle; if (name) { status = dhcpctl_new_authenticator (&authenticator, name, algorithm, secret.data, secret.len); if (status != ISC_R_SUCCESS) { fprintf (stderr, "Cannot create authenticator: %s\n", isc_result_totext (status)); break; } } memset (&connection, 0, sizeof connection); status = dhcpctl_connect (&connection, server, port, authenticator); if (status != ISC_R_SUCCESS) { fprintf (stderr, "dhcpctl_connect: %s\n", isc_result_totext (status)); break; } connected = 1; break; case TOKEN_NEW: token = next_token (&val, (unsigned *)0, cfile); if ((!is_identifier (token) && token != STRING)) { printf ("usage: new \n"); break; } if (oh) { printf ("an object is already open.\n"); skip_to_semi (cfile); break; } if (!connected) { printf ("not connected.\n"); skip_to_semi (cfile); break; } status = dhcpctl_new_object (&oh, connection, val); if (status != ISC_R_SUCCESS) { printf ("can't create object: %s\n", isc_result_totext (status)); break; } token = next_token (&val, (unsigned *)0, cfile); if (token != END_OF_FILE && token != EOL) { printf ("usage: new \n"); skip_to_semi (cfile); break; } break; case TOKEN_CLOSE: token = next_token (&val, (unsigned *)0, cfile); if (token != END_OF_FILE && token != EOL) { printf ("usage: close\n"); skip_to_semi (cfile); break; } if (!connected) { printf ("not connected.\n"); skip_to_semi (cfile); break; } if (!oh) { printf ("not open.\n"); skip_to_semi (cfile); break; } omapi_object_dereference (&oh, MDL); break; case TOKEN_SET: token = next_token (&val, (unsigned *)0, cfile); if ((!is_identifier (token) && token != STRING)) { set_usage: printf ("usage: set = \n"); skip_to_semi (cfile); break; } if (oh == NULL) { printf ("no open object.\n"); skip_to_semi (cfile); break; } if (!connected) { printf ("not connected.\n"); skip_to_semi (cfile); break; } s1[0] = '\0'; strncat (s1, val, sizeof(s1)-1); token = next_token (&val, (unsigned *)0, cfile); if (token != EQUAL) goto set_usage; token = next_token (&val, (unsigned *)0, cfile); switch (token) { case STRING: dhcpctl_set_string_value (oh, val, s1); token = next_token (&val, (unsigned *)0, cfile); break; case NUMBER: strcpy (buf, val); token = peek_token (&val, (unsigned *)0, cfile); /* Colon-seperated hex list? */ if (token == COLON) goto cshl; else if (token == DOT) { s = buf; val = buf; do { int intval = atoi (val); dotiszero: if (intval > 255) { parse_warn (cfile, "dotted octet > 255: %s", val); skip_to_semi (cfile); goto badnum; } *s++ = intval; token = next_token (&val, (unsigned *)0, cfile); if (token != DOT) break; /* DOT is zero. */ while ((token = next_token (&val, (unsigned *)0, cfile)) == DOT) *s++ = 0; } while (token == NUMBER); dhcpctl_set_data_value (oh, buf, (unsigned)(s - buf), s1); break; } dhcpctl_set_int_value (oh, atoi (buf), s1); token = next_token (&val, (unsigned *)0, cfile); badnum: break; case NUMBER_OR_NAME: strcpy (buf, val); cshl: s = buf; val = buf; do { convert_num (cfile, (unsigned char *)s, val, 16, 8); ++s; token = next_token (&val, (unsigned *)0, cfile); if (token != COLON) break; token = next_token (&val, (unsigned *)0, cfile); } while (token == NUMBER || token == NUMBER_OR_NAME); dhcpctl_set_data_value (oh, buf, (unsigned)(s - buf), s1); break; default: printf ("invalid value.\n"); skip_to_semi (cfile); } if (token != END_OF_FILE && token != EOL) goto set_usage; break; case UNSET: token = next_token (&val, (unsigned *)0, cfile); if ((!is_identifier (token) && token != STRING)) { unset_usage: printf ("usage: unset \n"); skip_to_semi (cfile); break; } if (!oh) { printf ("no open object.\n"); skip_to_semi (cfile); break; } if (!connected) { printf ("not connected.\n"); skip_to_semi (cfile); break; } s1[0] = '\0'; strncat (s1, val, sizeof(s1)-1); token = next_token (&val, (unsigned *)0, cfile); if (token != END_OF_FILE && token != EOL) goto unset_usage; dhcpctl_set_null_value (oh, s1); break; case TOKEN_CREATE: case TOKEN_OPEN: i = token; token = next_token (&val, (unsigned *)0, cfile); if (token != END_OF_FILE && token != EOL) { printf ("usage: %s\n", val); skip_to_semi (cfile); break; } if (!connected) { printf ("not connected.\n"); skip_to_semi (cfile); break; } if (!oh) { printf ("you must make a new object first!\n"); skip_to_semi (cfile); break; } if (i == TOKEN_CREATE) i = DHCPCTL_CREATE | DHCPCTL_EXCL; else i = 0; status = dhcpctl_open_object (oh, connection, i); if (status == ISC_R_SUCCESS) status = dhcpctl_wait_for_completion (oh, &waitstatus); if (status == ISC_R_SUCCESS) status = waitstatus; if (status != ISC_R_SUCCESS) { printf ("can't open object: %s\n", isc_result_totext (status)); break; } break; case UPDATE: token = next_token (&val, (unsigned *)0, cfile); if (token != END_OF_FILE && token != EOL) { printf ("usage: %s\n", val); skip_to_semi (cfile); break; } if (!connected) { printf ("not connected.\n"); skip_to_semi (cfile); break; } if (!oh) { printf ("you haven't opened an object yet!\n"); skip_to_semi (cfile); break; } status = dhcpctl_object_update(connection, oh); if (status == ISC_R_SUCCESS) status = dhcpctl_wait_for_completion (oh, &waitstatus); if (status == ISC_R_SUCCESS) status = waitstatus; if (status != ISC_R_SUCCESS) { printf ("can't update object: %s\n", isc_result_totext (status)); break; } break; case REMOVE: token = next_token (&val, (unsigned *)0, cfile); if (token != END_OF_FILE && token != EOL) { printf ("usage: remove\n"); skip_to_semi (cfile); break; } if (!connected) { printf ("not connected.\n"); break; } if (!oh) { printf ("no object.\n"); break; } status = dhcpctl_object_remove(connection, oh); if (status == ISC_R_SUCCESS) status = dhcpctl_wait_for_completion (oh, &waitstatus); if (status == ISC_R_SUCCESS) status = waitstatus; if (status != ISC_R_SUCCESS) { printf ("can't destroy object: %s\n", isc_result_totext (status)); break; } omapi_object_dereference (&oh, MDL); break; case REFRESH: token = next_token (&val, (unsigned *)0, cfile); if (token != END_OF_FILE && token != EOL) { printf ("usage: refresh\n"); skip_to_semi (cfile); break; } if (!connected) { printf ("not connected.\n"); break; } if (!oh) { printf ("no object.\n"); break; } status = dhcpctl_object_refresh(connection, oh); if (status == ISC_R_SUCCESS) status = dhcpctl_wait_for_completion (oh, &waitstatus); if (status == ISC_R_SUCCESS) status = waitstatus; if (status != ISC_R_SUCCESS) { printf ("can't refresh object: %s\n", isc_result_totext (status)); break; } break; } } while (1); exit (0); } /* Sigh */ isc_result_t dhcp_set_control_state (control_object_state_t oldstate, control_object_state_t newstate) { return ISC_R_SUCCESS; } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/remote.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/remote.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/dhcpctl/remote.c (revision 131136) @@ -1,371 +1,367 @@ /* remote.c The dhcpctl remote object. */ /* - * Copyright (c) 1999-2003 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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: remote.c,v 1.12.2.6 2004/06/10 17:59:24 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; +#endif /* not lint */ #include #include "dhcpctl.h" /* dhcpctl_new_authenticator synchronous - creates an authenticator object. returns nonzero status code if the object couldn't be created stores handle to authenticator through h if successful, and returns zero. name is the authenticator name (NUL-terminated string). algorithm is the NUL-terminated string name of the algorithm to use (currently, only "hmac-md5" is supported). secret and secret_len is the key secret. */ dhcpctl_status dhcpctl_new_authenticator (dhcpctl_handle *h, const char *name, const char *algorithm, const unsigned char *secret, unsigned secret_len) { struct auth_key *key = (struct auth_key *)0; isc_result_t status; status = omapi_auth_key_new (&key, MDL); if (status != ISC_R_SUCCESS) return status; key -> name = dmalloc (strlen (name) + 1, MDL); if (!key -> name) { omapi_auth_key_dereference (&key, MDL); return ISC_R_NOMEMORY; } strcpy (key -> name, name); /* If the algorithm name isn't an FQDN, tack on the .SIG-ALG.REG.NET. domain. */ if (strchr (algorithm, '.') == 0) { static char add[] = ".SIG-ALG.REG.INT."; key -> algorithm = dmalloc (strlen (algorithm) + sizeof (add), MDL); if (!key -> algorithm) { omapi_auth_key_dereference (&key, MDL); return ISC_R_NOMEMORY; } strcpy (key -> algorithm, algorithm); strcat (key -> algorithm, add); } else { key -> algorithm = dmalloc (strlen (algorithm) + 1, MDL); if (!key -> algorithm) { omapi_auth_key_dereference (&key, MDL); return ISC_R_NOMEMORY; } strcpy (key -> algorithm, algorithm); } status = omapi_data_string_new (&key -> key, secret_len, MDL); if (status != ISC_R_SUCCESS) { omapi_auth_key_dereference (&key, MDL); return status; } memcpy (key -> key -> value, secret, secret_len); key -> key -> len = secret_len; *h = (dhcpctl_handle) key; return ISC_R_SUCCESS; } /* dhcpctl_new_object synchronous - creates a local handle for a host entry. returns nonzero status code if the local host entry couldn't be created stores handle to host through h if successful, and returns zero. object_type is a pointer to a NUL-terminated string containing the ascii name of the type of object being accessed - e.g., "host" */ dhcpctl_status dhcpctl_new_object (dhcpctl_handle *h, dhcpctl_handle connection, const char *object_type) { dhcpctl_remote_object_t *m; omapi_object_t *g; isc_result_t status; m = (dhcpctl_remote_object_t *)0; status = omapi_object_allocate ((omapi_object_t **)&m, dhcpctl_remote_type, 0, MDL); if (status != ISC_R_SUCCESS) return status; g = (omapi_object_t *)0; status = omapi_generic_new (&g, MDL); if (status != ISC_R_SUCCESS) { dfree (m, MDL); return status; } status = omapi_object_reference (&m -> inner, g, MDL); if (status != ISC_R_SUCCESS) { omapi_object_dereference ((omapi_object_t **)&m, MDL); omapi_object_dereference (&g, MDL); return status; } status = omapi_object_reference (&g -> outer, (omapi_object_t *)m, MDL); if (status != ISC_R_SUCCESS) { omapi_object_dereference ((omapi_object_t **)&m, MDL); omapi_object_dereference (&g, MDL); return status; } status = omapi_typed_data_new (MDL, &m -> rtype, omapi_datatype_string, object_type); if (status != ISC_R_SUCCESS) { omapi_object_dereference ((omapi_object_t **)&m, MDL); omapi_object_dereference (&g, MDL); return status; } status = omapi_object_reference (h, (omapi_object_t *)m, MDL); omapi_object_dereference ((omapi_object_t **)&m, MDL); omapi_object_dereference (&g, MDL); if (status != ISC_R_SUCCESS) return status; return status; } /* asynchronous - just queues the request returns nonzero status code if open couldn't be queued returns zero if open was queued h is a handle to an object created by dhcpctl_new_object connection is a connection to a DHCP server flags include: DHCPCTL_CREATE - if the object doesn't exist, create it DHCPCTL_UPDATE - update the object on the server using the attached parameters DHCPCTL_EXCL - error if the object exists and DHCPCTL_CREATE was also specified */ dhcpctl_status dhcpctl_open_object (dhcpctl_handle h, dhcpctl_handle connection, int flags) { isc_result_t status; omapi_object_t *message = (omapi_object_t *)0; dhcpctl_remote_object_t *remote; if (h -> type != dhcpctl_remote_type) return ISC_R_INVALIDARG; remote = (dhcpctl_remote_object_t *)h; status = omapi_message_new (&message, MDL); if (status != ISC_R_SUCCESS) return status; status = omapi_set_int_value (message, (omapi_object_t *)0, "op", OMAPI_OP_OPEN); if (status != ISC_R_SUCCESS) { omapi_object_dereference (&message, MDL); return status; } status = omapi_set_object_value (message, (omapi_object_t *)0, "object", h); if (status != ISC_R_SUCCESS) { omapi_object_dereference (&message, MDL); return status; } if (flags & DHCPCTL_CREATE) { status = omapi_set_boolean_value (message, (omapi_object_t *)0, "create", 1); if (status != ISC_R_SUCCESS) { omapi_object_dereference (&message, MDL); return status; } } if (flags & DHCPCTL_UPDATE) { status = omapi_set_boolean_value (message, (omapi_object_t *)0, "update", 1); if (status != ISC_R_SUCCESS) { omapi_object_dereference (&message, MDL); return status; } } if (flags & DHCPCTL_EXCL) { status = omapi_set_boolean_value (message, (omapi_object_t *)0, "exclusive", 1); if (status != ISC_R_SUCCESS) { omapi_object_dereference (&message, MDL); return status; } } if (remote -> rtype) { status = omapi_set_value_str (message, (omapi_object_t *)0, "type", remote -> rtype); if (status != ISC_R_SUCCESS) { omapi_object_dereference (&message, MDL); return status; } } status = omapi_message_register (message); if (status != ISC_R_SUCCESS) { omapi_object_dereference (&message, MDL); return status; } status = omapi_protocol_send_message (connection -> outer, (omapi_object_t *)0, message, (omapi_object_t *)0); if (status != ISC_R_SUCCESS) omapi_message_unregister (message); omapi_object_dereference (&message, MDL); return status; } /* Callback methods (not meant to be called directly) */ isc_result_t dhcpctl_remote_set_value (omapi_object_t *h, omapi_object_t *id, omapi_data_string_t *name, omapi_typed_data_t *value) { dhcpctl_remote_object_t *ro; unsigned long rh; isc_result_t status; if (h -> type != dhcpctl_remote_type) return ISC_R_INVALIDARG; ro = (dhcpctl_remote_object_t *)h; if (!omapi_ds_strcmp (name, "remote-handle")) { status = omapi_get_int_value (&rh, value); if (status == ISC_R_SUCCESS) ro -> remote_handle = rh; return status; } if (h -> inner && h -> inner -> type -> set_value) return (*(h -> inner -> type -> set_value)) (h -> inner, id, name, value); return ISC_R_NOTFOUND; } isc_result_t dhcpctl_remote_get_value (omapi_object_t *h, omapi_object_t *id, omapi_data_string_t *name, omapi_value_t **value) { if (h -> type != dhcpctl_remote_type) return ISC_R_INVALIDARG; if (h -> inner && h -> inner -> type -> get_value) return (*(h -> inner -> type -> get_value)) (h -> inner, id, name, value); return ISC_R_NOTFOUND; } isc_result_t dhcpctl_remote_signal_handler (omapi_object_t *o, const char *name, va_list ap) { dhcpctl_remote_object_t *p; omapi_typed_data_t *tv; if (o -> type != dhcpctl_remote_type) return ISC_R_INVALIDARG; p = (dhcpctl_remote_object_t *)o; if (!strcmp (name, "updated")) { p -> waitstatus = ISC_R_SUCCESS; if (o -> inner -> type == omapi_type_generic) omapi_generic_clear_flags (o -> inner); return omapi_signal_in (o -> inner, "ready"); } if (!strcmp (name, "status")) { p -> waitstatus = va_arg (ap, isc_result_t); if (p -> message) omapi_typed_data_dereference (&p -> message, MDL); tv = va_arg (ap, omapi_typed_data_t *); if (tv) omapi_typed_data_reference (&p -> message, tv, MDL); return omapi_signal_in (o -> inner, "ready"); } if (p -> inner && p -> inner -> type -> signal_handler) return (*(p -> inner -> type -> signal_handler)) (p -> inner, name, ap); return ISC_R_SUCCESS; } isc_result_t dhcpctl_remote_destroy (omapi_object_t *h, const char *file, int line) { dhcpctl_remote_object_t *p; if (h -> type != dhcpctl_remote_type) return ISC_R_INVALIDARG; p = (dhcpctl_remote_object_t *)h; if (p -> handle) omapi_object_dereference ((omapi_object_t **)&p -> handle, file, line); if (p -> rtype) omapi_typed_data_dereference ((omapi_typed_data_t **)&p->rtype, file, line); return ISC_R_SUCCESS; } /* Write all the published values associated with the object through the specified connection. */ isc_result_t dhcpctl_remote_stuff_values (omapi_object_t *c, omapi_object_t *id, omapi_object_t *p) { int i; if (p -> type != dhcpctl_remote_type) return ISC_R_INVALIDARG; if (p -> inner && p -> inner -> type -> stuff_values) return (*(p -> inner -> type -> stuff_values)) (c, id, p -> inner); return ISC_R_SUCCESS; } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/Makefile.dist =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/Makefile.dist (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/Makefile.dist (revision 131136) @@ -1,55 +1,59 @@ # Makefile.dist # -# Copyright (c) 1996-2002 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: +# Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") +# Copyright (c) 1996-2003 by Internet Software Consortium # -# http://www.isc.org/isc-license-1.0.html. +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. # -# 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. +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -# Support and other services are available for ISC products - see -# http://www.isc.org for more information. -# +# Internet Systems Consortium, Inc. +# 950 Charter Street +# Redwood City, CA 94063 +# +# http://www.isc.org/ SRC = dst_support.c dst_api.c hmac_link.c md5_dgst.c base64.c prandom.c OBJ = dst_support.o dst_api.o hmac_link.o md5_dgst.o base64.o prandom.o HDRS = dst_internal.h md5.h md5_locl.h INCLUDES = $(BINDINC) -I$(TOP)/includes CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS) -DHMAC_MD5 -DMINIRES_LIB all: libdst.a install: libdst.a: $(OBJ) rm -f dst.a ar cruv libdst.a $(OBJ) $(RANLIB) libdst.a depend: $(MKDEP) $(INCLUDES) $(PREDEFINES) $(SRC) clean: -rm -f $(OBJ) libdst.a realclean: clean -rm -f *~ $(CATMANPAGES) $(SEDMANPAGES) distclean: realclean -rm -f Makefile links: @for foo in $(SRC) $(MAN) $(HDRS); do \ if [ ! -b $$foo ]; then \ rm -f $$foo; \ fi; \ ln -s $(TOP)/dst/$$foo $$foo; \ done # Dependencies (semi-automatically-generated) Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/base64.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/base64.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/base64.c (revision 131136) @@ -1,319 +1,325 @@ /* - * Copyright (c) 1996-1999 by Internet Software Consortium. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ */ /* * Portions Copyright (c) 1995 by International Business Machines, Inc. * * International Business Machines, Inc. (hereinafter called IBM) grants * permission under its copyrights to use, copy, modify, and distribute this * Software with or without fee, provided that the above copyright notice and * all paragraphs of this notice appear in all copies, and that the name of IBM * not be used in connection with the marketing of any product incorporating * the Software or modifications thereof, without specific, written prior * permission. * * To the extent it has a right to do so, IBM grants an immunity from suit * under its patents, if any, for the use, sale or manufacture of products to * the extent that such products are used for performing Domain Name System * dynamic updates in TCP/IP networks by means of the Software. No immunity is * granted for any product per se or for any other function of any product. * * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #if !defined(LINT) && !defined(CODECENTER) -static const char rcsid[] = "$Id: base64.c,v 1.1 2001/02/22 07:22:08 mellon Exp $"; +static const char rcsid[] = "$Id: base64.c,v 1.1.2.1 2004/06/10 17:59:28 dhankins Exp $"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include "minires/minires.h" #include "arpa/nameser.h" #define Assert(Cond) if (!(Cond)) abort() static const char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const char Pad64 = '='; /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) The following encoding technique is taken from RFC 1521 by Borenstein and Freed. It is reproduced here in a slightly edited form for convenience. A 65-character subset of US-ASCII is used, enabling 6 bits to be represented per printable character. (The extra 65th character, "=", is used to signify a special processing function.) The encoding process represents 24-bit groups of input bits as output strings of 4 encoded characters. Proceeding from left to right, a 24-bit input group is formed by concatenating 3 8-bit input groups. These 24 bits are then treated as 4 concatenated 6-bit groups, each of which is translated into a single digit in the base64 alphabet. Each 6-bit group is used as an index into an array of 64 printable characters. The character referenced by the index is placed in the output string. Table 1: The Base64 Alphabet Value Encoding Value Encoding Value Encoding Value Encoding 0 A 17 R 34 i 51 z 1 B 18 S 35 j 52 0 2 C 19 T 36 k 53 1 3 D 20 U 37 l 54 2 4 E 21 V 38 m 55 3 5 F 22 W 39 n 56 4 6 G 23 X 40 o 57 5 7 H 24 Y 41 p 58 6 8 I 25 Z 42 q 59 7 9 J 26 a 43 r 60 8 10 K 27 b 44 s 61 9 11 L 28 c 45 t 62 + 12 M 29 d 46 u 63 / 13 N 30 e 47 v 14 O 31 f 48 w (pad) = 15 P 32 g 49 x 16 Q 33 h 50 y Special processing is performed if fewer than 24 bits are available at the end of the data being encoded. A full encoding quantum is always completed at the end of a quantity. When fewer than 24 input bits are available in an input group, zero bits are added (on the right) to form an integral number of 6-bit groups. Padding at the end of the data is performed using the '=' character. Since all base64 input is an integral number of octets, only the ------------------------------------------------- following cases can arise: (1) the final quantum of encoding input is an integral multiple of 24 bits; here, the final unit of encoded output will be an integral multiple of 4 characters with no "=" padding, (2) the final quantum of encoding input is exactly 8 bits; here, the final unit of encoded output will be two characters followed by two "=" padding characters, or (3) the final quantum of encoding input is exactly 16 bits; here, the final unit of encoded output will be three characters followed by one "=" padding character. */ int b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) { size_t datalength = 0; u_char input[3]; u_char output[4]; size_t i; while (2 < srclength) { input[0] = *src++; input[1] = *src++; input[2] = *src++; srclength -= 3; output[0] = input[0] >> 2; output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); output[3] = input[2] & 0x3f; Assert(output[0] < 64); Assert(output[1] < 64); Assert(output[2] < 64); Assert(output[3] < 64); if (datalength + 4 > targsize) return (-1); target[datalength++] = Base64[output[0]]; target[datalength++] = Base64[output[1]]; target[datalength++] = Base64[output[2]]; target[datalength++] = Base64[output[3]]; } /* Now we worry about padding. */ if (0 != srclength) { /* Get what's left. */ input[0] = input[1] = input[2] = '\0'; for (i = 0; i < srclength; i++) input[i] = *src++; output[0] = input[0] >> 2; output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); Assert(output[0] < 64); Assert(output[1] < 64); Assert(output[2] < 64); if (datalength + 4 > targsize) return (-1); target[datalength++] = Base64[output[0]]; target[datalength++] = Base64[output[1]]; if (srclength == 1) target[datalength++] = Pad64; else target[datalength++] = Base64[output[2]]; target[datalength++] = Pad64; } if (datalength >= targsize) return (-1); target[datalength] = '\0'; /* Returned value doesn't count \0. */ return (datalength); } /* skips all whitespace anywhere. converts characters, four at a time, starting at (or after) src from base - 64 numbers into three 8 bit bytes in the target area. it returns the number of data bytes stored at the target, or -1 on error. */ int b64_pton(src, target, targsize) char const *src; u_char *target; size_t targsize; { int tarindex, state, ch; char *pos; state = 0; tarindex = 0; while ((ch = *src++) != '\0') { if (isspace(ch)) /* Skip whitespace anywhere. */ continue; if (ch == Pad64) break; pos = strchr(Base64, ch); if (pos == 0) /* A non-base64 character. */ return (-1); switch (state) { case 0: if (target) { if ((size_t)tarindex >= targsize) return (-1); target[tarindex] = (pos - Base64) << 2; } state = 1; break; case 1: if (target) { if ((size_t)tarindex + 1 >= targsize) return (-1); target[tarindex] |= (pos - Base64) >> 4; target[tarindex+1] = ((pos - Base64) & 0x0f) << 4 ; } tarindex++; state = 2; break; case 2: if (target) { if ((size_t)tarindex + 1 >= targsize) return (-1); target[tarindex] |= (pos - Base64) >> 2; target[tarindex+1] = ((pos - Base64) & 0x03) << 6; } tarindex++; state = 3; break; case 3: if (target) { if ((size_t)tarindex >= targsize) return (-1); target[tarindex] |= (pos - Base64); } tarindex++; state = 0; break; default: abort(); } } /* * We are done decoding Base-64 chars. Let's see if we ended * on a byte boundary, and/or with erroneous trailing characters. */ if (ch == Pad64) { /* We got a pad char. */ ch = *src++; /* Skip it, get next. */ switch (state) { case 0: /* Invalid = in first position */ case 1: /* Invalid = in second position */ return (-1); case 2: /* Valid, means one byte of info */ /* Skip any number of spaces. */ for ((void)NULL; ch != '\0'; ch = *src++) if (!isspace(ch)) break; /* Make sure there is another trailing = sign. */ if (ch != Pad64) return (-1); ch = *src++; /* Skip the = */ /* Fall through to "single trailing =" case. */ /* FALLTHROUGH */ case 3: /* Valid, means two bytes of info */ /* * We know this char is an =. Is there anything but * whitespace after it? */ for ((void)NULL; ch != '\0'; ch = *src++) if (!isspace(ch)) return (-1); /* * Now make sure for cases 2 and 3 that the "extra" * bits that slopped past the last full byte were * zeros. If we don't check them, they become a * subliminal channel. */ if (target && target[tarindex] != 0) return (-1); } } else { /* * We ended by seeing the end of the string. Make sure we * have no partial bytes lying around. */ if (state != 0) return (-1); } return (tarindex); } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/dst_api.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/dst_api.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/dst_api.c (revision 131136) @@ -1,1081 +1,1081 @@ #ifndef LINT -static const char rcsid[] = "$Header: /rc0/proj/cvs/isc/DHCP/dst/dst_api.c,v 1.1 2001/02/22 07:22:08 mellon Exp $"; +static const char rcsid[] = "$Header: /proj/cvs/prod/DHCP/dst/dst_api.c,v 1.1 2001/02/22 07:22:08 mellon Exp $"; #endif /* * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. * * Permission to use, copy modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. */ /* * This file contains the interface between the DST API and the crypto API. * This is the only file that needs to be changed if the crypto system is * changed. Exported functions are: * void dst_init() Initialize the toolkit * int dst_check_algorithm() Function to determines if alg is suppored. * int dst_compare_keys() Function to compare two keys for equality. * int dst_sign_data() Incremental signing routine. * int dst_verify_data() Incremental verify routine. * int dst_generate_key() Function to generate new KEY * DST_KEY *dst_read_key() Function to retrieve private/public KEY. * void dst_write_key() Function to write out a key. * DST_KEY *dst_dnskey_to_key() Function to convert DNS KEY RR to a DST * KEY structure. * int dst_key_to_dnskey() Function to return a public key in DNS * format binary * DST_KEY *dst_buffer_to_key() Converst a data in buffer to KEY * int *dst_key_to_buffer() Writes out DST_KEY key matterial in buffer * void dst_free_key() Releases all memory referenced by key structure */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "minires/minires.h" #include "arpa/nameser.h" #include "dst_internal.h" /* static variables */ static int done_init = 0; dst_func *dst_t_func[DST_MAX_ALGS]; const char *key_file_fmt_str = "Private-key-format: v%s\nAlgorithm: %d (%s)\n"; const char *dst_path = ""; /* internal I/O functions */ static DST_KEY *dst_s_read_public_key(const char *in_name, const unsigned in_id, int in_alg); static int dst_s_read_private_key_file(char *name, DST_KEY *pk_key, unsigned in_id, int in_alg); static int dst_s_write_public_key(const DST_KEY *key); static int dst_s_write_private_key(const DST_KEY *key); /* internal function to set up data structure */ static DST_KEY *dst_s_get_key_struct(const char *name, const int alg, const u_int32_t flags, const int protocol, const int bits); /* * dst_init * This function initializes the Digital Signature Toolkit. * Right now, it just checks the DSTKEYPATH environment variable. * Parameters * none * Returns * none */ void dst_init() { char *s; unsigned len; if (done_init != 0) return; done_init = 1; s = getenv("DSTKEYPATH"); len = 0; if (s) { struct stat statbuf; len = strlen(s); if (len > PATH_MAX) { EREPORT(("%s is longer than %d characters, ignoring\n", s, PATH_MAX)); } else if (stat(s, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) { EREPORT(("%s is not a valid directory\n", s)); } else { char *dp = (char *) malloc(len + 2); int l; memcpy(dp, s, len + 1); l = strlen (dp); if (dp[l - 1] != '/') { dp[l + 1] = 0; dp[l] = '/'; } dst_path = dp; } } memset(dst_t_func, 0, sizeof(dst_t_func)); /* first one is selected */ #if 0 dst_bsafe_init(); dst_rsaref_init(); #endif dst_hmac_md5_init(); #if 0 dst_eay_dss_init(); dst_cylink_init(); #endif } /* * dst_check_algorithm * This function determines if the crypto system for the specified * algorithm is present. * Parameters * alg 1 KEY_RSA * 3 KEY_DSA * 157 KEY_HMAC_MD5 * future algorithms TBD and registered with IANA. * Returns * 1 - The algorithm is available. * 0 - The algorithm is not available. */ int dst_check_algorithm(const int alg) { return (dst_t_func[alg] != NULL); } /* * dst_s_get_key_struct * This function allocates key structure and fills in some of the * fields of the structure. * Parameters: * name: the name of the key * alg: the algorithm number * flags: the dns flags of the key * protocol: the dns protocol of the key * bits: the size of the key * Returns: * NULL if error * valid pointer otherwise */ static DST_KEY * dst_s_get_key_struct(const char *name, const int alg, const u_int32_t flags, const int protocol, const int bits) { DST_KEY *new_key = NULL; if (dst_check_algorithm(alg)) /* make sure alg is available */ new_key = (DST_KEY *) malloc(sizeof(*new_key)); if (new_key == NULL) return (NULL); memset(new_key, 0, sizeof(*new_key)); new_key->dk_key_name = strdup(name); new_key->dk_alg = alg; new_key->dk_flags = flags; new_key->dk_proto = protocol; new_key->dk_KEY_struct = NULL; new_key->dk_key_size = bits; new_key->dk_func = dst_t_func[alg]; return (new_key); } /* * dst_compare_keys * Compares two keys for equality. * Parameters * key1, key2 Two keys to be compared. * Returns * 0 The keys are equal. * non-zero The keys are not equal. */ int dst_compare_keys(const DST_KEY *key1, const DST_KEY *key2) { if (key1 == key2) return (0); if (key1 == NULL || key2 == NULL) return (4); if (key1->dk_alg != key2->dk_alg) return (1); if (key1->dk_key_size != key2->dk_key_size) return (2); if (key1->dk_id != key2->dk_id) return (3); return (key1->dk_func->compare(key1, key2)); } /* * dst_sign_data * An incremental signing function. Data is signed in steps. * First the context must be initialized (SIG_MODE_INIT). * Then data is hashed (SIG_MODE_UPDATE). Finally the signature * itself is created (SIG_MODE_FINAL). This function can be called * once with INIT, UPDATE and FINAL modes all set, or it can be * called separately with a different mode set for each step. The * UPDATE step can be repeated. * Parameters * mode A bit mask used to specify operation(s) to be performed. * SIG_MODE_INIT 1 Initialize digest * SIG_MODE_UPDATE 2 Add data to digest * SIG_MODE_FINAL 4 Generate signature * from signature * SIG_MODE_ALL (SIG_MODE_INIT,SIG_MODE_UPDATE,SIG_MODE_FINAL * data Data to be signed. * len The length in bytes of data to be signed. * in_key Contains a private key to sign with. * KEY structures should be handled (created, converted, * compared, stored, freed) by the DST. * signature * The location to which the signature will be written. * sig_len Length of the signature field in bytes. * Return * 0 Successfull INIT or Update operation * >0 success FINAL (sign) operation * <0 failure */ int dst_sign_data(const int mode, DST_KEY *in_key, void **context, const u_char *data, const unsigned len, u_char *signature, const unsigned sig_len) { DUMP(data, mode, len, "dst_sign_data()"); if (mode & SIG_MODE_FINAL && (in_key->dk_KEY_struct == NULL || signature == NULL)) return (MISSING_KEY_OR_SIGNATURE); if (in_key->dk_func && in_key->dk_func->sign) return (in_key->dk_func->sign(mode, in_key, context, data, len, signature, sig_len)); return (UNKNOWN_KEYALG); } /* * dst_verify_data * An incremental verify function. Data is verified in steps. * First the context must be initialized (SIG_MODE_INIT). * Then data is hashed (SIG_MODE_UPDATE). Finally the signature * is verified (SIG_MODE_FINAL). This function can be called * once with INIT, UPDATE and FINAL modes all set, or it can be * called separately with a different mode set for each step. The * UPDATE step can be repeated. * Parameters * mode Operations to perform this time. * SIG_MODE_INIT 1 Initialize digest * SIG_MODE_UPDATE 2 add data to digest * SIG_MODE_FINAL 4 verify signature * SIG_MODE_ALL * (SIG_MODE_INIT,SIG_MODE_UPDATE,SIG_MODE_FINAL) * data Data to pass through the hash function. * len Length of the data in bytes. * in_key Key for verification. * signature Location of signature. * sig_len Length of the signature in bytes. * Returns * 0 Verify success * Non-Zero Verify Failure */ int dst_verify_data(const int mode, DST_KEY *in_key, void **context, const u_char *data, const unsigned len, const u_char *signature, const unsigned sig_len) { DUMP(data, mode, len, "dst_verify_data()"); if (mode & SIG_MODE_FINAL && (in_key->dk_KEY_struct == NULL || signature == NULL)) return (MISSING_KEY_OR_SIGNATURE); if (in_key->dk_func == NULL || in_key->dk_func->verify == NULL) return (UNSUPPORTED_KEYALG); return (in_key->dk_func->verify(mode, in_key, context, data, len, signature, sig_len)); } /* * dst_read_private_key * Access a private key. First the list of private keys that have * already been read in is searched, then the key accessed on disk. * If the private key can be found, it is returned. If the key cannot * be found, a null pointer is returned. The options specify required * key characteristics. If the private key requested does not have * these characteristics, it will not be read. * Parameters * in_keyname The private key name. * in_id The id of the private key. * options DST_FORCE_READ Read from disk - don't use a previously * read key. * DST_CAN_SIGN The key must be useable for signing. * DST_NO_AUTHEN The key must be useable for authentication. * DST_STANDARD Return any key * Returns * NULL If there is no key found in the current directory or * this key has not been loaded before. * !NULL Success - KEY structure returned. */ DST_KEY * dst_read_key(const char *in_keyname, const unsigned in_id, const int in_alg, const int type) { char keyname[PATH_MAX]; DST_KEY *dg_key = NULL, *pubkey = NULL; if (!dst_check_algorithm(in_alg)) { /* make sure alg is available */ EREPORT(("dst_read_private_key(): Algorithm %d not suppored\n", in_alg)); return (NULL); } if ((type && (DST_PUBLIC | DST_PRIVATE)) == 0) return (NULL); if (in_keyname == NULL) { EREPORT(("dst_read_private_key(): Null key name passed in\n")); return (NULL); } else strcpy(keyname, in_keyname); /* before I read in the public key, check if it is allowed to sign */ if ((pubkey = dst_s_read_public_key(keyname, in_id, in_alg)) == NULL) return (NULL); if (type == DST_PUBLIC) return pubkey; if (!(dg_key = dst_s_get_key_struct(keyname, pubkey->dk_alg, pubkey->dk_flags, pubkey->dk_proto, 0))) return (dg_key); /* Fill in private key and some fields in the general key structure */ if (dst_s_read_private_key_file(keyname, dg_key, pubkey->dk_id, pubkey->dk_alg) == 0) dg_key = dst_free_key(dg_key); pubkey = dst_free_key(pubkey); return (dg_key); } int dst_write_key(const DST_KEY *key, const int type) { int pub = 0, priv = 0; if (key == NULL) return (0); if (!dst_check_algorithm(key->dk_alg)) { /* make sure alg is available */ EREPORT(("dst_write_key(): Algorithm %d not suppored\n", key->dk_alg)); return (UNSUPPORTED_KEYALG); } if ((type & (DST_PRIVATE|DST_PUBLIC)) == 0) return (0); if (type & DST_PUBLIC) if ((pub = dst_s_write_public_key(key)) < 0) return (pub); if (type & DST_PRIVATE) if ((priv = dst_s_write_private_key(key)) < 0) return (priv); return (priv+pub); } /* * dst_write_private_key * Write a private key to disk. The filename will be of the form: * Kdk_name>+dk_alg>+dk_id>.. * If there is already a file with this name, an error is returned. * * Parameters * key A DST managed key structure that contains * all information needed about a key. * Return * >= 0 Correct behavior. Returns length of encoded key value * written to disk. * < 0 error. */ static int dst_s_write_private_key(const DST_KEY *key) { u_char encoded_block[RAW_KEY_SIZE]; char file[PATH_MAX]; unsigned len; FILE *fp; /* First encode the key into the portable key format */ if (key == NULL) return (-1); if (key->dk_KEY_struct == NULL) return (0); /* null key has no private key */ if (key->dk_func == NULL || key->dk_func->to_file_fmt == NULL) { EREPORT(("dst_write_private_key(): Unsupported operation %d\n", key->dk_alg)); return (-5); } else if ((len = key->dk_func->to_file_fmt(key, (char *)encoded_block, sizeof(encoded_block))) <= 0) { EREPORT(("dst_write_private_key(): Failed encoding private RSA bsafe key %d\n", len)); return (-8); } /* Now I can create the file I want to use */ dst_s_build_filename(file, key->dk_key_name, key->dk_id, key->dk_alg, PRIVATE_KEY, PATH_MAX); /* Do not overwrite an existing file */ if ((fp = dst_s_fopen(file, "w", 0600)) != NULL) { int nn; if ((nn = fwrite(encoded_block, 1, len, fp)) != len) { EREPORT(("dst_write_private_key(): Write failure on %s %d != %d errno=%d\n", file, out_len, nn, errno)); return (-5); } fclose(fp); } else { EREPORT(("dst_write_private_key(): Can not create file %s\n" ,file)); return (-6); } memset(encoded_block, 0, len); return (len); } /* * * dst_read_public_key * Read a public key from disk and store in a DST key structure. * Parameters * in_name K. is the * filename of the key file to be read. * Returns * NULL If the key does not exist or no name is supplied. * NON-NULL Initalized key structure if the key exists. */ static DST_KEY * dst_s_read_public_key(const char *in_name, const unsigned in_id, int in_alg) { unsigned flags, len; int proto, alg, dlen; int c; char name[PATH_MAX], enckey[RAW_KEY_SIZE], *notspace; u_char deckey[RAW_KEY_SIZE]; FILE *fp; if (in_name == NULL) { EREPORT(("dst_read_public_key(): No key name given\n")); return (NULL); } if (dst_s_build_filename(name, in_name, in_id, in_alg, PUBLIC_KEY, PATH_MAX) == -1) { EREPORT(("dst_read_public_key(): Cannot make filename from %s, %d, and %s\n", in_name, in_id, PUBLIC_KEY)); return (NULL); } /* * Open the file and read it's formatted contents up to key * File format: * domain.name [ttl] [IN] KEY * flags, proto, alg stored as decimal (or hex numbers FIXME). * (FIXME: handle parentheses for line continuation.) */ if ((fp = dst_s_fopen(name, "r", 0)) == NULL) { EREPORT(("dst_read_public_key(): Public Key not found %s\n", name)); return (NULL); } /* Skip domain name, which ends at first blank */ while ((c = getc(fp)) != EOF) if (isspace(c)) break; /* Skip blank to get to next field */ while ((c = getc(fp)) != EOF) if (!isspace(c)) break; /* Skip optional TTL -- if initial digit, skip whole word. */ if (isdigit(c)) { while ((c = getc(fp)) != EOF) if (isspace(c)) break; while ((c = getc(fp)) != EOF) if (!isspace(c)) break; } /* Skip optional "IN" */ if (c == 'I' || c == 'i') { while ((c = getc(fp)) != EOF) if (isspace(c)) break; while ((c = getc(fp)) != EOF) if (!isspace(c)) break; } /* Locate and skip "KEY" */ if (c != 'K' && c != 'k') { EREPORT(("\"KEY\" doesn't appear in file: %s", name)); return NULL; } while ((c = getc(fp)) != EOF) if (isspace(c)) break; while ((c = getc(fp)) != EOF) if (!isspace(c)) break; ungetc(c, fp); /* return the charcter to the input field */ /* Handle hex!! FIXME. */ if (fscanf(fp, "%d %d %d", &flags, &proto, &alg) != 3) { EREPORT(("dst_read_public_key(): Can not read flag/proto/alg field from %s\n" ,name)); return (NULL); } /* read in the key string */ fgets(enckey, sizeof(enckey), fp); /* If we aren't at end-of-file, something is wrong. */ while ((c = getc(fp)) != EOF) if (!isspace(c)) break; if (!feof(fp)) { EREPORT(("Key too long in file: %s", name)); return NULL; } fclose(fp); if ((len = strlen(enckey)) <= 0) return (NULL); /* discard \n */ enckey[--len] = '\0'; /* remove leading spaces */ for (notspace = (char *) enckey; isspace(*notspace); len--) notspace++; dlen = b64_pton(notspace, deckey, sizeof(deckey)); if (dlen < 0) { EREPORT(("dst_read_public_key: bad return from b64_pton = %d", dlen)); return (NULL); } /* store key and info in a key structure that is returned */ /* return dst_store_public_key(in_name, alg, proto, 666, flags, deckey, dlen);*/ return dst_buffer_to_key(in_name, alg, flags, proto, deckey, (unsigned)dlen); } /* * dst_write_public_key * Write a key to disk in DNS format. * Parameters * key Pointer to a DST key structure. * Returns * 0 Failure * 1 Success */ static int dst_s_write_public_key(const DST_KEY *key) { FILE *fp; char filename[PATH_MAX]; u_char out_key[RAW_KEY_SIZE]; char enc_key[RAW_KEY_SIZE]; int len = 0; memset(out_key, 0, sizeof(out_key)); if (key == NULL) { EREPORT(("dst_write_public_key(): No key specified \n")); return (0); } else if ((len = dst_key_to_dnskey(key, out_key, sizeof(out_key)))< 0) return (0); /* Make the filename */ if (dst_s_build_filename(filename, key->dk_key_name, key->dk_id, key->dk_alg, PUBLIC_KEY, PATH_MAX) == -1) { EREPORT(("dst_write_public_key(): Cannot make filename from %s, %d, and %s\n", key->dk_key_name, key->dk_id, PUBLIC_KEY)); return (0); } /* create public key file */ if ((fp = dst_s_fopen(filename, "w+", 0644)) == NULL) { EREPORT(("DST_write_public_key: open of file:%s failed (errno=%d)\n", filename, errno)); return (0); } /*write out key first base64 the key data */ if (key->dk_flags & DST_EXTEND_FLAG) b64_ntop(&out_key[6], (unsigned)(len - 6), enc_key, sizeof(enc_key)); else b64_ntop(&out_key[4], (unsigned)(len - 4), enc_key, sizeof(enc_key)); fprintf(fp, "%s IN KEY %d %d %d %s\n", key->dk_key_name, key->dk_flags, key->dk_proto, key->dk_alg, enc_key); fclose(fp); return (1); } /* * dst_dnskey_to_public_key * This function converts the contents of a DNS KEY RR into a DST * key structure. * Paramters * len Length of the RDATA of the KEY RR RDATA * rdata A pointer to the the KEY RR RDATA. * in_name Key name to be stored in key structure. * Returns * NULL Failure * NON-NULL Success. Pointer to key structure. * Caller's responsibility to free() it. */ DST_KEY * dst_dnskey_to_key(const char *in_name, const u_char *rdata, const unsigned len) { DST_KEY *key_st; int alg ; int start = DST_KEY_START; if (rdata == NULL || len <= DST_KEY_ALG) /* no data */ return (NULL); alg = (u_int8_t) rdata[DST_KEY_ALG]; if (!dst_check_algorithm(alg)) { /* make sure alg is available */ EREPORT(("dst_dnskey_to_key(): Algorithm %d not suppored\n", alg)); return (NULL); } if ((key_st = dst_s_get_key_struct(in_name, alg, 0, 0, 0)) == NULL) return (NULL); if (in_name == NULL) return (NULL); key_st->dk_flags = dst_s_get_int16(rdata); key_st->dk_proto = (u_int16_t) rdata[DST_KEY_PROT]; if (key_st->dk_flags & DST_EXTEND_FLAG) { u_int32_t ext_flags; ext_flags = (u_int32_t) dst_s_get_int16(&rdata[DST_EXT_FLAG]); key_st->dk_flags = key_st->dk_flags | (ext_flags << 16); start += 2; } /* * now point to the begining of the data representing the encoding * of the key */ if (key_st->dk_func && key_st->dk_func->from_dns_key) { if (key_st->dk_func->from_dns_key(key_st, &rdata[start], len - start) > 0) return (key_st); } else EREPORT(("dst_dnskey_to_public_key(): unsuppored alg %d\n", alg)); SAFE_FREE(key_st); return (key_st); } /* * dst_public_key_to_dnskey * Function to encode a public key into DNS KEY wire format * Parameters * key Key structure to encode. * out_storage Location to write the encoded key to. * out_len Size of the output array. * Returns * <0 Failure * >=0 Number of bytes written to out_storage */ int dst_key_to_dnskey(const DST_KEY *key, u_char *out_storage, const unsigned out_len) { u_int16_t val; int loc = 0; int enc_len = 0; if (key == NULL) return (-1); if (!dst_check_algorithm(key->dk_alg)) { /* make sure alg is available */ EREPORT(("dst_key_to_dnskey(): Algorithm %d not suppored\n", key->dk_alg)); return (UNSUPPORTED_KEYALG); } memset(out_storage, 0, out_len); val = (u_int16_t)(key->dk_flags & 0xffff); out_storage[0] = (val >> 8) & 0xff; out_storage[1] = val & 0xff; loc += 2; out_storage[loc++] = (u_char) key->dk_proto; out_storage[loc++] = (u_char) key->dk_alg; if (key->dk_flags > 0xffff) { /* Extended flags */ val = (u_int16_t)((key->dk_flags >> 16) & 0xffff); out_storage[loc] = (val >> 8) & 0xff; out_storage[loc+1] = val & 0xff; loc += 2; } if (key->dk_KEY_struct == NULL) return (loc); if (key->dk_func && key->dk_func->to_dns_key) { enc_len = key->dk_func->to_dns_key(key, (u_char *) &out_storage[loc], out_len - loc); if (enc_len > 0) return (enc_len + loc); else return (-1); } else EREPORT(("dst_key_to_dnskey(): Unsupported ALG %d\n", key->dk_alg)); return (-1); } /* * dst_buffer_to_key * Function to encode a string of raw data into a DST key * Parameters * alg The algorithm (HMAC only) * key A pointer to the data * keylen The length of the data * Returns * NULL an error occurred * NON-NULL the DST key */ DST_KEY * dst_buffer_to_key(const char *key_name, /* name of the key */ const int alg, /* algorithm */ const unsigned flags, /* dns flags */ const int protocol, /* dns protocol */ const u_char *key_buf, /* key in dns wire fmt */ const unsigned key_len) /* size of key */ { DST_KEY *dkey = NULL; if (!dst_check_algorithm(alg)) { /* make sure alg is available */ EREPORT(("dst_buffer_to_key(): Algorithm %d not suppored\n", alg)); return (NULL); } dkey = dst_s_get_key_struct(key_name, alg, flags, protocol, -1); if (dkey == NULL) return (NULL); if (dkey->dk_func != NULL && dkey->dk_func->from_dns_key != NULL) { if (dkey->dk_func->from_dns_key(dkey, key_buf, key_len) < 0) { EREPORT(("dst_buffer_to_key(): dst_buffer_to_hmac failed\n")); return (dst_free_key(dkey)); } return (dkey); } return (NULL); } int dst_key_to_buffer(DST_KEY *key, u_char *out_buff, unsigned buf_len) { int len; /* this function will extrac the secret of HMAC into a buffer */ if(key == NULL) return (0); if(key->dk_func != NULL && key->dk_func != NULL) { len = key->dk_func->to_dns_key(key, out_buff, buf_len); if (len < 0) return (0); return (len); } return (0); } /* * dst_s_read_private_key_file * Function reads in private key from a file. * Fills out the KEY structure. * Parameters * name Name of the key to be read. * pk_key Structure that the key is returned in. * in_id Key identifier (tag) * Return * 1 if everthing works * 0 if there is any problem */ static int dst_s_read_private_key_file(char *name, DST_KEY *pk_key, unsigned in_id, int in_alg) { int cnt, alg, len, major, minor, file_major, file_minor; int id; char filename[PATH_MAX]; u_char in_buff[RAW_KEY_SIZE], *p; FILE *fp; if (name == NULL || pk_key == NULL) { EREPORT(("dst_read_private_key_file(): No key name given\n")); return (0); } /* Make the filename */ if (dst_s_build_filename(filename, name, in_id, in_alg, PRIVATE_KEY, PATH_MAX) == -1) { EREPORT(("dst_read_private_key(): Cannot make filename from %s, %d, and %s\n", name, in_id, PRIVATE_KEY)); return (0); } /* first check if we can find the key file */ if ((fp = dst_s_fopen(filename, "r", 0)) == NULL) { EREPORT(("dst_s_read_private_key_file: Could not open file %s in directory %s\n", filename, dst_path[0] ? dst_path : (char *) getcwd(NULL, PATH_MAX - 1))); return (0); } /* now read the header info from the file */ if ((cnt = fread(in_buff, 1, sizeof(in_buff), fp)) < 5) { fclose(fp); EREPORT(("dst_s_read_private_key_file: error reading file %s (empty file)\n", filename)); return (0); } /* decrypt key */ fclose(fp); if (memcmp(in_buff, "Private-key-format: v", 20) != 0) goto fail; len = cnt; p = in_buff; if (!dst_s_verify_str((const char **) &p, "Private-key-format: v")) { EREPORT(("dst_s_read_private_key_file(): Not a Key file/Decrypt failed %s\n", name)); goto fail; } /* read in file format */ sscanf((char *)p, "%d.%d", &file_major, &file_minor); sscanf(KEY_FILE_FORMAT, "%d.%d", &major, &minor); if (file_major < 1) { EREPORT(("dst_s_read_private_key_file(): Unknown keyfile %d.%d version for %s\n", file_major, file_minor, name)); goto fail; } else if (file_major > major || file_minor > minor) EREPORT(( "dst_s_read_private_key_file(): Keyfile %s version higher than mine %d.%d MAY FAIL\n", name, file_major, file_minor)); while (*p++ != '\n') ; /* skip to end of line */ if (!dst_s_verify_str((const char **) &p, "Algorithm: ")) goto fail; if (sscanf((char *)p, "%d", &alg) != 1) goto fail; while (*p++ != '\n') ; /* skip to end of line */ if (pk_key->dk_key_name && !strcmp(pk_key->dk_key_name, name)) SAFE_FREE2(pk_key->dk_key_name, strlen(pk_key->dk_key_name)); pk_key->dk_key_name = (char *) strdup(name); /* allocate and fill in key structure */ if (pk_key->dk_func == NULL || pk_key->dk_func->from_file_fmt == NULL) goto fail; id = pk_key->dk_func->from_file_fmt(pk_key, (char *)p, (unsigned)(&in_buff[len] - p)); if (id < 0) goto fail; /* Make sure the actual key tag matches the input tag used in the filename */ if (id != in_id) { EREPORT(("dst_s_read_private_key_file(): actual tag of key read %d != input tag used to build filename %d.\n", id, in_id)); goto fail; } pk_key->dk_id = (u_int16_t) id; pk_key->dk_alg = alg; memset(in_buff, 0, (unsigned)cnt); return (1); fail: memset(in_buff, 0, (unsigned)cnt); return (0); } /* * dst_generate_key * Generate and store a public/private keypair. * Keys will be stored in formatted files. * Parameters * name Name of the new key. Used to create key files * K++.public and K++.private. * bits Size of the new key in bits. * exp What exponent to use: * 0 use exponent 3 * non-zero use Fermant4 * flags The default value of the DNS Key flags. * The DNS Key RR Flag field is defined in RFC 2065, * section 3.3. The field has 16 bits. * protocol * Default value of the DNS Key protocol field. * The DNS Key protocol field is defined in RFC 2065, * section 3.4. The field has 8 bits. * alg What algorithm to use. Currently defined: * KEY_RSA 1 * KEY_DSA 3 * KEY_HMAC 157 * out_id The key tag is returned. * * Return * NULL Failure * non-NULL the generated key pair * Caller frees the result, and its dk_name pointer. */ DST_KEY * dst_generate_key(const char *name, const int bits, const int exp, const unsigned flags, const int protocol, const int alg) { DST_KEY *new_key = NULL; int res; if (name == NULL) return (NULL); if (!dst_check_algorithm(alg)) { /* make sure alg is available */ EREPORT(("dst_generate_key(): Algorithm %d not suppored\n", alg)); return (NULL); } new_key = dst_s_get_key_struct(name, alg, flags, protocol, bits); if (new_key == NULL) return (NULL); if (bits == 0) /* null key we are done */ return (new_key); if (new_key->dk_func == NULL || new_key->dk_func->generate == NULL) { EREPORT(("dst_generate_key_pair():Unsupported algorithm %d\n", alg)); return (dst_free_key(new_key)); } if ((res = new_key->dk_func->generate(new_key, exp)) <= 0) { EREPORT(("dst_generate_key_pair(): Key generation failure %s %d %d %d\n", new_key->dk_key_name, new_key->dk_alg, new_key->dk_key_size, exp)); return (dst_free_key(new_key)); } return (new_key); } /* * dst_free_key * Release all data structures pointed to by a key structure. * Parameters * f_key Key structure to be freed. */ DST_KEY * dst_free_key(DST_KEY *f_key) { if (f_key == NULL) return (f_key); if (f_key->dk_func && f_key->dk_func->destroy) f_key->dk_KEY_struct = f_key->dk_func->destroy(f_key->dk_KEY_struct); else { EREPORT(("dst_free_key(): Unknown key alg %d\n", f_key->dk_alg)); free(f_key->dk_KEY_struct); /* SHOULD NOT happen */ } if (f_key->dk_KEY_struct) { free(f_key->dk_KEY_struct); f_key->dk_KEY_struct = NULL; } if (f_key->dk_key_name) SAFE_FREE(f_key->dk_key_name); SAFE_FREE(f_key); return (NULL); } /* * dst_sig_size * Return the maximim size of signature from the key specified in bytes * Parameters * key * Returns * bytes */ int dst_sig_size(DST_KEY *key) { switch (key->dk_alg) { case KEY_HMAC_MD5: return (16); case KEY_HMAC_SHA1: return (20); case KEY_RSA: return (key->dk_key_size + 7) / 8; case KEY_DSA: return (40); default: EREPORT(("dst_sig_size(): Unknown key alg %d\n", key->dk_alg)); return -1; } } /* * dst_random * function that multiplexes number of random number generators * Parameters * mode: select the random number generator * wanted is how many bytes of random data are requested * outran is a buffer of size at least wanted for the output data * * Returns * number of bytes written to outran */ int dst_random(const int mode, unsigned wanted, u_char *outran) { u_int32_t *buff = NULL, *bp = NULL; int i; if (wanted <= 0 || outran == NULL) return (0); switch (mode) { case DST_RAND_SEMI: bp = buff = (u_int32_t *) malloc(wanted+sizeof(u_int32_t)); for (i = 0; i < wanted; i+= sizeof(u_int32_t), bp++) { *bp = dst_s_quick_random(i); } memcpy(outran, buff, (unsigned)wanted); SAFE_FREE(buff); return (wanted); case DST_RAND_STD: return (dst_s_semi_random(outran, wanted)); case DST_RAND_KEY: return (dst_s_random(outran, wanted)); case DST_RAND_DSS: default: /* need error case here XXX OG */ return (0); } } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/dst_support.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/dst_support.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/dst_support.c (revision 131136) @@ -1,463 +1,463 @@ -static const char rcsid[] = "$Header: /rc0/proj/cvs/isc/DHCP/dst/dst_support.c,v 1.1 2001/02/22 07:22:08 mellon Exp $"; +static const char rcsid[] = "$Header: /proj/cvs/prod/DHCP/dst/dst_support.c,v 1.1 2001/02/22 07:22:08 mellon Exp $"; /* * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. * * Permission to use, copy modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include "minires/minires.h" #include "arpa/nameser.h" #include "dst_internal.h" /* * dst_s_conv_bignum_u8_to_b64 * This function converts binary data stored as a u_char[] to a * base-64 string. Leading zeroes are discarded. If a header is * supplied, it is prefixed to the input prior to encoding. The * output is \n\0 terminated (the \0 is not included in output length). * Parameters * out_buf binary data to convert * header character string to prefix to the output (label) * bin_data binary data * bin_len size of binary data * Return * -1 not enough space in output work area * 0 no output * >0 number of bytes written to output work area */ int dst_s_conv_bignum_u8_to_b64(char *out_buf, const unsigned out_len, const char *header, const u_char *bin_data, const unsigned bin_len) { const u_char *bp = bin_data; char *op = out_buf; unsigned lenh = 0, len64 = 0; unsigned local_in_len = bin_len; unsigned local_out_len = out_len; if (bin_data == NULL) /* no data no */ return (0); if (out_buf == NULL || out_len <= 0) /* no output_work area */ return (-1); /* suppress leading \0 */ for (; (*bp == 0x0) && (local_in_len > 0); local_in_len--) bp++; if (header) { /* add header to output string */ lenh = strlen(header); if (lenh < out_len) memcpy(op, header, lenh); else return (-1); local_out_len -= lenh; op += lenh; } len64 = b64_ntop(bp, local_in_len, op, local_out_len - 2); if (len64 < 0) return (-1); op += len64++; *(op++) = '\n'; /* put CR in the output */ *op = '\0'; /* make sure output is 0 terminated */ return (lenh + len64); } /* * dst_s_verify_str() * Validate that the input string(*str) is at the head of the input * buffer(**buf). If so, move the buffer head pointer (*buf) to * the first byte of data following the string(*str). * Parameters * buf Input buffer. * str Input string. * Return * 0 *str is not the head of **buff * 1 *str is the head of **buff, *buf is is advanced to * the tail of **buf. */ int dst_s_verify_str(const char **buf, const char *str) { unsigned b, s; if (*buf == NULL) /* error checks */ return (0); if (str == NULL || *str == '\0') return (1); b = strlen(*buf); /* get length of strings */ s = strlen(str); if (s > b || strncmp(*buf, str, s)) /* check if same */ return (0); /* not a match */ (*buf) += s; /* advance pointer */ return (1); } /* * dst_s_conv_bignum_b64_to_u8 * Read a line of base-64 encoded string from the input buffer, * convert it to binary, and store it in an output area. The * input buffer is read until reaching a newline marker or the * end of the buffer. The binary data is stored in the last X * number of bytes of the output area where X is the size of the * binary output. If the operation is successful, the input buffer * pointer is advanced. This procedure does not do network to host * byte order conversion. * Parameters * buf Pointer to encoded input string. Pointer is updated if * function is successfull. * loc Output area. * loclen Size in bytes of output area. * Return * >0 Return = number of bytes of binary data stored in loc. * 0 Failure. */ int dst_s_conv_bignum_b64_to_u8(const char **buf, u_char *loc, const unsigned loclen) { unsigned blen; char *bp; u_char bstr[RAW_KEY_SIZE]; if (buf == NULL || *buf == NULL) { /* error checks */ EREPORT(("dst_s_conv_bignum_b64_to_u8: null input buffer.\n")); return (0); } bp = strchr(*buf, '\n'); /* find length of input line */ if (bp != NULL) *bp = (u_char) NULL; blen = b64_pton(*buf, bstr, sizeof(bstr)); if (blen <= 0) { EREPORT(("dst_s_conv_bignum_b64_to_u8: decoded value is null.\n")); return (0); } else if (loclen < blen) { EREPORT(("dst_s_conv_bignum_b64_to_u8: decoded value is longer than output buffer.\n")); return (0); } if (bp) *buf = bp; /* advancing buffer past \n */ memset(loc, 0, loclen - blen); /* clearing unused output area */ memcpy(loc + loclen - blen, bstr, blen); /* write last blen bytes */ return (blen); } /* * dst_s_calculate_bits * Given a binary number represented in a u_char[], determine * the number of significant bits used. * Parameters * str An input character string containing a binary number. * max_bits The maximum possible significant bits. * Return * N The number of significant bits in str. */ int dst_s_calculate_bits(const u_char *str, const int max_bits) { const u_char *p = str; u_char i, j = 0x80; int bits; for (bits = max_bits; *p == 0x00 && bits > 0; p++) bits -= 8; for (i = *p; (i & j) != j; j >>= 1) bits--; return (bits); } /* * calculates a checksum used in kmt for a id. * takes an array of bytes and a length. * returns a 16 bit checksum. */ u_int16_t dst_s_id_calc(const u_char *key, const unsigned keysize) { u_int32_t ac; const u_char *kp = key; unsigned size = keysize; if (!key) return 0; for (ac = 0; size > 1; size -= 2, kp += 2) ac += ((*kp) << 8) + *(kp + 1); if (size > 0) ac += ((*kp) << 8); ac += (ac >> 16) & 0xffff; return (ac & 0xffff); } /* * dst_s_dns_key_id() Function to calculated DNSSEC footprint from KEY reocrd * rdata (all of record) * Input: * dns_key_rdata: the raw data in wire format * rdata_len: the size of the input data * Output: * the key footprint/id calcuated from the key data */ u_int16_t dst_s_dns_key_id(const u_char *dns_key_rdata, const unsigned rdata_len) { unsigned key_data = 4; if (!dns_key_rdata || (rdata_len < key_data)) return 0; /* check the extended parameters bit in the DNS Key RR flags */ if (dst_s_get_int16(dns_key_rdata) & DST_EXTEND_FLAG) key_data += 2; /* compute id */ if (dns_key_rdata[3] == KEY_RSA) /* Algorithm RSA */ return dst_s_get_int16((const u_char *) &dns_key_rdata[rdata_len - 3]); else /* compute a checksum on the key part of the key rr */ return dst_s_id_calc(&dns_key_rdata[key_data], (rdata_len - key_data)); } /* * dst_s_get_int16 * This routine extracts a 16 bit integer from a two byte character * string. The character string is assumed to be in network byte * order and may be unaligned. The number returned is in host order. * Parameter * buf A two byte character string. * Return * The converted integer value. */ u_int16_t dst_s_get_int16(const u_char *buf) { register u_int16_t a = 0; a = ((u_int16_t)(buf[0] << 8)) | ((u_int16_t)(buf[1])); return (a); } /* * dst_s_get_int32 * This routine extracts a 32 bit integer from a four byte character * string. The character string is assumed to be in network byte * order and may be unaligned. The number returned is in host order. * Parameter * buf A four byte character string. * Return * The converted integer value. */ u_int32_t dst_s_get_int32(const u_char *buf) { register u_int32_t a = 0; a = ((u_int32_t)(buf[0] << 24)) | ((u_int32_t)(buf[1] << 16)) | ((u_int32_t)(buf[2] << 8)) | ((u_int32_t)(buf[3])); return (a); } /* * dst_s_put_int16 * Take a 16 bit integer and store the value in a two byte * character string. The integer is assumed to be in network * order and the string is returned in host order. * * Parameters * buf Storage for a two byte character string. * val 16 bit integer. */ void dst_s_put_int16(u_int8_t *buf, const u_int16_t val) { buf[0] = (u_int8_t)(val >> 8); buf[1] = (u_int8_t)(val); } /* * dst_s_put_int32 * Take a 32 bit integer and store the value in a four byte * character string. The integer is assumed to be in network * order and the string is returned in host order. * * Parameters * buf Storage for a four byte character string. * val 32 bit integer. */ void dst_s_put_int32(u_int8_t *buf, const u_int32_t val) { buf[0] = (u_int8_t)(val >> 24); buf[1] = (u_int8_t)(val >> 16); buf[2] = (u_int8_t)(val >> 8); buf[3] = (u_int8_t)(val); } /* * dst_s_filename_length * * This function returns the number of bytes needed to hold the * filename for a key file. '/', '\' and ':' are not allowed. * form: K++. * * Returns 0 if the filename would contain either '\', '/' or ':' */ size_t dst_s_filename_length(const char *name, const char *suffix) { if (name == NULL) return (0); if (strrchr(name, '\\')) return (0); if (strrchr(name, '/')) return (0); if (strrchr(name, ':')) return (0); if (suffix == NULL) return (0); if (strrchr(suffix, '\\')) return (0); if (strrchr(suffix, '/')) return (0); if (strrchr(suffix, ':')) return (0); return (1 + strlen(name) + 6 + strlen(suffix)); } /* * dst_s_build_filename () * Builds a key filename from the key name, it's id, and a * suffix. '\', '/' and ':' are not allowed. fA filename is of the * form: K. * form: K++. * * Returns -1 if the conversion fails: * if the filename would be too long for space allotted * if the filename would contain a '\', '/' or ':' * Returns 0 on success */ int dst_s_build_filename(char *filename, const char *name, unsigned id, int alg, const char *suffix, size_t filename_length) { unsigned my_id; if (filename == NULL) return (-1); memset(filename, 0, filename_length); if (name == NULL) return (-1); if (suffix == NULL) return (-1); if (filename_length < 1 + strlen(name) + 4 + 6 + 1 + strlen(suffix)) return (-1); my_id = id; sprintf(filename, "K%s+%03d+%05d.%s", name, alg, my_id, (const char *) suffix); if (strrchr(filename, '/')) return (-1); if (strrchr(filename, '\\')) return (-1); if (strrchr(filename, ':')) return (-1); return (0); } /* * dst_s_fopen () * Open a file in the dst_path directory. If perm is specified, the * file is checked for existence first, and not opened if it exists. * Parameters * filename File to open * mode Mode to open the file (passed directly to fopen) * perm File permission, if creating a new file. * Returns * NULL Failure * NON-NULL (FILE *) of opened file. */ FILE * dst_s_fopen(const char *filename, const char *mode, unsigned perm) { FILE *fp; char pathname[PATH_MAX]; unsigned plen = sizeof(pathname); if (*dst_path != '\0') { strcpy(pathname, dst_path); plen -= strlen(pathname); } else pathname[0] = '\0'; if (plen > strlen(filename)) strncpy(&pathname[PATH_MAX - plen], filename, plen-1); else return (NULL); fp = fopen(pathname, mode); if (perm) chmod(pathname, perm); return (fp); } #if 0 void dst_s_dump(const int mode, const u_char *data, const int size, const char *msg) { if (size > 0) { #ifdef LONG_TEST static u_char scratch[1000]; int n ; n = b64_ntop(data, scratch, size, sizeof(scratch)); printf("%s: %x %d %s\n", msg, mode, n, scratch); #else printf("%s,%x %d\n", msg, mode, size); #endif } } #endif Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/hmac_link.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/hmac_link.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/hmac_link.c (revision 131136) @@ -1,494 +1,494 @@ #ifdef HMAC_MD5 #ifndef LINT -static const char rcsid[] = "$Header: /rc0/proj/cvs/isc/DHCP/dst/hmac_link.c,v 1.1 2001/02/22 07:22:08 mellon Exp $"; +static const char rcsid[] = "$Header: /proj/cvs/prod/DHCP/dst/hmac_link.c,v 1.1 2001/02/22 07:22:08 mellon Exp $"; #endif /* * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. * * Permission to use, copy modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. */ /* * This file contains an implementation of the HMAC-MD5 algorithm. */ #include #include #include #include #include #include #include #include #include #include "minires/minires.h" #include "arpa/nameser.h" #include "dst_internal.h" #ifdef USE_MD5 # include "md5.h" # ifndef _MD5_H_ # define _MD5_H_ 1 /* make sure we do not include rsaref md5.h file */ # endif #endif #define HMAC_LEN 64 #define HMAC_IPAD 0x36 #define HMAC_OPAD 0x5c #define MD5_LEN 16 typedef struct hmackey { u_char hk_ipad[64], hk_opad[64]; } HMAC_Key; /************************************************************************** * dst_hmac_md5_sign * Call HMAC signing functions to sign a block of data. * There are three steps to signing, INIT (initialize structures), * UPDATE (hash (more) data), FINAL (generate a signature). This * routine performs one or more of these steps. * Parameters * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. * priv_key key to use for signing. * context the context to be used in this digest * data data to be signed. * len length in bytes of data. * signature location to store signature. * sig_len size of the signature location * returns * N Success on SIG_MODE_FINAL = returns signature length in bytes * 0 Success on SIG_MODE_INIT and UPDATE * <0 Failure */ static int dst_hmac_md5_sign(const int mode, DST_KEY *d_key, void **context, const u_char *data, const unsigned len, u_char *signature, const unsigned sig_len) { HMAC_Key *key; int sign_len = 0; MD5_CTX *ctx = NULL; if (mode & SIG_MODE_INIT) ctx = (MD5_CTX *) malloc(sizeof(*ctx)); else if (context) ctx = (MD5_CTX *) *context; if (ctx == NULL) return (-1); if (d_key == NULL || d_key->dk_KEY_struct == NULL) return (-1); key = (HMAC_Key *) d_key->dk_KEY_struct; if (mode & SIG_MODE_INIT) { MD5Init(ctx); MD5Update(ctx, key->hk_ipad, HMAC_LEN); } if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) MD5Update(ctx, (const unsigned char *)data, len); if (mode & SIG_MODE_FINAL) { if (signature == NULL || sig_len < MD5_LEN) return (SIGN_FINAL_FAILURE); MD5Final(signature, ctx); /* perform outer MD5 */ MD5Init(ctx); MD5Update(ctx, key->hk_opad, HMAC_LEN); MD5Update(ctx, signature, MD5_LEN); MD5Final(signature, ctx); sign_len = MD5_LEN; SAFE_FREE(ctx); } else { if (context == NULL) return (-1); *context = (void *) ctx; } return (sign_len); } /************************************************************************** * dst_hmac_md5_verify() * Calls HMAC verification routines. There are three steps to * verification, INIT (initialize structures), UPDATE (hash (more) data), * FINAL (generate a signature). This routine performs one or more of * these steps. * Parameters * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. * dkey key to use for verify. * data data signed. * len length in bytes of data. * signature signature. * sig_len length in bytes of signature. * returns * 0 Success * <0 Failure */ static int dst_hmac_md5_verify(const int mode, DST_KEY *d_key, void **context, const u_char *data, const unsigned len, const u_char *signature, const unsigned sig_len) { HMAC_Key *key; MD5_CTX *ctx = NULL; if (mode & SIG_MODE_INIT) ctx = (MD5_CTX *) malloc(sizeof(*ctx)); else if (context) ctx = (MD5_CTX *) *context; if (ctx == NULL) return (-1); if (d_key == NULL || d_key->dk_KEY_struct == NULL) return (-1); key = (HMAC_Key *) d_key->dk_KEY_struct; if (mode & SIG_MODE_INIT) { MD5Init(ctx); MD5Update(ctx, key->hk_ipad, HMAC_LEN); } if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) MD5Update(ctx, (const unsigned char *)data, len); if (mode & SIG_MODE_FINAL) { u_char digest[MD5_LEN]; if (signature == NULL || key == NULL || sig_len != MD5_LEN) return (VERIFY_FINAL_FAILURE); MD5Final(digest, ctx); /* perform outer MD5 */ MD5Init(ctx); MD5Update(ctx, key->hk_opad, HMAC_LEN); MD5Update(ctx, digest, MD5_LEN); MD5Final(digest, ctx); SAFE_FREE(ctx); if (memcmp(digest, signature, MD5_LEN) != 0) return (VERIFY_FINAL_FAILURE); } else { if (context == NULL) return (-1); *context = (void *) ctx; } return (0); } /************************************************************************** * dst_buffer_to_hmac_md5 * Converts key from raw data to an HMAC Key * This function gets in a pointer to the data * Parameters * hkey the HMAC key to be filled in * key the key in raw format * keylen the length of the key * Return * 0 Success * <0 Failure */ static int dst_buffer_to_hmac_md5(DST_KEY *dkey, const u_char *key, const unsigned keylen) { int i; HMAC_Key *hkey = NULL; MD5_CTX ctx; unsigned local_keylen = keylen; if (dkey == NULL || key == NULL || keylen < 0) return (-1); if ((hkey = (HMAC_Key *) malloc(sizeof(HMAC_Key))) == NULL) return (-2); memset(hkey->hk_ipad, 0, sizeof(hkey->hk_ipad)); memset(hkey->hk_opad, 0, sizeof(hkey->hk_opad)); /* if key is longer than HMAC_LEN bytes reset it to key=MD5(key) */ if (keylen > HMAC_LEN) { u_char tk[MD5_LEN]; MD5Init(&ctx); MD5Update(&ctx, (const unsigned char *)key, keylen); MD5Final(tk, &ctx); memset((void *) &ctx, 0, sizeof(ctx)); key = tk; local_keylen = MD5_LEN; } /* start out by storing key in pads */ memcpy(hkey->hk_ipad, key, local_keylen); memcpy(hkey->hk_opad, key, local_keylen); /* XOR key with hk_ipad and opad values */ for (i = 0; i < HMAC_LEN; i++) { hkey->hk_ipad[i] ^= HMAC_IPAD; hkey->hk_opad[i] ^= HMAC_OPAD; } dkey->dk_key_size = local_keylen; dkey->dk_KEY_struct = (void *) hkey; return (1); } /************************************************************************** * dst_hmac_md5_key_to_file_format * Encodes an HMAC Key into the portable file format. * Parameters * hkey HMAC KEY structure * buff output buffer * buff_len size of output buffer * Return * 0 Failure - null input hkey * -1 Failure - not enough space in output area * N Success - Length of data returned in buff */ static int dst_hmac_md5_key_to_file_format(const DST_KEY *dkey, char *buff, const unsigned buff_len) { char *bp; int i; unsigned len, b_len, key_len; u_char key[HMAC_LEN]; HMAC_Key *hkey; if (dkey == NULL || dkey->dk_KEY_struct == NULL) return (0); if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str)) return (-1); /* no OR not enough space in output area */ hkey = (HMAC_Key *) dkey->dk_KEY_struct; memset(buff, 0, buff_len); /* just in case */ /* write file header */ sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_HMAC_MD5, "HMAC"); bp = (char *) strchr(buff, '\0'); b_len = buff_len - (bp - buff); memset(key, 0, HMAC_LEN); for (i = 0; i < HMAC_LEN; i++) key[i] = hkey->hk_ipad[i] ^ HMAC_IPAD; for (i = HMAC_LEN - 1; i >= 0; i--) if (key[i] != 0) break; key_len = i + 1; strcat(bp, "Key: "); bp += strlen("Key: "); b_len = buff_len - (bp - buff); len = b64_ntop(key, key_len, bp, b_len); if (len < 0) return (-1); bp += len; *(bp++) = '\n'; *bp = '\0'; b_len = buff_len - (bp - buff); return (buff_len - b_len); } /************************************************************************** * dst_hmac_md5_key_from_file_format * Converts contents of a key file into an HMAC key. * Parameters * hkey structure to put key into * buff buffer containing the encoded key * buff_len the length of the buffer * Return * n >= 0 Foot print of the key converted * n < 0 Error in conversion */ static int dst_hmac_md5_key_from_file_format(DST_KEY *dkey, const char *buff, const unsigned buff_len) { const char *p = buff, *eol; u_char key[HMAC_LEN+1]; /* b64_pton needs more than 64 bytes do decode * it should probably be fixed rather than doing * this */ u_char *tmp; unsigned key_len, len; if (dkey == NULL) return (-2); if (buff == NULL) return (-1); memset(key, 0, sizeof(key)); if (!dst_s_verify_str(&p, "Key: ")) return (-3); eol = strchr(p, '\n'); if (eol == NULL) return (-4); len = eol - p; tmp = malloc(len + 2); memcpy(tmp, p, len); *(tmp + len) = 0x0; key_len = b64_pton((char *)tmp, key, HMAC_LEN+1); /* see above */ SAFE_FREE2(tmp, len + 2); if (dst_buffer_to_hmac_md5(dkey, key, key_len) < 0) { return (-6); } return (0); } /* * dst_hmac_md5_to_dns_key() * function to extract hmac key from DST_KEY structure * intput: * in_key: HMAC-MD5 key * output: * out_str: buffer to write ot * out_len: size of output buffer * returns: * number of bytes written to output buffer */ static int dst_hmac_md5_to_dns_key(const DST_KEY *in_key, u_char *out_str, const unsigned out_len) { HMAC_Key *hkey; int i; if (in_key == NULL || in_key->dk_KEY_struct == NULL || out_len <= in_key->dk_key_size || out_str == NULL) return (-1); hkey = (HMAC_Key *) in_key->dk_KEY_struct; for (i = 0; i < in_key->dk_key_size; i++) out_str[i] = hkey->hk_ipad[i] ^ HMAC_IPAD; return (i); } /************************************************************************** * dst_hmac_md5_compare_keys * Compare two keys for equality. * Return * 0 The keys are equal * NON-ZERO The keys are not equal */ static int dst_hmac_md5_compare_keys(const DST_KEY *key1, const DST_KEY *key2) { HMAC_Key *hkey1 = (HMAC_Key *) key1->dk_KEY_struct; HMAC_Key *hkey2 = (HMAC_Key *) key2->dk_KEY_struct; return memcmp(hkey1->hk_ipad, hkey2->hk_ipad, HMAC_LEN); } /************************************************************************** * dst_hmac_md5_free_key_structure * Frees all (none) dynamically allocated structures in hkey */ static void * dst_hmac_md5_free_key_structure(void *key) { HMAC_Key *hkey = key; SAFE_FREE(hkey); return (NULL); } /*************************************************************************** * dst_hmac_md5_generate_key * Creates a HMAC key of size size with a maximum size of 63 bytes * generating a HMAC key larger than 63 bytes makes no sense as that key * is digested before use. */ static int dst_hmac_md5_generate_key(DST_KEY *key, const int nothing) { u_char *buff; int n; unsigned size, len; if (key == NULL || key->dk_alg != KEY_HMAC_MD5) return (0); size = (key->dk_key_size + 7) / 8; /* convert to bytes */ if (size <= 0) return(0); len = size > 64 ? 64 : size; buff = malloc(len+8); n = dst_random(DST_RAND_SEMI, len, buff); n += dst_random(DST_RAND_KEY, len, buff); if (n <= len) { /* failed getting anything */ SAFE_FREE2(buff, len); return (-1); } n = dst_buffer_to_hmac_md5(key, buff, len); SAFE_FREE2(buff, len); if (n <= 0) return (n); return (1); } /* * dst_hmac_md5_init() Function to answer set up function pointers for HMAC * related functions */ int dst_hmac_md5_init() { if (dst_t_func[KEY_HMAC_MD5] != NULL) return (1); dst_t_func[KEY_HMAC_MD5] = malloc(sizeof(struct dst_func)); if (dst_t_func[KEY_HMAC_MD5] == NULL) return (0); memset(dst_t_func[KEY_HMAC_MD5], 0, sizeof(struct dst_func)); dst_t_func[KEY_HMAC_MD5]->sign = dst_hmac_md5_sign; dst_t_func[KEY_HMAC_MD5]->verify = dst_hmac_md5_verify; dst_t_func[KEY_HMAC_MD5]->compare = dst_hmac_md5_compare_keys; dst_t_func[KEY_HMAC_MD5]->generate = dst_hmac_md5_generate_key; dst_t_func[KEY_HMAC_MD5]->destroy = dst_hmac_md5_free_key_structure; dst_t_func[KEY_HMAC_MD5]->to_dns_key = dst_hmac_md5_to_dns_key; dst_t_func[KEY_HMAC_MD5]->from_dns_key = dst_buffer_to_hmac_md5; dst_t_func[KEY_HMAC_MD5]->to_file_fmt = dst_hmac_md5_key_to_file_format; dst_t_func[KEY_HMAC_MD5]->from_file_fmt = dst_hmac_md5_key_from_file_format; return (1); } #else int dst_hmac_md5_init(){ return (0); } #endif Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/md5_dgst.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/md5_dgst.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/md5_dgst.c (revision 131136) @@ -1,373 +1,373 @@ /* crypto/md/md5_dgst.c */ /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * 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 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include #include #include #include #include "md5_locl.h" #include "minires/minires.h" #ifdef USE_MD5 /* Added by ogud@tis.com 1998/1/26 */ const char *MD5_version="MD5 part of SSLeay 0.8.1 19-Jul-1997"; /* Implemented from RFC1321 The MD5 Message-Digest Algorithm */ #define INIT_DATA_A (unsigned long)0x67452301L #define INIT_DATA_B (unsigned long)0xefcdab89L #define INIT_DATA_C (unsigned long)0x98badcfeL #define INIT_DATA_D (unsigned long)0x10325476L #ifndef NOPROTO static void md5_block(MD5_CTX *c, unsigned long *p); #else static void md5_block(); #endif void MD5_Init(c) MD5_CTX *c; { c->A=INIT_DATA_A; c->B=INIT_DATA_B; c->C=INIT_DATA_C; c->D=INIT_DATA_D; c->Nl=0; c->Nh=0; c->num=0; } void MD5_Update(c, data, len) MD5_CTX *c; const register unsigned char *data; unsigned long len; { register ULONG *p; int sw,sc; ULONG l; if (len == 0) return; l=(c->Nl+(len<<3))&0xffffffffL; /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to * Wei Dai for pointing it out. */ if (l < c->Nl) /* overflow */ c->Nh++; c->Nh+=(len>>29); c->Nl=l; if (c->num != 0) { p=c->data; sw=c->num>>2; sc=c->num&0x03; if ((c->num+len) >= MD5_CBLOCK) { l= p[sw]; p_c2l(data,l,sc); p[sw++]=l; for (; swnum); md5_block(c,p); c->num=0; /* drop through and do the rest */ } else { int ew,ec; c->num+=(int)len; if ((sc+len) < 4) /* ugly, add char's to a word */ { l= p[sw]; p_c2l_p(data,l,sc,len); p[sw]=l; } else { ew=(c->num>>2); ec=(c->num&0x03); l= p[sw]; p_c2l(data,l,sc); p[sw++]=l; for (; sw < ew; sw++) { c2l(data,l); p[sw]=l; } if (ec) { c2l_p(data,l,ec); p[sw]=l; } } return; } } /* we now can process the input data in blocks of MD5_CBLOCK * chars and save the leftovers to c->data. */ p=c->data; while (len >= MD5_CBLOCK) { #if defined(L_ENDIAN) || defined(B_ENDIAN) memcpy(p,data,MD5_CBLOCK); data+=MD5_CBLOCK; #ifdef B_ENDIAN for (sw=(MD5_LBLOCK/4); sw; sw--) { Endian_Reverse32(p[0]); Endian_Reverse32(p[1]); Endian_Reverse32(p[2]); Endian_Reverse32(p[3]); p+=4; } #endif #else for (sw=(MD5_LBLOCK/4); sw; sw--) { c2l(data,l); *(p++)=l; c2l(data,l); *(p++)=l; c2l(data,l); *(p++)=l; c2l(data,l); *(p++)=l; } #endif p=c->data; md5_block(c,p); len-=MD5_CBLOCK; } sc=(int)len; c->num=sc; if (sc) { sw=sc>>2; /* words to copy */ #ifdef L_ENDIAN p[sw]=0; memcpy(p,data,sc); #else sc&=0x03; for ( ; sw; sw--) { c2l(data,l); *(p++)=l; } c2l_p(data,l,sc); *p=l; #endif } } static void md5_block(c, X) MD5_CTX *c; register ULONG *X; { register ULONG A,B,C,D; A=c->A; B=c->B; C=c->C; D=c->D; /* Round 0 */ - R0(A,B,C,D,X[ 0], 7,0xd76aa478L); - R0(D,A,B,C,X[ 1],12,0xe8c7b756L); - R0(C,D,A,B,X[ 2],17,0x242070dbL); - R0(B,C,D,A,X[ 3],22,0xc1bdceeeL); - R0(A,B,C,D,X[ 4], 7,0xf57c0fafL); - R0(D,A,B,C,X[ 5],12,0x4787c62aL); - R0(C,D,A,B,X[ 6],17,0xa8304613L); - R0(B,C,D,A,X[ 7],22,0xfd469501L); - R0(A,B,C,D,X[ 8], 7,0x698098d8L); - R0(D,A,B,C,X[ 9],12,0x8b44f7afL); - R0(C,D,A,B,X[10],17,0xffff5bb1L); - R0(B,C,D,A,X[11],22,0x895cd7beL); - R0(A,B,C,D,X[12], 7,0x6b901122L); - R0(D,A,B,C,X[13],12,0xfd987193L); - R0(C,D,A,B,X[14],17,0xa679438eL); - R0(B,C,D,A,X[15],22,0x49b40821L); + LOCL_R0(A,B,C,D,X[ 0], 7,0xd76aa478L); + LOCL_R0(D,A,B,C,X[ 1],12,0xe8c7b756L); + LOCL_R0(C,D,A,B,X[ 2],17,0x242070dbL); + LOCL_R0(B,C,D,A,X[ 3],22,0xc1bdceeeL); + LOCL_R0(A,B,C,D,X[ 4], 7,0xf57c0fafL); + LOCL_R0(D,A,B,C,X[ 5],12,0x4787c62aL); + LOCL_R0(C,D,A,B,X[ 6],17,0xa8304613L); + LOCL_R0(B,C,D,A,X[ 7],22,0xfd469501L); + LOCL_R0(A,B,C,D,X[ 8], 7,0x698098d8L); + LOCL_R0(D,A,B,C,X[ 9],12,0x8b44f7afL); + LOCL_R0(C,D,A,B,X[10],17,0xffff5bb1L); + LOCL_R0(B,C,D,A,X[11],22,0x895cd7beL); + LOCL_R0(A,B,C,D,X[12], 7,0x6b901122L); + LOCL_R0(D,A,B,C,X[13],12,0xfd987193L); + LOCL_R0(C,D,A,B,X[14],17,0xa679438eL); + LOCL_R0(B,C,D,A,X[15],22,0x49b40821L); /* Round 1 */ - R1(A,B,C,D,X[ 1], 5,0xf61e2562L); - R1(D,A,B,C,X[ 6], 9,0xc040b340L); - R1(C,D,A,B,X[11],14,0x265e5a51L); - R1(B,C,D,A,X[ 0],20,0xe9b6c7aaL); - R1(A,B,C,D,X[ 5], 5,0xd62f105dL); - R1(D,A,B,C,X[10], 9,0x02441453L); - R1(C,D,A,B,X[15],14,0xd8a1e681L); - R1(B,C,D,A,X[ 4],20,0xe7d3fbc8L); - R1(A,B,C,D,X[ 9], 5,0x21e1cde6L); - R1(D,A,B,C,X[14], 9,0xc33707d6L); - R1(C,D,A,B,X[ 3],14,0xf4d50d87L); - R1(B,C,D,A,X[ 8],20,0x455a14edL); - R1(A,B,C,D,X[13], 5,0xa9e3e905L); - R1(D,A,B,C,X[ 2], 9,0xfcefa3f8L); - R1(C,D,A,B,X[ 7],14,0x676f02d9L); - R1(B,C,D,A,X[12],20,0x8d2a4c8aL); + LOCL_R1(A,B,C,D,X[ 1], 5,0xf61e2562L); + LOCL_R1(D,A,B,C,X[ 6], 9,0xc040b340L); + LOCL_R1(C,D,A,B,X[11],14,0x265e5a51L); + LOCL_R1(B,C,D,A,X[ 0],20,0xe9b6c7aaL); + LOCL_R1(A,B,C,D,X[ 5], 5,0xd62f105dL); + LOCL_R1(D,A,B,C,X[10], 9,0x02441453L); + LOCL_R1(C,D,A,B,X[15],14,0xd8a1e681L); + LOCL_R1(B,C,D,A,X[ 4],20,0xe7d3fbc8L); + LOCL_R1(A,B,C,D,X[ 9], 5,0x21e1cde6L); + LOCL_R1(D,A,B,C,X[14], 9,0xc33707d6L); + LOCL_R1(C,D,A,B,X[ 3],14,0xf4d50d87L); + LOCL_R1(B,C,D,A,X[ 8],20,0x455a14edL); + LOCL_R1(A,B,C,D,X[13], 5,0xa9e3e905L); + LOCL_R1(D,A,B,C,X[ 2], 9,0xfcefa3f8L); + LOCL_R1(C,D,A,B,X[ 7],14,0x676f02d9L); + LOCL_R1(B,C,D,A,X[12],20,0x8d2a4c8aL); /* Round 2 */ - R2(A,B,C,D,X[ 5], 4,0xfffa3942L); - R2(D,A,B,C,X[ 8],11,0x8771f681L); - R2(C,D,A,B,X[11],16,0x6d9d6122L); - R2(B,C,D,A,X[14],23,0xfde5380cL); - R2(A,B,C,D,X[ 1], 4,0xa4beea44L); - R2(D,A,B,C,X[ 4],11,0x4bdecfa9L); - R2(C,D,A,B,X[ 7],16,0xf6bb4b60L); - R2(B,C,D,A,X[10],23,0xbebfbc70L); - R2(A,B,C,D,X[13], 4,0x289b7ec6L); - R2(D,A,B,C,X[ 0],11,0xeaa127faL); - R2(C,D,A,B,X[ 3],16,0xd4ef3085L); - R2(B,C,D,A,X[ 6],23,0x04881d05L); - R2(A,B,C,D,X[ 9], 4,0xd9d4d039L); - R2(D,A,B,C,X[12],11,0xe6db99e5L); - R2(C,D,A,B,X[15],16,0x1fa27cf8L); - R2(B,C,D,A,X[ 2],23,0xc4ac5665L); + LOCL_R2(A,B,C,D,X[ 5], 4,0xfffa3942L); + LOCL_R2(D,A,B,C,X[ 8],11,0x8771f681L); + LOCL_R2(C,D,A,B,X[11],16,0x6d9d6122L); + LOCL_R2(B,C,D,A,X[14],23,0xfde5380cL); + LOCL_R2(A,B,C,D,X[ 1], 4,0xa4beea44L); + LOCL_R2(D,A,B,C,X[ 4],11,0x4bdecfa9L); + LOCL_R2(C,D,A,B,X[ 7],16,0xf6bb4b60L); + LOCL_R2(B,C,D,A,X[10],23,0xbebfbc70L); + LOCL_R2(A,B,C,D,X[13], 4,0x289b7ec6L); + LOCL_R2(D,A,B,C,X[ 0],11,0xeaa127faL); + LOCL_R2(C,D,A,B,X[ 3],16,0xd4ef3085L); + LOCL_R2(B,C,D,A,X[ 6],23,0x04881d05L); + LOCL_R2(A,B,C,D,X[ 9], 4,0xd9d4d039L); + LOCL_R2(D,A,B,C,X[12],11,0xe6db99e5L); + LOCL_R2(C,D,A,B,X[15],16,0x1fa27cf8L); + LOCL_R2(B,C,D,A,X[ 2],23,0xc4ac5665L); /* Round 3 */ - R3(A,B,C,D,X[ 0], 6,0xf4292244L); - R3(D,A,B,C,X[ 7],10,0x432aff97L); - R3(C,D,A,B,X[14],15,0xab9423a7L); - R3(B,C,D,A,X[ 5],21,0xfc93a039L); - R3(A,B,C,D,X[12], 6,0x655b59c3L); - R3(D,A,B,C,X[ 3],10,0x8f0ccc92L); - R3(C,D,A,B,X[10],15,0xffeff47dL); - R3(B,C,D,A,X[ 1],21,0x85845dd1L); - R3(A,B,C,D,X[ 8], 6,0x6fa87e4fL); - R3(D,A,B,C,X[15],10,0xfe2ce6e0L); - R3(C,D,A,B,X[ 6],15,0xa3014314L); - R3(B,C,D,A,X[13],21,0x4e0811a1L); - R3(A,B,C,D,X[ 4], 6,0xf7537e82L); - R3(D,A,B,C,X[11],10,0xbd3af235L); - R3(C,D,A,B,X[ 2],15,0x2ad7d2bbL); - R3(B,C,D,A,X[ 9],21,0xeb86d391L); + LOCL_R3(A,B,C,D,X[ 0], 6,0xf4292244L); + LOCL_R3(D,A,B,C,X[ 7],10,0x432aff97L); + LOCL_R3(C,D,A,B,X[14],15,0xab9423a7L); + LOCL_R3(B,C,D,A,X[ 5],21,0xfc93a039L); + LOCL_R3(A,B,C,D,X[12], 6,0x655b59c3L); + LOCL_R3(D,A,B,C,X[ 3],10,0x8f0ccc92L); + LOCL_R3(C,D,A,B,X[10],15,0xffeff47dL); + LOCL_R3(B,C,D,A,X[ 1],21,0x85845dd1L); + LOCL_R3(A,B,C,D,X[ 8], 6,0x6fa87e4fL); + LOCL_R3(D,A,B,C,X[15],10,0xfe2ce6e0L); + LOCL_R3(C,D,A,B,X[ 6],15,0xa3014314L); + LOCL_R3(B,C,D,A,X[13],21,0x4e0811a1L); + LOCL_R3(A,B,C,D,X[ 4], 6,0xf7537e82L); + LOCL_R3(D,A,B,C,X[11],10,0xbd3af235L); + LOCL_R3(C,D,A,B,X[ 2],15,0x2ad7d2bbL); + LOCL_R3(B,C,D,A,X[ 9],21,0xeb86d391L); c->A+=A&0xffffffffL; c->B+=B&0xffffffffL; c->C+=C&0xffffffffL; c->D+=D&0xffffffffL; } void MD5_Final(md, c) unsigned char *md; MD5_CTX *c; { register int i,j; register ULONG l; register ULONG *p; static unsigned char end[4]={0x80,0x00,0x00,0x00}; unsigned char *cp=end; /* c->num should definitly have room for at least one more byte. */ p=c->data; j=c->num; i=j>>2; /* purify often complains about the following line as an * Uninitialized Memory Read. While this can be true, the * following p_c2l macro will reset l when that case is true. * This is because j&0x03 contains the number of 'valid' bytes * already in p[i]. If and only if j&0x03 == 0, the UMR will * occur but this is also the only time p_c2l will do * l= *(cp++) instead of l|= *(cp++) * Many thanks to Alex Tang for pickup this * 'potential bug' */ #ifdef PURIFY if ((j&0x03) == 0) p[i]=0; #endif l=p[i]; p_c2l(cp,l,j&0x03); p[i]=l; i++; /* i is the next 'undefined word' */ if (c->num >= MD5_LAST_BLOCK) { for (; iNl; p[MD5_LBLOCK-1]=c->Nh; md5_block(c,p); cp=md; l=c->A; l2c(l,cp); l=c->B; l2c(l,cp); l=c->C; l2c(l,cp); l=c->D; l2c(l,cp); /* clear stuff, md5_block may be leaving some stuff on the stack * but I'm not worried :-) */ c->num=0; /* memset((char *)&c,0,sizeof(c));*/ } #ifdef undef int printit(l) unsigned long *l; { int i,ii; for (i=0; i<2; i++) { for (ii=0; ii<8; ii++) { fprintf(stderr,"%08lx ",l[i*8+ii]); } fprintf(stderr,"\n"); } } #endif #endif /* USE_MD5 */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/md5_locl.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/md5_locl.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/md5_locl.h (revision 131136) @@ -1,190 +1,189 @@ /* crypto/md/md5_locl.h */ /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * 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 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #include #include #include "md5.h" #define ULONG unsigned long #define UCHAR unsigned char #define UINT unsigned int #if defined(NOCONST) #define const #endif #undef c2l #define c2l(c,l) (l = ((unsigned long)(*((c)++))) , \ l|=(((unsigned long)(*((c)++)))<< 8), \ l|=(((unsigned long)(*((c)++)))<<16), \ l|=(((unsigned long)(*((c)++)))<<24)) #undef p_c2l #define p_c2l(c,l,n) { \ switch (n) { \ case 0: l =((unsigned long)(*((c)++))); \ case 1: l|=((unsigned long)(*((c)++)))<< 8; \ case 2: l|=((unsigned long)(*((c)++)))<<16; \ case 3: l|=((unsigned long)(*((c)++)))<<24; \ } \ } /* NOTE the pointer is not incremented at the end of this */ #undef c2l_p #define c2l_p(c,l,n) { \ l=0; \ (c)+=n; \ switch (n) { \ case 3: l =((unsigned long)(*(--(c))))<<16; \ case 2: l|=((unsigned long)(*(--(c))))<< 8; \ case 1: l|=((unsigned long)(*(--(c)))) ; \ } \ } #undef p_c2l_p #define p_c2l_p(c,l,sc,len) { \ switch (sc) \ { \ case 0: l =((unsigned long)(*((c)++))); \ if (--len == 0) break; \ case 1: l|=((unsigned long)(*((c)++)))<< 8; \ if (--len == 0) break; \ case 2: l|=((unsigned long)(*((c)++)))<<16; \ } \ } #undef l2c #define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ *((c)++)=(unsigned char)(((l)>>16)&0xff), \ *((c)++)=(unsigned char)(((l)>>24)&0xff)) /* NOTE - c is not incremented as per l2c */ #undef l2cn #define l2cn(l1,l2,c,n) { \ c+=n; \ switch (n) { \ case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ } \ } /* A nice byte order reversal from Wei Dai */ #if defined(WIN32) /* 5 instructions with rotate instruction, else 9 */ #define Endian_Reverse32(a) \ { \ unsigned long l=(a); \ (a)=((ROTATE(l,8)&0x00FF00FF)|(ROTATE(l,24)&0xFF00FF00)); \ } #else /* 6 instructions with rotate instruction, else 8 */ #define Endian_Reverse32(a) \ { \ unsigned long l=(a); \ l=(((l&0xFF00FF00)>>8L)|((l&0x00FF00FF)<<8L)); \ (a)=ROTATE(l,16L); \ } #endif /* #define F(x,y,z) (((x) & (y)) | ((~(x)) & (z))) #define G(x,y,z) (((x) & (z)) | ((y) & (~(z)))) */ /* As pointed out by Wei Dai , the above can be * simplified to the code below. Wei attributes these optimisations * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel. */ #define F(x,y,z) ((((y) ^ (z)) & (x)) ^ (z)) #define G(x,y,z) ((((x) ^ (y)) & (z)) ^ (y)) #define H(x,y,z) ((x) ^ (y) ^ (z)) #define I(x,y,z) (((x) | (~(z))) ^ (y)) #undef ROTATE #if defined(WIN32) #define ROTATE(a,n) _lrotl(a,n) #else #define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) #endif - -#define R0(a,b,c,d,k,s,t) { \ +#define LOCL_R0(a,b,c,d,k,s,t) { \ a+=((k)+(t)+F((b),(c),(d))); \ a=ROTATE(a,s); \ a+=b; };\ -#define R1(a,b,c,d,k,s,t) { \ +#define LOCL_R1(a,b,c,d,k,s,t) { \ a+=((k)+(t)+G((b),(c),(d))); \ a=ROTATE(a,s); \ a+=b; }; -#define R2(a,b,c,d,k,s,t) { \ +#define LOCL_R2(a,b,c,d,k,s,t) { \ a+=((k)+(t)+H((b),(c),(d))); \ a=ROTATE(a,s); \ a+=b; }; -#define R3(a,b,c,d,k,s,t) { \ +#define LOCL_R3(a,b,c,d,k,s,t) { \ a+=((k)+(t)+I((b),(c),(d))); \ a=ROTATE(a,s); \ a+=b; }; Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/prandom.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/prandom.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/dst/prandom.c (revision 131136) @@ -1,862 +1,862 @@ #ifndef LINT -static const char rcsid[] = "$Header: /rc0/proj/cvs/isc/DHCP/dst/prandom.c,v 1.1 2001/02/22 07:22:09 mellon Exp $"; +static const char rcsid[] = "$Header: /proj/cvs/prod/DHCP/dst/prandom.c,v 1.1 2001/02/22 07:22:09 mellon Exp $"; #endif /* * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. * * Permission to use, copy modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define NEED_PRAND_CONF #include "minires/minires.h" #include "dst_internal.h" #include "arpa/nameser.h" #ifndef DST_NUM_HASHES #define DST_NUM_HASHES 4 #endif #ifndef DST_NUMBER_OF_COUNTERS #define DST_NUMBER_OF_COUNTERS 5 /* 32 * 5 == 160 == SHA(1) > MD5 */ #endif /* * the constant below is a prime number to make fixed data structues like * stat and time wrap over blocks. This adds certain uncertanty to what is * in each digested block. * The prime number 2879 has the special property that when * divided by 2,4 and 6 the result is also a prime numbers */ #ifndef DST_RANDOM_BLOCK_SIZE #define DST_RANDOM_BLOCK_SIZE 2879 #endif /* * This constant dictatates how many bits we shift to the right before using a */ #ifndef DST_SHIFT #define DST_SHIFT 9 #endif /* * An initalizer that is as bad as any other with half the bits set */ #ifndef DST_RANDOM_PATTERN #define DST_RANDOM_PATTERN 0x8765CA93 #endif /* * things must have changed in the last 3600 seconds to be used */ #define MAX_OLD 3600 /* * these two data structure are used to process input data into digests, * * The first structure is containts a pointer to a DST HMAC key * the variables accompanying are used for * step : select every step byte from input data for the hash * block: number of data elements going into each hash * digested: number of data elements digested so far * curr: offset into the next input data for the first byte. */ typedef struct hash { DST_KEY *key; void *ctx; int digested, block, step, curr; } prand_hash; /* * This data structure controlls number of hashes and keeps track of * overall progress in generating correct number of bytes of output. * output : array to store the output data in * needed : how many bytes of output are needed * filled : number of bytes in output so far. * bytes : total number of bytes processed by this structure * file_digest : the HMAC key used to digest files. */ typedef struct work { unsigned needed, filled, bytes; u_char *output; prand_hash *hash[DST_NUM_HASHES]; DST_KEY *file_digest; } dst_work; /* * forward function declarations */ static int get_dev_random(u_char *output, unsigned size); static int do_time(dst_work *work); static int do_ls(dst_work *work); static int unix_cmd(dst_work *work); static int digest_file(dst_work *work); static void force_hash(dst_work *work, prand_hash *hash); static int do_hash(dst_work *work, prand_hash *hash, const u_char *input, unsigned size); static int my_digest(dst_work *tmp, const u_char *input, unsigned size); static prand_hash *get_hmac_key(int step, int block); static unsigned own_random(dst_work *work); /* * variables used in the quick random number generator */ static u_int32_t ran_val = DST_RANDOM_PATTERN; static u_int32_t ran_cnt = (DST_RANDOM_PATTERN >> 10); /* * setting the quick_random generator to particular values or if both * input parameters are 0 then set it to initial vlaues */ void dst_s_quick_random_set(u_int32_t val, u_int32_t cnt) { ran_val = (val == 0) ? DST_RANDOM_PATTERN : val; ran_cnt = (cnt == 0) ? (DST_RANDOM_PATTERN >> 10) : cnt; } /* * this is a quick and random number generator that seems to generate quite * good distribution of data */ u_int32_t dst_s_quick_random(int inc) { ran_val = ((ran_val >> 13) ^ (ran_val << 19)) ^ ((ran_val >> 7) ^ (ran_val << 25)); if (inc > 0) /* only increasing values accepted */ ran_cnt += inc; ran_val += ran_cnt++; return (ran_val); } /* * get_dev_random: Function to read /dev/random reliably * this function returns how many bytes where read from the device. * port_after.h should set the control variable HAVE_DEV_RANDOM */ static int get_dev_random(u_char *output, unsigned size) { #ifdef HAVE_DEV_RANDOM struct stat st; int n = 0, fd = -1, s; s = stat("/dev/random", &st); if (s == 0 && S_ISCHR(st.st_mode)) { if ((fd = open("/dev/random", O_RDONLY | O_NONBLOCK)) != -1) { if ((n = read(fd, output, size)) < 0) n = 0; close(fd); } return (n); } #endif return (0); } /* * Portable way of getting the time values if gettimeofday is missing * then compile with -DMISSING_GETTIMEOFDAY time() is POSIX compliant but * gettimeofday() is not. * Time of day is predictable, we are looking for the randomness that comes * the last few bits in the microseconds in the timer are hard to predict when * this is invoked at the end of other operations */ struct timeval *mtime; static int do_time(dst_work *work) { int cnt = 0; static u_char tmp[sizeof(struct timeval) + sizeof(struct timezone)]; struct timezone *zone; zone = (struct timezone *) tmp; mtime = (struct timeval *)(tmp + sizeof(struct timezone)); gettimeofday(mtime, zone); cnt = sizeof(tmp); my_digest(work, tmp, sizeof(tmp)); return (cnt); } /* * this function simulates the ls command, but it uses stat which gives more * information and is harder to guess * Each call to this function will visit the next directory on the list of * directories, in a circular manner. * return value is the number of bytes added to the temp buffer * * do_ls() does not visit subdirectories * if attacker has access to machine it can guess most of the values seen * thus it is important to only visit directories that are freqently updated * Attacker that has access to the network can see network traffic * when NFS mounted directories are accessed and know exactly the data used * but may not know exactly in what order data is used. * Returns the number of bytes that where returned in stat structures */ static int do_ls(dst_work *work) { struct dir_info { uid_t uid; gid_t gid; off_t size; time_t atime, mtime, ctime; }; static struct dir_info dir_info; struct stat buf; struct dirent *entry; static int i = 0; static unsigned long d_round = 0; struct timeval tv; int n = 0, tb_i = 0, out = 0; unsigned dir_len; char file_name[1024]; u_char tmp_buff[1024]; DIR *dir = NULL; if (dirs[i] == NULL) /* if at the end of the list start over */ i = 0; if (stat(dirs[i++], &buf)) /* directory does not exist */ return (0); gettimeofday(&tv,NULL); if (d_round == 0) d_round = tv.tv_sec - MAX_OLD; else if (i==1) /* if starting a new round cut what we accept */ d_round += (tv.tv_sec - d_round)/2; if (buf.st_atime < d_round) return (0); EREPORT(("do_ls i %d filled %4d in_temp %4d\n", i-1, work->filled, work->in_temp)); memcpy(tmp_buff, &buf, sizeof(buf)); tb_i += sizeof(buf); if ((dir = opendir(dirs[i-1])) == NULL)/* open it for read */ return (0); strcpy(file_name, dirs[i-1]); dir_len = strlen(file_name); file_name[dir_len++] = '/'; while ((entry = readdir(dir))) { unsigned len = strlen(entry->d_name); out += len; if (my_digest(work, (u_char *)entry->d_name, len)) break; memcpy(&file_name[dir_len], entry->d_name, len); file_name[dir_len + len] = 0x0; /* for all entries in dir get the stats */ if (stat(file_name, &buf) == 0) { n++; /* count successfull stat calls */ /* copy non static fields */ dir_info.uid += buf.st_uid; dir_info.gid += buf.st_gid; dir_info.size += buf.st_size; dir_info.atime += buf.st_atime; dir_info.mtime += buf.st_mtime; dir_info.ctime += buf.st_ctime; out += sizeof(dir_info); if(my_digest(work, (u_char *)&dir_info, sizeof(dir_info))) break; } } closedir(dir); /* done */ out += do_time(work); /* add a time stamp */ return (out); } /* * unix_cmd() * this function executes the a command from the cmds[] list of unix commands * configured in the prand_conf.h file * return value is the number of bytes added to the randomness temp buffer * * it returns the number of bytes that where read in * if more data is needed at the end time is added to the data. * This function maintains a state to selects the next command to run * returns the number of bytes read in from the command */ static int unix_cmd(dst_work *work) { static int cmd_index = 0; int cnt = 0, n; FILE *pipe; u_char buffer[4096]; if (cmds[cmd_index] == NULL) cmd_index = 0; EREPORT(("unix_cmd() i %d filled %4d in_temp %4d\n", cmd_index, work->filled, work->in_temp)); pipe = popen(cmds[cmd_index++], "r"); /* execute the command */ while ((n = fread(buffer, sizeof(char), sizeof(buffer), pipe)) > 0) { cnt += n; /* process the output */ if (my_digest(work, buffer, (unsigned)n)) break; /* this adds some randomness to the output */ cnt += do_time(work); } while ((n = fread(buffer, sizeof(char), sizeof(buffer), pipe)) > 0) NULL; /* drain the pipe */ pclose(pipe); return (cnt); /* read how many bytes where read in */ } /* * digest_file() This function will read a file and run hash over it * input is a file name */ static int digest_file(dst_work *work) { static int f_cnt = 0; static unsigned long f_round = 0; FILE *fp; void *ctx; const char *name; int no, i; struct stat st; struct timeval tv; u_char buf[1024]; if (f_round == 0 || files[f_cnt] == NULL || work->file_digest == NULL) if (gettimeofday(&tv, NULL)) /* only do this if needed */ return (0); if (f_round == 0) /* first time called set to one hour ago */ f_round = (tv.tv_sec - MAX_OLD); name = files[f_cnt++]; if (files[f_cnt] == NULL) { /* end of list of files */ if(f_cnt <= 1) /* list is too short */ return (0); f_cnt = 0; /* start again on list */ f_round += (tv.tv_sec - f_round)/2; /* set new cutoff */ work->file_digest = dst_free_key(work->file_digest); } if (work->file_digest == NULL) { work->file_digest = dst_buffer_to_key("", KEY_HMAC_MD5, 0, 0, (u_char *)&tv, sizeof(tv)); if (work->file_digest == NULL) return (0); } if (access(name, R_OK) || stat(name, &st)) return (0); /* no such file or not allowed to read it */ if (strncmp(name, "/proc/", 6) && st.st_mtime < f_round) return(0); /* file has not changed recently enough */ if (dst_sign_data(SIG_MODE_INIT, work->file_digest, &ctx, NULL, 0, NULL, 0)) { work->file_digest = dst_free_key(work->file_digest); return (0); } if ((fp = fopen(name, "r")) == NULL) return (0); for (no = 0; (i = fread(buf, sizeof(*buf), sizeof(buf), fp)) > 0; no += i) dst_sign_data(SIG_MODE_UPDATE, work->file_digest, &ctx, buf, (unsigned)i, NULL, 0); fclose(fp); if (no >= 64) { i = dst_sign_data(SIG_MODE_FINAL, work->file_digest, &ctx, NULL, 0, &work->output[work->filled], DST_HASH_SIZE); if (i > 0) work->filled += i; } else if (i > 0) my_digest(work, buf, (unsigned)i); my_digest(work, (const u_char *)name, strlen(name)); return (no + strlen(name)); } /* * function to perform the FINAL and INIT operation on a hash if allowed */ static void force_hash(dst_work *work, prand_hash *hash) { int i = 0; /* * if more than half a block then add data to output * otherwise adde the digest to the next hash */ if ((hash->digested * 2) > hash->block) { i = dst_sign_data(SIG_MODE_FINAL, hash->key, &hash->ctx, NULL, 0, &work->output[work->filled], DST_HASH_SIZE); hash->digested = 0; dst_sign_data(SIG_MODE_INIT, hash->key, &hash->ctx, NULL, 0, NULL, 0); if (i > 0) work->filled += i; } return; } /* * This function takes the input data does the selection of data specified * by the hash control block. * The step varialbe in the work sturcture determines which 1/step bytes * are used, * */ static int do_hash(dst_work *work, prand_hash *hash, const u_char *input, unsigned size) { const u_char *tmp = input; u_char *tp, *abuf = (u_char *)0; int i, n; unsigned needed, avail, dig, cnt = size; unsigned tmp_size = 0; if (cnt <= 0 || input == NULL) return (0); if (hash->step > 1) { /* if using subset of input data */ tmp_size = size / hash->step + 2; abuf = tp = malloc(tmp_size); tmp = tp; for (cnt = 0, i = hash->curr; i < size; i += hash->step, cnt++) *(tp++) = input[i]; /* calcutate the starting point in the next input set */ hash->curr = (hash->step - (i - size)) % hash->step; } /* digest the data in block sizes */ for (n = 0; n < cnt; n += needed) { avail = (cnt - n); needed = hash->block - hash->digested; dig = (avail < needed) ? avail : needed; dst_sign_data(SIG_MODE_UPDATE, hash->key, &hash->ctx, &tmp[n], dig, NULL, 0); hash->digested += dig; if (hash->digested >= hash->block) force_hash(work, hash); if (work->needed < work->filled) { if (abuf) SAFE_FREE2(abuf, tmp_size); return (1); } } if (tmp_size > 0) SAFE_FREE2(abuf, tmp_size); return (0); } /* * Copy data from INPUT for length SIZE into the work-block TMP. * If we fill the work-block, digest it; then, * if work-block needs more data, keep filling with the rest of the input. */ static int my_digest(dst_work *work, const u_char *input, unsigned size) { int i, full = 0; static unsigned counter; counter += size; /* first do each one of the hashes */ for (i = 0; i < DST_NUM_HASHES && full == 0; i++) full = do_hash(work, work->hash[i], input, size) + do_hash(work, work->hash[i], (u_char *) &counter, sizeof(counter)); /* * if enough data has be generated do final operation on all hashes * that have enough date for that */ for (i = 0; full && (i < DST_NUM_HASHES); i++) force_hash(work, work->hash[i]); return (full); } /* * this function gets some semi random data and sets that as an HMAC key * If we get a valid key this function returns that key initalized * otherwise it returns NULL; */ static prand_hash * get_hmac_key(int step, int block) { u_char *buff; int temp = 0, n = 0; unsigned size = 70; DST_KEY *new_key = NULL; prand_hash *new = NULL; /* use key that is larger than digest algorithms (64) for key size */ buff = malloc(size); if (buff == NULL) return (NULL); /* do not memset the allocated memory to get random bytes there */ /* time of day is somewhat random expecialy in the last bytes */ gettimeofday((struct timeval *) &buff[n], NULL); n += sizeof(struct timeval); /* get some semi random stuff in here stir it with micro seconds */ if (n < size) { temp = dst_s_quick_random((int) buff[n - 1]); memcpy(&buff[n], &temp, sizeof(temp)); n += sizeof(temp); } /* get the pid of this process and its parent */ if (n < size) { temp = (int) getpid(); memcpy(&buff[n], &temp, sizeof(temp)); n += sizeof(temp); } if (n < size) { temp = (int) getppid(); memcpy(&buff[n], &temp, sizeof(temp)); n += sizeof(temp); } /* get the user ID */ if (n < size) { temp = (int) getuid(); memcpy(&buff[n], &temp, sizeof(temp)); n += sizeof(temp); } #ifndef GET_HOST_ID_MISSING if (n < size) { temp = (int) gethostid(); memcpy(&buff[n], &temp, sizeof(temp)); n += sizeof(temp); } #endif /* get some more random data */ if (n < size) { temp = dst_s_quick_random((int) buff[n - 1]); memcpy(&buff[n], &temp, sizeof(temp)); n += sizeof(temp); } /* covert this into a HMAC key */ new_key = dst_buffer_to_key("", KEY_HMAC_MD5, 0, 0, buff, size); SAFE_FREE(buff); /* get the control structure */ if ((new = malloc(sizeof(prand_hash))) == NULL) return (NULL); new->digested = new->curr = 0; new->step = step; new->block = block; new->key = new_key; if (dst_sign_data(SIG_MODE_INIT, new_key, &new->ctx, NULL, 0, NULL, 0)) return (NULL); return (new); } /* * own_random() * This function goes out and from various sources tries to generate enough * semi random data that a hash function can generate a random data. * This function will iterate between the two main random source sources, * information from programs and directores in random order. * This function return the number of bytes added to the random output buffer. */ static unsigned own_random(dst_work *work) { int dir = 0, b; int bytes, n, cmd = 0, dig = 0; int start =0; /* * now get the initial seed to put into the quick random function from * the address of the work structure */ bytes = (int) getpid(); /* * proceed while needed */ while (work->filled < work->needed) { EREPORT(("own_random r %08x b %6d t %6d f %6d\n", ran_val, bytes, work->in_temp, work->filled)); /* pick a random number in the range of 0..7 based on that random number * perform some operations that yield random data */ start = work->filled; n = (dst_s_quick_random(bytes) >> DST_SHIFT) & 0x07; switch (n) { case 0: case 3: if (sizeof(cmds) > 2 *sizeof(*cmds)) { b = unix_cmd(work); cmd += b; } break; case 1: case 7: if (sizeof(dirs) > 2 *sizeof(*dirs)) { b = do_ls(work); dir += b; } break; case 4: case 5: /* retry getting data from /dev/random */ b = get_dev_random(&work->output[work->filled], work->needed - work->filled); if (b > 0) work->filled += b; break; case 6: if (sizeof(files) > 2 * sizeof(*files)) { b = digest_file(work); dig += b; } break; case 2: default: /* to make sure we make some progress */ work->output[work->filled++] = 0xff & dst_s_quick_random(bytes); b = 1; break; } if (b > 0) bytes += b; } return (work->filled); } /* * dst_s_random() This function will return the requested number of bytes * of randomness to the caller it will use the best available sources of * randomness. * The current order is to use /dev/random, precalculated randomness, and * finaly use some system calls and programs to generate semi random data that * is then digested to generate randomness. * This function is thread safe as each thread uses its own context, but * concurrent treads will affect each other as they update shared state * information. * It is strongly recommended that this function be called requesting a size * that is not a multiple of the output of the hash function used. * * If /dev/random is not available this function is not suitable to generate * large ammounts of data, rather it is suitable to seed a pseudo-random * generator * Returns the number of bytes put in the output buffer */ int dst_s_random(u_char *output, unsigned size) { int n = 0, i; unsigned s; static u_char old_unused[DST_HASH_SIZE * DST_NUM_HASHES]; static unsigned unused = 0; if (size <= 0 || output == NULL) return (0); if (size >= 2048) return (-1); /* * Read from /dev/random */ n = get_dev_random(output, size); /* * If old data is available and needed use it */ if (n < size && unused > 0) { unsigned need = size - n; if (unused <= need) { memcpy(output, old_unused, unused); n += unused; unused = 0; } else { memcpy(output, old_unused, need); n += need; unused -= need; memcpy(old_unused, &old_unused[need], unused); } } /* * If we need more use the simulated randomness here. */ if (n < size) { dst_work *my_work = (dst_work *) malloc(sizeof(dst_work)); if (my_work == NULL) return (n); my_work->needed = size - n; my_work->filled = 0; my_work->output = (u_char *) malloc(my_work->needed + DST_HASH_SIZE * DST_NUM_HASHES); my_work->file_digest = NULL; if (my_work->output == NULL) return (n); memset(my_work->output, 0x0, my_work->needed); /* allocate upto 4 different HMAC hash functions out of order */ #if DST_NUM_HASHES >= 3 my_work->hash[2] = get_hmac_key(3, DST_RANDOM_BLOCK_SIZE / 2); #endif #if DST_NUM_HASHES >= 2 my_work->hash[1] = get_hmac_key(7, DST_RANDOM_BLOCK_SIZE / 6); #endif #if DST_NUM_HASHES >= 4 my_work->hash[3] = get_hmac_key(5, DST_RANDOM_BLOCK_SIZE / 4); #endif my_work->hash[0] = get_hmac_key(1, DST_RANDOM_BLOCK_SIZE); if (my_work->hash[0] == NULL) /* if failure bail out */ return (n); s = own_random(my_work); /* if more generated than needed store it for future use */ if (s >= my_work->needed) { EREPORT(("dst_s_random(): More than needed %d >= %d\n", s, my_work->needed)); memcpy(&output[n], my_work->output, my_work->needed); n += my_work->needed; /* saving unused data for next time */ unused = s - my_work->needed; memcpy(old_unused, &my_work->output[my_work->needed], unused); } else { /* XXXX This should not happen */ EREPORT(("Not enough %d >= %d\n", s, my_work->needed)); memcpy(&output[n], my_work->output, s); n += my_work->needed; } /* delete the allocated work area */ for (i = 0; i < DST_NUM_HASHES; i++) { dst_free_key(my_work->hash[i]->key); SAFE_FREE(my_work->hash[i]); } SAFE_FREE(my_work->output); SAFE_FREE(my_work); } return (n); } /* * A random number generator that is fast and strong * this random number generator is based on HASHing data, * the input to the digest function is a collection of * counters that is incremented between digest operations * each increment operation amortizes to 2 bits changed in that value * for 5 counters thus the input will amortize to have 10 bits changed * The counters are initaly set using the strong random function above * the HMAC key is selected by the same methold as the HMAC keys for the * strong random function. * Each set of counters is used for 2^25 operations * * returns the number of bytes written to the output buffer * or negative number in case of error */ int dst_s_semi_random(u_char *output, unsigned size) { static u_int32_t counter[DST_NUMBER_OF_COUNTERS]; static u_char semi_old[DST_HASH_SIZE]; static int semi_loc = 0, cnt = 0; static unsigned hb_size = 0; static DST_KEY *my_key = NULL; prand_hash *hash; unsigned out = 0; unsigned i; int n; if (output == NULL || size <= 0) return (-2); /* check if we need a new key */ if (my_key == NULL || cnt > (1 << 25)) { /* get HMAC KEY */ if (my_key) my_key->dk_func->destroy(my_key); if ((hash = get_hmac_key(1, DST_RANDOM_BLOCK_SIZE)) == NULL) return (0); my_key = hash->key; /* check if the key works stir the new key using some old random data */ hb_size = dst_sign_data(SIG_MODE_ALL, my_key, NULL, (u_char *) counter, sizeof(counter), semi_old, sizeof(semi_old)); if (hb_size <= 0) { EREPORT(("dst_s_semi_random() Sign of alg %d failed %d\n", my_key->dk_alg, hb_size)); return (-1); } /* new set the counters to random values */ dst_s_random((u_char *) counter, sizeof(counter)); cnt = 0; } /* if old data around use it first */ if (semi_loc < hb_size) { if (size <= hb_size - semi_loc) { /* need less */ memcpy(output, &semi_old[semi_loc], size); semi_loc += size; return (size); /* DONE */ } else { out = hb_size - semi_loc; memcpy(output, &semi_old[semi_loc], out); semi_loc += out; } } /* generate more randome stuff */ while (out < size) { /* * modify at least one bit by incrementing at least one counter * based on the last bit of the last counter updated update * the next one. * minimaly this operation will modify at least 1 bit, * amortized 2 bits */ for (n = 0; n < DST_NUMBER_OF_COUNTERS; n++) i = (int) counter[n]++; i = dst_sign_data(SIG_MODE_ALL, my_key, NULL, (u_char *) counter, hb_size, semi_old, sizeof(semi_old)); if (i != hb_size) EREPORT(("HMAC SIGNATURE FAILURE %d\n", i)); cnt++; if (size - out < i) /* Not all data is needed */ semi_loc = i = size - out; memcpy(&output[out], semi_old, i); out += i; } return (out); } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/arpa/nameser.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/arpa/nameser.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/arpa/nameser.h (revision 131136) @@ -1,461 +1,467 @@ /* * Copyright (c) 1983, 1989, 1993 * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. */ /* - * Copyright (c) 1996-1999 by Internet Software Consortium. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ */ /* - * $Id: nameser.h,v 1.4 2000/02/02 07:23:18 mellon Exp $ + * $Id: nameser.h,v 1.4.2.1 2004/06/10 17:59:31 dhankins Exp $ */ #ifndef _ARPA_NAMESER_H_ #define _ARPA_NAMESER_H_ /* * Revision information. This is the release date in YYYYMMDD format. * It can change every day so the right thing to do with it is use it * in preprocessor commands such as "#if (__NAMESER > 19931104)". Do not * compare for equality; rather, use it to determine whether your libbind.a * contains a new enough lib/nameser/ to support the feature you need. */ #define __NAMESER 19991006 /* New interface version stamp. */ /* * Define constants based on RFC 883, RFC 1034, RFC 1035 */ #define NS_PACKETSZ 512 /* maximum packet size */ #define NS_MAXDNAME 1025 /* maximum domain name */ #define NS_MAXCDNAME 255 /* maximum compressed domain name */ #define NS_MAXLABEL 63 /* maximum length of domain label */ #define NS_HFIXEDSZ 12 /* #/bytes of fixed data in header */ #define NS_QFIXEDSZ 4 /* #/bytes of fixed data in query */ #define NS_RRFIXEDSZ 10 /* #/bytes of fixed data in r record */ #define NS_INT32SZ 4 /* #/bytes of data in a u_int32_t */ #define NS_INT16SZ 2 /* #/bytes of data in a u_int16_t */ #define NS_INT8SZ 1 /* #/bytes of data in a u_int8_t */ #define NS_INADDRSZ 4 /* IPv4 T_A */ #define NS_IN6ADDRSZ 16 /* IPv6 T_AAAA */ #define NS_CMPRSFLGS 0xc0 /* Flag bits indicating name compression. */ #define NS_DEFAULTPORT 53 /* For both TCP and UDP. */ /* * These can be expanded with synonyms, just keep ns_parse.c:ns_parserecord() * in synch with it. */ typedef enum __ns_sect { ns_s_qd = 0, /* Query: Question. */ ns_s_zn = 0, /* Update: Zone. */ ns_s_an = 1, /* Query: Answer. */ ns_s_pr = 1, /* Update: Prerequisites. */ ns_s_ns = 2, /* Query: Name servers. */ ns_s_ud = 2, /* Update: Update. */ ns_s_ar = 3, /* Query|Update: Additional records. */ ns_s_max = 4 } ns_sect; /* * This is a message handle. It is caller allocated and has no dynamic data. * This structure is intended to be opaque to all but ns_parse.c, thus the * leading _'s on the member names. Use the accessor functions, not the _'s. */ typedef struct __ns_msg { const u_int8_t *_msg, *_eom; u_int16_t _id, _flags, _counts[ns_s_max]; const u_int8_t *_sections[ns_s_max]; ns_sect _sect; int _rrnum; const u_int8_t *_ptr; } ns_msg; /* Private data structure - do not use from outside library. */ struct _ns_flagdata { int mask, shift; }; extern struct _ns_flagdata _ns_flagdata[]; /* Accessor macros - this is part of the public interface. */ #define ns_msg_getflag(handle, flag) ( \ ((handle)._flags & _ns_flagdata[flag].mask) \ >> _ns_flagdata[flag].shift \ ) #define ns_msg_id(handle) ((handle)._id + 0) #define ns_msg_base(handle) ((handle)._msg + 0) #define ns_msg_end(handle) ((handle)._eom + 0) #define ns_msg_size(handle) ((handle)._eom - (handle)._msg) #define ns_msg_count(handle, section) ((handle)._counts[section] + 0) /* * This is a parsed record. It is caller allocated and has no dynamic data. */ typedef struct __ns_rr { char name[NS_MAXDNAME]; u_int16_t type; u_int16_t rr_class; u_int32_t ttl; u_int16_t rdlength; const u_int8_t *rdata; } ns_rr; /* Accessor macros - this is part of the public interface. */ #define ns_rr_name(rr) (((rr).name[0] != '\0') ? (rr).name : ".") #define ns_rr_type(rr) ((ns_type)((rr).type + 0)) #define ns_rr_class(rr) ((ns_class)((rr).rr_class + 0)) #define ns_rr_ttl(rr) ((rr).ttl + 0) #define ns_rr_rdlen(rr) ((rr).rdlength + 0) #define ns_rr_rdata(rr) ((rr).rdata + 0) /* * These don't have to be in the same order as in the packet flags word, * and they can even overlap in some cases, but they will need to be kept * in synch with ns_parse.c:ns_flagdata[]. */ typedef enum __ns_flag { ns_f_qr, /* Question/Response. */ ns_f_opcode, /* Operation code. */ ns_f_aa, /* Authoritative Answer. */ ns_f_tc, /* Truncation occurred. */ ns_f_rd, /* Recursion Desired. */ ns_f_ra, /* Recursion Available. */ ns_f_z, /* MBZ. */ ns_f_ad, /* Authentic Data (DNSSEC). */ ns_f_cd, /* Checking Disabled (DNSSEC). */ ns_f_rcode, /* Response code. */ ns_f_max } ns_flag; /* * Currently defined opcodes. */ typedef enum __ns_opcode { ns_o_query = 0, /* Standard query. */ ns_o_iquery = 1, /* Inverse query (deprecated/unsupported). */ ns_o_status = 2, /* Name server status query (unsupported). */ /* Opcode 3 is undefined/reserved. */ ns_o_notify = 4, /* Zone change notification. */ ns_o_update = 5, /* Zone update message. */ ns_o_max = 6 } ns_opcode; /* * Currently defined response codes. */ typedef enum __ns_rcode { ns_r_noerror = 0, /* No error occurred. */ ns_r_formerr = 1, /* Format error. */ ns_r_servfail = 2, /* Server failure. */ ns_r_nxdomain = 3, /* Name error. */ ns_r_notimpl = 4, /* Unimplemented. */ ns_r_refused = 5, /* Operation refused. */ /* these are for BIND_UPDATE */ ns_r_yxdomain = 6, /* Name exists */ ns_r_yxrrset = 7, /* RRset exists */ ns_r_nxrrset = 8, /* RRset does not exist */ ns_r_notauth = 9, /* Not authoritative for zone */ ns_r_notzone = 10, /* Zone of record different from zone section */ ns_r_max = 11, /* The following are TSIG extended errors */ ns_r_badsig = 16, ns_r_badkey = 17, ns_r_badtime = 18 } ns_rcode; /* BIND_UPDATE */ typedef enum __ns_update_operation { ns_uop_delete = 0, ns_uop_add = 1, ns_uop_max = 2 } ns_update_operation; /* * This structure is used for TSIG authenticated messages */ struct ns_tsig_key { char name[NS_MAXDNAME], alg[NS_MAXDNAME]; unsigned char *data; unsigned len; }; typedef struct ns_tsig_key ns_tsig_key; /* * This structure is used for TSIG authenticated TCP messages */ struct ns_tcp_tsig_state { int counter; struct dst_key *key; void *ctx; unsigned char sig[NS_PACKETSZ]; unsigned siglen; }; typedef struct ns_tcp_tsig_state ns_tcp_tsig_state; #define NS_TSIG_FUDGE 300 #define NS_TSIG_TCP_COUNT 100 #define NS_TSIG_ALG_HMAC_MD5 "HMAC-MD5.SIG-ALG.REG.INT" #define NS_TSIG_ERROR_NO_TSIG -10 #define NS_TSIG_ERROR_NO_SPACE -11 #define NS_TSIG_ERROR_FORMERR -12 /* * Currently defined type values for resources and queries. */ typedef enum __ns_type { ns_t_invalid = 0, /* Cookie. */ ns_t_a = 1, /* Host address. */ ns_t_ns = 2, /* Authoritative server. */ ns_t_md = 3, /* Mail destination. */ ns_t_mf = 4, /* Mail forwarder. */ ns_t_cname = 5, /* Canonical name. */ ns_t_soa = 6, /* Start of authority zone. */ ns_t_mb = 7, /* Mailbox domain name. */ ns_t_mg = 8, /* Mail group member. */ ns_t_mr = 9, /* Mail rename name. */ ns_t_null = 10, /* Null resource record. */ ns_t_wks = 11, /* Well known service. */ ns_t_ptr = 12, /* Domain name pointer. */ ns_t_hinfo = 13, /* Host information. */ ns_t_minfo = 14, /* Mailbox information. */ ns_t_mx = 15, /* Mail routing information. */ ns_t_txt = 16, /* Text strings. */ ns_t_rp = 17, /* Responsible person. */ ns_t_afsdb = 18, /* AFS cell database. */ ns_t_x25 = 19, /* X_25 calling address. */ ns_t_isdn = 20, /* ISDN calling address. */ ns_t_rt = 21, /* Router. */ ns_t_nsap = 22, /* NSAP address. */ ns_t_nsap_ptr = 23, /* Reverse NSAP lookup (deprecated). */ ns_t_sig = 24, /* Security signature. */ ns_t_key = 25, /* Security key. */ ns_t_px = 26, /* X.400 mail mapping. */ ns_t_gpos = 27, /* Geographical position (withdrawn). */ ns_t_aaaa = 28, /* Ip6 Address. */ ns_t_loc = 29, /* Location Information. */ ns_t_nxt = 30, /* Next domain (security). */ ns_t_eid = 31, /* Endpoint identifier. */ ns_t_nimloc = 32, /* Nimrod Locator. */ ns_t_srv = 33, /* Server Selection. */ ns_t_atma = 34, /* ATM Address */ ns_t_naptr = 35, /* Naming Authority PoinTeR */ ns_t_kx = 36, /* Key Exchange */ ns_t_cert = 37, /* Certification record */ ns_t_a6 = 38, /* IPv6 address (deprecates AAAA) */ ns_t_dname = 39, /* Non-terminal DNAME (for IPv6) */ ns_t_sink = 40, /* Kitchen sink (experimentatl) */ ns_t_opt = 41, /* EDNS0 option (meta-RR) */ ns_t_tsig = 250, /* Transaction signature. */ ns_t_ixfr = 251, /* Incremental zone transfer. */ ns_t_axfr = 252, /* Transfer zone of authority. */ ns_t_mailb = 253, /* Transfer mailbox records. */ ns_t_maila = 254, /* Transfer mail agent records. */ ns_t_any = 255, /* Wildcard match. */ ns_t_zxfr = 256, /* BIND-specific, nonstandard. */ ns_t_max = 65536 } ns_type; /* Exclusively a QTYPE? (not also an RTYPE) */ #define ns_t_qt_p(t) (ns_t_xfr_p(t) || (t) == ns_t_any || \ (t) == ns_t_mailb || (t) == ns_t_maila) /* Some kind of meta-RR? (not a QTYPE, but also not an RTYPE) */ #define ns_t_mrr_p(t) ((t) == ns_t_tsig || (t) == ns_t_opt) /* Exclusively an RTYPE? (not also a QTYPE or a meta-RR) */ #define ns_t_rr_p(t) (!ns_t_qt_p(t) && !ns_t_mrr_p(t)) #define ns_t_udp_p(t) ((t) != ns_t_axfr && (t) != ns_t_zxfr) #define ns_t_xfr_p(t) ((t) == ns_t_axfr || (t) == ns_t_ixfr || \ (t) == ns_t_zxfr) /* * Values for class field */ typedef enum __ns_class { ns_c_invalid = 0, /* Cookie. */ ns_c_in = 1, /* Internet. */ ns_c_2 = 2, /* unallocated/unsupported. */ ns_c_chaos = 3, /* MIT Chaos-net. */ ns_c_hs = 4, /* MIT Hesiod. */ /* Query class values which do not appear in resource records */ ns_c_none = 254, /* for prereq. sections in update requests */ ns_c_any = 255, /* Wildcard match. */ ns_c_max = 65536 } ns_class; /* DNSSEC constants. */ typedef enum __ns_key_types { ns_kt_rsa = 1, /* key type RSA/MD5 */ ns_kt_dh = 2, /* Diffie Hellman */ ns_kt_dsa = 3, /* Digital Signature Standard (MANDATORY) */ ns_kt_private = 254 /* Private key type starts with OID */ } ns_key_types; typedef enum __ns_cert_types { cert_t_pkix = 1, /* PKIX (X.509v3) */ cert_t_spki = 2, /* SPKI */ cert_t_pgp = 3, /* PGP */ cert_t_url = 253, /* URL private type */ cert_t_oid = 254 /* OID private type */ } ns_cert_types; /* Flags field of the KEY RR rdata. */ #define NS_KEY_TYPEMASK 0xC000 /* Mask for "type" bits */ #define NS_KEY_TYPE_AUTH_CONF 0x0000 /* Key usable for both */ #define NS_KEY_TYPE_CONF_ONLY 0x8000 /* Key usable for confidentiality */ #define NS_KEY_TYPE_AUTH_ONLY 0x4000 /* Key usable for authentication */ #define NS_KEY_TYPE_NO_KEY 0xC000 /* No key usable for either; no key */ /* The type bits can also be interpreted independently, as single bits: */ #define NS_KEY_NO_AUTH 0x8000 /* Key unusable for authentication */ #define NS_KEY_NO_CONF 0x4000 /* Key unusable for confidentiality */ #define NS_KEY_RESERVED2 0x2000 /* Security is *mandatory* if bit=0 */ #define NS_KEY_EXTENDED_FLAGS 0x1000 /* reserved - must be zero */ #define NS_KEY_RESERVED4 0x0800 /* reserved - must be zero */ #define NS_KEY_RESERVED5 0x0400 /* reserved - must be zero */ #define NS_KEY_NAME_TYPE 0x0300 /* these bits determine the type */ #define NS_KEY_NAME_USER 0x0000 /* key is assoc. with user */ #define NS_KEY_NAME_ENTITY 0x0200 /* key is assoc. with entity eg host */ #define NS_KEY_NAME_ZONE 0x0100 /* key is zone key */ #define NS_KEY_NAME_RESERVED 0x0300 /* reserved meaning */ #define NS_KEY_RESERVED8 0x0080 /* reserved - must be zero */ #define NS_KEY_RESERVED9 0x0040 /* reserved - must be zero */ #define NS_KEY_RESERVED10 0x0020 /* reserved - must be zero */ #define NS_KEY_RESERVED11 0x0010 /* reserved - must be zero */ #define NS_KEY_SIGNATORYMASK 0x000F /* key can sign RR's of same name */ #define NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED2 | \ NS_KEY_RESERVED4 | \ NS_KEY_RESERVED5 | \ NS_KEY_RESERVED8 | \ NS_KEY_RESERVED9 | \ NS_KEY_RESERVED10 | \ NS_KEY_RESERVED11 ) #define NS_KEY_RESERVED_BITMASK2 0xFFFF /* no bits defined here */ /* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */ #define NS_ALG_MD5RSA 1 /* MD5 with RSA */ #define NS_ALG_DH 2 /* Diffie Hellman KEY */ #define NS_ALG_DSA 3 /* DSA KEY */ #define NS_ALG_DSS NS_ALG_DSA #define NS_ALG_EXPIRE_ONLY 253 /* No alg, no security */ #define NS_ALG_PRIVATE_OID 254 /* Key begins with OID giving alg */ /* Protocol values */ /* value 0 is reserved */ #define NS_KEY_PROT_TLS 1 #define NS_KEY_PROT_EMAIL 2 #define NS_KEY_PROT_DNSSEC 3 #define NS_KEY_PROT_IPSEC 4 #define NS_KEY_PROT_ANY 255 /* Signatures */ #define NS_MD5RSA_MIN_BITS 512 /* Size of a mod or exp in bits */ #define NS_MD5RSA_MAX_BITS 2552 /* Total of binary mod and exp */ #define NS_MD5RSA_MAX_BYTES ((NS_MD5RSA_MAX_BITS+7/8)*2+3) /* Max length of text sig block */ #define NS_MD5RSA_MAX_BASE64 (((NS_MD5RSA_MAX_BYTES+2)/3)*4) #define NS_MD5RSA_MIN_SIZE ((NS_MD5RSA_MIN_BITS+7)/8) #define NS_MD5RSA_MAX_SIZE ((NS_MD5RSA_MAX_BITS+7)/8) #define NS_DSA_SIG_SIZE 41 #define NS_DSA_MIN_SIZE 213 #define NS_DSA_MAX_BYTES 405 /* Offsets into SIG record rdata to find various values */ #define NS_SIG_TYPE 0 /* Type flags */ #define NS_SIG_ALG 2 /* Algorithm */ #define NS_SIG_LABELS 3 /* How many labels in name */ #define NS_SIG_OTTL 4 /* Original TTL */ #define NS_SIG_EXPIR 8 /* Expiration time */ #define NS_SIG_SIGNED 12 /* Signature time */ #define NS_SIG_FOOT 16 /* Key footprint */ #define NS_SIG_SIGNER 18 /* Domain name of who signed it */ /* How RR types are represented as bit-flags in NXT records */ #define NS_NXT_BITS 8 #define NS_NXT_BIT_SET( n,p) (p[(n)/NS_NXT_BITS] |= (0x80>>((n)%NS_NXT_BITS))) #define NS_NXT_BIT_CLEAR(n,p) (p[(n)/NS_NXT_BITS] &= ~(0x80>>((n)%NS_NXT_BITS))) #define NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] & (0x80>>((n)%NS_NXT_BITS))) #define NS_NXT_MAX 127 /* * Inline versions of get/put short/long. Pointer is advanced. */ #define NS_GET16(s, cp) do { \ register u_int8_t *t_cp = (u_int8_t *)(cp); \ (s) = ((u_int16_t)t_cp[0] << 8) \ | ((u_int16_t)t_cp[1]) \ ; \ (cp) += NS_INT16SZ; \ } while (0) #define NS_GET32(l, cp) do { \ register u_int8_t *t_cp = (u_int8_t *)(cp); \ (l) = ((u_int32_t)t_cp[0] << 24) \ | ((u_int32_t)t_cp[1] << 16) \ | ((u_int32_t)t_cp[2] << 8) \ | ((u_int32_t)t_cp[3]) \ ; \ (cp) += NS_INT32SZ; \ } while (0) #define NS_PUT16(s, cp) do { \ register u_int16_t t_s = (u_int16_t)(s); \ register u_int8_t *t_cp = (u_int8_t *)(cp); \ *t_cp++ = t_s >> 8; \ *t_cp = t_s; \ (cp) += NS_INT16SZ; \ } while (0) #define NS_PUT32(l, cp) do { \ register u_int32_t t_l = (u_int32_t)(l); \ register u_int8_t *t_cp = (u_int8_t *)(cp); \ *t_cp++ = t_l >> 24; \ *t_cp++ = t_l >> 16; \ *t_cp++ = t_l >> 8; \ *t_cp = t_l; \ (cp) += NS_INT32SZ; \ } while (0) #include #endif /* !_ARPA_NAMESER_H_ */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/cdefs.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/cdefs.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/cdefs.h (revision 131136) @@ -1,66 +1,57 @@ /* cdefs.h Standard C definitions... */ /* * Copyright (c) 1995 RadioMail Corporation. All rights reserved. - * Copyright (c) 1996-1999 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * * This software was written for RadioMail Corporation by Ted Lemon * under a contract with Vixie Enterprises. Further modifications have - * been made for the Internet Software Consortium under a contract + * been made for Internet Systems Consortium under a contract * with Vixie Laboratories. */ #if !defined (__ISC_DHCP_CDEFS_H__) #define __ISC_DHCP_CDEFS_H__ /* Delete attributes if not gcc or not the right version of gcc. */ #if !defined(__GNUC__) || __GNUC__ < 2 || \ (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || defined (darwin) #define __attribute__(x) #endif #if (defined (__GNUC__) || defined (__STDC__)) && !defined (BROKEN_ANSI) #define PROTO(x) x #define KandR(x) #define ANSI_DECL(x) x #if defined (__GNUC__) #define INLINE inline #else #define INLINE #endif /* __GNUC__ */ #else #define PROTO(x) () #define KandR(x) x #define ANSI_DECL(x) #define INLINE #endif /* __GNUC__ || __STDC__ */ #endif /* __ISC_DHCP_CDEFS_H__ */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/cf/freebsd.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/cf/freebsd.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/cf/freebsd.h (revision 131136) @@ -1,146 +1,137 @@ /* freebsd.h System dependencies for FreeBSD... */ /* - * Copyright (c) 1996-1999 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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''. */ #include #include #include #include #include #include #include #include #include #include extern int h_errno; #include #include #include #if !defined (INADDR_LOOPBACK) # define INADDR_LOOPBACK ((u_int32_t)0x7f000001) #endif /* Varargs stuff... */ #include #define VA_DOTDOTDOT ... #define va_dcl #define VA_start(list, last) va_start (list, last) #ifndef _PATH_DHCPD_PID #define _PATH_DHCPD_PID "/var/run/dhcpd.pid" #endif #ifndef _PATH_DHCPD_DB #define _PATH_DHCPD_DB "/var/db/dhcpd.leases" #endif #ifndef _PATH_DHCLIENT_PID #define _PATH_DHCLIENT_PID "/var/run/dhclient.pid" #endif #ifndef _PATH_DHCLIENT_DB #define _PATH_DHCLIENT_DB "/var/db/dhclient.leases" #endif #define EOL '\n' #define VOIDPTR void * /* Time stuff... */ #include #define TIME time_t #define GET_TIME(x) time ((x)) #define HAVE_SA_LEN /* socklen_t was first defined on November 24 in sys/socket.h, and __FreeBSD_version was changed to 400013 on December 4, so if you get a compile error on this, and you updated between those dates, that's why. Also, it may be that some 3.x version after 3.4 will have socklen_t, but no such change has been made so far. */ #if __FreeBSD_version < 400013 #define SOCKLEN_T int #endif #if defined (USE_DEFAULT_NETWORK) # define USE_BPF #endif #define HAVE_MKSTEMP #ifdef NEED_PRAND_CONF #ifndef HAVE_DEV_RANDOM # define HAVE_DEV_RANDOM 1 #endif /* HAVE_DEV_RANDOM */ const char *cmds[] = { "/bin/ps -axlw 2>&1", "/usr/sbin/arp -an 2>&1", "/usr/bin/netstat -an 2>&1", "/bin/df 2>&1", "/usr/bin/dig com. soa +ti=1 +retry=0 2>&1", "/usr/bin/netstat -an 2>&1", "/usr/bin/dig . soa +ti=1 +retry=0 2>&1", "/usr/sbin/iostat 2>&1", "/usr/bin/vmstat 2>&1", "/usr/bin/w 2>&1", NULL }; const char *dirs[] = { "/tmp", "/usr/tmp", ".", "/", "/var/spool", "/dev", "/var/mail", "/home", "/usr/home", NULL }; const char *files[] = { "/var/log/messages", "/var/log/wtmp", "/var/log/lastlog", NULL }; #endif /* NEED_PRAND_CONF */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/ctrace.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/ctrace.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/ctrace.h (revision 131136) @@ -1,86 +1,77 @@ /* trace.h Definitions for dhcp tracing facility... */ /* - * Copyright (c) 2001 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2001-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems 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 + * about Internet Systems Consortium, see http://www.isc.org/. To * learn more about Nominum, Inc., see ``http://www.nominum.com''. */ typedef struct { struct in_addr primary_address; u_int32_t index; struct hardware hw_address; char name [IFNAMSIZ]; } trace_interface_packet_t; typedef struct { u_int32_t index; struct iaddr from; u_int16_t from_port; struct hardware hfrom; u_int8_t havehfrom; } trace_inpacket_t; typedef struct { u_int32_t index; struct iaddr from; struct iaddr to; u_int16_t to_port; struct hardware hto; u_int8_t havehto; } trace_outpacket_t; void trace_interface_register (trace_type_t *, struct interface_info *); void trace_interface_input (trace_type_t *, unsigned, char *); void trace_interface_stop (trace_type_t *); void trace_inpacket_stash (struct interface_info *, struct dhcp_packet *, unsigned, unsigned int, struct iaddr, struct hardware *); void trace_inpacket_input (trace_type_t *, unsigned, char *); void trace_inpacket_stop (trace_type_t *); void trace_outpacket_input (trace_type_t *, unsigned, char *); void trace_outpacket_stop (trace_type_t *); ssize_t trace_packet_send (struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *); void trace_icmp_input_input (trace_type_t *, unsigned, char *); void trace_icmp_input_stop (trace_type_t *); void trace_icmp_output_input (trace_type_t *, unsigned, char *); void trace_icmp_output_stop (trace_type_t *); void trace_seed_stash (trace_type_t *, unsigned); void trace_seed_input (trace_type_t *, unsigned, char *); void trace_seed_stop (trace_type_t *); Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/dhcp.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/dhcp.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/dhcp.h (revision 131136) @@ -1,195 +1,186 @@ /* dhcp.h Protocol structures... */ /* - * Copyright (c) 1995-2001 The Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises. To learn more - * about the Internet Software Consortium, see ``http://www.isc.org''. + * about Internet Systems Consortium, see ``http://www.isc.org''. * To learn more about Vixie Enterprises, see ``http://www.vix.com''. */ #define DHCP_UDP_OVERHEAD (14 + /* Ethernet header */ \ 20 + /* IP header */ \ 8) /* UDP header */ #define DHCP_SNAME_LEN 64 #define DHCP_FILE_LEN 128 #define DHCP_FIXED_NON_UDP 236 #define DHCP_FIXED_LEN (DHCP_FIXED_NON_UDP + DHCP_UDP_OVERHEAD) /* Everything but options. */ #define DHCP_MTU_MAX 1500 #define DHCP_OPTION_LEN (DHCP_MTU_MAX - DHCP_FIXED_LEN) #define BOOTP_MIN_LEN 300 #define DHCP_MIN_LEN 548 struct dhcp_packet { u_int8_t op; /* 0: Message opcode/type */ u_int8_t htype; /* 1: Hardware addr type (net/if_types.h) */ u_int8_t hlen; /* 2: Hardware addr length */ u_int8_t hops; /* 3: Number of relay agent hops from client */ u_int32_t xid; /* 4: Transaction ID */ u_int16_t secs; /* 8: Seconds since client started looking */ u_int16_t flags; /* 10: Flag bits */ struct in_addr ciaddr; /* 12: Client IP address (if already in use) */ struct in_addr yiaddr; /* 16: Client IP address */ struct in_addr siaddr; /* 18: IP address of next server to talk to */ struct in_addr giaddr; /* 20: DHCP relay agent IP address */ unsigned char chaddr [16]; /* 24: Client hardware address */ char sname [DHCP_SNAME_LEN]; /* 40: Server name */ char file [DHCP_FILE_LEN]; /* 104: Boot filename */ unsigned char options [DHCP_OPTION_LEN]; /* 212: Optional parameters (actual length dependent on MTU). */ }; /* BOOTP (rfc951) message types */ #define BOOTREQUEST 1 #define BOOTREPLY 2 /* Possible values for flags field... */ #define BOOTP_BROADCAST 32768L /* Possible values for hardware type (htype) field... */ #define HTYPE_ETHER 1 /* Ethernet 10Mbps */ #define HTYPE_IEEE802 6 /* IEEE 802.2 Token Ring... */ #define HTYPE_FDDI 8 /* FDDI... */ /* Magic cookie validating dhcp options field (and bootp vendor extensions field). */ #define DHCP_OPTIONS_COOKIE "\143\202\123\143" /* DHCP Option codes: */ #define DHO_PAD 0 #define DHO_SUBNET_MASK 1 #define DHO_TIME_OFFSET 2 #define DHO_ROUTERS 3 #define DHO_TIME_SERVERS 4 #define DHO_NAME_SERVERS 5 #define DHO_DOMAIN_NAME_SERVERS 6 #define DHO_LOG_SERVERS 7 #define DHO_COOKIE_SERVERS 8 #define DHO_LPR_SERVERS 9 #define DHO_IMPRESS_SERVERS 10 #define DHO_RESOURCE_LOCATION_SERVERS 11 #define DHO_HOST_NAME 12 #define DHO_BOOT_SIZE 13 #define DHO_MERIT_DUMP 14 #define DHO_DOMAIN_NAME 15 #define DHO_SWAP_SERVER 16 #define DHO_ROOT_PATH 17 #define DHO_EXTENSIONS_PATH 18 #define DHO_IP_FORWARDING 19 #define DHO_NON_LOCAL_SOURCE_ROUTING 20 #define DHO_POLICY_FILTER 21 #define DHO_MAX_DGRAM_REASSEMBLY 22 #define DHO_DEFAULT_IP_TTL 23 #define DHO_PATH_MTU_AGING_TIMEOUT 24 #define DHO_PATH_MTU_PLATEAU_TABLE 25 #define DHO_INTERFACE_MTU 26 #define DHO_ALL_SUBNETS_LOCAL 27 #define DHO_BROADCAST_ADDRESS 28 #define DHO_PERFORM_MASK_DISCOVERY 29 #define DHO_MASK_SUPPLIER 30 #define DHO_ROUTER_DISCOVERY 31 #define DHO_ROUTER_SOLICITATION_ADDRESS 32 #define DHO_STATIC_ROUTES 33 #define DHO_TRAILER_ENCAPSULATION 34 #define DHO_ARP_CACHE_TIMEOUT 35 #define DHO_IEEE802_3_ENCAPSULATION 36 #define DHO_DEFAULT_TCP_TTL 37 #define DHO_TCP_KEEPALIVE_INTERVAL 38 #define DHO_TCP_KEEPALIVE_GARBAGE 39 #define DHO_NIS_DOMAIN 40 #define DHO_NIS_SERVERS 41 #define DHO_NTP_SERVERS 42 #define DHO_VENDOR_ENCAPSULATED_OPTIONS 43 #define DHO_NETBIOS_NAME_SERVERS 44 #define DHO_NETBIOS_DD_SERVER 45 #define DHO_NETBIOS_NODE_TYPE 46 #define DHO_NETBIOS_SCOPE 47 #define DHO_FONT_SERVERS 48 #define DHO_X_DISPLAY_MANAGER 49 #define DHO_DHCP_REQUESTED_ADDRESS 50 #define DHO_DHCP_LEASE_TIME 51 #define DHO_DHCP_OPTION_OVERLOAD 52 #define DHO_DHCP_MESSAGE_TYPE 53 #define DHO_DHCP_SERVER_IDENTIFIER 54 #define DHO_DHCP_PARAMETER_REQUEST_LIST 55 #define DHO_DHCP_MESSAGE 56 #define DHO_DHCP_MAX_MESSAGE_SIZE 57 #define DHO_DHCP_RENEWAL_TIME 58 #define DHO_DHCP_REBINDING_TIME 59 #define DHO_VENDOR_CLASS_IDENTIFIER 60 #define DHO_DHCP_CLIENT_IDENTIFIER 61 #define DHO_NWIP_DOMAIN_NAME 62 #define DHO_NWIP_SUBOPTIONS 63 #define DHO_USER_CLASS 77 #define DHO_FQDN 81 #define DHO_DHCP_AGENT_OPTIONS 82 #define DHO_SUBNET_SELECTION 118 /* RFC3011! */ /* The DHO_AUTHENTICATE option is not a standard yet, so I've allocated an option out of the "local" option space for it on a temporary basis. Once an option code number is assigned, I will immediately and shamelessly break this, so don't count on it continuing to work. */ #define DHO_AUTHENTICATE 210 #define DHO_END 255 /* DHCP message types. */ #define DHCPDISCOVER 1 #define DHCPOFFER 2 #define DHCPREQUEST 3 #define DHCPDECLINE 4 #define DHCPACK 5 #define DHCPNAK 6 #define DHCPRELEASE 7 #define DHCPINFORM 8 /* Relay Agent Information option subtypes: */ #define RAI_CIRCUIT_ID 1 #define RAI_REMOTE_ID 2 #define RAI_AGENT_ID 3 /* FQDN suboptions: */ #define FQDN_NO_CLIENT_UPDATE 1 #define FQDN_SERVER_UPDATE 2 #define FQDN_ENCODED 3 #define FQDN_RCODE1 4 #define FQDN_RCODE2 5 #define FQDN_HOSTNAME 6 #define FQDN_DOMAINNAME 7 #define FQDN_FQDN 8 #define FQDN_SUBOPTION_COUNT 8 Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/dhcpd.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/dhcpd.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/dhcpd.h (revision 131136) @@ -1,2633 +1,2624 @@ /* dhcpd.h Definitions for dhcpd... */ /* - * Copyright (c) 1996-2001 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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 __CYGWIN32__ #include #include #include #include #include #include #else #define fd_set cygwin_fd_set #include #endif #include #include #include #include #include #include #include #include #include "cdefs.h" #include "osdep.h" #include "arpa/nameser.h" #if defined (NSUPDATE) # include "minires/minires.h" #endif struct hash_table; typedef struct hash_table group_hash_t; typedef struct hash_table universe_hash_t; typedef struct hash_table option_hash_t; typedef struct hash_table dns_zone_hash_t; typedef struct hash_table lease_hash_t; typedef struct hash_table host_hash_t; typedef struct hash_table class_hash_t; #include "dhcp.h" #include "statement.h" #include "tree.h" #include "inet.h" #include "dhctoken.h" #include #include #if !defined (OPTION_HASH_SIZE) # define OPTION_HASH_SIZE 17 # define OPTION_HASH_PTWO 32 /* Next power of two above option hash. */ # define OPTION_HASH_EXP 5 /* The exponent for that power of two. */ #endif #define compute_option_hash(x) \ (((x) & (OPTION_HASH_PTWO - 1)) + \ (((x) >> OPTION_HASH_EXP) & \ (OPTION_HASH_PTWO - 1))) % OPTION_HASH_SIZE; enum dhcp_shutdown_state { shutdown_listeners, shutdown_omapi_connections, shutdown_drop_omapi_connections, shutdown_dhcp, shutdown_done }; /* Client FQDN option, failover FQDN option, etc. */ typedef struct { u_int8_t codes [2]; unsigned length; u_int8_t *data; } ddns_fqdn_t; #include "failover.h" /* A parsing context. */ struct parse { int lexline; int lexchar; char *token_line; char *prev_line; char *cur_line; const char *tlname; int eol_token; char line1 [81]; char line2 [81]; int lpos; int line; int tlpos; int tline; enum dhcp_token token; int ugflag; char *tval; int tlen; char tokbuf [1500]; #ifdef OLD_LEXER char comments [4096]; int comment_index; #endif int warnings_occurred; int file; char *inbuf; unsigned bufix, buflen; unsigned bufsiz; }; /* Variable-length array of data. */ struct string_list { struct string_list *next; char string [1]; }; /* A name server, from /etc/resolv.conf. */ struct name_server { struct name_server *next; struct sockaddr_in addr; TIME rcdate; }; /* A domain search list element. */ struct domain_search_list { struct domain_search_list *next; char *domain; TIME rcdate; }; /* Option tag structures are used to build chains of option tags, for when we're sure we're not going to have enough of them to justify maintaining an array. */ struct option_tag { struct option_tag *next; u_int8_t data [1]; }; /* An agent option structure. We need a special structure for the Relay Agent Information option because if more than one appears in a message, we have to keep them seperate. */ struct agent_options { struct agent_options *next; int length; struct option_tag *first; }; struct option_cache { int refcnt; struct option_cache *next; struct expression *expression; struct option *option; struct data_string data; }; struct option_state { int refcnt; int universe_count; int site_universe; int site_code_min; VOIDPTR universes [1]; }; /* A dhcp packet and the pointers to its option values. */ struct packet { struct dhcp_packet *raw; int refcnt; unsigned packet_length; int packet_type; int options_valid; int client_port; struct iaddr client_addr; struct interface_info *interface; /* Interface on which packet was received. */ struct hardware *haddr; /* Physical link address of local sender (maybe gateway). */ /* Information for relay agent options (see draft-ietf-dhc-agent-options-xx.txt). */ u_int8_t *circuit_id; /* Circuit ID of client connection. */ int circuit_id_len; u_int8_t *remote_id; /* Remote ID of client. */ int remote_id_len; int got_requested_address; /* True if client sent the dhcp-requested-address option. */ struct shared_network *shared_network; struct option_state *options; #if !defined (PACKET_MAX_CLASSES) # define PACKET_MAX_CLASSES 5 #endif int class_count; struct class *classes [PACKET_MAX_CLASSES]; int known; int authenticated; }; /* A network interface's MAC address. */ struct hardware { u_int8_t hlen; u_int8_t hbuf [17]; }; typedef enum { server_startup = 0, server_running = 1, server_shutdown = 2, server_hibernate = 3, server_awaken = 4 } control_object_state_t; typedef struct { OMAPI_OBJECT_PREAMBLE; control_object_state_t state; } dhcp_control_object_t; /* Lease states: */ typedef enum { FTS_FREE = 1, FTS_ACTIVE = 2, FTS_EXPIRED = 3, FTS_RELEASED = 4, FTS_ABANDONED = 5, FTS_RESET = 6, FTS_BACKUP = 7 } binding_state_t; /* FTS_LAST is the highest value that is valid for a lease binding state. */ #define FTS_LAST FTS_BACKUP /* A dhcp lease declaration structure. */ struct lease { OMAPI_OBJECT_PREAMBLE; struct lease *next; struct lease *n_uid, *n_hw; struct iaddr ip_addr; TIME starts, ends, timestamp, sort_time; char *client_hostname; struct binding_scope *scope; struct host_decl *host; struct subnet *subnet; struct pool *pool; struct class *billing_class; struct option_chain_head *agent_options; struct executable_statement *on_expiry; struct executable_statement *on_commit; struct executable_statement *on_release; unsigned char *uid; unsigned short uid_len; unsigned short uid_max; unsigned char uid_buf [7]; struct hardware hardware_addr; u_int8_t flags; # define STATIC_LEASE 1 # define BOOTP_LEASE 2 # define PERSISTENT_FLAGS (ON_ACK_QUEUE | ON_UPDATE_QUEUE) # define MS_NULL_TERMINATION 8 # define ON_UPDATE_QUEUE 16 # define ON_ACK_QUEUE 32 # define UNICAST_BROADCAST_HACK 64 # define ON_DEFERRED_QUEUE 128 # define EPHEMERAL_FLAGS (MS_NULL_TERMINATION | \ UNICAST_BROADCAST_HACK) binding_state_t __attribute__ ((mode (__byte__))) binding_state; binding_state_t __attribute__ ((mode (__byte__))) next_binding_state; binding_state_t __attribute__ ((mode (__byte__))) desired_binding_state; struct lease_state *state; TIME tstp; /* Time sent to partner. */ TIME tsfp; /* Time sent from partner. */ TIME cltt; /* Client last transaction time. */ struct lease *next_pending; }; struct lease_state { struct lease_state *next; struct interface_info *ip; struct packet *packet; /* The incoming packet. */ TIME offered_expiry; struct option_state *options; struct data_string parameter_request_list; int max_message_size; u_int32_t expiry, renewal, rebind; struct data_string filename, server_name; int got_requested_address; int got_server_identifier; struct shared_network *shared_network; /* Shared network of interface on which request arrived. */ u_int32_t xid; u_int16_t secs; u_int16_t bootp_flags; struct in_addr ciaddr; struct in_addr siaddr; struct in_addr giaddr; u_int8_t hops; u_int8_t offer; struct iaddr from; }; #define ROOT_GROUP 0 #define HOST_DECL 1 #define SHARED_NET_DECL 2 #define SUBNET_DECL 3 #define CLASS_DECL 4 #define GROUP_DECL 5 #define POOL_DECL 6 /* Possible modes in which discover_interfaces can run. */ #define DISCOVER_RUNNING 0 #define DISCOVER_SERVER 1 #define DISCOVER_UNCONFIGURED 2 #define DISCOVER_RELAY 3 #define DISCOVER_REQUESTED 4 /* Server option names. */ #define SV_DEFAULT_LEASE_TIME 1 #define SV_MAX_LEASE_TIME 2 #define SV_MIN_LEASE_TIME 3 #define SV_BOOTP_LEASE_CUTOFF 4 #define SV_BOOTP_LEASE_LENGTH 5 #define SV_BOOT_UNKNOWN_CLIENTS 6 #define SV_DYNAMIC_BOOTP 7 #define SV_ALLOW_BOOTP 8 #define SV_ALLOW_BOOTING 9 #define SV_ONE_LEASE_PER_CLIENT 10 #define SV_GET_LEASE_HOSTNAMES 11 #define SV_USE_HOST_DECL_NAMES 12 #define SV_USE_LEASE_ADDR_FOR_DEFAULT_ROUTE 13 #define SV_MIN_SECS 14 #define SV_FILENAME 15 #define SV_SERVER_NAME 16 #define SV_NEXT_SERVER 17 #define SV_AUTHORITATIVE 18 #define SV_VENDOR_OPTION_SPACE 19 #define SV_ALWAYS_REPLY_RFC1048 20 #define SV_SITE_OPTION_SPACE 21 #define SV_ALWAYS_BROADCAST 22 #define SV_DDNS_DOMAIN_NAME 23 #define SV_DDNS_HOST_NAME 24 #define SV_DDNS_REV_DOMAIN_NAME 25 #define SV_LEASE_FILE_NAME 26 #define SV_PID_FILE_NAME 27 #define SV_DUPLICATES 28 #define SV_DECLINES 29 #define SV_DDNS_UPDATES 30 #define SV_OMAPI_PORT 31 #define SV_LOCAL_PORT 32 #define SV_LIMITED_BROADCAST_ADDRESS 33 #define SV_REMOTE_PORT 34 #define SV_LOCAL_ADDRESS 35 #define SV_OMAPI_KEY 36 #define SV_STASH_AGENT_OPTIONS 37 #define SV_DDNS_TTL 38 #define SV_DDNS_UPDATE_STYLE 39 #define SV_CLIENT_UPDATES 40 #define SV_UPDATE_OPTIMIZATION 41 #define SV_PING_CHECKS 42 #define SV_UPDATE_STATIC_LEASES 43 #define SV_LOG_FACILITY 44 #define SV_DO_FORWARD_UPDATES 45 #define SV_PING_TIMEOUT 46 #if !defined (DEFAULT_PING_TIMEOUT) # define DEFAULT_PING_TIMEOUT 1 #endif #if !defined (DEFAULT_DEFAULT_LEASE_TIME) # define DEFAULT_DEFAULT_LEASE_TIME 43200 #endif #if !defined (DEFAULT_MIN_LEASE_TIME) # define DEFAULT_MIN_LEASE_TIME 0 #endif #if !defined (DEFAULT_MAX_LEASE_TIME) # define DEFAULT_MAX_LEASE_TIME 86400 #endif #if !defined (DEFAULT_DDNS_TTL) # define DEFAULT_DDNS_TTL 3600 #endif /* Client option names */ #define CL_TIMEOUT 1 #define CL_SELECT_INTERVAL 2 #define CL_REBOOT_TIMEOUT 3 #define CL_RETRY_INTERVAL 4 #define CL_BACKOFF_CUTOFF 5 #define CL_INITIAL_INTERVAL 6 #define CL_BOOTP_POLICY 7 #define CL_SCRIPT_NAME 8 #define CL_REQUESTED_OPTIONS 9 #define CL_REQUESTED_LEASE_TIME 10 #define CL_SEND_OPTIONS 11 #define CL_MEDIA 12 #define CL_REJECT_LIST 13 #ifndef CL_DEFAULT_TIMEOUT # define CL_DEFAULT_TIMEOUT 60 #endif #ifndef CL_DEFAULT_SELECT_INTERVAL # define CL_DEFAULT_SELECT_INTERVAL 0 #endif #ifndef CL_DEFAULT_REBOOT_TIMEOUT # define CL_DEFAULT_REBOOT_TIMEOUT 10 #endif #ifndef CL_DEFAULT_RETRY_INTERVAL # define CL_DEFAULT_RETRY_INTERVAL 300 #endif #ifndef CL_DEFAULT_BACKOFF_CUTOFF # define CL_DEFAULT_BACKOFF_CUTOFF 120 #endif #ifndef CL_DEFAULT_INITIAL_INTERVAL # define CL_DEFAULT_INITIAL_INTERVAL 10 #endif #ifndef CL_DEFAULT_BOOTP_POLICY # define CL_DEFAULT_BOOTP_POLICY P_ACCEPT #endif #ifndef CL_DEFAULT_REQUESTED_OPTIONS # define CL_DEFAULT_REQUESTED_OPTIONS \ { DHO_SUBNET_MASK, \ DHO_BROADCAST_ADDRESS, \ DHO_TIME_OFFSET, \ DHO_ROUTERS, \ DHO_DOMAIN_NAME, \ DHO_DOMAIN_NAME_SERVERS, \ DHO_HOST_NAME } #endif struct group_object { OMAPI_OBJECT_PREAMBLE; struct group_object *n_dynamic; struct group *group; char *name; int flags; #define GROUP_OBJECT_DELETED 1 #define GROUP_OBJECT_DYNAMIC 2 #define GROUP_OBJECT_STATIC 4 }; /* Group of declarations that share common parameters. */ struct group { struct group *next; int refcnt; struct group_object *object; struct subnet *subnet; struct shared_network *shared_network; int authoritative; struct executable_statement *statements; }; /* A dhcp host declaration structure. */ struct host_decl { OMAPI_OBJECT_PREAMBLE; struct host_decl *n_ipaddr; struct host_decl *n_dynamic; char *name; struct hardware interface; struct data_string client_identifier; struct option_cache *fixed_addr; struct group *group; struct group_object *named_group; struct data_string auth_key_id; int flags; #define HOST_DECL_DELETED 1 #define HOST_DECL_DYNAMIC 2 #define HOST_DECL_STATIC 4 }; struct permit { struct permit *next; enum { permit_unknown_clients, permit_known_clients, permit_authenticated_clients, permit_unauthenticated_clients, permit_all_clients, permit_dynamic_bootp_clients, permit_class } type; struct class *class; }; struct pool { OMAPI_OBJECT_PREAMBLE; struct pool *next; struct group *group; struct shared_network *shared_network; struct permit *permit_list; struct permit *prohibit_list; struct lease *active; struct lease *expired; struct lease *free; struct lease *backup; struct lease *abandoned; TIME next_event_time; int lease_count; int free_leases; int backup_leases; int index; #if defined (FAILOVER_PROTOCOL) dhcp_failover_state_t *failover_peer; #endif }; struct shared_network { OMAPI_OBJECT_PREAMBLE; struct shared_network *next; char *name; struct subnet *subnets; struct interface_info *interface; struct pool *pools; struct group *group; #if defined (FAILOVER_PROTOCOL) dhcp_failover_state_t *failover_peer; #endif }; struct subnet { OMAPI_OBJECT_PREAMBLE; struct subnet *next_subnet; struct subnet *next_sibling; struct shared_network *shared_network; struct interface_info *interface; struct iaddr interface_address; struct iaddr net; struct iaddr netmask; struct group *group; }; struct collection { struct collection *next; const char *name; struct class *classes; }; /* XXX classes must be reference-counted. */ struct class { OMAPI_OBJECT_PREAMBLE; struct class *nic; /* Next in collection. */ struct class *superclass; /* Set for spawned classes only. */ char *name; /* Not set for spawned classes. */ /* A class may be configured to permit a limited number of leases. */ int lease_limit; int leases_consumed; struct lease **billed_leases; /* If nonzero, class has not been saved since it was last modified. */ int dirty; /* Hash table containing subclasses. */ class_hash_t *hash; struct data_string hash_string; /* Expression used to match class. */ struct expression *expr; /* Expression used to compute subclass identifiers for spawning and to do subclass matching. */ struct expression *submatch; int spawning; struct group *group; /* Statements to execute if class matches. */ struct executable_statement *statements; }; /* DHCP client lease structure... */ struct client_lease { struct client_lease *next; /* Next lease in list. */ TIME expiry, renewal, rebind; /* Lease timeouts. */ struct iaddr address; /* Address being leased. */ char *server_name; /* Name of boot server. */ char *filename; /* Name of file we're supposed to boot. */ struct string_list *medium; /* Network medium. */ struct auth_key *key; /* Key used in basic DHCP authentication. */ unsigned int is_static : 1; /* If set, lease is from config file. */ unsigned int is_bootp: 1; /* If set, lease was acquired with BOOTP. */ struct option_state *options; /* Options supplied with lease. */ }; /* Possible states in which the client can be. */ enum dhcp_state { S_REBOOTING = 1, S_INIT = 2, S_SELECTING = 3, S_REQUESTING = 4, S_BOUND = 5, S_RENEWING = 6, S_REBINDING = 7, S_STOPPED = 8 }; /* Authentication and BOOTP policy possibilities (not all values work for each). */ enum policy { P_IGNORE, P_ACCEPT, P_PREFER, P_REQUIRE, P_DONT }; /* Configuration information from the config file... */ struct client_config { /* * When a message has been received, run these statements * over it. */ struct group *on_receipt; /* * When a message is sent, run these statements. */ struct group *on_transmission; u_int32_t *required_options; /* Options server must supply. */ u_int32_t *requested_options; /* Options to request from server. */ TIME timeout; /* Start to panic if we don't get a lease in this time period when SELECTING. */ TIME initial_interval; /* All exponential backoff intervals start here. */ TIME retry_interval; /* If the protocol failed to produce an address before the timeout, try the protocol again after this many seconds. */ TIME select_interval; /* Wait this many seconds from the first DHCPDISCOVER before picking an offered lease. */ TIME reboot_timeout; /* When in INIT-REBOOT, wait this long before giving up and going to INIT. */ TIME backoff_cutoff; /* When doing exponential backoff, never back off to an interval longer than this amount. */ u_int32_t requested_lease; /* Requested lease time, if user doesn't configure one. */ struct string_list *media; /* Possible network media values. */ char *script_name; /* Name of config script. */ char *vendor_space_name; /* Name of config script. */ enum policy bootp_policy; /* Ignore, accept or prefer BOOTP responses. */ enum policy auth_policy; /* Require authentication, prefer authentication, or don't try to authenticate. */ struct string_list *medium; /* Current network medium. */ struct iaddrlist *reject_list; /* Servers to reject. */ int omapi_port; /* port on which to accept OMAPI connections, or -1 for no listener. */ int do_forward_update; /* If nonzero, and if we have the information we need, update the A record for the address we get. */ }; /* Per-interface state used in the dhcp client... */ struct client_state { struct client_state *next; struct interface_info *interface; char *name; struct client_lease *active; /* Currently active lease. */ struct client_lease *new; /* New lease. */ struct client_lease *offered_leases; /* Leases offered to us. */ struct client_lease *leases; /* Leases we currently hold. */ struct client_lease *alias; /* Alias lease. */ enum dhcp_state state; /* Current state for this interface. */ struct iaddr destination; /* Where to send packet. */ u_int32_t xid; /* Transaction ID. */ u_int16_t secs; /* secs value from DHCPDISCOVER. */ TIME first_sending; /* When was first copy sent? */ TIME interval; /* What's the current resend interval? */ int dns_update_timeout; /* Last timeout set for DNS update. */ struct string_list *medium; /* Last media type tried. */ struct dhcp_packet packet; /* Outgoing DHCP packet. */ unsigned packet_length; /* Actual length of generated packet. */ struct iaddr requested_address; /* Address we would like to get. */ struct client_config *config; /* Client configuration. */ struct string_list *env; /* Client script environment. */ int envc; /* Number of entries in environment. */ struct option_state *sent_options; /* Options we sent. */ }; /* Information about each network interface. */ struct interface_info { OMAPI_OBJECT_PREAMBLE; struct interface_info *next; /* Next interface in list... */ struct shared_network *shared_network; /* Networks connected to this interface. */ struct hardware hw_address; /* Its physical address. */ struct in_addr primary_address; /* Primary interface address. */ u_int8_t *circuit_id; /* Circuit ID associated with this interface. */ unsigned circuit_id_len; /* Length of Circuit ID, if there is one. */ u_int8_t *remote_id; /* Remote ID associated with this interface (if any). */ unsigned remote_id_len; /* Length of Remote ID. */ char name [IFNAMSIZ]; /* Its name... */ int index; /* Its index. */ int rfdesc; /* Its read file descriptor. */ int wfdesc; /* Its write file descriptor, if different. */ unsigned char *rbuf; /* Read buffer, if required. */ unsigned int rbuf_max; /* Size of read buffer. */ size_t rbuf_offset; /* Current offset into buffer. */ size_t rbuf_len; /* Length of data in buffer. */ struct ifreq *ifp; /* Pointer to ifreq struct. */ u_int32_t flags; /* Control flags... */ #define INTERFACE_REQUESTED 1 #define INTERFACE_AUTOMATIC 2 #define INTERFACE_RUNNING 4 /* Only used by DHCP client code. */ struct client_state *client; # if defined (USE_DLPI_SEND) || defined (USE_DLPI_RECEIVE) int dlpi_sap_length; struct hardware dlpi_broadcast_addr; # endif /* DLPI_SEND || DLPI_RECEIVE */ }; struct hardware_link { struct hardware_link *next; char name [IFNAMSIZ]; struct hardware address; }; typedef void (*tvref_t)(void *, void *, const char *, int); typedef void (*tvunref_t)(void *, const char *, int); struct timeout { struct timeout *next; TIME when; void (*func) PROTO ((void *)); void *what; tvref_t ref; tvunref_t unref; }; struct protocol { struct protocol *next; int fd; void (*handler) PROTO ((struct protocol *)); void *local; }; struct dns_query; /* forward */ struct dns_wakeup { struct dns_wakeup *next; /* Next wakeup in chain. */ void (*func) PROTO ((struct dns_query *)); }; struct dns_question { u_int16_t type; /* Type of query. */ u_int16_t class; /* Class of query. */ unsigned char data [1]; /* Query data. */ }; struct dns_answer { u_int16_t type; /* Type of answer. */ u_int16_t class; /* Class of answer. */ int count; /* Number of answers. */ unsigned char *answers[1]; /* Pointers to answers. */ }; struct dns_query { struct dns_query *next; /* Next query in hash bucket. */ u_int32_t hash; /* Hash bucket index. */ TIME expiry; /* Query expiry time (zero if not yet answered. */ u_int16_t id; /* Query ID (also hash table index) */ caddr_t waiters; /* Pointer to list of things waiting on this query. */ struct dns_question *question; /* Question, internal format. */ struct dns_answer *answer; /* Answer, internal format. */ unsigned char *query; /* Query formatted for DNS server. */ unsigned len; /* Length of entire query. */ int sent; /* The query has been sent. */ struct dns_wakeup *wakeups; /* Wakeups to call if this query is answered. */ struct name_server *next_server; /* Next server to try. */ int backoff; /* Current backoff, in seconds. */ }; struct dns_zone { int refcnt; TIME timeout; char *name; struct option_cache *primary; struct option_cache *secondary; struct auth_key *key; }; struct icmp_state { OMAPI_OBJECT_PREAMBLE; int socket; void (*icmp_handler) PROTO ((struct iaddr, u_int8_t *, int)); }; #include "ctrace.h" /* Bitmask of dhcp option codes. */ typedef unsigned char option_mask [16]; /* DHCP Option mask manipulation macros... */ #define OPTION_ZERO(mask) (memset (mask, 0, 16)) #define OPTION_SET(mask, bit) (mask [bit >> 8] |= (1 << (bit & 7))) #define OPTION_CLR(mask, bit) (mask [bit >> 8] &= ~(1 << (bit & 7))) #define OPTION_ISSET(mask, bit) (mask [bit >> 8] & (1 << (bit & 7))) #define OPTION_ISCLR(mask, bit) (!OPTION_ISSET (mask, bit)) /* An option occupies its length plus two header bytes (code and length) for every 255 bytes that must be stored. */ #define OPTION_SPACE(x) ((x) + 2 * ((x) / 255 + 1)) /* Default path to dhcpd config file. */ #ifdef DEBUG #undef _PATH_DHCPD_CONF #define _PATH_DHCPD_CONF "dhcpd.conf" #undef _PATH_DHCPD_DB #define _PATH_DHCPD_DB "dhcpd.leases" #undef _PATH_DHCPD_PID #define _PATH_DHCPD_PID "dhcpd.pid" #else #ifndef _PATH_DHCPD_CONF #define _PATH_DHCPD_CONF "/etc/dhcpd.conf" #endif #ifndef _PATH_DHCPD_DB #define _PATH_DHCPD_DB "/etc/dhcpd.leases" #endif #ifndef _PATH_DHCPD_PID #define _PATH_DHCPD_PID "/var/run/dhcpd.pid" #endif #endif #ifndef _PATH_DHCLIENT_CONF #define _PATH_DHCLIENT_CONF "/etc/dhclient.conf" #endif #ifndef _PATH_DHCLIENT_SCRIPT #define _PATH_DHCLIENT_SCRIPT "/sbin/dhclient-script" #endif #ifndef _PATH_DHCLIENT_PID #define _PATH_DHCLIENT_PID "/var/run/dhclient.pid" #endif #ifndef _PATH_DHCLIENT_DB #define _PATH_DHCLIENT_DB "/etc/dhclient.leases" #endif #ifndef _PATH_RESOLV_CONF #define _PATH_RESOLV_CONF "/etc/resolv.conf" #endif #ifndef _PATH_DHCRELAY_PID #define _PATH_DHCRELAY_PID "/var/run/dhcrelay.pid" #endif #ifndef DHCPD_LOG_FACILITY #define DHCPD_LOG_FACILITY LOG_DAEMON #endif #define MAX_TIME 0x7fffffff #define MIN_TIME 0 /* External definitions... */ HASH_FUNCTIONS_DECL (group, const char *, struct group_object, group_hash_t) HASH_FUNCTIONS_DECL (universe, const char *, struct universe, universe_hash_t) HASH_FUNCTIONS_DECL (option, const char *, struct option, option_hash_t) HASH_FUNCTIONS_DECL (dns_zone, const char *, struct dns_zone, dns_zone_hash_t) HASH_FUNCTIONS_DECL (lease, const unsigned char *, struct lease, lease_hash_t) HASH_FUNCTIONS_DECL (host, const unsigned char *, struct host_decl, host_hash_t) HASH_FUNCTIONS_DECL (class, const char *, struct class, class_hash_t) /* options.c */ extern struct option *vendor_cfg_option; int parse_options PROTO ((struct packet *)); int parse_option_buffer PROTO ((struct option_state *, const unsigned char *, unsigned, struct universe *)); struct universe *find_option_universe (struct option *, const char *); int parse_encapsulated_suboptions (struct option_state *, struct option *, const unsigned char *, unsigned, struct universe *, const char *); int cons_options PROTO ((struct packet *, struct dhcp_packet *, struct lease *, struct client_state *, int, struct option_state *, struct option_state *, struct binding_scope **, int, int, int, struct data_string *, const char *)); int fqdn_universe_decode (struct option_state *, const unsigned char *, unsigned, struct universe *); int store_options PROTO ((unsigned char *, unsigned, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, unsigned *, int, unsigned, unsigned, int, const char *)); const char *pretty_print_option PROTO ((struct option *, const unsigned char *, unsigned, int, int)); int get_option (struct data_string *, struct universe *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct option_state *, struct binding_scope **, unsigned, const char *, int); void set_option (struct universe *, struct option_state *, struct option_cache *, enum statement_op); struct option_cache *lookup_option PROTO ((struct universe *, struct option_state *, unsigned)); struct option_cache *lookup_hashed_option PROTO ((struct universe *, struct option_state *, unsigned)); int save_option_buffer (struct universe *, struct option_state *, struct buffer *, unsigned char *, unsigned, struct option *, int); void save_option PROTO ((struct universe *, struct option_state *, struct option_cache *)); void save_hashed_option PROTO ((struct universe *, struct option_state *, struct option_cache *)); void delete_option PROTO ((struct universe *, struct option_state *, int)); void delete_hashed_option PROTO ((struct universe *, struct option_state *, int)); int option_cache_dereference PROTO ((struct option_cache **, const char *, int)); int hashed_option_state_dereference PROTO ((struct universe *, struct option_state *, const char *, int)); int store_option PROTO ((struct data_string *, struct universe *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct option_cache *)); int option_space_encapsulate PROTO ((struct data_string *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct data_string *)); int hashed_option_space_encapsulate PROTO ((struct data_string *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *)); int nwip_option_space_encapsulate PROTO ((struct data_string *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *)); int fqdn_option_space_encapsulate (struct data_string *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *); void suboption_foreach (struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *, void (*) (struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *), struct option_cache *, const char *); void option_space_foreach (struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *, void (*) (struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *)); void hashed_option_space_foreach (struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *, void (*) (struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *)); int linked_option_get PROTO ((struct data_string *, struct universe *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct option_state *, struct binding_scope **, unsigned)); int linked_option_state_dereference PROTO ((struct universe *, struct option_state *, const char *, int)); void save_linked_option (struct universe *, struct option_state *, struct option_cache *); void linked_option_space_foreach (struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *, void (*) (struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *)); int linked_option_space_encapsulate (struct data_string *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *); void delete_linked_option (struct universe *, struct option_state *, int); struct option_cache *lookup_linked_option (struct universe *, struct option_state *, unsigned); void do_packet PROTO ((struct interface_info *, struct dhcp_packet *, unsigned, unsigned int, struct iaddr, struct hardware *)); /* dhcpd.c */ extern TIME cur_time; int ddns_update_style; extern const char *path_dhcpd_conf; extern const char *path_dhcpd_db; extern const char *path_dhcpd_pid; extern int dhcp_max_agent_option_packet_length; int main PROTO ((int, char **, char **)); void postconf_initialization (int); void postdb_startup (void); void cleanup PROTO ((void)); void lease_pinged PROTO ((struct iaddr, u_int8_t *, int)); void lease_ping_timeout PROTO ((void *)); int dhcpd_interface_setup_hook (struct interface_info *ip, struct iaddr *ia); enum dhcp_shutdown_state shutdown_state; isc_result_t dhcp_io_shutdown (omapi_object_t *, void *); isc_result_t dhcp_set_control_state (control_object_state_t oldstate, control_object_state_t newstate); /* conflex.c */ isc_result_t new_parse PROTO ((struct parse **, int, char *, unsigned, const char *, int)); isc_result_t end_parse PROTO ((struct parse **)); enum dhcp_token next_token PROTO ((const char **, unsigned *, struct parse *)); enum dhcp_token peek_token PROTO ((const char **, unsigned *, struct parse *)); /* confpars.c */ void parse_trace_setup (void); isc_result_t readconf PROTO ((void)); isc_result_t read_conf_file (const char *, struct group *, int, int); #if defined (TRACING) void trace_conf_input (trace_type_t *, unsigned, char *); void trace_conf_stop (trace_type_t *ttype); #endif isc_result_t conf_file_subparse (struct parse *, struct group *, int); isc_result_t lease_file_subparse (struct parse *); int parse_statement PROTO ((struct parse *, struct group *, int, struct host_decl *, int)); #if defined (FAILOVER_PROTOCOL) void parse_failover_peer PROTO ((struct parse *, struct group *, int)); void parse_failover_state_declaration (struct parse *, dhcp_failover_state_t *); void parse_failover_state PROTO ((struct parse *, enum failover_state *, TIME *)); #endif int permit_list_match (struct permit *, struct permit *); void parse_pool_statement PROTO ((struct parse *, struct group *, int)); int parse_boolean PROTO ((struct parse *)); int parse_lbrace PROTO ((struct parse *)); void parse_host_declaration PROTO ((struct parse *, struct group *)); int parse_class_declaration PROTO ((struct class **, struct parse *, struct group *, int)); void parse_shared_net_declaration PROTO ((struct parse *, struct group *)); void parse_subnet_declaration PROTO ((struct parse *, struct shared_network *)); void parse_group_declaration PROTO ((struct parse *, struct group *)); int parse_fixed_addr_param PROTO ((struct option_cache **, struct parse *)); TIME parse_timestamp PROTO ((struct parse *)); int parse_lease_declaration PROTO ((struct lease **, struct parse *)); void parse_address_range PROTO ((struct parse *, struct group *, int, struct pool *, struct lease **)); /* ddns.c */ int ddns_updates PROTO ((struct packet *, struct lease *, struct lease *, struct lease_state *)); int ddns_removals PROTO ((struct lease *)); /* parse.c */ void add_enumeration (struct enumeration *); struct enumeration *find_enumeration (const char *, int); struct enumeration_value *find_enumeration_value (const char *, int, const char *); void skip_to_semi PROTO ((struct parse *)); void skip_to_rbrace PROTO ((struct parse *, int)); int parse_semi PROTO ((struct parse *)); int parse_string PROTO ((struct parse *, char **, unsigned *)); char *parse_host_name PROTO ((struct parse *)); int parse_ip_addr_or_hostname PROTO ((struct expression **, struct parse *, int)); void parse_hardware_param PROTO ((struct parse *, struct hardware *)); void parse_lease_time PROTO ((struct parse *, TIME *)); unsigned char *parse_numeric_aggregate PROTO ((struct parse *, unsigned char *, unsigned *, int, int, unsigned)); void convert_num PROTO ((struct parse *, unsigned char *, const char *, int, unsigned)); TIME parse_date PROTO ((struct parse *)); struct option *parse_option_name PROTO ((struct parse *, int, int *)); void parse_option_space_decl PROTO ((struct parse *)); int parse_option_code_definition PROTO ((struct parse *, struct option *)); int parse_base64 (struct data_string *, struct parse *); int parse_cshl PROTO ((struct data_string *, struct parse *)); int parse_executable_statement PROTO ((struct executable_statement **, struct parse *, int *, enum expression_context)); int parse_executable_statements PROTO ((struct executable_statement **, struct parse *, int *, enum expression_context)); int parse_zone (struct dns_zone *, struct parse *); int parse_key (struct parse *); int parse_on_statement PROTO ((struct executable_statement **, struct parse *, int *)); int parse_switch_statement PROTO ((struct executable_statement **, struct parse *, int *)); int parse_case_statement PROTO ((struct executable_statement **, struct parse *, int *, enum expression_context)); int parse_if_statement PROTO ((struct executable_statement **, struct parse *, int *)); int parse_boolean_expression PROTO ((struct expression **, struct parse *, int *)); int parse_data_expression PROTO ((struct expression **, struct parse *, int *)); int parse_numeric_expression PROTO ((struct expression **, struct parse *, int *)); int parse_dns_expression PROTO ((struct expression **, struct parse *, int *)); int parse_non_binary PROTO ((struct expression **, struct parse *, int *, enum expression_context)); int parse_expression PROTO ((struct expression **, struct parse *, int *, enum expression_context, struct expression **, enum expr_op)); int parse_option_statement PROTO ((struct executable_statement **, struct parse *, int, struct option *, enum statement_op)); int parse_option_token PROTO ((struct expression **, struct parse *, const char **, struct expression *, int, int)); int parse_allow_deny PROTO ((struct option_cache **, struct parse *, int)); int parse_auth_key PROTO ((struct data_string *, struct parse *)); int parse_warn (struct parse *, const char *, ...) __attribute__((__format__(__printf__,2,3))); /* tree.c */ #if defined (NSUPDATE) extern struct __res_state resolver_state; extern int resolver_inited; #endif extern struct binding_scope *global_scope; pair cons PROTO ((caddr_t, pair)); int make_const_option_cache PROTO ((struct option_cache **, struct buffer **, u_int8_t *, unsigned, struct option *, const char *, int)); int make_host_lookup PROTO ((struct expression **, const char *)); int enter_dns_host PROTO ((struct dns_host_entry **, const char *)); int make_const_data (struct expression **, const unsigned char *, unsigned, int, int, const char *, int); int make_const_int PROTO ((struct expression **, unsigned long)); int make_concat PROTO ((struct expression **, struct expression *, struct expression *)); int make_encapsulation PROTO ((struct expression **, struct data_string *)); int make_substring PROTO ((struct expression **, struct expression *, struct expression *, struct expression *)); int make_limit PROTO ((struct expression **, struct expression *, int)); int make_let PROTO ((struct executable_statement **, const char *)); int option_cache PROTO ((struct option_cache **, struct data_string *, struct expression *, struct option *, const char *, int)); int evaluate_expression (struct binding_value **, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct expression *, const char *, int); int binding_value_dereference (struct binding_value **, const char *, int); #if defined (NSUPDATE) int evaluate_dns_expression PROTO ((ns_updrec **, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct expression *)); #endif int evaluate_boolean_expression PROTO ((int *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct expression *)); int evaluate_data_expression PROTO ((struct data_string *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct expression *, const char *, int)); int evaluate_numeric_expression (unsigned long *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct expression *); int evaluate_option_cache PROTO ((struct data_string *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct option_cache *, const char *, int)); int evaluate_boolean_option_cache PROTO ((int *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct option_cache *, const char *, int)); int evaluate_boolean_expression_result PROTO ((int *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct expression *)); void expression_dereference PROTO ((struct expression **, const char *, int)); int is_dns_expression PROTO ((struct expression *)); int is_boolean_expression PROTO ((struct expression *)); int is_data_expression PROTO ((struct expression *)); int is_numeric_expression PROTO ((struct expression *)); int is_compound_expression PROTO ((struct expression *)); int op_precedence PROTO ((enum expr_op, enum expr_op)); enum expression_context expression_context (struct expression *); enum expression_context op_context PROTO ((enum expr_op)); int write_expression PROTO ((FILE *, struct expression *, int, int, int)); struct binding *find_binding PROTO ((struct binding_scope *, const char *)); int free_bindings PROTO ((struct binding_scope *, const char *, int)); int binding_scope_dereference PROTO ((struct binding_scope **, const char *, int)); int fundef_dereference (struct fundef **, const char *, int); int data_subexpression_length (int *, struct expression *); int expr_valid_for_context (struct expression *, enum expression_context); struct binding *create_binding (struct binding_scope **, const char *); int bind_ds_value (struct binding_scope **, const char *, struct data_string *); int find_bound_string (struct data_string *, struct binding_scope *, const char *); int unset (struct binding_scope *, const char *); /* dhcp.c */ extern int outstanding_pings; void dhcp PROTO ((struct packet *)); void dhcpdiscover PROTO ((struct packet *, int)); void dhcprequest PROTO ((struct packet *, int, struct lease *)); void dhcprelease PROTO ((struct packet *, int)); void dhcpdecline PROTO ((struct packet *, int)); void dhcpinform PROTO ((struct packet *, int)); void nak_lease PROTO ((struct packet *, struct iaddr *cip)); void ack_lease PROTO ((struct packet *, struct lease *, unsigned int, TIME, char *, int)); void dhcp_reply PROTO ((struct lease *)); int find_lease PROTO ((struct lease **, struct packet *, struct shared_network *, int *, int *, struct lease *, const char *, int)); int mockup_lease PROTO ((struct lease **, struct packet *, struct shared_network *, struct host_decl *)); void static_lease_dereference PROTO ((struct lease *, const char *, int)); int allocate_lease PROTO ((struct lease **, struct packet *, struct pool *, int *)); int permitted PROTO ((struct packet *, struct permit *)); int locate_network PROTO ((struct packet *)); int parse_agent_information_option PROTO ((struct packet *, int, u_int8_t *)); unsigned cons_agent_information_options PROTO ((struct option_state *, struct dhcp_packet *, unsigned, unsigned)); /* bootp.c */ void bootp PROTO ((struct packet *)); /* memory.c */ int (*group_write_hook) (struct group_object *); extern struct group *root_group; extern group_hash_t *group_name_hash; isc_result_t delete_group (struct group_object *, int); isc_result_t supersede_group (struct group_object *, int); int clone_group (struct group **, struct group *, const char *, int); int write_group PROTO ((struct group_object *)); /* salloc.c */ void relinquish_lease_hunks (void); struct lease *new_leases PROTO ((unsigned, const char *, int)); #if defined (DEBUG_MEMORY_LEAKAGE) || \ defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) void relinquish_free_lease_states (void); #endif OMAPI_OBJECT_ALLOC_DECL (lease, struct lease, dhcp_type_lease) OMAPI_OBJECT_ALLOC_DECL (class, struct class, dhcp_type_class) OMAPI_OBJECT_ALLOC_DECL (pool, struct pool, dhcp_type_pool) OMAPI_OBJECT_ALLOC_DECL (host, struct host_decl, dhcp_type_host) /* alloc.c */ OMAPI_OBJECT_ALLOC_DECL (subnet, struct subnet, dhcp_type_subnet) OMAPI_OBJECT_ALLOC_DECL (shared_network, struct shared_network, dhcp_type_shared_network) OMAPI_OBJECT_ALLOC_DECL (group_object, struct group_object, dhcp_type_group) OMAPI_OBJECT_ALLOC_DECL (dhcp_control, dhcp_control_object_t, dhcp_type_control) #if defined (DEBUG_MEMORY_LEAKAGE) || \ defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) void relinquish_free_pairs (void); void relinquish_free_expressions (void); void relinquish_free_binding_values (void); void relinquish_free_option_caches (void); void relinquish_free_packets (void); #endif int option_chain_head_allocate (struct option_chain_head **, const char *, int); int option_chain_head_reference (struct option_chain_head **, struct option_chain_head *, const char *, int); int option_chain_head_dereference (struct option_chain_head **, const char *, int); int group_allocate (struct group **, const char *, int); int group_reference (struct group **, struct group *, const char *, int); int group_dereference (struct group **, const char *, int); struct dhcp_packet *new_dhcp_packet PROTO ((const char *, int)); struct protocol *new_protocol PROTO ((const char *, int)); struct lease_state *new_lease_state PROTO ((const char *, int)); struct domain_search_list *new_domain_search_list PROTO ((const char *, int)); struct name_server *new_name_server PROTO ((const char *, int)); void free_name_server PROTO ((struct name_server *, const char *, int)); struct option *new_option PROTO ((const char *, int)); int group_allocate (struct group **, const char *, int); int group_reference (struct group **, struct group *, const char *, int); int group_dereference (struct group **, const char *, int); void free_option PROTO ((struct option *, const char *, int)); struct universe *new_universe PROTO ((const char *, int)); void free_universe PROTO ((struct universe *, const char *, int)); void free_domain_search_list PROTO ((struct domain_search_list *, const char *, int)); void free_lease_state PROTO ((struct lease_state *, const char *, int)); void free_protocol PROTO ((struct protocol *, const char *, int)); void free_dhcp_packet PROTO ((struct dhcp_packet *, const char *, int)); struct client_lease *new_client_lease PROTO ((const char *, int)); void free_client_lease PROTO ((struct client_lease *, const char *, int)); struct permit *new_permit PROTO ((const char *, int)); void free_permit PROTO ((struct permit *, const char *, int)); pair new_pair PROTO ((const char *, int)); void free_pair PROTO ((pair, const char *, int)); int expression_allocate PROTO ((struct expression **, const char *, int)); int expression_reference PROTO ((struct expression **, struct expression *, const char *, int)); void free_expression PROTO ((struct expression *, const char *, int)); int binding_value_allocate PROTO ((struct binding_value **, const char *, int)); int binding_value_reference PROTO ((struct binding_value **, struct binding_value *, const char *, int)); void free_binding_value PROTO ((struct binding_value *, const char *, int)); int fundef_allocate PROTO ((struct fundef **, const char *, int)); int fundef_reference PROTO ((struct fundef **, struct fundef *, const char *, int)); int option_cache_allocate PROTO ((struct option_cache **, const char *, int)); int option_cache_reference PROTO ((struct option_cache **, struct option_cache *, const char *, int)); int buffer_allocate PROTO ((struct buffer **, unsigned, const char *, int)); int buffer_reference PROTO ((struct buffer **, struct buffer *, const char *, int)); int buffer_dereference PROTO ((struct buffer **, const char *, int)); int dns_host_entry_allocate PROTO ((struct dns_host_entry **, const char *, const char *, int)); int dns_host_entry_reference PROTO ((struct dns_host_entry **, struct dns_host_entry *, const char *, int)); int dns_host_entry_dereference PROTO ((struct dns_host_entry **, const char *, int)); int option_state_allocate PROTO ((struct option_state **, const char *, int)); int option_state_reference PROTO ((struct option_state **, struct option_state *, const char *, int)); int option_state_dereference PROTO ((struct option_state **, const char *, int)); void data_string_copy PROTO ((struct data_string *, struct data_string *, const char *, int)); void data_string_forget PROTO ((struct data_string *, const char *, int)); void data_string_truncate PROTO ((struct data_string *, int)); int executable_statement_allocate PROTO ((struct executable_statement **, const char *, int)); int executable_statement_reference PROTO ((struct executable_statement **, struct executable_statement *, const char *, int)); int packet_allocate PROTO ((struct packet **, const char *, int)); int packet_reference PROTO ((struct packet **, struct packet *, const char *, int)); int packet_dereference PROTO ((struct packet **, const char *, int)); int binding_scope_allocate PROTO ((struct binding_scope **, const char *, int)); int binding_scope_reference PROTO ((struct binding_scope **, struct binding_scope *, const char *, int)); int dns_zone_allocate PROTO ((struct dns_zone **, const char *, int)); int dns_zone_reference PROTO ((struct dns_zone **, struct dns_zone *, const char *, int)); /* print.c */ char *quotify_string (const char *, const char *, int); char *quotify_buf (const unsigned char *, unsigned, const char *, int); char *print_base64 (const unsigned char *, unsigned, const char *, int); char *print_hw_addr PROTO ((int, int, unsigned char *)); void print_lease PROTO ((struct lease *)); void dump_raw PROTO ((const unsigned char *, unsigned)); void dump_packet_option (struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *); void dump_packet PROTO ((struct packet *)); void hash_dump PROTO ((struct hash_table *)); char *print_hex_1 PROTO ((unsigned, const u_int8_t *, unsigned)); char *print_hex_2 PROTO ((unsigned, const u_int8_t *, unsigned)); char *print_hex_3 PROTO ((unsigned, const u_int8_t *, unsigned)); char *print_dotted_quads PROTO ((unsigned, const u_int8_t *)); char *print_dec_1 PROTO ((unsigned long)); char *print_dec_2 PROTO ((unsigned long)); void print_expression PROTO ((const char *, struct expression *)); int token_print_indent_concat (FILE *, int, int, const char *, const char *, ...); int token_indent_data_string (FILE *, int, int, const char *, const char *, struct data_string *); int token_print_indent (FILE *, int, int, const char *, const char *, const char *); void indent_spaces (FILE *, int); #if defined (NSUPDATE) void print_dns_status (int, ns_updque *); #endif /* socket.c */ #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_RECEIVE) \ || defined (USE_SOCKET_FALLBACK) int if_register_socket PROTO ((struct interface_info *)); #endif #if defined (USE_SOCKET_FALLBACK) && !defined (USE_SOCKET_SEND) void if_reinitialize_fallback PROTO ((struct interface_info *)); void if_register_fallback PROTO ((struct interface_info *)); ssize_t send_fallback PROTO ((struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)); #endif #ifdef USE_SOCKET_SEND void if_reinitialize_send PROTO ((struct interface_info *)); void if_register_send PROTO ((struct interface_info *)); void if_deregister_send PROTO ((struct interface_info *)); ssize_t send_packet PROTO ((struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)); #endif #ifdef USE_SOCKET_RECEIVE void if_reinitialize_receive PROTO ((struct interface_info *)); void if_register_receive PROTO ((struct interface_info *)); void if_deregister_receive PROTO ((struct interface_info *)); ssize_t receive_packet PROTO ((struct interface_info *, unsigned char *, size_t, struct sockaddr_in *, struct hardware *)); #endif #if defined (USE_SOCKET_FALLBACK) isc_result_t fallback_discard PROTO ((omapi_object_t *)); #endif #if defined (USE_SOCKET_SEND) int can_unicast_without_arp PROTO ((struct interface_info *)); int can_receive_unicast_unconfigured PROTO ((struct interface_info *)); int supports_multiple_interfaces (struct interface_info *); void maybe_setup_fallback PROTO ((void)); #endif /* bpf.c */ #if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE) int if_register_bpf PROTO ( (struct interface_info *)); #endif #ifdef USE_BPF_SEND void if_reinitialize_send PROTO ((struct interface_info *)); void if_register_send PROTO ((struct interface_info *)); void if_deregister_send PROTO ((struct interface_info *)); ssize_t send_packet PROTO ((struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)); #endif #ifdef USE_BPF_RECEIVE void if_reinitialize_receive PROTO ((struct interface_info *)); void if_register_receive PROTO ((struct interface_info *)); void if_deregister_receive PROTO ((struct interface_info *)); ssize_t receive_packet PROTO ((struct interface_info *, unsigned char *, size_t, struct sockaddr_in *, struct hardware *)); #endif #if defined (USE_BPF_SEND) int can_unicast_without_arp PROTO ((struct interface_info *)); int can_receive_unicast_unconfigured PROTO ((struct interface_info *)); int supports_multiple_interfaces (struct interface_info *); void maybe_setup_fallback PROTO ((void)); #endif /* lpf.c */ #if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE) int if_register_lpf PROTO ( (struct interface_info *)); #endif #ifdef USE_LPF_SEND void if_reinitialize_send PROTO ((struct interface_info *)); void if_register_send PROTO ((struct interface_info *)); void if_deregister_send PROTO ((struct interface_info *)); ssize_t send_packet PROTO ((struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)); #endif #ifdef USE_LPF_RECEIVE void if_reinitialize_receive PROTO ((struct interface_info *)); void if_register_receive PROTO ((struct interface_info *)); void if_deregister_receive PROTO ((struct interface_info *)); ssize_t receive_packet PROTO ((struct interface_info *, unsigned char *, size_t, struct sockaddr_in *, struct hardware *)); #endif #if defined (USE_LPF_SEND) int can_unicast_without_arp PROTO ((struct interface_info *)); int can_receive_unicast_unconfigured PROTO ((struct interface_info *)); int supports_multiple_interfaces (struct interface_info *); void maybe_setup_fallback PROTO ((void)); #endif /* nit.c */ #if defined (USE_NIT_SEND) || defined (USE_NIT_RECEIVE) int if_register_nit PROTO ( (struct interface_info *)); #endif #ifdef USE_NIT_SEND void if_reinitialize_send PROTO ((struct interface_info *)); void if_register_send PROTO ((struct interface_info *)); void if_deregister_send PROTO ((struct interface_info *)); ssize_t send_packet PROTO ((struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)); #endif #ifdef USE_NIT_RECEIVE void if_reinitialize_receive PROTO ((struct interface_info *)); void if_register_receive PROTO ((struct interface_info *)); void if_deregister_receive PROTO ((struct interface_info *)); ssize_t receive_packet PROTO ((struct interface_info *, unsigned char *, size_t, struct sockaddr_in *, struct hardware *)); #endif #if defined (USE_NIT_SEND) int can_unicast_without_arp PROTO ((struct interface_info *)); int can_receive_unicast_unconfigured PROTO ((struct interface_info *)); int supports_multiple_interfaces (struct interface_info *); void maybe_setup_fallback PROTO ((void)); #endif /* dlpi.c */ #if defined (USE_DLPI_SEND) || defined (USE_DLPI_RECEIVE) int if_register_dlpi PROTO ( (struct interface_info *)); #endif #ifdef USE_DLPI_SEND void if_reinitialize_send PROTO ((struct interface_info *)); void if_register_send PROTO ((struct interface_info *)); void if_deregister_send PROTO ((struct interface_info *)); ssize_t send_packet PROTO ((struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)); #endif #ifdef USE_DLPI_RECEIVE void if_reinitialize_receive PROTO ((struct interface_info *)); void if_register_receive PROTO ((struct interface_info *)); void if_deregister_receive PROTO ((struct interface_info *)); ssize_t receive_packet PROTO ((struct interface_info *, unsigned char *, size_t, struct sockaddr_in *, struct hardware *)); #endif /* raw.c */ #ifdef USE_RAW_SEND void if_reinitialize_send PROTO ((struct interface_info *)); void if_register_send PROTO ((struct interface_info *)); void if_deregister_send PROTO ((struct interface_info *)); ssize_t send_packet PROTO ((struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)); int can_unicast_without_arp PROTO ((struct interface_info *)); int can_receive_unicast_unconfigured PROTO ((struct interface_info *)); int supports_multiple_interfaces (struct interface_info *); void maybe_setup_fallback PROTO ((void)); #endif /* discover.c */ extern struct interface_info *interfaces, *dummy_interfaces, *fallback_interface; extern struct protocol *protocols; extern int quiet_interface_discovery; isc_result_t interface_setup (void); void interface_trace_setup (void); extern struct in_addr limited_broadcast; extern struct in_addr local_address; extern u_int16_t local_port; extern u_int16_t remote_port; extern int (*dhcp_interface_setup_hook) (struct interface_info *, struct iaddr *); extern int (*dhcp_interface_discovery_hook) (struct interface_info *); isc_result_t (*dhcp_interface_startup_hook) (struct interface_info *); extern void (*bootp_packet_handler) PROTO ((struct interface_info *, struct dhcp_packet *, unsigned, unsigned int, struct iaddr, struct hardware *)); extern struct timeout *timeouts; extern 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 extern struct interface_info **interface_vector; extern int interface_count; extern int interface_max; isc_result_t interface_initialize (omapi_object_t *, const char *, int); void discover_interfaces PROTO ((int)); int setup_fallback (struct interface_info **, const char *, int); int if_readsocket PROTO ((omapi_object_t *)); void reinitialize_interfaces PROTO ((void)); /* dispatch.c */ void set_time (u_int32_t); struct timeval *process_outstanding_timeouts (struct timeval *); void dispatch PROTO ((void)); isc_result_t got_one PROTO ((omapi_object_t *)); isc_result_t interface_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t interface_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t interface_destroy (omapi_object_t *, const char *, int); isc_result_t interface_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t interface_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); void add_timeout PROTO ((TIME, void (*) PROTO ((void *)), void *, tvref_t, tvunref_t)); void cancel_timeout PROTO ((void (*) PROTO ((void *)), void *)); void cancel_all_timeouts (void); void relinquish_timeouts (void); #if 0 struct protocol *add_protocol PROTO ((const char *, int, void (*) PROTO ((struct protocol *)), void *)); void remove_protocol PROTO ((struct protocol *)); #endif OMAPI_OBJECT_ALLOC_DECL (interface, struct interface_info, dhcp_type_interface) /* tables.c */ extern struct universe dhcp_universe; extern struct option dhcp_options [256]; extern struct universe nwip_universe; extern struct option nwip_options [256]; extern struct universe fqdn_universe; extern struct option fqdn_options [256]; extern int dhcp_option_default_priority_list []; extern int dhcp_option_default_priority_list_count; extern const char *hardware_types [256]; int universe_count, universe_max; struct universe **universes; extern universe_hash_t *universe_hash; void initialize_common_option_spaces PROTO ((void)); struct universe *config_universe; /* stables.c */ #if defined (FAILOVER_PROTOCOL) extern failover_option_t null_failover_option; extern failover_option_t skip_failover_option; extern struct failover_option_info ft_options []; extern u_int32_t fto_allowed []; extern int ft_sizes []; extern const char *dhcp_flink_state_names []; #endif extern const char *binding_state_names []; extern struct universe agent_universe; extern struct option agent_options [256]; extern struct universe server_universe; extern struct option server_options [256]; extern struct enumeration ddns_styles; extern struct enumeration syslog_enum; void initialize_server_option_spaces PROTO ((void)); /* inet.c */ struct iaddr subnet_number PROTO ((struct iaddr, struct iaddr)); struct iaddr ip_addr PROTO ((struct iaddr, struct iaddr, u_int32_t)); struct iaddr broadcast_addr PROTO ((struct iaddr, struct iaddr)); u_int32_t host_addr PROTO ((struct iaddr, struct iaddr)); int addr_eq PROTO ((struct iaddr, struct iaddr)); char *piaddr PROTO ((struct iaddr)); char *piaddrmask (struct iaddr, struct iaddr, const char *, int); char *piaddr1 PROTO ((struct iaddr)); /* dhclient.c */ extern const char *path_dhclient_conf; extern const char *path_dhclient_db; extern const char *path_dhclient_pid; extern char *path_dhclient_script; extern int interfaces_requested; extern struct client_config top_level_config; void dhcpoffer PROTO ((struct packet *)); void dhcpack PROTO ((struct packet *)); void dhcpnak PROTO ((struct packet *)); void send_discover PROTO ((void *)); void send_request PROTO ((void *)); void send_release PROTO ((void *)); void send_decline PROTO ((void *)); void state_reboot PROTO ((void *)); void state_init PROTO ((void *)); void state_selecting PROTO ((void *)); void state_requesting PROTO ((void *)); void state_bound PROTO ((void *)); void state_stop PROTO ((void *)); void state_panic PROTO ((void *)); void bind_lease PROTO ((struct client_state *)); void make_client_options PROTO ((struct client_state *, struct client_lease *, u_int8_t *, struct option_cache *, struct iaddr *, u_int32_t *, struct option_state **)); void make_discover PROTO ((struct client_state *, struct client_lease *)); void make_request PROTO ((struct client_state *, struct client_lease *)); void make_decline PROTO ((struct client_state *, struct client_lease *)); void make_release PROTO ((struct client_state *, struct client_lease *)); void destroy_client_lease PROTO ((struct client_lease *)); void rewrite_client_leases PROTO ((void)); void write_lease_option (struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *); int write_client_lease PROTO ((struct client_state *, struct client_lease *, int, int)); int dhcp_option_ev_name (char *, size_t, struct option *); void script_init PROTO ((struct client_state *, const char *, struct string_list *)); void client_option_envadd (struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *); void script_write_params PROTO ((struct client_state *, const char *, struct client_lease *)); int script_go PROTO ((struct client_state *)); void client_envadd (struct client_state *, const char *, const char *, const char *, ...) __attribute__((__format__(__printf__,4,5))); struct client_lease *packet_to_lease (struct packet *, struct client_state *); void go_daemon PROTO ((void)); void write_client_pid_file PROTO ((void)); void client_location_changed PROTO ((void)); void do_release PROTO ((struct client_state *)); int dhclient_interface_shutdown_hook (struct interface_info *); int dhclient_interface_discovery_hook (struct interface_info *); isc_result_t dhclient_interface_startup_hook (struct interface_info *); void client_dns_update_timeout (void *cp); isc_result_t client_dns_update (struct client_state *client, int, int); /* db.c */ int write_lease PROTO ((struct lease *)); int write_host PROTO ((struct host_decl *)); #if defined (FAILOVER_PROTOCOL) int write_failover_state (dhcp_failover_state_t *); #endif int db_printable PROTO ((const char *)); int db_printable_len PROTO ((const unsigned char *, unsigned)); void write_named_billing_class (const char *, unsigned, struct class *); void write_billing_classes (void); int write_billing_class PROTO ((struct class *)); void commit_leases_timeout PROTO ((void *)); int commit_leases PROTO ((void)); void db_startup PROTO ((int)); int new_lease_file PROTO ((void)); int group_writer (struct group_object *); /* packet.c */ u_int32_t checksum PROTO ((unsigned char *, unsigned, u_int32_t)); u_int32_t wrapsum PROTO ((u_int32_t)); void assemble_hw_header PROTO ((struct interface_info *, unsigned char *, unsigned *, struct hardware *)); void assemble_udp_ip_header PROTO ((struct interface_info *, unsigned char *, unsigned *, u_int32_t, u_int32_t, u_int32_t, unsigned char *, unsigned)); ssize_t decode_hw_header PROTO ((struct interface_info *, unsigned char *, unsigned, struct hardware *)); ssize_t decode_udp_ip_header PROTO ((struct interface_info *, unsigned char *, unsigned, struct sockaddr_in *, unsigned char *, unsigned)); /* ethernet.c */ void assemble_ethernet_header PROTO ((struct interface_info *, unsigned char *, unsigned *, struct hardware *)); ssize_t decode_ethernet_header PROTO ((struct interface_info *, unsigned char *, unsigned, struct hardware *)); /* tr.c */ void assemble_tr_header PROTO ((struct interface_info *, unsigned char *, unsigned *, struct hardware *)); ssize_t decode_tr_header PROTO ((struct interface_info *, unsigned char *, unsigned, struct hardware *)); /* dhxpxlt.c */ void convert_statement PROTO ((struct parse *)); void convert_host_statement PROTO ((struct parse *, jrefproto)); void convert_host_name PROTO ((struct parse *, jrefproto)); void convert_class_statement PROTO ((struct parse *, jrefproto, int)); void convert_class_decl PROTO ((struct parse *, jrefproto)); void convert_lease_time PROTO ((struct parse *, jrefproto, char *)); void convert_shared_net_statement PROTO ((struct parse *, jrefproto)); void convert_subnet_statement PROTO ((struct parse *, jrefproto)); void convert_subnet_decl PROTO ((struct parse *, jrefproto)); void convert_host_decl PROTO ((struct parse *, jrefproto)); void convert_hardware_decl PROTO ((struct parse *, jrefproto)); void convert_hardware_addr PROTO ((struct parse *, jrefproto)); void convert_filename_decl PROTO ((struct parse *, jrefproto)); void convert_servername_decl PROTO ((struct parse *, jrefproto)); void convert_ip_addr_or_hostname PROTO ((struct parse *, jrefproto, int)); void convert_fixed_addr_decl PROTO ((struct parse *, jrefproto)); void convert_option_decl PROTO ((struct parse *, jrefproto)); void convert_timestamp PROTO ((struct parse *, jrefproto)); void convert_lease_statement PROTO ((struct parse *, jrefproto)); void convert_address_range PROTO ((struct parse *, jrefproto)); void convert_date PROTO ((struct parse *, jrefproto, char *)); void convert_numeric_aggregate PROTO ((struct parse *, jrefproto, int, int, int, int)); void indent PROTO ((int)); /* route.c */ void add_route_direct PROTO ((struct interface_info *, struct in_addr)); void add_route_net PROTO ((struct interface_info *, struct in_addr, struct in_addr)); void add_route_default_gateway PROTO ((struct interface_info *, struct in_addr)); void remove_routes PROTO ((struct in_addr)); void remove_if_route PROTO ((struct interface_info *, struct in_addr)); void remove_all_if_routes PROTO ((struct interface_info *)); void set_netmask PROTO ((struct interface_info *, struct in_addr)); void set_broadcast_addr PROTO ((struct interface_info *, struct in_addr)); void set_ip_address PROTO ((struct interface_info *, struct in_addr)); /* clparse.c */ isc_result_t read_client_conf PROTO ((void)); int read_client_conf_file (const char *, struct interface_info *, struct client_config *); void read_client_leases PROTO ((void)); void parse_client_statement PROTO ((struct parse *, struct interface_info *, struct client_config *)); int parse_X PROTO ((struct parse *, u_int8_t *, unsigned)); void parse_option_list PROTO ((struct parse *, u_int32_t **)); void parse_interface_declaration PROTO ((struct parse *, struct client_config *, char *)); int interface_or_dummy PROTO ((struct interface_info **, const char *)); void make_client_state PROTO ((struct client_state **)); void make_client_config PROTO ((struct client_state *, struct client_config *)); void parse_client_lease_statement PROTO ((struct parse *, int)); void parse_client_lease_declaration PROTO ((struct parse *, struct client_lease *, struct interface_info **, struct client_state **)); int parse_option_decl PROTO ((struct option_cache **, struct parse *)); void parse_string_list PROTO ((struct parse *, struct string_list **, int)); int parse_ip_addr PROTO ((struct parse *, struct iaddr *)); void parse_reject_statement PROTO ((struct parse *, struct client_config *)); /* dhcrelay.c */ void relay PROTO ((struct interface_info *, struct dhcp_packet *, unsigned, unsigned int, struct iaddr, struct hardware *)); int strip_relay_agent_options PROTO ((struct interface_info *, struct interface_info **, struct dhcp_packet *, unsigned)); int find_interface_by_agent_option PROTO ((struct dhcp_packet *, struct interface_info **, u_int8_t *, int)); int add_relay_agent_options PROTO ((struct interface_info *, struct dhcp_packet *, unsigned, struct in_addr)); /* icmp.c */ OMAPI_OBJECT_ALLOC_DECL (icmp_state, struct icmp_state, dhcp_type_icmp) extern struct icmp_state *icmp_state; void icmp_startup PROTO ((int, void (*) PROTO ((struct iaddr, u_int8_t *, int)))); int icmp_readsocket PROTO ((omapi_object_t *)); int icmp_echorequest PROTO ((struct iaddr *)); isc_result_t icmp_echoreply PROTO ((omapi_object_t *)); /* dns.c */ #if defined (NSUPDATE) isc_result_t find_tsig_key (ns_tsig_key **, const char *, struct dns_zone *); void tkey_free (ns_tsig_key **); #endif isc_result_t enter_dns_zone (struct dns_zone *); isc_result_t dns_zone_lookup (struct dns_zone **, const char *); int dns_zone_dereference PROTO ((struct dns_zone **, const char *, int)); #if defined (NSUPDATE) isc_result_t find_cached_zone (const char *, ns_class, char *, size_t, struct in_addr *, int, int *, struct dns_zone **); void forget_zone (struct dns_zone **); void repudiate_zone (struct dns_zone **); void cache_found_zone (ns_class, char *, struct in_addr *, int); int get_dhcid (struct data_string *, int, const u_int8_t *, unsigned); isc_result_t ddns_update_a (struct data_string *, struct iaddr, struct data_string *, unsigned long, int); isc_result_t ddns_remove_a (struct data_string *, struct iaddr, struct data_string *); #endif /* NSUPDATE */ /* resolv.c */ extern char path_resolv_conf []; struct name_server *name_servers; struct domain_search_list *domains; void read_resolv_conf PROTO ((TIME)); struct name_server *first_name_server PROTO ((void)); /* inet_addr.c */ #ifdef NEED_INET_ATON int inet_aton PROTO ((const char *, struct in_addr *)); #endif /* class.c */ extern int have_billing_classes; struct class unknown_class; struct class known_class; struct collection default_collection; struct collection *collections; struct executable_statement *default_classification_rules; void classification_setup PROTO ((void)); void classify_client PROTO ((struct packet *)); int check_collection PROTO ((struct packet *, struct lease *, struct collection *)); void classify PROTO ((struct packet *, struct class *)); isc_result_t find_class PROTO ((struct class **, const char *, const char *, int)); int unbill_class PROTO ((struct lease *, struct class *)); int bill_class PROTO ((struct lease *, struct class *)); /* execute.c */ int execute_statements PROTO ((struct binding_value **result, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct executable_statement *)); void execute_statements_in_scope PROTO ((struct binding_value **result, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct group *, struct group *)); int executable_statement_dereference PROTO ((struct executable_statement **, const char *, int)); void write_statements (FILE *, struct executable_statement *, int); int find_matching_case (struct executable_statement **, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct expression *, struct executable_statement *); int executable_statement_foreach (struct executable_statement *, int (*) (struct executable_statement *, void *, int), void *, int); /* comapi.c */ extern omapi_object_type_t *dhcp_type_interface; extern omapi_object_type_t *dhcp_type_group; extern omapi_object_type_t *dhcp_type_shared_network; extern omapi_object_type_t *dhcp_type_subnet; extern omapi_object_type_t *dhcp_type_control; extern dhcp_control_object_t *dhcp_control_object; void dhcp_common_objects_setup (void); isc_result_t dhcp_group_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t dhcp_group_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t dhcp_group_destroy (omapi_object_t *, const char *, int); isc_result_t dhcp_group_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t dhcp_group_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_group_lookup (omapi_object_t **, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_group_create (omapi_object_t **, omapi_object_t *); isc_result_t dhcp_group_remove (omapi_object_t *, omapi_object_t *); isc_result_t dhcp_control_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t dhcp_control_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t dhcp_control_destroy (omapi_object_t *, const char *, int); isc_result_t dhcp_control_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t dhcp_control_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_control_lookup (omapi_object_t **, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_control_create (omapi_object_t **, omapi_object_t *); isc_result_t dhcp_control_remove (omapi_object_t *, omapi_object_t *); isc_result_t dhcp_subnet_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t dhcp_subnet_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t dhcp_subnet_destroy (omapi_object_t *, const char *, int); isc_result_t dhcp_subnet_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t dhcp_subnet_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_subnet_lookup (omapi_object_t **, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_subnet_create (omapi_object_t **, omapi_object_t *); isc_result_t dhcp_subnet_remove (omapi_object_t *, omapi_object_t *); isc_result_t dhcp_shared_network_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t dhcp_shared_network_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t dhcp_shared_network_destroy (omapi_object_t *, const char *, int); isc_result_t dhcp_shared_network_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t dhcp_shared_network_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_shared_network_lookup (omapi_object_t **, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_shared_network_create (omapi_object_t **, omapi_object_t *); isc_result_t dhcp_shared_network_remove (omapi_object_t *, omapi_object_t *); /* omapi.c */ extern int (*dhcp_interface_shutdown_hook) (struct interface_info *); extern omapi_object_type_t *dhcp_type_lease; extern omapi_object_type_t *dhcp_type_pool; extern omapi_object_type_t *dhcp_type_class; #if defined (FAILOVER_PROTOCOL) extern omapi_object_type_t *dhcp_type_failover_state; extern omapi_object_type_t *dhcp_type_failover_link; extern omapi_object_type_t *dhcp_type_failover_listener; #endif void dhcp_db_objects_setup (void); isc_result_t dhcp_lease_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t dhcp_lease_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t dhcp_lease_destroy (omapi_object_t *, const char *, int); isc_result_t dhcp_lease_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t dhcp_lease_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_lease_lookup (omapi_object_t **, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_lease_create (omapi_object_t **, omapi_object_t *); isc_result_t dhcp_lease_remove (omapi_object_t *, omapi_object_t *); isc_result_t dhcp_group_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t dhcp_group_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t dhcp_group_destroy (omapi_object_t *, const char *, int); isc_result_t dhcp_group_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t dhcp_group_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_group_lookup (omapi_object_t **, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_group_create (omapi_object_t **, omapi_object_t *); isc_result_t dhcp_group_remove (omapi_object_t *, omapi_object_t *); isc_result_t dhcp_host_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t dhcp_host_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t dhcp_host_destroy (omapi_object_t *, const char *, int); isc_result_t dhcp_host_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t dhcp_host_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_host_lookup (omapi_object_t **, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_host_create (omapi_object_t **, omapi_object_t *); isc_result_t dhcp_host_remove (omapi_object_t *, omapi_object_t *); isc_result_t dhcp_pool_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t dhcp_pool_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t dhcp_pool_destroy (omapi_object_t *, const char *, int); isc_result_t dhcp_pool_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t dhcp_pool_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_pool_lookup (omapi_object_t **, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_pool_create (omapi_object_t **, omapi_object_t *); isc_result_t dhcp_pool_remove (omapi_object_t *, omapi_object_t *); isc_result_t dhcp_class_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t dhcp_class_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t dhcp_class_destroy (omapi_object_t *, const char *, int); isc_result_t dhcp_class_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t dhcp_class_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_class_lookup (omapi_object_t **, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_class_create (omapi_object_t **, omapi_object_t *); isc_result_t dhcp_class_remove (omapi_object_t *, omapi_object_t *); isc_result_t dhcp_subclass_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t dhcp_subclass_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t dhcp_subclass_destroy (omapi_object_t *, const char *, int); isc_result_t dhcp_subclass_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t dhcp_subclass_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_subclass_lookup (omapi_object_t **, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_subclass_create (omapi_object_t **, omapi_object_t *); isc_result_t dhcp_subclass_remove (omapi_object_t *, omapi_object_t *); isc_result_t dhcp_shared_network_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t dhcp_shared_network_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t dhcp_shared_network_destroy (omapi_object_t *, const char *, int); isc_result_t dhcp_shared_network_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t dhcp_shared_network_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_shared_network_lookup (omapi_object_t **, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_shared_network_create (omapi_object_t **, omapi_object_t *); isc_result_t dhcp_subnet_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t dhcp_subnet_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t dhcp_subnet_destroy (omapi_object_t *, const char *, int); isc_result_t dhcp_subnet_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t dhcp_subnet_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_subnet_lookup (omapi_object_t **, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_subnet_create (omapi_object_t **, omapi_object_t *); isc_result_t dhcp_interface_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t dhcp_interface_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t dhcp_interface_destroy (omapi_object_t *, const char *, int); isc_result_t dhcp_interface_signal_handler (omapi_object_t *, const char *, va_list ap); isc_result_t dhcp_interface_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_interface_lookup (omapi_object_t **, omapi_object_t *, omapi_object_t *); isc_result_t dhcp_interface_create (omapi_object_t **, omapi_object_t *); isc_result_t dhcp_interface_remove (omapi_object_t *, omapi_object_t *); void interface_stash (struct interface_info *); void interface_snorf (struct interface_info *, int); isc_result_t binding_scope_set_value (struct binding_scope *, int, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t binding_scope_get_value (omapi_value_t **, struct binding_scope *, omapi_data_string_t *); isc_result_t binding_scope_stuff_values (omapi_object_t *, struct binding_scope *); /* mdb.c */ extern struct subnet *subnets; extern struct shared_network *shared_networks; extern host_hash_t *host_hw_addr_hash; extern host_hash_t *host_uid_hash; extern host_hash_t *host_name_hash; extern lease_hash_t *lease_uid_hash; extern lease_hash_t *lease_ip_addr_hash; extern lease_hash_t *lease_hw_addr_hash; extern omapi_object_type_t *dhcp_type_host; isc_result_t enter_host PROTO ((struct host_decl *, int, int)); isc_result_t delete_host PROTO ((struct host_decl *, int)); int find_hosts_by_haddr PROTO ((struct host_decl **, int, const unsigned char *, unsigned, const char *, int)); int find_hosts_by_uid PROTO ((struct host_decl **, const unsigned char *, unsigned, const char *, int)); int find_host_for_network PROTO ((struct subnet **, struct host_decl **, struct iaddr *, struct shared_network *)); void new_address_range PROTO ((struct parse *, struct iaddr, struct iaddr, struct subnet *, struct pool *, struct lease **)); isc_result_t dhcp_lease_free (omapi_object_t *, const char *, int); isc_result_t dhcp_lease_get (omapi_object_t **, const char *, int); int find_grouped_subnet PROTO ((struct subnet **, struct shared_network *, struct iaddr, const char *, int)); int find_subnet (struct subnet **, struct iaddr, const char *, int); void enter_shared_network PROTO ((struct shared_network *)); void new_shared_network_interface PROTO ((struct parse *, struct shared_network *, const char *)); int subnet_inner_than PROTO ((struct subnet *, struct subnet *, int)); void enter_subnet PROTO ((struct subnet *)); void enter_lease PROTO ((struct lease *)); int supersede_lease PROTO ((struct lease *, struct lease *, int, int, int)); void make_binding_state_transition (struct lease *); int lease_copy PROTO ((struct lease **, struct lease *, const char *, int)); void release_lease PROTO ((struct lease *, struct packet *)); void abandon_lease PROTO ((struct lease *, const char *)); void dissociate_lease PROTO ((struct lease *)); void pool_timer PROTO ((void *)); int find_lease_by_uid PROTO ((struct lease **, const unsigned char *, unsigned, const char *, int)); int find_lease_by_hw_addr PROTO ((struct lease **, const unsigned char *, unsigned, const char *, int)); int find_lease_by_ip_addr PROTO ((struct lease **, struct iaddr, const char *, int)); void uid_hash_add PROTO ((struct lease *)); void uid_hash_delete PROTO ((struct lease *)); void hw_hash_add PROTO ((struct lease *)); void hw_hash_delete PROTO ((struct lease *)); int write_leases PROTO ((void)); int lease_enqueue (struct lease *); void lease_instantiate (const unsigned char *, unsigned, struct lease *); void expire_all_pools PROTO ((void)); void dump_subnets PROTO ((void)); #if defined (DEBUG_MEMORY_LEAKAGE) || \ defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) void free_everything (void); #endif /* nsupdate.c */ char *ddns_rev_name (struct lease *, struct lease_state *, struct packet *); char *ddns_fwd_name (struct lease *, struct lease_state *, struct packet *); int nsupdateA (const char *, const unsigned char *, u_int32_t, int); int nsupdatePTR (const char *, const unsigned char *, u_int32_t, int); void nsupdate (struct lease *, struct lease_state *, struct packet *, int); int updateA (const struct data_string *, const struct data_string *, unsigned int, struct lease *); int updatePTR (const struct data_string *, const struct data_string *, unsigned int, struct lease *); int deleteA (const struct data_string *, const struct data_string *, struct lease *); int deletePTR (const struct data_string *, const struct data_string *, struct lease *); /* failover.c */ #if defined (FAILOVER_PROTOCOL) extern dhcp_failover_state_t *failover_states; void dhcp_failover_startup PROTO ((void)); int dhcp_failover_write_all_states (void); isc_result_t enter_failover_peer PROTO ((dhcp_failover_state_t *)); isc_result_t find_failover_peer PROTO ((dhcp_failover_state_t **, const char *, const char *, int)); isc_result_t dhcp_failover_link_initiate PROTO ((omapi_object_t *)); isc_result_t dhcp_failover_link_signal PROTO ((omapi_object_t *, const char *, va_list)); isc_result_t dhcp_failover_link_set_value PROTO ((omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *)); isc_result_t dhcp_failover_link_get_value PROTO ((omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **)); isc_result_t dhcp_failover_link_destroy PROTO ((omapi_object_t *, const char *, int)); isc_result_t dhcp_failover_link_stuff_values PROTO ((omapi_object_t *, omapi_object_t *, omapi_object_t *)); isc_result_t dhcp_failover_listen PROTO ((omapi_object_t *)); isc_result_t dhcp_failover_listener_signal PROTO ((omapi_object_t *, const char *, va_list)); isc_result_t dhcp_failover_listener_set_value PROTO ((omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *)); isc_result_t dhcp_failover_listener_get_value PROTO ((omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **)); isc_result_t dhcp_failover_listener_destroy PROTO ((omapi_object_t *, const char *, int)); isc_result_t dhcp_failover_listener_stuff PROTO ((omapi_object_t *, omapi_object_t *, omapi_object_t *)); isc_result_t dhcp_failover_register PROTO ((omapi_object_t *)); isc_result_t dhcp_failover_state_signal PROTO ((omapi_object_t *, const char *, va_list)); isc_result_t dhcp_failover_state_transition (dhcp_failover_state_t *, const char *); isc_result_t dhcp_failover_set_service_state (dhcp_failover_state_t *state); isc_result_t dhcp_failover_set_state (dhcp_failover_state_t *, enum failover_state); isc_result_t dhcp_failover_peer_state_changed (dhcp_failover_state_t *, failover_message_t *); int dhcp_failover_pool_rebalance (dhcp_failover_state_t *); int dhcp_failover_pool_check (struct pool *); int dhcp_failover_state_pool_check (dhcp_failover_state_t *); void dhcp_failover_timeout (void *); void dhcp_failover_send_contact (void *); isc_result_t dhcp_failover_send_state (dhcp_failover_state_t *); isc_result_t dhcp_failover_send_updates (dhcp_failover_state_t *); int dhcp_failover_queue_update (struct lease *, int); int dhcp_failover_send_acks (dhcp_failover_state_t *); void dhcp_failover_toack_queue_timeout (void *); int dhcp_failover_queue_ack (dhcp_failover_state_t *, failover_message_t *msg); void dhcp_failover_ack_queue_remove (dhcp_failover_state_t *, struct lease *); isc_result_t dhcp_failover_state_set_value PROTO ((omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *)); void dhcp_failover_keepalive (void *); void dhcp_failover_reconnect (void *); void dhcp_failover_startup_timeout (void *); void dhcp_failover_link_startup_timeout (void *); void dhcp_failover_listener_restart (void *); isc_result_t dhcp_failover_state_get_value PROTO ((omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **)); isc_result_t dhcp_failover_state_destroy PROTO ((omapi_object_t *, const char *, int)); isc_result_t dhcp_failover_state_stuff PROTO ((omapi_object_t *, omapi_object_t *, omapi_object_t *)); isc_result_t dhcp_failover_state_lookup PROTO ((omapi_object_t **, omapi_object_t *, omapi_object_t *)); isc_result_t dhcp_failover_state_create PROTO ((omapi_object_t **, omapi_object_t *)); isc_result_t dhcp_failover_state_remove PROTO ((omapi_object_t *, omapi_object_t *)); int dhcp_failover_state_match (dhcp_failover_state_t *, u_int8_t *, unsigned); const char *dhcp_failover_reject_reason_print (int); const char *dhcp_failover_state_name_print (enum failover_state); const char *dhcp_failover_message_name (unsigned); const char *dhcp_failover_option_name (unsigned); failover_option_t *dhcp_failover_option_printf (unsigned, char *, unsigned *, unsigned, const char *, ...) __attribute__((__format__(__printf__,5,6))); failover_option_t *dhcp_failover_make_option (unsigned, char *, unsigned *, unsigned, ...); isc_result_t dhcp_failover_put_message (dhcp_failover_link_t *, omapi_object_t *, int, ...); isc_result_t dhcp_failover_send_connect PROTO ((omapi_object_t *)); isc_result_t dhcp_failover_send_connectack PROTO ((omapi_object_t *, dhcp_failover_state_t *, int, const char *)); isc_result_t dhcp_failover_send_disconnect PROTO ((omapi_object_t *, int, const char *)); isc_result_t dhcp_failover_send_bind_update (dhcp_failover_state_t *, struct lease *); isc_result_t dhcp_failover_send_bind_ack (dhcp_failover_state_t *, failover_message_t *, int, const char *); isc_result_t dhcp_failover_send_poolreq (dhcp_failover_state_t *); isc_result_t dhcp_failover_send_poolresp (dhcp_failover_state_t *, int); isc_result_t dhcp_failover_send_update_request (dhcp_failover_state_t *); isc_result_t dhcp_failover_send_update_request_all (dhcp_failover_state_t *); isc_result_t dhcp_failover_send_update_done (dhcp_failover_state_t *); isc_result_t dhcp_failover_process_bind_update (dhcp_failover_state_t *, failover_message_t *); isc_result_t dhcp_failover_process_bind_ack (dhcp_failover_state_t *, failover_message_t *); isc_result_t dhcp_failover_generate_update_queue (dhcp_failover_state_t *, int); isc_result_t dhcp_failover_process_update_request (dhcp_failover_state_t *, failover_message_t *); isc_result_t dhcp_failover_process_update_request_all (dhcp_failover_state_t *, failover_message_t *); isc_result_t dhcp_failover_process_update_done (dhcp_failover_state_t *, failover_message_t *); void dhcp_failover_recover_done (void *); void failover_print PROTO ((char *, unsigned *, unsigned, const char *)); void update_partner PROTO ((struct lease *)); int load_balance_mine (struct packet *, dhcp_failover_state_t *); binding_state_t normal_binding_state_transition_check (struct lease *, dhcp_failover_state_t *, binding_state_t, u_int32_t); binding_state_t conflict_binding_state_transition_check (struct lease *, dhcp_failover_state_t *, binding_state_t, u_int32_t); int lease_mine_to_reallocate (struct lease *); OMAPI_OBJECT_ALLOC_DECL (dhcp_failover_state, dhcp_failover_state_t, dhcp_type_failover_state) OMAPI_OBJECT_ALLOC_DECL (dhcp_failover_listener, dhcp_failover_listener_t, dhcp_type_failover_listener) OMAPI_OBJECT_ALLOC_DECL (dhcp_failover_link, dhcp_failover_link_t, dhcp_type_failover_link) #endif /* FAILOVER_PROTOCOL */ const char *binding_state_print (enum failover_state); Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/dhctoken.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/dhctoken.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/dhctoken.h (revision 131136) @@ -1,325 +1,316 @@ /* dhctoken.h Tokens for config file lexer and parser. */ /* - * Copyright (c) 1996-2002 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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''. */ enum dhcp_token { SEMI = ';', DOT = '.', COLON = ':', COMMA = ',', SLASH = '/', LBRACE = '{', RBRACE = '}', LPAREN = '(', RPAREN = ')', EQUAL = '=', BANG = '!', PERCENT = '%', PLUS = '+', MINUS = '-', ASTERISK = '*', AMPERSAND = '&', PIPE = '|', CARET = '^', HOST = 256, FIRST_TOKEN = HOST, HARDWARE = 257, FILENAME = 258, FIXED_ADDR = 259, OPTION = 260, ETHERNET = 261, STRING = 262, NUMBER = 263, NUMBER_OR_NAME = 264, NAME = 265, TIMESTAMP = 266, STARTS = 267, ENDS = 268, UID = 269, CLASS = 270, LEASE = 271, RANGE = 272, PACKET = 273, CIADDR = 274, YIADDR = 275, SIADDR = 276, GIADDR = 277, SUBNET = 278, NETMASK = 279, DEFAULT_LEASE_TIME = 280, MAX_LEASE_TIME = 281, VENDOR_CLASS = 282, USER_CLASS = 283, SHARED_NETWORK = 284, SERVER_NAME = 285, DYNAMIC_BOOTP = 286, SERVER_IDENTIFIER = 287, DYNAMIC_BOOTP_LEASE_CUTOFF = 288, DYNAMIC_BOOTP_LEASE_LENGTH = 289, BOOT_UNKNOWN_CLIENTS = 290, NEXT_SERVER = 291, TOKEN_RING = 292, GROUP = 293, ONE_LEASE_PER_CLIENT = 294, GET_LEASE_HOSTNAMES = 295, USE_HOST_DECL_NAMES = 296, SEND = 297, CLIENT_IDENTIFIER = 298, REQUEST = 299, REQUIRE = 300, TIMEOUT = 301, RETRY = 302, SELECT_TIMEOUT = 303, SCRIPT = 304, INTERFACE = 305, RENEW = 306, REBIND = 307, EXPIRE = 308, UNKNOWN_CLIENTS = 309, ALLOW = 310, DENY = 312, BOOTING = 313, DEFAULT = 314, MEDIA = 315, MEDIUM = 316, ALIAS = 317, REBOOT = 318, TOKEN_ABANDONED = 319, BACKOFF_CUTOFF = 320, INITIAL_INTERVAL = 321, NAMESERVER = 322, DOMAIN = 323, SEARCH = 324, SUPERSEDE = 325, APPEND = 326, PREPEND = 327, HOSTNAME = 328, CLIENT_HOSTNAME = 329, REJECT = 330, USE_LEASE_ADDR_FOR_DEFAULT_ROUTE = 331, MIN_LEASE_TIME = 332, MIN_SECS = 333, AND = 334, OR = 335, SUBSTRING = 337, SUFFIX = 338, CHECK = 339, EXTRACT_INT = 340, IF = 341, TOKEN_ADD = 342, BREAK = 343, ELSE = 344, ELSIF = 345, SUBCLASS = 346, MATCH = 347, SPAWN = 348, WITH = 349, EXISTS = 350, POOL = 351, UNKNOWN = 352, CLIENTS = 353, KNOWN = 354, AUTHENTICATED = 355, UNAUTHENTICATED = 356, ALL = 357, DYNAMIC = 358, MEMBERS = 359, OF = 360, PSEUDO = 361, LIMIT = 362, BILLING = 363, PEER = 364, FAILOVER = 365, MY = 366, PARTNER = 367, PRIMARY = 368, SECONDARY = 369, IDENTIFIER = 370, PORT = 371, MAX_TRANSMIT_IDLE = 372, MAX_RESPONSE_DELAY = 373, PARTNER_DOWN = 374, NORMAL = 375, COMMUNICATIONS_INTERRUPTED = 376, POTENTIAL_CONFLICT = 377, RECOVER = 378, FDDI = 379, AUTHORITATIVE = 380, TOKEN_NOT = 381, AUTHENTICATION = 383, IGNORE = 384, ACCEPT = 385, PREFER = 386, DONT = 387, CODE = 388, ARRAY = 389, BOOLEAN = 390, INTEGER = 391, SIGNED = 392, UNSIGNED = 393, IP_ADDRESS = 394, TEXT = 395, STRING_TOKEN = 396, SPACE = 397, CONCAT = 398, ENCODE_INT = 399, REVERSE = 402, LEASED_ADDRESS = 403, BINARY_TO_ASCII = 404, PICK = 405, CONFIG_OPTION = 406, HOST_DECL_NAME = 407, ON = 408, EXPIRY = 409, RELEASE = 410, COMMIT = 411, DNS_UPDATE = 412, LEASE_TIME = 413, STATIC = 414, NEVER = 415, INFINITE = 416, TOKEN_DELETED = 417, UPDATED_DNS_RR = 418, DNS_DELETE = 419, DUPLICATES = 420, DECLINES = 421, TSTP = 422, TSFP = 423, OWNER = 424, IS = 425, HBA = 426, MAX_UNACKED_UPDATES = 427, MCLT = 428, SPLIT = 429, AT = 430, NO = 431, TOKEN_DELETE = 432, NS_UPDATE = 433, UPDATE = 434, SWITCH = 435, CASE = 436, NS_FORMERR = 437, NS_NOERROR = 438, NS_NOTAUTH = 439, NS_NOTIMP = 440, NS_NOTZONE = 441, NS_NXDOMAIN = 442, NS_NXRRSET = 443, NS_REFUSED = 444, NS_SERVFAIL = 445, NS_YXDOMAIN = 446, NS_YXRRSET = 447, TOKEN_NULL = 448, TOKEN_SET = 449, DEFINED = 450, UNSET = 451, EVAL = 452, LET = 453, FUNCTION = 454, DEFINE = 455, ZONE = 456, KEY = 457, SECRET = 458, ALGORITHM = 459, LOAD = 460, BALANCE = 461, TOKEN_MAX = 462, SECONDS = 463, ADDRESS = 464, RESOLUTION_INTERRUPTED = 465, STATE = 466, UNKNOWN_STATE = 567, CLTT = 568, INCLUDE = 569, BINDING = 570, TOKEN_FREE = 571, TOKEN_ACTIVE = 572, TOKEN_EXPIRED = 573, TOKEN_RELEASED = 574, TOKEN_RESET = 575, TOKEN_BACKUP = 576, TOKEN_RESERVED = 577, TOKEN_BOOTP = 578, TOKEN_NEXT = 579, OMAPI = 580, LOG = 581, FATAL = 582, ERROR = 583, TOKEN_DEBUG = 584, INFO = 585, RETURN = 586, PAUSED = 587, RECOVER_DONE = 588, SHUTDOWN = 589, STARTUP = 590, ENCAPSULATE = 591, VENDOR = 592, CLIENT_STATE = 593, INIT_REBOOT = 594, TOKEN_INIT = 595, SELECT = 596, BOUND = 597, RENEWING = 598, REBINDING = 599, RECONTACT_INTERVAL = 600, CLIENT_UPDATES = 601, TOKEN_NEW = 601, TRANSMISSION = 602, TOKEN_CLOSE = 603, TOKEN_CREATE = 604, TOKEN_OPEN = 605, TOKEN_HELP = 606, END_OF_FILE = 607, RECOVER_WAIT = 608, SERVER = 609, CONNECT = 610, REMOVE = 611, REFRESH = 612, DOMAIN_NAME = 613, DO_FORWARD_UPDATE = 614 }; #define is_identifier(x) ((x) >= FIRST_TOKEN && \ (x) != STRING && \ (x) != NUMBER && \ (x) != END_OF_FILE) Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/failover.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/failover.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/failover.h (revision 131136) @@ -1,322 +1,313 @@ /* failover.h Definitions for address trees... */ /* - * Copyright (c) 2000-2001 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2000-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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''. */ #if defined (FAILOVER_PROTOCOL) struct failover_option_info { int code; const char *name; enum { FT_UINT8, FT_IPADDR, FT_UINT32, FT_BYTES, FT_TEXT_OR_BYTES, FT_DDNS, FT_DDNS1, FT_UINT16, FT_TEXT, FT_UNDEF, FT_DIGEST } type; int num_present; int offset; u_int32_t bit; }; typedef struct { unsigned count; u_int8_t *data; } failover_option_t; #define FM_OFFSET(x) (long)(&(((failover_message_t *)0) -> x)) /* Failover message options: */ #define FTO_BINDING_STATUS 1 #define FTB_BINDING_STATUS 0x00000002 #define FTO_ASSIGNED_IP_ADDRESS 2 #define FTB_ASSIGNED_IP_ADDRESS 0x00000004 #define FTO_SERVER_ADDR 3 #define FTB_SERVER_ADDR 0x00000008 #define FTO_ADDRESSES_TRANSFERRED 4 #define FTB_ADDRESSES_TRANSFERRED 0x00000010 #define FTO_CLIENT_IDENTIFIER 5 #define FTB_CLIENT_IDENTIFIER 0x00000020 #define FTO_CHADDR 6 #define FTB_CHADDR 0x00000040 #define FTO_DDNS 7 #define FTB_DDNS 0x00000080 #define FTO_REJECT_REASON 8 #define FTB_REJECT_REASON 0x00000100 #define FTO_MESSAGE 9 #define FTB_MESSAGE 0x00000200 #define FTO_MCLT 10 #define FTB_MCLT 0x00000400 #define FTO_VENDOR_CLASS 11 #define FTB_VENDOR_CLASS 0x00000800 #define FTO_LEASE_EXPIRY 13 #define FTB_LEASE_EXPIRY 0x00002000 #define FTO_POTENTIAL_EXPIRY 14 #define FTB_POTENTIAL_EXPIRY 0x00004000 #define FTO_GRACE_EXPIRY 15 #define FTB_GRACE_EXPIRY 0x00008000 #define FTO_CLTT 16 #define FTB_CLTT 0x00010000 #define FTO_STOS 17 #define FTB_STOS 0x00020000 #define FTO_SERVER_STATE 18 #define FTB_SERVER_STATE 0x00040000 #define FTO_SERVER_FLAGS 19 #define FTB_SERVER_FLAGS 0x00080000 #define FTO_VENDOR_OPTIONS 20 #define FTB_VENDOR_OPTIONS 0x00100000 #define FTO_MAX_UNACKED 21 #define FTB_MAX_UNACKED 0x00200000 #define FTO_RECEIVE_TIMER 23 #define FTB_RECEIVE_TIMER 0x00800000 #define FTO_HBA 24 #define FTB_HBA 0x01000000 #define FTO_MESSAGE_DIGEST 25 #define FTB_MESSAGE_DIGEST 0x02000000 #define FTO_PROTOCOL_VERSION 26 #define FTB_PROTOCOL_VERSION 0x04000000 #define FTO_TLS_REQUEST 27 #define FTB_TLS_REQUEST 0x08000000 #define FTO_TLS_REPLY 28 #define FTB_TLS_REPLY 0x10000000 #define FTO_REQUEST_OPTIONS 29 #define FTB_REQUEST_OPTIONS 0x20000000 #define FTO_REPLY_OPTIONS 30 #define FTB_REPLY_OPTIONS 0x40000000 #define FTO_MAX FTO_REPLY_OPTIONS /* Failover protocol message types: */ #define FTM_POOLREQ 1 #define FTM_POOLRESP 2 #define FTM_BNDUPD 3 #define FTM_BNDACK 4 #define FTM_CONNECT 5 #define FTM_CONNECTACK 6 #define FTM_UPDREQ 7 #define FTM_UPDDONE 8 #define FTM_UPDREQALL 9 #define FTM_STATE 10 #define FTM_CONTACT 11 #define FTM_DISCONNECT 12 /* Reject reasons: */ #define FTR_ILLEGAL_IP_ADDR 1 #define FTR_FATAL_CONFLICT 2 #define FTR_MISSING_BINDINFO 3 #define FTR_TIMEMISMATCH 4 #define FTR_INVALID_MCLT 5 #define FTR_MISC_REJECT 6 #define FTR_DUP_CONNECTION 7 #define FTR_INVALID_PARTNER 8 #define FTR_TLS_UNSUPPORTED 9 #define FTR_TLS_UNCONFIGURED 10 #define FTR_TLS_REQUIRED 11 #define FTR_DIGEST_UNSUPPORTED 12 #define FTR_DIGEST_UNCONFIGURED 13 #define FTR_VERSION_MISMATCH 14 #define FTR_MISSING_BIND_INFO 15 #define FTR_OUTDATED_BIND_INFO 16 #define FTR_LESS_CRIT_BIND_INFO 17 #define FTR_NO_TRAFFIC 18 #define FTR_HBA_CONFLICT 19 #define FTR_UNKNOWN 254 #define DHCP_FAILOVER_MAX_MESSAGE_SIZE 2048 /* Failover server flags. */ #define FTF_STARTUP 1 typedef struct failover_message { int refcnt; struct failover_message *next; u_int8_t type; u_int8_t binding_status; u_int8_t protocol_version; u_int8_t reject_reason; u_int8_t server_flags; u_int8_t server_state; u_int8_t tls_reply; u_int8_t tls_request; u_int32_t stos; u_int32_t time; u_int32_t xid; u_int32_t addresses_transferred; u_int32_t assigned_addr; u_int32_t client_ltt; u_int32_t expiry; u_int32_t grace_expiry; u_int32_t max_unacked; u_int32_t mclt; u_int32_t potential_expiry; u_int32_t receive_timer; u_int32_t server_addr; failover_option_t chaddr; failover_option_t client_identifier; failover_option_t hba; failover_option_t message; failover_option_t reply_options; failover_option_t request_options; ddns_fqdn_t ddns; failover_option_t vendor_class; failover_option_t vendor_options; int options_present; } failover_message_t; typedef struct { OMAPI_OBJECT_PREAMBLE; struct option_cache *peer_address; unsigned peer_port; int options_present; enum dhcp_flink_state { dhcp_flink_start, dhcp_flink_message_length_wait, dhcp_flink_message_wait, dhcp_flink_disconnected, dhcp_flink_state_max } state; failover_message_t *imsg; struct _dhcp_failover_state *state_object; u_int16_t imsg_len; unsigned imsg_count; u_int8_t imsg_payoff; /* Pay*load* offset. :') */ u_int32_t xid; } dhcp_failover_link_t; typedef struct _dhcp_failover_listener { OMAPI_OBJECT_PREAMBLE; struct _dhcp_failover_listener *next; omapi_addr_t address; } dhcp_failover_listener_t; #endif /* FAILOVER_PROTOCOL */ /* A failover peer. */ enum failover_state { unknown_state, partner_down, normal, communications_interrupted, resolution_interrupted, potential_conflict, recover, recover_done, shut_down, paused, startup, recover_wait }; /* Service states are simplifications of failover states, particularly useful because the startup state isn't actually implementable as a seperate failover state without maintaining a state stack. */ enum service_state { unknown_service_state, cooperating, not_cooperating, service_partner_down, not_responding, service_startup }; #if defined (FAILOVER_PROTOCOL) typedef struct _dhcp_failover_config { struct option_cache *address; int port; u_int32_t max_flying_updates; enum failover_state state; TIME stos; u_int32_t max_response_delay; } dhcp_failover_config_t; typedef struct _dhcp_failover_state { OMAPI_OBJECT_PREAMBLE; struct _dhcp_failover_state *next; char *name; /* Name of this failover instance. */ dhcp_failover_config_t me; /* My configuration. */ dhcp_failover_config_t partner; /* Partner's configuration. */ enum failover_state saved_state; /* Saved state during startup. */ struct data_string server_identifier; /* Server identifier (IP addr) */ u_int32_t mclt; u_int8_t *hba; /* Hash bucket array for load balancing. */ int load_balance_max_secs; enum service_state service_state; const char *nrr; /* Printable reason why we're in the not_responding service state (empty string if we are responding. */ dhcp_failover_link_t *link_to_peer; /* Currently-established link to peer. */ enum { primary, secondary } i_am; /* We are primary or secondary in this relationship. */ TIME last_packet_sent; /* Timestamp on last packet we sent. */ TIME last_timestamp_received; /* The last timestamp we sent that has been returned by our partner. */ TIME skew; /* The skew between our clock and our partner's. */ struct lease *update_queue_head; /* List of leases we haven't sent to peer. */ struct lease *update_queue_tail; struct lease *ack_queue_head; /* List of lease updates the peer hasn't yet acked. */ struct lease *ack_queue_tail; struct lease *send_update_done; /* When we get a BNDACK for this lease, send an UPDDONE message. */ int cur_unacked_updates; /* Number of updates we've sent that have not yet been acked. */ /* List of messages which we haven't acked yet. */ failover_message_t *toack_queue_head; failover_message_t *toack_queue_tail; int pending_acks; /* Number of messages in the toack queue. */ int pool_count; /* Number of pools referencing this failover state object. */ } dhcp_failover_state_t; #define DHCP_FAILOVER_VERSION 1 #endif /* FAILOVER_PROTOCOL */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/inet.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/inet.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/inet.h (revision 131136) @@ -1,54 +1,45 @@ /* inet.h Portable definitions for internet addresses */ /* - * Copyright (c) 1996-1999 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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''. */ /* An internet address of up to 128 bits. */ struct iaddr { unsigned len; unsigned char iabuf [16]; }; struct iaddrlist { struct iaddrlist *next; struct iaddr addr; }; Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/isc-dhcp/boolean.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/isc-dhcp/boolean.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/isc-dhcp/boolean.h (revision 131136) @@ -1,32 +1,38 @@ /* - * Copyright (C) 1998, 1999 Internet Software Consortium. - * + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1998-2003 by Internet Software Consortium + * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ */ #ifndef ISC_BOOLEAN_H #define ISC_BOOLEAN_H 1 #include ISC_LANG_BEGINDECLS typedef enum { isc_boolean_false = 0, isc_boolean_true = 1 } isc_boolean_t; #define ISC_FALSE isc_boolean_false #define ISC_TRUE isc_boolean_true ISC_LANG_ENDDECLS #endif /* ISC_BOOLEAN_H */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/isc-dhcp/int.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/isc-dhcp/int.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/isc-dhcp/int.h (revision 131136) @@ -1,36 +1,42 @@ /* - * Copyright (C) 1999 Internet Software Consortium. - * + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999-2003 by Internet Software Consortium + * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ */ #ifndef ISC_INT_H #define ISC_INT_H 1 #include ISC_LANG_BEGINDECLS typedef char isc_int8_t; typedef unsigned char isc_uint8_t; typedef short isc_int16_t; typedef unsigned short isc_uint16_t; typedef int isc_int32_t; typedef unsigned int isc_uint32_t; typedef long long isc_int64_t; typedef unsigned long long isc_uint64_t; ISC_LANG_ENDDECLS #endif /* ISC_INT_H */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/isc-dhcp/lang.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/isc-dhcp/lang.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/isc-dhcp/lang.h (revision 131136) @@ -1,29 +1,35 @@ /* - * Copyright (C) 1999 Internet Software Consortium. - * + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999-2003 by Internet Software Consortium + * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ */ #ifndef ISC_LANG_H #define ISC_LANG_H 1 #ifdef __cplusplus #define ISC_LANG_BEGINDECLS extern "C" { #define ISC_LANG_ENDDECLS } #else #define ISC_LANG_BEGINDECLS #define ISC_LANG_ENDDECLS #endif #endif /* ISC_LANG_H */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/isc-dhcp/list.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/isc-dhcp/list.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/isc-dhcp/list.h (revision 131136) @@ -1,116 +1,122 @@ /* - * Copyright (C) 1997, 1999 Internet Software Consortium. - * + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1997-2003 by Internet Software Consortium + * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ */ #ifndef ISC_LIST_H #define ISC_LIST_H 1 #define ISC_LIST(type) struct { type *head, *tail; } #define ISC_LIST_INIT(list) \ do { (list).head = NULL; (list).tail = NULL; } while (0) #define ISC_LINK(type) struct { type *prev, *next; } #define ISC_LINK_INIT(elt, link) \ do { \ (elt)->link.prev = (void *)(-1); \ (elt)->link.next = (void *)(-1); \ } while (0) #define ISC_LINK_LINKED(elt, link) ((elt)->link.prev != (void *)(-1)) #define ISC_LIST_HEAD(list) ((list).head) #define ISC_LIST_TAIL(list) ((list).tail) #define ISC_LIST_EMPTY(list) ((list).head == NULL) #define ISC_LIST_PREPEND(list, elt, link) \ do { \ if ((list).head != NULL) \ (list).head->link.prev = (elt); \ else \ (list).tail = (elt); \ (elt)->link.prev = NULL; \ (elt)->link.next = (list).head; \ (list).head = (elt); \ } while (0) #define ISC_LIST_APPEND(list, elt, link) \ do { \ if ((list).tail != NULL) \ (list).tail->link.next = (elt); \ else \ (list).head = (elt); \ (elt)->link.prev = (list).tail; \ (elt)->link.next = NULL; \ (list).tail = (elt); \ } while (0) #define ISC_LIST_UNLINK(list, elt, link) \ do { \ if ((elt)->link.next != NULL) \ (elt)->link.next->link.prev = (elt)->link.prev; \ else \ (list).tail = (elt)->link.prev; \ if ((elt)->link.prev != NULL) \ (elt)->link.prev->link.next = (elt)->link.next; \ else \ (list).head = (elt)->link.next; \ (elt)->link.prev = (void *)(-1); \ (elt)->link.next = (void *)(-1); \ } while (0) #define ISC_LIST_PREV(elt, link) ((elt)->link.prev) #define ISC_LIST_NEXT(elt, link) ((elt)->link.next) #define ISC_LIST_INSERTBEFORE(list, before, elt, link) \ do { \ if ((before)->link.prev == NULL) \ ISC_LIST_PREPEND(list, elt, link); \ else { \ (elt)->link.prev = (before)->link.prev; \ (before)->link.prev = (elt); \ (elt)->link.prev->link.next = (elt); \ (elt)->link.next = (before); \ } \ } while (0) #define ISC_LIST_INSERTAFTER(list, after, elt, link) \ do { \ if ((after)->link.next == NULL) \ ISC_LIST_APPEND(list, elt, link); \ else { \ (elt)->link.next = (after)->link.next; \ (after)->link.next = (elt); \ (elt)->link.next->link.prev = (elt); \ (elt)->link.prev = (after); \ } \ } while (0) #define ISC_LIST_APPENDLIST(list1, list2, link) \ do { \ if (ISC_LIST_EMPTY(list1)) \ (list1) = (list2); \ else if (!ISC_LIST_EMPTY(list2)) { \ (list1).tail->link.next = (list2).head; \ (list2).head->link.prev = (list1).tail; \ (list1).tail = (list2).tail; \ (list2).head = NULL; \ (list2).tail = NULL; \ } \ } while (0) #define ISC_LIST_ENQUEUE(list, elt, link) ISC_LIST_APPEND(list, elt, link) #define ISC_LIST_DEQUEUE(list, elt, link) ISC_LIST_UNLINK(list, elt, link) #endif /* ISC_LIST_H */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/isc-dhcp/result.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/isc-dhcp/result.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/isc-dhcp/result.h (revision 131136) @@ -1,113 +1,119 @@ /* - * Copyright (C) 1998, 1999 Internet Software Consortium. - * + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1998-2003 by Internet Software Consortium + * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ */ #ifndef ISC_RESULT_H #define ISC_RESULT_H 1 #include #include #include #include ISC_LANG_BEGINDECLS typedef enum { ISC_R_SUCCESS = 0, ISC_R_NOMEMORY = 1, ISC_R_TIMEDOUT = 2, ISC_R_NOTHREADS = 3, ISC_R_ADDRNOTAVAIL = 4, ISC_R_ADDRINUSE = 5, ISC_R_NOPERM = 6, ISC_R_NOCONN = 7, ISC_R_NETUNREACH = 8, ISC_R_HOSTUNREACH = 9, ISC_R_NETDOWN = 10, ISC_R_HOSTDOWN = 11, ISC_R_CONNREFUSED = 12, ISC_R_NORESOURCES = 13, ISC_R_EOF = 14, ISC_R_BOUND = 15, ISC_R_TASKDONE = 16, ISC_R_LOCKBUSY = 17, ISC_R_EXISTS = 18, ISC_R_NOSPACE = 19, ISC_R_CANCELED = 20, ISC_R_TASKNOSEND = 21, ISC_R_SHUTTINGDOWN = 22, ISC_R_NOTFOUND = 23, ISC_R_UNEXPECTEDEND = 24, ISC_R_FAILURE = 25, ISC_R_IOERROR = 26, ISC_R_NOTIMPLEMENTED = 27, ISC_R_UNBALANCED = 28, ISC_R_NOMORE = 29, ISC_R_INVALIDFILE = 30, ISC_R_BADBASE64 = 31, ISC_R_UNEXPECTEDTOKEN = 32, ISC_R_QUOTA = 33, ISC_R_UNEXPECTED = 34, ISC_R_ALREADYRUNNING = 35, ISC_R_HOSTUNKNOWN = 36, ISC_R_VERSIONMISMATCH = 37, ISC_R_PROTOCOLERROR = 38, ISC_R_INVALIDARG = 39, ISC_R_NOTCONNECTED = 40, ISC_R_NOTYET = 41, ISC_R_UNCHANGED = 42, ISC_R_MULTIPLE = 43, ISC_R_KEYCONFLICT = 44, ISC_R_BADPARSE = 45, ISC_R_NOKEYS = 46, ISC_R_KEY_UNKNOWN = 47, ISC_R_INVALIDKEY = 48, ISC_R_INCOMPLETE = 49, ISC_R_FORMERR = 50, ISC_R_SERVFAIL = 51, ISC_R_NXDOMAIN = 52, ISC_R_NOTIMPL = 53, ISC_R_REFUSED = 54, ISC_R_YXDOMAIN = 55, ISC_R_YXRRSET = 56, ISC_R_NXRRSET = 57, ISC_R_NOTAUTH = 58, ISC_R_NOTZONE = 59, ISC_R_BADSIG = 60, ISC_R_BADKEY = 61, ISC_R_BADTIME = 62, ISC_R_NOROOTZONE = 63, ISC_R_DESTADDRREQ = 64, ISC_R_CROSSZONE = 65, ISC_R_NO_TSIG = 66, ISC_R_NOT_EQUAL = 67, ISC_R_CONNRESET = 68, ISC_R_UNKNOWNATTRIBUTE = 69 } isc_result_t; #define ISC_R_NRESULTS 70 /* Number of results */ const char * isc_result_totext(isc_result_t); isc_result_t isc_result_register(unsigned int base, unsigned int nresults, char **text, isc_msgcat_t *msgcat, int set); ISC_LANG_ENDDECLS #endif /* ISC_RESULT_H */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/isc-dhcp/types.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/isc-dhcp/types.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/isc-dhcp/types.h (revision 131136) @@ -1,40 +1,46 @@ /* - * Copyright (C) 1999 Internet Software Consortium. - * + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999-2003 by Internet Software Consortium + * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ */ #ifndef ISC_TYPES_H #define ISC_TYPES_H 1 #include #include #include /*** *** Core Types. ***/ typedef struct isc_mem isc_mem_t; typedef struct isc_mempool isc_mempool_t; typedef struct isc_msgcat isc_msgcat_t; typedef unsigned int isc_eventtype_t; typedef struct isc_event isc_event_t; typedef struct isc_task isc_task_t; typedef struct isc_taskmgr isc_taskmgr_t; typedef struct isc_rwlock isc_rwlock_t; typedef void (*isc_taskaction_t)(isc_task_t *, isc_event_t *); #endif /* ISC_TYPES_H */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/minires/minires.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/minires/minires.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/minires/minires.h (revision 131136) @@ -1,224 +1,230 @@ /* - * Copyright (c) 2001 by Internet Software Consortium. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2001-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ */ #include "cdefs.h" #include "osdep.h" #define _ns_flagdata MR_ns_flagdata #include "minires/resolv.h" #include "minires/res_update.h" #include "isc-dhcp/result.h" /* * Based on the Dynamic DNS reference implementation by Viraj Bais * */ int minires_mkupdate (ns_updrec *, unsigned char *, unsigned); int minires_update (ns_updrec *); ns_updrec *minires_mkupdrec (int, const char *, unsigned int, unsigned int, unsigned long); void minires_freeupdrec (ns_updrec *); int minires_nmkupdate (res_state, ns_updrec *, double *, unsigned *); isc_result_t minires_nupdate (res_state, ns_updrec *); int minires_ninit (res_state); ns_rcode isc_rcode_to_ns (isc_result_t); #if defined (MINIRES_LIB) #define res_update minires_update #define res_mkupdate minires_mkupdate #define res_mkupdrec minires_mkupdrec #define res_freeupdrec minires_freeupdrec #define res_nmkupdate minires_nmkupdate #define res_nupdate minires_nupdate #define __p_type_syms MR__p_type_syms #define dn_comp MRdn_comp #define loc_aton MRloc_aton #define sym_ston MRsym_ston #define res_buildservicelist MRres_buildservicelist #define res_destroyservicelist MRres_destroyservicelist #define res_buildprotolist MRres_buildprotolist #define res_destroyprotolist MRres_destroyprotolist #define res_servicenumber MRres_servicenumber #define res_protocolnumber MRres_protocolnumber #define res_protocolname MRres_protocolname #define res_servicename MRres_servicename #define ns_datetosecs MRns_datetosecs #define b64_pton MRb64_pton #define res_ninit minires_ninit #define res_randomid MRres_randomid #define res_findzonecut MRres_findzonecut #define res_nsend MRres_nsend #define res_nsendsigned MRres_nsendsigned #define ns_samename MRns_samename #define res_nameinquery MRres_nameinquery #define res_queriesmatch MRres_queriesmatch #define dn_expand MRdn_expand #define ns_get16 MRns_get16 #define res_close MRres_close #define res_nclose MRres_nclose #define res_ourserver_p MRres_ourserver_p #define ns_sign MRns_sign #define p_class MRp_class #define p_section MRp_section #define ns_makecanon MRns_makecanon #define ns_parserr MRns_parserr #define ns_samedomain MRns_samedomain #define ns_name_uncompress MRns_name_uncompress #define res_nmkquery MRres_nmkquery #define ns_initparse MRns_initparse #define res_nquery MRres_nquery #define res_nsearch MRres_nsearch #define res_hostalias MRres_hostalias #define res_nquerydomain MRres_nquerydomain #define ns_skiprr MRns_skiprr #define dn_skipname MRdn_skipname #define ns_name_ntol MRns_name_ntol #define ns_sign_tcp_init MRns_sign_tcp_init #define ns_sign_tcp MRns_sign_tcp #define ns_name_ntop MRns_name_ntop #define ns_name_pton MRns_name_pton #define ns_name_unpack MRns_name_unpack #define ns_name_pack MRns_name_pack #define ns_name_compress MRns_name_compress #define ns_name_skip MRns_name_skip #define ns_subdomain MRns_subdomain #define ns_find_tsig MRns_find_tsig #define ns_verify MRns_verify #define ns_verify_tcp_init MRns_verify_tcp_init #define ns_verify_tcp MRns_verify_tcp #define b64_ntop MRb64_ntop extern const struct res_sym __p_type_syms[]; extern time_t cur_time; int dn_comp (const char *, unsigned char *, unsigned, unsigned char **, unsigned char **); int loc_aton (const char *, u_char *); int sym_ston (const struct res_sym *, const char *, int *); void res_buildservicelist (void); void res_destroyservicelist (void); void res_buildprotolist(void); void res_destroyprotolist(void); int res_servicenumber(const char *); int res_protocolnumber(const char *); const char *res_protocolname(int); const char *res_servicename(u_int16_t, const char *); u_int32_t ns_datetosecs (const char *cp, int *errp); int b64_pton (char const *, unsigned char *, size_t); unsigned int res_randomid (void); isc_result_t res_findzonecut (res_state, const char *, ns_class, int, char *, size_t, struct in_addr *, int, int *, void *); isc_result_t res_nsend (res_state, double *, unsigned, double *, unsigned, unsigned *); isc_result_t res_nsendsigned (res_state, double *, unsigned, ns_tsig_key *, double *, unsigned, unsigned *); int ns_samename (const char *, const char *); int res_nameinquery (const char *, int, int, const unsigned char *, const unsigned char *); int res_queriesmatch (const unsigned char *, const unsigned char *, const unsigned char *, const unsigned char *); int dn_expand (const unsigned char *, const unsigned char *, const unsigned char *, char *, unsigned); unsigned int ns_get16 (const unsigned char *); void res_close (void); void res_nclose (res_state); int res_ourserver_p (const res_state, const struct sockaddr_in *); isc_result_t ns_sign (unsigned char *, unsigned *, unsigned, int, void *, const unsigned char *, unsigned, unsigned char *, unsigned *, time_t); const char *p_class (int); const char *p_section (int section, int opcode); isc_result_t ns_makecanon (const char *, char *, size_t); isc_result_t ns_parserr (ns_msg *, ns_sect, int, ns_rr *); int ns_samedomain (const char *, const char *); int ns_name_uncompress (const u_char *, const u_char *, const u_char *, char *, size_t); isc_result_t res_nmkquery (res_state, int, const char *, ns_class, ns_type, const unsigned char *, unsigned, const unsigned char *, double *, unsigned, unsigned *); isc_result_t ns_initparse (const unsigned char *, unsigned, ns_msg *); isc_result_t res_nquery(res_state, const char *, ns_class, ns_type, double *, unsigned, unsigned *); isc_result_t res_nsearch(res_state, const char *, ns_class, ns_type, double *, unsigned, unsigned *); const char *res_hostalias (const res_state, const char *, char *, size_t); isc_result_t res_nquerydomain(res_state, const char *, const char *, ns_class class, ns_type type, double *, unsigned, unsigned *); isc_result_t ns_skiprr(const unsigned char *, const unsigned char *, ns_sect, int, int *); int dn_skipname (const unsigned char *, const unsigned char *); u_int32_t getULong (const unsigned char *); int32_t getLong (const unsigned char *); u_int32_t getUShort (const unsigned char *); int32_t getShort (const unsigned char *); u_int32_t getUChar (const unsigned char *); void putULong (unsigned char *, u_int32_t); void putLong (unsigned char *, int32_t); void putUShort (unsigned char *, u_int32_t); void putShort (unsigned char *, int32_t); void putUChar (unsigned char *, u_int32_t); int ns_name_ntol (const unsigned char *, unsigned char *, size_t); isc_result_t ns_sign_tcp_init (void *, const unsigned char *, unsigned, ns_tcp_tsig_state *); isc_result_t ns_sign_tcp (unsigned char *, unsigned *, unsigned, int, ns_tcp_tsig_state *, int); int ns_name_ntop (const unsigned char *, char *, size_t); int ns_name_pton (const char *, unsigned char *, size_t); int ns_name_unpack (const unsigned char *, const unsigned char *, const unsigned char *, unsigned char *, size_t); int ns_name_pack (const unsigned char *, unsigned char *, unsigned, const unsigned char **, const unsigned char **); int ns_name_compress (const char *, unsigned char *, size_t, const unsigned char **, const unsigned char **); int ns_name_skip (const unsigned char **, const unsigned char *); int ns_subdomain (const char *, const char *); unsigned char *ns_find_tsig (unsigned char *, unsigned char *); isc_result_t ns_verify (unsigned char *, unsigned *, void *, const unsigned char *, unsigned, unsigned char *, unsigned *, time_t *, int); isc_result_t ns_verify_tcp_init (void *, const unsigned char *, unsigned, ns_tcp_tsig_state *); isc_result_t ns_verify_tcp (unsigned char *, unsigned *, ns_tcp_tsig_state *, int); int b64_ntop (unsigned char const *, size_t, char *, size_t); ns_rcode find_cached_zone (const char *, ns_class, char *, size_t, struct in_addr *, int, int *, void *); int find_tsig_key (ns_tsig_key **, const char *, void *); int forget_zone (void *); int repudiate_zone (void *); void cache_found_zone (ns_class, char *, struct in_addr *, int); isc_result_t uerr2isc (int); isc_result_t ns_rcode_to_isc (int); #define DprintQ(a,b,c,d) #define Dprint(a,b) #define Perror(a, b, c, d) #define Aerror(a, b, c, d, e) #define DPRINTF(x) #define USE_MD5 #endif #if defined (TRACING) void trace_mr_statp_setup (res_state); #endif Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/minires/res_update.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/minires/res_update.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/minires/res_update.h (revision 131136) @@ -1,51 +1,57 @@ /* - * Copyright (c) 1999 by Internet Software Consortium, Inc. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ */ /* - * $Id: res_update.h,v 1.2.2.1 2001/05/17 20:47:28 mellon Exp $ + * $Id: res_update.h,v 1.2.2.2 2004/06/10 17:59:37 dhankins Exp $ */ #ifndef __RES_UPDATE_H #define __RES_UPDATE_H #include #include "arpa/nameser.h" #include /* * This RR-like structure is particular to UPDATE. */ typedef struct ns_updrec { ISC_LINK(struct ns_updrec) r_link, r_glink; ns_sect r_section; /* ZONE/PREREQUISITE/UPDATE */ char *r_dname; /* owner of the RR */ ns_class r_class; /* class number */ ns_type r_type; /* type number */ u_int32_t r_ttl; /* time to live */ const unsigned char *r_data; /* rdata fields as text string */ unsigned char *r_data_ephem; /* pointer to freeable r_data */ unsigned int r_size; /* size of r_data field */ int r_opcode; /* type of operation */ /* following fields for private use by the resolver/server routines */ struct databuf *r_dp; /* databuf to process */ struct databuf *r_deldp; /* databuf's deleted/overwritten */ unsigned int r_zone; /* zone number on server */ } ns_updrec; typedef ISC_LIST(ns_updrec) ns_updque; #endif /*__RES_UPDATE_H*/ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/minires/resolv.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/minires/resolv.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/minires/resolv.h (revision 131136) @@ -1,314 +1,320 @@ /* * Copyright (c) 1983, 1987, 1989 * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. */ /* - * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * Portions Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (c) 1995-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ */ /* * @(#)resolv.h 8.1 (Berkeley) 6/2/93 - * $Id: resolv.h,v 1.3 2000/07/17 20:54:12 mellon Exp $ + * $Id: resolv.h,v 1.3.2.1 2004/06/10 17:59:37 dhankins Exp $ */ #ifndef _RESOLV_H_ #define _RESOLV_H_ /* * This used to be defined in res_query.c, now it's in herror.c. * [XXX no it's not. It's in irs/irs_data.c] * It was * never extern'd by any *.h file before it was placed here. For thread * aware programs, the last h_errno value set is stored in res->h_errno. * * XXX: There doesn't seem to be a good reason for exposing RES_SET_H_ERRNO * (and __h_errno_set) to the public via . * XXX: __h_errno_set is really part of IRS, not part of the resolver. * If somebody wants to build and use a resolver that doesn't use IRS, * what do they do? Perhaps something like * #ifdef WANT_IRS * # define RES_SET_H_ERRNO(r,x) __h_errno_set(r,x) * #else * # define RES_SET_H_ERRNO(r,x) (h_errno = (r)->res_h_errno = (x)) * #endif */ #define RES_SET_H_ERRNO(r,x) __h_errno_set(r,x) struct __res_state; /* forward */ void __h_errno_set(struct __res_state *res, int err); /* * Resolver configuration file. * Normally not present, but may contain the address of the * inital name server(s) to query and the domain search list. */ #ifndef _PATH_RESCONF #define _PATH_RESCONF "/etc/resolv.conf" #endif typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error } res_sendhookact; typedef res_sendhookact (*res_send_qhook) (struct sockaddr_in * const *ns, double **query, unsigned *querylen, double *ans, unsigned anssiz, int *resplen); typedef res_sendhookact (*res_send_rhook) (const struct sockaddr_in *ns, double *query, unsigned querylen, double *ans, unsigned anssiz, int *resplen); struct res_sym { int number; /* Identifying number, like T_MX */ char * name; /* Its symbolic name, like "MX" */ char * humanname; /* Its fun name, like "mail exchanger" */ }; /* * Global defines and variables for resolver stub. */ #define MAXNS 3 /* max # name servers we'll track */ #define MAXDFLSRCH 3 /* # default domain levels to try */ #define MAXDNSRCH 6 /* max # domains in search path */ #define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */ #define RES_TIMEOUT 5 /* min. seconds between retries */ #define MAXRESOLVSORT 10 /* number of net to sort on */ #define RES_MAXNDOTS 15 /* should reflect bit field size */ #define RES_MAXRETRANS 30 /* only for resolv.conf/RES_OPTIONS */ #define RES_MAXRETRY 5 /* only for resolv.conf/RES_OPTIONS */ #define RES_DFLRETRY 2 /* Default #/tries. */ struct __res_state { int retrans; /* retransmition time interval */ int retry; /* number of times to retransmit */ u_long options; /* option flags - see below. */ int nscount; /* number of name servers */ struct sockaddr_in nsaddr_list[MAXNS]; /* address of name server */ #define nsaddr nsaddr_list[0] /* for backward compatibility */ u_short id; /* current message id */ char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */ char defdname[256]; /* default domain (deprecated) */ u_long pfcode; /* RES_PRF_ flags - see below. */ unsigned ndots:4; /* threshold for initial abs. query */ unsigned nsort:4; /* number of elements in sort_list[] */ char unused[3]; struct { struct in_addr addr; u_int32_t mask; } sort_list[MAXRESOLVSORT]; res_send_qhook qhook; /* query hook */ res_send_rhook rhook; /* response hook */ int res_h_errno; /* last one set for this context */ int _sock; /* PRIVATE: for res_send i/o */ u_int _flags; /* PRIVATE: see below */ char pad[52]; /* On an i386 this means 512b total. */ }; typedef struct __res_state *res_state; /* * Resolver flags (used to be discrete per-module statics ints). */ #define RES_F_VC 0x00000001 /* socket is TCP */ #define RES_F_CONN 0x00000002 /* socket is connected */ /* res_findzonecut() options */ #define RES_EXHAUSTIVE 0x00000001 /* always do all queries */ /* * Resolver options (keep these in synch with res_debug.c, please) */ #define RES_INIT 0x00000001 /* address initialized */ #define RES_DEBUG 0x00000002 /* print debug messages */ #define RES_AAONLY 0x00000004 /* authoritative answers only (!IMPL)*/ #define RES_USEVC 0x00000008 /* use virtual circuit */ #define RES_PRIMARY 0x00000010 /* query primary server only (!IMPL) */ #define RES_IGNTC 0x00000020 /* ignore trucation errors */ #define RES_RECURSE 0x00000040 /* recursion desired */ #define RES_DEFNAMES 0x00000080 /* use default domain name */ #define RES_STAYOPEN 0x00000100 /* Keep TCP socket open */ #define RES_DNSRCH 0x00000200 /* search up local domain tree */ #define RES_INSECURE1 0x00000400 /* type 1 security disabled */ #define RES_INSECURE2 0x00000800 /* type 2 security disabled */ #define RES_NOALIASES 0x00001000 /* shuts off HOSTALIASES feature */ #define RES_USE_INET6 0x00002000 /* use/map IPv6 in gethostbyname() */ #define RES_ROTATE 0x00004000 /* rotate ns list after each query */ #define RES_NOCHECKNAME 0x00008000 /* do not check names for sanity. */ #define RES_KEEPTSIG 0x00010000 /* do not strip TSIG records */ #define RES_DEFAULT (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH) /* * Resolver "pfcode" values. Used by dig. */ #define RES_PRF_STATS 0x00000001 #define RES_PRF_UPDATE 0x00000002 #define RES_PRF_CLASS 0x00000004 #define RES_PRF_CMD 0x00000008 #define RES_PRF_QUES 0x00000010 #define RES_PRF_ANS 0x00000020 #define RES_PRF_AUTH 0x00000040 #define RES_PRF_ADD 0x00000080 #define RES_PRF_HEAD1 0x00000100 #define RES_PRF_HEAD2 0x00000200 #define RES_PRF_TTLID 0x00000400 #define RES_PRF_HEADX 0x00000800 #define RES_PRF_QUERY 0x00001000 #define RES_PRF_REPLY 0x00002000 #define RES_PRF_INIT 0x00004000 /* 0x00008000 */ #if 0 /* Things involving an internal (static) resolver context. */ #ifdef _REENTRANT extern struct __res_state *__res_state(void); #define _res (*__res_state()) #else #ifndef __BIND_NOSTATIC extern struct __res_state _res; #endif #endif void fp_nquery (const u_char *, int, FILE *); void fp_query (const u_char *, FILE *); const char * hostalias (const char *); void p_query (const u_char *); void res_close (void); int res_init (void); int res_isourserver (const struct sockaddr_in *); int res_mkquery (int, const char *, int, int, const u_char *, int, const u_char *, u_char *, int); int res_query (const char *, int, int, u_char *, int); int res_querydomain (const char *, const char *, int, int, u_char *, int); int res_search (const char *, int, int, u_char *, int); int res_send (const u_char *, int, u_char *, int); int res_sendsigned (const u_char *, int, ns_tsig_key *, u_char *, int); #if !defined(SHARED_LIBBIND) || defined(LIB) /* * If libbind is a shared object (well, DLL anyway) * these externs break the linker when resolv.h is * included by a lib client (like named) * Make them go away if a client is including this * */ extern const struct res_sym __p_key_syms[]; extern const struct res_sym __p_cert_syms[]; extern const struct res_sym __p_class_syms[]; extern const struct res_sym __p_type_syms[]; extern const struct res_sym __p_rcode_syms[]; #endif /* SHARED_LIBBIND */ int res_hnok (const char *); int res_ownok (const char *); int res_mailok (const char *); int res_dnok (const char *); int sym_ston (const struct res_sym *, const char *, int *); const char * sym_ntos (const struct res_sym *, int, int *); const char * sym_ntop (const struct res_sym *, int, int *); int b64_ntop (u_char const *, size_t, char *, size_t); int b64_pton (char const *, u_char *, size_t); int loc_aton (const char *ascii, u_char *binary); const char * loc_ntoa (const u_char *binary, char *ascii); int dn_skipname (const u_char *, const u_char *); void putlong (u_int32_t, u_char *); void putshort (u_int16_t, u_char *); const char * p_class (int); const char * p_time (u_int32_t); const char * p_type (int); const char * p_rcode (int); const u_char * p_cdnname (const u_char *, const u_char *, int, FILE *); const u_char * p_cdname (const u_char *, const u_char *, FILE *); const u_char * p_fqnname (const u_char *cp, const u_char *msg, int, char *, int); const u_char * p_fqname (const u_char *, const u_char *, FILE *); const char * p_option (u_long option); char * p_secstodate (u_long); int dn_count_labels (const char *); int dn_expand (const u_char *, const u_char *, const u_char *, char *, int); u_int res_randomid (void); int res_nameinquery (const char *, int, int, const u_char *, const u_char *); int res_queriesmatch (const u_char *, const u_char *, const u_char *, const u_char *); const char * p_section (int section, int opcode); /* Things involving a resolver context. */ int res_ninit (res_state); int res_nisourserver (const res_state, const struct sockaddr_in *); void fp_resstat (const res_state, FILE *); void res_npquery (const res_state, const u_char *, int, FILE *); const char * res_hostalias (const res_state, const char *, char *, size_t); int res_nquery (res_state, const char *, int, int, u_char *, int); int res_nsearch (res_state, const char *, int, int, u_char *, int); int res_nquerydomain (res_state, const char *, const char *, int, int, u_char *, int); int res_nmkquery (res_state, int, const char *, int, int, const u_char *, int, const u_char *, u_char *, int); int res_nsend (res_state, const u_char *, int, u_char *, int); int res_nsendsigned (res_state, const u_char *, int, ns_tsig_key *, u_char *, int); int res_findzonecut (res_state, const char *, ns_class, int, char *, size_t, struct in_addr *, int); void res_nclose (res_state); #endif /* 0 */ #endif /* !_RESOLV_H_ */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/netinet/udp.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/netinet/udp.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/netinet/udp.h (revision 131136) @@ -1,47 +1,70 @@ /* $NetBSD: udp.h,v 1.6 1995/04/13 06:37:10 cgd Exp $ */ /* * Copyright (c) 1982, 1986, 1993 * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. * * @(#)udp.h 8.1 (Berkeley) 6/10/93 */ /* + * Portions Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (c) 2000-2003 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ + */ + +/* * Udp protocol header. * Per RFC 768, September, 1981. */ struct udphdr { u_int16_t uh_sport; /* source port */ u_int16_t uh_dport; /* destination port */ u_int16_t uh_ulen; /* udp length */ u_int16_t uh_sum; /* udp checksum */ }; Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/alloc.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/alloc.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/alloc.h (revision 131136) @@ -1,120 +1,111 @@ /* alloc.h Definitions for the object management API protocol memory allocation... */ /* - * Copyright (c) 1996-2001 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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''. */ isc_result_t omapi_buffer_new (omapi_buffer_t **, const char *, int); isc_result_t omapi_buffer_reference (omapi_buffer_t **, omapi_buffer_t *, const char *, int); isc_result_t omapi_buffer_dereference (omapi_buffer_t **, const char *, int); #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \ defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) #define DMDOFFSET (sizeof (struct dmalloc_preamble)) #define DMLFSIZE 16 #define DMUFSIZE 16 #define DMDSIZE (DMDOFFSET + DMLFSIZE + DMUFSIZE) struct dmalloc_preamble { struct dmalloc_preamble *prev, *next; const char *file; int line; size_t size; unsigned long generation; unsigned char low_fence [DMLFSIZE]; }; #else #define DMDOFFSET 0 #define DMDSIZE 0 #endif /* rc_history flags... */ #define RC_LEASE 1 #define RC_MISC 2 #if defined (DEBUG_RC_HISTORY) #if !defined (RC_HISTORY_MAX) # define RC_HISTORY_MAX 256 #endif #if !defined (RC_HISTORY_FLAGS) # define RC_HISTORY_FLAGS (RC_LEASE | RC_MISC) #endif struct rc_history_entry { const char *file; int line; void *reference; void *addr; int refcnt; }; #define rc_register(x, l, r, y, z, d, f) do { \ if (RC_HISTORY_FLAGS & ~(f)) { \ rc_history [rc_history_index].file = (x); \ rc_history [rc_history_index].line = (l); \ rc_history [rc_history_index].reference = (r); \ rc_history [rc_history_index].addr = (y); \ rc_history [rc_history_index].refcnt = (z); \ rc_history_next (d); \ } \ } while (0) #define rc_register_mdl(r, y, z, d, f) \ rc_register (__FILE__, __LINE__, r, y, z, d, f) #else #define rc_register(file, line, reference, addr, refcnt, d, f) #define rc_register_mdl(reference, addr, refcnt, d, f) #endif #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \ defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) extern struct dmalloc_preamble *dmalloc_list; extern unsigned long dmalloc_outstanding; extern unsigned long dmalloc_longterm; extern unsigned long dmalloc_generation; extern unsigned long dmalloc_cutoff_generation; #endif #if defined (DEBUG_RC_HISTORY) extern struct rc_history_entry rc_history [RC_HISTORY_MAX]; extern int rc_history_index; extern int rc_history_count; #endif Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/buffer.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/buffer.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/buffer.h (revision 131136) @@ -1,92 +1,83 @@ /* buffer.h Definitions for the object management API protocol buffering... */ /* - * Copyright (c) 1996-1999 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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''. */ /* OMAPI buffers are ring buffers, which means that the beginning of the buffer and the end of the buffer chase each other around. As long as the tail never catches up to the head, there's room in the buffer for data. - If the tail and the head are equal, the buffer is empty. - If the tail is less than the head, the contents of the buffer are the bytes from the head to the end of buffer, and in addition, the bytes between the beginning of the buffer and the tail, not including the byte addressed by the tail. - If the tail is greater than the head, then the buffer contains valid bytes starting with the byte addressed by the head, and ending with the byte before the byte addressed by the tail. There will always be at least one byte of waste, because the tail can't increase so that it's equal to the head (that would represent an empty buffer. */ #define OMAPI_BUF_SIZE 4048 typedef struct _omapi_buffer { struct _omapi_buffer *next; /* Buffers can be chained. */ u_int32_t refcnt; /* Buffers are reference counted. */ u_int16_t head, tail; /* Buffers are organized in a ring. */ char buf [OMAPI_BUF_SIZE]; /* The actual buffer is included in the buffer data structure. */ } omapi_buffer_t; #define BUFFER_BYTES_FREE(x) \ ((x) -> tail > (x) -> head \ ? sizeof ((x) -> buf) - ((x) -> tail - (x) -> head) \ : (x) -> head - (x) -> tail) #define BYTES_IN_BUFFER(x) \ ((x) -> tail > (x) -> head \ ? (x) -> tail - (x) -> head - 1 \ : sizeof ((x) -> buf) - ((x) -> head - (x) -> tail) - 1) isc_result_t omapi_connection_require (omapi_object_t *, unsigned); isc_result_t omapi_connection_copyout (unsigned char *, omapi_object_t *, unsigned); isc_result_t omapi_connection_copyin (omapi_object_t *, const unsigned char *, unsigned); isc_result_t omapi_connection_flush (omapi_object_t *); isc_result_t omapi_connection_get_uint32 (omapi_object_t *, u_int32_t *); isc_result_t omapi_connection_put_uint32 (omapi_object_t *, u_int32_t); isc_result_t omapi_connection_get_uint16 (omapi_object_t *, u_int16_t *); isc_result_t omapi_connection_put_uint16 (omapi_object_t *, u_int32_t); Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/convert.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/convert.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/convert.h (revision 131136) @@ -1,61 +1,52 @@ /* convert.h Safe copying of integers into and out of a non-aligned memory buffer. */ /* - * Copyright (c) 1996-1999 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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 OMAPI_CONVERT_H #define OMAPI_CONVERT_H u_int32_t getULong (const unsigned char *); int32_t getLong (const unsigned char *); u_int32_t getUShort (const unsigned char *); int32_t getShort (const unsigned char *); u_int32_t getUChar (const unsigned char *); void putULong (unsigned char *, u_int32_t); void putLong (unsigned char *, int32_t); void putUShort (unsigned char *, u_int32_t); void putShort (unsigned char *, int32_t); void putUChar (unsigned char *, u_int32_t); int converted_length (const unsigned char *, unsigned int, unsigned int); int binary_to_ascii (unsigned char *, const unsigned char *, unsigned int, unsigned int); #endif /* OMAPI_CONVERT_H */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/hash.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/hash.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/hash.h (revision 131136) @@ -1,159 +1,150 @@ /* hash.h Definitions for hashing... */ /* - * Copyright (c) 1995-2001 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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 OMAPI_HASH_H #define OMAPI_HASH_H #define DEFAULT_HASH_SIZE 9973 /* The purpose of the hashed_object_t struct is to not match anything else. */ typedef struct { int foo; } hashed_object_t; typedef void (*hash_foreach_func) (const unsigned char *, unsigned, hashed_object_t *); typedef int (*hash_reference) (hashed_object_t **, hashed_object_t *, const char *, int); typedef int (*hash_dereference) (hashed_object_t **, const char *, int); struct hash_bucket { struct hash_bucket *next; const unsigned char *name; unsigned len; hashed_object_t *value; }; typedef int (*hash_comparator_t)(const void *, const void *, unsigned long); struct hash_table { unsigned hash_count; struct hash_bucket *buckets [DEFAULT_HASH_SIZE]; hash_reference referencer; hash_dereference dereferencer; hash_comparator_t cmp; int (*do_hash) (const unsigned char *, unsigned, unsigned); }; struct named_hash { struct named_hash *next; const char *name; struct hash_table *hash; }; #define HASH_FUNCTIONS_DECL(name, bufarg, type, hashtype) \ void name##_hash_add (hashtype *, bufarg, unsigned, type *, \ const char *, int); \ void name##_hash_delete (hashtype *, bufarg, unsigned, \ const char *, int); \ int name##_hash_lookup (type **, hashtype *, bufarg, unsigned, \ const char *, int); \ int name##_hash_foreach (hashtype *, \ void (*) (bufarg, unsigned, type *)); \ int name##_new_hash (hashtype **, int, const char *, int); \ void name##_free_hash_table (hashtype **, const char *, int); #define HASH_FUNCTIONS(name, bufarg, type, hashtype, ref, deref) \ void name##_hash_add (hashtype *table, \ bufarg buf, unsigned len, type *ptr, \ const char *file, int line) \ { \ add_hash ((struct hash_table *)table, \ (const unsigned char *)buf, \ len, (hashed_object_t *)ptr, file, line); \ } \ \ void name##_hash_delete (hashtype *table, \ bufarg buf, unsigned len, const char *file, int line)\ { \ delete_hash_entry ((struct hash_table *)table, \ (const unsigned char *)buf, \ len, file, line); \ } \ \ int name##_hash_lookup (type **ptr, hashtype *table, \ bufarg buf, unsigned len, const char *file, int line) \ { \ return hash_lookup ((hashed_object_t **)ptr, \ (struct hash_table *)table, \ (const unsigned char *)buf, len, file, line); \ } \ \ int name##_hash_foreach (hashtype *table, \ void (*func) (bufarg, unsigned, type *)) \ { \ return hash_foreach ((struct hash_table *)table, \ (hash_foreach_func)func); \ } \ \ int name##_new_hash (hashtype **tp, int c, const char *file, int line) \ { \ return new_hash ((struct hash_table **)tp, \ (hash_reference)ref, (hash_dereference)deref, c, \ file, line); \ } \ \ void name##_free_hash_table (hashtype **table, const char *file, int line) \ { \ free_hash_table ((struct hash_table **)table, file, line); \ } void relinquish_hash_bucket_hunks (void); int new_hash_table (struct hash_table **, int, const char *, int); void free_hash_table (struct hash_table **, const char *, int); struct hash_bucket *new_hash_bucket (const char *, int); void free_hash_bucket (struct hash_bucket *, const char *, int); int new_hash (struct hash_table **, hash_reference, hash_dereference, int, const char *, int); void add_hash (struct hash_table *, const unsigned char *, unsigned, hashed_object_t *, const char *, int); void delete_hash_entry (struct hash_table *, const unsigned char *, unsigned, const char *, int); int hash_lookup (hashed_object_t **, struct hash_table *, const unsigned char *, unsigned, const char *, int); int hash_foreach (struct hash_table *, hash_foreach_func); int casecmp (const void *s, const void *t, unsigned long len); #endif /* OMAPI_HASH_H */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/omapip.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/omapip.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/omapip.h (revision 131136) @@ -1,620 +1,611 @@ /* omapip.h Definitions for the object management API and protocol... */ /* - * Copyright (c) 1996-2001 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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 _OMAPIP_H_ #define _OMAPIP_H_ #include typedef unsigned int omapi_handle_t; struct __omapi_object; typedef struct __omapi_object omapi_object_t; typedef enum { omapi_datatype_int, omapi_datatype_string, omapi_datatype_data, omapi_datatype_object } omapi_datatype_t; typedef struct { int refcnt; omapi_datatype_t type; union { struct { unsigned len; #define OMAPI_TYPED_DATA_NOBUFFER_LEN (sizeof (int) + \ sizeof (omapi_datatype_t) + \ sizeof (int)) unsigned char value [1]; } buffer; #define OMAPI_TYPED_DATA_OBJECT_LEN (sizeof (int) + \ sizeof (omapi_datatype_t) + \ sizeof (omapi_object_t *)) omapi_object_t *object; #define OMAPI_TYPED_DATA_REF_LEN (sizeof (int) + \ sizeof (omapi_datatype_t) + \ 3 * sizeof (void *)) struct { void *ptr; isc_result_t (*reference) (void *, void *, const char *, int); isc_result_t (*dereference) (void *, const char *, int); } ref; #define OMAPI_TYPED_DATA_INT_LEN (sizeof (int) + \ sizeof (omapi_datatype_t) + \ sizeof (int)) int integer; } u; } omapi_typed_data_t; typedef struct { int refcnt; unsigned len; #define OMAPI_DATA_STRING_EMPTY_SIZE (2 * sizeof (int)) unsigned char value [1]; } omapi_data_string_t; typedef struct { int refcnt; omapi_data_string_t *name; omapi_typed_data_t *value; } omapi_value_t; typedef struct __omapi_object_type_t { const char *name; struct __omapi_object_type_t *next; isc_result_t (*set_value) (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t (*get_value) (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t (*destroy) (omapi_object_t *, const char *, int); isc_result_t (*signal_handler) (omapi_object_t *, const char *, va_list); isc_result_t (*stuff_values) (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t (*lookup) (omapi_object_t **, omapi_object_t *, omapi_object_t *); isc_result_t (*create) (omapi_object_t **, omapi_object_t *); isc_result_t (*remove) (omapi_object_t *, omapi_object_t *); isc_result_t (*freer) (omapi_object_t *, const char *, int); isc_result_t (*allocator) (omapi_object_t **, const char *, int); isc_result_t (*sizer) (size_t); size_t size; int rc_flag; isc_result_t (*initialize) (omapi_object_t *, const char *, int); } omapi_object_type_t; #define OMAPI_OBJECT_PREAMBLE \ omapi_object_type_t *type; \ int refcnt; \ omapi_handle_t handle; \ omapi_object_t *outer, *inner /* The omapi handle structure. */ struct __omapi_object { OMAPI_OBJECT_PREAMBLE; }; /* The port on which applications should listen for OMAPI connections. */ #define OMAPI_PROTOCOL_PORT 7911 typedef struct { unsigned addrtype; unsigned addrlen; unsigned char address [16]; unsigned port; } omapi_addr_t; typedef struct { int refcnt; unsigned count; omapi_addr_t *addresses; } omapi_addr_list_t; typedef struct auth_key { OMAPI_OBJECT_PREAMBLE; char *name; char *algorithm; omapi_data_string_t *key; } omapi_auth_key_t; #define OMAPI_CREATE 1 #define OMAPI_UPDATE 2 #define OMAPI_EXCL 4 #define OMAPI_NOTIFY_PROTOCOL 8 #define OMAPI_OBJECT_ALLOC(name, stype, type) \ isc_result_t name##_allocate (stype **p, const char *file, int line) \ { \ return omapi_object_allocate ((omapi_object_t **)p, \ type, 0, file, line); \ } \ \ isc_result_t name##_reference (stype **pptr, stype *ptr, \ const char *file, int line) \ { \ return omapi_object_reference ((omapi_object_t **)pptr, \ (omapi_object_t *)ptr, file, line); \ } \ \ isc_result_t name##_dereference (stype **ptr, const char *file, int line) \ { \ return omapi_object_dereference ((omapi_object_t **)ptr, file, line); \ } #define OMAPI_OBJECT_ALLOC_DECL(name, stype, type) \ isc_result_t name##_allocate (stype **p, const char *file, int line); \ isc_result_t name##_reference (stype **pptr, stype *ptr, \ const char *file, int line); \ isc_result_t name##_dereference (stype **ptr, const char *file, int line); typedef isc_result_t (*omapi_array_ref_t) (char **, char *, const char *, int); typedef isc_result_t (*omapi_array_deref_t) (char **, const char *, int); /* An extensible array type. */ typedef struct { char **data; omapi_array_ref_t ref; omapi_array_deref_t deref; int count; int max; } omapi_array_t; #define OMAPI_ARRAY_TYPE(name, stype) \ isc_result_t name##_array_allocate (omapi_array_t **p, \ const char *file, int line) \ { \ return (omapi_array_allocate \ (p, \ (omapi_array_ref_t)name##_reference, \ (omapi_array_deref_t)name##_dereference, \ file, line)); \ } \ \ isc_result_t name##_array_free (omapi_array_t **p, \ const char *file, int line) \ { \ return omapi_array_free (p, file, line); \ } \ \ isc_result_t name##_array_extend (omapi_array_t *pptr, stype *ptr, int *index,\ const char *file, int line) \ { \ return omapi_array_extend (pptr, (char *)ptr, index, file, line); \ } \ \ isc_result_t name##_array_set (omapi_array_t *pptr, stype *ptr, int index, \ const char *file, int line) \ { \ return omapi_array_set (pptr, (char *)ptr, index, file, line); \ } \ \ isc_result_t name##_array_lookup (stype **ptr, omapi_array_t *pptr, \ int index, const char *file, int line) \ { \ return omapi_array_lookup ((char **)ptr, pptr, index, file, line); \ } #define OMAPI_ARRAY_TYPE_DECL(name, stype) \ isc_result_t name##_array_allocate (omapi_array_t **, const char *, int); \ isc_result_t name##_array_free (omapi_array_t **, const char *, int); \ isc_result_t name##_array_extend (omapi_array_t *, stype *, int *, \ const char *, int); \ isc_result_t name##_array_set (omapi_array_t *, \ stype *, int, const char *, int); \ isc_result_t name##_array_lookup (stype **, \ omapi_array_t *, int, const char *, int) #define omapi_array_foreach_begin(array, stype, var) \ { \ int omapi_array_foreach_index; \ stype *var = (stype *)0; \ for (omapi_array_foreach_index = 0; \ array && \ omapi_array_foreach_index < (array) -> count; \ omapi_array_foreach_index++) { \ if ((array) -> data [omapi_array_foreach_index]) { \ ((*(array) -> ref) \ ((char **)&var, \ (array) -> data [omapi_array_foreach_index],\ MDL)); #define omapi_array_foreach_end(array, stype, var) \ (*(array) -> deref) ((char **)&var, MDL); \ } \ } \ } isc_result_t omapi_protocol_connect (omapi_object_t *, const char *, unsigned, omapi_object_t *); isc_result_t omapi_connect_list (omapi_object_t *, omapi_addr_list_t *, omapi_addr_t *); isc_result_t omapi_protocol_listen (omapi_object_t *, unsigned, int); isc_boolean_t omapi_protocol_authenticated (omapi_object_t *); isc_result_t omapi_protocol_configure_security (omapi_object_t *, isc_result_t (*) (omapi_object_t *, omapi_addr_t *), isc_result_t (*) (omapi_object_t *, omapi_auth_key_t *)); isc_result_t omapi_protocol_accept (omapi_object_t *); isc_result_t omapi_protocol_send_intro (omapi_object_t *, unsigned, unsigned); isc_result_t omapi_protocol_ready (omapi_object_t *); isc_result_t omapi_protocol_add_auth (omapi_object_t *, omapi_object_t *, omapi_handle_t); isc_result_t omapi_protocol_lookup_auth (omapi_object_t **, omapi_object_t *, omapi_handle_t); isc_result_t omapi_protocol_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t omapi_protocol_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t omapi_protocol_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t omapi_protocol_destroy (omapi_object_t *, const char *, int); isc_result_t omapi_protocol_send_message (omapi_object_t *, omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t omapi_protocol_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t omapi_protocol_listener_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t omapi_protocol_listener_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t omapi_protocol_listener_destroy (omapi_object_t *, const char *, int); isc_result_t omapi_protocol_listener_signal (omapi_object_t *, const char *, va_list); isc_result_t omapi_protocol_listener_stuff (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t omapi_protocol_send_status (omapi_object_t *, omapi_object_t *, isc_result_t, unsigned, const char *); isc_result_t omapi_protocol_send_open (omapi_object_t *, omapi_object_t *, const char *, omapi_object_t *, unsigned); isc_result_t omapi_protocol_send_update (omapi_object_t *, omapi_object_t *, unsigned, omapi_object_t *); isc_result_t omapi_connect (omapi_object_t *, const char *, unsigned); isc_result_t omapi_disconnect (omapi_object_t *, int); int omapi_connection_readfd (omapi_object_t *); int omapi_connection_writefd (omapi_object_t *); isc_result_t omapi_connection_connect (omapi_object_t *); isc_result_t omapi_connection_reader (omapi_object_t *); isc_result_t omapi_connection_writer (omapi_object_t *); isc_result_t omapi_connection_reaper (omapi_object_t *); isc_result_t omapi_connection_output_auth_length (omapi_object_t *, unsigned *); isc_result_t omapi_connection_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t omapi_connection_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t omapi_connection_destroy (omapi_object_t *, const char *, int); isc_result_t omapi_connection_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t omapi_connection_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t omapi_connection_write_typed_data (omapi_object_t *, omapi_typed_data_t *); isc_result_t omapi_connection_put_name (omapi_object_t *, const char *); isc_result_t omapi_connection_put_string (omapi_object_t *, const char *); isc_result_t omapi_connection_put_handle (omapi_object_t *c, omapi_object_t *h); isc_result_t omapi_listen (omapi_object_t *, unsigned, int); isc_result_t omapi_listen_addr (omapi_object_t *, omapi_addr_t *, int); isc_result_t omapi_listener_accept (omapi_object_t *); int omapi_listener_readfd (omapi_object_t *); isc_result_t omapi_accept (omapi_object_t *); isc_result_t omapi_listener_configure_security (omapi_object_t *, isc_result_t (*) (omapi_object_t *, omapi_addr_t *)); isc_result_t omapi_listener_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t omapi_listener_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t omapi_listener_destroy (omapi_object_t *, const char *, int); isc_result_t omapi_listener_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t omapi_listener_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t omapi_register_io_object (omapi_object_t *, int (*)(omapi_object_t *), int (*)(omapi_object_t *), isc_result_t (*)(omapi_object_t *), isc_result_t (*)(omapi_object_t *), isc_result_t (*)(omapi_object_t *)); isc_result_t omapi_unregister_io_object (omapi_object_t *); isc_result_t omapi_dispatch (struct timeval *); isc_result_t omapi_wait_for_completion (omapi_object_t *, struct timeval *); isc_result_t omapi_one_dispatch (omapi_object_t *, struct timeval *); isc_result_t omapi_io_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t omapi_io_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t omapi_io_destroy (omapi_object_t *, const char *, int); isc_result_t omapi_io_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t omapi_io_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t omapi_waiter_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t omapi_io_state_foreach (isc_result_t (*func) (omapi_object_t *, void *), void *p); isc_result_t omapi_generic_new (omapi_object_t **, const char *, int); isc_result_t omapi_generic_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t omapi_generic_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t omapi_generic_destroy (omapi_object_t *, const char *, int); isc_result_t omapi_generic_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t omapi_generic_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t omapi_generic_clear_flags (omapi_object_t *); isc_result_t omapi_message_new (omapi_object_t **, const char *, int); isc_result_t omapi_message_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t omapi_message_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t omapi_message_destroy (omapi_object_t *, const char *, int); isc_result_t omapi_message_signal_handler (omapi_object_t *, const char *, va_list); isc_result_t omapi_message_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t omapi_message_register (omapi_object_t *); isc_result_t omapi_message_unregister (omapi_object_t *); isc_result_t omapi_message_process (omapi_object_t *, omapi_object_t *); OMAPI_OBJECT_ALLOC_DECL (omapi_auth_key, omapi_auth_key_t, omapi_type_auth_key) isc_result_t omapi_auth_key_new (omapi_auth_key_t **, const char *, int); isc_result_t omapi_auth_key_destroy (omapi_object_t *, const char *, int); isc_result_t omapi_auth_key_enter (omapi_auth_key_t *); isc_result_t omapi_auth_key_lookup_name (omapi_auth_key_t **, const char *); isc_result_t omapi_auth_key_lookup (omapi_object_t **, omapi_object_t *, omapi_object_t *); isc_result_t omapi_auth_key_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t omapi_auth_key_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); extern omapi_object_type_t *omapi_type_connection; extern omapi_object_type_t *omapi_type_listener; extern omapi_object_type_t *omapi_type_io_object; extern omapi_object_type_t *omapi_type_generic; extern omapi_object_type_t *omapi_type_protocol; extern omapi_object_type_t *omapi_type_protocol_listener; extern omapi_object_type_t *omapi_type_waiter; extern omapi_object_type_t *omapi_type_remote; extern omapi_object_type_t *omapi_type_message; extern omapi_object_type_t *omapi_type_auth_key; extern omapi_object_type_t *omapi_object_types; void omapi_type_relinquish (void); isc_result_t omapi_init (void); isc_result_t omapi_object_type_register (omapi_object_type_t **, const char *, isc_result_t (*) (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *), isc_result_t (*) (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **), isc_result_t (*) (omapi_object_t *, const char *, int), isc_result_t (*) (omapi_object_t *, const char *, va_list), isc_result_t (*) (omapi_object_t *, omapi_object_t *, omapi_object_t *), isc_result_t (*) (omapi_object_t **, omapi_object_t *, omapi_object_t *), isc_result_t (*) (omapi_object_t **, omapi_object_t *), isc_result_t (*) (omapi_object_t *, omapi_object_t *), isc_result_t (*) (omapi_object_t *, const char *, int), isc_result_t (*) (omapi_object_t **, const char *, int), isc_result_t (*) (size_t), size_t, isc_result_t (*) (omapi_object_t *, const char *, int), int); isc_result_t omapi_signal (omapi_object_t *, const char *, ...); isc_result_t omapi_signal_in (omapi_object_t *, const char *, ...); isc_result_t omapi_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); isc_result_t omapi_set_value_str (omapi_object_t *, omapi_object_t *, const char *, omapi_typed_data_t *); isc_result_t omapi_set_boolean_value (omapi_object_t *, omapi_object_t *, const char *, int); isc_result_t omapi_set_int_value (omapi_object_t *, omapi_object_t *, const char *, int); isc_result_t omapi_set_object_value (omapi_object_t *, omapi_object_t *, const char *, omapi_object_t *); isc_result_t omapi_set_string_value (omapi_object_t *, omapi_object_t *, const char *, const char *); isc_result_t omapi_get_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **); isc_result_t omapi_get_value_str (omapi_object_t *, omapi_object_t *, const char *, omapi_value_t **); isc_result_t omapi_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); isc_result_t omapi_object_create (omapi_object_t **, omapi_object_t *, omapi_object_type_t *); isc_result_t omapi_object_update (omapi_object_t *, omapi_object_t *, omapi_object_t *, omapi_handle_t); int omapi_data_string_cmp (omapi_data_string_t *, omapi_data_string_t *); int omapi_ds_strcmp (omapi_data_string_t *, const char *); int omapi_td_strcmp (omapi_typed_data_t *, const char *); int omapi_td_strcasecmp (omapi_typed_data_t *, const char *); isc_result_t omapi_make_value (omapi_value_t **, omapi_data_string_t *, omapi_typed_data_t *, const char *, int); isc_result_t omapi_make_const_value (omapi_value_t **, omapi_data_string_t *, const unsigned char *, unsigned, const char *, int); isc_result_t omapi_make_int_value (omapi_value_t **, omapi_data_string_t *, int, const char *, int); isc_result_t omapi_make_uint_value (omapi_value_t **, omapi_data_string_t *, unsigned int, const char *, int); isc_result_t omapi_make_object_value (omapi_value_t **, omapi_data_string_t *, omapi_object_t *, const char *, int); isc_result_t omapi_make_handle_value (omapi_value_t **, omapi_data_string_t *, omapi_object_t *, const char *, int); isc_result_t omapi_make_string_value (omapi_value_t **, omapi_data_string_t *, const char *, const char *, int); isc_result_t omapi_get_int_value (unsigned long *, omapi_typed_data_t *); isc_result_t omapi_object_handle (omapi_handle_t *, omapi_object_t *); isc_result_t omapi_handle_lookup (omapi_object_t **, omapi_handle_t); isc_result_t omapi_handle_td_lookup (omapi_object_t **, omapi_typed_data_t *); void * dmalloc (unsigned, const char *, int); void dfree (void *, const char *, int); #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \ defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) void dmalloc_reuse (void *, const char *, int, int); void dmalloc_dump_outstanding (void); #else #define dmalloc_reuse(x,y,l,z) #endif #define MDL __FILE__, __LINE__ #if defined (DEBUG_RC_HISTORY) void dump_rc_history (void *); void rc_history_next (int); #endif void omapi_print_dmalloc_usage_by_caller (void); isc_result_t omapi_object_allocate (omapi_object_t **, omapi_object_type_t *, size_t, const char *, int); isc_result_t omapi_object_initialize (omapi_object_t *, omapi_object_type_t *, size_t, size_t, const char *, int); isc_result_t omapi_object_reference (omapi_object_t **, omapi_object_t *, const char *, int); isc_result_t omapi_object_dereference (omapi_object_t **, const char *, int); isc_result_t omapi_typed_data_new (const char *, int, omapi_typed_data_t **, omapi_datatype_t, ...); isc_result_t omapi_typed_data_reference (omapi_typed_data_t **, omapi_typed_data_t *, const char *, int); isc_result_t omapi_typed_data_dereference (omapi_typed_data_t **, const char *, int); isc_result_t omapi_data_string_new (omapi_data_string_t **, unsigned, const char *, int); isc_result_t omapi_data_string_reference (omapi_data_string_t **, omapi_data_string_t *, const char *, int); isc_result_t omapi_data_string_dereference (omapi_data_string_t **, const char *, int); isc_result_t omapi_value_new (omapi_value_t **, const char *, int); isc_result_t omapi_value_reference (omapi_value_t **, omapi_value_t *, const char *, int); isc_result_t omapi_value_dereference (omapi_value_t **, const char *, int); isc_result_t omapi_addr_list_new (omapi_addr_list_t **, unsigned, const char *, int); isc_result_t omapi_addr_list_reference (omapi_addr_list_t **, omapi_addr_list_t *, const char *, int); isc_result_t omapi_addr_list_dereference (omapi_addr_list_t **, const char *, int); isc_result_t omapi_array_allocate (omapi_array_t **, omapi_array_ref_t, omapi_array_deref_t, const char *, int); isc_result_t omapi_array_free (omapi_array_t **, const char *, int); isc_result_t omapi_array_extend (omapi_array_t *, char *, int *, const char *, int); isc_result_t omapi_array_set (omapi_array_t *, void *, int, const char *, int); isc_result_t omapi_array_lookup (char **, omapi_array_t *, int, const char *, int); OMAPI_ARRAY_TYPE_DECL(omapi_object, omapi_object_t); #endif /* _OMAPIP_H_ */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/omapip_p.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/omapip_p.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/omapip_p.h (revision 131136) @@ -1,302 +1,293 @@ /* omapip_p.h Private master include file for the OMAPI library. */ /* - * Copyright (c) 1996-2001 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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 __OMAPIP_OMAPIP_P_H__ #define __OMAPIP_OMAPIP_P_H__ #ifndef __CYGWIN32__ #include #include #include #include #include #include #else #define fd_set cygwin_fd_set #include #endif #include #include #include #include #include #include #include #include #include #include "cdefs.h" #include "osdep.h" #include #include #include #include #include #include /* OMAPI protocol header, version 1.00 */ typedef struct { u_int32_t authlen; /* Length of authenticator. */ u_int32_t authid; /* Authenticator object ID. */ u_int32_t op; /* Opcode. */ omapi_handle_t handle; /* Handle of object being operated on, or zero. */ u_int32_t id; /* Transaction ID. */ u_int32_t rid; /* ID of transaction to which this is a response. */ } omapi_protocol_header_t; #define OMAPI_PROTOCOL_VERSION 100 #define OMAPI_OP_OPEN 1 #define OMAPI_OP_REFRESH 2 #define OMAPI_OP_UPDATE 3 #define OMAPI_OP_NOTIFY 4 #define OMAPI_OP_STATUS 5 #define OMAPI_OP_DELETE 6 typedef enum { omapi_connection_unconnected, omapi_connection_connecting, omapi_connection_connected, omapi_connection_disconnecting, omapi_connection_closed } omapi_connection_state_t; typedef enum { omapi_protocol_intro_wait, omapi_protocol_header_wait, omapi_protocol_signature_wait, omapi_protocol_name_wait, omapi_protocol_name_length_wait, omapi_protocol_value_wait, omapi_protocol_value_length_wait } omapi_protocol_state_t; typedef struct __omapi_message_object { OMAPI_OBJECT_PREAMBLE; struct __omapi_message_object *next, *prev; omapi_object_t *object; omapi_object_t *notify_object; struct __omapi_protocol_object *protocol_object; u_int32_t authlen; omapi_typed_data_t *authenticator; u_int32_t authid; omapi_object_t *id_object; u_int32_t op; u_int32_t h; u_int32_t id; u_int32_t rid; } omapi_message_object_t; typedef struct __omapi_remote_auth { struct __omapi_remote_auth *next; omapi_handle_t remote_handle; omapi_object_t *a; } omapi_remote_auth_t; typedef struct __omapi_protocol_object { OMAPI_OBJECT_PREAMBLE; u_int32_t header_size; u_int32_t protocol_version; u_int32_t next_xid; omapi_protocol_state_t state; /* Input state. */ int reading_message_values; /* True if reading message-specific values. */ omapi_message_object_t *message; /* Incoming message. */ omapi_data_string_t *name; /* Incoming name. */ omapi_typed_data_t *value; /* Incoming value. */ isc_result_t verify_result; omapi_remote_auth_t *default_auth; /* Default authinfo to use. */ omapi_remote_auth_t *remote_auth_list; /* Authenticators active on this connection. */ isc_boolean_t insecure; /* Set to allow unauthenticated messages. */ isc_result_t (*verify_auth) (omapi_object_t *, omapi_auth_key_t *); } omapi_protocol_object_t; typedef struct { OMAPI_OBJECT_PREAMBLE; isc_boolean_t insecure; /* Set to allow unauthenticated messages. */ isc_result_t (*verify_auth) (omapi_object_t *, omapi_auth_key_t *); } omapi_protocol_listener_object_t; #include typedef struct __omapi_listener_object { OMAPI_OBJECT_PREAMBLE; int socket; /* Connection socket. */ int index; struct sockaddr_in address; isc_result_t (*verify_addr) (omapi_object_t *, omapi_addr_t *); } omapi_listener_object_t; typedef struct __omapi_connection_object { OMAPI_OBJECT_PREAMBLE; int socket; /* Connection socket. */ int32_t index; omapi_connection_state_t state; struct sockaddr_in remote_addr; struct sockaddr_in local_addr; omapi_addr_list_t *connect_list; /* List of addresses to which to connect. */ int cptr; /* Current element we are connecting to. */ u_int32_t bytes_needed; /* Bytes of input needed before wakeup. */ u_int32_t in_bytes; /* Bytes of input already buffered. */ omapi_buffer_t *inbufs; u_int32_t out_bytes; /* Bytes of output in buffers. */ omapi_buffer_t *outbufs; omapi_listener_object_t *listener; /* Listener that accepted this connection, if any. */ DST_KEY *in_key; /* Authenticator signing incoming data. */ void *in_context; /* Input hash context. */ DST_KEY *out_key; /* Authenticator signing outgoing data. */ void *out_context; /* Output hash context. */ } omapi_connection_object_t; typedef struct __omapi_io_object { OMAPI_OBJECT_PREAMBLE; struct __omapi_io_object *next; int (*readfd) (omapi_object_t *); int (*writefd) (omapi_object_t *); isc_result_t (*reader) (omapi_object_t *); isc_result_t (*writer) (omapi_object_t *); isc_result_t (*reaper) (omapi_object_t *); } omapi_io_object_t; typedef struct __omapi_generic_object { OMAPI_OBJECT_PREAMBLE; omapi_value_t **values; u_int8_t *changed; int nvalues, va_max; } omapi_generic_object_t; typedef struct __omapi_waiter_object { OMAPI_OBJECT_PREAMBLE; int ready; isc_result_t waitstatus; struct __omapi_waiter_object *next; } omapi_waiter_object_t; #define OMAPI_HANDLE_TABLE_SIZE 120 typedef struct __omapi_handle_table { omapi_handle_t first, limit; omapi_handle_t next; int leafp; union { omapi_object_t *object; struct __omapi_handle_table *table; } children [OMAPI_HANDLE_TABLE_SIZE]; } omapi_handle_table_t; #include OMAPI_OBJECT_ALLOC_DECL (omapi_protocol, omapi_protocol_object_t, omapi_type_protocol) OMAPI_OBJECT_ALLOC_DECL (omapi_protocol_listener, omapi_protocol_listener_object_t, omapi_type_protocol_listener) OMAPI_OBJECT_ALLOC_DECL (omapi_connection, omapi_connection_object_t, omapi_type_connection) OMAPI_OBJECT_ALLOC_DECL (omapi_listener, omapi_listener_object_t, omapi_type_listener) OMAPI_OBJECT_ALLOC_DECL (omapi_io, omapi_io_object_t, omapi_type_io_object) OMAPI_OBJECT_ALLOC_DECL (omapi_waiter, omapi_waiter_object_t, omapi_type_waiter) OMAPI_OBJECT_ALLOC_DECL (omapi_generic, omapi_generic_object_t, omapi_type_generic) OMAPI_OBJECT_ALLOC_DECL (omapi_message, omapi_message_object_t, omapi_type_message) isc_result_t omapi_connection_sign_data (int mode, DST_KEY *key, void **context, const unsigned char *data, const unsigned len, omapi_typed_data_t **result); isc_result_t omapi_listener_connect (omapi_connection_object_t **obj, omapi_listener_object_t *listener, int socket, struct sockaddr_in *remote_addr); void omapi_listener_trace_setup (void); void omapi_connection_trace_setup (void); void omapi_buffer_trace_setup (void); void omapi_connection_register (omapi_connection_object_t *, const char *, int); void trace_mr_init (void); OMAPI_ARRAY_TYPE_DECL(omapi_listener, omapi_listener_object_t); OMAPI_ARRAY_TYPE_DECL(omapi_connection, omapi_connection_object_t); extern int log_priority; extern int log_perror; extern void (*log_cleanup) (void); void log_fatal (const char *, ...) __attribute__((__format__(__printf__,1,2))); int log_error (const char *, ...) __attribute__((__format__(__printf__,1,2))); int log_info (const char *, ...) __attribute__((__format__(__printf__,1,2))); int log_debug (const char *, ...) __attribute__((__format__(__printf__,1,2))); void do_percentm (char *obuf, const char *ibuf); isc_result_t uerr2isc (int); isc_result_t ns_rcode_to_isc (int); extern omapi_message_object_t *omapi_registered_messages; #endif /* __OMAPIP_OMAPIP_P_H__ */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/trace.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/trace.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/omapip/trace.h (revision 131136) @@ -1,124 +1,115 @@ /* trace.h Definitions for omapi tracing facility... */ /* - * Copyright (c) 2001 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2001-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems 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 + * about Internet Systems Consortium, see http://www.isc.org/. To * learn more about Nominum, Inc., see ``http://www.nominum.com''. */ #define TRACEFILE_MAGIC 0x64484370UL /* dHCp */ #define TRACEFILE_VERSION 1 /* The first thing in a trace file is the header, which basically just defines the version of the file. */ typedef struct { u_int32_t magic; /* Magic number for trace file. */ u_int32_t version; /* Version of file. */ int32_t hlen; /* Length of this header. */ int32_t phlen; /* Length of packet headers. */ } tracefile_header_t; /* The trace file is composed of a bunch of trace packets. Each such packet has a type, followed by a length, followed by a timestamp, followed by the actual contents of the packet. The type indexes are not fixed - they are allocated either on readback or when writing a trace file. One index type is reserved - type zero means that this record is a type name to index mapping. */ typedef struct { u_int32_t type_index; /* Index to the type of handler that this packet needs. */ u_int32_t length; /* Length of the packet. This includes everything except the fixed header. */ u_int32_t when; /* When the packet was written. */ u_int32_t pad; /* Round this out to a quad boundary. */ } tracepacket_t; #define TRACE_INDEX_MAPPING_SIZE 4 /* trace_index_mapping_t less name. */ typedef struct { u_int32_t index; char name [1]; } trace_index_mapping_t; struct trace_type; /* forward */ typedef struct trace_type trace_type_t; struct trace_type { trace_type_t *next; int index; char *name; void *baggage; void (*have_packet) (trace_type_t *, unsigned, char *); void (*stop_tracing) (trace_type_t *); }; typedef struct trace_iov { const char *buf; unsigned len; } trace_iov_t; typedef struct { u_int16_t addrtype; u_int16_t addrlen; u_int8_t address [16]; u_int16_t port; } trace_addr_t; void trace_free_all (void); int trace_playback (void); int trace_record (void); isc_result_t trace_init (void (*set_time) (u_int32_t), const char *, int); isc_result_t trace_begin (const char *, const char *, int); isc_result_t trace_write_packet (trace_type_t *, unsigned, const char *, const char *, int); isc_result_t trace_write_packet_iov (trace_type_t *, int, trace_iov_t *, const char *, int); void trace_type_stash (trace_type_t *); trace_type_t *trace_type_register (const char *, void *, void (*) (trace_type_t *, unsigned, char *), void (*) (trace_type_t *), const char *, int); void trace_stop (void); void trace_index_map_input (trace_type_t *, unsigned, char *); void trace_index_stop_tracing (trace_type_t *); void trace_replay_init (void); void trace_file_replay (const char *); isc_result_t trace_get_next_packet (trace_type_t **, tracepacket_t *, char **, unsigned *, unsigned *); isc_result_t trace_get_file (trace_type_t *, const char *, unsigned *, char **); isc_result_t trace_get_packet (trace_type_t **, unsigned *, char **); time_t trace_snoop_time (trace_type_t **); Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/osdep.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/osdep.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/osdep.h (revision 131136) @@ -1,316 +1,315 @@ /* osdep.h Operating system dependencies... */ /* - * Copyright (c) 1996-1999 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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''. */ #if !defined (__ISC_DHCP_OSDEP_H__) #define __ISC_DHCP_OSDEP_H__ #include "site.h" /* Porting:: If you add a new network API, you must add a check for it below: */ #if !defined (USE_SOCKETS) && \ !defined (USE_SOCKET_SEND) && \ !defined (USE_SOCKET_RECEIVE) && \ !defined (USE_RAW_SOCKETS) && \ !defined (USE_RAW_SEND) && \ !defined (USE_SOCKET_RECEIVE) && \ !defined (USE_BPF) && \ !defined (USE_BPF_SEND) && \ !defined (USE_BPF_RECEIVE) && \ !defined (USE_LPF) && \ !defined (USE_LPF_SEND) && \ !defined (USE_LPF_RECEIVE) && \ !defined (USE_NIT) && \ !defined (USE_NIT_SEND) && \ !defined (USE_NIT_RECEIVE) && \ !defined (USR_DLPI_SEND) && \ !defined (USE_DLPI_RECEIVE) # define USE_DEFAULT_NETWORK #endif #if !defined (TIME_MAX) # define TIME_MAX 2147483647 #endif /* Porting:: If you add a new system configuration file, include it here: */ #if defined (sun) # if defined (__svr4__) || defined (__SVR4) # include "cf/sunos5-5.h" # else # include "cf/sunos4.h" # endif #endif #ifdef aix # include "cf/aix.h" #endif #ifdef bsdi # include "cf/bsdos.h" #endif #ifdef __NetBSD__ # include "cf/netbsd.h" #endif #ifdef __FreeBSD__ # include "cf/freebsd.h" #endif #ifdef OpenBSD # include "cf/openbsd.h" #endif #if defined (__osf__) && defined (__alpha) # include "cf/alphaosf.h" #endif #ifdef ultrix # include "cf/ultrix.h" #endif #ifdef linux # include "cf/linux.h" #endif #ifdef SCO # include "cf/sco.h" #endif #if defined (hpux) || defined (__hpux) # include "cf/hpux.h" #endif #ifdef __QNX__ # include "cf/qnx.h" #endif #ifdef __CYGWIN32__ # include "cf/cygwin32.h" #endif #ifdef __APPLE__ # include "cf/rhapsody.h" #else # if defined (NeXT) # include "cf/nextstep.h" # endif +#endif + +/* snprintf/vsnprintf hacks. for systems with no libc versions only. */ +#ifdef NO_SNPRINTF + extern int isc_print_snprintf(char *, size_t, const char *, ...); + extern int isc_print_vsnprintf(char *, size_t, const char *, va_list ap); +# define snprintf isc_print_snprintf +# define vsnprintf isc_print_vsnprintf #endif /* Porting:: If you add a new network API, and have it set up so that it can be used for sending or receiving, but doesn't have to be used for both, then set up an ifdef like the ones below: */ #ifdef USE_SOCKETS # define USE_SOCKET_SEND # define USE_SOCKET_RECEIVE #endif #ifdef USE_RAW_SOCKETS # define USE_RAW_SEND # define USE_SOCKET_RECEIVE #endif #ifdef USE_BPF # define USE_BPF_SEND # define USE_BPF_RECEIVE #endif #ifdef USE_LPF # define USE_LPF_SEND # define USE_LPF_RECEIVE #endif #ifdef USE_NIT # define USE_NIT_SEND # define USE_NIT_RECEIVE #endif #ifdef USE_DLPI # define USE_DLPI_SEND # define USE_DLPI_RECEIVE #endif #ifdef USE_UPF # define USE_UPF_SEND # define USE_UPF_RECEIVE #endif /* Porting:: If you add support for sending packets directly out an interface, and your support does not do ARP or routing, you must use a fallback mechanism to deal with packets that need to be sent to routers. Currently, all low-level packet interfaces use BSD sockets as a fallback. */ #if defined (USE_BPF_SEND) || defined (USE_NIT_SEND) || \ defined (USE_DLPI_SEND) || defined (USE_UPF_SEND) || \ defined (USE_LPF_SEND) || \ (defined (USE_SOCKET_SEND) && defined (HAVE_SO_BINDTODEVICE)) # define USE_SOCKET_FALLBACK # define USE_FALLBACK #endif /* Porting:: If you add support for sending packets directly out an interface and need to be able to assemble packets, add the USE_XXX_SEND definition for your interface to the list tested below. */ #if defined (USE_RAW_SEND) || defined (USE_BPF_SEND) || \ defined (USE_NIT_SEND) || defined (USE_UPF_SEND) || \ defined (USE_DLPI_SEND) || defined (USE_LPF_SEND) # define PACKET_ASSEMBLY #endif /* Porting:: If you add support for receiving packets directly from an interface and need to be able to decode raw packets, add the USE_XXX_RECEIVE definition for your interface to the list tested below. */ #if defined (USE_RAW_RECEIVE) || defined (USE_BPF_SEND) || \ defined (USE_NIT_RECEIVE) || defined (USE_UPF_RECEIVE) || \ defined (USE_DLPI_RECEIVE) || defined (USE_LPF_RECEIVE) # define PACKET_DECODING #endif /* If we don't have a DLPI packet filter, we have to filter in userland. Probably not worth doing, actually. */ #if defined (USE_DLPI_RECEIVE) && !defined (USE_DLPI_PFMOD) # define USERLAND_FILTER #endif /* jmp_buf is assumed to be a struct unless otherwise defined in the system header. */ #ifndef jbp_decl # define jbp_decl(x) jmp_buf *x #endif #ifndef jref # define jref(x) (&(x)) #endif #ifndef jdref # define jdref(x) (*(x)) #endif #ifndef jrefproto # define jrefproto jmp_buf * #endif #ifndef BPF_FORMAT # define BPF_FORMAT "/dev/bpf%d" #endif #if defined (F_SETFD) && !defined (HAVE_SETFD) # define HAVE_SETFD #endif #if defined (IFF_POINTOPOINT) && !defined (HAVE_IFF_POINTOPOINT) # define HAVE_IFF_POINTOPOINT #endif #if defined (AF_LINK) && !defined (HAVE_AF_LINK) # define HAVE_AF_LINK #endif #if defined (ARPHRD_TUNNEL) && !defined (HAVE_ARPHRD_TUNNEL) # define HAVE_ARPHRD_TUNNEL #endif #if defined (ARPHRD_LOOPBACK) && !defined (HAVE_ARPHRD_LOOPBACK) # define HAVE_ARPHRD_LOOPBACK #endif #if defined (ARPHRD_ROSE) && !defined (HAVE_ARPHRD_ROSE) # define HAVE_ARPHRD_ROSE #endif #if defined (ARPHRD_IEEE802) && !defined (HAVE_ARPHRD_IEEE802) # define HAVE_ARPHRD_IEEE802 #endif #if defined (ARPHRD_IEEE802_TR) && !defined (HAVE_ARPHRD_IEEE802_TR) # define HAVE_ARPHRD_IEEE802_TR #endif #if defined (ARPHRD_FDDI) && !defined (HAVE_ARPHRD_FDDI) # define HAVE_ARPHRD_FDDI #endif #if defined (ARPHRD_AX25) && !defined (HAVE_ARPHRD_AX25) # define HAVE_ARPHRD_AX25 #endif #if defined (ARPHRD_NETROM) && !defined (HAVE_ARPHRD_NETROM) # define HAVE_ARPHRD_NETROM #endif #if defined (ARPHRD_METRICOM) && !defined (HAVE_ARPHRD_METRICOM) # define HAVE_ARPHRD_METRICOM #endif #if defined (SO_BINDTODEVICE) && !defined (HAVE_SO_BINDTODEVICE) # define HAVE_SO_BINDTODEVICE #endif #if defined (AF_LINK) && !defined (HAVE_AF_LINK) # define HAVE_AF_LINK #endif /* Linux needs to define SHUT_* in /usr/include/sys/socket.h someday... */ #if !defined (SHUT_RD) # define SHUT_RD 0 #endif #if !defined (SOCKLEN_T) #define SOCKLEN_T socklen_t #endif #endif /* __ISC_DHCP_OSDEP_H__ */ Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/statement.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/statement.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/statement.h (revision 131136) @@ -1,113 +1,104 @@ /* statement.h Definitions for executable statements... */ /* - * Copyright (c) 1996-1999 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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''. */ struct executable_statement { int refcnt; struct executable_statement *next; enum statement_op { null_statement, if_statement, add_statement, eval_statement, break_statement, default_option_statement, supersede_option_statement, append_option_statement, prepend_option_statement, send_option_statement, statements_statement, on_statement, switch_statement, case_statement, default_statement, set_statement, unset_statement, let_statement, define_statement, log_statement, return_statement } op; union { struct { struct executable_statement *tc, *fc; struct expression *expr; } ie; struct expression *eval; struct expression *retval; struct class *add; struct option_cache *option; struct option_cache *supersede; struct option_cache *prepend; struct option_cache *append; struct executable_statement *statements; struct { int evtypes; # define ON_COMMIT 1 # define ON_EXPIRY 2 # define ON_RELEASE 4 # define ON_TRANSMISSION 8 struct executable_statement *statements; } on; struct { struct expression *expr; struct executable_statement *statements; } s_switch; struct expression *c_case; struct { char *name; struct expression *expr; struct executable_statement *statements; } set, let; char *unset; struct { enum { log_priority_fatal, log_priority_error, log_priority_debug, log_priority_info } priority; struct expression *expr; } log; } data; }; Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/tree.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/tree.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/tree.h (revision 131136) @@ -1,346 +1,337 @@ /* tree.h Definitions for address trees... */ /* - * Copyright (c) 1996-2001 Internet Software Consortium. - * All rights reserved. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * 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. + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ * - * This software has been written for the Internet Software Consortium + * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see + * To learn more about Internet Systems 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''. */ /* A pair of pointers, suitable for making a linked list. */ typedef struct _pair { caddr_t car; struct _pair *cdr; } *pair; struct option_chain_head { int refcnt; pair first; }; struct enumeration_value { const char *name; u_int8_t value; }; struct enumeration { struct enumeration *next; const char *name; struct enumeration_value *values; }; /* Tree node types... */ #define TREE_CONCAT 1 #define TREE_HOST_LOOKUP 2 #define TREE_CONST 3 #define TREE_LIMIT 4 #define TREE_DATA_EXPR 5 /* A data buffer with a reference count. */ struct buffer { int refcnt; unsigned char data [1]; }; /* XXX The mechanism by which data strings are returned is currently XXX broken: rather than returning an ephemeral pointer, we create XXX a reference to the data in the caller's space, which the caller XXX then has to dereference - instead, the reference should be XXX ephemeral by default and be made a persistent reference explicitly. */ /* XXX on the other hand, it seems to work pretty nicely, so maybe the XXX above comment is meshuggenah. */ /* A string of data bytes, possibly accompanied by a larger buffer. */ struct data_string { struct buffer *buffer; const unsigned char *data; unsigned len; /* Does not include NUL terminator, if any. */ int terminated; }; enum expression_context { context_any, /* indefinite */ context_boolean, context_data, context_numeric, context_dns, context_data_or_numeric, /* indefinite */ context_function }; struct fundef { int refcnt; struct string_list *args; struct executable_statement *statements; }; struct binding_value { int refcnt; enum { binding_boolean, binding_data, binding_numeric, binding_dns, binding_function } type; union value { struct data_string data; unsigned long intval; int boolean; #if defined (NSUPDATE) ns_updrec *dns; #endif struct fundef *fundef; struct binding_value *bv; } value; }; struct binding { struct binding *next; char *name; struct binding_value *value; }; struct binding_scope { int refcnt; struct binding_scope *outer; struct binding *bindings; }; /* Expression tree structure. */ enum expr_op { expr_none, expr_match, expr_check, expr_equal, expr_substring, expr_suffix, expr_concat, expr_host_lookup, expr_and, expr_or, expr_not, expr_option, expr_hardware, expr_packet, expr_const_data, expr_extract_int8, expr_extract_int16, expr_extract_int32, expr_encode_int8, expr_encode_int16, expr_encode_int32, expr_const_int, expr_exists, expr_encapsulate, expr_known, expr_reverse, expr_leased_address, expr_binary_to_ascii, expr_config_option, expr_host_decl_name, expr_pick_first_value, expr_lease_time, expr_dns_transaction, expr_static, expr_ns_add, expr_ns_delete, expr_ns_exists, expr_ns_not_exists, expr_not_equal, expr_null, expr_variable_exists, expr_variable_reference, expr_filename, expr_sname, expr_arg, expr_funcall, expr_function, expr_add, expr_subtract, expr_multiply, expr_divide, expr_remainder, expr_binary_and, expr_binary_or, expr_binary_xor, expr_client_state }; struct expression { int refcnt; enum expr_op op; union { struct { struct expression *expr; struct expression *offset; struct expression *len; } substring; struct expression *equal [2]; struct expression *and [2]; struct expression *or [2]; struct expression *not; struct expression *add; struct expression *subtract; struct expression *multiply; struct expression *divide; struct expression *remainder; struct collection *check; struct { struct expression *expr; struct expression *len; } suffix; struct option *option; struct option *config_option; struct { struct expression *offset; struct expression *len; } packet; struct data_string const_data; struct expression *extract_int; struct expression *encode_int; unsigned long const_int; struct expression *concat [2]; struct dns_host_entry *host_lookup; struct option *exists; struct data_string encapsulate; struct { struct expression *base; struct expression *width; struct expression *seperator; struct expression *buffer; } b2a; struct { struct expression *width; struct expression *buffer; } reverse; struct { struct expression *car; struct expression *cdr; } pick_first_value; struct { struct expression *car; struct expression *cdr; } dns_transaction; struct { unsigned rrclass; unsigned rrtype; struct expression *rrname; struct expression *rrdata; struct expression *ttl; } ns_add; struct { unsigned rrclass; unsigned rrtype; struct expression *rrname; struct expression *rrdata; } ns_delete, ns_exists, ns_not_exists; char *variable; struct { struct expression *val; struct expression *next; } arg; struct { char *name; struct expression *arglist; } funcall; struct fundef *func; } data; int flags; # define EXPR_EPHEMERAL 1 }; /* DNS host entry structure... */ struct dns_host_entry { int refcnt; TIME timeout; struct data_string data; char hostname [1]; }; struct option_cache; /* forward */ struct packet; /* forward */ struct option_state; /* forward */ struct decoded_option_state; /* forward */ struct lease; /* forward */ struct client_state; /* forward */ struct universe { const char *name; struct option_cache *(*lookup_func) (struct universe *, struct option_state *, unsigned); void (*save_func) (struct universe *, struct option_state *, struct option_cache *); void (*foreach) (struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *, void (*) (struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *)); void (*delete_func) (struct universe *universe, struct option_state *, int); int (*option_state_dereference) (struct universe *, struct option_state *, const char *, int); int (*decode) (struct option_state *, const unsigned char *, unsigned, struct universe *); int (*encapsulate) (struct data_string *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *); void (*store_tag) PROTO ((unsigned char *, u_int32_t)); void (*store_length) PROTO ((unsigned char *, u_int32_t)); int tag_size, length_size; option_hash_t *hash; struct option *options [256]; struct option *enc_opt; int index; }; struct option { const char *name; const char *format; struct universe *universe; unsigned code; }; Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/version.h =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/version.h (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/includes/version.h (revision 131136) @@ -1,3 +1,3 @@ /* Current version of ISC DHCP Distribution. */ -#define DHCP_VERSION "V3.0.1rc12" +#define DHCP_VERSION "V3.0.1rc14" Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/Makefile.dist =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/Makefile.dist (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/Makefile.dist (revision 131136) @@ -1,69 +1,73 @@ # Makefile.dist # -# 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: +# Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") +# Copyright (c) 1996-2003 by Internet Software Consortium # -# http://www.isc.org/isc-license-1.0.html. +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. # -# 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. +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # -# Support and other services are available for ISC products - see -# http://www.isc.org for more information. -# +# Internet Systems Consortium, Inc. +# 950 Charter Street +# Redwood City, CA 94063 +# +# http://www.isc.org/ CATMANPAGES = dhcpctl.cat3 SEDMANPAGES = dhcpctl.man3 MAN = dhcpctl.3 SRC = res_mkupdate.c res_init.c res_update.c res_send.c res_comp.c \ res_sendsigned.c res_findzonecut.c res_query.c res_mkquery.c \ ns_date.c ns_parse.c ns_sign.c ns_name.c ns_samedomain.c ns_verify.c OBJ = res_mkupdate.o res_init.o res_update.o res_send.o res_comp.o \ res_sendsigned.o res_findzonecut.o res_query.o res_mkquery.o \ ns_date.o ns_parse.o ns_sign.o ns_name.o ns_samedomain.o ns_verify.o INCLUDES = $(BINDINC) -I$(TOP)/includes CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS) -DHMAC_MD5 -DMINIRES_LIB all: libres.a install: libres.a: $(OBJ) rm -f res.a ar cruv libres.a $(OBJ) $(RANLIB) libres.a depend: $(MKDEP) $(INCLUDES) $(PREDEFINES) $(SRC) clean: -rm -f $(OBJ) libres.a realclean: clean -rm -f *~ $(CATMANPAGES) $(SEDMANPAGES) distclean: realclean -rm -f Makefile links: @for foo in $(SRC) $(MAN) $(HDRS); do \ if [ ! -b $$foo ]; then \ rm -f $$foo; \ fi; \ ln -s $(TOP)/minires/$$foo $$foo; \ done dhcpctl.cat3: dhcpctl.man3 nroff -man dhcpctl.man3 >dhcpctl.cat3 dhcpctl.man3: dhcpctl.3 sed -e "s#ETCDIR#$(ETC)#g" -e "s#DBDIR#$(VARDB)#g" \ -e "s#RUNDIR#$(VARRUN)#g" < dhcpctl.3 >dhcpctl.man3 # Dependencies (semi-automatically-generated) Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/ns_date.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/ns_date.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/ns_date.c (revision 131136) @@ -1,129 +1,135 @@ /* - * Copyright (c) 1999 by Internet Software Consortium. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ */ #ifndef lint -static const char rcsid[] = "$Id: ns_date.c,v 1.2 2000/04/11 01:58:39 mellon Exp $"; +static const char rcsid[] = "$Id: ns_date.c,v 1.2.2.1 2004/06/10 17:59:40 dhankins Exp $"; #endif /* Import. */ #include #include #include #include #include #include #include #include #include "minires/minires.h" #include "arpa/nameser.h" #ifdef SPRINTF_CHAR # define SPRINTF(x) strlen(sprintf/**/x) #else # define SPRINTF(x) ((size_t)sprintf x) #endif /* Forward. */ static int datepart(const char *, int, int, int, int *); /* Public. */ /* Convert a date in ASCII into the number of seconds since 1 January 1970 (GMT assumed). Format is yyyymmddhhmmss, all digits required, no spaces allowed. */ u_int32_t ns_datetosecs(const char *cp, int *errp) { struct tm time; u_int32_t result; int mdays, i; static const int days_per_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if (strlen(cp) != 14) { *errp = 1; return (0); } *errp = 0; memset(&time, 0, sizeof time); time.tm_year = datepart(cp + 0, 4, 1990, 9999, errp) - 1900; time.tm_mon = datepart(cp + 4, 2, 01, 12, errp) - 1; time.tm_mday = datepart(cp + 6, 2, 01, 31, errp); time.tm_hour = datepart(cp + 8, 2, 00, 23, errp); time.tm_min = datepart(cp + 10, 2, 00, 59, errp); time.tm_sec = datepart(cp + 12, 2, 00, 59, errp); if (*errp) /* Any parse errors? */ return (0); /* * OK, now because timegm() is not available in all environments, * we will do it by hand. Roll up sleeves, curse the gods, begin! */ #define SECS_PER_DAY ((u_int32_t)24*60*60) #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) result = time.tm_sec; /* Seconds */ result += time.tm_min * 60; /* Minutes */ result += time.tm_hour * (60*60); /* Hours */ result += (time.tm_mday - 1) * SECS_PER_DAY; /* Days */ /* Months are trickier. Look without leaping, then leap */ mdays = 0; for (i = 0; i < time.tm_mon; i++) mdays += days_per_month[i]; result += mdays * SECS_PER_DAY; /* Months */ if (time.tm_mon > 1 && isleap(1900+time.tm_year)) result += SECS_PER_DAY; /* Add leapday for this year */ /* First figure years without leapdays, then add them in. */ /* The loop is slow, FIXME, but simple and accurate. */ result += (time.tm_year - 70) * (SECS_PER_DAY*365); /* Years */ for (i = 70; i < time.tm_year; i++) if (isleap(1900+i)) result += SECS_PER_DAY; /* Add leapday for prev year */ return (result); } /* Private. */ /* * Parse part of a date. Set error flag if any error. * Don't reset the flag if there is no error. */ static int datepart(const char *buf, int size, int min, int max, int *errp) { int result = 0; int i; for (i = 0; i < size; i++) { if (!isdigit(buf[i])) *errp = 1; result = (result * 10) + buf[i] - '0'; } if (result < min) *errp = 1; if (result > max) *errp = 1; return (result); } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/ns_name.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/ns_name.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/ns_name.c (revision 131136) @@ -1,645 +1,651 @@ /* - * Copyright (c) 1996,1999-2003 by Internet Software Consortium. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ */ #ifndef lint -static const char rcsid[] = "$Id: ns_name.c,v 1.1.2.4 2003/01/14 23:15:06 dhankins Exp $"; +static const char rcsid[] = "$Id: ns_name.c,v 1.1.2.5 2004/06/10 17:59:40 dhankins Exp $"; #endif #include #include #include #include #include #include #include "minires/minires.h" #include "arpa/nameser.h" /* Data. */ static const char digits[] = "0123456789"; /* Forward. */ static int special(int); static int printable(int); static int dn_find(const u_char *, const u_char *, const u_char * const *, const u_char * const *); /* Public. */ /* * ns_name_ntop(src, dst, dstsiz) * Convert an encoded domain name to printable ascii as per RFC1035. * return: * Number of bytes written to buffer, or -1 (with errno set) * notes: * The root is returned as "." * All other domains are returned in non absolute form */ int ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) { const u_char *cp; char *dn, *eom; u_char c; u_int n; cp = src; dn = dst; eom = dst + dstsiz; while ((n = *cp++) != 0) { if ((n & NS_CMPRSFLGS) != 0) { /* Some kind of compression pointer. */ errno = EMSGSIZE; return (-1); } if (dn != dst) { if (dn >= eom) { errno = EMSGSIZE; return (-1); } *dn++ = '.'; } if (dn + n >= eom) { errno = EMSGSIZE; return (-1); } for ((void)NULL; n > 0; n--) { c = *cp++; if (special(c)) { if (dn + 1 >= eom) { errno = EMSGSIZE; return (-1); } *dn++ = '\\'; *dn++ = (char)c; } else if (!printable(c)) { if (dn + 3 >= eom) { errno = EMSGSIZE; return (-1); } *dn++ = '\\'; *dn++ = digits[c / 100]; *dn++ = digits[(c % 100) / 10]; *dn++ = digits[c % 10]; } else { if (dn >= eom) { errno = EMSGSIZE; return (-1); } *dn++ = (char)c; } } } if (dn == dst) { if (dn >= eom) { errno = EMSGSIZE; return (-1); } *dn++ = '.'; } if (dn >= eom) { errno = EMSGSIZE; return (-1); } *dn++ = '\0'; return (dn - dst); } /* * ns_name_pton(src, dst, dstsiz) * Convert a ascii string into an encoded domain name as per RFC1035. * return: * -1 if it fails * 1 if string was fully qualified * 0 is string was not fully qualified * notes: * Enforces label and domain length limits. */ int ns_name_pton(const char *src, u_char *dst, size_t dstsiz) { u_char *label, *bp, *eom; int c, n, escaped; char *cp; escaped = 0; bp = dst; eom = dst + dstsiz; label = bp++; while ((c = *src++) != 0) { if (escaped) { if ((cp = strchr(digits, c)) != NULL) { n = (cp - digits) * 100; if ((c = *src++) == 0 || (cp = strchr(digits, c)) == NULL) { errno = EMSGSIZE; return (-1); } n += (cp - digits) * 10; if ((c = *src++) == 0 || (cp = strchr(digits, c)) == NULL) { errno = EMSGSIZE; return (-1); } n += (cp - digits); if (n > 255) { errno = EMSGSIZE; return (-1); } c = n; } escaped = 0; } else if (c == '\\') { escaped = 1; continue; } else if (c == '.') { c = (bp - label - 1); if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ errno = EMSGSIZE; return (-1); } if (label >= eom) { errno = EMSGSIZE; return (-1); } *label = c; /* Fully qualified ? */ if (*src == '\0') { if (c != 0) { if (bp >= eom) { errno = EMSGSIZE; return (-1); } *bp++ = '\0'; } if ((bp - dst) > MAXCDNAME) { errno = EMSGSIZE; return (-1); } return (1); } if (c == 0 || *src == '.') { errno = EMSGSIZE; return (-1); } label = bp++; continue; } if (bp >= eom) { errno = EMSGSIZE; return (-1); } *bp++ = (u_char)c; } c = (bp - label - 1); if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ errno = EMSGSIZE; return (-1); } if (label >= eom) { errno = EMSGSIZE; return (-1); } *label = c; if (c != 0) { if (bp >= eom) { errno = EMSGSIZE; return (-1); } *bp++ = 0; } if ((bp - dst) > MAXCDNAME) { /* src too big */ errno = EMSGSIZE; return (-1); } return (0); } /* * ns_name_ntol(src, dst, dstsiz) * Convert a network strings labels into all lowercase. * return: * Number of bytes written to buffer, or -1 (with errno set) * notes: * Enforces label and domain length limits. */ int ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz) { const u_char *cp; u_char *dn, *eom; u_char c; u_int n; cp = src; dn = dst; eom = dst + dstsiz; if (dn >= eom) { errno = EMSGSIZE; return (-1); } while ((n = *cp++) != 0) { if ((n & NS_CMPRSFLGS) != 0) { /* Some kind of compression pointer. */ errno = EMSGSIZE; return (-1); } *dn++ = n; if (dn + n >= eom) { errno = EMSGSIZE; return (-1); } for ((void)NULL; n > 0; n--) { c = *cp++; if (isupper(c)) *dn++ = tolower(c); else *dn++ = c; } } *dn++ = '\0'; return (dn - dst); } /* * ns_name_unpack(msg, eom, src, dst, dstsiz) * Unpack a domain name from a message, source may be compressed. * return: * -1 if it fails, or consumed octets if it succeeds. */ int ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, u_char *dst, size_t dstsiz) { const u_char *srcp, *dstlim; u_char *dstp; unsigned n; int len; int checked; len = -1; checked = 0; dstp = dst; srcp = src; dstlim = dst + dstsiz; if (srcp < msg || srcp >= eom) { errno = EMSGSIZE; return (-1); } /* Fetch next label in domain name. */ while ((n = *srcp++) != 0) { /* Check for indirection. */ switch (n & NS_CMPRSFLGS) { case 0: /* Limit checks. */ if (dstp + n + 1 >= dstlim || srcp + n >= eom) { errno = EMSGSIZE; return (-1); } checked += n + 1; *dstp++ = n; memcpy(dstp, srcp, n); dstp += n; srcp += n; break; case NS_CMPRSFLGS: if (srcp >= eom) { errno = EMSGSIZE; return (-1); } if (len < 0) len = srcp - src + 1; srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff)); if (srcp < msg || srcp >= eom) { /* Out of range. */ errno = EMSGSIZE; return (-1); } checked += 2; /* * Check for loops in the compressed name; * if we've looked at the whole message, * there must be a loop. */ if (checked >= eom - msg) { errno = EMSGSIZE; return (-1); } break; default: errno = EMSGSIZE; return (-1); /* flag error */ } } *dstp = '\0'; if (len < 0) len = srcp - src; return (len); } /* * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr) * Pack domain name 'domain' into 'comp_dn'. * return: * Size of the compressed name, or -1. * notes: * 'dnptrs' is an array of pointers to previous compressed names. * dnptrs[0] is a pointer to the beginning of the message. The array * ends with NULL. * 'lastdnptr' is a pointer to the end of the array pointed to * by 'dnptrs'. * Side effects: * The list of pointers in dnptrs is updated for labels inserted into * the message as we compress the name. If 'dnptr' is NULL, we don't * try to compress names. If 'lastdnptr' is NULL, we don't update the * list. */ int ns_name_pack(const u_char *src, u_char *dst, unsigned dstsiz, const u_char **dnptrs, const u_char **lastdnptr) { u_char *dstp; const u_char **cpp, **lpp, *eob, *msg; const u_char *srcp; unsigned n; int l; srcp = src; dstp = dst; eob = dstp + dstsiz; lpp = cpp = NULL; if (dnptrs != NULL) { if ((msg = *dnptrs++) != NULL) { for (cpp = dnptrs; *cpp != NULL; cpp++) (void)NULL; lpp = cpp; /* end of list to search */ } } else msg = NULL; /* make sure the domain we are about to add is legal */ l = 0; do { n = *srcp; if ((n & NS_CMPRSFLGS) != 0) { errno = EMSGSIZE; return (-1); } l += n + 1; if (l > MAXCDNAME) { errno = EMSGSIZE; return (-1); } srcp += n + 1; } while (n != 0); /* from here on we need to reset compression pointer array on error */ srcp = src; do { /* Look to see if we can use pointers. */ n = *srcp; if (n != 0 && msg != NULL) { l = dn_find(srcp, msg, (const u_char * const *)dnptrs, (const u_char * const *)lpp); if (l >= 0) { if (dstp + 1 >= eob) { goto cleanup; } *dstp++ = (l >> 8) | NS_CMPRSFLGS; *dstp++ = l % 256; return (dstp - dst); } /* Not found, save it. */ if (lastdnptr != NULL && cpp < lastdnptr - 1 && (dstp - msg) < 0x4000) { *cpp++ = dstp; *cpp = NULL; } } /* copy label to buffer */ if (n & NS_CMPRSFLGS) { /* Should not happen. */ goto cleanup; } if (dstp + 1 + n >= eob) { goto cleanup; } memcpy(dstp, srcp, n + 1); srcp += n + 1; dstp += n + 1; } while (n != 0); if (dstp > eob) { cleanup: if (msg != NULL) *lpp = NULL; errno = EMSGSIZE; return (-1); } return (dstp - dst); } /* * ns_name_uncompress(msg, eom, src, dst, dstsiz) * Expand compressed domain name to presentation format. * return: * Number of bytes read out of `src', or -1 (with errno set). * note: * Root domain returns as "." not "". */ int ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src, char *dst, size_t dstsiz) { u_char tmp[NS_MAXCDNAME]; int n; if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1) return (-1); if (ns_name_ntop(tmp, dst, dstsiz) == -1) return (-1); return (n); } /* * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr) * Compress a domain name into wire format, using compression pointers. * return: * Number of bytes consumed in `dst' or -1 (with errno set). * notes: * 'dnptrs' is an array of pointers to previous compressed names. * dnptrs[0] is a pointer to the beginning of the message. * The list ends with NULL. 'lastdnptr' is a pointer to the end of the * array pointed to by 'dnptrs'. Side effect is to update the list of * pointers for labels inserted into the message as we compress the name. * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr' * is NULL, we don't update the list. */ int ns_name_compress(const char *src, u_char *dst, size_t dstsiz, const u_char **dnptrs, const u_char **lastdnptr) { u_char tmp[NS_MAXCDNAME]; if (ns_name_pton(src, tmp, sizeof tmp) == -1) return (-1); return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr)); } /* * ns_name_skip(ptrptr, eom) * Advance *ptrptr to skip over the compressed name it points at. * return: * 0 on success, -1 (with errno set) on failure. */ int ns_name_skip(const u_char **ptrptr, const u_char *eom) { const u_char *cp; u_int n; cp = *ptrptr; while (cp < eom && (n = *cp++) != 0) { /* Check for indirection. */ switch (n & NS_CMPRSFLGS) { case 0: /* normal case, n == len */ cp += n; continue; case NS_CMPRSFLGS: /* indirection */ cp++; break; default: /* illegal type */ errno = EMSGSIZE; return (-1); } break; } if (cp > eom) { errno = EMSGSIZE; return (-1); } *ptrptr = cp; return (0); } /* Private. */ /* * special(ch) * Thinking in noninternationalized USASCII (per the DNS spec), * is this characted special ("in need of quoting") ? * return: * boolean. */ static int special(int ch) { switch (ch) { case 0x22: /* '"' */ case 0x2E: /* '.' */ case 0x3B: /* ';' */ case 0x5C: /* '\\' */ /* Special modifiers in zone files. */ case 0x40: /* '@' */ case 0x24: /* '$' */ return (1); default: return (0); } } /* * printable(ch) * Thinking in noninternationalized USASCII (per the DNS spec), * is this character visible and not a space when printed ? * return: * boolean. */ static int printable(int ch) { return (ch > 0x20 && ch < 0x7f); } /* * Thinking in noninternationalized USASCII (per the DNS spec), * convert this character to lower case if it's upper case. */ static int mklower(int ch) { if (ch >= 0x41 && ch <= 0x5A) return (ch + 0x20); return (ch); } /* * dn_find(domain, msg, dnptrs, lastdnptr) * Search for the counted-label name in an array of compressed names. * return: * offset from msg if found, or -1. * notes: * dnptrs is the pointer to the first name on the list, * not the pointer to the start of the message. */ static int dn_find(const u_char *domain, const u_char *msg, const u_char * const *dnptrs, const u_char * const *lastdnptr) { const u_char *dn, *cp, *sp; const u_char * const *cpp; u_int n; for (cpp = dnptrs; cpp < lastdnptr; cpp++) { dn = domain; sp = cp = *cpp; while ((n = *cp++) != 0) { /* * check for indirection */ switch (n & NS_CMPRSFLGS) { case 0: /* normal case, n == len */ if (n != *dn++) goto next; for ((void)NULL; n > 0; n--) if (mklower(*dn++) != mklower(*cp++)) goto next; /* Is next root for both ? */ if (*dn == '\0' && *cp == '\0') return (sp - msg); if (*dn) continue; goto next; case NS_CMPRSFLGS: /* indirection */ cp = msg + (((n & 0x3f) << 8) | *cp); break; default: /* illegal type */ errno = EMSGSIZE; return (-1); } } next: ; } errno = ENOENT; return (-1); } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/ns_parse.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/ns_parse.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/ns_parse.c (revision 131136) @@ -1,208 +1,214 @@ /* - * Copyright (c) 1996,1999 by Internet Software Consortium. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ */ #ifndef lint -static const char rcsid[] = "$Id: ns_parse.c,v 1.2.2.1 2002/02/19 19:16:52 mellon Exp $"; +static const char rcsid[] = "$Id: ns_parse.c,v 1.2.2.2 2004/06/10 17:59:40 dhankins Exp $"; #endif /* Import. */ #include #include #include #include #include #include "minires/minires.h" #include "arpa/nameser.h" /* Forward. */ static void setsection(ns_msg *msg, ns_sect sect); /* Macros. */ /* Public. */ /* These need to be in the same order as the nres.h:ns_flag enum. */ struct _ns_flagdata _ns_flagdata[16] = { { 0x8000, 15 }, /* qr. */ { 0x7800, 11 }, /* opcode. */ { 0x0400, 10 }, /* aa. */ { 0x0200, 9 }, /* tc. */ { 0x0100, 8 }, /* rd. */ { 0x0080, 7 }, /* ra. */ { 0x0040, 6 }, /* z. */ { 0x0020, 5 }, /* ad. */ { 0x0010, 4 }, /* cd. */ { 0x000f, 0 }, /* rcode. */ { 0x0000, 0 }, /* expansion (1/6). */ { 0x0000, 0 }, /* expansion (2/6). */ { 0x0000, 0 }, /* expansion (3/6). */ { 0x0000, 0 }, /* expansion (4/6). */ { 0x0000, 0 }, /* expansion (5/6). */ { 0x0000, 0 }, /* expansion (6/6). */ }; isc_result_t ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count, int *rc) { const u_char *optr = ptr; for ((void)NULL; count > 0; count--) { int b, rdlength; b = dn_skipname(ptr, eom); if (b < 0) return ISC_R_INCOMPLETE; ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/; if (section != ns_s_qd) { if (ptr + NS_INT32SZ + NS_INT16SZ > eom) return ISC_R_INCOMPLETE; ptr += NS_INT32SZ/*TTL*/; rdlength = getUShort(ptr); ptr += 2; ptr += rdlength/*RData*/; } } if (ptr > eom) return ISC_R_INCOMPLETE; if (rc) *rc = ptr - optr; return ISC_R_SUCCESS; } isc_result_t ns_initparse(const u_char *msg, unsigned msglen, ns_msg *handle) { const u_char *eom = msg + msglen; int i; memset(handle, 0x5e, sizeof *handle); handle->_msg = msg; handle->_eom = eom; if (msg + NS_INT16SZ > eom) return ISC_R_INCOMPLETE; handle->_id = getUShort (msg); msg += 2; if (msg + NS_INT16SZ > eom) return ISC_R_INCOMPLETE; handle->_flags = getUShort (msg); msg += 2; for (i = 0; i < ns_s_max; i++) { if (msg + NS_INT16SZ > eom) return ISC_R_INCOMPLETE; handle->_counts[i] = getUShort (msg); msg += 2; } for (i = 0; i < ns_s_max; i++) if (handle->_counts[i] == 0) handle->_sections[i] = NULL; else { int b; isc_result_t status = ns_skiprr(msg, eom, (ns_sect)i, handle->_counts[i], &b); if (status != ISC_R_SUCCESS) return STATUS; handle->_sections[i] = msg; msg += b; } if (msg != eom) return ISC_R_INCOMPLETE; setsection(handle, ns_s_max); return ISC_R_SUCCESS; } isc_result_t ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) { int b; isc_result_t status; /* Make section right. */ if (section < 0 || section >= ns_s_max) return ISC_R_NOTIMPLEMENTED; if (section != handle->_sect) setsection(handle, section); /* Make rrnum right. */ if (rrnum == -1) rrnum = handle->_rrnum; if (rrnum < 0 || rrnum >= handle->_counts[(int)section]) return ISC_R_UNKNOWNATTRIBUTE; if (rrnum < handle->_rrnum) setsection(handle, section); if (rrnum > handle->_rrnum) { status = ns_skiprr(handle->_ptr, handle->_eom, section, rrnum - handle->_rrnum, &b); if (status != ISC_R_SUCCESS) return status; handle->_ptr += b; handle->_rrnum = rrnum; } /* Do the parse. */ b = dn_expand(handle->_msg, handle->_eom, handle->_ptr, rr->name, NS_MAXDNAME); if (b < 0) return ISC_R_FORMERR; handle->_ptr += b; if (handle->_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom) return ISC_R_INCOMPLETE; rr->type = getUShort (handle->_ptr); handle -> _ptr += 2; rr->rr_class = getUShort (handle->_ptr); handle -> _ptr += 2; if (section == ns_s_qd) { rr->ttl = 0; rr->rdlength = 0; rr->rdata = NULL; } else { if (handle->_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom) return ISC_R_INCOMPLETE; rr->ttl = getULong (handle->_ptr); handle -> _ptr += 4; rr->rdlength = getUShort (handle->_ptr); handle -> _ptr += 2; if (handle->_ptr + rr->rdlength > handle->_eom) return ISC_R_INCOMPLETE; rr->rdata = handle->_ptr; handle->_ptr += rr->rdlength; } if (++handle->_rrnum > handle->_counts[(int)section]) setsection(handle, (ns_sect)((int)section + 1)); /* All done. */ return ISC_R_SUCCESS; } /* Private. */ static void setsection(ns_msg *msg, ns_sect sect) { msg->_sect = sect; if (sect == ns_s_max) { msg->_rrnum = -1; msg->_ptr = NULL; } else { msg->_rrnum = 0; msg->_ptr = msg->_sections[(int)sect]; } } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/ns_samedomain.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/ns_samedomain.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/ns_samedomain.c (revision 131136) @@ -1,210 +1,216 @@ /* - * Copyright (c) 1995,1999-2003 by Internet Software Consortium. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ */ #ifndef lint -static const char rcsid[] = "$Id: ns_samedomain.c,v 1.3.2.3 2003/01/14 23:15:06 dhankins Exp $"; +static const char rcsid[] = "$Id: ns_samedomain.c,v 1.3.2.4 2004/06/10 17:59:41 dhankins Exp $"; #endif #include #include #include #include #include #include "minires/minires.h" #include "arpa/nameser.h" /* * int * ns_samedomain(a, b) * Check whether a name belongs to a domain. * Inputs: * a - the domain whose ancestory is being verified * b - the potential ancestor we're checking against * Return: * boolean - is a at or below b? * Notes: * Trailing dots are first removed from name and domain. * Always compare complete subdomains, not only whether the * domain name is the trailing string of the given name. * * "host.foobar.top" lies in "foobar.top" and in "top" and in "" * but NOT in "bar.top" */ int ns_samedomain(const char *a, const char *b) { size_t la, lb; int diff, i, escaped; const char *cp; la = strlen(a); lb = strlen(b); /* Ignore a trailing label separator (i.e. an unescaped dot) in 'a'. */ if (la != 0 && a[la - 1] == '.') { escaped = 0; /* Note this loop doesn't get executed if la==1. */ for (i = la - 2; i >= 0; i--) if (a[i] == '\\') { if (escaped) escaped = 0; else escaped = 1; } else break; if (!escaped) la--; } /* Ignore a trailing label separator (i.e. an unescaped dot) in 'b'. */ if (lb != 0 && b[lb - 1] == '.') { escaped = 0; /* note this loop doesn't get executed if lb==1 */ for (i = lb - 2; i >= 0; i--) if (b[i] == '\\') { if (escaped) escaped = 0; else escaped = 1; } else break; if (!escaped) lb--; } /* lb == 0 means 'b' is the root domain, so 'a' must be in 'b'. */ if (lb == 0) return (1); /* 'b' longer than 'a' means 'a' can't be in 'b'. */ if (lb > la) return (0); /* 'a' and 'b' being equal at this point indicates sameness. */ if (lb == la) return (strncasecmp(a, b, lb) == 0); /* Ok, we know la > lb. */ diff = la - lb; /* * If 'a' is only 1 character longer than 'b', then it can't be * a subdomain of 'b' (because of the need for the '.' label * separator). */ if (diff < 2) return (0); /* * If the character before the last 'lb' characters of 'b' * isn't '.', then it can't be a match (this lets us avoid * having "foobar.com" match "bar.com"). */ if (a[diff - 1] != '.') return (0); /* * We're not sure about that '.', however. It could be escaped * and thus not a really a label separator. */ escaped = 0; for (i = diff - 2; i >= 0; i--) if (a[i] == '\\') { if (escaped) escaped = 0; else escaped = 1; } else break; if (escaped) return (0); /* Now compare aligned trailing substring. */ cp = a + diff; return (strncasecmp(cp, b, lb) == 0); } /* * int * ns_subdomain(a, b) * is "a" a subdomain of "b"? */ int ns_subdomain(const char *a, const char *b) { return (ns_samename(a, b) != 1 && ns_samedomain(a, b)); } /* * int * ns_makecanon(src, dst, dstsize) * make a canonical copy of domain name "src" * notes: * foo -> foo. * foo. -> foo. * foo.. -> foo. * foo\. -> foo\.. * foo\\. -> foo\\. */ isc_result_t ns_makecanon(const char *src, char *dst, size_t dstsize) { size_t n = strlen(src); if (n + sizeof "." > dstsize) { return ISC_R_NOSPACE; } strcpy(dst, src); while (n > 0 && dst[n - 1] == '.') /* Ends in "." */ if (n > 1 && dst[n - 2] == '\\' && /* Ends in "\." */ (n < 2 || dst[n - 3] != '\\')) /* But not "\\." */ break; else dst[--n] = '\0'; dst[n++] = '.'; dst[n] = '\0'; return ISC_R_SUCCESS; } /* * int * ns_samename(a, b) * determine whether domain name "a" is the same as domain name "b" * return: * -1 on error * 0 if names differ * 1 if names are the same */ int ns_samename(const char *a, const char *b) { char ta[NS_MAXDNAME], tb[NS_MAXDNAME]; isc_result_t status; status = ns_makecanon(a, ta, sizeof ta); if (status != ISC_R_SUCCESS) return status; status = ns_makecanon(b, tb, sizeof tb); if (status != ISC_R_SUCCESS) return (-1); if (strcasecmp(ta, tb) == 0) return (1); else return (0); } Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/ns_sign.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/ns_sign.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/ns_sign.c (revision 131136) @@ -1,356 +1,362 @@ /* - * Copyright (c) 1999-2003 by Internet Software Consortium, Inc. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ */ #ifndef lint -static const char rcsid[] = "$Id: ns_sign.c,v 1.4.2.3 2003/01/14 23:15:06 dhankins Exp $"; +static const char rcsid[] = "$Id: ns_sign.c,v 1.4.2.4 2004/06/10 17:59:42 dhankins Exp $"; #endif #if defined (TRACING) #define time(x) trace_mr_time (x) time_t trace_mr_time (time_t *); #endif /* Import. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "minires/minires.h" #include "arpa/nameser.h" #include #define BOUNDS_CHECK(ptr, count) \ do { \ if ((ptr) + (count) > eob) { \ return ISC_R_NOSPACE; \ } \ } while (0) /* ns_sign * Parameters: * msg message to be sent * msglen input - length of message * output - length of signed message * msgsize length of buffer containing message * error value to put in the error field * key tsig key used for signing * querysig (response), the signature in the query * querysiglen (response), the length of the signature in the query * sig a buffer to hold the generated signature * siglen input - length of signature buffer * output - length of signature * * Errors: * - bad input data (-1) * - bad key / sign failed (-BADKEY) * - not enough space (NS_TSIG_ERROR_NO_SPACE) */ isc_result_t ns_sign(u_char *msg, unsigned *msglen, unsigned msgsize, int error, void *k, const u_char *querysig, unsigned querysiglen, u_char *sig, unsigned *siglen, time_t in_timesigned) { HEADER *hp = (HEADER *)msg; DST_KEY *key = (DST_KEY *)k; u_char *cp = msg + *msglen, *eob = msg + msgsize; u_char *lenp; u_char *name, *alg; unsigned n; time_t timesigned; dst_init(); if (msg == NULL || msglen == NULL || sig == NULL || siglen == NULL) return ISC_R_INVALIDARG; /* Name. */ if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) n = dn_comp(key->dk_key_name, cp, (unsigned)(eob - cp), NULL, NULL); else n = dn_comp("", cp, (unsigned)(eob - cp), NULL, NULL); if (n < 0) return ISC_R_NOSPACE; name = cp; cp += n; /* Type, class, ttl, length (not filled in yet). */ BOUNDS_CHECK(cp, INT16SZ + INT16SZ + INT32SZ + INT16SZ); PUTSHORT(ns_t_tsig, cp); PUTSHORT(ns_c_any, cp); PUTLONG(0, cp); /* TTL */ lenp = cp; cp += 2; /* Alg. */ if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) { if (key->dk_alg != KEY_HMAC_MD5) return ISC_R_BADKEY; n = dn_comp(NS_TSIG_ALG_HMAC_MD5, cp, (unsigned)(eob - cp), NULL, NULL); } else n = dn_comp("", cp, (unsigned)(eob - cp), NULL, NULL); if (n < 0) return ISC_R_NOSPACE; alg = cp; cp += n; /* Time. */ BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ); PUTSHORT(0, cp); timesigned = time(NULL); if (error != ns_r_badtime) PUTLONG(timesigned, cp); else PUTLONG(in_timesigned, cp); PUTSHORT(NS_TSIG_FUDGE, cp); /* Compute the signature. */ if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) { void *ctx; u_char buf[MAXDNAME], *cp2; unsigned n; dst_sign_data(SIG_MODE_INIT, key, &ctx, NULL, 0, NULL, 0); /* Digest the query signature, if this is a response. */ if (querysiglen > 0 && querysig != NULL) { u_int16_t len_n = htons(querysiglen); dst_sign_data(SIG_MODE_UPDATE, key, &ctx, (u_char *)&len_n, INT16SZ, NULL, 0); dst_sign_data(SIG_MODE_UPDATE, key, &ctx, querysig, querysiglen, NULL, 0); } /* Digest the message. */ dst_sign_data(SIG_MODE_UPDATE, key, &ctx, msg, *msglen, NULL, 0); /* Digest the key name. */ n = ns_name_ntol(name, buf, sizeof(buf)); dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0); /* Digest the class and TTL. */ cp2 = buf; PUTSHORT(ns_c_any, cp2); PUTLONG(0, cp2); dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, (unsigned)(cp2-buf), NULL, 0); /* Digest the algorithm. */ n = ns_name_ntol(alg, buf, sizeof(buf)); dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0); /* Digest the time signed, fudge, error, and other data */ cp2 = buf; PUTSHORT(0, cp2); /* Top 16 bits of time */ if (error != ns_r_badtime) PUTLONG(timesigned, cp2); else PUTLONG(in_timesigned, cp2); PUTSHORT(NS_TSIG_FUDGE, cp2); PUTSHORT(error, cp2); /* Error */ if (error != ns_r_badtime) PUTSHORT(0, cp2); /* Other data length */ else { PUTSHORT(INT16SZ+INT32SZ, cp2); /* Other data length */ PUTSHORT(0, cp2); /* Top 16 bits of time */ PUTLONG(timesigned, cp2); } dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, (unsigned)(cp2-buf), NULL, 0); n = dst_sign_data(SIG_MODE_FINAL, key, &ctx, NULL, 0, sig, *siglen); if (n < 0) return ISC_R_BADKEY; *siglen = n; } else *siglen = 0; /* Add the signature. */ BOUNDS_CHECK(cp, INT16SZ + (*siglen)); PUTSHORT(*siglen, cp); memcpy(cp, sig, *siglen); cp += (*siglen); /* The original message ID & error. */ BOUNDS_CHECK(cp, INT16SZ + INT16SZ); PUTSHORT(ntohs(hp->id), cp); /* already in network order */ PUTSHORT(error, cp); /* Other data. */ BOUNDS_CHECK(cp, INT16SZ); if (error != ns_r_badtime) PUTSHORT(0, cp); /* Other data length */ else { PUTSHORT(INT16SZ+INT32SZ, cp); /* Other data length */ BOUNDS_CHECK(cp, INT32SZ+INT16SZ); PUTSHORT(0, cp); /* Top 16 bits of time */ PUTLONG(timesigned, cp); } /* Go back and fill in the length. */ PUTSHORT(cp - lenp - INT16SZ, lenp); hp->arcount = htons(ntohs(hp->arcount) + 1); *msglen = (cp - msg); return ISC_R_SUCCESS; } #if 0 isc_result_t ns_sign_tcp_init(void *k, const u_char *querysig, unsigned querysiglen, ns_tcp_tsig_state *state) { dst_init(); if (state == NULL || k == NULL || querysig == NULL || querysiglen < 0) return ISC_R_INVALIDARG; state->counter = -1; state->key = k; if (state->key->dk_alg != KEY_HMAC_MD5) return ISC_R_BADKEY; if (querysiglen > sizeof(state->sig)) return ISC_R_NOSPACE; memcpy(state->sig, querysig, querysiglen); state->siglen = querysiglen; return ISC_R_SUCCESS; } isc_result_t ns_sign_tcp(u_char *msg, unsigned *msglen, unsigned msgsize, int error, ns_tcp_tsig_state *state, int done) { u_char *cp, *eob, *lenp; u_char buf[MAXDNAME], *cp2; HEADER *hp = (HEADER *)msg; time_t timesigned; int n; if (msg == NULL || msglen == NULL || state == NULL) return ISC_R_INVALIDARG; state->counter++; if (state->counter == 0) return ns_sign(msg, msglen, msgsize, error, state->key, state->sig, state->siglen, state->sig, &state->siglen, 0); if (state->siglen > 0) { u_int16_t siglen_n = htons(state->siglen); dst_sign_data(SIG_MODE_INIT, state->key, &state->ctx, NULL, 0, NULL, 0); dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, (u_char *)&siglen_n, INT16SZ, NULL, 0); dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, state->sig, state->siglen, NULL, 0); state->siglen = 0; } dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, msg, *msglen, NULL, 0); if (done == 0 && (state->counter % 100 != 0)) return ISC_R_SUCCESS; cp = msg + *msglen; eob = msg + msgsize; /* Name. */ n = dn_comp(state->key->dk_key_name, cp, (unsigned)(eob - cp), NULL, NULL); if (n < 0) return ISC_R_NOSPACE; cp += n; /* Type, class, ttl, length (not filled in yet). */ BOUNDS_CHECK(cp, INT16SZ + INT16SZ + INT32SZ + INT16SZ); PUTSHORT(ns_t_tsig, cp); PUTSHORT(ns_c_any, cp); PUTLONG(0, cp); /* TTL */ lenp = cp; cp += 2; /* Alg. */ n = dn_comp(NS_TSIG_ALG_HMAC_MD5, cp, (unsigned)(eob - cp), NULL, NULL); if (n < 0) return ISC_R_NOSPACE; cp += n; /* Time. */ BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ); PUTSHORT(0, cp); timesigned = time(NULL); PUTLONG(timesigned, cp); PUTSHORT(NS_TSIG_FUDGE, cp); /* * Compute the signature. */ /* Digest the time signed and fudge. */ cp2 = buf; PUTSHORT(0, cp2); /* Top 16 bits of time */ PUTLONG(timesigned, cp2); PUTSHORT(NS_TSIG_FUDGE, cp2); dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, buf, (unsigned)(cp2 - buf), NULL, 0); n = dst_sign_data(SIG_MODE_FINAL, state->key, &state->ctx, NULL, 0, state->sig, sizeof(state->sig)); if (n < 0) return ISC_R_BADKEY; state->siglen = n; /* Add the signature. */ BOUNDS_CHECK(cp, INT16SZ + state->siglen); PUTSHORT(state->siglen, cp); memcpy(cp, state->sig, state->siglen); cp += state->siglen; /* The original message ID & error. */ BOUNDS_CHECK(cp, INT16SZ + INT16SZ); PUTSHORT(ntohs(hp->id), cp); /* already in network order */ PUTSHORT(error, cp); /* Other data. */ BOUNDS_CHECK(cp, INT16SZ); PUTSHORT(0, cp); /* Go back and fill in the length. */ PUTSHORT(cp - lenp - INT16SZ, lenp); hp->arcount = htons(ntohs(hp->arcount) + 1); *msglen = (cp - msg); return ISC_R_SUCCESS; } #endif Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/ns_verify.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/ns_verify.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/ns_verify.c (revision 131136) @@ -1,476 +1,482 @@ /* - * Copyright (c) 1999-2001 by Internet Software Consortium, Inc. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ */ #ifndef lint -static const char rcsid[] = "$Id: ns_verify.c,v 1.5.2.2 2002/02/19 19:23:31 mellon Exp $"; +static const char rcsid[] = "$Id: ns_verify.c,v 1.5.2.3 2004/06/10 17:59:42 dhankins Exp $"; #endif #define time(x) trace_mr_time (x) /* Import. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "minires/minires.h" #include "arpa/nameser.h" #include time_t trace_mr_time (time_t *); /* Private. */ #define BOUNDS_CHECK(ptr, count) \ do { \ if ((ptr) + (count) > eom) { \ return (NS_TSIG_ERROR_FORMERR); \ } \ } while (0) /* Public. */ u_char * ns_find_tsig(u_char *msg, u_char *eom) { HEADER *hp = (HEADER *)msg; int n, type; u_char *cp = msg, *start; isc_result_t status; if (msg == NULL || eom == NULL || msg > eom) return (NULL); if (cp + HFIXEDSZ >= eom) return (NULL); if (hp->arcount == 0) return (NULL); cp += HFIXEDSZ; status = ns_skiprr(cp, eom, ns_s_qd, ntohs(hp->qdcount), &n); if (status != ISC_R_SUCCESS) return (NULL); cp += n; status = ns_skiprr(cp, eom, ns_s_an, ntohs(hp->ancount), &n); if (status != ISC_R_SUCCESS) return (NULL); cp += n; status = ns_skiprr(cp, eom, ns_s_ns, ntohs(hp->nscount), &n); if (status != ISC_R_SUCCESS) return (NULL); cp += n; status = ns_skiprr(cp, eom, ns_s_ar, ntohs(hp->arcount) - 1, &n); if (status != ISC_R_SUCCESS) return (NULL); cp += n; start = cp; n = dn_skipname(cp, eom); if (n < 0) return (NULL); cp += n; if (cp + INT16SZ >= eom) return (NULL); GETSHORT(type, cp); if (type != ns_t_tsig) return (NULL); return (start); } /* ns_verify * Parameters: * statp res stuff * msg received message * msglen length of message * key tsig key used for verifying. * querysig (response), the signature in the query * querysiglen (response), the length of the signature in the query * sig (query), a buffer to hold the signature * siglen (query), input - length of signature buffer * output - length of signature * * Errors: * - bad input (-1) * - invalid dns message (NS_TSIG_ERROR_FORMERR) * - TSIG is not present (NS_TSIG_ERROR_NO_TSIG) * - key doesn't match (-ns_r_badkey) * - TSIG verification fails with BADKEY (-ns_r_badkey) * - TSIG verification fails with BADSIG (-ns_r_badsig) * - TSIG verification fails with BADTIME (-ns_r_badtime) * - TSIG verification succeeds, error set to BAKEY (ns_r_badkey) * - TSIG verification succeeds, error set to BADSIG (ns_r_badsig) * - TSIG verification succeeds, error set to BADTIME (ns_r_badtime) */ isc_result_t ns_verify(u_char *msg, unsigned *msglen, void *k, const u_char *querysig, unsigned querysiglen, u_char *sig, unsigned *siglen, time_t *timesigned, int nostrip) { HEADER *hp = (HEADER *)msg; DST_KEY *key = (DST_KEY *)k; u_char *cp = msg, *eom; char name[MAXDNAME], alg[MAXDNAME]; u_char *recstart, *rdatastart; u_char *sigstart, *otherstart; unsigned n; int error; u_int16_t type, length; u_int16_t fudge, sigfieldlen, id, otherfieldlen; dst_init(); if (msg == NULL || msglen == NULL || *msglen < 0) return ISC_R_INVALIDARG; eom = msg + *msglen; recstart = ns_find_tsig(msg, eom); if (recstart == NULL) return ISC_R_NO_TSIG; cp = recstart; /* Read the key name. */ n = dn_expand(msg, eom, cp, name, MAXDNAME); if (n < 0) return ISC_R_FORMERR; cp += n; /* Read the type. */ BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ); GETSHORT(type, cp); if (type != ns_t_tsig) return ISC_R_NO_TSIG; /* Skip the class and TTL, save the length. */ cp += INT16SZ + INT32SZ; GETSHORT(length, cp); if (eom - cp != length) return ISC_R_FORMERR; /* Read the algorithm name. */ rdatastart = cp; n = dn_expand(msg, eom, cp, alg, MAXDNAME); if (n < 0) return ISC_R_FORMERR; if (ns_samename(alg, NS_TSIG_ALG_HMAC_MD5) != 1) return ISC_R_INVALIDKEY; cp += n; /* Read the time signed and fudge. */ BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ); cp += INT16SZ; GETLONG((*timesigned), cp); GETSHORT(fudge, cp); /* Read the signature. */ BOUNDS_CHECK(cp, INT16SZ); GETSHORT(sigfieldlen, cp); BOUNDS_CHECK(cp, sigfieldlen); sigstart = cp; cp += sigfieldlen; /* Read the original id and error. */ BOUNDS_CHECK(cp, 2*INT16SZ); GETSHORT(id, cp); GETSHORT(error, cp); /* Parse the other data. */ BOUNDS_CHECK(cp, INT16SZ); GETSHORT(otherfieldlen, cp); BOUNDS_CHECK(cp, otherfieldlen); otherstart = cp; cp += otherfieldlen; if (cp != eom) return ISC_R_FORMERR; /* Verify that the key used is OK. */ if (key != NULL) { if (key->dk_alg != KEY_HMAC_MD5) return ISC_R_INVALIDKEY; if (error != ns_r_badsig && error != ns_r_badkey) { if (ns_samename(key->dk_key_name, name) != 1) return ISC_R_INVALIDKEY; } } hp->arcount = htons(ntohs(hp->arcount) - 1); /* * Do the verification. */ if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) { void *ctx; u_char buf[MAXDNAME]; /* Digest the query signature, if this is a response. */ dst_verify_data(SIG_MODE_INIT, key, &ctx, NULL, 0, NULL, 0); if (querysiglen > 0 && querysig != NULL) { u_int16_t len_n = htons(querysiglen); dst_verify_data(SIG_MODE_UPDATE, key, &ctx, (u_char *)&len_n, INT16SZ, NULL, 0); dst_verify_data(SIG_MODE_UPDATE, key, &ctx, querysig, querysiglen, NULL, 0); } /* Digest the message. */ dst_verify_data(SIG_MODE_UPDATE, key, &ctx, msg, (unsigned)(recstart - msg), NULL, 0); /* Digest the key name. */ n = ns_name_ntol(recstart, buf, sizeof(buf)); dst_verify_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0); /* Digest the class and TTL. */ dst_verify_data(SIG_MODE_UPDATE, key, &ctx, recstart + dn_skipname(recstart, eom) + INT16SZ, INT16SZ + INT32SZ, NULL, 0); /* Digest the algorithm. */ n = ns_name_ntol(rdatastart, buf, sizeof(buf)); dst_verify_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0); /* Digest the time signed and fudge. */ dst_verify_data(SIG_MODE_UPDATE, key, &ctx, rdatastart + dn_skipname(rdatastart, eom), INT16SZ + INT32SZ + INT16SZ, NULL, 0); /* Digest the error and other data. */ dst_verify_data(SIG_MODE_UPDATE, key, &ctx, otherstart - INT16SZ - INT16SZ, (unsigned)otherfieldlen + INT16SZ + INT16SZ, NULL, 0); n = dst_verify_data(SIG_MODE_FINAL, key, &ctx, NULL, 0, sigstart, sigfieldlen); if (n < 0) return ISC_R_BADSIG; if (sig != NULL && siglen != NULL) { if (*siglen < sigfieldlen) return ISC_R_NOSPACE; memcpy(sig, sigstart, sigfieldlen); *siglen = sigfieldlen; } } else { if (sigfieldlen > 0) return ISC_R_FORMERR; if (sig != NULL && siglen != NULL) *siglen = 0; } /* Reset the counter, since we still need to check for badtime. */ hp->arcount = htons(ntohs(hp->arcount) + 1); /* Verify the time. */ if (abs((*timesigned) - time(NULL)) > fudge) return ISC_R_BADTIME; if (nostrip == 0) { *msglen = recstart - msg; hp->arcount = htons(ntohs(hp->arcount) - 1); } if (error != NOERROR) return ns_rcode_to_isc (error); return ISC_R_SUCCESS; } #if 0 isc_result_t ns_verify_tcp_init(void *k, const u_char *querysig, unsigned querysiglen, ns_tcp_tsig_state *state) { dst_init(); if (state == NULL || k == NULL || querysig == NULL || querysiglen < 0) return ISC_R_INVALIDARG; state->counter = -1; state->key = k; if (state->key->dk_alg != KEY_HMAC_MD5) return ISC_R_BADKEY; if (querysiglen > sizeof(state->sig)) return ISC_R_NOSPACE; memcpy(state->sig, querysig, querysiglen); state->siglen = querysiglen; return ISC_R_SUCCESS; } isc_result_t ns_verify_tcp(u_char *msg, unsigned *msglen, ns_tcp_tsig_state *state, int required) { HEADER *hp = (HEADER *)msg; u_char *recstart, *rdatastart, *sigstart; unsigned sigfieldlen, otherfieldlen; u_char *cp, *eom = msg + *msglen, *cp2; char name[MAXDNAME], alg[MAXDNAME]; u_char buf[MAXDNAME]; int n, type, length, fudge, id, error; time_t timesigned; if (msg == NULL || msglen == NULL || state == NULL) return ISC_R_INVALIDARG; state->counter++; if (state->counter == 0) return (ns_verify(msg, msglen, state->key, state->sig, state->siglen, state->sig, &state->siglen, ×igned, 0)); if (state->siglen > 0) { u_int16_t siglen_n = htons(state->siglen); dst_verify_data(SIG_MODE_INIT, state->key, &state->ctx, NULL, 0, NULL, 0); dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, (u_char *)&siglen_n, INT16SZ, NULL, 0); dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, state->sig, state->siglen, NULL, 0); state->siglen = 0; } cp = recstart = ns_find_tsig(msg, eom); if (recstart == NULL) { if (required) return ISC_R_NO_TSIG; dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, msg, *msglen, NULL, 0); return ISC_R_SUCCESS; } hp->arcount = htons(ntohs(hp->arcount) - 1); dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, msg, (unsigned)(recstart - msg), NULL, 0); /* Read the key name. */ n = dn_expand(msg, eom, cp, name, MAXDNAME); if (n < 0) return ISC_R_FORMERR; cp += n; /* Read the type. */ BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ); GETSHORT(type, cp); if (type != ns_t_tsig) return ISC_R_NO_TSIG; /* Skip the class and TTL, save the length. */ cp += INT16SZ + INT32SZ; GETSHORT(length, cp); if (eom - cp != length) return ISC_R_FORMERR; /* Read the algorithm name. */ rdatastart = cp; n = dn_expand(msg, eom, cp, alg, MAXDNAME); if (n < 0) return ISC_R_FORMERR; if (ns_samename(alg, NS_TSIG_ALG_HMAC_MD5) != 1) return ISC_R_BADKEY; cp += n; /* Verify that the key used is OK. */ if ((ns_samename(state->key->dk_key_name, name) != 1 || state->key->dk_alg != KEY_HMAC_MD5)) return ISC_R_BADKEY; /* Read the time signed and fudge. */ BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ); cp += INT16SZ; GETLONG(timesigned, cp); GETSHORT(fudge, cp); /* Read the signature. */ BOUNDS_CHECK(cp, INT16SZ); GETSHORT(sigfieldlen, cp); BOUNDS_CHECK(cp, sigfieldlen); sigstart = cp; cp += sigfieldlen; /* Read the original id and error. */ BOUNDS_CHECK(cp, 2*INT16SZ); GETSHORT(id, cp); GETSHORT(error, cp); /* Parse the other data. */ BOUNDS_CHECK(cp, INT16SZ); GETSHORT(otherfieldlen, cp); BOUNDS_CHECK(cp, otherfieldlen); cp += otherfieldlen; if (cp != eom) return ISC_R_FORMERR; /* * Do the verification. */ /* Digest the time signed and fudge. */ cp2 = buf; PUTSHORT(0, cp2); /* Top 16 bits of time. */ PUTLONG(timesigned, cp2); PUTSHORT(NS_TSIG_FUDGE, cp2); dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, buf, (unsigned)(cp2 - buf), NULL, 0); n = dst_verify_data(SIG_MODE_FINAL, state->key, &state->ctx, NULL, 0, sigstart, sigfieldlen); if (n < 0) return ISC_R_BADSIG; if (sigfieldlen > sizeof(state->sig)) return ISC_R_BADSIG; if (sigfieldlen > sizeof(state->sig)) return ISC_R_NOSPACE; memcpy(state->sig, sigstart, sigfieldlen); state->siglen = sigfieldlen; /* Verify the time. */ if (abs(timesigned - time(NULL)) > fudge) return ISC_R_BADTIME; *msglen = recstart - msg; if (error != NOERROR) return ns_rcode_to_isc (error); return ISC_R_SUCCESS; } #endif Index: vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/res_comp.c =================================================================== --- vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/res_comp.c (revision 131135) +++ vendor/isc-dhcp/dist/contrib/isc-dhcp/minires/res_comp.c (revision 131136) @@ -1,236 +1,242 @@ /* * Copyright (c) 1985, 1993 * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. */ /* * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ /* - * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * Portions Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (c) 1996-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * + * http://www.isc.org/ */ #if defined(LIBC_SCCS) && !defined(lint) static const char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93"; -static const char rcsid[] = "$Id: res_comp.c,v 1.2 2000/02/02 19:59:16 mellon Exp $"; +static const char rcsid[] = "$Id: res_comp.c,v 1.2.2.1 2004/06/10 17:59:42 dhankins Exp $"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #include #include #include #include #include "minires/minires.h" #include "arpa/nameser.h" /* * Expand compressed domain name 'comp_dn' to full domain name. * 'msg' is a pointer to the begining of the message, * 'eomorig' points to the first location after the message, * 'exp_dn' is a pointer to a buffer of size 'length' for the result. * Return size of compressed name or -1 if there was an error. */ int dn_expand(const u_char *msg, const u_char *eom, const u_char *src, char *dst, unsigned dstsiz) { int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz); if (n > 0 && dst[0] == '.') dst[0] = '\0'; return (n); } /* * Pack domain name 'exp_dn' in presentation form into 'comp_dn'. * Return the size of the compressed name or -1. * 'length' is the size of the array pointed to by 'comp_dn'. */ int dn_comp(const char *src, u_char *dst, unsigned dstsiz, u_char **dnptrs, u_char **lastdnptr) { return (ns_name_compress(src, dst, (size_t)dstsiz, (const u_char **)dnptrs, (const u_char **)lastdnptr)); } /* * Skip over a compressed domain name. Return the size or -1. */ int dn_skipname(const u_char *ptr, const u_char *eom) { const u_char *saveptr = ptr; if (ns_name_skip(&ptr, eom) == -1) return (-1); return (ptr - saveptr); } /* * Verify that a domain name uses an acceptable character set. */ #if 0 /* * Note the conspicuous absence of ctype macros in these definitions. On * non-ASCII hosts, we can't depend on string literals or ctype macros to * tell us anything about network-format data. The rest of the BIND system * is not careful about this, but for some reason, we're doing it right here. */ #define PERIOD 0x2e #define hyphenchar(c) ((c) == 0x2d) #define bslashchar(c) ((c) == 0x5c) #define periodchar(c) ((c) == PERIOD) #define asterchar(c) ((c) == 0x2a) #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \ || ((c) >= 0x61 && (c) <= 0x7a)) #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39) #define borderchar(c) (alphachar(c) || digitchar(c)) #define middlechar(c) (borderchar(c) || hyphenchar(c)) #define domainchar(c) ((c) > 0x20 && (c) < 0x7f) int res_hnok(const char *dn) { int ppch = '\0', pch = PERIOD, ch = *dn++; while (ch != '\0') { int nch = *dn++; if (periodchar(ch)) { (void)NULL; } else if (periodchar(pch)) { if (!borderchar(ch)) return (0); } else if (periodchar(nch) || nch == '\0') { if (!borderchar(ch)) return (0); } else { if (!middlechar(ch)) return (0); } ppch = pch, pch = ch, ch = nch; } return (1); } /* * hostname-like (A, MX, WKS) owners can have "*" as their first label * but must otherwise be as a host name. */ int res_ownok(const char *dn) { if (asterchar(dn[0])) { if (periodchar(dn[1])) return (res_hnok(dn+2)); if (dn[1] == '\0') return (1); } return (res_hnok(dn)); } /* * SOA RNAMEs and RP RNAMEs can have any printable character in their first * label, but the rest of the name has to look like a host name. */ int res_mailok(const char *dn) { int ch, escaped = 0; /* "." is a valid missing representation */ if (*dn == '\0') return (1); /* otherwise