Index: head/contrib/isc-dhcp/LICENSE =================================================================== --- head/contrib/isc-dhcp/LICENSE (nonexistent) +++ head/contrib/isc-dhcp/LICENSE (revision 131137) @@ -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: head/contrib/isc-dhcp/LICENSE ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/contrib/isc-dhcp/Makefile =================================================================== --- head/contrib/isc-dhcp/Makefile (revision 131136) +++ head/contrib/isc-dhcp/Makefile (revision 131137) @@ -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: head/contrib/isc-dhcp/Makefile.conf =================================================================== --- head/contrib/isc-dhcp/Makefile.conf (revision 131136) +++ head/contrib/isc-dhcp/Makefile.conf (revision 131137) @@ -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: head/contrib/isc-dhcp/Makefile.dist =================================================================== --- head/contrib/isc-dhcp/Makefile.dist (revision 131136) +++ head/contrib/isc-dhcp/Makefile.dist (revision 131137) @@ -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: head/contrib/isc-dhcp/README =================================================================== --- head/contrib/isc-dhcp/README (revision 131136) +++ head/contrib/isc-dhcp/README (revision 131137) @@ -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: head/contrib/isc-dhcp/RELNOTES =================================================================== --- head/contrib/isc-dhcp/RELNOTES (revision 131136) +++ head/contrib/isc-dhcp/RELNOTES (revision 131137) @@ -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: head/contrib/isc-dhcp/client/Makefile.dist =================================================================== --- head/contrib/isc-dhcp/client/Makefile.dist (revision 131136) +++ head/contrib/isc-dhcp/client/Makefile.dist (revision 131137) @@ -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: head/contrib/isc-dhcp/common/Makefile.dist =================================================================== --- head/contrib/isc-dhcp/common/Makefile.dist (revision 131136) +++ head/contrib/isc-dhcp/common/Makefile.dist (revision 131137) @@ -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: head/contrib/isc-dhcp/common/alloc.c =================================================================== --- head/contrib/isc-dhcp/common/alloc.c (revision 131136) +++ head/contrib/isc-dhcp/common/alloc.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/bpf.c =================================================================== --- head/contrib/isc-dhcp/common/bpf.c (revision 131136) +++ head/contrib/isc-dhcp/common/bpf.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/comapi.c =================================================================== --- head/contrib/isc-dhcp/common/comapi.c (revision 131136) +++ head/contrib/isc-dhcp/common/comapi.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/conflex.c =================================================================== --- head/contrib/isc-dhcp/common/conflex.c (revision 131136) +++ head/contrib/isc-dhcp/common/conflex.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/ctrace.c =================================================================== --- head/contrib/isc-dhcp/common/ctrace.c (revision 131136) +++ head/contrib/isc-dhcp/common/ctrace.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/dhcp-eval.5 =================================================================== --- head/contrib/isc-dhcp/common/dhcp-eval.5 (revision 131136) +++ head/contrib/isc-dhcp/common/dhcp-eval.5 (revision 131137) @@ -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: head/contrib/isc-dhcp/common/discover.c =================================================================== --- head/contrib/isc-dhcp/common/discover.c (revision 131136) +++ head/contrib/isc-dhcp/common/discover.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/dlpi.c =================================================================== --- head/contrib/isc-dhcp/common/dlpi.c (revision 131136) +++ head/contrib/isc-dhcp/common/dlpi.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/dns.c =================================================================== --- head/contrib/isc-dhcp/common/dns.c (revision 131136) +++ head/contrib/isc-dhcp/common/dns.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/ethernet.c =================================================================== --- head/contrib/isc-dhcp/common/ethernet.c (revision 131136) +++ head/contrib/isc-dhcp/common/ethernet.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/execute.c =================================================================== --- head/contrib/isc-dhcp/common/execute.c (revision 131136) +++ head/contrib/isc-dhcp/common/execute.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/fddi.c =================================================================== --- head/contrib/isc-dhcp/common/fddi.c (revision 131136) +++ head/contrib/isc-dhcp/common/fddi.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/icmp.c =================================================================== --- head/contrib/isc-dhcp/common/icmp.c (revision 131136) +++ head/contrib/isc-dhcp/common/icmp.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/inet.c =================================================================== --- head/contrib/isc-dhcp/common/inet.c (revision 131136) +++ head/contrib/isc-dhcp/common/inet.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/iscprint.c =================================================================== --- head/contrib/isc-dhcp/common/iscprint.c (nonexistent) +++ head/contrib/isc-dhcp/common/iscprint.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/iscprint.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/contrib/isc-dhcp/common/lpf.c =================================================================== --- head/contrib/isc-dhcp/common/lpf.c (revision 131136) +++ head/contrib/isc-dhcp/common/lpf.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/memory.c =================================================================== --- head/contrib/isc-dhcp/common/memory.c (revision 131136) +++ head/contrib/isc-dhcp/common/memory.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/nit.c =================================================================== --- head/contrib/isc-dhcp/common/nit.c (revision 131136) +++ head/contrib/isc-dhcp/common/nit.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/options.c =================================================================== --- head/contrib/isc-dhcp/common/options.c (revision 131136) +++ head/contrib/isc-dhcp/common/options.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/packet.c =================================================================== --- head/contrib/isc-dhcp/common/packet.c (revision 131136) +++ head/contrib/isc-dhcp/common/packet.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/parse.c =================================================================== --- head/contrib/isc-dhcp/common/parse.c (revision 131136) +++ head/contrib/isc-dhcp/common/parse.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/print.c =================================================================== --- head/contrib/isc-dhcp/common/print.c (revision 131136) +++ head/contrib/isc-dhcp/common/print.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/raw.c =================================================================== --- head/contrib/isc-dhcp/common/raw.c (revision 131136) +++ head/contrib/isc-dhcp/common/raw.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/resolv.c =================================================================== --- head/contrib/isc-dhcp/common/resolv.c (revision 131136) +++ head/contrib/isc-dhcp/common/resolv.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/socket.c =================================================================== --- head/contrib/isc-dhcp/common/socket.c (revision 131136) +++ head/contrib/isc-dhcp/common/socket.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/tr.c =================================================================== --- head/contrib/isc-dhcp/common/tr.c (revision 131136) +++ head/contrib/isc-dhcp/common/tr.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/tree.c =================================================================== --- head/contrib/isc-dhcp/common/tree.c (revision 131136) +++ head/contrib/isc-dhcp/common/tree.c (revision 131137) @@ -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: head/contrib/isc-dhcp/common/upf.c =================================================================== --- head/contrib/isc-dhcp/common/upf.c (revision 131136) +++ head/contrib/isc-dhcp/common/upf.c (revision 131137) @@ -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: head/contrib/isc-dhcp/dhcpctl/Makefile.dist =================================================================== --- head/contrib/isc-dhcp/dhcpctl/Makefile.dist (revision 131136) +++ head/contrib/isc-dhcp/dhcpctl/Makefile.dist (revision 131137) @@ -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: head/contrib/isc-dhcp/dhcpctl/callback.c =================================================================== --- head/contrib/isc-dhcp/dhcpctl/callback.c (revision 131136) +++ head/contrib/isc-dhcp/dhcpctl/callback.c (revision 131137) @@ -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: head/contrib/isc-dhcp/dhcpctl/cltest.c =================================================================== --- head/contrib/isc-dhcp/dhcpctl/cltest.c (revision 131136) +++ head/contrib/isc-dhcp/dhcpctl/cltest.c (revision 131137) @@ -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: head/contrib/isc-dhcp/dhcpctl/dhcpctl.3 =================================================================== --- head/contrib/isc-dhcp/dhcpctl/dhcpctl.3 (revision 131136) +++ head/contrib/isc-dhcp/dhcpctl/dhcpctl.3 (revision 131137) @@ -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: head/contrib/isc-dhcp/dhcpctl/dhcpctl.c =================================================================== --- head/contrib/isc-dhcp/dhcpctl/dhcpctl.c (revision 131136) +++ head/contrib/isc-dhcp/dhcpctl/dhcpctl.c (revision 131137) @@ -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: head/contrib/isc-dhcp/dhcpctl/dhcpctl.h =================================================================== --- head/contrib/isc-dhcp/dhcpctl/dhcpctl.h (revision 131136) +++ head/contrib/isc-dhcp/dhcpctl/dhcpctl.h (revision 131137) @@ -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: head/contrib/isc-dhcp/dhcpctl/omshell.1 =================================================================== --- head/contrib/isc-dhcp/dhcpctl/omshell.1 (revision 131136) +++ head/contrib/isc-dhcp/dhcpctl/omshell.1 (revision 131137) @@ -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: head/contrib/isc-dhcp/dhcpctl/omshell.c =================================================================== --- head/contrib/isc-dhcp/dhcpctl/omshell.c (revision 131136) +++ head/contrib/isc-dhcp/dhcpctl/omshell.c (revision 131137) @@ -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: head/contrib/isc-dhcp/dhcpctl/remote.c =================================================================== --- head/contrib/isc-dhcp/dhcpctl/remote.c (revision 131136) +++ head/contrib/isc-dhcp/dhcpctl/remote.c (revision 131137) @@ -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: head/contrib/isc-dhcp/dst/Makefile.dist =================================================================== --- head/contrib/isc-dhcp/dst/Makefile.dist (revision 131136) +++ head/contrib/isc-dhcp/dst/Makefile.dist (revision 131137) @@ -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: head/contrib/isc-dhcp/dst/base64.c =================================================================== --- head/contrib/isc-dhcp/dst/base64.c (revision 131136) +++ head/contrib/isc-dhcp/dst/base64.c (revision 131137) @@ -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: head/contrib/isc-dhcp/dst/dst_api.c =================================================================== --- head/contrib/isc-dhcp/dst/dst_api.c (revision 131136) +++ head/contrib/isc-dhcp/dst/dst_api.c (revision 131137) @@ -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: head/contrib/isc-dhcp/dst/dst_support.c =================================================================== --- head/contrib/isc-dhcp/dst/dst_support.c (revision 131136) +++ head/contrib/isc-dhcp/dst/dst_support.c (revision 131137) @@ -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: head/contrib/isc-dhcp/dst/hmac_link.c =================================================================== --- head/contrib/isc-dhcp/dst/hmac_link.c (revision 131136) +++ head/contrib/isc-dhcp/dst/hmac_link.c (revision 131137) @@ -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: head/contrib/isc-dhcp/dst/md5_dgst.c =================================================================== --- head/contrib/isc-dhcp/dst/md5_dgst.c (revision 131136) +++ head/contrib/isc-dhcp/dst/md5_dgst.c (revision 131137) @@ -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: head/contrib/isc-dhcp/dst/md5_locl.h =================================================================== --- head/contrib/isc-dhcp/dst/md5_locl.h (revision 131136) +++ head/contrib/isc-dhcp/dst/md5_locl.h (revision 131137) @@ -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: head/contrib/isc-dhcp/dst/prandom.c =================================================================== --- head/contrib/isc-dhcp/dst/prandom.c (revision 131136) +++ head/contrib/isc-dhcp/dst/prandom.c (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/arpa/nameser.h =================================================================== --- head/contrib/isc-dhcp/includes/arpa/nameser.h (revision 131136) +++ head/contrib/isc-dhcp/includes/arpa/nameser.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/cdefs.h =================================================================== --- head/contrib/isc-dhcp/includes/cdefs.h (revision 131136) +++ head/contrib/isc-dhcp/includes/cdefs.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/ctrace.h =================================================================== --- head/contrib/isc-dhcp/includes/ctrace.h (revision 131136) +++ head/contrib/isc-dhcp/includes/ctrace.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/dhcp.h =================================================================== --- head/contrib/isc-dhcp/includes/dhcp.h (revision 131136) +++ head/contrib/isc-dhcp/includes/dhcp.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/dhctoken.h =================================================================== --- head/contrib/isc-dhcp/includes/dhctoken.h (revision 131136) +++ head/contrib/isc-dhcp/includes/dhctoken.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/failover.h =================================================================== --- head/contrib/isc-dhcp/includes/failover.h (revision 131136) +++ head/contrib/isc-dhcp/includes/failover.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/inet.h =================================================================== --- head/contrib/isc-dhcp/includes/inet.h (revision 131136) +++ head/contrib/isc-dhcp/includes/inet.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/isc-dhcp/boolean.h =================================================================== --- head/contrib/isc-dhcp/includes/isc-dhcp/boolean.h (revision 131136) +++ head/contrib/isc-dhcp/includes/isc-dhcp/boolean.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/isc-dhcp/int.h =================================================================== --- head/contrib/isc-dhcp/includes/isc-dhcp/int.h (revision 131136) +++ head/contrib/isc-dhcp/includes/isc-dhcp/int.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/isc-dhcp/lang.h =================================================================== --- head/contrib/isc-dhcp/includes/isc-dhcp/lang.h (revision 131136) +++ head/contrib/isc-dhcp/includes/isc-dhcp/lang.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/isc-dhcp/list.h =================================================================== --- head/contrib/isc-dhcp/includes/isc-dhcp/list.h (revision 131136) +++ head/contrib/isc-dhcp/includes/isc-dhcp/list.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/isc-dhcp/result.h =================================================================== --- head/contrib/isc-dhcp/includes/isc-dhcp/result.h (revision 131136) +++ head/contrib/isc-dhcp/includes/isc-dhcp/result.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/isc-dhcp/types.h =================================================================== --- head/contrib/isc-dhcp/includes/isc-dhcp/types.h (revision 131136) +++ head/contrib/isc-dhcp/includes/isc-dhcp/types.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/minires/minires.h =================================================================== --- head/contrib/isc-dhcp/includes/minires/minires.h (revision 131136) +++ head/contrib/isc-dhcp/includes/minires/minires.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/minires/res_update.h =================================================================== --- head/contrib/isc-dhcp/includes/minires/res_update.h (revision 131136) +++ head/contrib/isc-dhcp/includes/minires/res_update.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/minires/resolv.h =================================================================== --- head/contrib/isc-dhcp/includes/minires/resolv.h (revision 131136) +++ head/contrib/isc-dhcp/includes/minires/resolv.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/netinet/udp.h =================================================================== --- head/contrib/isc-dhcp/includes/netinet/udp.h (revision 131136) +++ head/contrib/isc-dhcp/includes/netinet/udp.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/omapip/alloc.h =================================================================== --- head/contrib/isc-dhcp/includes/omapip/alloc.h (revision 131136) +++ head/contrib/isc-dhcp/includes/omapip/alloc.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/omapip/buffer.h =================================================================== --- head/contrib/isc-dhcp/includes/omapip/buffer.h (revision 131136) +++ head/contrib/isc-dhcp/includes/omapip/buffer.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/omapip/convert.h =================================================================== --- head/contrib/isc-dhcp/includes/omapip/convert.h (revision 131136) +++ head/contrib/isc-dhcp/includes/omapip/convert.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/omapip/hash.h =================================================================== --- head/contrib/isc-dhcp/includes/omapip/hash.h (revision 131136) +++ head/contrib/isc-dhcp/includes/omapip/hash.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/omapip/omapip.h =================================================================== --- head/contrib/isc-dhcp/includes/omapip/omapip.h (revision 131136) +++ head/contrib/isc-dhcp/includes/omapip/omapip.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/omapip/omapip_p.h =================================================================== --- head/contrib/isc-dhcp/includes/omapip/omapip_p.h (revision 131136) +++ head/contrib/isc-dhcp/includes/omapip/omapip_p.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/omapip/trace.h =================================================================== --- head/contrib/isc-dhcp/includes/omapip/trace.h (revision 131136) +++ head/contrib/isc-dhcp/includes/omapip/trace.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/osdep.h =================================================================== --- head/contrib/isc-dhcp/includes/osdep.h (revision 131136) +++ head/contrib/isc-dhcp/includes/osdep.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/statement.h =================================================================== --- head/contrib/isc-dhcp/includes/statement.h (revision 131136) +++ head/contrib/isc-dhcp/includes/statement.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/tree.h =================================================================== --- head/contrib/isc-dhcp/includes/tree.h (revision 131136) +++ head/contrib/isc-dhcp/includes/tree.h (revision 131137) @@ -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: head/contrib/isc-dhcp/includes/version.h =================================================================== --- head/contrib/isc-dhcp/includes/version.h (revision 131136) +++ head/contrib/isc-dhcp/includes/version.h (revision 131137) @@ -1,3 +1,3 @@ /* Current version of ISC DHCP Distribution. */ -#define DHCP_VERSION "V3.0.1rc12" +#define DHCP_VERSION "V3.0.1rc14" Index: head/contrib/isc-dhcp/minires/Makefile.dist =================================================================== --- head/contrib/isc-dhcp/minires/Makefile.dist (revision 131136) +++ head/contrib/isc-dhcp/minires/Makefile.dist (revision 131137) @@ -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: head/contrib/isc-dhcp/minires/ns_date.c =================================================================== --- head/contrib/isc-dhcp/minires/ns_date.c (revision 131136) +++ head/contrib/isc-dhcp/minires/ns_date.c (revision 131137) @@ -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: head/contrib/isc-dhcp/minires/ns_name.c =================================================================== --- head/contrib/isc-dhcp/minires/ns_name.c (revision 131136) +++ head/contrib/isc-dhcp/minires/ns_name.c (revision 131137) @@ -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: head/contrib/isc-dhcp/minires/ns_parse.c =================================================================== --- head/contrib/isc-dhcp/minires/ns_parse.c (revision 131136) +++ head/contrib/isc-dhcp/minires/ns_parse.c (revision 131137) @@ -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: head/contrib/isc-dhcp/minires/ns_samedomain.c =================================================================== --- head/contrib/isc-dhcp/minires/ns_samedomain.c (revision 131136) +++ head/contrib/isc-dhcp/minires/ns_samedomain.c (revision 131137) @@ -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: head/contrib/isc-dhcp/minires/ns_sign.c =================================================================== --- head/contrib/isc-dhcp/minires/ns_sign.c (revision 131136) +++ head/contrib/isc-dhcp/minires/ns_sign.c (revision 131137) @@ -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: head/contrib/isc-dhcp/minires/ns_verify.c =================================================================== --- head/contrib/isc-dhcp/minires/ns_verify.c (revision 131136) +++ head/contrib/isc-dhcp/minires/ns_verify.c (revision 131137) @@ -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: head/contrib/isc-dhcp/minires/res_comp.c =================================================================== --- head/contrib/isc-dhcp/minires/res_comp.c (revision 131136) +++ head/contrib/isc-dhcp/minires/res_comp.c (revision 131137) @@ -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