summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomek Mrugalski <tomek@isc.org>2022-03-30 15:56:52 +0200
committerTomek Mrugalski <tomek@isc.org>2022-03-30 15:56:52 +0200
commit5f89e214d36d5b0b38a15d9dcdeaff9f571e0be3 (patch)
tree2731b1c01e399952f91017f9ef0884702e8e06ec
parent33226f2d76b6b7a06df6b76abbb3526100f5ae2d (diff)
downloadisc-dhcp-5f89e214d36d5b0b38a15d9dcdeaff9f571e0be3.tar.gz
[#227] client and relay code removed
-rw-r--r--client/.cvsignore7
-rw-r--r--client/Makefile.am22
-rw-r--r--client/Makefile.in904
-rw-r--r--client/client_tables.c81
-rw-r--r--client/clparse.c2347
-rw-r--r--client/dhc6.c6129
-rw-r--r--client/dhclient-script.8239
-rw-r--r--client/dhclient.8608
-rw-r--r--client/dhclient.c5890
-rw-r--r--client/dhclient.conf.5786
-rw-r--r--client/dhclient.conf.example36
-rw-r--r--client/dhclient.leases.550
-rwxr-xr-xclient/scripts/bsdos324
-rwxr-xr-xclient/scripts/freebsd474
-rwxr-xr-xclient/scripts/linux496
-rwxr-xr-xclient/scripts/macos288
-rwxr-xr-xclient/scripts/netbsd405
-rw-r--r--client/scripts/nextstep61
-rwxr-xr-xclient/scripts/openbsd403
-rwxr-xr-xclient/scripts/openwrt285
-rwxr-xr-xclient/scripts/solaris203
-rw-r--r--client/tests/Atffile5
-rw-r--r--client/tests/Kyuafile4
-rw-r--r--client/tests/Makefile.am58
-rw-r--r--client/tests/Makefile.in787
-rw-r--r--client/tests/duid0_test.txt33
-rw-r--r--client/tests/duid1_test.txt3
-rw-r--r--client/tests/duid2_test.txt66
-rw-r--r--client/tests/duid3_test.txt66
-rw-r--r--client/tests/duid_unittest.c136
-rw-r--r--relay/.cvsignore4
-rw-r--r--relay/Makefile.am13
-rw-r--r--relay/Makefile.in810
-rw-r--r--relay/dhcrelay.8355
-rw-r--r--relay/dhcrelay.c2173
-rw-r--r--relay/tests/Atffile5
-rw-r--r--relay/tests/Kyuafile4
-rw-r--r--relay/tests/Makefile.am49
-rw-r--r--relay/tests/Makefile.in742
-rw-r--r--relay/tests/relay_unittests.c431
40 files changed, 0 insertions, 25782 deletions
diff --git a/client/.cvsignore b/client/.cvsignore
deleted file mode 100644
index f668817d..00000000
--- a/client/.cvsignore
+++ /dev/null
@@ -1,7 +0,0 @@
-.deps
-Makefile
-dhclient
-dhclient.man8
-dhclient.conf.man5
-dhclient-script.man8
-dhclient.leases.man5
diff --git a/client/Makefile.am b/client/Makefile.am
deleted file mode 100644
index d1771598..00000000
--- a/client/Makefile.am
+++ /dev/null
@@ -1,22 +0,0 @@
-# We want to build this directory first, before descending into tests subdir.
-# The reason is that ideally the tests should link existing objects from this
-# directory. That eliminates any discrepancies between tested code and
-# production code. Sadly, we are not there yet.
-SUBDIRS = . tests
-
-AM_CPPFLAGS = -DCLIENT_PATH='"PATH=$(sbindir):/sbin:/bin:/usr/sbin:/usr/bin"'
-AM_CPPFLAGS += -DLOCALSTATEDIR='"$(localstatedir)"'
-
-dist_sysconf_DATA = dhclient.conf.example
-sbin_PROGRAMS = dhclient
-dhclient_SOURCES = client_tables.c clparse.c dhclient.c dhc6.c \
- scripts/bsdos scripts/freebsd scripts/linux scripts/macos \
- scripts/netbsd scripts/nextstep scripts/openbsd \
- scripts/solaris scripts/openwrt
-dhclient_LDADD = ../common/libdhcp.@A@ ../omapip/libomapi.@A@ \
- @BINDLIBIRSDIR@/libirs.@A@ \
- @BINDLIBDNSDIR@/libdns.@A@ \
- @BINDLIBISCCFGDIR@/libisccfg.@A@ \
- @BINDLIBISCDIR@/libisc.@A@
-man_MANS = dhclient.8 dhclient-script.8 dhclient.conf.5 dhclient.leases.5
-EXTRA_DIST = $(man_MANS)
diff --git a/client/Makefile.in b/client/Makefile.in
deleted file mode 100644
index 2dde99e5..00000000
--- a/client/Makefile.in
+++ /dev/null
@@ -1,904 +0,0 @@
-# Makefile.in generated by automake 1.16.5 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2021 Free Software Foundation, Inc.
-
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-
-VPATH = @srcdir@
-am__is_gnu_make = { \
- if test -z '$(MAKELEVEL)'; then \
- false; \
- elif test -n '$(MAKE_HOST)'; then \
- true; \
- elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
- true; \
- else \
- false; \
- fi; \
-}
-am__make_running_with_option = \
- case $${target_option-} in \
- ?) ;; \
- *) echo "am__make_running_with_option: internal error: invalid" \
- "target option '$${target_option-}' specified" >&2; \
- exit 1;; \
- esac; \
- has_opt=no; \
- sane_makeflags=$$MAKEFLAGS; \
- if $(am__is_gnu_make); then \
- sane_makeflags=$$MFLAGS; \
- else \
- case $$MAKEFLAGS in \
- *\\[\ \ ]*) \
- bs=\\; \
- sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
- | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
- esac; \
- fi; \
- skip_next=no; \
- strip_trailopt () \
- { \
- flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
- }; \
- for flg in $$sane_makeflags; do \
- test $$skip_next = yes && { skip_next=no; continue; }; \
- case $$flg in \
- *=*|--*) continue;; \
- -*I) strip_trailopt 'I'; skip_next=yes;; \
- -*I?*) strip_trailopt 'I';; \
- -*O) strip_trailopt 'O'; skip_next=yes;; \
- -*O?*) strip_trailopt 'O';; \
- -*l) strip_trailopt 'l'; skip_next=yes;; \
- -*l?*) strip_trailopt 'l';; \
- -[dEDm]) skip_next=yes;; \
- -[JT]) skip_next=yes;; \
- esac; \
- case $$flg in \
- *$$target_option*) has_opt=yes; break;; \
- esac; \
- done; \
- test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-sbin_PROGRAMS = dhclient$(EXEEXT)
-subdir = client
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-DIST_COMMON = $(srcdir)/Makefile.am $(dist_sysconf_DATA) \
- $(am__DIST_COMMON)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/includes/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man5dir)" \
- "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(sysconfdir)"
-PROGRAMS = $(sbin_PROGRAMS)
-am_dhclient_OBJECTS = client_tables.$(OBJEXT) clparse.$(OBJEXT) \
- dhclient.$(OBJEXT) dhc6.$(OBJEXT)
-dhclient_OBJECTS = $(am_dhclient_OBJECTS)
-dhclient_DEPENDENCIES = ../common/libdhcp.@A@ ../omapip/libomapi.@A@
-AM_V_P = $(am__v_P_@AM_V@)
-am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo " GEN " $@;
-am__v_GEN_1 =
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/includes
-depcomp = $(SHELL) $(top_srcdir)/depcomp
-am__maybe_remake_depfiles = depfiles
-am__depfiles_remade = ./$(DEPDIR)/client_tables.Po \
- ./$(DEPDIR)/clparse.Po ./$(DEPDIR)/dhc6.Po \
- ./$(DEPDIR)/dhclient.Po
-am__mv = mv -f
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo " CC " $@;
-am__v_CC_1 =
-CCLD = $(CC)
-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo " CCLD " $@;
-am__v_CCLD_1 =
-SOURCES = $(dhclient_SOURCES)
-DIST_SOURCES = $(dhclient_SOURCES)
-RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
- ctags-recursive dvi-recursive html-recursive info-recursive \
- install-data-recursive install-dvi-recursive \
- install-exec-recursive install-html-recursive \
- install-info-recursive install-pdf-recursive \
- install-ps-recursive install-recursive installcheck-recursive \
- installdirs-recursive pdf-recursive ps-recursive \
- tags-recursive uninstall-recursive
-am__can_run_installinfo = \
- case $$AM_UPDATE_INFO_DIR in \
- n|no|NO) false;; \
- *) (install-info --version) >/dev/null 2>&1;; \
- esac
-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
-am__vpath_adj = case $$p in \
- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
- *) f=$$p;; \
- esac;
-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
-am__install_max = 40
-am__nobase_strip_setup = \
- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
-am__nobase_strip = \
- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
-am__nobase_list = $(am__nobase_strip_setup); \
- for p in $$list; do echo "$$p $$p"; done | \
- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
- if (++n[$$2] == $(am__install_max)) \
- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
- END { for (dir in files) print dir, files[dir] }'
-am__base_list = \
- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__uninstall_files_from_dir = { \
- test -z "$$files" \
- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
- $(am__cd) "$$dir" && rm -f $$files; }; \
- }
-man5dir = $(mandir)/man5
-man8dir = $(mandir)/man8
-NROFF = nroff
-MANS = $(man_MANS)
-DATA = $(dist_sysconf_DATA)
-RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
- distclean-recursive maintainer-clean-recursive
-am__recursive_targets = \
- $(RECURSIVE_TARGETS) \
- $(RECURSIVE_CLEAN_TARGETS) \
- $(am__extra_recursive_targets)
-AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
- distdir distdir-am
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-# Read a list of newline-separated strings from the standard input,
-# and print each of them once, without duplicates. Input order is
-# *not* preserved.
-am__uniquify_input = $(AWK) '\
- BEGIN { nonempty = 0; } \
- { items[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in items) print i; }; } \
-'
-# Make sure the list of sources is unique. This is necessary because,
-# e.g., the same source file might be shared among _SOURCES variables
-# for different programs/libraries.
-am__define_uniq_tagged_files = \
- list='$(am__tagged_files)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | $(am__uniquify_input)`
-DIST_SUBDIRS = $(SUBDIRS)
-am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-am__relativize = \
- dir0=`pwd`; \
- sed_first='s,^\([^/]*\)/.*$$,\1,'; \
- sed_rest='s,^[^/]*/*,,'; \
- sed_last='s,^.*/\([^/]*\)$$,\1,'; \
- sed_butlast='s,/*[^/]*$$,,'; \
- while test -n "$$dir1"; do \
- first=`echo "$$dir1" | sed -e "$$sed_first"`; \
- if test "$$first" != "."; then \
- if test "$$first" = ".."; then \
- dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
- dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
- else \
- first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
- if test "$$first2" = "$$first"; then \
- dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
- else \
- dir2="../$$dir2"; \
- fi; \
- dir0="$$dir0"/"$$first"; \
- fi; \
- fi; \
- dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
- done; \
- reldir="$$dir2"
-A = @A@
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-ATF_BIN = @ATF_BIN@
-ATF_CFLAGS = @ATF_CFLAGS@
-ATF_LDFLAGS = @ATF_LDFLAGS@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-BINDCONFIG = @BINDCONFIG@
-BINDDIR = @BINDDIR@
-BINDIOMUX = @BINDIOMUX@
-BINDLIBDNSDIR = @BINDLIBDNSDIR@
-BINDLIBIRSDIR = @BINDLIBIRSDIR@
-BINDLIBISCCFGDIR = @BINDLIBISCCFGDIR@
-BINDLIBISCDIR = @BINDLIBISCDIR@
-BINDLT = @BINDLT@
-BINDSRCDIR = @BINDSRCDIR@
-BINDSUBDIR = @BINDSUBDIR@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CSCOPE = @CSCOPE@
-CTAGS = @CTAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DHLIBS = @DHLIBS@
-DISTCHECK_ATF_CONFIGURE_FLAG = @DISTCHECK_ATF_CONFIGURE_FLAG@
-DISTCHECK_LIBBIND_CONFIGURE_FLAG = @DISTCHECK_LIBBIND_CONFIGURE_FLAG@
-DISTCHECK_LIBTOOL_CONFIGURE_FLAG = @DISTCHECK_LIBTOOL_CONFIGURE_FLAG@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-ETAGS = @ETAGS@
-EXEEXT = @EXEEXT@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LDAP_CFLAGS = @LDAP_CFLAGS@
-LDAP_LIBS = @LDAP_LIBS@
-LDFLAGS = @LDFLAGS@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-MKDIR_P = @MKDIR_P@
-OBJEXT = @OBJEXT@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-Q = @Q@
-RANLIB = @RANLIB@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-UNITTESTS = @UNITTESTS@
-VERSION = @VERSION@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_CC = @ac_ct_CC@
-ac_prefix_program = @ac_prefix_program@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-byte_order = @byte_order@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-pkgcfg_found = @pkgcfg_found@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-
-# We want to build this directory first, before descending into tests subdir.
-# The reason is that ideally the tests should link existing objects from this
-# directory. That eliminates any discrepancies between tested code and
-# production code. Sadly, we are not there yet.
-SUBDIRS = . tests
-AM_CPPFLAGS = -DCLIENT_PATH='"PATH=$(sbindir):/sbin:/bin:/usr/sbin:/usr/bin"' \
- -DLOCALSTATEDIR='"$(localstatedir)"'
-dist_sysconf_DATA = dhclient.conf.example
-dhclient_SOURCES = client_tables.c clparse.c dhclient.c dhc6.c \
- scripts/bsdos scripts/freebsd scripts/linux scripts/macos \
- scripts/netbsd scripts/nextstep scripts/openbsd \
- scripts/solaris scripts/openwrt
-
-dhclient_LDADD = ../common/libdhcp.@A@ ../omapip/libomapi.@A@ \
- @BINDLIBIRSDIR@/libirs.@A@ \
- @BINDLIBDNSDIR@/libdns.@A@ \
- @BINDLIBISCCFGDIR@/libisccfg.@A@ \
- @BINDLIBISCDIR@/libisc.@A@
-
-man_MANS = dhclient.8 dhclient-script.8 dhclient.conf.5 dhclient.leases.5
-EXTRA_DIST = $(man_MANS)
-all: all-recursive
-
-.SUFFIXES:
-.SUFFIXES: .c .o .obj
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
- @for dep in $?; do \
- case '$(am__configure_deps)' in \
- *$$dep*) \
- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
- && { if test -f $@; then exit 0; else break; fi; }; \
- exit 1;; \
- esac; \
- done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign client/Makefile'; \
- $(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --foreign client/Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- @case '$?' in \
- *config.status*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
- *) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
- esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(am__aclocal_m4_deps):
-install-sbinPROGRAMS: $(sbin_PROGRAMS)
- @$(NORMAL_INSTALL)
- @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
- if test -n "$$list"; then \
- echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
- fi; \
- for p in $$list; do echo "$$p $$p"; done | \
- sed 's/$(EXEEXT)$$//' | \
- while read p p1; do if test -f $$p \
- ; then echo "$$p"; echo "$$p"; else :; fi; \
- done | \
- sed -e 'p;s,.*/,,;n;h' \
- -e 's|.*|.|' \
- -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
- sed 'N;N;N;s,\n, ,g' | \
- $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
- { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
- if ($$2 == $$4) files[d] = files[d] " " $$1; \
- else { print "f", $$3 "/" $$4, $$1; } } \
- END { for (d in files) print "f", d, files[d] }' | \
- while read type dir files; do \
- if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
- test -z "$$files" || { \
- echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
- $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
- } \
- ; done
-
-uninstall-sbinPROGRAMS:
- @$(NORMAL_UNINSTALL)
- @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
- files=`for p in $$list; do echo "$$p"; done | \
- sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
- -e 's/$$/$(EXEEXT)/' \
- `; \
- test -n "$$list" || exit 0; \
- echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
- cd "$(DESTDIR)$(sbindir)" && rm -f $$files
-
-clean-sbinPROGRAMS:
- -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS)
-
-dhclient$(EXEEXT): $(dhclient_OBJECTS) $(dhclient_DEPENDENCIES) $(EXTRA_dhclient_DEPENDENCIES)
- @rm -f dhclient$(EXEEXT)
- $(AM_V_CCLD)$(LINK) $(dhclient_OBJECTS) $(dhclient_LDADD) $(LIBS)
-
-mostlyclean-compile:
- -rm -f *.$(OBJEXT)
-
-distclean-compile:
- -rm -f *.tab.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_tables.Po@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clparse.Po@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dhc6.Po@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dhclient.Po@am__quote@ # am--include-marker
-
-$(am__depfiles_remade):
- @$(MKDIR_P) $(@D)
- @echo '# dummy' >$@-t && $(am__mv) $@-t $@
-
-am--depfiles: $(am__depfiles_remade)
-
-.c.o:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
-
-.c.obj:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
-install-man5: $(man_MANS)
- @$(NORMAL_INSTALL)
- @list1=''; \
- list2='$(man_MANS)'; \
- test -n "$(man5dir)" \
- && test -n "`echo $$list1$$list2`" \
- || exit 0; \
- echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \
- { for i in $$list1; do echo "$$i"; done; \
- if test -n "$$list2"; then \
- for i in $$list2; do echo "$$i"; done \
- | sed -n '/\.5[a-z]*$$/p'; \
- fi; \
- } | while read p; do \
- if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
- echo "$$d$$p"; echo "$$p"; \
- done | \
- sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
- -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
- sed 'N;N;s,\n, ,g' | { \
- list=; while read file base inst; do \
- if test "$$base" = "$$inst"; then list="$$list $$file"; else \
- echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \
- $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \
- fi; \
- done; \
- for i in $$list; do echo "$$i"; done | $(am__base_list) | \
- while read files; do \
- test -z "$$files" || { \
- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \
- $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \
- done; }
-
-uninstall-man5:
- @$(NORMAL_UNINSTALL)
- @list=''; test -n "$(man5dir)" || exit 0; \
- files=`{ for i in $$list; do echo "$$i"; done; \
- l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
- sed -n '/\.5[a-z]*$$/p'; \
- } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
- -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
- dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir)
-install-man8: $(man_MANS)
- @$(NORMAL_INSTALL)
- @list1=''; \
- list2='$(man_MANS)'; \
- test -n "$(man8dir)" \
- && test -n "`echo $$list1$$list2`" \
- || exit 0; \
- echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
- { for i in $$list1; do echo "$$i"; done; \
- if test -n "$$list2"; then \
- for i in $$list2; do echo "$$i"; done \
- | sed -n '/\.8[a-z]*$$/p'; \
- fi; \
- } | while read p; do \
- if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
- echo "$$d$$p"; echo "$$p"; \
- done | \
- sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
- -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
- sed 'N;N;s,\n, ,g' | { \
- list=; while read file base inst; do \
- if test "$$base" = "$$inst"; then list="$$list $$file"; else \
- echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
- $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
- fi; \
- done; \
- for i in $$list; do echo "$$i"; done | $(am__base_list) | \
- while read files; do \
- test -z "$$files" || { \
- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
- $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
- done; }
-
-uninstall-man8:
- @$(NORMAL_UNINSTALL)
- @list=''; test -n "$(man8dir)" || exit 0; \
- files=`{ for i in $$list; do echo "$$i"; done; \
- l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
- sed -n '/\.8[a-z]*$$/p'; \
- } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
- -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
- dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
-install-dist_sysconfDATA: $(dist_sysconf_DATA)
- @$(NORMAL_INSTALL)
- @list='$(dist_sysconf_DATA)'; test -n "$(sysconfdir)" || list=; \
- if test -n "$$list"; then \
- echo " $(MKDIR_P) '$(DESTDIR)$(sysconfdir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(sysconfdir)" || exit 1; \
- fi; \
- for p in $$list; do \
- if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
- echo "$$d$$p"; \
- done | $(am__base_list) | \
- while read files; do \
- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(sysconfdir)'"; \
- $(INSTALL_DATA) $$files "$(DESTDIR)$(sysconfdir)" || exit $$?; \
- done
-
-uninstall-dist_sysconfDATA:
- @$(NORMAL_UNINSTALL)
- @list='$(dist_sysconf_DATA)'; test -n "$(sysconfdir)" || list=; \
- files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
- dir='$(DESTDIR)$(sysconfdir)'; $(am__uninstall_files_from_dir)
-
-# This directory's subdirectories are mostly independent; you can cd
-# into them and run 'make' without going through this Makefile.
-# To change the values of 'make' variables: instead of editing Makefiles,
-# (1) if the variable is set in 'config.status', edit 'config.status'
-# (which will cause the Makefiles to be regenerated when you run 'make');
-# (2) otherwise, pass the desired values on the 'make' command line.
-$(am__recursive_targets):
- @fail=; \
- if $(am__make_keepgoing); then \
- failcom='fail=yes'; \
- else \
- failcom='exit 1'; \
- fi; \
- dot_seen=no; \
- target=`echo $@ | sed s/-recursive//`; \
- case "$@" in \
- distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
- *) list='$(SUBDIRS)' ;; \
- esac; \
- for subdir in $$list; do \
- echo "Making $$target in $$subdir"; \
- if test "$$subdir" = "."; then \
- dot_seen=yes; \
- local_target="$$target-am"; \
- else \
- local_target="$$target"; \
- fi; \
- ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
- || eval $$failcom; \
- done; \
- if test "$$dot_seen" = "no"; then \
- $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
- fi; test -z "$$fail"
-
-ID: $(am__tagged_files)
- $(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-recursive
-TAGS: tags
-
-tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
- set x; \
- here=`pwd`; \
- if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
- include_option=--etags-include; \
- empty_fix=.; \
- else \
- include_option=--include; \
- empty_fix=; \
- fi; \
- list='$(SUBDIRS)'; for subdir in $$list; do \
- if test "$$subdir" = .; then :; else \
- test ! -f $$subdir/TAGS || \
- set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
- fi; \
- done; \
- $(am__define_uniq_tagged_files); \
- shift; \
- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
- test -n "$$unique" || unique=$$empty_fix; \
- if test $$# -gt 0; then \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- "$$@" $$unique; \
- else \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$unique; \
- fi; \
- fi
-ctags: ctags-recursive
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
- $(am__define_uniq_tagged_files); \
- test -z "$(CTAGS_ARGS)$$unique" \
- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$unique
-
-GTAGS:
- here=`$(am__cd) $(top_builddir) && pwd` \
- && $(am__cd) $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-recursive
-
-cscopelist-am: $(am__tagged_files)
- list='$(am__tagged_files)'; \
- case "$(srcdir)" in \
- [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
- *) sdir=$(subdir)/$(srcdir) ;; \
- esac; \
- for i in $$list; do \
- if test -f "$$i"; then \
- echo "$(subdir)/$$i"; \
- else \
- echo "$$sdir/$$i"; \
- fi; \
- done >> $(top_builddir)/cscope.files
-
-distclean-tags:
- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-distdir: $(BUILT_SOURCES)
- $(MAKE) $(AM_MAKEFLAGS) distdir-am
-
-distdir-am: $(DISTFILES)
- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- list='$(DISTFILES)'; \
- dist_files=`for file in $$list; do echo $$file; done | \
- sed -e "s|^$$srcdirstrip/||;t" \
- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
- case $$dist_files in \
- */*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
- sort -u` ;; \
- esac; \
- for file in $$dist_files; do \
- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
- if test -d $$d/$$file; then \
- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
- if test -d "$(distdir)/$$file"; then \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
- else \
- test -f "$(distdir)/$$file" \
- || cp -p $$d/$$file "$(distdir)/$$file" \
- || exit 1; \
- fi; \
- done
- @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
- if test "$$subdir" = .; then :; else \
- $(am__make_dryrun) \
- || test -d "$(distdir)/$$subdir" \
- || $(MKDIR_P) "$(distdir)/$$subdir" \
- || exit 1; \
- dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
- $(am__relativize); \
- new_distdir=$$reldir; \
- dir1=$$subdir; dir2="$(top_distdir)"; \
- $(am__relativize); \
- new_top_distdir=$$reldir; \
- echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
- echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
- ($(am__cd) $$subdir && \
- $(MAKE) $(AM_MAKEFLAGS) \
- top_distdir="$$new_top_distdir" \
- distdir="$$new_distdir" \
- am__remove_distdir=: \
- am__skip_length_check=: \
- am__skip_mode_fix=: \
- distdir) \
- || exit 1; \
- fi; \
- done
-check-am: all-am
-check: check-recursive
-all-am: Makefile $(PROGRAMS) $(MANS) $(DATA)
-installdirs: installdirs-recursive
-installdirs-am:
- for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(sysconfdir)"; do \
- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
- done
-install: install-recursive
-install-exec: install-exec-recursive
-install-data: install-data-recursive
-uninstall: uninstall-recursive
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-recursive
-install-strip:
- if test -z '$(STRIP)'; then \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- install; \
- else \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
- fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
-clean: clean-recursive
-
-clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am
-
-distclean: distclean-recursive
- -rm -f ./$(DEPDIR)/client_tables.Po
- -rm -f ./$(DEPDIR)/clparse.Po
- -rm -f ./$(DEPDIR)/dhc6.Po
- -rm -f ./$(DEPDIR)/dhclient.Po
- -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
- distclean-tags
-
-dvi: dvi-recursive
-
-dvi-am:
-
-html: html-recursive
-
-html-am:
-
-info: info-recursive
-
-info-am:
-
-install-data-am: install-man
-
-install-dvi: install-dvi-recursive
-
-install-dvi-am:
-
-install-exec-am: install-dist_sysconfDATA install-sbinPROGRAMS
-
-install-html: install-html-recursive
-
-install-html-am:
-
-install-info: install-info-recursive
-
-install-info-am:
-
-install-man: install-man5 install-man8
-
-install-pdf: install-pdf-recursive
-
-install-pdf-am:
-
-install-ps: install-ps-recursive
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-recursive
- -rm -f ./$(DEPDIR)/client_tables.Po
- -rm -f ./$(DEPDIR)/clparse.Po
- -rm -f ./$(DEPDIR)/dhc6.Po
- -rm -f ./$(DEPDIR)/dhclient.Po
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-recursive
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic
-
-pdf: pdf-recursive
-
-pdf-am:
-
-ps: ps-recursive
-
-ps-am:
-
-uninstall-am: uninstall-dist_sysconfDATA uninstall-man \
- uninstall-sbinPROGRAMS
-
-uninstall-man: uninstall-man5 uninstall-man8
-
-.MAKE: $(am__recursive_targets) install-am install-strip
-
-.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
- am--depfiles check check-am clean clean-generic \
- clean-sbinPROGRAMS cscopelist-am ctags ctags-am distclean \
- distclean-compile distclean-generic distclean-tags distdir dvi \
- dvi-am html html-am info info-am install install-am \
- install-data install-data-am install-dist_sysconfDATA \
- install-dvi install-dvi-am install-exec install-exec-am \
- install-html install-html-am install-info install-info-am \
- install-man install-man5 install-man8 install-pdf \
- install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \
- install-strip installcheck installcheck-am installdirs \
- installdirs-am maintainer-clean maintainer-clean-generic \
- mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
- ps ps-am tags tags-am uninstall uninstall-am \
- uninstall-dist_sysconfDATA uninstall-man uninstall-man5 \
- uninstall-man8 uninstall-sbinPROGRAMS
-
-.PRECIOUS: Makefile
-
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/client/client_tables.c b/client/client_tables.c
deleted file mode 100644
index 25f471d9..00000000
--- a/client/client_tables.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/* client_tables.c
-
- Tables of information only used by client... */
-
-/*
- * Copyright (C) 2017-2022 Internet Systems Consortium, Inc. ("ISC")
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * 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.
- * PO Box 360
- * Newmarket, NH 03857 USA
- * <info@isc.org>
- * https://www.isc.org/
- *
- */
-
-#include "dhcpd.h"
-
-struct universe client_universe;
-static struct option client_options[] = {
- /* @todo dummy-client-parm should be removed with the first real param */
- { "dummy-client-parm", "T", &client_universe, 1, 1 },
- { NULL, NULL, NULL, 0, 0 }
-};
-
-#define CLIENT_HASH_SIZE (2*(sizeof(client_options) / sizeof(struct option)))
-
-void initialize_client_option_spaces()
-{
- int i;
-
- /* Set up the client option universe... */
- client_universe.name = "client";
- client_universe.concat_duplicates = 0;
- client_universe.lookup_func = lookup_hashed_option;
- client_universe.option_state_dereference =
- hashed_option_state_dereference;
- client_universe.save_func = save_hashed_option;
- client_universe.delete_func = delete_hashed_option;
- client_universe.encapsulate = hashed_option_space_encapsulate;
- client_universe.foreach = hashed_option_space_foreach;
- client_universe.length_size = 1; /* Never used ... */
- client_universe.tag_size = 4;
- client_universe.store_tag = putUChar;
- client_universe.store_length = putUChar;
- client_universe.site_code_min = 0;
- client_universe.end = 0;
- client_universe.index = universe_count++;
- universes [client_universe.index] = &client_universe;
- if (!option_name_new_hash(&client_universe.name_hash,
- CLIENT_HASH_SIZE, MDL) ||
- !option_code_new_hash(&client_universe.code_hash,
- CLIENT_HASH_SIZE, MDL))
- log_fatal ("Can't allocate client option hash table.");
- for (i = 0 ; client_options[i].name ; i++) {
- option_code_hash_add(client_universe.code_hash,
- &client_options[i].code, 0,
- &client_options[i], MDL);
- option_name_hash_add(client_universe.name_hash,
- client_options[i].name, 0,
- &client_options[i], MDL);
- }
-
- /* Add the client option space to the option space hash. */
- universe_hash_add (universe_hash,
- client_universe.name, 0, &client_universe, MDL);
-
- /* Make the client universe the configuration option universe. */
- config_universe = &client_universe;
-}
diff --git a/client/clparse.c b/client/clparse.c
deleted file mode 100644
index 74ca499d..00000000
--- a/client/clparse.c
+++ /dev/null
@@ -1,2347 +0,0 @@
-/* clparse.c
-
- Parser for dhclient config and lease files... */
-
-/*
- * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 1996-2003 by Internet Software Consortium
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * 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.
- * PO Box 360
- * Newmarket, NH 03857 USA
- * <info@isc.org>
- * https://www.isc.org/
- *
- */
-
-#include "dhcpd.h"
-#include <errno.h>
-
-struct client_config top_level_config;
-
-#define NUM_DEFAULT_REQUESTED_OPTS 9
-/* There can be 2 extra requested options for DHCPv4-over-DHCPv6. */
-struct option *default_requested_options[NUM_DEFAULT_REQUESTED_OPTS + 2 + 1];
-
-static void parse_client_default_duid(struct parse *cfile);
-static void parse_client6_lease_statement(struct parse *cfile);
-#ifdef DHCPv6
-static struct dhc6_ia *parse_client6_ia_na_statement(struct parse *cfile);
-static struct dhc6_ia *parse_client6_ia_ta_statement(struct parse *cfile);
-static struct dhc6_ia *parse_client6_ia_pd_statement(struct parse *cfile);
-static struct dhc6_addr *parse_client6_iaaddr_statement(struct parse *cfile);
-static struct dhc6_addr *parse_client6_iaprefix_statement(struct parse *cfile);
-#endif /* DHCPv6 */
-
-static void parse_lease_id_format (struct parse *cfile);
-
-extern void discard_duplicate (struct client_lease** lease_list,
- struct client_lease* lease);
-
-/* client-conf-file :== client-declarations END_OF_FILE
- client-declarations :== <nil>
- | client-declaration
- | client-declarations client-declaration */
-
-isc_result_t read_client_conf ()
-{
- struct client_config *config;
- struct interface_info *ip;
- isc_result_t status;
- unsigned code;
-
- /*
- * TODO: LATER constant is very undescriptive. We should review it and
- * change it to something more descriptive or even better remove it
- * completely as it is currently not used.
- */
-#ifdef LATER
- struct parse *parse = NULL;
-#endif
-
- /* Initialize the default request list. */
- memset(default_requested_options, 0, sizeof(default_requested_options));
-
- /* 1 */
- code = DHO_SUBNET_MASK;
- option_code_hash_lookup(&default_requested_options[0],
- dhcp_universe.code_hash, &code, 0, MDL);
-
- /* 2 */
- code = DHO_BROADCAST_ADDRESS;
- option_code_hash_lookup(&default_requested_options[1],
- dhcp_universe.code_hash, &code, 0, MDL);
-
- /* 3 */
- code = DHO_TIME_OFFSET;
- option_code_hash_lookup(&default_requested_options[2],
- dhcp_universe.code_hash, &code, 0, MDL);
-
- /* 4 */
- code = DHO_ROUTERS;
- option_code_hash_lookup(&default_requested_options[3],
- dhcp_universe.code_hash, &code, 0, MDL);
-
- /* 5 */
- code = DHO_DOMAIN_NAME;
- option_code_hash_lookup(&default_requested_options[4],
- dhcp_universe.code_hash, &code, 0, MDL);
-
- /* 6 */
- code = DHO_DOMAIN_NAME_SERVERS;
- option_code_hash_lookup(&default_requested_options[5],
- dhcp_universe.code_hash, &code, 0, MDL);
-
- /* 7 */
- code = DHO_HOST_NAME;
- option_code_hash_lookup(&default_requested_options[6],
- dhcp_universe.code_hash, &code, 0, MDL);
-
- /* 8 */
- code = D6O_NAME_SERVERS;
- option_code_hash_lookup(&default_requested_options[7],
- dhcpv6_universe.code_hash, &code, 0, MDL);
-
- /* 9 */
- code = D6O_DOMAIN_SEARCH;
- option_code_hash_lookup(&default_requested_options[8],
- dhcpv6_universe.code_hash, &code, 0, MDL);
-
- for (code = 0 ; code < NUM_DEFAULT_REQUESTED_OPTS ; code++) {
- if (default_requested_options[code] == NULL)
- log_fatal("Unable to find option definition for "
- "index %u during default parameter request "
- "assembly.", code);
- }
-
-#ifdef DHCP4o6
- /* DHCPv4-over-DHCPv6 extra requested options in code order */
- if (dhcpv4_over_dhcpv6 == 1) {
- /* The DHCP4o6 server option should be requested */
- code = D6O_DHCP4_O_DHCP6_SERVER;
- option_code_hash_lookup(&default_requested_options[9],
- dhcpv6_universe.code_hash,
- &code, 0, MDL);
- if (default_requested_options[9] == NULL) {
- log_fatal("Unable to find option definition for "
- "index %u during default parameter request "
- "assembly.", code);
- }
- } else if (dhcpv4_over_dhcpv6 > 1) {
- /* Called from run_stateless so the IRT should
- be requested too */
- code = D6O_INFORMATION_REFRESH_TIME;
- option_code_hash_lookup(&default_requested_options[9],
- dhcpv6_universe.code_hash,
- &code, 0, MDL);
- if (default_requested_options[9] == NULL) {
- log_fatal("Unable to find option definition for "
- "index %u during default parameter request "
- "assembly.", code);
- }
- code = D6O_DHCP4_O_DHCP6_SERVER;
- option_code_hash_lookup(&default_requested_options[10],
- dhcpv6_universe.code_hash,
- &code, 0, MDL);
- if (default_requested_options[10] == NULL) {
- log_fatal("Unable to find option definition for "
- "index %u during default parameter request "
- "assembly.", code);
- }
- }
-#endif
-
- /* Initialize the top level client configuration. */
- memset (&top_level_config, 0, sizeof top_level_config);
-
- /* Set some defaults... */
- top_level_config.timeout = 60;
- top_level_config.select_interval = 0;
- top_level_config.reboot_timeout = 10;
- top_level_config.retry_interval = 300;
- top_level_config.backoff_cutoff = 15;
- top_level_config.initial_interval = 3;
- top_level_config.lease_id_format = TOKEN_OCTAL;
-
- /*
- * RFC 2131, section 4.4.1 specifies that the client SHOULD wait a
- * random time between 1 and 10 seconds. However, we choose to not
- * implement this default. If user is inclined to really have that
- * delay, he is welcome to do so, using 'initial-delay X;' parameter
- * in config file.
- */
- top_level_config.initial_delay = 0;
-
- top_level_config.bootp_policy = P_ACCEPT;
- top_level_config.script_name = path_dhclient_script;
- top_level_config.requested_options = default_requested_options;
- top_level_config.omapi_port = -1;
- top_level_config.do_forward_update = 1;
- /* Requested lease time, used by DHCPv6 (DHCPv4 uses the option cache)
- */
- top_level_config.requested_lease = 7200;
-
- group_allocate (&top_level_config.on_receipt, MDL);
- if (!top_level_config.on_receipt)
- log_fatal ("no memory for top-level on_receipt group");
-
- group_allocate (&top_level_config.on_transmission, MDL);
- if (!top_level_config.on_transmission)
- log_fatal ("no memory for top-level on_transmission group");
-
- status = read_client_conf_file (path_dhclient_conf,
- (struct interface_info *)0,
- &top_level_config);
-
- if (status != ISC_R_SUCCESS) {
- ;
-#ifdef LATER
- /* Set up the standard name service updater routine. */
- status = new_parse(&parse, -1, default_client_config,
- sizeof(default_client_config) - 1,
- "default client configuration", 0);
- if (status != ISC_R_SUCCESS)
- log_fatal ("can't begin default client config!");
- }
-
- if (parse != NULL) {
- do {
- token = peek_token(&val, NULL, cfile);
- if (token == END_OF_FILE)
- break;
- parse_client_statement(cfile, NULL, &top_level_config);
- } while (1);
- end_parse(&parse);
-#endif
- }
-
- /* Set up state and config structures for clients that don't
- have per-interface configuration statements. */
- config = (struct client_config *)0;
- for (ip = interfaces; ip; ip = ip -> next) {
- if (!ip -> client) {
- ip -> client = (struct client_state *)
- dmalloc (sizeof (struct client_state), MDL);
- if (!ip -> client)
- log_fatal ("no memory for client state.");
- memset (ip -> client, 0, sizeof *(ip -> client));
- ip -> client -> interface = ip;
- }
-
- if (!ip -> client -> config) {
- if (!config) {
- config = (struct client_config *)
- dmalloc (sizeof (struct client_config),
- MDL);
- if (!config)
- log_fatal ("no memory for client config.");
- memcpy (config, &top_level_config,
- sizeof top_level_config);
- }
- ip -> client -> config = config;
- }
- }
- return status;
-}
-
-int read_client_conf_file (const char *name, struct interface_info *ip,
- struct client_config *client)
-{
- int file;
- struct parse *cfile;
- const char *val;
- int token;
- isc_result_t status;
-
- if ((file = open (name, O_RDONLY)) < 0)
- return uerr2isc (errno);
-
- cfile = NULL;
- status = new_parse(&cfile, file, NULL, 0, path_dhclient_conf, 0);
- if (status != ISC_R_SUCCESS || cfile == NULL)
- return status;
-
- do {
- token = peek_token (&val, (unsigned *)0, cfile);
- if (token == END_OF_FILE)
- break;
- parse_client_statement (cfile, ip, client);
- } while (1);
- skip_token(&val, (unsigned *)0, cfile);
- status = (cfile -> warnings_occurred
- ? DHCP_R_BADPARSE
- : ISC_R_SUCCESS);
- end_parse (&cfile);
- return status;
-}
-
-
-/* lease-file :== client-lease-statements END_OF_FILE
- client-lease-statements :== <nil>
- | client-lease-statements LEASE client-lease-statement
- * This routine looks through a lease file and only tries to parse
- * the duid statements.
- */
-
-void read_client_duid ()
-{
- int file;
- isc_result_t status;
- struct parse *cfile;
- const char *val;
- int token;
-
- /* Open the lease file. If we can't open it, just return -
- we can safely trust the server to remember our state. */
- if ((file = open (path_dhclient_duid, O_RDONLY)) < 0)
- return;
-
- cfile = NULL;
- status = new_parse(&cfile, file, NULL, 0, path_dhclient_duid, 0);
- if (status != ISC_R_SUCCESS || cfile == NULL)
- return;
-
- while ((token = next_token(&val, NULL, cfile)) != END_OF_FILE) {
- /*
- * All we care about is DUIDs - if we get anything else
- * just toss it and continue looking for DUIDs until we
- * run out of file.
- */
- if (token == DEFAULT_DUID) {
- parse_client_default_duid(cfile);
- }
- }
-
- end_parse(&cfile);
-}
-
-/* lease-file :== client-lease-statements END_OF_FILE
- client-lease-statements :== <nil>
- | client-lease-statements LEASE client-lease-statement */
-
-void read_client_leases ()
-{
- int file;
- isc_result_t status;
- struct parse *cfile;
- const char *val;
- int token;
-
- /* Open the lease file. If we can't open it, just return -
- we can safely trust the server to remember our state. */
- if ((file = open (path_dhclient_db, O_RDONLY)) < 0)
- return;
-
- cfile = NULL;
- status = new_parse(&cfile, file, NULL, 0, path_dhclient_db, 0);
- if (status != ISC_R_SUCCESS || cfile == NULL)
- return;
-
- do {
- token = next_token (&val, (unsigned *)0, cfile);
- if (token == END_OF_FILE)
- break;
-
- switch (token) {
- case DEFAULT_DUID:
- parse_client_default_duid(cfile);
- break;
-
- case LEASE:
- parse_client_lease_statement(cfile, 0);
- break;
-
- case LEASE6:
- parse_client6_lease_statement(cfile);
- break;
-
- default:
- log_error ("Corrupt lease file - possible data loss!");
- skip_to_semi (cfile);
- break;
- }
- } while (1);
-
- end_parse (&cfile);
-}
-
-/* client-declaration :==
- SEND option-decl |
- DEFAULT option-decl |
- SUPERSEDE option-decl |
- PREPEND option-decl |
- APPEND option-decl |
- hardware-declaration |
- ALSO REQUEST option-list |
- ALSO REQUIRE option-list |
- REQUEST option-list |
- REQUIRE option-list |
- TIMEOUT number |
- RETRY number |
- REBOOT number |
- SELECT_TIMEOUT number |
- SCRIPT string |
- VENDOR_SPACE string |
- interface-declaration |
- LEASE client-lease-statement |
- ALIAS client-lease-statement |
- KEY key-definition */
-
-void parse_client_statement (cfile, ip, config)
- struct parse *cfile;
- struct interface_info *ip;
- struct client_config *config;
-{
- int token;
- const char *val;
- struct option *option = NULL;
- struct executable_statement *stmt;
- int lose;
- char *name;
- enum policy policy;
- int known;
- int tmp, i;
- isc_result_t status;
- struct option ***append_list, **new_list, **cat_list;
-
- switch (peek_token (&val, (unsigned *)0, cfile)) {
- case INCLUDE:
- skip_token(&val, (unsigned *)0, cfile);
- token = next_token (&val, (unsigned *)0, cfile);
- if (token != STRING) {
- parse_warn (cfile, "filename string expected.");
- skip_to_semi (cfile);
- } else {
- status = read_client_conf_file (val, ip, config);
- if (status != ISC_R_SUCCESS)
- parse_warn (cfile, "%s: bad parse.", val);
- parse_semi (cfile);
- }
- return;
-
- case KEY:
- skip_token(&val, (unsigned *)0, cfile);
- if (ip) {
- /* This may seem arbitrary, but there's a reason for
- doing it: the authentication key database is not
- scoped. If we allow the user to declare a key other
- than in the outer scope, the user is very likely to
- believe that the key will only be used in that
- scope. If the user only wants the key to be used on
- one interface, because it's known that the other
- interface may be connected to an insecure net and
- the secret key is considered sensitive, we don't
- want to lull them into believing they've gotten
- their way. This is a bit contrived, but people
- tend not to be entirely rational about security. */
- parse_warn (cfile, "key definition not allowed here.");
- skip_to_semi (cfile);
- break;
- }
- parse_key (cfile);
- return;
-
- case TOKEN_ALSO:
- /* consume ALSO */
- skip_token(&val, NULL, cfile);
-
- /* consume type of ALSO list. */
- token = next_token(&val, NULL, cfile);
-
- if (token == REQUEST) {
- append_list = &config->requested_options;
- } else if (token == REQUIRE) {
- append_list = &config->required_options;
- } else {
- parse_warn(cfile, "expected REQUEST or REQUIRE list");
- skip_to_semi(cfile);
- return;
- }
-
- /* If there is no list, cut the concat short. */
- if (*append_list == NULL) {
- parse_option_list(cfile, append_list);
- return;
- }
-
- /* Count the length of the existing list. */
- for (i = 0 ; (*append_list)[i] != NULL ; i++)
- ; /* This space intentionally left blank. */
-
- /* If there's no codes on the list, cut the concat short. */
- if (i == 0) {
- parse_option_list(cfile, append_list);
- return;
- }
-
- tmp = parse_option_list(cfile, &new_list);
-
- if (tmp == 0 || new_list == NULL)
- return;
-
- /* Allocate 'i + tmp' buckets plus a terminator. */
- cat_list = dmalloc(sizeof(struct option *) * (i + tmp + 1),
- MDL);
-
- if (cat_list == NULL) {
- log_error("Unable to allocate memory for new "
- "request list.");
- skip_to_semi(cfile);
- return;
- }
-
- for (i = 0 ; (*append_list)[i] != NULL ; i++)
- option_reference(&cat_list[i], (*append_list)[i], MDL);
-
- tmp = i;
-
- for (i = 0 ; new_list[i] != 0 ; i++)
- option_reference(&cat_list[tmp++], new_list[i], MDL);
-
- cat_list[tmp] = 0;
-
- /* XXX: We cannot free the old list, because it may have been
- * XXX: assigned from an outer configuration scope (or may be
- * XXX: the static default setting).
- */
- *append_list = cat_list;
-
- return;
-
- /* REQUIRE can either start a policy statement or a
- comma-separated list of names of required options. */
- case REQUIRE:
- skip_token(&val, (unsigned *)0, cfile);
- token = peek_token (&val, (unsigned *)0, cfile);
- if (token == AUTHENTICATION) {
- policy = P_REQUIRE;
- goto do_policy;
- }
- parse_option_list (cfile, &config -> required_options);
- return;
-
- case IGNORE:
- skip_token(&val, (unsigned *)0, cfile);
- policy = P_IGNORE;
- goto do_policy;
-
- case ACCEPT:
- skip_token(&val, (unsigned *)0, cfile);
- policy = P_ACCEPT;
- goto do_policy;
-
- case PREFER:
- skip_token(&val, (unsigned *)0, cfile);
- policy = P_PREFER;
- goto do_policy;
-
- case DONT:
- skip_token(&val, (unsigned *)0, cfile);
- policy = P_DONT;
- goto do_policy;
-
- do_policy:
- token = next_token (&val, (unsigned *)0, cfile);
- if (token == AUTHENTICATION) {
- if (policy != P_PREFER &&
- policy != P_REQUIRE &&
- policy != P_DONT) {
- parse_warn (cfile,
- "invalid authentication policy.");
- skip_to_semi (cfile);
- return;
- }
- config -> auth_policy = policy;
- } else if (token != TOKEN_BOOTP) {
- if (policy != P_PREFER &&
- policy != P_IGNORE &&
- policy != P_ACCEPT) {
- parse_warn (cfile, "invalid bootp policy.");
- skip_to_semi (cfile);
- return;
- }
- config -> bootp_policy = policy;
- } else {
- parse_warn (cfile, "expecting a policy type.");
- skip_to_semi (cfile);
- return;
- }
- break;
-
- case OPTION:
- skip_token(&val, (unsigned *)0, cfile);
- token = peek_token (&val, (unsigned *)0, cfile);
- if (token == SPACE) {
- if (ip) {
- parse_warn (cfile,
- "option space definitions %s",
- " may not be scoped.");
- skip_to_semi (cfile);
- break;
- }
- parse_option_space_decl (cfile);
- return;
- }
-
- known = 0;
- status = parse_option_name(cfile, 1, &known, &option);
- if (status != ISC_R_SUCCESS || option == NULL)
- return;
-
- token = next_token (&val, (unsigned *)0, cfile);
- if (token != CODE) {
- parse_warn (cfile, "expecting \"code\" keyword.");
- skip_to_semi (cfile);
- option_dereference(&option, MDL);
- return;
- }
- if (ip) {
- parse_warn (cfile,
- "option definitions may only appear in %s",
- "the outermost scope.");
- skip_to_semi (cfile);
- option_dereference(&option, MDL);
- return;
- }
-
- /*
- * If the option was known, remove it from the code and name
- * hash tables before redefining it.
- */
- if (known) {
- option_name_hash_delete(option->universe->name_hash,
- option->name, 0, MDL);
- option_code_hash_delete(option->universe->code_hash,
- &option->code, 0, MDL);
- }
-
- parse_option_code_definition(cfile, option);
- option_dereference(&option, MDL);
- return;
-
- case MEDIA:
- skip_token(&val, (unsigned *)0, cfile);
- parse_string_list (cfile, &config -> media, 1);
- return;
-
- case HARDWARE:
- skip_token(&val, (unsigned *)0, cfile);
- if (ip) {
- parse_hardware_param (cfile, &ip -> hw_address);
- } else {
- parse_warn (cfile, "hardware address parameter %s",
- "not allowed here.");
- skip_to_semi (cfile);
- }
- return;
-
- case ANYCAST_MAC:
- skip_token(&val, NULL, cfile);
- if (ip != NULL) {
- parse_hardware_param(cfile, &ip->anycast_mac_addr);
- } else {
- parse_warn(cfile, "anycast mac address parameter "
- "not allowed here.");
- skip_to_semi (cfile);
- }
- return;
-
- case REQUEST:
- skip_token(&val, (unsigned *)0, cfile);
- if (config -> requested_options == default_requested_options)
- config -> requested_options = NULL;
- parse_option_list (cfile, &config -> requested_options);
- return;
-
- case TIMEOUT:
- skip_token(&val, (unsigned *)0, cfile);
- parse_lease_time (cfile, &config -> timeout);
- return;
-
- case RETRY:
- skip_token(&val, (unsigned *)0, cfile);
- parse_lease_time (cfile, &config -> retry_interval);
- return;
-
- case SELECT_TIMEOUT:
- skip_token(&val, (unsigned *)0, cfile);
- parse_lease_time (cfile, &config -> select_interval);
- return;
-
- case OMAPI:
- skip_token(&val, (unsigned *)0, cfile);
- token = next_token (&val, (unsigned *)0, cfile);
- if (token != PORT) {
- parse_warn (cfile,
- "unexpected omapi subtype: %s", val);
- skip_to_semi (cfile);
- return;
- }
- token = next_token (&val, (unsigned *)0, cfile);
- if (token != NUMBER) {
- parse_warn (cfile, "invalid port number: `%s'", val);
- skip_to_semi (cfile);
- return;
- }
- tmp = atoi (val);
- if (tmp < 0 || tmp > 65535)
- parse_warn (cfile, "invalid omapi port %d.", tmp);
- else if (config != &top_level_config)
- parse_warn (cfile,
- "omapi port only works at top level.");
- else
- config -> omapi_port = tmp;
- parse_semi (cfile);
- return;
-
- case DO_FORWARD_UPDATE:
- skip_token(&val, (unsigned *)0, cfile);
- token = next_token (&val, (unsigned *)0, cfile);
- if (!strcasecmp (val, "on") ||
- !strcasecmp (val, "true"))
- config -> do_forward_update = 1;
- else if (!strcasecmp (val, "off") ||
- !strcasecmp (val, "false"))
- config -> do_forward_update = 0;
- else {
- parse_warn (cfile, "expecting boolean value.");
- skip_to_semi (cfile);
- return;
- }
- parse_semi (cfile);
- return;
-
- case REBOOT:
- skip_token(&val, (unsigned *)0, cfile);
- parse_lease_time (cfile, &config -> reboot_timeout);
- return;
-
- case BACKOFF_CUTOFF:
- skip_token(&val, (unsigned *)0, cfile);
- parse_lease_time (cfile, &config -> backoff_cutoff);
- return;
-
- case INITIAL_INTERVAL:
- skip_token(&val, (unsigned *)0, cfile);
- parse_lease_time (cfile, &config -> initial_interval);
- return;
-
- case INITIAL_DELAY:
- skip_token(&val, (unsigned *)0, cfile);
- parse_lease_time (cfile, &config -> initial_delay);
- return;
-
- case SCRIPT:
- skip_token(&val, (unsigned *)0, cfile);
- parse_string (cfile, &config -> script_name, (unsigned *)0);
- return;
-
- case VENDOR:
- skip_token(&val, (unsigned *)0, cfile);
- token = next_token (&val, (unsigned *)0, cfile);
- if (token != OPTION) {
- parse_warn (cfile, "expecting 'vendor option space'");
- skip_to_semi (cfile);
- return;
- }
- token = next_token (&val, (unsigned *)0, cfile);
- if (token != SPACE) {
- parse_warn (cfile, "expecting 'vendor option space'");
- skip_to_semi (cfile);
- return;
- }
- token = next_token (&val, (unsigned *)0, cfile);
- if (!is_identifier (token)) {
- parse_warn (cfile, "expecting an identifier.");
- skip_to_semi (cfile);
- return;
- }
- config -> vendor_space_name = dmalloc (strlen (val) + 1, MDL);
- if (!config -> vendor_space_name)
- log_fatal ("no memory for vendor option space name.");
- strcpy (config -> vendor_space_name, val);
- for (i = 0; i < universe_count; i++)
- if (!strcmp (universes [i] -> name,
- config -> vendor_space_name))
- break;
- if (i == universe_count) {
- log_error ("vendor option space %s not found.",
- config -> vendor_space_name);
- }
- parse_semi (cfile);
- return;
-
- case INTERFACE:
- skip_token(&val, (unsigned *)0, cfile);
- if (ip)
- parse_warn (cfile, "nested interface declaration.");
- parse_interface_declaration (cfile, config, (char *)0);
- return;
-
- case PSEUDO:
- skip_token(&val, (unsigned *)0, cfile);
- token = next_token (&val, (unsigned *)0, cfile);
- name = dmalloc (strlen (val) + 1, MDL);
- if (!name)
- log_fatal ("no memory for pseudo interface name");
- strcpy (name, val);
- parse_interface_declaration (cfile, config, name);
- return;
-
- case LEASE:
- skip_token(&val, (unsigned *)0, cfile);
- parse_client_lease_statement (cfile, 1);
- return;
-
- case ALIAS:
- skip_token(&val, (unsigned *)0, cfile);
- parse_client_lease_statement (cfile, 2);
- return;
-
- case REJECT:
- skip_token(&val, (unsigned *)0, cfile);
- parse_reject_statement (cfile, config);
- return;
-
- case LEASE_ID_FORMAT:
- skip_token(&val, (unsigned *)0, cfile);
- parse_lease_id_format(cfile);
- break;
-
-
- default:
- lose = 0;
- stmt = (struct executable_statement *)0;
- if (!parse_executable_statement (&stmt,
- cfile, &lose, context_any)) {
- if (!lose) {
- parse_warn (cfile, "expecting a statement.");
- skip_to_semi (cfile);
- }
- } else {
- struct executable_statement **eptr, *sptr;
- if (stmt &&
- (stmt -> op == send_option_statement ||
- (stmt -> op == on_statement &&
- (stmt -> data.on.evtypes & ON_TRANSMISSION)))) {
- eptr = &config -> on_transmission -> statements;
- if (stmt -> op == on_statement) {
- sptr = (struct executable_statement *)0;
- executable_statement_reference
- (&sptr,
- stmt -> data.on.statements, MDL);
- executable_statement_dereference (&stmt,
- MDL);
- executable_statement_reference (&stmt,
- sptr,
- MDL);
- executable_statement_dereference (&sptr,
- MDL);
- }
- } else
- eptr = &config -> on_receipt -> statements;
-
- if (stmt) {
- for (; *eptr; eptr = &(*eptr) -> next)
- ;
- executable_statement_reference (eptr,
- stmt, MDL);
- }
- return;
- }
- break;
- }
- parse_semi (cfile);
-}
-
-/* option-list :== option_name |
- option_list COMMA option_name */
-
-int
-parse_option_list(struct parse *cfile, struct option ***list)
-{
- int ix;
- int token;
- const char *val;
- pair p = (pair)0, q = (pair)0, r;
- struct option *option = NULL;
- isc_result_t status;
-
- ix = 0;
- do {
- token = peek_token (&val, (unsigned *)0, cfile);
- if (token == SEMI) {
- token = next_token (&val, (unsigned *)0, cfile);
- break;
- }
- if (!is_identifier (token)) {
- parse_warn (cfile, "%s: expected option name.", val);
- skip_token(&val, (unsigned *)0, cfile);
- skip_to_semi (cfile);
- return 0;
- }
- status = parse_option_name(cfile, 0, NULL, &option);
- if (status != ISC_R_SUCCESS || option == NULL) {
- parse_warn (cfile, "%s: expected option name.", val);
- return 0;
- }
- r = new_pair (MDL);
- if (!r)
- log_fatal ("can't allocate pair for option code.");
- /* XXX: we should probably carry a reference across this */
- r->car = (caddr_t)option;
- option_dereference(&option, MDL);
- r -> cdr = (pair)0;
- if (p)
- q -> cdr = r;
- else
- p = r;
- q = r;
- ++ix;
- token = next_token (&val, (unsigned *)0, cfile);
- } while (token == COMMA);
- if (token != SEMI) {
- parse_warn (cfile, "expecting semicolon.");
- skip_to_semi (cfile);
- return 0;
- }
- /* XXX we can't free the list here, because we may have copied
- XXX it from an outer config state. */
- *list = NULL;
- if (ix) {
- *list = dmalloc ((ix + 1) * sizeof(struct option *), MDL);
- if (!*list)
- log_error ("no memory for option list.");
- else {
- ix = 0;
- for (q = p; q; q = q -> cdr)
- option_reference(&(*list)[ix++],
- (struct option *)q->car, MDL);
- (*list)[ix] = NULL;
- }
- while (p) {
- q = p -> cdr;
- free_pair (p, MDL);
- p = q;
- }
- }
-
- return ix;
-}
-
-/* interface-declaration :==
- INTERFACE string LBRACE client-declarations RBRACE */
-
-void parse_interface_declaration (cfile, outer_config, name)
- struct parse *cfile;
- struct client_config *outer_config;
- char *name;
-{
- int token;
- const char *val;
- struct client_state *client, **cp;
- struct interface_info *ip = (struct interface_info *)0;
-
- token = next_token (&val, (unsigned *)0, cfile);
- if (token != STRING) {
- parse_warn (cfile, "expecting interface name (in quotes).");
- skip_to_semi (cfile);
- return;
- }
-
- if (!interface_or_dummy (&ip, val))
- log_fatal ("Can't allocate interface %s.", val);
-
- /* If we were given a name, this is a pseudo-interface. */
- if (name) {
- make_client_state (&client);
- client -> name = name;
- client -> interface = ip;
- for (cp = &ip -> client; *cp; cp = &((*cp) -> next))
- ;
- *cp = client;
- } else {
- if (!ip -> client) {
- make_client_state (&ip -> client);
- ip -> client -> interface = ip;
- }
- client = ip -> client;
- }
-
- if (!client -> config)
- make_client_config (client, outer_config);
-
- ip -> flags &= ~INTERFACE_AUTOMATIC;
- interfaces_requested = 1;
-
- token = next_token (&val, (unsigned *)0, cfile);
- if (token != LBRACE) {
- parse_warn (cfile, "expecting left brace.");
- skip_to_semi (cfile);
- return;
- }
-
- do {
- token = peek_token (&val, (unsigned *)0, cfile);
- if (token == END_OF_FILE) {
- parse_warn (cfile,
- "unterminated interface declaration.");
- return;
- }
- if (token == RBRACE)
- break;
- parse_client_statement (cfile, ip, client -> config);
- } while (1);
- skip_token(&val, (unsigned *)0, cfile);
-}
-
-int interface_or_dummy (struct interface_info **pi, const char *name)
-{
- struct interface_info *i;
- struct interface_info *ip = (struct interface_info *)0;
- isc_result_t status;
-
- /* Find the interface (if any) that matches the name. */
- for (i = interfaces; i; i = i -> next) {
- if (!strcmp (i -> name, name)) {
- interface_reference (&ip, i, MDL);
- break;
- }
- }
-
- /* If it's not a real interface, see if it's on the dummy list. */
- if (!ip) {
- for (ip = dummy_interfaces; ip; ip = ip -> next) {
- if (!strcmp (ip -> name, name)) {
- interface_reference (&ip, i, MDL);
- break;
- }
- }
- }
-
- /* If we didn't find an interface, make a dummy interface as
- a placeholder. */
- if (!ip) {
- if ((status = interface_allocate (&ip, MDL)) != ISC_R_SUCCESS)
- log_fatal ("Can't record interface %s: %s",
- name, isc_result_totext (status));
-
- if (strlen(name) >= sizeof(ip->name)) {
- interface_dereference(&ip, MDL);
- return 0;
- }
- strcpy(ip->name, name);
-
- if (dummy_interfaces) {
- interface_reference (&ip -> next,
- dummy_interfaces, MDL);
- interface_dereference (&dummy_interfaces, MDL);
- }
- interface_reference (&dummy_interfaces, ip, MDL);
- }
- if (pi)
- status = interface_reference (pi, ip, MDL);
- else
- status = ISC_R_FAILURE;
- interface_dereference (&ip, MDL);
- if (status != ISC_R_SUCCESS)
- return 0;
- return 1;
-}
-
-void make_client_state (state)
- struct client_state **state;
-{
- *state = ((struct client_state *)dmalloc (sizeof **state, MDL));
- if (!*state)
- log_fatal ("no memory for client state\n");
- memset (*state, 0, sizeof **state);
-}
-
-void make_client_config (client, config)
- struct client_state *client;
- struct client_config *config;
-{
- client -> config = (((struct client_config *)
- dmalloc (sizeof (struct client_config), MDL)));
- if (!client -> config)
- log_fatal ("no memory for client config\n");
- memcpy (client -> config, config, sizeof *config);
- if (!clone_group (&client -> config -> on_receipt,
- config -> on_receipt, MDL) ||
- !clone_group (&client -> config -> on_transmission,
- config -> on_transmission, MDL))
- log_fatal ("no memory for client state groups.");
-}
-
-/* client-lease-statement :==
- LBRACE client-lease-declarations RBRACE
-
- client-lease-declarations :==
- <nil> |
- client-lease-declaration |
- client-lease-declarations client-lease-declaration */
-
-
-void parse_client_lease_statement (cfile, is_static)
- struct parse *cfile;
- int is_static;
-{
- struct client_lease *lease;
- struct interface_info *ip = (struct interface_info *)0;
- int token;
- const char *val;
- struct client_state *client = (struct client_state *)0;
-
- token = next_token (&val, (unsigned *)0, cfile);
- if (token != LBRACE) {
- parse_warn (cfile, "expecting left brace.");
- skip_to_semi (cfile);
- return;
- }
-
- lease = ((struct client_lease *)
- dmalloc (sizeof (struct client_lease), MDL));
- if (!lease)
- log_fatal ("no memory for lease.\n");
- memset (lease, 0, sizeof *lease);
- lease -> is_static = is_static;
- if (!option_state_allocate (&lease -> options, MDL))
- log_fatal ("no memory for lease options.\n");
-
- do {
- token = peek_token (&val, (unsigned *)0, cfile);
- if (token == END_OF_FILE) {
- parse_warn (cfile, "unterminated lease declaration.");
- return;
- }
- if (token == RBRACE)
- break;
- parse_client_lease_declaration (cfile, lease, &ip, &client);
- } while (1);
- skip_token(&val, (unsigned *)0, cfile);
-
- /* If the lease declaration didn't include an interface
- declaration that we recognized, it's of no use to us. */
- if (!ip) {
- destroy_client_lease (lease);
- return;
- }
-
- /* Make sure there's a client state structure... */
- if (!ip -> client) {
- make_client_state (&ip -> client);
- ip -> client -> interface = ip;
- }
- if (!client)
- client = ip -> client;
-
- /* If this is an alias lease, it doesn't need to be sorted in. */
- if (is_static == 2) {
- ip -> client -> alias = lease;
- return;
- }
-
- /* The new lease may supersede a lease that's not the
- active lease but is still on the lease list, so scan the
- lease list looking for a lease with the same address, and
- if we find it, toss it. We only allow supercession if
- the leases originated from the same source. In other words,
- either both are from the config file or both are from the lease
- file. This keeps us from discarding fallback leases */
- discard_duplicate (&client->leases, lease);
-
- /* If this is a preloaded lease, just put it on the list of recorded
- leases - don't make it the active lease. */
- if (is_static) {
- lease -> next = client -> leases;
- client -> leases = lease;
- return;
- }
-
- /* The last lease in the lease file on a particular interface is
- the active lease for that interface. Of course, we don't know
- what the last lease in the file is until we've parsed the whole
- file, so at this point, we assume that the lease we just parsed
- is the active lease for its interface. If there's already
- an active lease for the interface, and this lease is for the same
- ip address, then we just toss the old active lease and replace
- it with this one. If this lease is for a different address,
- then if the old active lease has expired, we dump it; if not,
- we put it on the list of leases for this interface which are
- still valid but no longer active. */
- if (client -> active) {
- if (client -> active -> expiry < cur_time)
- destroy_client_lease (client -> active);
- else if (client -> active -> address.len ==
- lease -> address.len &&
- !memcmp (client -> active -> address.iabuf,
- lease -> address.iabuf,
- lease -> address.len))
- destroy_client_lease (client -> active);
- else {
- client -> active -> next = client -> leases;
- client -> leases = client -> active;
- }
- }
- client -> active = lease;
-
- /* phew. */
-}
-
-/* client-lease-declaration :==
- BOOTP |
- INTERFACE string |
- FIXED_ADDR ip_address |
- FILENAME string |
- SERVER_NAME string |
- OPTION option-decl |
- RENEW time-decl |
- REBIND time-decl |
- EXPIRE time-decl |
- KEY id */
-
-void parse_client_lease_declaration (cfile, lease, ipp, clientp)
- struct parse *cfile;
- struct client_lease *lease;
- struct interface_info **ipp;
- struct client_state **clientp;
-{
- int token;
- const char *val;
- struct interface_info *ip;
- struct option_cache *oc;
- struct client_state *client = (struct client_state *)0;
-
- switch (next_token (&val, (unsigned *)0, cfile)) {
- case KEY:
- token = next_token (&val, (unsigned *)0, cfile);
- if (token != STRING && !is_identifier (token)) {
- parse_warn (cfile, "expecting key name.");
- skip_to_semi (cfile);
- break;
- }
- if (omapi_auth_key_lookup_name (&lease -> key, val) !=
- ISC_R_SUCCESS)
- parse_warn (cfile, "unknown key %s", val);
- parse_semi (cfile);
- break;
- case TOKEN_BOOTP:
- lease -> is_bootp = 1;
- break;
-
- case INTERFACE:
- token = next_token (&val, (unsigned *)0, cfile);
- if (token != STRING) {
- parse_warn (cfile,
- "expecting interface name (in quotes).");
- skip_to_semi (cfile);
- break;
- }
- if (!interface_or_dummy (ipp, val))
- log_fatal ("Can't allocate interface %s.", val);
- break;
-
- case NAME:
- token = next_token (&val, (unsigned *)0, cfile);
- ip = *ipp;
- if (!ip) {
- parse_warn (cfile, "state name precedes interface.");
- break;
- }
- for (client = ip -> client; client; client = client -> next)
- if (client -> name && !strcmp (client -> name, val))
- break;
- if (!client)
- parse_warn (cfile,
- "lease specified for unknown pseudo.");
- *clientp = client;
- break;
-
- case FIXED_ADDR:
- if (!parse_ip_addr (cfile, &lease -> address))
- return;
- break;
-
- case MEDIUM:
- parse_string_list (cfile, &lease -> medium, 0);
- return;
-
- case FILENAME:
- parse_string (cfile, &lease -> filename, (unsigned *)0);
- return;
-
- case SERVER_NAME:
- parse_string (cfile, &lease -> server_name, (unsigned *)0);
- return;
-
- case RENEW:
- lease -> renewal = parse_date (cfile);
- return;
-
- case REBIND:
- lease -> rebind = parse_date (cfile);
- return;
-
- case EXPIRE:
- lease -> expiry = parse_date (cfile);
- return;
-
- case OPTION:
- oc = (struct option_cache *)0;
- if (parse_option_decl (&oc, cfile)) {
- save_option(oc->option->universe, lease->options, oc);
- option_cache_dereference (&oc, MDL);
- }
- return;
-
- default:
- parse_warn (cfile, "expecting lease declaration.");
- skip_to_semi (cfile);
- break;
- }
- token = next_token (&val, (unsigned *)0, cfile);
- if (token != SEMI) {
- parse_warn (cfile, "expecting semicolon.");
- skip_to_semi (cfile);
- }
-}
-
-/* Parse a default-duid ""; statement.
- */
-static void
-parse_client_default_duid(struct parse *cfile)
-{
- struct data_string new_duid;
- u_int8_t buf[128];
- unsigned len;
-
- len = parse_X(cfile, buf, sizeof(buf));
- if (len <= 2) {
- parse_warn(cfile, "Invalid DUID contents.");
- skip_to_semi(cfile);
- return;
- }
-
- memset(&new_duid, 0, sizeof(new_duid));
- if (!buffer_allocate(&new_duid.buffer, len, MDL)) {
- parse_warn(cfile, "Out of memory parsing default DUID.");
- skip_to_semi(cfile);
- return;
- }
- new_duid.data = new_duid.buffer->data;
- new_duid.len = len;
-
- memcpy(new_duid.buffer->data, buf, len);
-
- /* Rotate the last entry into place. */
- if (default_duid.buffer != NULL)
- data_string_forget(&default_duid, MDL);
- data_string_copy(&default_duid, &new_duid, MDL);
- data_string_forget(&new_duid, MDL);
-
- parse_semi(cfile);
-}
-
-/* Parse a lease6 {} construct. The v6 client is a little different
- * than the v4 client today, in that it only retains one lease, the
- * active lease, and discards any less recent information. It may
- * be useful in the future to cache additional information, but it
- * is not worth the effort for the moment.
- */
-static void
-parse_client6_lease_statement(struct parse *cfile)
-{
-#if !defined(DHCPv6)
- parse_warn(cfile, "No DHCPv6 support.");
- skip_to_semi(cfile);
-#else /* defined(DHCPv6) */
- struct option_cache *oc = NULL;
- struct dhc6_lease *lease;
- struct dhc6_ia **ia;
- struct client_state *client = NULL;
- struct interface_info *iface = NULL;
- struct data_string ds;
- const char *val;
- unsigned len;
- int token, has_ia, no_semi, has_name;
-
- token = next_token(NULL, NULL, cfile);
- if (token != LBRACE) {
- parse_warn(cfile, "Expecting open curly brace.");
- skip_to_semi(cfile);
- return;
- }
-
- lease = dmalloc(sizeof(*lease), MDL);
- if (lease == NULL) {
- parse_warn(cfile, "Unable to allocate lease state.");
- skip_to_rbrace(cfile, 1);
- return;
- }
-
- option_state_allocate(&lease->options, MDL);
- if (lease->options == NULL) {
- parse_warn(cfile, "Unable to allocate option cache.");
- skip_to_rbrace(cfile, 1);
- dfree(lease, MDL);
- return;
- }
-
- has_ia = 0;
- has_name = 0;
- ia = &lease->bindings;
- token = next_token(&val, NULL, cfile);
- while (token != RBRACE) {
- no_semi = 0;
-
- switch(token) {
- case IA_NA:
- *ia = parse_client6_ia_na_statement(cfile);
- if (*ia != NULL) {
- ia = &(*ia)->next;
- has_ia = 1;
- }
-
- no_semi = 1;
-
- break;
-
- case IA_TA:
- *ia = parse_client6_ia_ta_statement(cfile);
- if (*ia != NULL) {
- ia = &(*ia)->next;
- has_ia = 1;
- }
-
- no_semi = 1;
-
- break;
-
- case IA_PD:
- *ia = parse_client6_ia_pd_statement(cfile);
- if (*ia != NULL) {
- ia = &(*ia)->next;
- has_ia = 1;
- }
-
- no_semi = 1;
-
- break;
-
- case INTERFACE:
- if (iface != NULL) {
- parse_warn(cfile, "Multiple interface names?");
- skip_to_semi(cfile);
- no_semi = 1;
- break;
- }
-
- token = next_token(&val, &len, cfile);
- if (token != STRING) {
- strerror:
- parse_warn(cfile, "Expecting a string.");
- skip_to_semi(cfile);
- no_semi = 1;
- break;
- }
-
- for (iface = interfaces ; iface != NULL ;
- iface = iface->next) {
- if (strcmp(iface->name, val) == 0)
- break;
- }
-
- if (iface == NULL) {
- parse_warn(cfile, "Unknown interface.");
- break;
- }
-
- break;
-
- case NAME:
- has_name = 1;
-
- if (client != NULL) {
- parse_warn(cfile, "Multiple state names?");
- skip_to_semi(cfile);
- no_semi = 1;
- break;
- }
-
- if (iface == NULL) {
- parse_warn(cfile, "Client name without "
- "interface.");
- skip_to_semi(cfile);
- no_semi = 1;
- break;
- }
-
- token = next_token(&val, &len, cfile);
- if (token != STRING)
- goto strerror;
-
- for (client = iface->client ; client != NULL ;
- client = client->next) {
- if ((client->name != NULL) &&
- (strcmp(client->name, val) == 0))
- break;
- }
-
- if (client == NULL) {
- parse_warn(cfile, "Unknown client state %s.",
- val);
- break;
- }
-
- break;
-
- case OPTION:
- if (parse_option_decl(&oc, cfile)) {
- save_option(oc->option->universe,
- lease->options, oc);
- option_cache_dereference(&oc, MDL);
- }
- no_semi = 1;
- break;
-
- case TOKEN_RELEASED:
- case TOKEN_ABANDONED:
- lease->released = ISC_TRUE;
- break;
-
- default:
- parse_warn(cfile, "Unexpected token, %s.", val);
- no_semi = 1;
- skip_to_semi(cfile);
- break;
- }
-
- if (!no_semi)
- parse_semi(cfile);
-
- token = next_token(&val, NULL, cfile);
-
- if (token == END_OF_FILE) {
- parse_warn(cfile, "Unexpected end of file.");
- break;
- }
- }
-
- if (!has_ia) {
- log_debug("Lease with no IA's discarded from lease db.");
- dhc6_lease_destroy(&lease, MDL);
- return;
- }
-
- if (iface == NULL)
- parse_warn(cfile, "Lease has no interface designation.");
- else if (!has_name && (client == NULL)) {
- for (client = iface->client ; client != NULL ;
- client = client->next) {
- if (client->name == NULL)
- break;
- }
- }
-
- if (client == NULL) {
- parse_warn(cfile, "No matching client state.");
- dhc6_lease_destroy(&lease, MDL);
- return;
- }
-
- /* Fetch Preference option from option cache. */
- memset(&ds, 0, sizeof(ds));
- oc = lookup_option(&dhcpv6_universe, lease->options, D6O_PREFERENCE);
- if ((oc != NULL) &&
- evaluate_option_cache(&ds, NULL, NULL, NULL, lease->options,
- NULL, &global_scope, oc, MDL)) {
- if (ds.len != 1) {
- log_error("Invalid length of DHCPv6 Preference option "
- "(%d != 1)", ds.len);
- data_string_forget(&ds, MDL);
- dhc6_lease_destroy(&lease, MDL);
- return;
- } else
- lease->pref = ds.data[0];
-
- data_string_forget(&ds, MDL);
- }
-
- /* Fetch server-id option from option cache. */
- oc = lookup_option(&dhcpv6_universe, lease->options, D6O_SERVERID);
- if ((oc == NULL) ||
- !evaluate_option_cache(&lease->server_id, NULL, NULL, NULL,
- lease->options, NULL, &global_scope, oc,
- MDL) ||
- (lease->server_id.len == 0)) {
- /* This should be impossible... */
- log_error("Invalid SERVERID option cache.");
- dhc6_lease_destroy(&lease, MDL);
- return;
- }
-
- if (client->active_lease != NULL)
- dhc6_lease_destroy(&client->active_lease, MDL);
-
- client->active_lease = lease;
-#endif /* defined(DHCPv6) */
-}
-
-/* Parse an ia_na object from the client lease.
- */
-#ifdef DHCPv6
-static struct dhc6_ia *
-parse_client6_ia_na_statement(struct parse *cfile)
-{
- struct option_cache *oc = NULL;
- struct dhc6_ia *ia;
- struct dhc6_addr **addr;
- const char *val;
- int token, no_semi, len;
- u_int8_t buf[5];
-
- ia = dmalloc(sizeof(*ia), MDL);
- if (ia == NULL) {
- parse_warn(cfile, "Out of memory allocating IA_NA state.");
- skip_to_semi(cfile);
- return NULL;
- }
- ia->ia_type = D6O_IA_NA;
-
- /* Get IAID. */
- len = parse_X(cfile, buf, 5);
- if (len == 4) {
- memcpy(ia->iaid, buf, 4);
- } else {
- parse_warn(cfile, "Expecting IAID of length 4, got %d.", len);
- skip_to_semi(cfile);
- dfree(ia, MDL);
- return NULL;
- }
-
- token = next_token(NULL, NULL, cfile);
- if (token != LBRACE) {
- parse_warn(cfile, "Expecting open curly brace.");
- skip_to_semi(cfile);
- dfree(ia, MDL);
- return NULL;
- }
-
- option_state_allocate(&ia->options, MDL);
- if (ia->options == NULL) {
- parse_warn(cfile, "Unable to allocate option state.");
- skip_to_rbrace(cfile, 1);
- dfree(ia, MDL);
- return NULL;
- }
-
- addr = &ia->addrs;
- token = next_token(&val, NULL, cfile);
- while (token != RBRACE) {
- no_semi = 0;
-
- switch (token) {
- case STARTS:
- token = next_token(&val, NULL, cfile);
- if (token == NUMBER) {
- ia->starts = atoi(val);
- } else {
- parse_warn(cfile, "Expecting a number.");
- skip_to_semi(cfile);
- no_semi = 1;
- }
- break;
-
- case RENEW:
- token = next_token(&val, NULL, cfile);
- if (token == NUMBER) {
- ia->renew = atoi(val);
- } else {
- parse_warn(cfile, "Expecting a number.");
- skip_to_semi(cfile);
- no_semi = 1;
- }
- break;
-
- case REBIND:
- token = next_token(&val, NULL, cfile);
- if (token == NUMBER) {
- ia->rebind = atoi(val);
- } else {
- parse_warn(cfile, "Expecting a number.");
- skip_to_semi(cfile);
- no_semi = 1;
- }
- break;
-
- case IAADDR:
- *addr = parse_client6_iaaddr_statement(cfile);
-
- if (*addr != NULL)
- addr = &(*addr)->next;
-
- no_semi = 1;
-
- break;
-
- case OPTION:
- if (parse_option_decl(&oc, cfile)) {
- save_option(oc->option->universe,
- ia->options, oc);
- option_cache_dereference(&oc, MDL);
- }
- no_semi = 1;
- break;
-
- default:
- parse_warn(cfile, "Unexpected token.");
- no_semi = 1;
- skip_to_semi(cfile);
- break;
- }
-
- if (!no_semi)
- parse_semi(cfile);
-
- token = next_token(&val, NULL, cfile);
-
- if (token == END_OF_FILE) {
- parse_warn(cfile, "Unexpected end of file.");
- break;
- }
- }
-
- return ia;
-}
-#endif /* DHCPv6 */
-
-/* Parse an ia_ta object from the client lease.
- */
-#ifdef DHCPv6
-static struct dhc6_ia *
-parse_client6_ia_ta_statement(struct parse *cfile)
-{
- struct option_cache *oc = NULL;
- struct dhc6_ia *ia;
- struct dhc6_addr **addr;
- const char *val;
- int token, no_semi, len;
- u_int8_t buf[5];
-
- ia = dmalloc(sizeof(*ia), MDL);
- if (ia == NULL) {
- parse_warn(cfile, "Out of memory allocating IA_TA state.");
- skip_to_semi(cfile);
- return NULL;
- }
- ia->ia_type = D6O_IA_TA;
-
- /* Get IAID. */
- len = parse_X(cfile, buf, 5);
- if (len == 4) {
- memcpy(ia->iaid, buf, 4);
- } else {
- parse_warn(cfile, "Expecting IAID of length 4, got %d.", len);
- skip_to_semi(cfile);
- dfree(ia, MDL);
- return NULL;
- }
-
- token = next_token(NULL, NULL, cfile);
- if (token != LBRACE) {
- parse_warn(cfile, "Expecting open curly brace.");
- skip_to_semi(cfile);
- dfree(ia, MDL);
- return NULL;
- }
-
- option_state_allocate(&ia->options, MDL);
- if (ia->options == NULL) {
- parse_warn(cfile, "Unable to allocate option state.");
- skip_to_rbrace(cfile, 1);
- dfree(ia, MDL);
- return NULL;
- }
-
- addr = &ia->addrs;
- token = next_token(&val, NULL, cfile);
- while (token != RBRACE) {
- no_semi = 0;
-
- switch (token) {
- case STARTS:
- token = next_token(&val, NULL, cfile);
- if (token == NUMBER) {
- ia->starts = atoi(val);
- } else {
- parse_warn(cfile, "Expecting a number.");
- skip_to_semi(cfile);
- no_semi = 1;
- }
- break;
-
- /* No RENEW or REBIND */
-
- case IAADDR:
- *addr = parse_client6_iaaddr_statement(cfile);
-
- if (*addr != NULL)
- addr = &(*addr)->next;
-
- no_semi = 1;
-
- break;
-
- case OPTION:
- if (parse_option_decl(&oc, cfile)) {
- save_option(oc->option->universe,
- ia->options, oc);
- option_cache_dereference(&oc, MDL);
- }
- no_semi = 1;
- break;
-
- default:
- parse_warn(cfile, "Unexpected token.");
- no_semi = 1;
- skip_to_semi(cfile);
- break;
- }
-
- if (!no_semi)
- parse_semi(cfile);
-
- token = next_token(&val, NULL, cfile);
-
- if (token == END_OF_FILE) {
- parse_warn(cfile, "Unexpected end of file.");
- break;
- }
- }
-
- return ia;
-}
-#endif /* DHCPv6 */
-
-/* Parse an ia_pd object from the client lease.
- */
-#ifdef DHCPv6
-static struct dhc6_ia *
-parse_client6_ia_pd_statement(struct parse *cfile)
-{
- struct option_cache *oc = NULL;
- struct dhc6_ia *ia;
- struct dhc6_addr **pref;
- const char *val;
- int token, no_semi, len;
- u_int8_t buf[5];
-
- ia = dmalloc(sizeof(*ia), MDL);
- if (ia == NULL) {
- parse_warn(cfile, "Out of memory allocating IA_PD state.");
- skip_to_semi(cfile);
- return NULL;
- }
- ia->ia_type = D6O_IA_PD;
-
- /* Get IAID. */
- len = parse_X(cfile, buf, 5);
- if (len == 4) {
- memcpy(ia->iaid, buf, 4);
- } else {
- parse_warn(cfile, "Expecting IAID of length 4, got %d.", len);
- skip_to_semi(cfile);
- dfree(ia, MDL);
- return NULL;
- }
-
- token = next_token(NULL, NULL, cfile);
- if (token != LBRACE) {
- parse_warn(cfile, "Expecting open curly brace.");
- skip_to_semi(cfile);
- dfree(ia, MDL);
- return NULL;
- }
-
- option_state_allocate(&ia->options, MDL);
- if (ia->options == NULL) {
- parse_warn(cfile, "Unable to allocate option state.");
- skip_to_rbrace(cfile, 1);
- dfree(ia, MDL);
- return NULL;
- }
-
- pref = &ia->addrs;
- token = next_token(&val, NULL, cfile);
- while (token != RBRACE) {
- no_semi = 0;
-
- switch (token) {
- case STARTS:
- token = next_token(&val, NULL, cfile);
- if (token == NUMBER) {
- ia->starts = atoi(val);
- } else {
- parse_warn(cfile, "Expecting a number.");
- skip_to_semi(cfile);
- no_semi = 1;
- }
- break;
-
- case RENEW:
- token = next_token(&val, NULL, cfile);
- if (token == NUMBER) {
- ia->renew = atoi(val);
- } else {
- parse_warn(cfile, "Expecting a number.");
- skip_to_semi(cfile);
- no_semi = 1;
- }
- break;
-
- case REBIND:
- token = next_token(&val, NULL, cfile);
- if (token == NUMBER) {
- ia->rebind = atoi(val);
- } else {
- parse_warn(cfile, "Expecting a number.");
- skip_to_semi(cfile);
- no_semi = 1;
- }
- break;
-
- case IAPREFIX:
- *pref = parse_client6_iaprefix_statement(cfile);
-
- if (*pref != NULL)
- pref = &(*pref)->next;
-
- no_semi = 1;
-
- break;
-
- case OPTION:
- if (parse_option_decl(&oc, cfile)) {
- save_option(oc->option->universe,
- ia->options, oc);
- option_cache_dereference(&oc, MDL);
- }
- no_semi = 1;
- break;
-
- default:
- parse_warn(cfile, "Unexpected token.");
- no_semi = 1;
- skip_to_semi(cfile);
- break;
- }
-
- if (!no_semi)
- parse_semi(cfile);
-
- token = next_token(&val, NULL, cfile);
-
- if (token == END_OF_FILE) {
- parse_warn(cfile, "Unexpected end of file.");
- break;
- }
- }
-
- return ia;
-}
-#endif /* DHCPv6 */
-
-/* Parse an iaaddr {} structure. */
-#ifdef DHCPv6
-static struct dhc6_addr *
-parse_client6_iaaddr_statement(struct parse *cfile)
-{
- struct option_cache *oc = NULL;
- struct dhc6_addr *addr;
- const char *val;
- int token, no_semi;
-
- addr = dmalloc(sizeof(*addr), MDL);
- if (addr == NULL) {
- parse_warn(cfile, "Unable to allocate IAADDR state.");
- skip_to_semi(cfile);
- return NULL;
- }
-
- /* Get IP address. */
- if (!parse_ip6_addr(cfile, &addr->address)) {
- skip_to_semi(cfile);
- dfree(addr, MDL);
- return NULL;
- }
-
- token = next_token(NULL, NULL, cfile);
- if (token != LBRACE) {
- parse_warn(cfile, "Expecting open curly bracket.");
- skip_to_semi(cfile);
- dfree(addr, MDL);
- return NULL;
- }
-
- option_state_allocate(&addr->options, MDL);
- if (addr->options == NULL) {
- parse_warn(cfile, "Unable to allocate option state.");
- skip_to_semi(cfile);
- dfree(addr, MDL);
- return NULL;
- }
-
- token = next_token(&val, NULL, cfile);
- while (token != RBRACE) {
- no_semi = 0;
-
- switch (token) {
- case STARTS:
- token = next_token(&val, NULL, cfile);
- if (token == NUMBER) {
- addr->starts = atoi(val);
- } else {
- parse_warn(cfile, "Expecting a number.");
- skip_to_semi(cfile);
- no_semi = 1;
- }
- break;
-
- case PREFERRED_LIFE:
- token = next_token(&val, NULL, cfile);
- if (token == NUMBER) {
- addr->preferred_life = atoi(val);
- } else {
- parse_warn(cfile, "Expecting a number.");
- skip_to_semi(cfile);
- no_semi = 1;
- }
- break;
-
- case MAX_LIFE:
- token = next_token(&val, NULL, cfile);
- if (token == NUMBER) {
- addr->max_life = atoi(val);
- } else {
- parse_warn(cfile, "Expecting a number.");
- skip_to_semi(cfile);
- no_semi = 1;
- }
- break;
-
- case OPTION:
- if (parse_option_decl(&oc, cfile)) {
- save_option(oc->option->universe,
- addr->options, oc);
- option_cache_dereference(&oc, MDL);
- }
- no_semi = 1;
- break;
-
- default:
- parse_warn(cfile, "Unexpected token.");
- skip_to_rbrace(cfile, 1);
- no_semi = 1;
- break;
- }
-
- if (!no_semi)
- parse_semi(cfile);
-
- token = next_token(&val, NULL, cfile);
- if (token == END_OF_FILE) {
- parse_warn(cfile, "Unexpected end of file.");
- break;
- }
- }
-
- return addr;
-}
-#endif /* DHCPv6 */
-
-/* Parse an iaprefix {} structure. */
-#ifdef DHCPv6
-static struct dhc6_addr *
-parse_client6_iaprefix_statement(struct parse *cfile)
-{
- struct option_cache *oc = NULL;
- struct dhc6_addr *pref;
- const char *val;
- int token, no_semi;
-
- pref = dmalloc(sizeof(*pref), MDL);
- if (pref == NULL) {
- parse_warn(cfile, "Unable to allocate IAPREFIX state.");
- skip_to_semi(cfile);
- return NULL;
- }
-
- /* Get IP prefix. */
- if (!parse_ip6_prefix(cfile, &pref->address, &pref->plen)) {
- skip_to_semi(cfile);
- dfree(pref, MDL);
- return NULL;
- }
-
- token = next_token(NULL, NULL, cfile);
- if (token != LBRACE) {
- parse_warn(cfile, "Expecting open curly bracket.");
- skip_to_semi(cfile);
- dfree(pref, MDL);
- return NULL;
- }
-
- option_state_allocate(&pref->options, MDL);
- if (pref->options == NULL) {
- parse_warn(cfile, "Unable to allocate option state.");
- skip_to_semi(cfile);
- dfree(pref, MDL);
- return NULL;
- }
-
- token = next_token(&val, NULL, cfile);
- while (token != RBRACE) {
- no_semi = 0;
-
- switch (token) {
- case STARTS:
- token = next_token(&val, NULL, cfile);
- if (token == NUMBER) {
- pref->starts = atoi(val);
- } else {
- parse_warn(cfile, "Expecting a number.");
- skip_to_semi(cfile);
- no_semi = 1;
- }
- break;
-
- case PREFERRED_LIFE:
- token = next_token(&val, NULL, cfile);
- if (token == NUMBER) {
- pref->preferred_life = atoi(val);
- } else {
- parse_warn(cfile, "Expecting a number.");
- skip_to_semi(cfile);
- no_semi = 1;
- }
- break;
-
- case MAX_LIFE:
- token = next_token(&val, NULL, cfile);
- if (token == NUMBER) {
- pref->max_life = atoi(val);
- } else {
- parse_warn(cfile, "Expecting a number.");
- skip_to_semi(cfile);
- no_semi = 1;
- }
- break;
-
- case OPTION:
- if (parse_option_decl(&oc, cfile)) {
- save_option(oc->option->universe,
- pref->options, oc);
- option_cache_dereference(&oc, MDL);
- }
- no_semi = 1;
- break;
-
- default:
- parse_warn(cfile, "Unexpected token.");
- skip_to_rbrace(cfile, 1);
- no_semi = 1;
- break;
- }
-
- if (!no_semi)
- parse_semi(cfile);
-
- token = next_token(&val, NULL, cfile);
- if (token == END_OF_FILE) {
- parse_warn(cfile, "Unexpected end of file.");
- break;
- }
- }
-
- return pref;
-}
-#endif /* DHCPv6 */
-
-void parse_string_list (cfile, lp, multiple)
- struct parse *cfile;
- struct string_list **lp;
- int multiple;
-{
- int token;
- const char *val;
- struct string_list *cur, *tmp;
-
- /* Find the last medium in the media list. */
- if (*lp) {
- for (cur = *lp; cur -> next; cur = cur -> next)
- ;
- } else {
- cur = (struct string_list *)0;
- }
-
- do {
- token = next_token (&val, (unsigned *)0, cfile);
- if (token != STRING) {
- parse_warn (cfile, "Expecting media options.");
- skip_to_semi (cfile);
- return;
- }
-
- tmp = ((struct string_list *)
- dmalloc (strlen (val) + sizeof (struct string_list),
- MDL));
- if (!tmp)
- log_fatal ("no memory for string list entry.");
-
- strcpy (tmp -> string, val);
- tmp -> next = (struct string_list *)0;
-
- /* Store this medium at the end of the media list. */
- if (cur)
- cur -> next = tmp;
- else
- *lp = tmp;
- cur = tmp;
-
- token = next_token (&val, (unsigned *)0, cfile);
- } while (multiple && token == COMMA);
-
- if (token != SEMI) {
- parse_warn (cfile, "expecting semicolon.");
- skip_to_semi (cfile);
- }
-}
-
-void parse_reject_statement (cfile, config)
- struct parse *cfile;
- struct client_config *config;
-{
- int token;
- const char *val;
- struct iaddrmatch match;
- struct iaddrmatchlist *list;
- int i;
-
- do {
- if (!parse_ip_addr_with_subnet (cfile, &match)) {
- /* no warn: parser will have reported what's wrong */
- skip_to_semi (cfile);
- return;
- }
-
- /* check mask is not all zeros (because that would
- * reject EVERY address). This check could be
- * simplified if we assume that the mask *always*
- * represents a prefix .. but perhaps it might be
- * useful to have a mask which is not a proper prefix
- * (perhaps for ipv6?). The following is almost as
- * efficient as inspection of match.mask.iabuf[0] when
- * it IS a true prefix, and is more general when it is
- * not.
- */
-
- for (i=0 ; i < match.mask.len ; i++) {
- if (match.mask.iabuf[i]) {
- break;
- }
- }
-
- if (i == match.mask.len) {
- /* oops we found all zeros */
- parse_warn(cfile, "zero-length prefix is not permitted "
- "for reject statement");
- skip_to_semi(cfile);
- return;
- }
-
- list = dmalloc(sizeof(struct iaddrmatchlist), MDL);
- if (!list)
- log_fatal ("no memory for reject list!");
-
- list->match = match;
- list->next = config->reject_list;
- config->reject_list = list;
-
- token = next_token (&val, (unsigned *)0, cfile);
- } while (token == COMMA);
-
- if (token != SEMI) {
- parse_warn (cfile, "expecting semicolon.");
- skip_to_semi (cfile);
- }
-}
-
-/* allow-deny-keyword :== BOOTP
- | BOOTING
- | DYNAMIC_BOOTP
- | UNKNOWN_CLIENTS */
-
-int parse_allow_deny (oc, cfile, flag)
- struct option_cache **oc;
- struct parse *cfile;
- int flag;
-{
- parse_warn (cfile, "allow/deny/ignore not permitted here.");
- skip_to_semi (cfile);
- return 0;
-}
-
-
-
-/*!
- * \brief Parses an lease-id-format statement
- *
- * A valid statement looks like this:
- *
- * lease-id-format :==
- * LEASE_ID_FORMAT TOKEN_OCTAL | TOKEN_HEX ;
- *
- * This function is used to parse the lease-id-format statement. It sets
- * top_level_config.lease_id_format.
- *
- * \param cfile the current parse file
- *
-*/
-void parse_lease_id_format (struct parse *cfile)
-{
- enum dhcp_token token;
- const char *val;
-
- token = next_token(&val, NULL, cfile);
- switch(token) {
- case TOKEN_OCTAL:
- top_level_config.lease_id_format = TOKEN_OCTAL;
- break;
- case TOKEN_HEX:
- top_level_config.lease_id_format = TOKEN_HEX;
- break;
- default:
- parse_warn(cfile, "lease-id-format is invalid: "
- " it must be octal or hex.");
- skip_to_semi(cfile);
- return;
- }
-
- log_debug("lease_id_format is: %s",
- (top_level_config.lease_id_format == TOKEN_OCTAL
- ? "octal" : "hex"));
-
-}
diff --git a/client/dhc6.c b/client/dhc6.c
deleted file mode 100644
index 35cf3d08..00000000
--- a/client/dhc6.c
+++ /dev/null
@@ -1,6129 +0,0 @@
-/* dhc6.c - DHCPv6 client routines. */
-
-/*
- * Copyright (C) 2012-2022 Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 2006-2010 by Internet Systems Consortium, Inc. ("ISC")
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * 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.
- * PO Box 360
- * Newmarket, NH 03857 USA
- * <info@isc.org>
- * https://www.isc.org/
- */
-
-#include "dhcpd.h"
-
-#ifdef DHCPv6
-
-struct sockaddr_in6 DHCPv6DestAddr;
-
-/*
- * Option definition structures that are used by the software - declared
- * here once and assigned at startup to save lookups.
- */
-struct option *clientid_option = NULL;
-struct option *elapsed_option = NULL;
-struct option *ia_na_option = NULL;
-struct option *ia_ta_option = NULL;
-struct option *ia_pd_option = NULL;
-struct option *iaaddr_option = NULL;
-struct option *iaprefix_option = NULL;
-struct option *oro_option = NULL;
-struct option *irt_option = NULL;
-
-static struct dhc6_lease *dhc6_dup_lease(struct dhc6_lease *lease,
- const char *file, int line);
-static struct dhc6_ia *dhc6_dup_ia(struct dhc6_ia *ia,
- const char *file, int line);
-static struct dhc6_addr *dhc6_dup_addr(struct dhc6_addr *addr,
- const char *file, int line);
-static void dhc6_ia_destroy(struct dhc6_ia **src, const char *file, int line);
-static isc_result_t dhc6_parse_ia_na(struct dhc6_ia **pia,
- struct packet *packet,
- struct option_state *options,
- unsigned code);
-static isc_result_t dhc6_parse_ia_ta(struct dhc6_ia **pia,
- struct packet *packet,
- struct option_state *options,
- unsigned code);
-static isc_result_t dhc6_parse_ia_pd(struct dhc6_ia **pia,
- struct packet *packet,
- struct option_state *options,
- unsigned code);
-static isc_result_t dhc6_parse_addrs(struct dhc6_addr **paddr,
- struct packet *packet,
- struct option_state *options);
-static isc_result_t dhc6_parse_prefixes(struct dhc6_addr **ppref,
- struct packet *packet,
- struct option_state *options);
-static struct dhc6_ia *find_ia(struct dhc6_ia *head,
- u_int16_t type, const char *id);
-static struct dhc6_addr *find_addr(struct dhc6_addr *head,
- struct iaddr *address);
-static struct dhc6_addr *find_pref(struct dhc6_addr *head,
- struct iaddr *prefix, u_int8_t plen);
-void init_handler(struct packet *packet, struct client_state *client);
-void info_request_handler(struct packet *packet, struct client_state *client);
-void rapid_commit_handler(struct packet *packet, struct client_state *client);
-void do_init6(void *input);
-void do_info_request6(void *input);
-void do_confirm6(void *input);
-void reply_handler(struct packet *packet, struct client_state *client);
-static isc_result_t dhc6_create_iaid(struct client_state *client,
- struct data_string *ia,
- int idx,
- unsigned len);
-static int dhc6_count_ia(struct dhc6_lease *lease,
- u_int16_t ia_type);
-static isc_result_t dhc6_bare_ia_xx(struct client_state *client,
- struct data_string *packet,
- int wanted,
- u_int16_t ia_type);
-static isc_result_t dhc6_add_ia_na(struct client_state *client,
- struct data_string *packet,
- struct dhc6_lease *lease,
- u_int8_t message,
- int wanted,
- int *added);
-static isc_result_t dhc6_add_ia_ta(struct client_state *client,
- struct data_string *packet,
- struct dhc6_lease *lease,
- u_int8_t message,
- int wanted,
- int *added);
-static isc_result_t dhc6_add_ia_pd(struct client_state *client,
- struct data_string *packet,
- struct dhc6_lease *lease,
- u_int8_t message,
- int wanted,
- int *added);
-static isc_boolean_t stopping_finished(void);
-static void dhc6_merge_lease(struct dhc6_lease *src, struct dhc6_lease *dst);
-void do_select6(void *input);
-void do_refresh6(void *input);
-static void do_release6(void *input);
-static void start_bound(struct client_state *client);
-static void start_decline6(struct client_state *client);
-static void do_decline6(void *input);
-static void start_informed(struct client_state *client);
-void informed_handler(struct packet *packet, struct client_state *client);
-void bound_handler(struct packet *packet, struct client_state *client);
-void start_renew6(void *input);
-void start_rebind6(void *input);
-void do_depref(void *input);
-void do_expire(void *input);
-static void make_client6_options(struct client_state *client,
- struct option_state **op,
- struct dhc6_lease *lease, u_int8_t message);
-static void script_write_params6(struct client_state *client,
- const char *prefix,
- struct option_state *options);
-static void script_write_requested6(struct client_state *client);
-static isc_boolean_t active_prefix(struct client_state *client);
-
-static int check_timing6(struct client_state *client, u_int8_t msg_type,
- char *msg_str, struct dhc6_lease *lease,
- struct data_string *ds);
-static isc_result_t dhc6_get_status_code(struct option_state *options,
- unsigned *code,
- struct data_string *msg);
-static isc_result_t dhc6_check_status(isc_result_t rval,
- struct option_state *options,
- const char *scope,
- unsigned *code);
-static int dhc6_score_lease(struct client_state *client,
- struct dhc6_lease *lease);
-static isc_result_t dhc6_add_ia_na_decline(struct client_state *client,
- struct data_string *packet,
- struct dhc6_lease *lease);
-static int drop_declined_addrs(struct dhc6_lease *lease);
-static isc_boolean_t unexpired_address_in_lease(struct dhc6_lease *lease);
-
-extern int onetry;
-extern int stateless;
-extern int prefix_len_hint;
-extern int address_prefix_len;
-
-/*
- * Assign DHCPv6 port numbers as a client.
- */
-void
-dhcpv6_client_assignments(void)
-{
- struct servent *ent;
- unsigned code;
-
- if (path_dhclient_pid == NULL)
- path_dhclient_pid = _PATH_DHCLIENT6_PID;
- if (path_dhclient_db == NULL)
- path_dhclient_db = _PATH_DHCLIENT6_DB;
-
- if (local_port == 0) {
- ent = getservbyname("dhcpv6-client", "udp");
- if (ent == NULL)
- local_port = htons(546);
- else
- local_port = ent->s_port;
- }
-
- if (remote_port == 0) {
- ent = getservbyname("dhcpv6-server", "udp");
- if (ent == NULL)
- remote_port = htons(547);
- else
- remote_port = ent->s_port;
- }
-
- memset(&DHCPv6DestAddr, 0, sizeof(DHCPv6DestAddr));
- DHCPv6DestAddr.sin6_family = AF_INET6;
- DHCPv6DestAddr.sin6_port = remote_port;
- if (inet_pton(AF_INET6, All_DHCP_Relay_Agents_and_Servers,
- &DHCPv6DestAddr.sin6_addr) <= 0) {
- log_fatal("Bad address %s", All_DHCP_Relay_Agents_and_Servers);
- }
-
- code = D6O_CLIENTID;
- if (!option_code_hash_lookup(&clientid_option,
- dhcpv6_universe.code_hash, &code, 0, MDL))
- log_fatal("Unable to find the CLIENTID option definition.");
-
- code = D6O_ELAPSED_TIME;
- if (!option_code_hash_lookup(&elapsed_option,
- dhcpv6_universe.code_hash, &code, 0, MDL))
- log_fatal("Unable to find the ELAPSED_TIME option definition.");
-
- code = D6O_IA_NA;
- if (!option_code_hash_lookup(&ia_na_option, dhcpv6_universe.code_hash,
- &code, 0, MDL))
- log_fatal("Unable to find the IA_NA option definition.");
-
- code = D6O_IA_TA;
- if (!option_code_hash_lookup(&ia_ta_option, dhcpv6_universe.code_hash,
- &code, 0, MDL))
- log_fatal("Unable to find the IA_TA option definition.");
-
- code = D6O_IA_PD;
- if (!option_code_hash_lookup(&ia_pd_option, dhcpv6_universe.code_hash,
- &code, 0, MDL))
- log_fatal("Unable to find the IA_PD option definition.");
-
- code = D6O_IAADDR;
- if (!option_code_hash_lookup(&iaaddr_option, dhcpv6_universe.code_hash,
- &code, 0, MDL))
- log_fatal("Unable to find the IAADDR option definition.");
-
- code = D6O_IAPREFIX;
- if (!option_code_hash_lookup(&iaprefix_option,
- dhcpv6_universe.code_hash,
- &code, 0, MDL))
- log_fatal("Unable to find the IAPREFIX option definition.");
-
- code = D6O_ORO;
- if (!option_code_hash_lookup(&oro_option, dhcpv6_universe.code_hash,
- &code, 0, MDL))
- log_fatal("Unable to find the ORO option definition.");
-
- code = D6O_INFORMATION_REFRESH_TIME;
- if (!option_code_hash_lookup(&irt_option, dhcpv6_universe.code_hash,
- &code, 0, MDL))
- log_fatal("Unable to find the IRT option definition.");
-
-#ifndef __CYGWIN32__ /* XXX */
- endservent();
-#endif
-}
-
-/*
- * Instead of implementing RFC3315 RAND (section 14) as a float "between"
- * -0.1 and 0.1 non-inclusive, we implement it as an integer.
- *
- * The result is expected to follow this table:
- *
- * split range answer
- * - ERROR - base <= 0
- * 0 1 0..0 1 <= base <= 10
- * 1 3 -1..1 11 <= base <= 20
- * 2 5 -2..2 21 <= base <= 30
- * 3 7 -3..3 31 <= base <= 40
- * ...
- *
- * XXX: For this to make sense, we really need to do timing on a
- * XXX: usec scale...we currently can assume zero for any value less than
- * XXX: 11, which are very common in early stages of transmission for most
- * XXX: messages.
- */
-static TIME
-dhc6_rand(TIME base)
-{
- TIME rval;
- TIME range;
- TIME split;
-
- /*
- * A zero or less timeout is a bad thing...we don't want to
- * DHCP-flood anyone.
- */
- if (base <= 0)
- log_fatal("Impossible condition at %s:%d.", MDL);
-
- /*
- * The first thing we do is count how many random integers we want
- * in either direction (best thought of as the maximum negative
- * integer, as we will subtract this potentially from a random 0).
- */
- split = (base - 1) / 10;
-
- /* Don't bother with the rest of the math if we know we'll get 0. */
- if (split == 0)
- return 0;
-
- /*
- * Then we count the total number of integers in this set. This
- * is twice the number of integers in positive and negative
- * directions, plus zero (-1, 0, 1 is 3, -2..2 adds 2 to 5, so forth).
- */
- range = (split * 2) + 1;
-
- /* Take a random number from [0..(range-1)]. */
- rval = random();
- rval %= range;
-
- /* Offset it to uncover potential negative values. */
- rval -= split;
-
- return rval;
-}
-
-/* Initialize message exchange timers (set RT from Initial-RT). */
-static void
-dhc6_retrans_init(struct client_state *client)
-{
- int xid;
-
- /* Initialize timers. */
- client->txcount = 0;
- client->RT = client->IRT + dhc6_rand(client->IRT);
-
- /* Generate a new random 24-bit transaction ID for this exchange. */
-
-#if (RAND_MAX >= 0x00ffffff)
- xid = random();
-#elif (RAND_MAX >= 0x0000ffff)
- xid = (random() << 16) ^ random();
-#elif (RAND_MAX >= 0x000000ff)
- xid = (random() << 16) ^ (random() << 8) ^ random();
-#else
-# error "Random number generator of less than 8 bits not supported."
-#endif
-
- client->dhcpv6_transaction_id[0] = (xid >> 16) & 0xff;
- client->dhcpv6_transaction_id[1] = (xid >> 8) & 0xff;
- client->dhcpv6_transaction_id[2] = xid & 0xff;
-}
-
-/* Advance the DHCPv6 retransmission state once. */
-static void
-dhc6_retrans_advance(struct client_state *client)
-{
- struct timeval elapsed, elapsed_plus_rt;
-
- /* elapsed = cur - start */
- elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
- elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
- if (elapsed.tv_usec < 0) {
- elapsed.tv_sec -= 1;
- elapsed.tv_usec += 1000000;
- }
- /* retrans_advance is called after consuming client->RT. */
- /* elapsed += RT */
- elapsed.tv_sec += client->RT / 100;
- elapsed.tv_usec += (client->RT % 100) * 10000;
- if (elapsed.tv_usec >= 1000000) {
- elapsed.tv_sec += 1;
- elapsed.tv_usec -= 1000000;
- }
- /*
- * Save what the time will be after the current RT to determine
- * what the delta to MRD will be.
- */
- elapsed_plus_rt.tv_sec = elapsed.tv_sec;
- elapsed_plus_rt.tv_usec = elapsed.tv_usec;
-
- /*
- * RT for each subsequent message transmission is based on the previous
- * value of RT:
- *
- * RT = 2*RTprev + RAND*RTprev
- */
- client->RT += client->RT + dhc6_rand(client->RT);
-
- /*
- * MRT specifies an upper bound on the value of RT (disregarding the
- * randomization added by the use of RAND). If MRT has a value of 0,
- * there is no upper limit on the value of RT. Otherwise:
- *
- * if (RT > MRT)
- * RT = MRT + RAND*MRT
- */
- if ((client->MRT != 0) && (client->RT > client->MRT))
- client->RT = client->MRT + dhc6_rand(client->MRT);
-
- /*
- * Further, if there's an MRD, we should wake up upon reaching
- * the MRD rather than at some point after it.
- */
- if (client->MRD == 0) {
- /* Done. */
- client->txcount++;
- return;
- }
- /* elapsed += client->RT */
- elapsed.tv_sec += client->RT / 100;
- elapsed.tv_usec += (client->RT % 100) * 10000;
- if (elapsed.tv_usec >= 1000000) {
- elapsed.tv_sec += 1;
- elapsed.tv_usec -= 1000000;
- }
- if (elapsed.tv_sec >= client->MRD) {
- /*
- * The desired RT is the time that will be remaining in MRD
- * when the current timeout finishes. We then have
- * desired RT = MRD - (elapsed time + previous RT); or
- * desired RT = MRD - elapsed_plut_rt;
- */
- client->RT = client->MRD - elapsed_plus_rt.tv_sec;
- client->RT = (client->RT * 100) -
- (elapsed_plus_rt.tv_usec / 10000);
- if (client->RT < 0)
- client->RT = 0;
- }
- client->txcount++;
-}
-
-/* Quick validation of DHCPv6 ADVERTISE packet contents. */
-static int
-valid_reply(struct packet *packet, struct client_state *client)
-{
- struct data_string sid, cid;
- struct option_cache *oc;
- int rval = ISC_TRUE;
-
- memset(&sid, 0, sizeof(sid));
- memset(&cid, 0, sizeof(cid));
-
- if (!lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID)) {
- log_error("Response without a server identifier received.");
- rval = ISC_FALSE;
- }
-
- oc = lookup_option(&dhcpv6_universe, packet->options, D6O_CLIENTID);
- if (!oc ||
- !evaluate_option_cache(&sid, packet, NULL, client, packet->options,
- client->sent_options, &global_scope, oc,
- MDL)) {
- log_error("Response without a client identifier.");
- rval = ISC_FALSE;
- }
-
- oc = lookup_option(&dhcpv6_universe, client->sent_options,
- D6O_CLIENTID);
- if (!oc ||
- !evaluate_option_cache(&cid, packet, NULL, client,
- client->sent_options, NULL, &global_scope,
- oc, MDL)) {
- log_error("Local client identifier is missing!");
- rval = ISC_FALSE;
- }
-
- if (sid.len == 0 ||
- sid.len != cid.len ||
- memcmp(sid.data, cid.data, sid.len)) {
- log_error("Advertise with matching transaction ID, but "
- "mismatching client id.");
- rval = ISC_FALSE;
- }
-
- /* clean up pointers to the strings */
- if (sid.data != NULL)
- data_string_forget(&sid, MDL);
- if (cid.data != NULL)
- data_string_forget(&cid, MDL);
-
- return rval;
-}
-
-/*
- * Create a complete copy of a DHCPv6 lease structure.
- */
-static struct dhc6_lease *
-dhc6_dup_lease(struct dhc6_lease *lease, const char *file, int line)
-{
- struct dhc6_lease *copy;
- struct dhc6_ia **insert_ia, *ia;
-
- copy = dmalloc(sizeof(*copy), file, line);
- if (copy == NULL) {
- log_error("Out of memory for v6 lease structure.");
- return NULL;
- }
-
- data_string_copy(&copy->server_id, &lease->server_id, file, line);
- copy->pref = lease->pref;
-
- memcpy(copy->dhcpv6_transaction_id, lease->dhcpv6_transaction_id,
- sizeof(copy->dhcpv6_transaction_id));
-
- option_state_reference(&copy->options, lease->options, file, line);
-
- insert_ia = &copy->bindings;
- for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
- *insert_ia = dhc6_dup_ia(ia, file, line);
-
- if (*insert_ia == NULL) {
- dhc6_lease_destroy(&copy, file, line);
- return NULL;
- }
-
- insert_ia = &(*insert_ia)->next;
- }
-
- return copy;
-}
-
-/*
- * Duplicate an IA structure.
- */
-static struct dhc6_ia *
-dhc6_dup_ia(struct dhc6_ia *ia, const char *file, int line)
-{
- struct dhc6_ia *copy;
- struct dhc6_addr **insert_addr, *addr;
-
- copy = dmalloc(sizeof(*ia), file, line);
- if (copy == NULL) {
- log_error("Out of memory for v6 duplicate IA structure.");
- return NULL;
- }
-
- memcpy(copy->iaid, ia->iaid, sizeof(copy->iaid));
-
- copy->ia_type = ia->ia_type;
- copy->starts = ia->starts;
- copy->renew = ia->renew;
- copy->rebind = ia->rebind;
-
- insert_addr = &copy->addrs;
- for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
- *insert_addr = dhc6_dup_addr(addr, file, line);
-
- if (*insert_addr == NULL) {
- dhc6_ia_destroy(&copy, file, line);
- return NULL;
- }
-
- insert_addr = &(*insert_addr)->next;
- }
-
- if (ia->options != NULL)
- option_state_reference(&copy->options, ia->options,
- file, line);
-
- return copy;
-}
-
-/*
- * Duplicate an IAADDR or IAPREFIX structure.
- */
-static struct dhc6_addr *
-dhc6_dup_addr(struct dhc6_addr *addr, const char *file, int line)
-{
- struct dhc6_addr *copy;
-
- copy = dmalloc(sizeof(*addr), file, line);
-
- if (copy == NULL)
- return NULL;
-
- memcpy(&copy->address, &addr->address, sizeof(copy->address));
-
- copy->plen = addr->plen;
- copy->flags = addr->flags;
- copy->starts = addr->starts;
- copy->preferred_life = addr->preferred_life;
- copy->max_life = addr->max_life;
-
- if (addr->options != NULL)
- option_state_reference(&copy->options, addr->options,
- file, line);
-
- return copy;
-}
-
-/*
- * Form a DHCPv6 lease structure based upon packet contents. Creates and
- * populates IA's and any IAADDR/IAPREFIX's they contain.
- * Parsed options are deleted in order to not save them in the lease file.
- *
- * If we get a status code of NoAddrs or NoPrefix we toss the affected
- * IAs. If it as at the top level we toss all IAs of that type. If it
- * is in an IA we only toss that one. According to the spec we shouldn't
- * get a NoPrefix status at the top level but we will allow it.
- *
- */
-static struct dhc6_lease *
-dhc6_leaseify(struct packet *packet, struct client_state* client)
-{
- struct data_string ds;
- struct dhc6_lease *lease;
- struct option_cache *oc;
- unsigned code;
-
- lease = dmalloc(sizeof(*lease), MDL);
- if (lease == NULL) {
- log_error("Out of memory for v6 lease structure.");
- return NULL;
- }
-
- memcpy(lease->dhcpv6_transaction_id, packet->dhcpv6_transaction_id, 3);
- option_state_reference(&lease->options, packet->options, MDL);
-
- memset(&ds, 0, sizeof(ds));
-
- /* Determine preference (default zero). */
- oc = lookup_option(&dhcpv6_universe, lease->options, D6O_PREFERENCE);
- if (oc &&
- evaluate_option_cache(&ds, packet, NULL, NULL, lease->options,
- NULL, &global_scope, oc, MDL)) {
- if (ds.len != 1) {
- log_error("Invalid length of DHCPv6 Preference option "
- "(%d != 1)", ds.len);
- data_string_forget(&ds, MDL);
- dhc6_lease_destroy(&lease, MDL);
- return NULL;
- } else {
- lease->pref = ds.data[0];
- log_debug("RCV: X-- Preference %u.",
- (unsigned)lease->pref);
- }
-
- data_string_forget(&ds, MDL);
- }
- delete_option(&dhcpv6_universe, lease->options, D6O_PREFERENCE);
-
- /* Get the top level status code. If the code is NoAddrsAvail
- * or NoPrefixAvail strip it from the options as we don't
- * want it to show up in check_[advertise reply]. We
- * pass it along to the parse_ia_xx routines and they
- * will drop the affected IAs for NoAddrs or NoPrefix,
- * other status codes will be ignored and handled by
- * the check_[advertise reply] routines.
- */
- code = STATUS_Success;
- if ((dhc6_get_status_code(lease->options, &code, NULL) == ISC_R_SUCCESS)
- &&
- ((code == STATUS_NoAddrsAvail) || (code == STATUS_NoPrefixAvail))) {
- delete_option(&dhcpv6_universe, lease->options,
- D6O_STATUS_CODE);
- }
-
- /*
- * Dig into recursive DHCPv6 pockets for IA_NA and contained IAADDR
- * options.
- */
- if (dhc6_parse_ia_na(&lease->bindings, packet,
- lease->options, code) != ISC_R_SUCCESS) {
- /* Error conditions are logged by the caller. */
- dhc6_lease_destroy(&lease, MDL);
- return NULL;
- }
- /*
- * Dig into recursive DHCPv6 pockets for IA_TA and contained IAADDR
- * options.
- */
- if (dhc6_parse_ia_ta(&lease->bindings, packet,
- lease->options, code) != ISC_R_SUCCESS) {
- /* Error conditions are logged by the caller. */
- dhc6_lease_destroy(&lease, MDL);
- return NULL;
- }
- /*
- * Dig into recursive DHCPv6 pockets for IA_PD and contained IAPREFIX
- * options.
- */
- if (dhc6_parse_ia_pd(&lease->bindings, packet,
- lease->options, code) != ISC_R_SUCCESS) {
- /* Error conditions are logged by the caller. */
- dhc6_lease_destroy(&lease, MDL);
- return NULL;
- }
-
- /*
- * This is last because in the future we may want to make a different
- * key based upon additional information from the packet (we may need
- * to allow multiple leases in one client state per server, but we're
- * not sure based on what additional keys now).
- */
- oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
- if ((oc == NULL) ||
- !evaluate_option_cache(&lease->server_id, packet, NULL, NULL,
- lease->options, NULL, &global_scope,
- oc, MDL) ||
- lease->server_id.len == 0) {
- /* This should be impossible due to validation checks earlier.
- */
- log_error("Invalid SERVERID option cache.");
- dhc6_lease_destroy(&lease, MDL);
- return NULL;
- } else {
- log_debug("RCV: X-- Server ID: %s",
- print_hex_1(lease->server_id.len,
- lease->server_id.data, 52));
- }
-
- execute_statements_in_scope(NULL, (struct packet *)packet, NULL,
- client, lease->options, lease->options,
- &global_scope, client->config->on_receipt,
- NULL, NULL);
-
- return lease;
-}
-
-static isc_result_t
-dhc6_parse_ia_na(struct dhc6_ia **pia, struct packet *packet,
- struct option_state *options, unsigned code)
-{
- struct data_string ds;
- struct dhc6_ia *ia;
- struct option_cache *oc;
- isc_result_t result;
- unsigned ia_code;
-
- memset(&ds, 0, sizeof(ds));
-
- oc = lookup_option(&dhcpv6_universe, options, D6O_IA_NA);
- for ( ; oc != NULL ; oc = oc->next) {
- ia = dmalloc(sizeof(*ia), MDL);
- if (ia == NULL) {
- log_error("Out of memory allocating IA_NA structure.");
- return ISC_R_NOMEMORY;
- } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
- options, NULL,
- &global_scope, oc, MDL) &&
- ds.len >= 12) {
- memcpy(ia->iaid, ds.data, 4);
- ia->ia_type = D6O_IA_NA;
- ia->starts = cur_time;
- ia->renew = getULong(ds.data + 4);
- ia->rebind = getULong(ds.data + 8);
-
- log_debug("RCV: X-- IA_NA %s",
- print_hex_1(4, ia->iaid, 59));
- /* XXX: This should be the printed time I think. */
- log_debug("RCV: | X-- starts %u",
- (unsigned)ia->starts);
- log_debug("RCV: | X-- t1 - renew +%u", ia->renew);
- log_debug("RCV: | X-- t2 - rebind +%u", ia->rebind);
-
- /*
- * RFC3315 section 22.4, discard IA_NA's that
- * have t1 greater than t2, and both not zero.
- * Since RFC3315 defines this behaviour, it is not
- * an error - just normal operation.
- *
- * Note that RFC3315 says we MUST honor these values
- * if they are not zero. So insane values are
- * totally OK.
- */
- if ((ia->renew > 0) && (ia->rebind > 0) &&
- (ia->renew > ia->rebind)) {
- log_debug("RCV: | !-- INVALID renew/rebind "
- "times, IA_NA discarded.");
- dfree(ia, MDL);
- data_string_forget(&ds, MDL);
- continue;
- }
-
- if (ds.len > 12) {
- log_debug("RCV: | X-- [Options]");
-
- if (!option_state_allocate(&ia->options,
- MDL)) {
- log_error("Out of memory allocating "
- "IA_NA option state.");
- dfree(ia, MDL);
- data_string_forget(&ds, MDL);
- return ISC_R_NOMEMORY;
- }
-
- if (!parse_option_buffer(ia->options,
- ds.data + 12,
- ds.len - 12,
- &dhcpv6_universe)) {
- log_error("Corrupt IA_NA options.");
- option_state_dereference(&ia->options,
- MDL);
- dfree(ia, MDL);
- data_string_forget(&ds, MDL);
- return DHCP_R_BADPARSE;
- }
- }
- data_string_forget(&ds, MDL);
-
- if (ia->options != NULL) {
- result = dhc6_parse_addrs(&ia->addrs, packet,
- ia->options);
- if (result != ISC_R_SUCCESS) {
- option_state_dereference(&ia->options,
- MDL);
- dfree(ia, MDL);
- return result;
- }
- }
-
- /* If we have no addresses or the top level status code
- * or the status code in this IA indicate no addresses
- * toss the IA.
- */
- ia_code = STATUS_Success;
- if ((ia->addrs == NULL) ||
- (code == STATUS_NoAddrsAvail) ||
- ((ia->options != NULL) &&
- (dhc6_get_status_code(ia->options, &ia_code, NULL)
- == ISC_R_SUCCESS) &&
- (ia_code == STATUS_NoAddrsAvail))) {
- log_debug("RCV: | !-- Status code of "
- "no addrs, IA_NA discarded.");
- dhc6_ia_destroy(&ia, MDL);
- continue;
- }
-
- while (*pia != NULL)
- pia = &(*pia)->next;
- *pia = ia;
- pia = &ia->next;
- } else {
- log_error("Invalid IA_NA option cache.");
- dfree(ia, MDL);
- data_string_forget(&ds, MDL);
- return ISC_R_UNEXPECTED;
- }
- }
- delete_option(&dhcpv6_universe, options, D6O_IA_NA);
-
- return ISC_R_SUCCESS;
-}
-
-static isc_result_t
-dhc6_parse_ia_ta(struct dhc6_ia **pia, struct packet *packet,
- struct option_state *options, unsigned code)
-{
- struct data_string ds;
- struct dhc6_ia *ia;
- struct option_cache *oc;
- isc_result_t result;
- unsigned ia_code;
-
- memset(&ds, 0, sizeof(ds));
-
- oc = lookup_option(&dhcpv6_universe, options, D6O_IA_TA);
- for ( ; oc != NULL ; oc = oc->next) {
- ia = dmalloc(sizeof(*ia), MDL);
- if (ia == NULL) {
- log_error("Out of memory allocating IA_TA structure.");
- return ISC_R_NOMEMORY;
- } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
- options, NULL,
- &global_scope, oc, MDL) &&
- ds.len >= 4) {
- memcpy(ia->iaid, ds.data, 4);
- ia->ia_type = D6O_IA_TA;
- ia->starts = cur_time;
-
- log_debug("RCV: X-- IA_TA %s",
- print_hex_1(4, ia->iaid, 59));
- /* XXX: This should be the printed time I think. */
- log_debug("RCV: | X-- starts %u",
- (unsigned)ia->starts);
-
- if (ds.len > 4) {
- log_debug("RCV: | X-- [Options]");
-
- if (!option_state_allocate(&ia->options,
- MDL)) {
- log_error("Out of memory allocating "
- "IA_TA option state.");
- dfree(ia, MDL);
- data_string_forget(&ds, MDL);
- return ISC_R_NOMEMORY;
- }
-
- if (!parse_option_buffer(ia->options,
- ds.data + 4,
- ds.len - 4,
- &dhcpv6_universe)) {
- log_error("Corrupt IA_TA options.");
- option_state_dereference(&ia->options,
- MDL);
- dfree(ia, MDL);
- data_string_forget(&ds, MDL);
- return DHCP_R_BADPARSE;
- }
- }
- data_string_forget(&ds, MDL);
-
- if (ia->options != NULL) {
- result = dhc6_parse_addrs(&ia->addrs, packet,
- ia->options);
- if (result != ISC_R_SUCCESS) {
- option_state_dereference(&ia->options,
- MDL);
- dfree(ia, MDL);
- return result;
- }
- }
-
- /* If we have no addresses or the top level status code
- * or the status code in this IA indicate no addresses
- * toss the IA.
- */
- ia_code = STATUS_Success;
- if ((ia->addrs == NULL) ||
- (code == STATUS_NoAddrsAvail) ||
- ((ia->options != NULL) &&
- (dhc6_get_status_code(ia->options, &ia_code, NULL)
- == ISC_R_SUCCESS) &&
- (ia_code == STATUS_NoAddrsAvail))) {
- log_debug("RCV: | !-- Status code of "
- "no addrs, IA_TA discarded.");
- dhc6_ia_destroy(&ia, MDL);
- continue;
- }
-
- while (*pia != NULL)
- pia = &(*pia)->next;
- *pia = ia;
- pia = &ia->next;
- } else {
- log_error("Invalid IA_TA option cache.");
- dfree(ia, MDL);
- data_string_forget(&ds, MDL);
- return ISC_R_UNEXPECTED;
- }
- }
- delete_option(&dhcpv6_universe, options, D6O_IA_TA);
-
- return ISC_R_SUCCESS;
-}
-
-static isc_result_t
-dhc6_parse_ia_pd(struct dhc6_ia **pia, struct packet *packet,
- struct option_state *options, unsigned code)
-{
- struct data_string ds;
- struct dhc6_ia *ia;
- struct option_cache *oc;
- isc_result_t result;
- unsigned ia_code;
-
- memset(&ds, 0, sizeof(ds));
-
- oc = lookup_option(&dhcpv6_universe, options, D6O_IA_PD);
- for ( ; oc != NULL ; oc = oc->next) {
- ia = dmalloc(sizeof(*ia), MDL);
- if (ia == NULL) {
- log_error("Out of memory allocating IA_PD structure.");
- return ISC_R_NOMEMORY;
- } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
- options, NULL,
- &global_scope, oc, MDL) &&
- ds.len >= 12) {
- memcpy(ia->iaid, ds.data, 4);
- ia->ia_type = D6O_IA_PD;
- ia->starts = cur_time;
- ia->renew = getULong(ds.data + 4);
- ia->rebind = getULong(ds.data + 8);
-
- log_debug("RCV: X-- IA_PD %s",
- print_hex_1(4, ia->iaid, 59));
- /* XXX: This should be the printed time I think. */
- log_debug("RCV: | X-- starts %u",
- (unsigned)ia->starts);
- log_debug("RCV: | X-- t1 - renew +%u", ia->renew);
- log_debug("RCV: | X-- t2 - rebind +%u", ia->rebind);
-
- /*
- * RFC3633 section 9, discard IA_PD's that
- * have t1 greater than t2, and both not zero.
- * Since RFC3633 defines this behaviour, it is not
- * an error - just normal operation.
- */
- if ((ia->renew > 0) && (ia->rebind > 0) &&
- (ia->renew > ia->rebind)) {
- log_debug("RCV: | !-- INVALID renew/rebind "
- "times, IA_PD discarded.");
- dfree(ia, MDL);
- data_string_forget(&ds, MDL);
- continue;
- }
-
- if (ds.len > 12) {
- log_debug("RCV: | X-- [Options]");
-
- if (!option_state_allocate(&ia->options,
- MDL)) {
- log_error("Out of memory allocating "
- "IA_PD option state.");
- dfree(ia, MDL);
- data_string_forget(&ds, MDL);
- return ISC_R_NOMEMORY;
- }
-
- if (!parse_option_buffer(ia->options,
- ds.data + 12,
- ds.len - 12,
- &dhcpv6_universe)) {
- log_error("Corrupt IA_PD options.");
- option_state_dereference(&ia->options,
- MDL);
- dfree(ia, MDL);
- data_string_forget(&ds, MDL);
- return DHCP_R_BADPARSE;
- }
- }
- data_string_forget(&ds, MDL);
-
- if (ia->options != NULL) {
- result = dhc6_parse_prefixes(&ia->addrs,
- packet,
- ia->options);
- if (result != ISC_R_SUCCESS) {
- option_state_dereference(&ia->options,
- MDL);
- dfree(ia, MDL);
- return result;
- }
- }
-
- /* If we have no prefixes or the top level status code
- * or the status code in this IA indicate no prefixes
- * toss the IA.
- */
- ia_code = STATUS_Success;
- if ((ia->addrs == NULL) ||
- (code == STATUS_NoPrefixAvail) ||
- ((ia->options != NULL) &&
- (dhc6_get_status_code(ia->options, &ia_code, NULL)
- == ISC_R_SUCCESS) &&
- (ia_code == STATUS_NoPrefixAvail))) {
- log_debug("RCV: | !-- Status code of "
- "no prefix, IA_PD discarded.");
- dhc6_ia_destroy(&ia, MDL);
- continue;
- }
-
- while (*pia != NULL)
- pia = &(*pia)->next;
- *pia = ia;
- pia = &ia->next;
- } else {
- log_error("Invalid IA_PD option cache.");
- dfree(ia, MDL);
- data_string_forget(&ds, MDL);
- return ISC_R_UNEXPECTED;
- }
- }
- delete_option(&dhcpv6_universe, options, D6O_IA_PD);
-
- return ISC_R_SUCCESS;
-}
-
-
-static isc_result_t
-dhc6_parse_addrs(struct dhc6_addr **paddr, struct packet *packet,
- struct option_state *options)
-{
- struct data_string ds;
- struct option_cache *oc;
- struct dhc6_addr *addr;
- isc_result_t rval = ISC_R_SUCCESS;
- unsigned code;
-
- memset(&ds, 0, sizeof(ds));
-
- oc = lookup_option(&dhcpv6_universe, options, D6O_IAADDR);
- for ( ; oc != NULL ; oc = oc->next) {
- addr = dmalloc(sizeof(*addr), MDL);
- if (addr == NULL) {
- log_error("Out of memory allocating "
- "address structure.");
- return ISC_R_NOMEMORY;
- } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
- options, NULL, &global_scope,
- oc, MDL) &&
- (ds.len >= 24)) {
-
- addr->address.len = 16;
- memcpy(addr->address.iabuf, ds.data, 16);
- addr->starts = cur_time;
- addr->preferred_life = getULong(ds.data + 16);
- addr->max_life = getULong(ds.data + 20);
-
- log_debug("RCV: | | X-- IAADDR %s",
- piaddr(addr->address));
- log_debug("RCV: | | | X-- Preferred lifetime %u.",
- addr->preferred_life);
- log_debug("RCV: | | | X-- Max lifetime %u.",
- addr->max_life);
-
- /*
- * RFC 3315 section 22.6 says we must discard
- * addresses whose pref is later than valid.
- */
- if ((addr->preferred_life > addr->max_life)) {
- log_debug("RCV: | | | !-- INVALID lifetimes, "
- "IAADDR discarded. Check your "
- "server configuration.");
- dfree(addr, MDL);
- data_string_forget(&ds, MDL);
- continue;
- }
-
- /*
- * Fortunately this is the last recursion in the
- * protocol.
- */
- if (ds.len > 24) {
- if (!option_state_allocate(&addr->options,
- MDL)) {
- log_error("Out of memory allocating "
- "IAADDR option state.");
- dfree(addr, MDL);
- data_string_forget(&ds, MDL);
- return ISC_R_NOMEMORY;
- }
-
- if (!parse_option_buffer(addr->options,
- ds.data + 24,
- ds.len - 24,
- &dhcpv6_universe)) {
- log_error("Corrupt IAADDR options.");
- option_state_dereference(&addr->options,
- MDL);
- dfree(addr, MDL);
- data_string_forget(&ds, MDL);
- return DHCP_R_BADPARSE;
- }
- }
-
- data_string_forget(&ds, MDL);
-
- if (addr->options != NULL) {
- log_debug("RCV: | | | X-- [Options]");
-
- /* Get the status code if the return value
- * indicates an error or the status code
- * indicates no address toss the address
- */
- code = STATUS_Success;
- rval = dhc6_check_status(ISC_R_SUCCESS,
- addr->options,
- "IAADDR", &code);
- if (rval != ISC_R_SUCCESS) {
- log_debug("RCV: | | | X-- Status code"
- " issue, IAADDR discarded.");
- option_state_dereference(&addr->options,
- MDL);
- dfree(addr, MDL);
- continue;
- }
- }
-
- *paddr = addr;
- paddr = &addr->next;
- } else {
- log_error("Invalid IAADDR option cache.");
- dfree(addr, MDL);
- data_string_forget(&ds, MDL);
- return ISC_R_UNEXPECTED;
- }
- }
- delete_option(&dhcpv6_universe, options, D6O_IAADDR);
-
- return ISC_R_SUCCESS;
-}
-
-static isc_result_t
-dhc6_parse_prefixes(struct dhc6_addr **ppfx, struct packet *packet,
- struct option_state *options)
-{
- struct data_string ds;
- struct option_cache *oc;
- struct dhc6_addr *pfx;
- isc_result_t rval = ISC_R_SUCCESS;
- unsigned code;
-
- memset(&ds, 0, sizeof(ds));
-
- oc = lookup_option(&dhcpv6_universe, options, D6O_IAPREFIX);
- for ( ; oc != NULL ; oc = oc->next) {
- pfx = dmalloc(sizeof(*pfx), MDL);
- if (pfx == NULL) {
- log_error("Out of memory allocating "
- "prefix structure.");
- return ISC_R_NOMEMORY;
- } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
- options, NULL, &global_scope,
- oc, MDL) &&
- (ds.len >= 25)) {
-
- pfx->preferred_life = getULong(ds.data);
- pfx->max_life = getULong(ds.data + 4);
- pfx->plen = getUChar(ds.data + 8);
- pfx->address.len = 16;
- memcpy(pfx->address.iabuf, ds.data + 9, 16);
- pfx->starts = cur_time;
-
- log_debug("RCV: | | X-- IAPREFIX %s/%d",
- piaddr(pfx->address), (int)pfx->plen);
- log_debug("RCV: | | | X-- Preferred lifetime %u.",
- pfx->preferred_life);
- log_debug("RCV: | | | X-- Max lifetime %u.",
- pfx->max_life);
-
- /* Sanity check over the prefix length */
- if ((pfx->plen < 4) || (pfx->plen > 128)) {
- log_debug("RCV: | | | !-- INVALID prefix "
- "length, IAPREFIX discarded. "
- "Check your server configuration.");
- dfree(pfx, MDL);
- data_string_forget(&ds, MDL);
- continue;
- }
- /*
- * RFC 3633 section 10 says we must discard
- * prefixes whose pref is later than valid.
- */
- if ((pfx->preferred_life > pfx->max_life)) {
- log_debug("RCV: | | | !-- INVALID lifetimes, "
- "IAPREFIX discarded. Check your "
- "server configuration.");
- dfree(pfx, MDL);
- data_string_forget(&ds, MDL);
- continue;
- }
-
- /*
- * Fortunately this is the last recursion in the
- * protocol.
- */
- if (ds.len > 25) {
- if (!option_state_allocate(&pfx->options,
- MDL)) {
- log_error("Out of memory allocating "
- "IAPREFIX option state.");
- dfree(pfx, MDL);
- data_string_forget(&ds, MDL);
- return ISC_R_NOMEMORY;
- }
-
- if (!parse_option_buffer(pfx->options,
- ds.data + 25,
- ds.len - 25,
- &dhcpv6_universe)) {
- log_error("Corrupt IAPREFIX options.");
- option_state_dereference(&pfx->options,
- MDL);
- dfree(pfx, MDL);
- data_string_forget(&ds, MDL);
- return DHCP_R_BADPARSE;
- }
- }
-
- data_string_forget(&ds, MDL);
-
- if (pfx->options != NULL) {
- log_debug("RCV: | | | X-- [Options]");
-
- /* Get the status code if the return value
- * indicates an error or the status code
- * indicates no prefix toss the prefix
- */
- code = STATUS_Success;
- rval = dhc6_check_status(ISC_R_SUCCESS,
- pfx->options,
- "IAPREFIX", &code);
- if (rval != ISC_R_SUCCESS) {
- log_debug("RCV: | | | X-- Status code"
- " issue IAPREFIX discarded.");
- option_state_dereference(&pfx->options,
- MDL);
- dfree(pfx, MDL);
- continue;
- }
- }
-
- *ppfx = pfx;
- ppfx = &pfx->next;
- } else {
- log_error("Invalid IAPREFIX option cache.");
- dfree(pfx, MDL);
- data_string_forget(&ds, MDL);
- return ISC_R_UNEXPECTED;
- }
- }
- delete_option(&dhcpv6_universe, options, D6O_IAPREFIX);
-
- return ISC_R_SUCCESS;
-}
-
-/* Clean up a lease object, deallocate all its parts, and set it to NULL. */
-void
-dhc6_lease_destroy(struct dhc6_lease **src, const char *file, int line)
-{
- struct dhc6_ia *ia, *nia;
- struct dhc6_lease *lease;
-
- if (src == NULL || *src == NULL) {
- log_error("Attempt to destroy null lease.");
- return;
- }
- lease = *src;
-
- data_string_forget(&lease->server_id, file, line);
- for (ia = lease->bindings ; ia != NULL ; ia = nia) {
- nia = ia->next;
-
- dhc6_ia_destroy(&ia, file, line);
- }
-
- if (lease->options != NULL)
- option_state_dereference(&lease->options, file, line);
-
- dfree(lease, file, line);
- *src = NULL;
-}
-
-/*
- * Traverse the addresses list, and destroy their contents, and NULL the
- * list pointer.
- */
-static void
-dhc6_ia_destroy(struct dhc6_ia **src, const char *file, int line)
-{
- struct dhc6_addr *addr, *naddr;
- struct dhc6_ia *ia;
-
- if (src == NULL || *src == NULL) {
- log_error("Attempt to destroy null IA.");
- return;
- }
- ia = *src;
-
- for (addr = ia->addrs ; addr != NULL ; addr = naddr) {
- naddr = addr->next;
-
- if (addr->options != NULL)
- option_state_dereference(&addr->options, file, line);
-
- dfree(addr, file, line);
- }
-
- if (ia->options != NULL)
- option_state_dereference(&ia->options, file, line);
-
- dfree(ia, file, line);
- *src = NULL;
-}
-
-/*
- * For a given lease, insert it into the tail of the lease list. Upon
- * finding a duplicate by server id, remove it and take over its position.
- */
-static void
-insert_lease(struct dhc6_lease **head, struct dhc6_lease *new)
-{
- while (*head != NULL) {
- if ((*head)->server_id.len == new->server_id.len &&
- memcmp((*head)->server_id.data, new->server_id.data,
- new->server_id.len) == 0) {
- new->next = (*head)->next;
- dhc6_lease_destroy(head, MDL);
- break;
- }
-
- head= &(*head)->next;
- }
-
- *head = new;
- return;
-}
-
-/*!
- *
- * \brief Determine a score for a lease. We use this to
- * compare and choose leases if we receive multiple candidates.
- *
- * We originally started with scores of 50 for a binding and 100 for
- * an address. This would select multiple adresses over multiple
- * bindings. As part of the 7550 work I've changed this to be
- * 10000 for a binding, 100 for an address and 1 for an option.
- * This will cause us to choose a lease with more bindings over
- * a lease with less bindings but more addresses which seems
- * to be the best selection criteria to me.
- * In theory we could end up with a lease with enough addresses
- * or options being better but at 100 to 1 I don't think it's likely.
- *
- * \param client = the state of the entire client
- * \param lease = the lease to score.
- *
- * \retrun the score of the lease
- */
-
-/* The scores for individual items. */
-#ifdef USE_ORIGINAL_CLIENT_LEASE_WEIGHTS
-#define SCORE_BINDING 50
-#define SCORE_ADDRESS 100
-#else
-#define SCORE_BINDING 10000
-#define SCORE_ADDRESS 100
-#endif
-
-#define SCORE_OPTION 1
-/* We need a lease with at least 1 binding and 1 address */
-#define SCORE_MIN (SCORE_BINDING + SCORE_ADDRESS)
-
-static int
-dhc6_score_lease(struct client_state *client, struct dhc6_lease *lease)
-{
- struct dhc6_ia *ia;
- struct dhc6_addr *addr;
- struct option **req;
- int i;
-
- if (lease->score)
- return lease->score;
-
- lease->score = SCORE_OPTION;
-
- /* If this lease lacks a required option, dump it. */
- /* XXX: we should be able to cache the failure... */
- req = client->config->required_options;
- if (req != NULL) {
- for (i = 0 ; req[i] != NULL ; i++) {
- if (lookup_option(&dhcpv6_universe, lease->options,
- req[i]->code) == NULL) {
- lease->score = 0;
- return lease->score;
- }
- }
- }
-
- /* If this lease contains a requested option, improve its score. */
- req = client->config->requested_options;
- if (req != NULL) {
- for (i = 0 ; req[i] != NULL ; i++) {
- if (lookup_option(&dhcpv6_universe, lease->options,
- req[i]->code) != NULL)
- lease->score += SCORE_OPTION;
- }
- }
-
- for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
- lease->score += SCORE_BINDING;
-
- for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
- lease->score += SCORE_ADDRESS;
- }
- }
-
- return lease->score;
-}
-
-/*
- * start_init6() kicks off the process, transmitting a packet and
- * scheduling a retransmission event.
- */
-void
-start_init6(struct client_state *client)
-{
- struct timeval tv;
-
- log_debug("PRC: Soliciting for leases (INIT).");
- client->state = S_INIT;
-
- /* Initialize timers, RFC3315 section 17.1.2. */
- client->IRT = SOL_TIMEOUT * 100;
- client->MRT = SOL_MAX_RT * 100;
- client->MRC = 0;
- /* Default is 0 (no max) but -1 changes this. */
- if (!onetry)
- client->MRD = 0;
- else
- client->MRD = client->config->timeout;
-
- dhc6_retrans_init(client);
-
- /*
- * RFC3315 section 17.1.2 goes out of its way:
- * Also, the first RT MUST be selected to be strictly greater than IRT
- * by choosing RAND to be strictly greater than 0.
- */
- /* if RAND < 0 then RAND = -RAND */
- if (client->RT <= client->IRT)
- client->RT = client->IRT + (client->IRT - client->RT);
- /* if RAND == 0 then RAND = 1 */
- if (client->RT <= client->IRT)
- client->RT = client->IRT + 1;
-
- client->v6_handler = init_handler;
-
- /*
- * RFC3315 section 17.1.2 says we MUST start the first packet
- * between 0 and SOL_MAX_DELAY seconds. The good news is
- * SOL_MAX_DELAY is 1.
- */
- tv.tv_sec = cur_tv.tv_sec;
- tv.tv_usec = cur_tv.tv_usec;
- tv.tv_usec += (random() % (SOL_MAX_DELAY * 100)) * 10000;
- if (tv.tv_usec >= 1000000) {
- tv.tv_sec += 1;
- tv.tv_usec -= 1000000;
- }
- add_timeout(&tv, do_init6, client, NULL, NULL);
-
- if (nowait)
- detach();
-}
-
-/*
- * start_info_request6() kicks off the process, transmitting an info
- * request packet and scheduling a retransmission event.
- */
-void
-start_info_request6(struct client_state *client)
-{
- struct timeval tv;
-
- log_debug("PRC: Requesting information (INIT).");
- client->state = S_INIT;
-
- /* Initialize timers, RFC3315 section 18.1.5. */
- client->IRT = INF_TIMEOUT * 100;
- client->MRT = INF_MAX_RT * 100;
- client->MRC = 0;
- /* Default is 0 (no max) but -1 changes this. */
- if (!onetry)
- client->MRD = 0;
- else
- client->MRD = client->config->timeout;
-
- dhc6_retrans_init(client);
-
- client->v6_handler = info_request_handler;
-
- /*
- * RFC3315 section 18.1.5 says we MUST start the first packet
- * between 0 and INF_MAX_DELAY seconds. The good news is
- * INF_MAX_DELAY is 1.
- */
- tv.tv_sec = cur_tv.tv_sec;
- tv.tv_usec = cur_tv.tv_usec;
- tv.tv_usec += (random() % (INF_MAX_DELAY * 100)) * 10000;
- if (tv.tv_usec >= 1000000) {
- tv.tv_sec += 1;
- tv.tv_usec -= 1000000;
- }
- add_timeout(&tv, do_info_request6, client, NULL, NULL);
-
- if (nowait)
- detach();
-}
-
-/*
- * start_confirm6() kicks off an "init-reboot" version of the process, at
- * startup to find out if old bindings are 'fair' and at runtime whenever
- * a link cycles state we'll eventually want to do this.
- */
-void
-start_confirm6(struct client_state *client)
-{
- struct timeval tv;
-
- /* If there is no active lease, there is nothing to check. */
- if ((client->active_lease == NULL) ||
- !active_prefix(client) ||
- client->active_lease->released ||
- !unexpired_address_in_lease(client->active_lease)) {
- dhc6_lease_destroy(&client->active_lease, MDL);
- start_init6(client);
- return;
- }
-
- log_debug("PRC: Confirming active lease (INIT-REBOOT).");
- client->state = S_REBOOTING;
-
- /* Initialize timers, RFC3315 section 17.1.3. */
- client->IRT = CNF_TIMEOUT * 100;
- client->MRT = CNF_MAX_RT * 100;
- client->MRC = 0;
- client->MRD = CNF_MAX_RD;
-
- dhc6_retrans_init(client);
-
- client->v6_handler = reply_handler;
-
- /*
- * RFC3315 section 18.1.2 says we MUST start the first packet
- * between 0 and CNF_MAX_DELAY seconds. The good news is
- * CNF_MAX_DELAY is 1.
- */
- tv.tv_sec = cur_tv.tv_sec;
- tv.tv_usec = cur_tv.tv_usec;
- tv.tv_usec += (random() % (CNF_MAX_DELAY * 100)) * 10000;
- if (tv.tv_usec >= 1000000) {
- tv.tv_sec += 1;
- tv.tv_usec -= 1000000;
- }
-
- /* We do a rebind instead of a confirm if the user
- * is requesting PDs or previously requesed PDs or
- * increased the number of NAs or TAs they want
- * Confirms don't tell us if PDs are still on-link and
- * we won't add new IAs on a confirm.
- */
-
- if ((wanted_ia_pd != 0) ||
- (dhc6_count_ia(client->active_lease, D6O_IA_PD) != 0) ||
- (dhc6_count_ia(client->active_lease, D6O_IA_NA) < wanted_ia_na) ||
- (dhc6_count_ia(client->active_lease, D6O_IA_TA) < wanted_ia_ta)) {
- client->state = S_REBINDING;
- client->refresh_type = DHCPV6_REBIND;
- add_timeout(&tv, do_refresh6, client, NULL, NULL);
- } else
- add_timeout(&tv, do_confirm6, client, NULL, NULL);
-}
-
-/*
- * check_timing6() check on the timing for sending a v6 message
- * and then do the basic initialization for a v6 message.
- */
-#define CHK_TIM_SUCCESS 0
-#define CHK_TIM_MRC_EXCEEDED 1
-#define CHK_TIM_MRD_EXCEEDED 2
-#define CHK_TIM_ALLOC_FAILURE 3
-
-int
-check_timing6 (struct client_state *client, u_int8_t msg_type,
- char *msg_str, struct dhc6_lease *lease,
- struct data_string *ds)
-{
- struct timeval elapsed;
-
- /*
- * Start_time starts at the first transmission.
- */
- if (client->txcount == 0) {
- client->start_time.tv_sec = cur_tv.tv_sec;
- client->start_time.tv_usec = cur_tv.tv_usec;
- } else if ((client->MRC != 0) && (client->txcount > client->MRC)) {
- log_info("Max retransmission count exceeded.");
- return(CHK_TIM_MRC_EXCEEDED);
- }
-
- /* elapsed = cur - start */
- elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
- elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
- if (elapsed.tv_usec < 0) {
- elapsed.tv_sec -= 1;
- elapsed.tv_usec += 1000000;
- }
-
- /* Check if finished (-1 argument). */
- if ((client->MRD != 0) && (elapsed.tv_sec >= client->MRD)) {
- log_info("Max retransmission duration exceeded.");
- return(CHK_TIM_MRD_EXCEEDED);
- }
-
- memset(ds, 0, sizeof(*ds));
- if (!buffer_allocate(&(ds->buffer), 4, MDL)) {
- log_error("Unable to allocate memory for %s.", msg_str);
- return(CHK_TIM_ALLOC_FAILURE);
- }
- ds->data = ds->buffer->data;
- ds->len = 4;
-
- ds->buffer->data[0] = msg_type;
- memcpy(ds->buffer->data + 1, client->dhcpv6_transaction_id, 3);
-
- /* Form an elapsed option. */
- /* Maximum value is 65535 1/100s coded as 0xffff. */
- if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
- ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
- client->elapsed = 0xffff;
- } else {
- client->elapsed = elapsed.tv_sec * 100;
- client->elapsed += elapsed.tv_usec / 10000;
- }
-
- if (client->elapsed == 0)
- log_debug("XMT: Forming %s, 0 ms elapsed.", msg_str);
- else
- log_debug("XMT: Forming %s, %u0 ms elapsed.", msg_str,
- (unsigned)client->elapsed);
-
- client->elapsed = htons(client->elapsed);
-
- make_client6_options(client, &client->sent_options, lease, msg_type);
-
- return(CHK_TIM_SUCCESS);
-}
-
-/*!
- *
- * \brief Create an iaid from information from the client.
- *
- * \param client = the state of the entire client
- * \param ia = the ia to fill in
- * \param idx = index of the ia in case we are doing multiples
- * \param len = length of the base IA (4 for TA, 12 for NA & PD)
- *
- * \return ISC_R_SUCCESS - all is well continue, any other return indicates
- * an error and the packet should be tossed
- */
-
-static isc_result_t
-dhc6_create_iaid(struct client_state *client,
- struct data_string *ia,
- int idx,
- unsigned len)
-{
- int start_idx, copy_len;
-
- memset(ia, 0, sizeof(*ia));
- if (!buffer_allocate(&ia->buffer, len, MDL)) {
- return (ISC_R_NOMEMORY);
- }
- ia->data = ia->buffer->data;
- ia->len = len;
-
- /*
- * A simple IAID is the last 4 bytes
- * of the hardware address.
- */
- if (client->interface->hw_address.hlen > 4) {
- start_idx = client->interface->hw_address.hlen - 4;
- copy_len = 4;
- } else {
- start_idx = 0;
- copy_len = client->interface->hw_address.hlen;
- }
- memcpy(ia->buffer->data,
- client->interface->hw_address.hbuf + start_idx,
- copy_len);
- if (idx)
- ia->buffer->data[3] += idx;
-
- return (ISC_R_SUCCESS);
-}
-
-/*!
- *
- * \brief Add bare IA_NAs, IA_TAs or IA_PDs to the packet we are building.
- *
- * Attempt to add the number of bare IAs indicated by wanted to
- * the packet. As we have already added a number of IAs based
- * on what is in the current lease after we create an IAID we check
- * it against the current lease and skip any that are already in use.
- *
- * \param client = the state of the entire client
- * \param packet = the packet we are building and where we
- * shall append the IA_NA, IA_TA or IA_PDs we create
- * \param wanted = the number of IA_NA, IA_TA or IA_PDs we want to create
- * \param ia_type = the type of the IAs we want to create: NA, TA or PD.
- *
- * \return ISC_R_SUCCESS - all is well continue, any other return indicates
- * an error and the packet should be tossed
- */
-static isc_result_t
-dhc6_bare_ia_xx(struct client_state *client,
- struct data_string *packet,
- int wanted,
- u_int16_t ia_type)
-{
- struct dhc6_ia *old_ia;
- struct data_string ia;
- u_int32_t t1, t2;
- int i, len;
- isc_result_t rval;
- char *type_string;
- struct option *type_option;
-
- /* figure out what type of option we are working with */
- switch (ia_type) {
- case D6O_IA_NA:
- type_string = "IA_NA";
- type_option = ia_na_option;
- len = IA_NA_OFFSET;
- break;
- case D6O_IA_TA:
- type_string = "IA_TA";
- type_option = ia_ta_option;
- len = IA_TA_OFFSET;
- break;
- case D6O_IA_PD:
- type_string = "IA_PD";
- type_option = ia_pd_option;
- len = IA_PD_OFFSET;
- if (prefix_len_hint > 0) {
- len += IASUBOPT_PD_LEN;
- }
- break;
-
- default:
- return (ISC_R_FAILURE);
- }
-
- for (i = 0; wanted != 0; i++) {
- rval = dhc6_create_iaid(client, &ia, i, len);
- if (rval != ISC_R_SUCCESS) {
- log_error("Unable to allocate memory for %s.",
- type_string);
- return (rval);
- }
-
- /* If we are already using this IAID, skip it and try again */
- if ((client->active_lease != NULL) &&
- ((old_ia = find_ia(client->active_lease->bindings,
- ia_type,
- (char *)ia.buffer->data)) != NULL)) {
- data_string_forget(&ia, MDL);
- continue;
- }
-
- /* We have a good IAID, log it */
- log_debug("XMT: X-- %s %s",
- type_string, print_hex_1(4, ia.buffer->data, 55));
-
- /* If we are requesting an NA or a PD we also want to add
- * the renew and rebind times we are requesting.
- */
- if (ia_type != D6O_IA_TA) {
- t1 = client->config->requested_lease / 2;
- t2 = t1 + (t1 / 2);
- putULong(ia.buffer->data + 4, t1);
- putULong(ia.buffer->data + 8, t2);
-
- log_debug("XMT: | X-- Request renew in +%u",
- (unsigned)t1);
- log_debug("XMT: | X-- Request rebind in +%u",
- (unsigned)t2);
- }
-
- if (ia_type == D6O_IA_PD && prefix_len_hint > 0) {
- unsigned char *ptr = ia.buffer->data + IA_NA_OFFSET;
- putUShort(ptr, D6O_IAPREFIX);
- ptr += 2;
- putUShort(ptr, IASUBOPT_PD_LEN);
- ptr += 2;
- putUChar(ptr + IASUBOPT_PD_PREFLEN_OFFSET,
- prefix_len_hint);
- log_debug("XMT: | | X-- Request prefix ::/%u.",
- prefix_len_hint);
- }
-
- /* and append it to the packet */
- append_option(packet, &dhcpv6_universe, type_option, &ia);
- data_string_forget(&ia, MDL);
-
- /* decrement the number of IAs we want */
- wanted--;
- }
-
- return (ISC_R_SUCCESS);
-}
-
-/*
- * do_init6() marshals and transmits a solicit.
- */
-void
-do_init6(void *input)
-{
- struct client_state *client;
- struct dhc6_ia *old_ia;
- struct dhc6_addr *old_addr;
- struct data_string ds;
- struct data_string ia;
- struct data_string addr;
- struct timeval tv;
- u_int32_t t1, t2;
- int i, send_ret;
-
- client = input;
-
- /*
- * In RFC3315 section 17.1.2, the retransmission timer is
- * used as the selecting timer.
- */
- if (client->advertised_leases != NULL) {
- start_selecting6(client);
- return;
- }
-
- switch(check_timing6(client, DHCPV6_SOLICIT, "Solicit", NULL, &ds)) {
- case CHK_TIM_MRC_EXCEEDED:
- case CHK_TIM_ALLOC_FAILURE:
- return;
- case CHK_TIM_MRD_EXCEEDED:
- client->state = S_STOPPED;
- if (client->active_lease != NULL) {
- dhc6_lease_destroy(&client->active_lease, MDL);
- client->active_lease = NULL;
- }
- /* Stop if and only if this is the last client. */
- if (stopping_finished())
- finish(2);
- return;
- }
-
- /*
- * Fetch any configured 'sent' options (includes DUID) in wire format.
- */
- dhcpv6_universe.encapsulate(&ds, NULL, NULL, client,
- NULL, client->sent_options, &global_scope,
- &dhcpv6_universe);
-
- /* Use a specific handler with rapid-commit. */
- if (lookup_option(&dhcpv6_universe, client->sent_options,
- D6O_RAPID_COMMIT) != NULL) {
- client->v6_handler = rapid_commit_handler;
- }
-
- /* Append IA_NA. */
- for (i = 0; i < wanted_ia_na; i++) {
- /*
- * XXX: maybe the IA_NA('s) should be put into the sent_options
- * cache. They'd have to be pulled down as they also contain
- * different option caches in the same universe...
- */
- if (dhc6_create_iaid(client, &ia, i, 12) != ISC_R_SUCCESS) {
- log_error("Unable to allocate memory for IA_NA.");
- data_string_forget(&ds, MDL);
- return;
- }
-
- t1 = client->config->requested_lease / 2;
- t2 = t1 + (t1 / 2);
- putULong(ia.buffer->data + 4, t1);
- putULong(ia.buffer->data + 8, t2);
-
- log_debug("XMT: X-- IA_NA %s",
- print_hex_1(4, ia.buffer->data, 55));
- log_debug("XMT: | X-- Request renew in +%u", (unsigned)t1);
- log_debug("XMT: | X-- Request rebind in +%u", (unsigned)t2);
-
- if ((client->active_lease != NULL) &&
- ((old_ia = find_ia(client->active_lease->bindings,
- D6O_IA_NA,
- (char *)ia.buffer->data)) != NULL)) {
- /*
- * For each address in the old IA_NA,
- * request a binding.
- */
- memset(&addr, 0, sizeof(addr));
- for (old_addr = old_ia->addrs ; old_addr != NULL ;
- old_addr = old_addr->next) {
- if (old_addr->address.len != 16) {
- log_error("Invalid IPv6 address "
- "length %d. "
- "Ignoring. (%s:%d)",
- old_addr->address.len,
- MDL);
- continue;
- }
-
- if (!buffer_allocate(&addr.buffer, 24, MDL)) {
- log_error("Unable to allocate memory "
- "for IAADDR.");
- data_string_forget(&ia, MDL);
- data_string_forget(&ds, MDL);
- return;
- }
- addr.data = addr.buffer->data;
- addr.len = 24;
-
- memcpy(addr.buffer->data,
- old_addr->address.iabuf,
- 16);
-
- t1 = client->config->requested_lease;
- t2 = t1 + (t1 / 2);
- putULong(addr.buffer->data + 16, t1);
- putULong(addr.buffer->data + 20, t2);
-
- log_debug("XMT: | X-- Request address %s.",
- piaddr(old_addr->address));
- log_debug("XMT: | | X-- Request "
- "preferred in +%u",
- (unsigned)t1);
- log_debug("XMT: | | X-- Request valid "
- "in +%u",
- (unsigned)t2);
-
- append_option(&ia, &dhcpv6_universe,
- iaaddr_option,
- &addr);
-
- data_string_forget(&addr, MDL);
- }
- }
-
- append_option(&ds, &dhcpv6_universe, ia_na_option, &ia);
- data_string_forget(&ia, MDL);
- }
-
- /* Append IA_TA. */
- for (i = 0; i < wanted_ia_ta; i++) {
- /*
- * XXX: maybe the IA_TA('s) should be put into the sent_options
- * cache. They'd have to be pulled down as they also contain
- * different option caches in the same universe...
- */
- if (dhc6_create_iaid(client, &ia, i, 4) != ISC_R_SUCCESS) {
- log_error("Unable to allocate memory for IA_TA.");
- data_string_forget(&ds, MDL);
- return;
- }
-
- log_debug("XMT: X-- IA_TA %s",
- print_hex_1(4, ia.buffer->data, 55));
-
- if ((client->active_lease != NULL) &&
- ((old_ia = find_ia(client->active_lease->bindings,
- D6O_IA_TA,
- (char *)ia.buffer->data)) != NULL)) {
- /*
- * For each address in the old IA_TA,
- * request a binding.
- */
- memset(&addr, 0, sizeof(addr));
- for (old_addr = old_ia->addrs ; old_addr != NULL ;
- old_addr = old_addr->next) {
- if (old_addr->address.len != 16) {
- log_error("Invalid IPv6 address "
- "length %d. "
- "Ignoring. (%s:%d)",
- old_addr->address.len,
- MDL);
- continue;
- }
-
- if (!buffer_allocate(&addr.buffer, 24, MDL)) {
- log_error("Unable to allocate memory "
- "for IAADDR.");
- data_string_forget(&ia, MDL);
- data_string_forget(&ds, MDL);
- return;
- }
- addr.data = addr.buffer->data;
- addr.len = 24;
-
- memcpy(addr.buffer->data,
- old_addr->address.iabuf,
- 16);
-
- t1 = client->config->requested_lease;
- t2 = t1 + (t1 / 2);
- putULong(addr.buffer->data + 16, t1);
- putULong(addr.buffer->data + 20, t2);
-
- log_debug("XMT: | X-- Request address %s.",
- piaddr(old_addr->address));
- log_debug("XMT: | | X-- Request "
- "preferred in +%u",
- (unsigned)t1);
- log_debug("XMT: | | X-- Request valid "
- "in +%u",
- (unsigned)t2);
-
- append_option(&ia, &dhcpv6_universe,
- iaaddr_option,
- &addr);
-
- data_string_forget(&addr, MDL);
- }
- }
-
- append_option(&ds, &dhcpv6_universe, ia_ta_option, &ia);
- data_string_forget(&ia, MDL);
- }
-
- /* Append IA_PD. */
- for (i = 0; i < wanted_ia_pd; i++) {
- /*
- * XXX: maybe the IA_PD('s) should be put into the sent_options
- * cache. They'd have to be pulled down as they also contain
- * different option caches in the same universe...
- */
- memset(&ia, 0, sizeof(ia));
- if (dhc6_create_iaid(client, &ia, i, 12) != ISC_R_SUCCESS) {
- log_error("Unable to allocate memory for IA_PD.");
- data_string_forget(&ds, MDL);
- return;
- }
-
- t1 = client->config->requested_lease / 2;
- t2 = t1 + (t1 / 2);
- putULong(ia.buffer->data + 4, t1);
- putULong(ia.buffer->data + 8, t2);
-
- log_debug("XMT: X-- IA_PD %s",
- print_hex_1(4, ia.buffer->data, 55));
- log_debug("XMT: | X-- Request renew in +%u", (unsigned)t1);
- log_debug("XMT: | X-- Request rebind in +%u", (unsigned)t2);
-
- if ((client->active_lease != NULL) &&
- ((old_ia = find_ia(client->active_lease->bindings,
- D6O_IA_PD,
- (char *)ia.buffer->data)) != NULL)) {
- /*
- * For each prefix in the old IA_PD,
- * request a binding.
- */
- memset(&addr, 0, sizeof(addr));
- for (old_addr = old_ia->addrs ; old_addr != NULL ;
- old_addr = old_addr->next) {
- if (old_addr->address.len != 16) {
- log_error("Invalid IPv6 prefix, "
- "Ignoring. (%s:%d)",
- MDL);
- continue;
- }
-
- if (!buffer_allocate(&addr.buffer, 25, MDL)) {
- log_error("Unable to allocate memory "
- "for IAPREFIX.");
- data_string_forget(&ia, MDL);
- data_string_forget(&ds, MDL);
- return;
- }
- addr.data = addr.buffer->data;
- addr.len = 25;
-
- t1 = client->config->requested_lease;
- t2 = t1 + (t1 / 2);
- putULong(addr.buffer->data, t1);
- putULong(addr.buffer->data + 4, t2);
-
- putUChar(addr.buffer->data + 8,
- old_addr->plen);
- memcpy(addr.buffer->data + 9,
- old_addr->address.iabuf,
- 16);
-
- log_debug("XMT: | X-- Request prefix %s/%u.",
- piaddr(old_addr->address),
- (unsigned) old_addr->plen);
- log_debug("XMT: | | X-- Request "
- "preferred in +%u",
- (unsigned)t1);
- log_debug("XMT: | | X-- Request valid "
- "in +%u",
- (unsigned)t2);
-
- append_option(&ia, &dhcpv6_universe,
- iaprefix_option,
- &addr);
-
- data_string_forget(&addr, MDL);
- }
- } else if (prefix_len_hint > 0) {
- memset(&addr, 0, sizeof(addr));
- if (!buffer_allocate(&addr.buffer, 25, MDL)) {
- log_error("Unable to allocate memory "
- "for IAPREFIX.");
- data_string_forget(&ia, MDL);
- data_string_forget(&ds, MDL);
- return;
- }
-
- addr.data = addr.buffer->data;
- addr.len = 25;
-
- putUChar(addr.buffer->data + 8, prefix_len_hint);
- log_debug("XMT: | | X-- Request prefix ::/%u.",
- prefix_len_hint);
- append_option(&ia, &dhcpv6_universe, iaprefix_option,
- &addr);
- data_string_forget(&addr, MDL);
- }
-
- append_option(&ds, &dhcpv6_universe, ia_pd_option, &ia);
- data_string_forget(&ia, MDL);
- }
-
- /* Transmit and wait. */
-
- log_info("XMT: Solicit on %s, interval %ld0ms.",
- client->name ? client->name : client->interface->name,
- (long int)client->RT);
-
- send_ret = send_packet6(client->interface,
- ds.data, ds.len, &DHCPv6DestAddr);
- if (send_ret != ds.len) {
- log_error("dhc6: send_packet6() sent %d of %d bytes",
- send_ret, ds.len);
- }
-
- data_string_forget(&ds, MDL);
-
- /* Wait RT */
- tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
- tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
- if (tv.tv_usec >= 1000000) {
- tv.tv_sec += 1;
- tv.tv_usec -= 1000000;
- }
- add_timeout(&tv, do_init6, client, NULL, NULL);
-
- dhc6_retrans_advance(client);
-}
-
-/* do_info_request6() marshals and transmits an information-request. */
-void
-do_info_request6(void *input)
-{
- struct client_state *client;
- struct data_string ds;
- struct timeval tv;
- int send_ret;
-
- client = input;
-
- switch(check_timing6(client, DHCPV6_INFORMATION_REQUEST,
- "Info-Request", NULL, &ds)) {
- case CHK_TIM_MRC_EXCEEDED:
- case CHK_TIM_ALLOC_FAILURE:
- return;
- case CHK_TIM_MRD_EXCEEDED:
- finish(2);
- case CHK_TIM_SUCCESS:
- break;
- }
-
- /* Fetch any configured 'sent' options (includes DUID) in wire format.
- */
- dhcpv6_universe.encapsulate(&ds, NULL, NULL, client,
- NULL, client->sent_options, &global_scope,
- &dhcpv6_universe);
-
- /* Transmit and wait. */
-
- log_info("XMT: Info-Request on %s, interval %ld0ms.",
- client->name ? client->name : client->interface->name,
- (long int)client->RT);
-
- send_ret = send_packet6(client->interface,
- ds.data, ds.len, &DHCPv6DestAddr);
- if (send_ret != ds.len) {
- log_error("dhc6: send_packet6() sent %d of %d bytes",
- send_ret, ds.len);
- }
-
- data_string_forget(&ds, MDL);
-
- /* Wait RT */
- tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
- tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
- if (tv.tv_usec >= 1000000) {
- tv.tv_sec += 1;
- tv.tv_usec -= 1000000;
- }
- add_timeout(&tv, do_info_request6, client, NULL, NULL);
-
- dhc6_retrans_advance(client);
-}
-
-/* do_confirm6() creates a Confirm packet and transmits it. This function
- * is called on every timeout to (re)transmit.
- */
-void
-do_confirm6(void *input)
-{
- struct client_state *client;
- struct data_string ds;
- int send_ret, added;
- struct timeval tv;
-
- client = input;
-
- if (client->active_lease == NULL)
- log_fatal("Impossible condition at %s:%d.", MDL);
-
- /* In section 17.1.3, it is said:
- *
- * If the client receives no responses before the message
- * transmission process terminates, as described in section 14,
- * the client SHOULD continue to use any IP addresses, using the
- * last known lifetimes for those addresses, and SHOULD continue
- * to use any other previously obtained configuration parameters.
- *
- * So if confirm times out, we go active.
- *
- * XXX: Should we reduce all IA's t1 to 0, so that we renew and
- * stick there until we get a reply?
- */
-
- switch(check_timing6(client, DHCPV6_CONFIRM, "Confirm",
- client->active_lease, &ds)) {
- case CHK_TIM_MRC_EXCEEDED:
- case CHK_TIM_MRD_EXCEEDED:
- start_bound(client);
- return;
- case CHK_TIM_ALLOC_FAILURE:
- return;
- case CHK_TIM_SUCCESS:
- break;
- }
-
- /* Fetch any configured 'sent' options (includes DUID') in wire format.
- */
- dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
- client->sent_options, &global_scope,
- &dhcpv6_universe);
-
- /* Append IA's. */
- if (wanted_ia_na &&
- dhc6_add_ia_na(client, &ds, client->active_lease,
- DHCPV6_CONFIRM, 0, &added) != ISC_R_SUCCESS) {
- data_string_forget(&ds, MDL);
- return;
- }
- if (wanted_ia_ta &&
- dhc6_add_ia_ta(client, &ds, client->active_lease,
- DHCPV6_CONFIRM, 0, &added) != ISC_R_SUCCESS) {
- data_string_forget(&ds, MDL);
- return;
- }
-
- /* Transmit and wait. */
-
- log_info("XMT: Confirm on %s, interval %ld0ms.",
- client->name ? client->name : client->interface->name,
- (long int)client->RT);
-
- send_ret = send_packet6(client->interface, ds.data, ds.len,
- &DHCPv6DestAddr);
- if (send_ret != ds.len) {
- log_error("dhc6: sendpacket6() sent %d of %d bytes",
- send_ret, ds.len);
- }
-
- data_string_forget(&ds, MDL);
-
- /* Wait RT */
- tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
- tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
- if (tv.tv_usec >= 1000000) {
- tv.tv_sec += 1;
- tv.tv_usec -= 1000000;
- }
- add_timeout(&tv, do_confirm6, client, NULL, NULL);
-
- dhc6_retrans_advance(client);
-}
-
-/*
- * Release addresses.
- */
-void
-start_release6(struct client_state *client)
-{
- /* Cancel any pending transmissions */
- cancel_timeout(do_confirm6, client);
- cancel_timeout(do_select6, client);
- cancel_timeout(do_refresh6, client);
- cancel_timeout(do_release6, client);
- cancel_timeout(do_decline6, client);
- client->state = S_STOPPED;
-
- /*
- * It is written: "The client MUST NOT use any of the addresses it
- * is releasing as the source address in the Release message or in
- * any subsequently transmitted message." So unconfigure now.
- */
- unconfigure6(client, "RELEASE6");
-
- /* Note this in the lease file. */
- if (client->active_lease == NULL)
- return;
- client->active_lease->released = ISC_TRUE;
- write_client6_lease(client, client->active_lease, 0, 1);
-
- /* Set timers per RFC3315 section 18.1.6. */
- client->IRT = REL_TIMEOUT * 100;
- client->MRT = 0;
- client->MRC = REL_MAX_RC;
- client->MRD = 0;
-
- dhc6_retrans_init(client);
- client->v6_handler = reply_handler;
-
- do_release6(client);
-}
-/*
- * do_release6() creates a Release packet and transmits it.
- */
-static void
-do_release6(void *input)
-{
- struct client_state *client;
- struct data_string ds;
- int send_ret, added;
- struct timeval tv;
-
- client = input;
-
- if ((client->active_lease == NULL) || !active_prefix(client))
- return;
-
- switch(check_timing6(client, DHCPV6_RELEASE, "Release",
- client->active_lease, &ds)) {
- case CHK_TIM_MRC_EXCEEDED:
- case CHK_TIM_ALLOC_FAILURE:
- case CHK_TIM_MRD_EXCEEDED:
- goto release_done;
- case CHK_TIM_SUCCESS:
- break;
- }
-
- /*
- * Don't use unicast as we don't know if we still have an
- * available address with enough scope.
- */
-
- dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
- client->sent_options, &global_scope,
- &dhcpv6_universe);
-
- /* Append IA's (but don't release temporary addresses). */
- if (wanted_ia_na &&
- dhc6_add_ia_na(client, &ds, client->active_lease,
- DHCPV6_RELEASE, 0, &added) != ISC_R_SUCCESS) {
- data_string_forget(&ds, MDL);
- goto release_done;
- }
- if (wanted_ia_pd &&
- dhc6_add_ia_pd(client, &ds, client->active_lease,
- DHCPV6_RELEASE, 0, &added) != ISC_R_SUCCESS) {
- data_string_forget(&ds, MDL);
- goto release_done;
- }
-
- /* Transmit and wait. */
- log_info("XMT: Release on %s, interval %ld0ms.",
- client->name ? client->name : client->interface->name,
- (long int)client->RT);
-
- send_ret = send_packet6(client->interface, ds.data, ds.len,
- &DHCPv6DestAddr);
- if (send_ret != ds.len) {
- log_error("dhc6: sendpacket6() sent %d of %d bytes",
- send_ret, ds.len);
- }
-
- data_string_forget(&ds, MDL);
-
- /* Wait RT */
- tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
- tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
- if (tv.tv_usec >= 1000000) {
- tv.tv_sec += 1;
- tv.tv_usec -= 1000000;
- }
- add_timeout(&tv, do_release6, client, NULL, NULL);
- dhc6_retrans_advance(client);
- return;
-
- release_done:
- dhc6_lease_destroy(&client->active_lease, MDL);
- client->active_lease = NULL;
- if (stopping_finished())
- finish(0);
-}
-
-/* status_log() just puts a status code into displayable form and logs it
- * to info level.
- */
-static void
-status_log(int code, const char *scope, const char *additional, int len)
-{
- const char *msg = NULL;
-
- switch(code) {
- case STATUS_Success:
- msg = "Success";
- break;
-
- case STATUS_UnspecFail:
- msg = "UnspecFail";
- break;
-
- case STATUS_NoAddrsAvail:
- msg = "NoAddrsAvail";
- break;
-
- case STATUS_NoBinding:
- msg = "NoBinding";
- break;
-
- case STATUS_NotOnLink:
- msg = "NotOnLink";
- break;
-
- case STATUS_UseMulticast:
- msg = "UseMulticast";
- break;
-
- case STATUS_NoPrefixAvail:
- msg = "NoPrefixAvail";
- break;
-
- default:
- msg = "UNKNOWN";
- break;
- }
-
- if (len > 0)
- log_info("%s status code %s: %s", scope, msg,
- print_hex_1(len,
- (const unsigned char *)additional, 50));
- else
- log_info("%s status code %s.", scope, msg);
-}
-
-/* Acquire a status code.
- */
-static isc_result_t
-dhc6_get_status_code(struct option_state *options, unsigned *code,
- struct data_string *msg)
-{
- struct option_cache *oc;
- struct data_string ds;
- isc_result_t rval = ISC_R_SUCCESS;
-
- if ((options == NULL) || (code == NULL))
- return DHCP_R_INVALIDARG;
-
- if ((msg != NULL) && (msg->len != 0))
- return DHCP_R_INVALIDARG;
-
- memset(&ds, 0, sizeof(ds));
-
- /* Assume success if there is no option. */
- *code = STATUS_Success;
-
- oc = lookup_option(&dhcpv6_universe, options, D6O_STATUS_CODE);
- if ((oc != NULL) &&
- evaluate_option_cache(&ds, NULL, NULL, NULL, options,
- NULL, &global_scope, oc, MDL)) {
- if (ds.len < 2) {
- log_error("Invalid status code length %d.", ds.len);
- rval = DHCP_R_FORMERR;
- } else
- *code = getUShort(ds.data);
-
- if ((msg != NULL) && (ds.len > 2)) {
- data_string_copy(msg, &ds, MDL);
- msg->data += 2;
- msg->len -= 2;
- }
-
- data_string_forget(&ds, MDL);
- return rval;
- }
-
- return ISC_R_NOTFOUND;
-}
-
-/* Look at status codes in an advertise, and reform the return value.
- */
-static isc_result_t
-dhc6_check_status(isc_result_t rval, struct option_state *options,
- const char *scope, unsigned *code)
-{
- struct data_string msg;
- isc_result_t status;
-
- if ((scope == NULL) || (code == NULL))
- return DHCP_R_INVALIDARG;
-
- /* If we don't find a code, we assume success. */
- *code = STATUS_Success;
-
- /* If there is no options cache, then there is no code. */
- if (options != NULL) {
- memset(&msg, 0, sizeof(msg));
- status = dhc6_get_status_code(options, code, &msg);
-
- if (status == ISC_R_SUCCESS) {
- status_log(*code, scope, (char *)msg.data, msg.len);
- data_string_forget(&msg, MDL);
-
- if (*code != STATUS_Success)
- rval = ISC_R_FAILURE;
-
- } else if (status != ISC_R_NOTFOUND)
- rval = status;
- }
-
- return rval;
-}
-
-/* Determine if this packet could provide usable information.
- * We check the status codes at the top level and at the IA level,
- * IAADDRS have already been checked in the leaseify step and any with
- * a bad format or status code that wasn't success have been dropped.
- *
- * leaseify has also already removed any IAs for which the top level status
- * code or the IA status code indicated no addresses or prefixes were
- * available.
- */
-static isc_result_t
-dhc6_check_advertise(struct dhc6_lease *lease)
-{
- struct dhc6_ia *ia;
- isc_result_t rval = ISC_R_SUCCESS;
- int have_addrs = ISC_FALSE;
- unsigned code;
- const char *scope;
- int got_na = 0, got_ta = 0, got_pd = 0;
-
- rval = dhc6_check_status(rval, lease->options, "message", &code);
-
- for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
- switch (ia->ia_type) {
- case D6O_IA_NA:
- scope = "IA_NA";
- got_na++;
- break;
- case D6O_IA_TA:
- scope = "IA_TA";
- got_ta++;
- break;
- case D6O_IA_PD:
- scope = "IA_PD";
- got_pd++;
- break;
- default:
- log_error("dhc6_check_advertise: no type.");
- return ISC_R_FAILURE;
- }
- /* Currently we toss packets if we have an error getting a
- * status code or if the status code isn't success, so
- * no need to loop through the addresses */
- rval = dhc6_check_status(rval, ia->options, scope, &code);
- if (rval != ISC_R_SUCCESS)
- continue;
-
- /* We don't need to check status on IAADDRS here as we already
- * did it as part of the leaseify step and tossed bad IAADDRS.
- * We are just checking to see if we have any addrs.
- * Should we check the addr itself for usability?
- */
- if (ia->addrs != NULL) {
- have_addrs = ISC_TRUE;
- }
- }
-
- /* If we didn't get some addrs or the user required us to
- * get all of the requested IAs and we didn't return an error
- */
- if ((have_addrs != ISC_TRUE) ||
- ((require_all_ias != 0) &&
- ((got_na < wanted_ia_na) ||
- (got_ta < wanted_ia_ta) ||
- (got_pd < wanted_ia_pd))))
- rval = ISC_R_ADDRNOTAVAIL;
-
- return rval;
-}
-
-/* status code <-> action matrix for the client in INIT state
- * (rapid/commit). Returns always false as no action is defined.
- */
-static isc_boolean_t
-dhc6_init_action(struct client_state *client, isc_result_t *rvalp,
- unsigned code)
-{
- if (rvalp == NULL)
- log_fatal("Impossible condition at %s:%d.", MDL);
-
- if (client == NULL) {
- *rvalp = DHCP_R_INVALIDARG;
- return ISC_FALSE;
- }
-
- if (*rvalp == ISC_R_SUCCESS)
- return ISC_FALSE;
-
- /* No possible action in any case... */
- return ISC_FALSE;
-}
-
-/* status code <-> action matrix for the client in SELECT state
- * (request/reply). Returns true if action was taken (and the
- * packet should be ignored), or false if no action was taken.
- */
-static isc_boolean_t
-dhc6_select_action(struct client_state *client, isc_result_t *rvalp,
- unsigned code)
-{
- struct dhc6_lease *lease;
- isc_result_t rval;
-
- if (rvalp == NULL)
- log_fatal("Impossible condition at %s:%d.", MDL);
-
- if (client == NULL) {
- *rvalp = DHCP_R_INVALIDARG;
- return ISC_FALSE;
- }
- rval = *rvalp;
-
- if (rval == ISC_R_SUCCESS)
- return ISC_FALSE;
-
- switch (code) {
- /* We may have an earlier failure status code (so no
- * success rval), and a success code now. This
- * doesn't upgrade the rval to success, but it does
- * mean we take no action here.
- */
- case STATUS_Success:
- /* Gimpy server, or possibly an attacker. */
- case STATUS_NoBinding:
- case STATUS_UseMulticast:
- /* Take no action. */
- return ISC_FALSE;
-
- /* If the server can't deal with us, either try the
- * next advertised server, or continue retrying if there
- * weren't any.
- */
- default:
- case STATUS_UnspecFail:
- if (client->advertised_leases != NULL) {
- dhc6_lease_destroy(&client->selected_lease, MDL);
- client->selected_lease = NULL;
-
- start_selecting6(client);
-
- break;
- } else /* Take no action - continue to retry. */
- return ISC_FALSE;
-
- /* If the server has no addresses, try other servers if
- * we got some, otherwise go to INIT to hope for more
- * servers.
- */
- case STATUS_NoAddrsAvail:
- case STATUS_NoPrefixAvail:
- if (client->state == S_REBOOTING)
- return ISC_FALSE;
-
- if (client->selected_lease == NULL)
- log_fatal("Impossible case at %s:%d.", MDL);
-
- dhc6_lease_destroy(&client->selected_lease, MDL);
- client->selected_lease = NULL;
-
- if (client->advertised_leases != NULL)
- start_selecting6(client);
- else
- start_init6(client);
-
- break;
-
- /* If we got a NotOnLink from a Confirm, then we're not
- * on link. Kill the old-active binding and start over.
- *
- * If we got a NotOnLink from our Request, something weird
- * happened. Start over from scratch anyway.
- */
- case STATUS_NotOnLink:
- if (client->state == S_REBOOTING) {
- if (client->active_lease == NULL)
- log_fatal("Impossible case at %s:%d.", MDL);
-
- dhc6_lease_destroy(&client->active_lease, MDL);
- } else {
- if (client->selected_lease == NULL)
- log_fatal("Impossible case at %s:%d.", MDL);
-
- dhc6_lease_destroy(&client->selected_lease, MDL);
- client->selected_lease = NULL;
-
- while (client->advertised_leases != NULL) {
- lease = client->advertised_leases;
- client->advertised_leases = lease->next;
-
- dhc6_lease_destroy(&lease, MDL);
- }
- }
-
- start_init6(client);
- break;
- }
-
- return ISC_TRUE;
-}
-
-static void
-dhc6_withdraw_lease(struct client_state *client)
-{
- struct dhc6_ia *ia;
- struct dhc6_addr *addr;
-
- if ((client == NULL) || (client->active_lease == NULL))
- return;
-
- for (ia = client->active_lease->bindings ; ia != NULL ;
- ia = ia->next) {
- for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
- addr->max_life = addr->preferred_life = 0;
- }
- }
-
- /* Perform expiry. */
- do_expire(client);
-}
-
-/* status code <-> action matrix for the client in BOUND state
- * (request/reply). Returns true if action was taken (and the
- * packet should be ignored), or false if no action was taken.
- */
-static isc_boolean_t
-dhc6_reply_action(struct client_state *client, isc_result_t *rvalp,
- unsigned code)
-{
- isc_result_t rval;
-
- if (rvalp == NULL)
- log_fatal("Impossible condition at %s:%d.", MDL);
-
- if (client == NULL) {
- *rvalp = DHCP_R_INVALIDARG;
- return ISC_FALSE;
- }
- rval = *rvalp;
-
- if (rval == ISC_R_SUCCESS)
- return ISC_FALSE;
-
- switch (code) {
- /* It's possible an earlier status code set rval to a failure
- * code, and we've encountered a later success.
- */
- case STATUS_Success:
- /* In "refreshes" (where we get replies), we probably
- * still have a valid lease. So "take no action" and
- * the upper levels will keep retrying until the lease
- * expires (or we rebind).
- */
- case STATUS_UnspecFail:
- /* For unknown codes...it's a soft (retryable) error. */
- default:
- return ISC_FALSE;
-
- /* The server is telling us to use a multicast address, so
- * we have to delete the unicast option from the active
- * lease, then allow retransmission to occur normally.
- * (XXX: It might be preferable in this case to retransmit
- * sooner than the current interval, but for now we don't.)
- */
- case STATUS_UseMulticast:
- if (client->active_lease != NULL)
- delete_option(&dhcp_universe,
- client->active_lease->options,
- D6O_UNICAST);
- return ISC_FALSE;
-
- /* "When the client receives a NotOnLink status from the
- * server in response to a Request, the client can either
- * re-issue the Request without specifying any addresses
- * or restart the DHCP server discovery process."
- *
- * This is strange. If competing server evaluation is
- * useful (and therefore in the protocol), then why would
- * a client's first reaction be to request from the same
- * server on a different link? Surely you'd want to
- * re-evaluate your server selection.
- *
- * Well, I guess that's the answer.
- */
- case STATUS_NotOnLink:
- /* In this case, we need to rescind all current active
- * bindings (just 'expire' them all normally, if early).
- * They're no use to us on the wrong link. Then head back
- * to init, redo server selection and get new addresses.
- */
- dhc6_withdraw_lease(client);
- break;
-
- /* "If the status code is NoAddrsAvail, the client has
- * received no usable addresses in the IA and may choose
- * to try obtaining addresses for the IA from another
- * server."
- */
- case STATUS_NoAddrsAvail:
- case STATUS_NoPrefixAvail:
- /* Head back to init, keeping any active bindings (!). */
- start_init6(client);
- break;
-
- /* - sends a Request message if the IA contained a Status
- * Code option with the NoBinding status (and does not
- * send any additional Renew/Rebind messages)
- */
- case STATUS_NoBinding:
- if (client->advertised_leases != NULL)
- log_fatal("Impossible condition at %s:%d.", MDL);
-
- client->advertised_leases =
- dhc6_dup_lease(client->active_lease, MDL);
- start_selecting6(client);
- break;
- }
-
- return ISC_TRUE;
-}
-
-/* status code <-> action matrix for the client in STOPPED state
- * (release/decline). Returns true if action was taken (and the
- * packet should be ignored), or false if no action was taken.
- * NoBinding is translated into Success.
- */
-static isc_boolean_t
-dhc6_stop_action(struct client_state *client, isc_result_t *rvalp,
- unsigned code)
-{
- isc_result_t rval;
-
- if (rvalp == NULL)
- log_fatal("Impossible condition at %s:%d.", MDL);
-
- if (client == NULL) {
- *rvalp = DHCP_R_INVALIDARG;
- return ISC_FALSE;
- }
- rval = *rvalp;
-
- if (rval == ISC_R_SUCCESS)
- return ISC_FALSE;
-
- switch (code) {
- /* It's possible an earlier status code set rval to a failure
- * code, and we've encountered a later success.
- */
- case STATUS_Success:
- /* For unknown codes...it's a soft (retryable) error. */
- case STATUS_UnspecFail:
- default:
- return ISC_FALSE;
-
- /* NoBinding is not an error */
- case STATUS_NoBinding:
- if (rval == ISC_R_FAILURE)
- *rvalp = ISC_R_SUCCESS;
- return ISC_FALSE;
-
- /* Should not happen */
- case STATUS_NoAddrsAvail:
- case STATUS_NoPrefixAvail:
- break;
-
- /* Give up on it */
- case STATUS_NotOnLink:
- break;
-
- /* The server is telling us to use a multicast address, so
- * we have to delete the unicast option from the active
- * lease, then allow retransmission to occur normally.
- * (XXX: It might be preferable in this case to retransmit
- * sooner than the current interval, but for now we don't.)
- */
- case STATUS_UseMulticast:
- if (client->active_lease != NULL)
- delete_option(&dhcp_universe,
- client->active_lease->options,
- D6O_UNICAST);
- return ISC_FALSE;
- }
-
- return ISC_TRUE;
-}
-
-static isc_boolean_t
-dhc6_decline_action(struct client_state *client, isc_result_t *rvalp,
- unsigned code)
-{
- isc_result_t rval;
-
- if (rvalp == NULL)
- log_fatal("Impossible condition at %s:%d.", MDL);
-
- if (client == NULL) {
- *rvalp = DHCP_R_INVALIDARG;
- return ISC_FALSE;
- }
- rval = *rvalp;
-
- if (rval == ISC_R_SUCCESS) {
- return ISC_FALSE;
- }
-
- switch (code) {
- case STATUS_UseMulticast:
- /* The server is telling us to use a multicast address, so
- * we have to delete the unicast option from the active
- * lease, then allow retransmission to occur normally.
- * (XXX: It might be preferable in this case to retransmit
- * sooner than the current interval, but for now we don't.)
- */
- if (client->active_lease != NULL)
- delete_option(&dhcp_universe,
- client->active_lease->options,
- D6O_UNICAST);
- return ISC_FALSE;
- default:
- /* Anything else is basically meaningless */
- break;
- }
-
- return ISC_TRUE;
-}
-
-
-/* Look at a new and old lease, and make sure the new information is not
- * losing us any state.
- */
-static isc_result_t
-dhc6_check_reply(struct client_state *client, struct dhc6_lease *new)
-{
- isc_boolean_t (*action)(struct client_state *,
- isc_result_t *, unsigned);
- struct dhc6_ia *ia;
- isc_result_t rval = ISC_R_SUCCESS;
- unsigned code;
- const char *scope;
- int nscore, sscore;
- int have_addrs = ISC_FALSE;
- int got_na = 0, got_ta = 0, got_pd = 0;
-
- if ((client == NULL) || (new == NULL))
- return DHCP_R_INVALIDARG;
-
- switch (client->state) {
- case S_INIT:
- action = dhc6_init_action;
- break;
-
- case S_SELECTING:
- case S_REBOOTING:
- action = dhc6_select_action;
- break;
-
- case S_RENEWING:
- case S_REBINDING:
- action = dhc6_reply_action;
- break;
-
- case S_STOPPED:
- action = dhc6_stop_action;
- break;
-
- case S_DECLINING:
- action = dhc6_decline_action;
- break;
-
- default:
- log_fatal("Impossible condition at %s:%d.", MDL);
- return ISC_R_CANCELED;
- }
-
- /* If there is a code to extract, and if there is some
- * action to take based on that code, then take the action
- * and do not continue.
- */
- rval = dhc6_check_status(rval, new->options, "message", &code);
- if (action(client, &rval, code))
- return ISC_R_CANCELED;
-
- for (ia = new->bindings ; ia != NULL ; ia = ia->next) {
- switch (ia->ia_type) {
- case D6O_IA_NA:
- scope = "IA_NA";
- got_na++;
- break;
- case D6O_IA_TA:
- scope = "IA_TA";
- got_ta++;
- break;
- case D6O_IA_PD:
- scope = "IA_PD";
- got_pd++;
- break;
- default:
- log_error("dhc6_check_reply: no type.");
- return DHCP_R_INVALIDARG;
- }
- rval = dhc6_check_status(rval, ia->options, scope, &code);
-
- if (action(client, &rval, code))
- return ISC_R_CANCELED;
-
- if (ia->addrs != NULL) {
- have_addrs = ISC_TRUE;
- }
- }
-
- /* A Confirm->Reply is unsuitable for comparison to the old lease. */
- if (client->state == S_REBOOTING)
- return rval;
-
- /* We expect the lease to have at least one address and if
- * required all of the requested IAs if not flag it as
- * NoAddrs and call the action routine to try again.
- *
- * Currently we don't completely handle TAs in all cases
- * so we don't check them for requires. I've left the
- * check in and commented it as I eventually do want
- * us to check for TAs as well. SAR
- */
- if ((have_addrs != ISC_TRUE) ||
- ((require_all_ias != 0) &&
- ((got_na < wanted_ia_na) ||
- /*(got_ta < wanted_ia_ta) ||*/
- (got_pd < wanted_ia_pd)))) {
- rval = ISC_R_FAILURE;
- if (action(client, &rval, STATUS_NoAddrsAvail) == ISC_TRUE) {
- return ISC_R_CANCELED;
- }
- }
-
- /* No old lease in rapid-commit. */
- if (client->state == S_INIT)
- return rval;
-
- switch (client->state) {
- case S_SELECTING:
- /* Compare the new lease with the selected lease to make
- * sure there is no risky business.
- */
- nscore = dhc6_score_lease(client, new);
- sscore = dhc6_score_lease(client, client->selected_lease);
- if ((client->advertised_leases != NULL) &&
- (nscore < (sscore / 2))) {
- /* XXX: An attacker might reply this way to make
- * XXX: sure we latch onto their configuration.
- * XXX: We might want to ignore the packet and
- * XXX: schedule re-selection at the next timeout?
- */
- log_error("PRC: BAIT AND SWITCH detected. Score of "
- "supplied lease (%d) is substantially "
- "smaller than the advertised score (%d). "
- "Trying other servers.",
- nscore, sscore);
-
- dhc6_lease_destroy(&client->selected_lease, MDL);
- client->selected_lease = NULL;
-
- start_selecting6(client);
-
- return ISC_R_CANCELED;
- }
- break;
-
- case S_RENEWING:
- case S_REBINDING:
- /* This leaves one RFC3315 status check unimplemented:
- *
- * - sends a Renew/Rebind if the IA is not in the Reply
- * message
- *
- * We rely on the scheduling system to note that the IA has
- * not left Renewal/Rebinding/whatever since it still carries
- * old times from the last successful binding. So this is
- * implemented actually, just not explicitly.
- */
- break;
-
- case S_STOPPED:
- case S_DECLINING:
- /* Nothing critical to do at this stage. */
- break;
-
- default:
- log_fatal("REALLY impossible condition at %s:%d.", MDL);
- return ISC_R_CANCELED;
- }
-
- return rval;
-}
-
-/* While in init state, we only collect advertisements. If there happens
- * to be an advertisement with a preference option of 255, that's an
- * automatic exit. Otherwise, we collect advertisements until our timeout
- * expires (client->RT).
- */
-void
-init_handler(struct packet *packet, struct client_state *client)
-{
- struct dhc6_lease *lease;
-
- /* In INIT state, we send solicits, we only expect to get
- * advertises (rapid commit has its own handler).
- */
- if (packet->dhcpv6_msg_type != DHCPV6_ADVERTISE)
- return;
-
- /* RFC3315 section 15.3 validation (same as 15.10 since we
- * always include a client id).
- */
- if (!valid_reply(packet, client)) {
- log_error("Invalid Advertise - rejecting.");
- return;
- }
-
- lease = dhc6_leaseify(packet, client);
-
- /* Out of memory or corrupt packet condition...hopefully a temporary
- * problem. Returning now makes us try to retransmit later.
- */
- if (lease == NULL)
- return;
-
- if (dhc6_check_advertise(lease) != ISC_R_SUCCESS) {
- log_debug("PRC: Lease failed to satisfy.");
- dhc6_lease_destroy(&lease, MDL);
- return;
- }
-
- int lease_score = dhc6_score_lease(client, lease);
-#ifdef ENFORCE_DHCPV6_CLIENT_REQUIRE
- if (lease_score == 0) {
- log_debug("RCV:Advertised lease scored 0, toss it.");
- dhc6_lease_destroy(&lease, MDL);
- return;
- }
-#endif
-
- insert_lease(&client->advertised_leases, lease);
-
- /* According to RFC3315 section 17.1.2, the client MUST wait for
- * the first RT before selecting a lease. But on the 400th RT,
- * we dont' want to wait the full timeout if we finally get an
- * advertise. We could probably wait a second, but ohwell,
- * RFC3315 doesn't say so.
- *
- * If the lease is highest possible preference, 255, RFC3315 claims
- * we should continue immediately even on the first RT. We probably
- * should not if the advertise contains less than one IA and address.
- */
- if ((client->txcount > 1) ||
- ((lease->pref == 255) && (lease_score > SCORE_MIN))) {
- log_debug("RCV: Advertisement immediately selected.");
- cancel_timeout(do_init6, client);
- start_selecting6(client);
- } else
- log_debug("RCV: Advertisement recorded.");
-}
-
-/* info_request_handler() accepts a Reply to an Info-request.
- */
-void
-info_request_handler(struct packet *packet, struct client_state *client)
-{
- isc_result_t check_status;
- unsigned code;
-
- if (packet->dhcpv6_msg_type != DHCPV6_REPLY)
- return;
-
- /* RFC3315 section 15.10 validation (same as 15.3 since we
- * always include a client id).
- */
- if (!valid_reply(packet, client)) {
- log_error("Invalid Reply - rejecting.");
- return;
- }
-
- check_status = dhc6_check_status(ISC_R_SUCCESS, packet->options,
- "message", &code);
-
- if (check_status != ISC_R_SUCCESS) {
- /* If no action was taken, but there is an error, then
- * we wait for a retransmission.
- */
- if (check_status != ISC_R_CANCELED)
- return;
- }
-
- /* We're done retransmitting at this point. */
- cancel_timeout(do_info_request6, client);
-
- /* Action was taken, so now that we've torn down our scheduled
- * retransmissions, return.
- */
- if (check_status == ISC_R_CANCELED)
- return;
-
- /* Cleanup if a previous attempt to go bound failed. */
- if (client->old_lease != NULL) {
- dhc6_lease_destroy(&client->old_lease, MDL);
- client->old_lease = NULL;
- }
-
- /* Cache options in the active_lease. */
- if (client->active_lease != NULL)
- client->old_lease = client->active_lease;
- client->active_lease = dmalloc(sizeof(struct dhc6_lease), MDL);
- if (client->active_lease == NULL)
- log_fatal("Out of memory for v6 lease structure.");
- option_state_reference(&client->active_lease->options,
- packet->options, MDL);
-
- execute_statements_in_scope(NULL, (struct packet *)packet, NULL, client,
- client->active_lease->options,
- client->active_lease->options,
- &global_scope, client->config->on_receipt,
- NULL, NULL);
-
- start_informed(client);
-}
-
-/* Specific version of init_handler() for rapid-commit.
- */
-void
-rapid_commit_handler(struct packet *packet, struct client_state *client)
-{
- struct dhc6_lease *lease;
- isc_result_t check_status;
-
- /* On ADVERTISE just fall back to the init_handler().
- */
- if (packet->dhcpv6_msg_type == DHCPV6_ADVERTISE) {
- init_handler(packet, client);
- return;
- } else if (packet->dhcpv6_msg_type != DHCPV6_REPLY)
- return;
-
- /* RFC3315 section 15.10 validation (same as 15.3 since we
- * always include a client id).
- */
- if (!valid_reply(packet, client)) {
- log_error("Invalid Reply - rejecting.");
- return;
- }
-
- /* A rapid-commit option MUST be here. */
- if (lookup_option(&dhcpv6_universe, packet->options,
- D6O_RAPID_COMMIT) == 0) {
- log_error("Reply without Rapid-Commit - rejecting.");
- return;
- }
-
- lease = dhc6_leaseify(packet, client);
-
- /* Out of memory or corrupt packet condition...hopefully a temporary
- * problem. Returning now makes us try to retransmit later.
- */
- if (lease == NULL)
- return;
-
- check_status = dhc6_check_reply(client, lease);
- if (check_status != ISC_R_SUCCESS) {
- dhc6_lease_destroy(&lease, MDL);
- return;
- }
-
- /* Jump to the selecting state. */
- cancel_timeout(do_init6, client);
- client->state = S_SELECTING;
-
- /* Merge any bindings in the active lease (if there is one) into
- * the new active lease.
- */
- dhc6_merge_lease(client->active_lease, lease);
-
- /* Cleanup if a previous attempt to go bound failed. */
- if (client->old_lease != NULL) {
- dhc6_lease_destroy(&client->old_lease, MDL);
- client->old_lease = NULL;
- }
-
- /* Make this lease active and BIND to it. */
- if (client->active_lease != NULL)
- client->old_lease = client->active_lease;
- client->active_lease = lease;
-
- /* We're done with the ADVERTISEd leases, if any. */
- while(client->advertised_leases != NULL) {
- lease = client->advertised_leases;
- client->advertised_leases = lease->next;
-
- dhc6_lease_destroy(&lease, MDL);
- }
-
- start_bound(client);
-}
-
-/* Find the 'best' lease in the cache of advertised leases (usually). From
- * RFC3315 Section 17.1.3:
- *
- * Upon receipt of one or more valid Advertise messages, the client
- * selects one or more Advertise messages based upon the following
- * criteria.
- *
- * - Those Advertise messages with the highest server preference value
- * are preferred over all other Advertise messages.
- *
- * - Within a group of Advertise messages with the same server
- * preference value, a client MAY select those servers whose
- * Advertise messages advertise information of interest to the
- * client. For example, the client may choose a server that returned
- * an advertisement with configuration options of interest to the
- * client.
- *
- * - The client MAY choose a less-preferred server if that server has a
- * better set of advertised parameters, such as the available
- * addresses advertised in IAs.
- *
- * Note that the first and third contradict each other. The third should
- * probably be taken to mean that the client should prefer answers that
- * offer bindings, even if that violates the preference rule.
- *
- * The above also isn't deterministic where there are ties. So the final
- * tiebreaker we add, if all other values are equal, is to compare the
- * server identifiers and to select the numerically lower one.
- */
-static struct dhc6_lease *
-dhc6_best_lease(struct client_state *client, struct dhc6_lease **head)
-{
- struct dhc6_lease **rpos, *rval, **candp, *cand;
- int cscore, rscore;
-
- if (head == NULL || *head == NULL)
- return NULL;
-
- rpos = head;
- rval = *rpos;
- rscore = dhc6_score_lease(client, rval);
- candp = &rval->next;
- cand = *candp;
-
- log_debug("PRC: Considering best lease.");
- log_debug("PRC: X-- Initial candidate %s (s: %d, p: %u).",
- print_hex_1(rval->server_id.len,
- rval->server_id.data, 48),
- rscore, (unsigned)rval->pref);
-
- for (; cand != NULL ; candp = &cand->next, cand = *candp) {
- cscore = dhc6_score_lease(client, cand);
-
- log_debug("PRC: X-- Candidate %s (s: %d, p: %u).",
- print_hex_1(cand->server_id.len,
- cand->server_id.data, 48),
- cscore, (unsigned)cand->pref);
-
- /* Above you'll find quoted RFC3315 Section 17.1.3.
- *
- * The third clause tells us to give up on leases that
- * have no bindings even if their preference is better.
- * So where our 'selected' lease's score is less than
- * SCORE_MIN (1 ia + 1 addr), choose any candidate >= SCORE_MIN.
- *
- * The first clause tells us to make preference the primary
- * deciding factor. So if it's lower, reject, if it's
- * higher, select.
- *
- * The second clause tells us where the preference is
- * equal, we should use 'our judgement' of what we like
- * to see in an advertisement primarily.
- *
- * But there can still be a tie. To make this deterministic,
- * we compare the server identifiers and select the binary
- * lowest.
- *
- * Since server id's are unique in this list, there is
- * no further tie to break.
- */
- if ((rscore < SCORE_MIN) && (cscore >= SCORE_MIN)) {
- log_debug("PRC: | X-- Selected, has bindings.");
- } else if (cand->pref < rval->pref) {
- log_debug("PRC: | X-- Rejected, lower preference.");
- continue;
- } else if (cand->pref > rval->pref) {
- log_debug("PRC: | X-- Selected, higher preference.");
- } else if (cscore > rscore) {
- log_debug("PRC: | X-- Selected, equal preference, "
- "higher score.");
- } else if (cscore < rscore) {
- log_debug("PRC: | X-- Rejected, equal preference, "
- "lower score.");
- continue;
- } else if ((cand->server_id.len < rval->server_id.len) ||
- ((cand->server_id.len == rval->server_id.len) &&
- (memcmp(cand->server_id.data,
- rval->server_id.data,
- cand->server_id.len) < 0))) {
- log_debug("PRC: | X-- Selected, equal preference, "
- "equal score, binary lesser server ID.");
- } else {
- log_debug("PRC: | X-- Rejected, equal preference, "
- "equal score, binary greater server ID.");
- continue;
- }
-
- rpos = candp;
- rval = cand;
- rscore = cscore;
- }
-
- /* Remove the selected lease from the chain. */
- *rpos = rval->next;
-
- return rval;
-}
-
-/* Select a lease out of the advertised leases and setup state to try and
- * acquire that lease.
- */
-void
-start_selecting6(struct client_state *client)
-{
- struct dhc6_lease *lease;
-
- if (client->advertised_leases == NULL) {
- log_error("Can not enter DHCPv6 SELECTING state with no "
- "leases to select from!");
- return;
- }
-
- log_debug("PRC: Selecting best advertised lease.");
- client->state = S_SELECTING;
-
- lease = dhc6_best_lease(client, &client->advertised_leases);
-
- if (lease == NULL)
- log_fatal("Impossible error at %s:%d.", MDL);
-
- client->selected_lease = lease;
-
- /* Set timers per RFC3315 section 18.1.1. */
- client->IRT = REQ_TIMEOUT * 100;
- client->MRT = REQ_MAX_RT * 100;
- client->MRC = REQ_MAX_RC;
- client->MRD = 0;
-
- dhc6_retrans_init(client);
-
- client->v6_handler = reply_handler;
-
- /* ("re")transmit the first packet. */
- do_select6(client);
-}
-
-/* Transmit a Request to select a lease offered in Advertisements. In
- * the event of failure, either move on to the next-best advertised lease,
- * or head back to INIT state if there are none.
- */
-void
-do_select6(void *input)
-{
- struct client_state *client;
- struct dhc6_lease *lease;
- struct data_string ds;
- struct timeval tv;
- int send_ret, added;
-
- client = input;
-
- /* 'lease' is fewer characters to type. */
- lease = client->selected_lease;
- if (lease == NULL || lease->bindings == NULL) {
- log_error("Illegal to attempt selection without selecting "
- "a lease.");
- return;
- }
-
- switch(check_timing6(client, DHCPV6_REQUEST, "Request", lease, &ds)) {
- case CHK_TIM_MRC_EXCEEDED:
- case CHK_TIM_MRD_EXCEEDED:
- log_debug("PRC: Lease %s failed.",
- print_hex_1(lease->server_id.len,
- lease->server_id.data, 56));
-
- /* Get rid of the lease that timed/counted out. */
- dhc6_lease_destroy(&lease, MDL);
- client->selected_lease = NULL;
-
- /* If there are more leases great. If not, get more. */
- if (client->advertised_leases != NULL)
- start_selecting6(client);
- else
- start_init6(client);
- return;
- case CHK_TIM_ALLOC_FAILURE:
- return;
- case CHK_TIM_SUCCESS:
- break;
- }
-
- /* Now make a packet that looks suspiciously like the one we
- * got from the server. But different.
- *
- * XXX: I guess IAID is supposed to be something the client
- * indicates and uses as a key to its internal state. It is
- * kind of odd to ask the server for IA's whose IAID the client
- * did not manufacture. We first need a formal dhclient.conf
- * construct for the iaid, then we can delve into this matter
- * more properly. In the time being, this will work.
- */
-
- /* Fetch any configured 'sent' options (includes DUID) in wire format.
- */
- dhcpv6_universe.encapsulate(&ds, NULL, NULL, client,
- NULL, client->sent_options, &global_scope,
- &dhcpv6_universe);
-
- /* Now append any IA's, and within them any IAADDR/IAPREFIXs.
- * For each type of IA (na, ta, pd) we start with the ones for
- * which we already have addresses (dhc6_add_ia_xx) and then
- * if we still want more we add aditional IAs (dhc6_bare_ia_xx)
- */
- if (wanted_ia_na &&
- ((dhc6_add_ia_na(client, &ds, lease, DHCPV6_REQUEST,
- wanted_ia_na, &added) != ISC_R_SUCCESS) ||
- (dhc6_bare_ia_xx(client, &ds, wanted_ia_na - added,
- D6O_IA_NA) != ISC_R_SUCCESS))) {
- data_string_forget(&ds, MDL);
- return;
- }
- if (wanted_ia_ta &&
- ((dhc6_add_ia_ta(client, &ds, lease, DHCPV6_REQUEST,
- wanted_ia_ta, &added) != ISC_R_SUCCESS) ||
- (dhc6_bare_ia_xx(client, &ds, wanted_ia_ta - added,
- D6O_IA_TA) != ISC_R_SUCCESS))) {
- data_string_forget(&ds, MDL);
- return;
- }
- if (wanted_ia_pd &&
- ((dhc6_add_ia_pd(client, &ds, lease, DHCPV6_REQUEST,
- wanted_ia_pd, &added) != ISC_R_SUCCESS) ||
- (dhc6_bare_ia_xx(client, &ds, wanted_ia_pd - added,
- D6O_IA_PD) != ISC_R_SUCCESS))) {
- data_string_forget(&ds, MDL);
- return;
- }
-
- log_info("XMT: Request on %s, interval %ld0ms.",
- client->name ? client->name : client->interface->name,
- (long int)client->RT);
-
- send_ret = send_packet6(client->interface,
- ds.data, ds.len, &DHCPv6DestAddr);
- if (send_ret != ds.len) {
- log_error("dhc6: send_packet6() sent %d of %d bytes",
- send_ret, ds.len);
- }
-
- data_string_forget(&ds, MDL);
-
- /* Wait RT */
- tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
- tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
- if (tv.tv_usec >= 1000000) {
- tv.tv_sec += 1;
- tv.tv_usec -= 1000000;
- }
- add_timeout(&tv, do_select6, client, NULL, NULL);
-
- dhc6_retrans_advance(client);
-}
-
-/*!
- *
- * \brief Count the number of IAs in the bindings
- *
- * \param lease the lease to count
- * \param ia_type the type of the IA we wish to count
- *
- * \return The number of IAs of the specified type we found
- */
-static int
-dhc6_count_ia(struct dhc6_lease *lease, u_int16_t ia_type)
-{
- struct dhc6_ia *ia;
- int i = 0;
-
- for (ia = lease->bindings; ia != NULL; ia = ia->next) {
- if (ia->ia_type == ia_type)
- /* bump the counter for the correct types */
- i++;
- }
-
- return (i);
-}
-
-/*!
- *
- * \brief Add IA_NA information from the lease to the packet
- * we are building.
- *
- * Walk through the lease and for each IA_NA in the lease
- * and for each address in the IA_NA append that information
- * onto the packet-so-far. If wanted is 0 include all IA_NAs
- * in the lease if wanted is non-zero include only that many
- * IA_NAs (this may occur if sommebody restarts a client with
- * arugments for a smaller number of NAs than before).
- *
- * \param client = the state of the entire client
- * \param packet = the packet we are building and where we
- * shall append the IA_NAs we create
- * \param lease = the current lease
- * \param message = the type of the packet
- * \param wanted = the number of IA_NAs to include in the packet
- * 0 means include all
- * \param added = the number of IA_NAs that were added to the packet
- *
- * \return ISC_R_SUCCESS - all is well continue, any other return
- * indicates an error (most likely memory issues)
- * and the packet should be tossed.
- */
-static isc_result_t
-dhc6_add_ia_na(struct client_state *client, struct data_string *packet,
- struct dhc6_lease *lease, u_int8_t message,
- int wanted, int *added)
-{
- struct data_string iads;
- struct data_string addrds;
- struct dhc6_addr *addr;
- struct dhc6_ia *ia;
- isc_result_t rval = ISC_R_SUCCESS;
- TIME t1, t2;
- int i;
-
- *added = 0;
- memset(&iads, 0, sizeof(iads));
- memset(&addrds, 0, sizeof(addrds));
- for (ia = lease->bindings, i = 0;
- ia != NULL && rval == ISC_R_SUCCESS && (wanted == 0 || i < wanted);
- ia = ia->next) {
- if (ia->ia_type != D6O_IA_NA)
- continue;
-
- /* Now that we know this is an NA bump the counter */
- i++;
-
- if (!buffer_allocate(&iads.buffer, 12, MDL)) {
- log_error("Unable to allocate memory for IA_NA.");
- rval = ISC_R_NOMEMORY;
- break;
- }
-
- /* Copy the IAID into the packet buffer. */
- memcpy(iads.buffer->data, ia->iaid, 4);
- iads.data = iads.buffer->data;
- iads.len = 12;
-
- switch (message) {
- case DHCPV6_REQUEST:
- case DHCPV6_RENEW:
- case DHCPV6_REBIND:
-
- t1 = client->config->requested_lease / 2;
- t2 = t1 + (t1 / 2);
-#if MAX_TIME > 0xffffffff
- if (t1 > 0xffffffff)
- t1 = 0xffffffff;
- if (t2 > 0xffffffff)
- t2 = 0xffffffff;
-#endif
- putULong(iads.buffer->data + 4, t1);
- putULong(iads.buffer->data + 8, t2);
-
- log_debug("XMT: X-- IA_NA %s",
- print_hex_1(4, iads.data, 59));
- log_debug("XMT: | X-- Requested renew +%u",
- (unsigned) t1);
- log_debug("XMT: | X-- Requested rebind +%u",
- (unsigned) t2);
- break;
-
- case DHCPV6_CONFIRM:
- case DHCPV6_RELEASE:
- case DHCPV6_DECLINE:
- /* Set t1 and t2 to zero; server will ignore them */
- memset(iads.buffer->data + 4, 0, 8);
- log_debug("XMT: X-- IA_NA %s",
- print_hex_1(4, iads.buffer->data, 55));
-
- break;
-
- default:
- log_fatal("Impossible condition at %s:%d.", MDL);
- }
-
- for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
- /*
- * Do not confirm expired addresses, do not request
- * expired addresses (but we keep them around for
- * solicit).
- */
- if (addr->flags & DHC6_ADDR_EXPIRED)
- continue;
-
- if (addr->address.len != 16) {
- log_error("Illegal IPv6 address length (%d), "
- "ignoring. (%s:%d)",
- addr->address.len, MDL);
- continue;
- }
-
- if (!buffer_allocate(&addrds.buffer, 24, MDL)) {
- log_error("Unable to allocate memory for "
- "IAADDR.");
- rval = ISC_R_NOMEMORY;
- break;
- }
-
- addrds.data = addrds.buffer->data;
- addrds.len = 24;
-
- /* Copy the address into the packet buffer. */
- memcpy(addrds.buffer->data, addr->address.iabuf, 16);
-
- /* Copy in additional information as appropriate */
- switch (message) {
- case DHCPV6_REQUEST:
- case DHCPV6_RENEW:
- case DHCPV6_REBIND:
- t1 = client->config->requested_lease;
- t2 = t1 + 300;
- putULong(addrds.buffer->data + 16, t1);
- putULong(addrds.buffer->data + 20, t2);
-
- log_debug("XMT: | | X-- IAADDR %s",
- piaddr(addr->address));
- log_debug("XMT: | | | X-- Preferred "
- "lifetime +%u", (unsigned)t1);
- log_debug("XMT: | | | X-- Max lifetime +%u",
- (unsigned)t2);
-
- break;
-
- case DHCPV6_CONFIRM:
- /*
- * Set preferred and max life to zero,
- * per 17.1.3.
- */
- memset(addrds.buffer->data + 16, 0, 8);
- log_debug("XMT: | X-- Confirm Address %s",
- piaddr(addr->address));
- break;
-
- case DHCPV6_RELEASE:
- /* Preferred and max life are irrelevant */
- memset(addrds.buffer->data + 16, 0, 8);
- log_debug("XMT: | X-- Release Address %s",
- piaddr(addr->address));
- break;
-
- case DHCPV6_DECLINE:
- /* Preferred and max life are irrelevant */
- memset(addrds.buffer->data + 16, 0, 8);
- log_debug("XMT: | X-- Decline Address %s",
- piaddr(addr->address));
- break;
-
- default:
- log_fatal("Impossible condition at %s:%d.",
- MDL);
- }
-
- append_option(&iads, &dhcpv6_universe, iaaddr_option,
- &addrds);
- data_string_forget(&addrds, MDL);
- }
-
- /*
- * It doesn't make sense to make a request without an
- * address.
- */
- if (ia->addrs == NULL) {
- log_debug("!!!: V IA_NA has no IAADDRs - removed.");
- rval = ISC_R_FAILURE;
- } else if (rval == ISC_R_SUCCESS) {
- log_debug("XMT: V IA_NA appended.");
- append_option(packet, &dhcpv6_universe, ia_na_option,
- &iads);
- }
-
- data_string_forget(&iads, MDL);
- }
-
- if (rval == ISC_R_SUCCESS)
- *added = i;
-
- return (rval);
-}
-
-/*!
- *
- * \brief Add IA_TA information from the lease to the packet
- * we are building.
- *
- * Walk through the lease and for each IA_TA in the lease
- * and for each address in the IA_TA append that information
- * onto the packet-so-far. If wanted is 0 include all IA_TAs
- * in the lease if wanted is non-zero include only that many
- * IA_TAs (this may occur if sommebody restarts a client with
- * arugments for a smaller number of TAs than before).
- *
- * \param client = the state of the entire client
- * \param packet = the packet we are building and where we
- * shall append the IA_TAs we create
- * \param lease = the current lease
- * \param message = the type of the packet
- * \param wanted = the number of IA_TAs to include in the packet
- * 0 means include all
- * \param added = the number of IA_TAs that were added to the packet
- *
- * \return ISC_R_SUCCESS - all is well continue, any other return
- * indicates an error (most likely memory issues)
- * and the packet should be tossed.
- */
-static isc_result_t
-dhc6_add_ia_ta(struct client_state *client, struct data_string *packet,
- struct dhc6_lease *lease, u_int8_t message,
- int wanted, int *added)
-{
- struct data_string iads;
- struct data_string addrds;
- struct dhc6_addr *addr;
- struct dhc6_ia *ia;
- isc_result_t rval = ISC_R_SUCCESS;
- TIME t1, t2;
- int i;
-
- *added = 0;
- memset(&iads, 0, sizeof(iads));
- memset(&addrds, 0, sizeof(addrds));
- for (ia = lease->bindings, i = 0;
- ia != NULL && rval == ISC_R_SUCCESS && (wanted == 0 || i < wanted);
- ia = ia->next) {
- if (ia->ia_type != D6O_IA_TA)
- continue;
-
- /* Now that we know this is an TA bump the counter */
- i++;
-
- if (!buffer_allocate(&iads.buffer, 4, MDL)) {
- log_error("Unable to allocate memory for IA_TA.");
- rval = ISC_R_NOMEMORY;
- break;
- }
-
- /* Copy the IAID into the packet buffer. */
- memcpy(iads.buffer->data, ia->iaid, 4);
- iads.data = iads.buffer->data;
- iads.len = 4;
-
- log_debug("XMT: X-- IA_TA %s",
- print_hex_1(4, iads.buffer->data, 55));
-
- for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
- /*
- * Do not confirm expired addresses, do not request
- * expired addresses (but we keep them around for
- * solicit).
- */
- if (addr->flags & DHC6_ADDR_EXPIRED)
- continue;
-
- if (addr->address.len != 16) {
- log_error("Illegal IPv6 address length (%d), "
- "ignoring. (%s:%d)",
- addr->address.len, MDL);
- continue;
- }
-
- if (!buffer_allocate(&addrds.buffer, 24, MDL)) {
- log_error("Unable to allocate memory for "
- "IAADDR.");
- rval = ISC_R_NOMEMORY;
- break;
- }
-
- addrds.data = addrds.buffer->data;
- addrds.len = 24;
-
- /* Copy the address into the packet buffer. */
- memcpy(addrds.buffer->data, addr->address.iabuf, 16);
-
- /* Copy in additional information as appropriate */
- switch (message) {
- case DHCPV6_REQUEST:
- case DHCPV6_RENEW:
- case DHCPV6_REBIND:
- t1 = client->config->requested_lease;
- t2 = t1 + 300;
- putULong(addrds.buffer->data + 16, t1);
- putULong(addrds.buffer->data + 20, t2);
-
- log_debug("XMT: | | X-- IAADDR %s",
- piaddr(addr->address));
- log_debug("XMT: | | | X-- Preferred "
- "lifetime +%u", (unsigned)t1);
- log_debug("XMT: | | | X-- Max lifetime +%u",
- (unsigned)t2);
-
- break;
-
- case DHCPV6_CONFIRM:
- /*
- * Set preferred and max life to zero,
- * per 17.1.3.
- */
- memset(addrds.buffer->data + 16, 0, 8);
- log_debug("XMT: | X-- Confirm Address %s",
- piaddr(addr->address));
- break;
-
- case DHCPV6_RELEASE:
- /* Preferred and max life are irrelevant */
- memset(addrds.buffer->data + 16, 0, 8);
- log_debug("XMT: | X-- Release Address %s",
- piaddr(addr->address));
- break;
-
- default:
- log_fatal("Impossible condition at %s:%d.",
- MDL);
- }
-
- append_option(&iads, &dhcpv6_universe, iaaddr_option,
- &addrds);
- data_string_forget(&addrds, MDL);
- }
-
- /*
- * It doesn't make sense to make a request without an
- * address.
- */
- if (ia->addrs == NULL) {
- log_debug("!!!: V IA_TA has no IAADDRs - removed.");
- rval = ISC_R_FAILURE;
- } else if (rval == ISC_R_SUCCESS) {
- log_debug("XMT: V IA_TA appended.");
- append_option(packet, &dhcpv6_universe, ia_ta_option,
- &iads);
- }
-
- data_string_forget(&iads, MDL);
- }
-
- if (rval == ISC_R_SUCCESS)
- *added = i;
-
- return (rval);
-}
-
-/*!
- *
- * \brief Add IA_PD information from the lease to the packet
- * we are building.
- *
- * Walk through the lease and for each IA_PD in the lease
- * and for each address in the IA_PD append that information
- * onto the packet-so-far. If wanted is 0 include all IA_PDs
- * in the lease if wanted is non-zero include only that many
- * IA_PDs (this may occur if sommebody restarts a client with
- * arugments for a smaller number of PDs than before).
- *
- * \param client = the state of the entire client
- * \param packet = the packet we are building and where we
- * shall append the IA_PDs we create
- * \param lease = the current lease
- * \param message = the type of the packet
- * \param wanted = the number of IA_PDs to include in the packet
- * 0 means include all
- * \param added = the number of IA_PDs that were added to the packet
- *
- * \return ISC_R_SUCCESS - all is well continue, any other return
- * indicates an error (most likely memory issues)
- * and the packet should be tossed.
- */
-static isc_result_t
-dhc6_add_ia_pd(struct client_state *client, struct data_string *packet,
- struct dhc6_lease *lease, u_int8_t message,
- int wanted, int *added)
-{
- struct data_string iads;
- struct data_string prefds;
- struct dhc6_addr *pref;
- struct dhc6_ia *ia;
- isc_result_t rval = ISC_R_SUCCESS;
- TIME t1, t2;
- int i;
-
- *added = 0;
- memset(&iads, 0, sizeof(iads));
- memset(&prefds, 0, sizeof(prefds));
- for (ia = lease->bindings, i = 0;
- ia != NULL && rval == ISC_R_SUCCESS && (wanted == 0 || i < wanted);
- ia = ia->next) {
- if (ia->ia_type != D6O_IA_PD)
- continue;
-
- /* Now that we know this is an PD bump the counter */
- i++;
-
- if (!buffer_allocate(&iads.buffer, 12, MDL)) {
- log_error("Unable to allocate memory for IA_PD.");
- rval = ISC_R_NOMEMORY;
- break;
- }
-
- /* Copy the IAID into the packet buffer. */
- memcpy(iads.buffer->data, ia->iaid, 4);
- iads.data = iads.buffer->data;
- iads.len = 12;
-
- switch (message) {
- case DHCPV6_REQUEST:
- case DHCPV6_RENEW:
- case DHCPV6_REBIND:
-
- t1 = client->config->requested_lease / 2;
- t2 = t1 + (t1 / 2);
-#if MAX_TIME > 0xffffffff
- if (t1 > 0xffffffff)
- t1 = 0xffffffff;
- if (t2 > 0xffffffff)
- t2 = 0xffffffff;
-#endif
- putULong(iads.buffer->data + 4, t1);
- putULong(iads.buffer->data + 8, t2);
-
- log_debug("XMT: X-- IA_PD %s",
- print_hex_1(4, iads.data, 59));
- log_debug("XMT: | X-- Requested renew +%u",
- (unsigned) t1);
- log_debug("XMT: | X-- Requested rebind +%u",
- (unsigned) t2);
- break;
-
- case DHCPV6_RELEASE:
- /* Set t1 and t2 to zero; server will ignore them */
- memset(iads.buffer->data + 4, 0, 8);
- log_debug("XMT: X-- IA_PD %s",
- print_hex_1(4, iads.buffer->data, 55));
-
- break;
-
- default:
- log_fatal("Impossible condition at %s:%d.", MDL);
- }
-
- for (pref = ia->addrs ; pref != NULL ; pref = pref->next) {
- /*
- * Do not confirm expired prefixes, do not request
- * expired prefixes (but we keep them around for
- * solicit).
- */
- if (pref->flags & DHC6_ADDR_EXPIRED)
- continue;
-
- if (pref->address.len != 16) {
- log_error("Illegal IPv6 prefix "
- "ignoring. (%s:%d)",
- MDL);
- continue;
- }
-
- if (pref->plen == 0) {
- log_info("Null IPv6 prefix, "
- "ignoring. (%s:%d)",
- MDL);
- }
-
- if (!buffer_allocate(&prefds.buffer, 25, MDL)) {
- log_error("Unable to allocate memory for "
- "IAPREFIX.");
- rval = ISC_R_NOMEMORY;
- break;
- }
-
- prefds.data = prefds.buffer->data;
- prefds.len = 25;
-
- /* Copy the prefix into the packet buffer. */
- putUChar(prefds.buffer->data + 8, pref->plen);
- memcpy(prefds.buffer->data + 9,
- pref->address.iabuf,
- 16);
-
- /* Copy in additional information as appropriate */
- switch (message) {
- case DHCPV6_REQUEST:
- case DHCPV6_RENEW:
- case DHCPV6_REBIND:
- t1 = client->config->requested_lease;
- t2 = t1 + 300;
- putULong(prefds.buffer->data, t1);
- putULong(prefds.buffer->data + 4, t2);
-
- log_debug("XMT: | | X-- IAPREFIX %s/%u",
- piaddr(pref->address),
- (unsigned) pref->plen);
- log_debug("XMT: | | | X-- Preferred "
- "lifetime +%u", (unsigned)t1);
- log_debug("XMT: | | | X-- Max lifetime +%u",
- (unsigned)t2);
-
- break;
-
- case DHCPV6_RELEASE:
- /* Preferred and max life are irrelevant */
- memset(prefds.buffer->data, 0, 8);
- log_debug("XMT: | X-- Release Prefix %s/%u",
- piaddr(pref->address),
- (unsigned) pref->plen);
- break;
-
- default:
- log_fatal("Impossible condition at %s:%d.",
- MDL);
- }
-
- append_option(&iads, &dhcpv6_universe,
- iaprefix_option, &prefds);
- data_string_forget(&prefds, MDL);
- }
-
- /*
- * It doesn't make sense to make a request without an
- * address.
- */
- if (ia->addrs == NULL) {
- log_debug("!!!: V IA_PD has no IAPREFIXs - removed.");
- rval = ISC_R_FAILURE;
- } else if (rval == ISC_R_SUCCESS) {
- log_debug("XMT: V IA_PD appended.");
- append_option(packet, &dhcpv6_universe,
- ia_pd_option, &iads);
- }
-
- data_string_forget(&iads, MDL);
- }
-
- if (rval == ISC_R_SUCCESS)
- *added = i;
-
- return (rval);
-}
-
-/* stopping_finished() checks if there is a remaining work to do.
- */
-static isc_boolean_t
-stopping_finished(void)
-{
- struct interface_info *ip;
- struct client_state *client;
-
- for (ip = interfaces; ip; ip = ip -> next) {
- for (client = ip -> client; client; client = client -> next) {
- if (client->state != S_STOPPED)
- return ISC_FALSE;
- if (client->active_lease != NULL)
- return ISC_FALSE;
- }
- }
- return ISC_TRUE;
-}
-
-/* reply_handler() accepts a Reply while we're attempting Select or Renew or
- * Rebind. Basically any Reply packet.
- */
-void
-reply_handler(struct packet *packet, struct client_state *client)
-{
- struct dhc6_lease *lease;
- isc_result_t check_status;
-
- if (packet->dhcpv6_msg_type != DHCPV6_REPLY)
- return;
-
- /* RFC3315 section 15.10 validation (same as 15.3 since we
- * always include a client id).
- */
- if (!valid_reply(packet, client)) {
- log_error("Invalid Reply - rejecting.");
- return;
- }
-
- lease = dhc6_leaseify(packet, client);
-
- /* Out of memory or corrupt packet condition...hopefully a temporary
- * problem. Returning now makes us try to retransmit later.
- */
- if (lease == NULL)
- return;
-
- check_status = dhc6_check_reply(client, lease);
- if (check_status != ISC_R_SUCCESS) {
- dhc6_lease_destroy(&lease, MDL);
-
- /* If no action was taken, but there is an error, then
- * we wait for a retransmission.
- */
- if (check_status != ISC_R_CANCELED)
- return;
- }
-
- /* We're done retransmitting at this point. */
- cancel_timeout(do_confirm6, client);
- cancel_timeout(do_select6, client);
- cancel_timeout(do_refresh6, client);
- cancel_timeout(do_release6, client);
- cancel_timeout(do_decline6, client);
-
- /* If this is in response to a Release, clean up and return. */
- if (client->state == S_STOPPED) {
- if (client->active_lease != NULL) {
- dhc6_lease_destroy(&client->active_lease, MDL);
- client->active_lease = NULL;
- /* We should never wait for nothing!? */
- if (stopping_finished()) {
- finish(0);
- }
- }
-
- return;
- }
-
- if (client->state == S_DECLINING) {
- /* Weed thru the lease and delete all declined addresses.
- * Toss the lease if there aren't any addresses left */
- int live_cnt = drop_declined_addrs(client->active_lease);
- if (live_cnt == 0) {
- dhc6_lease_destroy(&client->active_lease, MDL);
- client->active_lease = NULL;
- }
-
- /* Solicit with any live addresses we have so far, and
- * add additional empty NA iasubopts for those we had
- * to decline. */
- start_init6(client);
- return;
- }
-
- /* Action was taken, so now that we've torn down our scheduled
- * retransmissions, return.
- */
- if (check_status == ISC_R_CANCELED)
- return;
-
- if (client->selected_lease != NULL) {
- dhc6_lease_destroy(&client->selected_lease, MDL);
- client->selected_lease = NULL;
- }
-
- /* If this is in response to a confirm, we use the lease we've
- * already got, not the reply we were sent.
- */
- if (client->state == S_REBOOTING) {
- if (client->active_lease == NULL)
- log_fatal("Impossible condition at %s:%d.", MDL);
-
- dhc6_lease_destroy(&lease, MDL);
- start_bound(client);
- return;
- }
-
- /* Merge any bindings in the active lease (if there is one) into
- * the new active lease.
- */
- dhc6_merge_lease(client->active_lease, lease);
-
- /* Cleanup if a previous attempt to go bound failed. */
- if (client->old_lease != NULL) {
- dhc6_lease_destroy(&client->old_lease, MDL);
- client->old_lease = NULL;
- }
-
- /* Make this lease active and BIND to it. */
- if (client->active_lease != NULL)
- client->old_lease = client->active_lease;
- client->active_lease = lease;
-
- /* We're done with the ADVERTISEd leases, if any. */
- while(client->advertised_leases != NULL) {
- lease = client->advertised_leases;
- client->advertised_leases = lease->next;
-
- dhc6_lease_destroy(&lease, MDL);
- }
-
- start_bound(client);
-}
-
-/* DHCPv6 packets are a little sillier than they needed to be - the root
- * packet contains options, then IA's which contain options, then within
- * that IAADDR's which contain options.
- *
- * To sort this out at dhclient-script time (which fetches config parameters
- * in environment variables), start_bound() iterates over each IAADDR, and
- * calls this function to marshall an environment variable set that includes
- * the most-specific option values related to that IAADDR in particular.
- *
- * To achieve this, we load environment variables for the root options space,
- * then the IA, then the IAADDR. Any duplicate option names will be
- * over-written by the later versions.
- */
-static void
-dhc6_marshall_values(const char *prefix, struct client_state *client,
- struct dhc6_lease *lease, struct dhc6_ia *ia,
- struct dhc6_addr *addr)
-{
- /* Option cache contents, in descending order of
- * scope.
- */
- if ((lease != NULL) && (lease->options != NULL))
- script_write_params6(client, prefix, lease->options);
- if ((ia != NULL) && (ia->options != NULL))
- script_write_params6(client, prefix, ia->options);
- if ((addr != NULL) && (addr->options != NULL))
- script_write_params6(client, prefix, addr->options);
-
- /* addr fields. */
- if (addr != NULL) {
- if ((ia != NULL) && (ia->ia_type == D6O_IA_PD)) {
- client_envadd(client, prefix,
- "ip6_prefix", "%s/%u",
- piaddr(addr->address),
- (unsigned) addr->plen);
- } else {
- client_envadd(client, prefix, "ip6_prefixlen",
- "%d", address_prefix_len);
- client_envadd(client, prefix, "ip6_address",
- "%s", piaddr(addr->address));
- }
- if ((ia != NULL) && (ia->ia_type == D6O_IA_TA)) {
- client_envadd(client, prefix,
- "ip6_type", "temporary");
- }
- client_envadd(client, prefix, "life_starts", "%d",
- (int)(addr->starts));
- client_envadd(client, prefix, "preferred_life", "%u",
- addr->preferred_life);
- client_envadd(client, prefix, "max_life", "%u",
- addr->max_life);
- }
-
- /* ia fields. */
- if (ia != NULL) {
- client_envadd(client, prefix, "iaid", "%s",
- print_hex_1(4, ia->iaid, 12));
- client_envadd(client, prefix, "starts", "%d",
- (int)(ia->starts));
- client_envadd(client, prefix, "renew", "%u", ia->renew);
- client_envadd(client, prefix, "rebind", "%u", ia->rebind);
- }
-}
-
-/* Look at where the client's active lease is sitting. If it's looking to
- * time out on renew, rebind, depref, or expiration, do those things.
- */
-static void
-dhc6_check_times(struct client_state *client)
-{
- struct dhc6_lease *lease;
- struct dhc6_ia *ia;
- struct dhc6_addr *addr;
- TIME renew=MAX_TIME, rebind=MAX_TIME, depref=MAX_TIME,
- lo_expire=MAX_TIME, hi_expire=0, max_ia_starts = 0, tmp;
- int has_addrs = ISC_FALSE;
- int has_preferred_addrs = ISC_FALSE;
- struct timeval tv;
-
- lease = client->active_lease;
-
- /* Bit spammy. We should probably keep record of scheduled
- * events instead.
- */
- cancel_timeout(start_renew6, client);
- cancel_timeout(start_rebind6, client);
- cancel_timeout(do_depref, client);
- cancel_timeout(do_expire, client);
-
- for(ia = lease->bindings ; ia != NULL ; ia = ia->next) {
- TIME this_ia_lo_expire, this_ia_hi_expire, use_expire;
-
- this_ia_lo_expire = MAX_TIME;
- this_ia_hi_expire = 0;
-
- for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
- if(!(addr->flags & DHC6_ADDR_DEPREFFED)) {
- if (addr->preferred_life == 0xffffffff)
- tmp = MAX_TIME;
- else
- tmp = addr->starts +
- addr->preferred_life;
-
- if (tmp < depref)
- depref = tmp;
-
- if (!(addr->flags & DHC6_ADDR_EXPIRED)) {
- has_preferred_addrs = ISC_TRUE;
- }
- }
-
- if (!(addr->flags & DHC6_ADDR_EXPIRED)) {
- /* Find EPOCH-relative expiration. */
- if (addr->max_life == 0xffffffff)
- tmp = MAX_TIME;
- else
- tmp = addr->starts + addr->max_life;
-
- /* Make the times ia->starts relative. */
- tmp -= ia->starts;
-
- if (tmp > this_ia_hi_expire)
- this_ia_hi_expire = tmp;
- if (tmp < this_ia_lo_expire)
- this_ia_lo_expire = tmp;
-
- has_addrs = ISC_TRUE;
- }
- }
-
- /* These times are ia->starts relative. */
- if (this_ia_lo_expire <= (this_ia_hi_expire / 2))
- use_expire = this_ia_hi_expire;
- else
- use_expire = this_ia_lo_expire;
-
- /*
- * If the auto-selected expiration time is "infinite", or
- * zero, assert a reasonable default.
- */
- if ((use_expire == MAX_TIME) || (use_expire <= 1))
- use_expire = client->config->requested_lease / 2;
- else
- use_expire /= 2;
-
- /* Don't renew/rebind temporary addresses. */
- /* For NA and PD we find the most recent IA and the smallest
- * values for the renew and rebind then base the timer on
- * the sum of the them.
- * Normally all the IAs will have the same time as they
- * are requested and served as a group but in some cases the
- * client isn't asking for all of the IAs (for example
- * restarted with a different set of arguments) or the server
- * isn't updating the client on all of them (probably a
- * broken server).
- */
- if (ia->ia_type != D6O_IA_TA) {
- if (ia->starts > max_ia_starts)
- max_ia_starts = ia->starts;
-
- if (ia->renew == 0) {
- tmp = use_expire;
- } else if (ia->renew == 0xffffffff)
- tmp = MAX_TIME;
- else
- tmp = ia->renew;
-
- if (tmp < renew)
- renew = tmp;
-
- if (ia->rebind == 0) {
- /* Set rebind to 3/4 expiration interval. */
- tmp = use_expire + (use_expire / 2);
- } else if (ia->rebind == 0xffffffff)
- tmp = MAX_TIME;
- else
- tmp = ia->rebind;
-
- if (tmp < rebind)
- rebind = tmp;
- }
-
- /*
- * Return expiration ranges to EPOCH relative for event
- * scheduling (add_timeout()).
- */
- this_ia_hi_expire += ia->starts;
- this_ia_lo_expire += ia->starts;
-
- if (this_ia_hi_expire > hi_expire)
- hi_expire = this_ia_hi_expire;
- if (this_ia_lo_expire < lo_expire)
- lo_expire = this_ia_lo_expire;
- }
-
- /* If there are no addresses, give up, go to INIT.
- * Note that if an address is unexpired with a date in the past,
- * we're scheduling an expiration event to ocurr in the past. We
- * could probably optimize this to expire now (but then there's
- * recursion).
- *
- * In the future, we may decide that we're done here, or to
- * schedule a future request (using 4-pkt info-request model).
- */
- if (has_addrs == ISC_FALSE) {
- dhc6_lease_destroy(&client->active_lease, MDL);
- client->active_lease = NULL;
-
- /* Go back to the beginning. */
- start_init6(client);
- return;
- }
-
- /* Second part of calculating the renew and rebind times.
- * We have the start time and the desired periods for renew
- * and rebind, just add them to get the desired end time.
- */
- if (renew != MAX_TIME)
- renew += max_ia_starts;
- if (rebind != MAX_TIME)
- rebind += max_ia_starts;
-
- switch(client->state) {
- case S_BOUND:
- /* We'd like to hit renewing, but if rebinding has already
- * passed (time warp), head straight there.
- */
- if ((rebind > cur_time) && (renew < rebind)) {
- log_debug("PRC: Renewal event scheduled in %d seconds, "
- "to run for %u seconds.",
- (int)(renew - cur_time),
- (unsigned)(rebind - renew));
- client->next_MRD = rebind;
- tv.tv_sec = renew;
- tv.tv_usec = 0;
- add_timeout(&tv, start_renew6, client, NULL, NULL);
-
- break;
- }
- /* FALL THROUGH */
- case S_RENEWING:
- /* While actively renewing, MRD is bounded by the time
- * we stop renewing and start rebinding. This helps us
- * process the state change on time.
- */
- client->MRD = rebind - cur_time;
- if (rebind != MAX_TIME) {
- log_debug("PRC: Rebind event scheduled in %d seconds, "
- "to run for %d seconds.",
- (int)(rebind - cur_time),
- (int)(hi_expire - rebind));
- client->next_MRD = hi_expire;
- tv.tv_sec = rebind;
- tv.tv_usec = 0;
- add_timeout(&tv, start_rebind6, client, NULL, NULL);
- }
- break;
-
- case S_REBINDING:
- /* For now, we rebind up until the last lease expires. In
- * the future, we might want to start SOLICITing when we've
- * depreffed an address.
- */
- client->MRD = hi_expire - cur_time;
- break;
-
- default:
- if (has_preferred_addrs) {
- log_fatal("Impossible condition, state %d at %s:%d.",
- client->state, MDL);
- }
- }
-
- /* Separately, set a time at which we will depref and expire
- * leases. This might happen with multiple addresses while we
- * keep trying to refresh.
- */
- if (depref != MAX_TIME) {
- log_debug("PRC: Depreference scheduled in %d seconds.",
- (int)(depref - cur_time));
- tv.tv_sec = depref;
- tv.tv_usec = 0;
- add_timeout(&tv, do_depref, client, NULL, NULL);
- }
- if (lo_expire != MAX_TIME) {
- log_debug("PRC: Expiration scheduled in %d seconds.",
- (int)(lo_expire - cur_time));
- tv.tv_sec = lo_expire;
- tv.tv_usec = 0;
- add_timeout(&tv, do_expire, client, NULL, NULL);
- }
-}
-
-/* In a given IA chain, find the IA with the same type and 'iaid'. */
-static struct dhc6_ia *
-find_ia(struct dhc6_ia *head, u_int16_t type, const char *id)
-{
- struct dhc6_ia *ia;
-
- for (ia = head ; ia != NULL ; ia = ia->next) {
- if (ia->ia_type != type)
- continue;
- if (memcmp(ia->iaid, id, 4) == 0)
- return ia;
- }
-
- return NULL;
-}
-
-/* In a given address chain, find a matching address. */
-static struct dhc6_addr *
-find_addr(struct dhc6_addr *head, struct iaddr *address)
-{
- struct dhc6_addr *addr;
-
- for (addr = head ; addr != NULL ; addr = addr->next) {
- if ((addr->address.len == address->len) &&
- (memcmp(addr->address.iabuf, address->iabuf,
- address->len) == 0))
- return addr;
- }
-
- return NULL;
-}
-
-/* In a given prefix chain, find a matching prefix. */
-static struct dhc6_addr *
-find_pref(struct dhc6_addr *head, struct iaddr *prefix, u_int8_t plen)
-{
- struct dhc6_addr *pref;
-
- for (pref = head ; pref != NULL ; pref = pref->next) {
- if ((pref->address.len == prefix->len) &&
- (pref->plen == plen) &&
- (memcmp(pref->address.iabuf, prefix->iabuf,
- prefix->len) == 0))
- return pref;
- }
-
- return NULL;
-}
-
-/*
- *
- * \brief Merge the bindings from the source lease into the destination
- * lease structure, where they are missing.
- *
- * This is used to merge any extra information we have in the current
- * (older, src) lease into the lease we have just received. For example
- * the src lease might include a binding for an NA that is still usable
- * but that we didn't request or that the server is no longer serving.
- * We want to keep that information until we toss the binding (expire,
- * release) so we move it to the new lease.
- *
- * We have to copy the stateful objects rather than move them over,
- * because later code needs to be able to compare new versus old if
- * they contain any bindings.
- *
- * \param src The older lease to copy the objects from
- * \param dst The newer lease to copy the objects to
- */
-static void
-dhc6_merge_lease(struct dhc6_lease *src, struct dhc6_lease *dst)
-{
- struct dhc6_ia *sia, *dia, *tia, **eia;
- struct dhc6_addr *saddr, *daddr, *taddr;
- int changes = 0;
-
- if ((dst == NULL) || (src == NULL))
- return;
-
- for (sia = src->bindings ; sia != NULL ; sia = sia->next) {
- dia = find_ia(dst->bindings, sia->ia_type, (char *)sia->iaid);
-
- if (dia == NULL) {
- tia = dhc6_dup_ia(sia, MDL);
-
- if (tia == NULL)
- log_fatal("Out of memory merging lease - "
- "Unable to continue without losing "
- "state! (%s:%d)", MDL);
-
- /* Put any bindings that aren't in the new lease at the
- * end of the list. If the user or server reduces the
- * number of IAs the ones in use will be at the front
- * and will be used when building the next requests
- * We could be more efficient by finding the end
- * of the list once but we don't expect to do this
- * often.
- */
- for (eia = &dst->bindings;
- *eia != NULL;
- eia = &(*eia)->next) {
- ; /* no work just find the end */
- }
- *eia = tia;
- changes = 1;
- } else {
- for (saddr = sia->addrs ; saddr != NULL ;
- saddr = saddr->next) {
- if (sia->ia_type != D6O_IA_PD)
- daddr = find_addr(dia->addrs,
- &saddr->address);
- else
- daddr = find_pref(dia->addrs,
- &saddr->address,
- saddr->plen);
-
- if (daddr == NULL) {
- taddr = dhc6_dup_addr(saddr, MDL);
-
- if (taddr == NULL)
- log_fatal("Out of memory "
- "merging lease - "
- "Unable to continue "
- "without losing "
- "state! (%s:%d)",
- MDL);
-
- /* XXX: consider sorting? */
- taddr->next = dia->addrs;
- dia->addrs = taddr;
- changes = 1;
- }
- }
- }
- }
-
- /* If we made changes, reset the score to 0 so it is recalculated. */
- if (changes)
- dst->score = 0;
-}
-
-/* We've either finished selecting or succeeded in Renew or Rebinding our
- * lease. In all cases we got a Reply. Give dhclient-script a tickle
- * to inform it about the new values, and then lay in wait for the next
- * event.
- */
-static void
-start_bound(struct client_state *client)
-{
- struct dhc6_ia *ia, *oldia;
- struct dhc6_addr *addr, *oldaddr;
- struct dhc6_lease *lease, *old;
- const char *reason;
- int decline_cnt = 0;
-#if defined (NSUPDATE)
- TIME dns_update_offset = 1;
-#endif
-
- lease = client->active_lease;
- if (lease == NULL) {
- log_error("Cannot enter bound state unless an active lease "
- "is selected.");
- return;
- }
- lease->released = ISC_FALSE;
- old = client->old_lease;
-
- client->v6_handler = bound_handler;
-
- switch (client->state) {
- case S_SELECTING:
- case S_REBOOTING: /* Pretend we got bound. */
- reason = "BOUND6";
- break;
-
- case S_RENEWING:
- reason = "RENEW6";
- break;
-
- case S_REBINDING:
- reason = "REBIND6";
- break;
-
- default:
- log_fatal("Impossible condition at %s:%d.", MDL);
- /* Silence compiler warnings. */
- return;
- }
-
- log_debug("PRC: Bound to lease %s.",
- print_hex_1(client->active_lease->server_id.len,
- client->active_lease->server_id.data, 55));
- client->state = S_BOUND;
-
- write_client6_lease(client, lease, 0, 1);
-
- oldia = NULL;
- for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
- if (old != NULL)
- oldia = find_ia(old->bindings,
- ia->ia_type,
- (char *)ia->iaid);
- else
- oldia = NULL;
-
- for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
- /* Don't try to use the address if it's already expired */
- if (addr->flags & DHC6_ADDR_EXPIRED)
- continue;
-
- if (oldia != NULL) {
- if (ia->ia_type != D6O_IA_PD)
- oldaddr = find_addr(oldia->addrs,
- &addr->address);
- else
- oldaddr = find_pref(oldia->addrs,
- &addr->address,
- addr->plen);
- } else
- oldaddr = NULL;
-
-#if defined (NSUPDATE)
- if ((oldaddr == NULL) && (ia->ia_type == D6O_IA_NA))
- dhclient_schedule_updates(client,
- &addr->address,
- dns_update_offset++);
-#endif
-
- /* Shell out to setup the new binding. */
- script_init(client, reason, NULL);
-
- if (old != NULL)
- dhc6_marshall_values("old_", client, old,
- oldia, oldaddr);
- dhc6_marshall_values("new_", client, lease, ia, addr);
- script_write_requested6(client);
-
- /* When script returns 3, DAD failed */
- if (script_go(client) == 3) {
- if (ia->ia_type == D6O_IA_NA) {
- addr->flags |= DHC6_ADDR_DECLINED;
- log_debug ("Flag address declined:%s",
- piaddr(addr->address));
- decline_cnt++;
- }
- }
- }
-
- /* If the client script DAD failed any addresses we need
- * build and issue a DECLINE */
- if (decline_cnt) {
- start_decline6(client);
- return;
- }
-
- /* XXX: maybe we should loop on the old values instead? */
- if (ia->addrs == NULL) {
- script_init(client, reason, NULL);
-
- if (old != NULL)
- dhc6_marshall_values("old_", client, old,
- oldia,
- oldia != NULL ?
- oldia->addrs : NULL);
-
- dhc6_marshall_values("new_", client, lease, ia,
- NULL);
- script_write_requested6(client);
-
- script_go(client);
- }
- }
-
- /* XXX: maybe we should loop on the old values instead? */
- if (lease->bindings == NULL) {
- script_init(client, reason, NULL);
-
- if (old != NULL)
- dhc6_marshall_values("old_", client, old,
- old->bindings,
- (old->bindings != NULL) ?
- old->bindings->addrs : NULL);
-
- dhc6_marshall_values("new_", client, lease, NULL, NULL);
- script_write_requested6(client);
-
- script_go(client);
- }
-
-#ifdef DHCP4o6
- if (dhcpv4_over_dhcpv6)
- dhcp4o6_start();
-#endif
-
- detach();
-
- if (client->old_lease != NULL) {
- dhc6_lease_destroy(&client->old_lease, MDL);
- client->old_lease = NULL;
- }
-
- /* Schedule events. */
- dhc6_check_times(client);
-}
-
-/* While bound, ignore packets. In the future we'll want to answer
- * Reconfigure-Request messages and the like.
- */
-void
-bound_handler(struct packet *packet, struct client_state *client)
-{
- log_debug("RCV: Input packets are ignored once bound.");
-}
-
-/*
- * start_decline6() kicks off the decline process, transmitting
- * an decline packet and scheduling a retransmission event.
- */
-void
-start_decline6(struct client_state *client)
-{
- /* Cancel any pending transmissions */
- cancel_timeout(do_confirm6, client);
- cancel_timeout(do_select6, client);
- cancel_timeout(do_refresh6, client);
- cancel_timeout(do_release6, client);
- cancel_timeout(do_decline6, client);
- client->state = S_DECLINING;
-
- if (client->active_lease == NULL)
- return;
-
- /* Set timers per RFC3315 section 18.1.7. */
- client->IRT = DEC_TIMEOUT * 100;
- client->MRT = 0;
- client->MRC = DEC_MAX_RC;
- client->MRD = 0;
-
- dhc6_retrans_init(client);
- client->v6_handler = reply_handler;
-
- client->refresh_type = DHCPV6_DECLINE;
- do_decline6(client);
-}
-
-/*
- * do_decline6() creates a Decline packet and transmits it.
- * The decline will contain an IA_NA with iasubopt(s) for
- * each IA_NA containing declined address(es) in the active
- * lease.
- */
-static void
-do_decline6(void *input)
-{
- struct client_state *client;
- struct data_string ds;
- int send_ret;
- struct timeval elapsed, tv;
-
- client = input;
- if (client == NULL || client->active_lease == NULL) {
- return;
- }
-
- if ((client->MRC != 0) && (client->txcount > client->MRC)) {
- log_info("Max retransmission count exceeded.");
- goto decline_done;
- }
-
- /*
- * Start_time starts at the first transmission.
- */
- if (client->txcount == 0) {
- client->start_time.tv_sec = cur_tv.tv_sec;
- client->start_time.tv_usec = cur_tv.tv_usec;
- }
-
- /* elapsed = cur - start */
- elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
- elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
- if (elapsed.tv_usec < 0) {
- elapsed.tv_sec -= 1;
- elapsed.tv_usec += 1000000;
- }
-
- memset(&ds, 0, sizeof(ds));
- if (!buffer_allocate(&ds.buffer, 4, MDL)) {
- log_error("Unable to allocate memory for Decline.");
- goto decline_done;
- }
-
- ds.data = ds.buffer->data;
- ds.len = 4;
- ds.buffer->data[0] = DHCPV6_DECLINE;
- memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
-
- /* Form an elapsed option. */
- /* Maximum value is 65535 1/100s coded as 0xffff. */
- if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
- ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
- client->elapsed = 0xffff;
- } else {
- client->elapsed = elapsed.tv_sec * 100;
- client->elapsed += elapsed.tv_usec / 10000;
- }
-
- client->elapsed = htons(client->elapsed);
-
- log_debug("XMT: Forming Decline.");
- make_client6_options(client, &client->sent_options,
- client->active_lease, DHCPV6_DECLINE);
- dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
- client->sent_options, &global_scope,
- &dhcpv6_universe);
-
- /* Append IA_NA's. */
- if (dhc6_add_ia_na_decline(client, &ds, client->active_lease)
- != ISC_R_SUCCESS) {
- data_string_forget(&ds, MDL);
- goto decline_done;
- }
-
- /* Transmit and wait. */
- log_info("XMT: Decline on %s, interval %ld0ms.",
- client->name ? client->name : client->interface->name,
- (long int)client->RT);
-
- send_ret = send_packet6(client->interface, ds.data, ds.len,
- &DHCPv6DestAddr);
- if (send_ret != ds.len) {
- log_error("dhc6: sendpacket6() sent %d of %d bytes",
- send_ret, ds.len);
- }
-
- data_string_forget(&ds, MDL);
-
- /* Wait RT */
- tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
- tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
- if (tv.tv_usec >= 1000000) {
- tv.tv_sec += 1;
- tv.tv_usec -= 1000000;
- }
- add_timeout(&tv, do_decline6, client, NULL, NULL);
- dhc6_retrans_advance(client);
- return;
-
-decline_done:
- /* We here because we've exhausted our retry limits or
- * something else has gone wrong with the decline process.
- * So let's just toss the existing lease and start over. */
- dhc6_lease_destroy(&client->active_lease, MDL);
- client->active_lease = NULL;
-
- start_init6(client);
- return;
-}
-
-/* start_renew6() gets us all ready to go to start transmitting Renew packets.
- * Note that client->next_MRD must be set before entering this function -
- * it must be set to the time at which the client should start Rebinding.
- */
-void
-start_renew6(void *input)
-{
- struct client_state *client;
-
- client = (struct client_state *)input;
-
- log_info("PRC: Renewing lease on %s.",
- client->name ? client->name : client->interface->name);
- client->state = S_RENEWING;
-
- client->v6_handler = reply_handler;
-
- /* Times per RFC3315 section 18.1.3. */
- client->IRT = REN_TIMEOUT * 100;
- client->MRT = REN_MAX_RT * 100;
- client->MRC = 0;
- /* MRD is special in renew - we need to set it by checking timer
- * state.
- */
- client->MRD = client->next_MRD - cur_time;
-
- dhc6_retrans_init(client);
-
- client->refresh_type = DHCPV6_RENEW;
- do_refresh6(client);
-}
-
-/* do_refresh6() transmits one DHCPv6 packet, be it a Renew or Rebind, and
- * gives the retransmission state a bump for the next time. Note that
- * client->refresh_type must be set before entering this function.
- */
-void
-do_refresh6(void *input)
-{
- struct option_cache *oc;
- struct sockaddr_in6 unicast, *dest_addr = &DHCPv6DestAddr;
- struct data_string ds;
- struct client_state *client;
- struct dhc6_lease *lease;
- struct timeval elapsed, tv;
- int send_ret, added;
-
- client = (struct client_state *)input;
- memset(&ds, 0, sizeof(ds));
-
- lease = client->active_lease;
- if (lease == NULL) {
- log_error("Cannot renew without an active binding.");
- return;
- }
-
- /* Ensure we're emitting a valid message type. */
- switch (client->refresh_type) {
- case DHCPV6_RENEW:
- case DHCPV6_REBIND:
- break;
-
- default:
- log_fatal("Internal inconsistency (%d) at %s:%d.",
- client->refresh_type, MDL);
- }
-
- /*
- * Start_time starts at the first transmission.
- */
- if (client->txcount == 0) {
- client->start_time.tv_sec = cur_tv.tv_sec;
- client->start_time.tv_usec = cur_tv.tv_usec;
- }
-
- /* elapsed = cur - start */
- elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
- elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
- if (elapsed.tv_usec < 0) {
- elapsed.tv_sec -= 1;
- elapsed.tv_usec += 1000000;
- }
- if (((client->MRC != 0) && (client->txcount > client->MRC)) ||
- ((client->MRD != 0) && (elapsed.tv_sec >= client->MRD))) {
- /* We're done. Move on to the next phase, if any. */
- dhc6_check_times(client);
- return;
- }
-
- /*
- * Check whether the server has sent a unicast option; if so, we can
- * use the address it specified for RENEWs.
- */
- oc = lookup_option(&dhcpv6_universe, lease->options, D6O_UNICAST);
- if (oc && evaluate_option_cache(&ds, NULL, NULL, NULL,
- lease->options, NULL, &global_scope,
- oc, MDL)) {
- if (ds.len < 16) {
- log_error("Invalid unicast option length %d.", ds.len);
- } else {
- memset(&unicast, 0, sizeof(DHCPv6DestAddr));
- unicast.sin6_family = AF_INET6;
- unicast.sin6_port = remote_port;
- memcpy(&unicast.sin6_addr, ds.data, 16);
- if (client->refresh_type == DHCPV6_RENEW) {
- dest_addr = &unicast;
- }
- }
-
- data_string_forget(&ds, MDL);
- }
-
- /* Commence forming a renew packet. */
- memset(&ds, 0, sizeof(ds));
- if (!buffer_allocate(&ds.buffer, 4, MDL)) {
- log_error("Unable to allocate memory for packet.");
- return;
- }
- ds.data = ds.buffer->data;
- ds.len = 4;
-
- ds.buffer->data[0] = client->refresh_type;
- memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
-
- /* Form an elapsed option. */
- /* Maximum value is 65535 1/100s coded as 0xffff. */
- if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
- ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
- client->elapsed = 0xffff;
- } else {
- client->elapsed = elapsed.tv_sec * 100;
- client->elapsed += elapsed.tv_usec / 10000;
- }
-
- if (client->elapsed == 0)
- log_debug("XMT: Forming %s, 0 ms elapsed.",
- dhcpv6_type_names[client->refresh_type]);
- else
- log_debug("XMT: Forming %s, %u0 ms elapsed.",
- dhcpv6_type_names[client->refresh_type],
- (unsigned)client->elapsed);
-
- client->elapsed = htons(client->elapsed);
-
- make_client6_options(client, &client->sent_options, lease,
- client->refresh_type);
-
- /* Put in any options from the sent cache. */
- dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
- client->sent_options, &global_scope,
- &dhcpv6_universe);
-
- /* Now append any IA's, and within them any IAADDR/IAPREFIXs.
- * For each type of IA (na, ta, pd) we start with the ones for
- * which we already have addresses (dhc6_add_ia_xx) and then
- * if we still want more we add aditional IAs (dhc6_bare_ia_xx)
- */
- if (wanted_ia_na &&
- ((dhc6_add_ia_na(client, &ds, lease, client->refresh_type,
- wanted_ia_na, &added) != ISC_R_SUCCESS) ||
- (dhc6_bare_ia_xx(client, &ds, wanted_ia_na - added,
- D6O_IA_NA) != ISC_R_SUCCESS))) {
- data_string_forget(&ds, MDL);
- return;
- }
- if (wanted_ia_pd &&
- ((dhc6_add_ia_pd(client, &ds, lease, client->refresh_type,
- wanted_ia_pd, &added) != ISC_R_SUCCESS) ||
- (dhc6_bare_ia_xx(client, &ds, wanted_ia_pd - added,
- D6O_IA_PD) != ISC_R_SUCCESS))) {
- data_string_forget(&ds, MDL);
- return;
- }
-
- log_info("XMT: %s on %s, interval %ld0ms.",
- dhcpv6_type_names[client->refresh_type],
- client->name ? client->name : client->interface->name,
- (long int)client->RT);
-
- send_ret = send_packet6(client->interface, ds.data, ds.len, dest_addr);
-
- if (send_ret != ds.len) {
- log_error("dhc6: send_packet6() sent %d of %d bytes",
- send_ret, ds.len);
- }
-
- data_string_forget(&ds, MDL);
-
- /* Wait RT */
- tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
- tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
- if (tv.tv_usec >= 1000000) {
- tv.tv_sec += 1;
- tv.tv_usec -= 1000000;
- }
- add_timeout(&tv, do_refresh6, client, NULL, NULL);
-
- dhc6_retrans_advance(client);
-}
-
-/* start_rebind6() gets us all set up to go and rebind a lease. Note that
- * client->next_MRD must be set before entering this function. In this case,
- * MRD must be set to the maximum time any address in the packet will
- * expire.
- */
-void
-start_rebind6(void *input)
-{
- struct client_state *client;
-
- client = (struct client_state *)input;
-
- log_info("PRC: Rebinding lease on %s.",
- client->name ? client->name : client->interface->name);
- client->state = S_REBINDING;
-
- client->v6_handler = reply_handler;
-
- /* Times per RFC3315 section 18.1.4. */
- client->IRT = REB_TIMEOUT * 100;
- client->MRT = REB_MAX_RT * 100;
- client->MRC = 0;
- /* MRD is special in rebind - it's determined by the timer
- * state.
- */
- client->MRD = client->next_MRD - cur_time;
-
- dhc6_retrans_init(client);
-
- client->refresh_type = DHCPV6_REBIND;
- do_refresh6(client);
-}
-
-/* do_depref() runs through a given lease's addresses, for each that has
- * not yet been depreffed, shells out to the dhclient-script to inform it
- * of the status change. The dhclient-script should then do...something...
- * to encourage applications to move off the address and onto one of the
- * remaining 'preferred' addresses.
- */
-void
-do_depref(void *input)
-{
- struct client_state *client;
- struct dhc6_lease *lease;
- struct dhc6_ia *ia;
- struct dhc6_addr *addr;
-
- client = (struct client_state *)input;
-
- lease = client->active_lease;
- if (lease == NULL)
- return;
-
- for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
- for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
- if (addr->flags & DHC6_ADDR_DEPREFFED)
- continue;
-
- if (addr->starts + addr->preferred_life <= cur_time) {
- script_init(client, "DEPREF6", NULL);
- dhc6_marshall_values("cur_", client, lease,
- ia, addr);
- script_write_requested6(client);
- script_go(client);
-
- addr->flags |= DHC6_ADDR_DEPREFFED;
-
- if (ia->ia_type != D6O_IA_PD)
- log_info("PRC: Address %s depreferred.",
- piaddr(addr->address));
- else
- log_info("PRC: Prefix %s/%u depreferred.",
- piaddr(addr->address),
- (unsigned) addr->plen);
-
-#if defined (NSUPDATE)
- /* Remove DDNS bindings at depref time. */
- if ((ia->ia_type == D6O_IA_NA) &&
- client->config->do_forward_update)
- client_dns_remove(client,
- &addr->address);
-#endif
- }
- }
- }
-
- dhc6_check_times(client);
-}
-
-/* do_expire() searches through all the addresses on a given lease, and
- * expires/removes any addresses that are no longer valid.
- */
-void
-do_expire(void *input)
-{
- struct client_state *client;
- struct dhc6_lease *lease;
- struct dhc6_ia *ia, **tia;
- struct dhc6_addr *addr;
- int has_addrs = ISC_FALSE;
- int ia_has_addrs = ISC_FALSE;
-
- client = (struct client_state *)input;
-
- lease = client->active_lease;
- if (lease == NULL)
- return;
-
- for (ia = lease->bindings, tia = &lease->bindings; ia != NULL ; ) {
- ia_has_addrs = ISC_FALSE;
- for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
- if (addr->flags & DHC6_ADDR_EXPIRED)
- continue;
-
- if (addr->starts + addr->max_life <= cur_time) {
- script_init(client, "EXPIRE6", NULL);
- dhc6_marshall_values("old_", client, lease,
- ia, addr);
- script_write_requested6(client);
- script_go(client);
-
- addr->flags |= DHC6_ADDR_EXPIRED;
-
- if (ia->ia_type != D6O_IA_PD)
- log_info("PRC: Address %s expired.",
- piaddr(addr->address));
- else
- log_info("PRC: Prefix %s/%u expired.",
- piaddr(addr->address),
- (unsigned) addr->plen);
-
-#if defined (NSUPDATE)
- /* We remove DNS records at depref time, but
- * it is possible that we might get here
- * without depreffing.
- */
- if ((ia->ia_type == D6O_IA_NA) &&
- client->config->do_forward_update &&
- !(addr->flags & DHC6_ADDR_DEPREFFED))
- client_dns_remove(client,
- &addr->address);
-#endif
-
- continue;
- }
-
- ia_has_addrs = ISC_TRUE;
- has_addrs = ISC_TRUE;
- }
-
- /* Update to the next ia and git rid of this ia
- * if it doesn't have any leases.
- */
- if (ia_has_addrs == ISC_TRUE) {
- /* leases, just advance the list pointer */
- tia = &(*tia)->next;
- } else {
- /* no leases, update the list pointer
- * and free the ia
- */
- *tia = ia->next;
- dhc6_ia_destroy(&ia, MDL);
- }
- /* lastly update the ia pointer to our new ia */
- ia = *tia;
- }
-
- /* Clean up empty leases. */
- if (has_addrs == ISC_FALSE) {
- log_info("PRC: Bound lease is devoid of active addresses."
- " Re-initializing.");
-
- dhc6_lease_destroy(&lease, MDL);
- client->active_lease = NULL;
-
- start_init6(client);
- return;
- }
-
- /* Schedule the next run through. */
- dhc6_check_times(client);
-}
-
-/*
- * Run client script to unconfigure interface.
- * Called with reason STOP6 when dhclient -x is run, or with reason
- * RELEASE6 when server has replied to a Release message.
- * Stateless is a special case.
- */
-void
-unconfigure6(struct client_state *client, const char *reason)
-{
- struct dhc6_ia *ia;
- struct dhc6_addr *addr;
-
- if (stateless) {
- script_init(client, reason, NULL);
- if (client->active_lease != NULL)
- script_write_params6(client, "old_",
- client->active_lease->options);
- script_write_requested6(client);
- script_go(client);
- return;
- }
-
- if (client->active_lease == NULL)
- return;
-
- for (ia = client->active_lease->bindings ; ia != NULL ; ia = ia->next) {
- if (ia->ia_type == D6O_IA_TA)
- continue;
-
- for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
- script_init(client, reason, NULL);
- dhc6_marshall_values("old_", client,
- client->active_lease, ia, addr);
- script_write_requested6(client);
- script_go(client);
-
-#if defined (NSUPDATE)
- if ((ia->ia_type == D6O_IA_NA) &&
- client->config->do_forward_update)
- client_dns_remove(client, &addr->address);
-#endif
- }
- }
-}
-
-void
-refresh_info_request6(void *input)
-{
- struct client_state *client;
-
- client = (struct client_state *)input;
- start_info_request6(client);
-}
-
-/* Timeout for Information-Request (using the IRT option).
- */
-static void
-dhc6_check_irt(struct client_state *client)
-{
- struct option **req;
- struct option_cache *oc;
- TIME expire = MAX_TIME;
- struct timeval tv;
- int i;
- isc_boolean_t found = ISC_FALSE;
-
- cancel_timeout(refresh_info_request6, client);
-
- req = client->config->requested_options;
- for (i = 0; req[i] != NULL; i++) {
- if (req[i] == irt_option) {
- found = ISC_TRUE;
- break;
- }
- }
- /* Simply return gives a endless loop waiting for nothing. */
- if (!found) {
-#ifdef DHCP4o6
- if (!dhcpv4_over_dhcpv6)
-#endif
- finish(0);
- }
-
- oc = lookup_option(&dhcpv6_universe, client->active_lease->options,
- D6O_INFORMATION_REFRESH_TIME);
- if (oc != NULL) {
- struct data_string irt;
-
- memset(&irt, 0, sizeof(irt));
- if (!evaluate_option_cache(&irt, NULL, NULL, client,
- client->active_lease->options,
- NULL, &global_scope, oc, MDL) ||
- (irt.len < 4)) {
- log_error("Can't evaluate IRT.");
- } else {
- expire = getULong(irt.data);
- if (expire < IRT_MINIMUM)
- expire = IRT_MINIMUM;
- if (expire == 0xffffffff)
- expire = MAX_TIME;
- }
- data_string_forget(&irt, MDL);
- } else
- expire = IRT_DEFAULT;
-
- if (expire != MAX_TIME) {
- log_debug("PRC: Refresh event scheduled in %u seconds.",
- (unsigned) expire);
- tv.tv_sec = cur_time + expire;
- tv.tv_usec = 0;
- add_timeout(&tv, refresh_info_request6, client, NULL, NULL);
- }
-}
-
-/* We got a Reply. Give dhclient-script a tickle to inform it about
- * the new values, and then lay in wait for the next event.
- */
-static void
-start_informed(struct client_state *client)
-{
- client->v6_handler = informed_handler;
-
- log_debug("PRC: Done.");
-
- client->state = S_BOUND;
-
- script_init(client, "RENEW6", NULL);
- if (client->old_lease != NULL)
- script_write_params6(client, "old_",
- client->old_lease->options);
- script_write_params6(client, "new_", client->active_lease->options);
- script_write_requested6(client);
- script_go(client);
-
-#ifdef DHCP4o6
- if (dhcpv4_over_dhcpv6)
- dhcp4o6_start();
-#endif
-
- detach();
-
- if (client->old_lease != NULL) {
- dhc6_lease_destroy(&client->old_lease, MDL);
- client->old_lease = NULL;
- }
-
- /* Schedule events. */
- dhc6_check_irt(client);
-}
-
-/* While informed, ignore packets.
- */
-void
-informed_handler(struct packet *packet, struct client_state *client)
-{
- log_debug("RCV: Input packets are ignored once bound.");
-}
-
-/* make_client6_options() fetches option caches relevant to the client's
- * scope and places them into the sent_options cache. This cache is later
- * used to populate DHCPv6 output packets with options.
- */
-static void
-make_client6_options(struct client_state *client, struct option_state **op,
- struct dhc6_lease *lease, u_int8_t message)
-{
- struct option_cache *oc;
- struct option **req;
- struct buffer *buffer;
- int buflen, i, oro_len;
-
- if ((op == NULL) || (client == NULL))
- return;
-
- if (*op)
- option_state_dereference(op, MDL);
-
- /* Create a cache to carry options to transmission. */
- option_state_allocate(op, MDL);
-
- /* Create and store an 'elapsed time' option in the cache. */
- oc = NULL;
- if (option_cache_allocate(&oc, MDL)) {
- const unsigned char *cdata;
-
- cdata = (unsigned char *)&client->elapsed;
-
- if (make_const_data(&oc->expression, cdata, 2, 0, 0, MDL)) {
- option_reference(&oc->option, elapsed_option, MDL);
- save_option(&dhcpv6_universe, *op, oc);
- }
-
- option_cache_dereference(&oc, MDL);
- }
-
- /* Bring in any configured options to send. */
- if (client->config->on_transmission)
- execute_statements_in_scope(NULL, NULL, NULL, client,
- lease ? lease->options : NULL,
- *op, &global_scope,
- client->config->on_transmission,
- NULL, NULL);
-
- /* Rapid-commit is only for SOLICITs. */
- if (message != DHCPV6_SOLICIT)
- delete_option(&dhcpv6_universe, *op, D6O_RAPID_COMMIT);
-
- /* See if the user configured a DUID in a relevant scope. If not,
- * introduce our default manufactured id.
- */
- if ((oc = lookup_option(&dhcpv6_universe, *op,
- D6O_CLIENTID)) == NULL) {
- if (!option_cache(&oc, &default_duid, NULL, clientid_option,
- MDL))
- log_fatal("Failure assembling a DUID.");
-
- save_option(&dhcpv6_universe, *op, oc);
- option_cache_dereference(&oc, MDL);
- }
-
- /* In cases where we're responding to a single server, put the
- * server's id in the response.
- *
- * Note that lease is NULL for SOLICIT or INFO request messages,
- * and otherwise MUST be present.
- */
- if (lease == NULL) {
- if ((message != DHCPV6_SOLICIT) &&
- (message != DHCPV6_INFORMATION_REQUEST))
- log_fatal("Impossible condition at %s:%d.", MDL);
- } else if ((message != DHCPV6_REBIND) &&
- (message != DHCPV6_CONFIRM)) {
- oc = lookup_option(&dhcpv6_universe, lease->options,
- D6O_SERVERID);
- if (oc != NULL)
- save_option(&dhcpv6_universe, *op, oc);
- }
-
- /* 'send dhcp6.oro foo;' syntax we used in 4.0.0a1/a2 has been
- * deprecated by adjustments to the 'request' syntax also used for
- * DHCPv4.
- */
- if (lookup_option(&dhcpv6_universe, *op, D6O_ORO) != NULL)
- log_error("'send dhcp6.oro' syntax is deprecated, please "
- "use the 'request' syntax (\"man dhclient.conf\").");
-
- /* Construct and store an ORO (Option Request Option). It is a
- * fatal error to fail to send an ORO (of at least zero length).
- *
- * Discussion: RFC3315 appears to be inconsistent in its statements
- * of whether or not the ORO is mandatory. In section 18.1.1
- * ("Creation and Transmission of Request Messages"):
- *
- * The client MUST include an Option Request option (see section
- * 22.7) to indicate the options the client is interested in
- * receiving. The client MAY include options with data values as
- * hints to the server about parameter values the client would like
- * to have returned.
- *
- * This MUST is missing from the creation/transmission of other
- * messages (such as Renew and Rebind), and the section 22.7 ("Option
- * Request Option" format and definition):
- *
- * A client MAY include an Option Request option in a Solicit,
- * Request, Renew, Rebind, Confirm or Information-request message to
- * inform the server about options the client wants the server to
- * send to the client. A server MAY include an Option Request
- * option in a Reconfigure option to indicate which options the
- * client should request from the server.
- *
- * seems to relax the requirement from MUST to MAY (and still other
- * language in RFC3315 supports this).
- *
- * In lieu of a clarification of RFC3315, we will conform with the
- * MUST. Instead of an absent ORO, we will if there are no options
- * to request supply an empty ORO. Theoretically, an absent ORO is
- * difficult to interpret (does the client want all options or no
- * options?). A zero-length ORO is intuitively clear: requesting
- * nothing.
- */
- buffer = NULL;
- oro_len = 0;
- buflen = 32;
- if (!buffer_allocate(&buffer, buflen, MDL))
- log_fatal("Out of memory constructing DHCPv6 ORO.");
- req = client->config->requested_options;
- if (req != NULL) {
- for (i = 0 ; req[i] != NULL ; i++) {
- if (buflen == oro_len) {
- struct buffer *tmpbuf = NULL;
-
- buflen += 32;
-
- /* Shell game. */
- buffer_reference(&tmpbuf, buffer, MDL);
- buffer_dereference(&buffer, MDL);
-
- if (!buffer_allocate(&buffer, buflen, MDL))
- log_fatal("Out of memory resizing "
- "DHCPv6 ORO buffer.");
-
- memcpy(buffer->data, tmpbuf->data, oro_len);
-
- buffer_dereference(&tmpbuf, MDL);
- }
-
- if (req[i]->universe == &dhcpv6_universe) {
- /* Append the code to the ORO. */
- putUShort(buffer->data + oro_len,
- req[i]->code);
- oro_len += 2;
- }
- }
- }
-
- oc = NULL;
- if (make_const_option_cache(&oc, &buffer, NULL, oro_len,
- oro_option, MDL)) {
- save_option(&dhcpv6_universe, *op, oc);
- } else {
- log_fatal("Unable to create ORO option cache.");
- }
-
- /*
- * Note: make_const_option_cache() consumes the buffer, we do not
- * need to dereference it (XXX).
- */
- option_cache_dereference(&oc, MDL);
-}
-
-/* A clone of the DHCPv4 script_write_params() minus the DHCPv4-specific
- * filename, server-name, etc specifics.
- *
- * Simply, store all values present in all universes of the option state
- * (probably derived from a DHCPv6 packet) into environment variables
- * named after the option names (and universe names) but with the 'prefix'
- * prepended.
- *
- * Later, dhclient-script may compare for example "new_time_servers" and
- * "old_time_servers" for differences, and only upon detecting a change
- * bother to rewrite ntp.conf and restart it. Or something along those
- * generic lines.
- */
-static void
-script_write_params6(struct client_state *client, const char *prefix,
- struct option_state *options)
-{
- struct envadd_state es;
- int i;
-
- if (options == NULL)
- return;
-
- es.client = client;
- es.prefix = prefix;
-
- for (i = 0 ; i < options->universe_count ; i++) {
- option_space_foreach(NULL, NULL, client, NULL, options,
- &global_scope, universes[i], &es,
- client_option_envadd);
- }
-}
-
-/*
- * A clone of the DHCPv4 routine.
- * Write out the environment variables for the objects that the
- * client requested. If the object was requested the variable will be:
- * requested_<option_name>=1
- * If it wasn't requested there won't be a variable.
- */
-static void script_write_requested6(client)
- struct client_state *client;
-{
- int i;
- struct option **req;
- char name[256];
- req = client->config->requested_options;
-
- if (req == NULL)
- return;
-
- for (i = 0 ; req[i] != NULL ; i++) {
- if ((req[i]->universe == &dhcpv6_universe) &&
- dhcp_option_ev_name (name, sizeof(name), req[i])) {
- client_envadd(client, "requested_", name, "%d", 1);
- }
- }
-}
-
-/*
- * Check if there is something not fully defined in the active lease.
- */
-static isc_boolean_t
-active_prefix(struct client_state *client)
-{
- struct dhc6_lease *lease;
- struct dhc6_ia *ia;
- struct dhc6_addr *pref;
- char zeros[16];
-
- lease = client->active_lease;
- if (lease == NULL)
- return ISC_FALSE;
- memset(zeros, 0, 16);
- for (ia = lease->bindings; ia != NULL; ia = ia->next) {
- if (ia->ia_type != D6O_IA_PD)
- continue;
- for (pref = ia->addrs; pref != NULL; pref = pref->next) {
- if (pref->plen == 0)
- return ISC_FALSE;
- if (pref->address.len != 16)
- return ISC_FALSE;
- if (memcmp(pref->address.iabuf, zeros, 16) == 0)
- return ISC_FALSE;
- }
- }
- return ISC_TRUE;
-}
-
-/* Adds a leases's declined addreses to the outbound packet
- *
- * For each IA_NA in the lease that contains one or more declined
- * addresses, an IA_NA option with an iasubopt for each declined
- * address is added to the outbound packet.
- *
- * We skip PDs and TAs as declines are undefined for them.
- */
-static isc_result_t
-dhc6_add_ia_na_decline(struct client_state *client, struct data_string *packet,
- struct dhc6_lease *lease) {
- struct data_string iads;
- struct data_string addrds;
- struct dhc6_addr *addr;
- struct dhc6_ia *ia;
- isc_result_t rval = ISC_R_SUCCESS;
-
- memset(&iads, 0, sizeof(iads));
- memset(&addrds, 0, sizeof(addrds));
- for (ia = lease->bindings; ia != NULL && rval == ISC_R_SUCCESS;
- ia = ia->next) {
- if (ia->ia_type != D6O_IA_NA)
- continue;
-
- int start_new_ia = 1;
- for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
- /*
- * Do not confirm expired addresses, do not request
- * expired addresses (but we keep them around for
- * solicit).
- */
- if (!(addr->flags & DHC6_ADDR_DECLINED)) {
- continue;
- }
-
- if (start_new_ia) {
- if (!buffer_allocate(&iads.buffer, 12, MDL)) {
- log_error("Unable to allocate memory"
- " for IA_NA.");
- rval = ISC_R_NOMEMORY;
- break;
- }
-
- /* Copy the IAID into the packet buffer. */
- memcpy(iads.buffer->data, ia->iaid, 4);
- iads.data = iads.buffer->data;
- iads.len = 12;
-
- /* Set t1/t2 to zero; server will ignore them */
- memset(iads.buffer->data + 4, 0, 8);
- log_debug("XMT: X-- IA_NA %s",
- print_hex_1(4, iads.buffer->data, 55));
- start_new_ia = 0;
- }
-
- if (addr->address.len != 16) {
- log_error("Illegal IPv6 address length (%d), "
- "ignoring. (%s:%d)",
- addr->address.len, MDL);
- continue;
- }
-
- if (!buffer_allocate(&addrds.buffer, 24, MDL)) {
- log_error("Unable to allocate memory for "
- "IAADDR.");
- rval = ISC_R_NOMEMORY;
- break;
- }
-
- addrds.data = addrds.buffer->data;
- addrds.len = 24;
-
- /* Copy the address into the packet buffer. */
- memcpy(addrds.buffer->data, addr->address.iabuf, 16);
-
- /* Preferred and max life are irrelevant */
- memset(addrds.buffer->data + 16, 0, 8);
- log_debug("XMT: | X-- Decline Address %s",
- piaddr(addr->address));
-
- append_option(&iads, &dhcpv6_universe, iaaddr_option,
- &addrds);
- data_string_forget(&addrds, MDL);
- }
-
- /*
- * It doesn't make sense to make a request without an
- * address.
- */
- if (ia->addrs == NULL) {
- log_debug("!!!: V IA_NA has no IAADDRs - removed.");
- rval = ISC_R_FAILURE;
- } else if (rval == ISC_R_SUCCESS) {
- log_debug("XMT: V IA_NA appended.");
- append_option(packet, &dhcpv6_universe, ia_na_option,
- &iads);
- }
-
- data_string_forget(&iads, MDL);
- }
-
- return (rval);
-}
-
-/*
- * Remove any declined NA addresses from the lease.
- *
- * Returns zero if the all of the bindings on the lease
- * were removed, non-zero if there are PD, TA, or usuable NA
- * bindings
- */
-int drop_declined_addrs(struct dhc6_lease *lease) {
- struct dhc6_ia *ia;
- int live_cnt = 0;
-
- for (ia = lease->bindings; ia != NULL; ia = ia->next) {
- struct dhc6_addr* prev_addr;
- struct dhc6_addr* addr;
- struct dhc6_addr* next;
-
- /* If it's a PD or TA, we assume it has at least
- * one usuable binding */
- if (ia->ia_type != D6O_IA_NA) {
- live_cnt++;
- continue;
- }
-
- prev_addr = NULL;
- for (addr = ia->addrs ; addr != NULL ; ) {
- if (!(addr->flags & DHC6_ADDR_DECLINED)) {
- live_cnt++;
- addr = addr->next;
- prev_addr = addr;
- continue;
- }
-
- /* If we're deleting head, move it up one */
- if (ia->addrs == addr) {
- ia->addrs = addr->next;
- prev_addr = addr->next;
- } else {
- prev_addr->next = addr->next;
- }
-
- if (addr->options != NULL) {
- option_state_dereference(&addr->options, MDL);
- }
-
- next = addr->next;
- dfree(addr, MDL);
- addr = next;
- }
- }
-
- return (live_cnt);
-}
-
-/* Run through the addresses in lease and return true if there's any unexpired.
- * Return false otherwise.
- */
-static isc_boolean_t
-unexpired_address_in_lease(struct dhc6_lease *lease)
-{
- struct dhc6_ia *ia;
- struct dhc6_addr *addr;
-
- if (lease == NULL) {
- return ISC_FALSE;
- }
-
- for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
- for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
- if (!(addr->flags & DHC6_ADDR_EXPIRED) &&
- (addr->starts + addr->max_life > cur_time)) {
- return ISC_TRUE;
- }
- }
- }
-
- log_debug("PRC: Previous lease is devoid of active addresses.");
- return ISC_FALSE;
-}
-#endif /* DHCPv6 */
diff --git a/client/dhclient-script.8 b/client/dhclient-script.8
deleted file mode 100644
index 5e5bd3d0..00000000
--- a/client/dhclient-script.8
+++ /dev/null
@@ -1,239 +0,0 @@
-.\" dhclient-script.8
-.\"
-.\" Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
-.\" Copyright (c) 1996-2003 by Internet Software Consortium
-.\"
-.\" This Source Code Form is subject to the terms of the Mozilla Public
-.\" License, v. 2.0. If a copy of the MPL was not distributed with this
-.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
-.\"
-.\" 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.
-.\" PO Box 360
-.\" Newmarket, NH 03857 USA
-.\" <info@isc.org>
-.\" https://www.isc.org/
-.\"
-.\" Support and other services are available for ISC products - see
-.\" https://www.isc.org for more information or to learn more about ISC.
-.\"
-.\" $Id: dhclient-script.8,v 1.14 2010/07/02 23:09:14 sar Exp $
-.\"
-.TH dhclient-script 8
-.SH NAME
-dhclient-script - DHCP client network configuration script
-.SH DESCRIPTION
-The DHCP client network configuration script is invoked from time to
-time by \fBdhclient(8)\fR. This script is used by the dhcp client to
-set each interface's initial configuration prior to requesting an
-address, to test the address once it has been offered, and to set the
-interface's final configuration once a lease has been acquired. If no
-lease is acquired, the script is used to test predefined leases, if
-any, and also called once if no valid lease can be identified.
-.PP
-This script is not meant to be customized by the end user. If local
-customizations are needed, they should be possible using the enter and
-exit hooks provided (see HOOKS for details). These hooks will allow the
-user to override the default behaviour of the client in creating a
-.B /etc/resolv.conf
-file.
-.PP
-No standard client script exists for some operating systems, even though
-the actual client may work, so a pioneering user may well need to create
-a new script or modify an existing one. In general, customizations specific
-to a particular computer should be done in the
-.B ETCDIR/dhclient.conf
-file. If you find that you can't make such a customization without
-customizing
-.B ETCDIR/dhclient.conf
-or using the enter and exit hooks, please submit a bug report.
-.SH HOOKS
-When it starts, the client script first defines a shell function,
-.B make_resolv_conf ,
-which is later used to create the
-.B /etc/resolv.conf
-file. To override the default behaviour, redefine this function in
-the enter hook script.
-.PP
-On after defining the make_resolv_conf function, the client script checks
-for the presence of an executable
-.B ETCDIR/dhclient-enter-hooks
-script, and if present, it invokes the script inline, using the Bourne
-shell \'.\' command. The entire environment documented under OPERATION
-is available to this script, which may modify the environment if needed
-to change the behaviour of the script. If an error occurs during the
-execution of the script, it can set the exit_status variable to a nonzero
-value, and
-.B CLIENTBINDIR/dhclient-script
-will exit with that error code immediately after the client script exits.
-.PP
-After all processing has completed,
-.B CLIENTBINDIR/dhclient-script
-checks for the presence of an executable
-.B ETCDIR/dhclient-exit-hooks
-script, which if present is invoked using the \'.\' command. The exit
-status of dhclient-script will be passed to dhclient-exit-hooks in the
-exit_status shell variable, and will always be zero if the script
-succeeded at the task for which it was invoked. The rest of the
-environment as described previously for dhclient-enter-hooks is also
-present. The
-.B ETCDIR/dhclient-exit-hooks
-script can modify the valid of exit_status to change the exit status
-of dhclient-script.
-.SH OPERATION
-When dhclient needs to invoke the client configuration script, it
-defines a set of variables in the environment, and then invokes
-.B CLIENTBINDIR/dhclient-script.
-In all cases, $reason is set to the name of the reason why the script
-has been invoked. The following reasons are currently defined:
-MEDIUM, PREINIT, BOUND, RENEW, REBIND, REBOOT, EXPIRE, FAIL, STOP, RELEASE,
-NBI and TIMEOUT.
-.PP
-.SH MEDIUM
-The DHCP client is requesting that an interface's media type
-be set. The interface name is passed in $interface, and the media
-type is passed in $medium.
-.SH PREINIT
-The DHCP client is requesting that an interface be configured as
-required in order to send packets prior to receiving an actual
-address. For clients which use the BSD socket library, this means
-configuring the interface with an IP address of 0.0.0.0 and a
-broadcast address of 255.255.255.255. For other clients, it may be
-possible to simply configure the interface up without actually giving
-it an IP address at all. The interface name is passed in $interface,
-and the media type in $medium.
-.PP
-If an IP alias has been declared in dhclient.conf, its address will be
-passed in $alias_ip_address, and that ip alias should be deleted from
-the interface, along with any routes to it.
-.SH BOUND
-The DHCP client has done an initial binding to a new address. The
-new ip address is passed in $new_ip_address, and the interface name is
-passed in $interface. The media type is passed in $medium. Any
-options acquired from the server are passed using the option name
-described in \fBdhcp-options\fR, except that dashes (\'-\') are replaced
-by underscores (\'_\') in order to make valid shell variables, and the
-variable names start with new_. So for example, the new subnet mask
-would be passed in $new_subnet_mask. Options from a non-default
-universe will have the universe name prepended to the option name, for
-example $new_dhcp6_server_id. The options that the client
-explicitly requested via a PRL or ORO option are passed with the same
-option name as above but prepended with requested_ and with a value of 1,
-for example requested_subnet_mask=1. No such variable is defined for
-options not requested by the client or options that don't require a
-request option, such as the ip address (*_ip_address) or expiration
-time (*_expiry).
-.PP
-Before actually configuring the address, dhclient-script should
-somehow ARP for it and exit with a nonzero status if it receives a
-reply. In this case, the client will send a DHCPDECLINE message to
-the server and acquire a different address. This may also be done in
-the RENEW, REBIND, or REBOOT states, but is not required, and indeed
-may not be desirable.
-.PP
-When a binding has been completed, a lot of network parameters are
-likely to need to be set up. A new /etc/resolv.conf needs to be
-created, using the values of $new_domain_name and
-$new_domain_name_servers (which may list more than one server,
-separated by spaces). A default route should be set using
-$new_routers, and static routes may need to be set up using
-$new_static_routes.
-.PP
-If an IP alias has been declared, it must be set up here. The alias
-IP address will be written as $alias_ip_address, and other DHCP
-options that are set for the alias (e.g., subnet mask) will be passed
-in variables named as described previously except starting with
-$alias_ instead of $new_. Care should be taken that the alias IP
-address not be used if it is identical to the bound IP address
-($new_ip_address), since the other alias parameters may be incorrect
-in this case.
-.SH RENEW
-When a binding has been renewed, the script is called as in BOUND,
-except that in addition to all the variables starting with $new_, and
-$requested_ there is another set of variables starting with $old_.
-Persistent settings that may have changed need to be deleted - for
-example, if a local route to the bound address is being configured,
-the old local route should be deleted. If the default route has changed,
-the old default route should be deleted. If the static routes have changed,
-the old ones should be deleted. Otherwise, processing can be done as with
-BOUND.
-.SH REBIND
-The DHCP client has rebound to a new DHCP server. This can be handled
-as with RENEW, except that if the IP address has changed, the ARP
-table should be cleared.
-.SH REBOOT
-The DHCP client has successfully reacquired its old address after a
-reboot. This can be processed as with BOUND.
-.SH EXPIRE
-The DHCP client has failed to renew its lease or acquire a new one,
-and the lease has expired. The IP address must be relinquished, and
-all related parameters should be deleted, as in RENEW and REBIND.
-.SH FAIL
-The DHCP client has been unable to contact any DHCP servers, and any
-leases that have been tested have not proved to be valid. The
-parameters from the last lease tested should be deconfigured. This
-can be handled in the same way as EXPIRE.
-.SH STOP
-The dhclient has been informed to shut down gracefully, the
-dhclient-script should unconfigure or shutdown the interface as
-appropriate.
-.SH RELEASE
-The dhclient has been executed using the -r flag, indicating that the
-administrator wishes it to release its lease(s). dhclient-script should
-unconfigure or shutdown the interface.
-.SH NBI
-No-Broadcast-Interfaces...dhclient was unable to find any interfaces
-upon which it believed it should commence DHCP. What dhclient-script
-should do in this situation is entirely up to the implementor.
-.SH TIMEOUT
-The DHCP client has been unable to contact any DHCP servers.
-However, an old lease has been identified, and its parameters have
-been passed in as with BOUND. The client configuration script should
-test these parameters and, if it has reason to believe they are valid,
-should exit with a value of zero. If not, it should exit with a
-nonzero value.
-.SH V6ONLY
-The DHCPv4 client has received a requested valid v6-only-preferred
-option. The system should disable IPv4 on the interface. On its side
-the dhclient waits for V6ONLY_WAIT seconds (the timer is carried by
-the option with a minimum of MIN_V6ONLY_WAIT) before returning in
-the INIT state.
-.PP
-The usual way to test a lease is to set up the network as with REBIND
-(since this may be called to test more than one lease) and then ping
-the first router defined in $routers. If a response is received, the
-lease must be valid for the network to which the interface is
-currently connected. It would be more complete to try to ping all of
-the routers listed in $new_routers, as well as those listed in
-$new_static_routes, but current scripts do not do this.
-.SH FILES
-Each operating system should generally have its own script file,
-although the script files for similar operating systems may be similar
-or even identical. The script files included in Internet
-Systems Consortium DHCP distribution appear in the distribution tree
-under client/scripts, and bear the names of the operating systems on
-which they are intended to work.
-.SH BUGS
-If more than one interface is being used, there's no obvious way to
-avoid clashes between server-supplied configuration parameters - for
-example, the stock dhclient-script rewrites /etc/resolv.conf. If
-more than one interface is being configured, /etc/resolv.conf will be
-repeatedly initialized to the values provided by one server, and then
-the other. Assuming the information provided by both servers is
-valid, this shouldn't cause any real problems, but it could be
-confusing.
-.SH SEE ALSO
-dhclient(8), dhcpd(8), dhcrelay(8), dhclient.conf(5) and
-dhclient.leases(5).
-.SH AUTHOR
-.B dhclient-script(8)
-To learn more about Internet Systems Consortium,
-see
-.B https://www.isc.org.
diff --git a/client/dhclient.8 b/client/dhclient.8
deleted file mode 100644
index 861ff569..00000000
--- a/client/dhclient.8
+++ /dev/null
@@ -1,608 +0,0 @@
-.\" $Id: dhclient.8,v 1.36 2011/04/15 21:58:12 sar Exp $
-.\"
-.\" Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
-.\" Copyright (c) 1996-2003 by Internet Software Consortium
-.\"
-.\" This Source Code Form is subject to the terms of the Mozilla Public
-.\" License, v. 2.0. If a copy of the MPL was not distributed with this
-.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
-.\"
-.\" 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.
-.\" PO Box 360
-.\" Newmarket, NH 03857 USA
-.\" <info@isc.org>
-.\" https://www.isc.org/
-.\"
-.\" Support and other services are available for ISC products - see
-.\" https://www.isc.org for more information or to learn more about ISC.
-.\"
-.TH dhclient 8
-.SH NAME
-dhclient - Dynamic Host Configuration Protocol Client
-.SH SYNOPSIS
-.B dhclient
-[
-.B -4
-|
-.B -6
-]
-[
-.B -S
-]
-[
-.B -N
-[
-.B -N...
-]
-]
-[
-.B -T
-[
-.B -T...
-]
-]
-[
-.B -P
-[
-.B -P...
-]
-]
-[
-.B -R
-]
-[
-.B -i
-]
-[
-.B -I
-]
-[
-.B -4o6
-.I port
-]
-[
-.B -D
-.I LL|LLT
-]
-[
-.B -p
-.I port-number
-]
-[
-.B -d
-]
-[
-.B -df
-.I duid-lease-file
-]
-[
-.B -e
-.I VAR=value
-]
-[
-.B -q
-]
-[
-.B -1
-]
-[
-.B -r
-|
-.B -x
-]
-[
-.B -lf
-.I lease-file
-]
-[
-.B -pf
-.I pid-file
-]
-[
-.B --no-pid
-]
-[
-.B -cf
-.I config-file
-]
-[
-.B -sf
-.I script-file
-]
-[
-.B -s
-.I server-addr
-]
-[
-.B -g
-.I relay
-]
-[
-.B -n
-]
-[
-.B -nw
-]
-[
-.B -w
-]
-[
-.B --dad-wait-time
-.I seconds
-]
-[
-.B --prefix-len-hint
-.I length
-]
-[
-.B --decline-wait-time
-.I seconds
-]
-[
-.B -v
-]
-[
-.B --version
-]
-[
-.I if0
-[
-.I ...ifN
-]
-]
-.SH DESCRIPTION
-The Internet Systems Consortium DHCP Client, \fBdhclient\fR, provides a
-means for configuring one or more network interfaces using the Dynamic
-Host Configuration Protocol, BOOTP protocol, or if these protocols
-fail, by statically assigning an address.
-.SH OPERATION
-.PP
-The DHCP protocol allows a host to contact a central server which
-maintains a list of IP addresses which may be assigned on one or more
-subnets. A DHCP client may request an address from this pool, and
-then use it on a temporary basis for communication on network. The
-DHCP protocol also provides a mechanism whereby a client can learn
-important details about the network to which it is attached, such as
-the location of a default router, the location of a name server, and
-so on.
-.PP
-There are two versions of the DHCP protocol DHCPv4 and DHCPv6. At
-startup the client may be started for one or the other via the
-.B -4
-or
-.B -6
-options.
-.PP
-On startup, \fBdhclient\fR reads the dhclient.conf
-for configuration instructions. It then gets a list of all the
-network interfaces that are configured in the current system. For
-each interface, it attempts to configure the interface using the DHCP
-protocol.
-.PP
-In order to keep track of leases across system reboots and server
-restarts, \fBdhclient\fR keeps a list of leases it has been assigned in the
-dhclient.leases file. On startup, after reading the dhclient.conf
-file, \fBdhclient\fR reads the dhclient.leases file to refresh its memory
-about what leases it has been assigned.
-.PP
-When a new lease is acquired, it is appended to the end of the
-dhclient.leases file. In order to prevent the file from becoming
-arbitrarily large, from time to time \fBdhclient\fR creates a new
-dhclient.leases file from its in-core lease database. The old version
-of the dhclient.leases file is retained under the name
-.IR dhclient.leases~
-until the next time \fBdhclient\fR rewrites the database.
-.PP
-Old leases are kept around in case the DHCP server is unavailable when
-\fBdhclient\fR is first invoked (generally during the initial system boot
-process). In that event, old leases from the dhclient.leases file
-which have not yet expired are tested, and if they are determined to
-be valid, they are used until either they expire or the DHCP server
-becomes available.
-.PP
-A mobile host which may sometimes need to access a network on which no
-DHCP server exists may be preloaded with a lease for a fixed
-address on that network. When all attempts to contact a DHCP server
-have failed, \fBdhclient\fR will try to validate the static lease, and if it
-succeeds, will use that lease until it is restarted.
-.PP
-A mobile host may also travel to some networks on which DHCP is not
-available but BOOTP is. In that case, it may be advantageous to
-arrange with the network administrator for an entry on the BOOTP
-database, so that the host can boot quickly on that network rather
-than cycling through the list of old leases.
-.SH COMMAND LINE
-.PP
-The names of the network interfaces that \fBdhclient\fR should attempt to
-configure may be specified on the command line. If no interface names
-are specified on the command line \fBdhclient\fR will normally identify all
-network interfaces, eliminating non-broadcast interfaces if
-possible, and attempt to configure each interface.
-.PP
-It is also possible to specify interfaces by name in the dhclient.conf
-file. If interfaces are specified in this way, then the client will
-only configure interfaces that are either specified in the
-configuration file or on the command line, and will ignore all other
-interfaces.
-.PP
-The client normally prints no output during its startup sequence. It
-can be made to emit verbose messages displaying the startup sequence events
-until it has acquired an address by supplying the
-.B -v
-command line argument. In either case, the client logs messages using
-the
-.B syslog(3)
-facility.
-.SH OPTIONS
-.TP
-.BI \-4
-Use the DHCPv4 protocol to obtain an IPv4 address and configuration
-parameters. This is the default and cannot be combined with
-\fB\-6\fR.
-.TP
-.BI \-6
-Use the DHCPv6 protocol to obtain whatever IPv6 addresses are available
-along with configuration parameters. It cannot be combined with
-\fB\-4\fR. The \fB\-S -T -P -N\fR and
-\fB\-D\fR arguments provide more control over aspects of the DHCPv6
-processing. Note: it is not recommended to mix queries of different
-types together or even to share the lease file between them.
-.TP
-.BI \-4o6 \ port
-Participate in the DHCPv4 over DHCPv6 protocol specified by RFC 7341.
-This associates a DHCPv4 and a DHCPv6 client to allow the v4 client to
-send v4 requests encapsulated in a v6 packet. Communication
-between the two clients is done on a pair of UDP sockets bound
-to ::1 \fIport\fR and \fIport + 1\fR. Both clients must
-be launched using the same \fIport\fR argument.
-.TP
-.BI \-1
-Try to get a lease once. On failure exit with code 2. In DHCPv6 this
-sets the maximum duration of the initial exchange to
-.I timeout
-(from dhclient.conf with a default of sixty seconds).
-.TP
-.BI \-d
-.\" This is not intuitive.
-Force
-.B dhclient
-to run as a foreground process. Normally the DHCP client will run
-in the foreground until is has configured an interface at which time
-it will revert to running in the background. This option is useful
-when running the client under a debugger, or when running it out of
-inittab on System V systems. This implies \fB-v\fR.
-.TP
-.BI \-nw
-Become a daemon immediately (nowait) rather than waiting until an
-IP address has been acquired.
-.TP
-.BI \-q
-Be quiet at startup, this is the default.
-.TP
-.BI \-v
-Enable verbose log messages.
-.\" This prints the version, copyright and URL.
-.TP
-.BI \-w
-Continue running even if no broadcast interfaces were found. Normally
-DHCP client will exit if it isn't able to identify any network interfaces
-to configure. On laptop computers and other computers with
-hot-swappable I/O buses, it is possible that a broadcast interface may
-be added after system startup. This flag can be used to cause the client
-not to exit when it doesn't find any such interfaces. The
-.B omshell(1)
-program can then be used to notify the client when a network interface
-has been added or removed, so that the client can attempt to configure an IP
-address on that interface.
-.TP
-.BI \-n
-Do not configure any interfaces. This is most likely to be useful in
-combination with the
-.B -w
-flag.
-.TP
-.BI \-e \ VAR=value
-Define additional environment variables for the environment where
-.B dhclient-script
-executes. You may specify multiple
-.B \-e
-options on the command line.
-.TP
-.BI \-r
-Release the current lease and stop the running DHCP client as previously
-recorded in the PID file. When shutdown via this method
-.B dhclient-script
-will be executed with the specific reason for calling the script set.
-The client normally doesn't release the current lease as this is not
-required by the DHCP protocol but some cable ISPs require their clients
-to notify the server if they wish to release an assigned IP address.
-.\" TODO what dhclient-script argument?
-.\" When released,
-.TP
-.BI \-x
-Stop the running DHCP client without releasing the current lease.
-Kills existing \fBdhclient\fR process as previously recorded in the
-PID file. When shutdown via this method
-.B dhclient-script
-will be executed with the specific reason for calling the script set.
-.TP
-.BI \-p \ port-number
-The UDP port number on which the DHCP client should listen and transmit.
-If unspecified,
-.B dhclient
-uses the default port of 68. This is mostly useful for debugging purposes.
-If a different port is specified on which the client should listen and
-transmit, the client will also use a different destination port -
-one less than the specified port.
-.TP
-.BI \-s \ server-addr
-Specify the server IP address or fully qualified domain name to use as
-a destination for DHCP protocol messages before
-.B dhclient
-has acquired an IP address. Normally,
-.B dhclient
-transmits these messages to 255.255.255.255 (the IP limited broadcast
-address). Overriding this is mostly useful for debugging purposes. This
-feature is not supported in DHCPv6 (\fB-6\fR) mode.
-.TP
-.BI \-g \ relay
-.\" mockup relay
-Set the giaddr field of all packets to the \fIrelay\fR IP address
-simulating a relay agent. This is for testing purposes only and
-should not be expected to work in any consistent or useful way.
-.TP
-.BI \-i
-Use a DUID with DHCPv4 clients. If no DUID is available in the
-lease file one will be constructed and saved. The DUID will be
-used to construct a RFC4361 style client id that will be included
-in the client's messages. This client id can be overridden by
-setting a client id in the configuration file. Overriding the
-client id in this fashion is discouraged.
-.TP
-.BI \-I
-Use the standard DDNS scheme from RFCs 4701 & 4702.
-.TP
-.TP
-.BI \--decline-wait-time \ seconds
-Specify the time (in seconds) that an IPv4 client should wait after
-declining an address before issuing a discover. The default is
-10 seconds as recommended by RFC 2131, Section 3.1.5. A value of
-zero equates to no wait at all.
-.PP
-.BI \--version
-Print version number and exit.
-.PP
-.I Options available for DHCPv6 mode:
-.TP
-.BI \-S
-.\" TODO: mention DUID?
-Use Information-request to get only stateless configuration parameters
-(i.e., without address). This implies \fB\-6\fR. It also doesn't
-rewrite the lease database.
-.\" TODO: May not be used with -N -P or -T. ??
-.TP
-.BI \-T
-.\" TODO wanted_ia_ta++
-Ask for IPv6 temporary addresses, one set per \fB\-T\fR flag. This
-implies \fB\-6\fR and also disables the normal address query.
-See \fB\-N\fR to restore it.
-.TP
-.BI \-P
-Enable IPv6 prefix delegation. This implies \fB\-6\fR and also
-disables the normal address query. See \fB\-N\fR to restore it.
-Multiple prefixes can be requested with multiple \fB\-P\fR flags.
-Note only one requested interface is allowed.
-.TP
-.BI \-R
-Require that responses include all of the items requested by any
-\fB\-N\fR, \fB\-T\fR, or \fB\-P\fR options. Normally even if
-the command line includes a number of these the client will be willing
-to accept the best lease it can even if the lease doesn't include all
-of the requested items. This option causes the client to only
-accept leases that include all of the requested items.
-
-Note well: enabling this may prevent the client from using any
-leases it receives if the servers aren't configured to supply
-all of the items.
-.TP
-.BI \-D \ LL\ or\ LLT
-Override the default when selecting the type of DUID to use. By default,
-DHCPv6 \fBdhclient\fR creates an identifier based on the link-layer address
-(DUID-LL) if it is running in stateless mode (with \fB\-S\fR, not
-requesting an address), or it creates an identifier based on the
-link-layer address plus a timestamp (DUID-LLT) if it is running in
-stateful mode (without \fB\-S\fR, requesting an address). When DHCPv4
-is configured to use a DUID using \fB\-i\fR option the default is to use
-a DUID-LLT. \fB\-D\fR
-overrides these default, with a value of either \fILL\fR or \fILLT\fR.
-.TP
-.BI \-N
-.\" TODO: is this for telling an already running dhclient?
-Restore normal address query for IPv6. This implies \fB-6\fR.
-It is used to restore normal operation after using \fB-T\fR or \fB-P\fR.
-Multiple addresses can be requested with multiple \fB\-N\fR flags.
-.TP
-.BI \--address-prefix-len \ length
-Specify the length of the prefix for IPv6 addresses. This value is passed by
-dhclient into the client script via the environment variable, ip6_prefixlen,
-when binding IPv6 addresses. The default value is 128. Alternatively you may
-change the default at compile time by setting DHCLIENT_DEFAULT_PREFIX_LEN in
-includes/site.h.
-.PP
-.TP
-.BI \--dad-wait-time \ seconds
-Specify maximum time (in seconds) that the client should wait for the
-duplicate address detection (DAD) to complete on an interface. This
-value is propagated to the dhclient script in a dad_wait_time environment
-variable. If any of the IPv6 addresses on the interface are tentative
-(DAD is in progress), the script will wait for the specified number of
-seconds for DAD to complete. If the script ignores this variable the
-parameter has no effect.
-.PP
-.TP
-.BI \--prefix-len-hint \ length
-When used in conjunction with -P, it directs the client to use the given
-length to use a prefix hint of, "::/length", when requesting new prefixes.
-.PP
-.I Modifying default file locations:
-The following options can be used to modify the locations a client uses
-for its files. They can be particularly useful if, for example,
-.B DBDIR
-or
-.B RUNDIR
-have not been mounted when the DHCP client is started.
-.TP
-.BI \-cf \ config-file
-Path to the client configuration file. If unspecified, the default
-.B ETCDIR/dhclient.conf
-is used. See \fBdhclient.conf(5)\fR for a description of this file.
-.TP
-.BI \-df \ duid-lease-file
-Path to a secondary lease file. If the primary lease file doesn't contain
-a DUID this file will be searched. The DUID read from the secondary will
-be written to the primary. This option can be used to allow an IPv4 instance
-of the client to share a DUID with an IPv6 instance. After starting one of
-the instances the second can be started with this option pointing to the
-lease file of the first instance. There is no default. If no file is
-specified no search is made for a DUID should one not be found in the main
-lease file.
-.TP
-.BI \-lf \ lease-file
-Path to the lease database file. If unspecified, the default
-.B DBDIR/dhclient.leases
-is used. See \fBdhclient.leases(5)\fR for a description of this file.
-.TP
-.BI \-pf \ pid-file
-Path to the process ID file. If unspecified, the default
-.B RUNDIR/dhclient.pid
-is used.
-.TP
-.BI \--no-pid
-Option to disable writing pid files. By default the program
-will write a pid file. If the program is invoked with this
-option it will not attempt to kill any existing client processes
-even if invoked with \fB-r\fR or \fB-x\fR.
-.TP
-.BI \-sf \ script-file
-Path to the network configuration script invoked by
-.B dhclient
-when it gets a lease. If unspecified, the default
-.B CLIENTBINDIR/dhclient-script
-is used. See \fBdhclient-script(8)\fR for a description of this file.
-.PP
-.SH PORTS
-During operations the client may use multiple UDP ports
-to provide different functions. Which ports are opened depends
-on both the way you compiled your code and the configuration you
-supply. The following should provide you an idea of what
-ports may be in use.
-
-Normally a DHCPv4 client will open a raw UDP socket to receive
-and send most DHCPv4 packets. It also opens a fallback UDP socket
-for use in sending unicast packets. Normally these will both
-use the well known port number for BOOTPC.
-
-For DHCPv6 the client opens a UDP socket on the well known
-client port and a fallback UDP socket on a random port for
-use in sending unicast messages. Unlike DHCPv4 the well
-known socket doesn't need to be opened in raw mode.
-
-If you have included an omapi port statement in your configuration
-file then the client will open a TCP socket on that port to
-listen for OMPAI connections. When something connects another
-port will be used for the established connection.
-
-When DDNS is enabled at compile time (see includes/site.h)
-the client will open both a v4 and a v6 UDP socket on
-random ports. These ports are not opened unless/until the
-client first attempts to do an update. If the client is not
-configured to do updates, the ports will never be opened.
-.PP
-.SH CONFIGURATION
-The syntax of the \fBdhclient.conf(5)\fR file is discussed separately.
-.SH OMAPI
-The DHCP client provides some ability to control it while it is
-running, without stopping it. This capability is provided using OMAPI,
-an API for manipulating remote objects. OMAPI clients connect to the
-client using TCP/IP, authenticate, and can then examine the client's
-current status and make changes to it.
-.PP
-Rather than implementing the underlying OMAPI protocol directly, user
-programs should use the dhcpctl API or OMAPI itself. Dhcpctl is a
-wrapper that handles some of the housekeeping chores that OMAPI does
-not do automatically. Dhcpctl and OMAPI are documented in
-\fBdhcpctl(3)\fR
-and \fBomapi(3)\fR. Most things you'd want to do with the client can
-be done directly using the \fBomshell(1)\fR command, rather than
-having to write a special program.
-.SH THE CONTROL OBJECT
-The control object allows you to shut the client down, releasing all
-leases that it holds and deleting any DNS records it may have added.
-It also allows you to pause the client - this unconfigures any
-interfaces the client is using. You can then restart it, which
-causes it to reconfigure those interfaces. You would normally pause
-the client prior to going into hibernation or sleep on a laptop
-computer. You would then resume it after the power comes back.
-This allows PC cards to be shut down while the computer is hibernating
-or sleeping, and then reinitialized to their previous state once the
-computer comes out of hibernation or sleep.
-.PP
-The control object has one attribute - the state attribute. To shut
-the client down, set its state attribute to 2. It will automatically
-do a DHCPRELEASE. To pause it, set its state attribute to 3. To
-resume it, set its state attribute to 4.
-.PP
-.SH ENVIRONMENT VARIABLES
-.PP
-The following environment variables may be defined
-to override the builtin defaults for file locations.
-Note that use of the related command-line options
-will ignore the corresponding environment variable settings.
-.TP
-.B PATH_DHCLIENT_CONF
-The dhclient.conf configuration file.
-.TP
-.B PATH_DHCLIENT_DB
-The dhclient.leases database.
-.TP
-.B PATH_DHCLIENT_PID
-The dhclient PID file.
-.TP
-.B PATH_DHCLIENT_SCRIPT
-The dhclient-script file.
-.PP
-.SH FILES
-.B CLIENTBINDIR/dhclient-script,
-.B ETCDIR/dhclient.conf, DBDIR/dhclient.leases, RUNDIR/dhclient.pid,
-.B DBDIR/dhclient.leases~.
-.SH SEE ALSO
-dhcpd(8), dhcrelay(8), dhclient-script(8), dhclient.conf(5),
-dhclient.leases(5), dhcp-eval(5).
-.SH AUTHOR
-.B dhclient(8)
-To learn more about Internet Systems Consortium,
-see
-.B https://www.isc.org
-.PP
-This client was substantially modified and enhanced by Elliot Poger
-for use on Linux while he was working on the MosquitoNet project at
-Stanford.
-.PP
-The current version owes much to Elliot's Linux enhancements, but
-was substantially reorganized and partially rewritten by Ted Lemon
-so as to use the same networking framework that the Internet Systems
-Consortium DHCP server uses. Much system-specific configuration code
-was moved into a shell script so that as support for more operating
-systems is added, it will not be necessary to port and maintain
-system-specific configuration code to these operating systems - instead,
-the shell script can invoke the native tools to accomplish the same
-purpose.
-.PP
diff --git a/client/dhclient.c b/client/dhclient.c
deleted file mode 100644
index 46dc3a71..00000000
--- a/client/dhclient.c
+++ /dev/null
@@ -1,5890 +0,0 @@
-/* dhclient.c
-
- DHCP Client. */
-
-/*
- * Copyright (c) 2004-2022 by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 1995-2003 by Internet Software Consortium
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * 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.
- * PO Box 360
- * Newmarket, NH 03857 USA
- * <info@isc.org>
- * https://www.isc.org/
- *
- * This code is based on the original client state machine that was
- * written by Elliot Poger. The code has been extensively hacked on
- * by Ted Lemon since then, so any mistakes you find are probably his
- * fault and not Elliot's.
- */
-
-#include "dhcpd.h"
-#include <isc/util.h>
-#include <isc/file.h>
-#include <dns/result.h>
-#include <syslog.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <limits.h>
-
-TIME default_lease_time = 43200; /* 12 hours... */
-TIME max_lease_time = 86400; /* 24 hours... */
-
-const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
-const char *path_dhclient_db = NULL;
-const char *path_dhclient_pid = NULL;
-static char path_dhclient_script_array[] = _PATH_DHCLIENT_SCRIPT;
-char *path_dhclient_script = path_dhclient_script_array;
-const char *path_dhclient_duid = NULL;
-
-static void add_to_tail(struct client_lease** lease_list, struct client_lease* lease);
-
-/* False (default) => we write and use a pid file */
-isc_boolean_t no_pid_file = ISC_FALSE;
-
-int dhcp_max_agent_option_packet_length = 0;
-
-int interfaces_requested = 0;
-
-struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
-struct iaddr iaddr_any = { 4, { 0, 0, 0, 0 } };
-struct in_addr inaddr_any;
-struct sockaddr_in sockaddr_broadcast;
-struct in_addr giaddr;
-struct data_string default_duid;
-int duid_type = 0;
-int duid_v4 = 0;
-int std_dhcid = 0;
-
-int decline_wait_time = 10; /* Default to 10 secs per, RFC 2131, 3.1.5 */
-
-/* ASSERT_STATE() does nothing now; it used to be
- assert (state_is == state_shouldbe). */
-#define ASSERT_STATE(state_is, state_shouldbe) {}
-
-#ifndef UNIT_TEST
-static const char copyright[] = "Copyright 2004-2022 Internet Systems Consortium.";
-static const char arr [] = "All rights reserved.";
-static const char message [] = "Internet Systems Consortium DHCP Client";
-static const char url [] = "For info, please visit https://www.isc.org/software/dhcp/";
-#endif /* UNIT_TEST */
-
-extern u_int16_t local_port;
-extern u_int16_t remote_port;
-
-#if defined(DHCPv6) && defined(DHCP4o6)
-int dhcp4o6_state = -1; /* -1 = stopped, 0 = polling, 1 = started */
-#endif
-int no_daemon = 0;
-int dfd[2] = { -1, -1 };
-struct string_list *client_env = NULL;
-int client_env_count = 0;
-int onetry = 0;
-int quiet = 1;
-int nowait = 0;
-int stateless = 0;
-int wanted_ia_na = -1; /* the absolute value is the real one. */
-int wanted_ia_ta = 0;
-int wanted_ia_pd = 0;
-int require_all_ias = 0; /* If the user requires all of the IAs to
- be available before accepting a lease
- 0 = no, 1 = requries */
-#if defined(DHCPv6)
-int dad_wait_time = 0;
-int prefix_len_hint = 0;
-#endif
-
-int address_prefix_len = DHCLIENT_DEFAULT_PREFIX_LEN;
-char *mockup_relay = NULL;
-
-char *progname = NULL;
-
-void run_stateless(int exit_mode, u_int16_t port);
-
-static isc_result_t write_duid(struct data_string *duid);
-static void add_reject(struct packet *packet);
-
-static int check_domain_name(const char *ptr, size_t len, int dots);
-static int check_domain_name_list(const char *ptr, size_t len, int dots);
-static int check_option_values(struct universe *universe, unsigned int opt,
- const char *ptr, size_t len);
-
-#if defined(NSUPDATE)
-static void dhclient_ddns_cb_free(dhcp_ddns_cb_t *ddns_cb,
- char* file, int line);
-#endif /* defined NSUPDATE */
-
-
-/*!
- *
- * \brief Print the generic usage message
- *
- * If the user has provided an incorrect command line print out
- * the description of the command line. The arguments provide
- * a way for the caller to request more specific information about
- * the error be printed as well. Mostly this will be that some
- * command doesn't include its argument.
- *
- * \param sfmt - The basic string and format for the specific error
- * \param sarg - Generally the offending argument from the command line.
- *
- * \return Nothing
- */
-
-#if defined(DHCPv6) && defined(DHCP4o6)
-static void dhcp4o6_poll(void *dummy);
-static void dhcp4o6_resume(void);
-static void recv_dhcpv4_response(struct data_string *raw);
-static int send_dhcpv4_query(struct client_state *client, int broadcast);
-
-static void dhcp4o6_stop(void);
-static void forw_dhcpv4_response(struct packet *packet);
-static void forw_dhcpv4_query(struct data_string *raw);
-#endif
-
-#ifndef UNIT_TEST
-/* These are only used when we call usage() from the main routine
- * which isn't compiled when building for unit tests
- */
-static const char use_noarg[] = "No argument for command: %s";
-#ifdef DHCPv6
-static const char use_v6command[] = "Command not used for DHCPv4: %s";
-#endif
-
-#ifdef DHCPv6
-#ifdef DHCP4o6
-#define DHCLIENT_USAGE0 \
-"[-4|-6] [-SNTPRI1dvrxi] [-nw] -4o6 <port>] [-p <port>] [-D LL|LLT]\n" \
-" [--dad-wait-time <seconds>] [--prefix-len-hint <length>]\n" \
-" [--decline-wait-time <seconds>]\n" \
-" [--address-prefix-len <length>]\n"
-#else /* DHCP4o6 */
-#define DHCLIENT_USAGE0 \
-"[-4|-6] [-SNTPRI1dvrxi] [-nw] [-p <port>] [-D LL|LLT]\n" \
-" [--dad-wait-time <seconds>] [--prefix-len-hint <length>]\n" \
-" [--decline-wait-time <seconds>]\n" \
-" [--address-prefix-len <length>]\n"
-#endif
-#else /* DHCPv6 */
-#define DHCLIENT_USAGE0 \
-"[-I1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n" \
-" [--decline-wait-time <seconds>]\n"
-#endif
-
-#define DHCLIENT_USAGEC \
-" [-s server-addr] [-cf config-file]\n" \
-" [-df duid-file] [-lf lease-file]\n" \
-" [-pf pid-file] [--no-pid] [-e VAR=val]\n" \
-" [-sf script-file] [interface]*"
-
-#define DHCLIENT_USAGEH "{--version|--help|-h}"
-
-static void
-usage(const char *sfmt, const char *sarg)
-{
- log_info("%s %s", message, PACKAGE_VERSION);
- log_info(copyright);
- log_info(arr);
- log_info(url);
-
- /* If desired print out the specific error message */
-#ifdef PRINT_SPECIFIC_CL_ERRORS
- if (sfmt != NULL)
- log_error(sfmt, sarg);
-#endif
-
- log_fatal("Usage: %s %s%s\n %s %s",
- isc_file_basename(progname),
- DHCLIENT_USAGE0,
- DHCLIENT_USAGEC,
- isc_file_basename(progname),
- DHCLIENT_USAGEH);
-}
-
-extern void initialize_client_option_spaces();
-
-int
-main(int argc, char **argv) {
- int fd;
- int i;
- struct interface_info *ip;
- struct client_state *client;
- unsigned seed;
- char *server = NULL;
- isc_result_t status;
- int exit_mode = 0;
- int release_mode = 0;
- struct timeval tv;
- omapi_object_t *listener;
- isc_result_t result;
- int persist = 0;
- int no_dhclient_conf = 0;
- int no_dhclient_db = 0;
- int no_dhclient_pid = 0;
- int no_dhclient_script = 0;
-#ifdef DHCPv6
- int local_family_set = 0;
-#ifdef DHCP4o6
- u_int16_t dhcp4o6_port = 0;
-#endif /* DHCP4o6 */
-#endif /* DHCPv6 */
- char *s;
-
-#ifdef OLD_LOG_NAME
- progname = "dhclient";
-#else
- progname = argv[0];
-#endif
- /* Initialize client globals. */
- memset(&default_duid, 0, sizeof(default_duid));
-
- /* Make sure that file descriptors 0 (stdin), 1, (stdout), and
- 2 (stderr) are open. To do this, we assume that when we
- open a file the lowest available file descriptor is used. */
- fd = open("/dev/null", O_RDWR);
- if (fd == 0)
- fd = open("/dev/null", O_RDWR);
- if (fd == 1)
- fd = open("/dev/null", O_RDWR);
- if (fd == 2)
- log_perror = 0; /* No sense logging to /dev/null. */
- else if (fd != -1)
- close(fd);
-
- openlog(isc_file_basename(progname), DHCP_LOG_OPTIONS, LOG_DAEMON);
-
-#if !(defined(DEBUG) || defined(__CYGWIN32__))
- setlogmask(LOG_UPTO(LOG_INFO));
-#endif
-
- /* Parse arguments changing no_daemon */
- for (i = 1; i < argc; i++) {
- if (!strcmp(argv[i], "-r")) {
- no_daemon = 1;
- } else if (!strcmp(argv[i], "-x")) {
- no_daemon = 0;
- } else if (!strcmp(argv[i], "-d")) {
- no_daemon = 1;
- } else if (!strcmp(argv[i], "--version")) {
- const char vstring[] = "isc-dhclient-";
- IGNORE_RET(write(STDERR_FILENO, vstring,
- strlen(vstring)));
- IGNORE_RET(write(STDERR_FILENO,
- PACKAGE_VERSION,
- strlen(PACKAGE_VERSION)));
- IGNORE_RET(write(STDERR_FILENO, "\n", 1));
- exit(0);
- } else if (!strcmp(argv[i], "--help") ||
- !strcmp(argv[i], "-h")) {
- const char *pname = isc_file_basename(progname);
- IGNORE_RET(write(STDERR_FILENO, "Usage: ", 7));
- IGNORE_RET(write(STDERR_FILENO, pname, strlen(pname)));
- IGNORE_RET(write(STDERR_FILENO, " ", 1));
- IGNORE_RET(write(STDERR_FILENO, DHCLIENT_USAGE0,
- strlen(DHCLIENT_USAGE0)));
- IGNORE_RET(write(STDERR_FILENO, DHCLIENT_USAGEC,
- strlen(DHCLIENT_USAGEC)));
- IGNORE_RET(write(STDERR_FILENO, "\n", 1));
- IGNORE_RET(write(STDERR_FILENO, " ", 7));
- IGNORE_RET(write(STDERR_FILENO, pname, strlen(pname)));
- IGNORE_RET(write(STDERR_FILENO, " ", 1));
- IGNORE_RET(write(STDERR_FILENO, DHCLIENT_USAGEH,
- strlen(DHCLIENT_USAGEH)));
- IGNORE_RET(write(STDERR_FILENO, "\n", 1));
- exit(0);
- }
- }
- /* When not forbidden prepare to become a daemon */
- if (!no_daemon) {
- int pid;
-
- if (pipe(dfd) == -1)
- log_fatal("Can't get pipe: %m");
- if ((pid = fork ()) < 0)
- log_fatal("Can't fork daemon: %m");
- if (pid != 0) {
- /* Parent: wait for the child to start */
- int n;
-
- (void) close(dfd[1]);
- do {
- char buf;
-
- n = read(dfd[0], &buf, 1);
- if (n == 1)
- _exit((int)buf);
- } while (n == -1 && errno == EINTR);
- _exit(1);
- }
- /* Child */
- (void) close(dfd[0]);
- }
-
- /* Set up the isc and dns library managers */
- status = dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB
- | DHCP_DNS_CLIENT_LAZY_INIT, NULL, NULL);
- if (status != ISC_R_SUCCESS)
- log_fatal("Can't initialize context: %s",
- isc_result_totext(status));
-
- /* Set up the OMAPI. */
- status = omapi_init();
- if (status != ISC_R_SUCCESS)
- log_fatal("Can't initialize OMAPI: %s",
- isc_result_totext(status));
-
- /* Set up the OMAPI wrappers for various server database internal
- objects. */
- dhcp_common_objects_setup();
-
- dhcp_interface_discovery_hook = dhclient_interface_discovery_hook;
- dhcp_interface_shutdown_hook = dhclient_interface_shutdown_hook;
- dhcp_interface_startup_hook = dhclient_interface_startup_hook;
-
- for (i = 1; i < argc; i++) {
- if (!strcmp(argv[i], "-r")) {
- release_mode = 1;
- /* no_daemon = 1; */
-#ifdef DHCPv6
- } else if (!strcmp(argv[i], "-4")) {
- if (local_family_set && local_family != AF_INET)
- log_fatal("Client can only do v4 or v6, not "
- "both.");
- local_family_set = 1;
- local_family = AF_INET;
- } else if (!strcmp(argv[i], "-6")) {
- if (local_family_set && local_family != AF_INET6)
- log_fatal("Client can only do v4 or v6, not "
- "both.");
- local_family_set = 1;
- local_family = AF_INET6;
-#ifdef DHCP4o6
- } else if (!strcmp(argv[i], "-4o6")) {
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
- dhcp4o6_port = validate_port_pair(argv[i]);
-
- log_debug("DHCPv4 over DHCPv6 over ::1 port %d and %d",
- ntohs(dhcp4o6_port),
- ntohs(dhcp4o6_port) + 1);
- dhcpv4_over_dhcpv6 = 1;
-#endif /* DHCP4o6 */
-#endif /* DHCPv6 */
- } else if (!strcmp(argv[i], "-x")) { /* eXit, no release */
- release_mode = 0;
- /* no_daemon = 0; */
- exit_mode = 1;
- } else if (!strcmp(argv[i], "-p")) {
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
- local_port = validate_port(argv[i]);
- log_debug("binding to user-specified port %d",
- ntohs(local_port));
- } else if (!strcmp(argv[i], "-d")) {
- /* no_daemon = 1; */
- quiet = 0;
- } else if (!strcmp(argv[i], "-pf")) {
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
- path_dhclient_pid = argv[i];
- no_dhclient_pid = 1;
- } else if (!strcmp(argv[i], "--no-pid")) {
- no_pid_file = ISC_TRUE;
- } else if (!strcmp(argv[i], "-cf")) {
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
- path_dhclient_conf = argv[i];
- no_dhclient_conf = 1;
- } else if (!strcmp(argv[i], "-df")) {
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
- path_dhclient_duid = argv[i];
- } else if (!strcmp(argv[i], "-lf")) {
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
- path_dhclient_db = argv[i];
- no_dhclient_db = 1;
- } else if (!strcmp(argv[i], "-sf")) {
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
- path_dhclient_script = argv[i];
- no_dhclient_script = 1;
- } else if (!strcmp(argv[i], "-1")) {
- onetry = 1;
- } else if (!strcmp(argv[i], "-q")) {
- quiet = 1;
- } else if (!strcmp(argv[i], "-s")) {
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
- server = argv[i];
- } else if (!strcmp(argv[i], "-g")) {
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
- mockup_relay = argv[i];
- } else if (!strcmp(argv[i], "-nw")) {
- nowait = 1;
- } else if (!strcmp(argv[i], "-n")) {
- /* do not start up any interfaces */
- interfaces_requested = -1;
- } else if (!strcmp(argv[i], "-w")) {
- /* do not exit if there are no broadcast interfaces. */
- persist = 1;
- } else if (!strcmp(argv[i], "-e")) {
- struct string_list *tmp;
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
- tmp = dmalloc(strlen(argv[i]) + sizeof *tmp, MDL);
- if (!tmp)
- log_fatal("No memory for %s", argv[i]);
- strcpy(tmp->string, argv[i]);
- tmp->next = client_env;
- client_env = tmp;
- client_env_count++;
-#ifdef DHCPv6
- } else if (!strcmp(argv[i], "-S")) {
- if (local_family_set && (local_family == AF_INET)) {
- usage(use_v6command, argv[i]);
- }
- local_family_set = 1;
- local_family = AF_INET6;
- wanted_ia_na = 0;
- stateless = 1;
- } else if (!strcmp(argv[i], "-N")) {
- if (local_family_set && (local_family == AF_INET)) {
- usage(use_v6command, argv[i]);
- }
- local_family_set = 1;
- local_family = AF_INET6;
- if (wanted_ia_na < 0) {
- wanted_ia_na = 0;
- }
- wanted_ia_na++;
- } else if (!strcmp(argv[i], "-T")) {
- if (local_family_set && (local_family == AF_INET)) {
- usage(use_v6command, argv[i]);
- }
- local_family_set = 1;
- local_family = AF_INET6;
- if (wanted_ia_na < 0) {
- wanted_ia_na = 0;
- }
- wanted_ia_ta++;
- } else if (!strcmp(argv[i], "-P")) {
- if (local_family_set && (local_family == AF_INET)) {
- usage(use_v6command, argv[i]);
- }
- local_family_set = 1;
- local_family = AF_INET6;
- if (wanted_ia_na < 0) {
- wanted_ia_na = 0;
- }
- wanted_ia_pd++;
- } else if (!strcmp(argv[i], "-R")) {
- if (local_family_set && (local_family == AF_INET)) {
- usage(use_v6command, argv[i]);
- }
- local_family_set = 1;
- local_family = AF_INET6;
- require_all_ias = 1;
- } else if (!strcmp(argv[i], "--dad-wait-time")) {
- if (++i == argc) {
- usage(use_noarg, argv[i-1]);
- }
- errno = 0;
- dad_wait_time = (int)strtol(argv[i], &s, 10);
- if (errno || (*s != '\0') || (dad_wait_time < 0)) {
- usage("Invalid value for --dad-wait-time: %s",
- argv[i]);
- }
- } else if (!strcmp(argv[i], "--prefix-len-hint")) {
- if (++i == argc) {
- usage(use_noarg, argv[i-1]);
- }
-
- errno = 0;
- prefix_len_hint = (int)strtol(argv[i], &s, 10);
- if (errno || (*s != '\0') || (prefix_len_hint < 0)) {
- usage("Invalid value for --prefix-len-hint: %s",
- argv[i]);
- }
- } else if (!strcmp(argv[i], "--address-prefix-len")) {
- if (++i == argc) {
- usage(use_noarg, argv[i-1]);
- }
- errno = 0;
- address_prefix_len = (int)strtol(argv[i], &s, 10);
- if (errno || (*s != '\0') ||
- (address_prefix_len < 0)) {
- usage("Invalid value for"
- " --address-prefix-len: %s", argv[i]);
- }
-#endif /* DHCPv6 */
- } else if (!strcmp(argv[i], "--decline-wait-time")) {
- if (++i == argc) {
- usage(use_noarg, argv[i-1]);
- }
-
- errno = 0;
- decline_wait_time = (int)strtol(argv[i], &s, 10);
- if (errno || (*s != '\0') ||
- (decline_wait_time < 0)) {
- usage("Invalid value for "
- "--decline-wait-time: %s", argv[i]);
- }
- } else if (!strcmp(argv[i], "-D")) {
- duid_v4 = 1;
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
- if (!strcasecmp(argv[i], "LL")) {
- duid_type = DUID_LL;
- } else if (!strcasecmp(argv[i], "LLT")) {
- duid_type = DUID_LLT;
- } else {
- usage("Unknown argument to -D: %s", argv[i]);
- }
- } else if (!strcmp(argv[i], "-i")) {
- /* enable DUID support for DHCPv4 clients */
- duid_v4 = 1;
- } else if (!strcmp(argv[i], "-I")) {
- /* enable standard DHCID support for DDNS updates */
- std_dhcid = 1;
- } else if (!strcmp(argv[i], "-v")) {
- quiet = 0;
- } else if (argv[i][0] == '-') {
- usage("Unknown command: %s", argv[i]);
- } else if (interfaces_requested < 0) {
- usage("No interfaces command -n and "
- " requested interface %s", argv[i]);
- } else {
- struct interface_info *tmp = NULL;
-
- status = interface_allocate(&tmp, MDL);
- if (status != ISC_R_SUCCESS)
- log_fatal("Can't record interface %s:%s",
- argv[i], isc_result_totext(status));
- if (strlen(argv[i]) >= sizeof(tmp->name))
- log_fatal("%s: interface name too long (is %ld)",
- argv[i], (long)strlen(argv[i]));
- strcpy(tmp->name, argv[i]);
- if (interfaces) {
- interface_reference(&tmp->next,
- interfaces, MDL);
- interface_dereference(&interfaces, MDL);
- }
- interface_reference(&interfaces, tmp, MDL);
- tmp->flags = INTERFACE_REQUESTED;
- interfaces_requested++;
- }
- }
-
- if (wanted_ia_na < 0) {
- wanted_ia_na = 1;
- }
-
- /* Support only one (requested) interface for Prefix Delegation. */
- if (wanted_ia_pd && (interfaces_requested != 1)) {
- usage("PD %s only supports one requested interface", "-P");
- }
-
-#if defined(DHCPv6) && defined(DHCP4o6)
- if ((local_family == AF_INET6) && dhcpv4_over_dhcpv6 &&
- (exit_mode || release_mode))
- log_error("Can't relay DHCPv4-over-DHCPv6 "
- "without a persistent DHCPv6 client");
- if ((local_family == AF_INET) && dhcpv4_over_dhcpv6 &&
- (interfaces_requested != 1))
- log_fatal("DHCPv4-over-DHCPv6 requires an explicit "
- "interface on which to be applied");
-#endif
-
- if (!no_dhclient_conf && (s = getenv("PATH_DHCLIENT_CONF"))) {
- path_dhclient_conf = s;
- }
- if (!no_dhclient_db && (s = getenv("PATH_DHCLIENT_DB"))) {
- path_dhclient_db = s;
- }
- if (!no_dhclient_pid && (s = getenv("PATH_DHCLIENT_PID"))) {
- path_dhclient_pid = s;
- }
- if (!no_dhclient_script && (s = getenv("PATH_DHCLIENT_SCRIPT"))) {
- path_dhclient_script = s;
- }
-
- /* Set up the initial dhcp option universe. */
- initialize_common_option_spaces();
-
- /* Set up the initial client option universe. */
- initialize_client_option_spaces();
-
- /* Assign v4 or v6 specific running parameters. */
- if (local_family == AF_INET)
- dhcpv4_client_assignments();
-#ifdef DHCPv6
- else if (local_family == AF_INET6)
- dhcpv6_client_assignments();
-#endif /* DHCPv6 */
- else
- log_fatal("Impossible condition at %s:%d.", MDL);
-
- /*
- * convert relative path names to absolute, for files that need
- * to be reopened after chdir() has been called
- */
- if (path_dhclient_db[0] != '/') {
- path_dhclient_db = absolute_path(path_dhclient_db);
- }
-
- if (path_dhclient_script[0] != '/') {
- path_dhclient_script = absolute_path(path_dhclient_script);
- }
-
- /*
- * See if we should kill off any currently running client
- * we don't try to kill it off if the user told us not
- * to write a pid file - we assume they are controlling
- * the process in some other fashion.
- */
- if ((release_mode || exit_mode) && (no_pid_file == ISC_FALSE)) {
- FILE *pidfd;
- pid_t oldpid;
- long temp;
- int e;
-
- if ((pidfd = fopen(path_dhclient_pid, "r")) != NULL) {
- e = fscanf(pidfd, "%ld\n", &temp);
- oldpid = (pid_t)temp;
-
- if (e != 0 && e != EOF && oldpid) {
- if (kill(oldpid, SIGTERM) == 0) {
- log_info("Killed old client process");
- (void) unlink(path_dhclient_pid);
- /*
- * wait for the old process to
- * cleanly terminate.
- * Note kill() with sig=0 could
- * detect termination but only
- * the parent can be signaled...
- */
- sleep(1);
- } else if (errno == ESRCH) {
- log_info("Removed stale PID file");
- (void) unlink(path_dhclient_pid);
- }
- }
- fclose(pidfd);
- }
- }
-
- if (!quiet) {
- log_info("%s %s", message, PACKAGE_VERSION);
- log_info(copyright);
- log_info(arr);
- log_info(url);
- log_info("%s", "");
- } else {
- log_perror = 0;
- quiet_interface_discovery = 1;
- }
-
- /* If we're given a relay agent address to insert, for testing
- purposes, figure out what it is. */
- if (mockup_relay) {
- if (!inet_aton(mockup_relay, &giaddr)) {
- struct hostent *he;
- he = gethostbyname(mockup_relay);
- if (he) {
- memcpy(&giaddr, he->h_addr_list[0],
- sizeof giaddr);
- } else {
- log_fatal("%s: no such host", mockup_relay);
- }
- }
- }
-
- /* Get the current time... */
- gettimeofday(&cur_tv, NULL);
-
- sockaddr_broadcast.sin_family = AF_INET;
- sockaddr_broadcast.sin_port = remote_port;
- if (server) {
- if (!inet_aton(server, &sockaddr_broadcast.sin_addr)) {
- struct hostent *he;
- he = gethostbyname(server);
- if (he) {
- memcpy(&sockaddr_broadcast.sin_addr,
- he->h_addr_list[0],
- sizeof sockaddr_broadcast.sin_addr);
- } else
- sockaddr_broadcast.sin_addr.s_addr =
- INADDR_BROADCAST;
- }
- } else {
- sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
- }
-
- inaddr_any.s_addr = INADDR_ANY;
-
- /* Stateless special case. */
- if (stateless) {
- if (release_mode || (wanted_ia_na > 0) ||
- wanted_ia_ta || wanted_ia_pd ||
- (interfaces_requested != 1)) {
- usage("Stateless command: %s incompatibile with "
- "other commands", "-S");
- }
-#if defined(DHCPv6) && defined(DHCP4o6)
- run_stateless(exit_mode, dhcp4o6_port);
-#else
- run_stateless(exit_mode, 0);
-#endif
- finish(0);
- }
-
- /* Discover all the network interfaces. */
- discover_interfaces(DISCOVER_UNCONFIGURED);
-
- /* Parse the dhclient.conf file. */
- read_client_conf();
-
- /* Parse the lease database. */
- read_client_leases();
-
- /* If desired parse the secondary lease database for a DUID */
- if ((default_duid.len == 0) && (path_dhclient_duid != NULL)) {
- read_client_duid();
- }
-
- /* Rewrite the lease database... */
- rewrite_client_leases();
-
- /* XXX */
-/* config_counter(&snd_counter, &rcv_counter); */
-
- /*
- * If no broadcast interfaces were discovered, call the script
- * and tell it so.
- */
- if (!interfaces) {
- /*
- * Call dhclient-script with the NBI flag,
- * in case somebody cares.
- */
- script_init(NULL, "NBI", NULL);
- script_go(NULL);
-
- /*
- * If we haven't been asked to persist, waiting for new
- * interfaces, then just exit.
- */
- if (!persist) {
- /* Nothing more to do. */
- log_info("No broadcast interfaces found - exiting.");
- finish(0);
- }
- } else if (!release_mode && !exit_mode) {
- /* Call the script with the list of interfaces. */
- for (ip = interfaces; ip; ip = ip->next) {
- /*
- * If interfaces were specified, don't configure
- * interfaces that weren't specified!
- */
- if ((interfaces_requested > 0) &&
- ((ip->flags & (INTERFACE_REQUESTED |
- INTERFACE_AUTOMATIC)) !=
- INTERFACE_REQUESTED))
- continue;
-
- if (local_family == AF_INET6) {
- script_init(ip->client, "PREINIT6", NULL);
- } else {
- script_init(ip->client, "PREINIT", NULL);
- if (ip->client->alias != NULL)
- script_write_params(ip->client,
- "alias_",
- ip->client->alias);
- }
- script_go(ip->client);
- }
- }
-
- /* At this point, all the interfaces that the script thinks
- are relevant should be running, so now we once again call
- discover_interfaces(), and this time ask it to actually set
- up the interfaces. */
- discover_interfaces(interfaces_requested != 0
- ? DISCOVER_REQUESTED
- : DISCOVER_RUNNING);
-
- /* PLEASE PREFER the random device: not all systems use random
- * process identifiers so the alternative can be predictable. */
- seed = 0;
- size_t nrnd = 0;
-#ifdef ISC_PATH_RANDOMDEV
- FILE *frnd = fopen(ISC_PATH_RANDOMDEV, "r");
- if (frnd) {
- nrnd = fread(&seed, sizeof(seed), 1, frnd);
- fclose(frnd);
- }
-#endif
- /* Please leave the compiler to emit a warning about a constant
- * condition in the if test. */
- if (!nrnd) {
- /* Make up a seed for the random number generator from current
- time plus the sum of the last four bytes of each
- interface's hardware address interpreted as an integer.
- Not much entropy, but we're booting, so we're not likely to
- find anything better. */
-
- for (ip = interfaces; ip; ip = ip->next) {
- int junk;
- memcpy(&junk,
- &ip->hw_address.hbuf[ip->hw_address.hlen -
- sizeof seed], sizeof seed);
- seed += junk;
- }
- seed += cur_time + (unsigned)getpid();
- }
- srandom(seed);
-
- /*
- * Establish a default DUID. We always do so for v6 and
- * do so if desired for v4 via the -D or -i options
- */
- if ((local_family == AF_INET6) ||
- ((local_family == AF_INET) && (duid_v4 == 1))) {
- if (default_duid.len == 0) {
- if (default_duid.buffer != NULL)
- data_string_forget(&default_duid, MDL);
-
- form_duid(&default_duid, MDL);
- write_duid(&default_duid);
- }
- }
-
-#if defined(DHCPv6) && defined(DHCP4o6)
- if (dhcpv4_over_dhcpv6 && !exit_mode)
- dhcp4o6_setup(dhcp4o6_port);
-#endif
-
- /* Start a configuration state machine for each interface. */
-#ifdef DHCPv6
- if (local_family == AF_INET6) {
- for (ip = interfaces ; ip != NULL ; ip = ip->next) {
- for (client = ip->client ; client != NULL ;
- client = client->next) {
- if (release_mode) {
- start_release6(client);
- continue;
- } else if (exit_mode) {
- unconfigure6(client, "STOP6");
- continue;
- }
-
- /* If we have a previous binding, Confirm
- * that we can (or can't) still use it.
- */
- if ((client->active_lease != NULL) &&
- !client->active_lease->released)
- start_confirm6(client);
- else
- start_init6(client);
- }
- }
- } else
-#endif /* DHCPv6 */
- {
- for (ip = interfaces ; ip ; ip = ip->next) {
- ip->flags |= INTERFACE_RUNNING;
- for (client = ip->client ; client ;
- client = client->next) {
- if (exit_mode)
- state_stop(client);
- if (release_mode)
- do_release(client);
- else {
- client->state = S_INIT;
-
- if (top_level_config.initial_delay>0)
- {
- tv.tv_sec = 0;
- if (top_level_config.
- initial_delay>1)
- tv.tv_sec = cur_time
- + random()
- % (top_level_config.
- initial_delay-1);
- tv.tv_usec = random()
- % 1000000;
- /*
- * this gives better
- * distribution than just
- *whole seconds
- */
- add_timeout(&tv, state_reboot,
- client, 0, 0);
- } else {
- state_reboot(client);
- }
- }
- }
- }
- }
-
- if (exit_mode)
- finish(0);
- if (release_mode) {
-#ifndef DHCPv6
- finish(0);
-#else
- if ((local_family == AF_INET6) || dhcpv4_over_dhcpv6) {
- if (onetry)
- finish(0);
- } else
- finish(0);
-#endif /* DHCPv6 */
- }
-
- /* Start up a listener for the object management API protocol. */
- if (top_level_config.omapi_port != -1) {
- listener = NULL;
- result = omapi_generic_new(&listener, MDL);
- if (result != ISC_R_SUCCESS)
- log_fatal("Can't allocate new generic object: %s\n",
- isc_result_totext(result));
- result = omapi_protocol_listen(listener,
- (unsigned)
- top_level_config.omapi_port,
- 1);
- if (result != ISC_R_SUCCESS)
- log_fatal("Can't start OMAPI protocol: %s",
- isc_result_totext (result));
- }
-
- /* Set up the bootp packet handler... */
- bootp_packet_handler = do_packet;
-#ifdef DHCPv6
- dhcpv6_packet_handler = do_packet6;
-#endif /* DHCPv6 */
-
-#if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
- defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
- dmalloc_cutoff_generation = dmalloc_generation;
- dmalloc_longterm = dmalloc_outstanding;
- dmalloc_outstanding = 0;
-#endif
-
-#if defined(ENABLE_GENTLE_SHUTDOWN)
- /* no signal handlers until we deal with the side effects */
- /* install signal handlers */
- signal(SIGINT, dhcp_signal_handler); /* control-c */
- signal(SIGTERM, dhcp_signal_handler); /* kill */
-#endif
-
- /* If we're not supposed to wait before getting the address,
- don't. */
- if (nowait)
- detach();
-
- /* If we're not going to daemonize, write the pid file
- now. */
- if (no_daemon || nowait)
- write_client_pid_file();
-
- /* Start dispatching packets and timeouts... */
- dispatch();
-
- /* In fact dispatch() never returns. */
- return 0;
-}
-
-/*
- * \brief Run the DHCPv6 stateless client (dhclient -6 -S)
- *
- * \param exist_mode set to 1 when dhclient was called with -x
- * \param port DHCPv4-over-DHCPv6 client inter-process communication
- * UDP port pair (port,port+1 with port in network byte order)
- */
-
-void run_stateless(int exit_mode, u_int16_t port)
-{
-#ifdef DHCPv6
- struct client_state *client;
- omapi_object_t *listener;
- isc_result_t result;
-
-#ifndef DHCP4o6
- IGNORE_UNUSED(port);
-#endif
-
- /* Discover the network interface. */
- discover_interfaces(DISCOVER_REQUESTED);
-
- if (!interfaces)
- usage("No interfaces available for stateless command: %s", "-S");
-
- /* Parse the dhclient.conf file. */
-#ifdef DHCP4o6
- if (dhcpv4_over_dhcpv6) {
- /* Mark we want to request IRT too! */
- dhcpv4_over_dhcpv6++;
- }
-#endif
- read_client_conf();
-
- /* Parse the lease database. */
- read_client_leases();
-
- /* If desired parse the secondary lease database for a DUID */
- if ((default_duid.len == 0) && (path_dhclient_duid != NULL)) {
- read_client_duid();
- }
-
- /* Establish a default DUID. */
- if (default_duid.len == 0) {
- if (default_duid.buffer != NULL)
- data_string_forget(&default_duid, MDL);
-
- form_duid(&default_duid, MDL);
- }
-
-#ifdef DHCP4o6
- if (dhcpv4_over_dhcpv6 && !exit_mode)
- dhcp4o6_setup(port);
-#endif
-
- /* Start a configuration state machine. */
- for (client = interfaces->client ;
- client != NULL ;
- client = client->next) {
- if (exit_mode) {
- unconfigure6(client, "STOP6");
- continue;
- }
- start_info_request6(client);
- }
- if (exit_mode)
- return;
-
- /* Start up a listener for the object management API protocol. */
- if (top_level_config.omapi_port != -1) {
- listener = NULL;
- result = omapi_generic_new(&listener, MDL);
- if (result != ISC_R_SUCCESS)
- log_fatal("Can't allocate new generic object: %s\n",
- isc_result_totext(result));
- result = omapi_protocol_listen(listener,
- (unsigned)
- top_level_config.omapi_port,
- 1);
- if (result != ISC_R_SUCCESS)
- log_fatal("Can't start OMAPI protocol: %s",
- isc_result_totext(result));
- }
-
- /* Set up the packet handler... */
- dhcpv6_packet_handler = do_packet6;
-
-#if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
- defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
- dmalloc_cutoff_generation = dmalloc_generation;
- dmalloc_longterm = dmalloc_outstanding;
- dmalloc_outstanding = 0;
-#endif
-
- /* If we're not supposed to wait before getting the address,
- don't. */
- if (nowait)
- detach();
-
- /* If we're not going to daemonize, write the pid file
- now. */
- if (no_daemon || nowait)
- write_client_pid_file();
-
- /* Start dispatching packets and timeouts... */
- dispatch();
-
-#endif /* DHCPv6 */
- return;
-}
-#endif /* !UNIT_TEST */
-
-isc_result_t find_class (struct class **c,
- const char *s, const char *file, int line)
-{
- return 0;
-}
-
-int check_collection (packet, lease, collection)
- struct packet *packet;
- struct lease *lease;
- struct collection *collection;
-{
- return 0;
-}
-
-void classify (packet, class)
- struct packet *packet;
- struct class *class;
-{
-}
-
-void unbill_class (lease)
- struct lease *lease;
-{
-}
-
-int find_subnet (struct subnet **sp,
- struct iaddr addr, const char *file, int line)
-{
- return 0;
-}
-
-/* Individual States:
- *
- * Each routine is called from the dhclient_state_machine() in one of
- * these conditions:
- * -> entering INIT state
- * -> recvpacket_flag == 0: timeout in this state
- * -> otherwise: received a packet in this state
- *
- * Return conditions as handled by dhclient_state_machine():
- * Returns 1, sendpacket_flag = 1: send packet, reset timer.
- * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
- * Returns 0: finish the nap which was interrupted for no good reason.
- *
- * Several per-interface variables are used to keep track of the process:
- * active_lease: the lease that is being used on the interface
- * (null pointer if not configured yet).
- * offered_leases: leases corresponding to DHCPOFFER messages that have
- * been sent to us by DHCP servers.
- * acked_leases: leases corresponding to DHCPACK messages that have been
- * sent to us by DHCP servers.
- * sendpacket: DHCP packet we're trying to send.
- * destination: IP address to send sendpacket to
- * In addition, there are several relevant per-lease variables.
- * T1_expiry, T2_expiry, lease_expiry: lease milestones
- * In the active lease, these control the process of renewing the lease;
- * In leases on the acked_leases list, this simply determines when we
- * can no longer legitimately use the lease.
- */
-
-void state_reboot (cpp)
- void *cpp;
-{
- struct client_state *client = cpp;
-
-#if defined(DHCPv6) && defined(DHCP4o6)
- if (dhcpv4_over_dhcpv6 && (dhcp4o6_state <= 0)) {
- if (dhcp4o6_state < 0)
- dhcp4o6_poll(NULL);
- client->pending = P_REBOOT;
- return;
- }
-#endif
-
- client->pending= P_NONE;
-
- /* If we don't remember an active lease, go straight to INIT. */
- if (!client -> active ||
- client -> active -> is_bootp ||
- client -> active -> expiry <= cur_time) {
- state_init (client);
- return;
- }
-
- /* We are in the rebooting state. */
- client -> state = S_REBOOTING;
-
- /*
- * make_request doesn't initialize xid because it normally comes
- * from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
- * so pick an xid now.
- */
- client -> xid = random ();
-
- /*
- * Make a DHCPREQUEST packet, and set
- * appropriate per-interface flags.
- */
- make_request (client, client -> active);
- client -> destination = iaddr_broadcast;
- client -> first_sending = cur_time;
- client -> interval = client -> config -> initial_interval;
-
- /* Zap the medium list... */
- client -> medium = NULL;
-
- /* Send out the first DHCPREQUEST packet. */
- send_request (client);
-}
-
-/* Called when a lease has completely expired and we've been unable to
- renew it. */
-
-void state_init (cpp)
- void *cpp;
-{
- struct client_state *client = cpp;
-
- ASSERT_STATE(state, S_INIT);
-
- /* Make a DHCPDISCOVER packet, and set appropriate per-interface
- flags. */
- make_discover (client, client -> active);
- client -> xid = client -> packet.xid;
- client -> destination = iaddr_broadcast;
- client -> state = S_SELECTING;
- client -> first_sending = cur_time;
- client -> interval = client -> config -> initial_interval;
-
- /* Add an immediate timeout to cause the first DHCPDISCOVER packet
- to go out. */
- send_discover (client);
-}
-
-/* check_v6only is called by dhcpoffer and dhcpack. It checks if a
- * requested v6-only-preferred option is present and returned the
- * V6ONLY_WAIT delay to suspend DHCPv4. */
-
-uint32_t check_v6only(packet, client)
- struct packet *packet;
- struct client_state *client;
-{
- int i;
- struct option **req;
- isc_boolean_t found = ISC_FALSE;
- struct option_cache *oc;
- struct data_string data;
- uint32_t v6only_wait = 0;
-
- /* Check if the v6-only-preferred was requested. */
- req = client->config->requested_options;
-
- if (req == NULL)
- return 0;
-
- for (i = 0 ; req[i] != NULL ; i++) {
- if ((req[i]->universe == &dhcp_universe) &&
- (req[i]->code == DHO_V6_ONLY_PREFERRED)) {
- found = ISC_TRUE;
- break;
- }
- }
-
- if (found == ISC_FALSE)
- return 0;
-
- /* Get the V6ONLY_WAIT timer. */
- oc = lookup_option(&dhcp_universe, packet->options,
- DHO_V6_ONLY_PREFERRED);
- if (!oc)
- return 0;
-
- memset(&data, 0, sizeof(data));
-
- if (evaluate_option_cache(&data, packet, (struct lease *)0, client,
- packet->options, (struct option_state *)0,
- &global_scope, oc, MDL)) {
- if (data.len == 4) {
- v6only_wait = getULong(data.data);
- if (v6only_wait < MIN_V6ONLY_WAIT)
- v6only_wait = MIN_V6ONLY_WAIT;
- }
- data_string_forget(&data, MDL);
- }
-
- return (v6only_wait);
-}
-
-/* finish_v6only is called when the V6ONLY_WAIT timer expired. */
-
-void finish_v6only(cpp)
- void *cpp;
-{
- struct client_state *client = cpp;
-
- cancel_timeout(finish_v6only, client);
- client->state = S_INIT;
- state_init(cpp);
-}
-
-/*
- * start_v6only is called when a requested v6-only-preferred option was
- * returned by the server. */
-
-void start_v6only(client, v6only_wait)
- struct client_state *client;
- uint32_t v6only_wait;
-{
- struct timeval tv;
-
- /* Enter V6ONLY state. */
-
- client->state = S_V6ONLY;
-
- /* Run the client script. */
- script_init(client, "V6ONLY", NULL);
- if (client->active) {
- script_write_params(client, "old_", client->active);
- destroy_client_lease(client->active);
- client->active = NULL;
- }
- script_write_requested(client);
- client_envadd(client, "", "v6-only-preferred", "%lu",
- (long unsigned)v6only_wait);
- script_go(client);
-
- /* Trigger finish_v6only after V6ONLY_WAIT seconds. */
- tv.tv_sec = cur_tv.tv_sec + v6only_wait;
- tv.tv_usec = cur_tv.tv_usec;
-
- add_timeout(&tv, finish_v6only, client, 0, 0);
-}
-
-/*
- * state_selecting is called when one or more DHCPOFFER packets have been
- * received and a configurable period of time has passed.
- */
-
-void state_selecting (cpp)
- void *cpp;
-{
- struct client_state *client = cpp;
- struct client_lease *lp, *next, *picked;
-
-
- ASSERT_STATE(state, S_SELECTING);
-
- /*
- * Cancel state_selecting and send_discover timeouts, since either
- * one could have got us here.
- */
- cancel_timeout (state_selecting, client);
- cancel_timeout (send_discover, client);
-
- /*
- * We have received one or more DHCPOFFER packets. Currently,
- * the only criterion by which we judge leases is whether or
- * not we get a response when we arp for them.
- */
- picked = NULL;
- for (lp = client -> offered_leases; lp; lp = next) {
- next = lp -> next;
-
- /*
- * Check to see if we got an ARPREPLY for the address
- * in this particular lease.
- */
- if (!picked) {
- picked = lp;
- picked -> next = NULL;
- } else {
- destroy_client_lease (lp);
- }
- }
- client -> offered_leases = NULL;
-
- /*
- * If we just tossed all the leases we were offered, go back
- * to square one.
- */
- if (!picked) {
- client -> state = S_INIT;
- state_init (client);
- return;
- }
-
- /* If it was a BOOTREPLY, we can just take the address right now. */
- if (picked -> is_bootp) {
- client -> new = picked;
-
- /* Make up some lease expiry times
- XXX these should be configurable. */
- client -> new -> expiry = cur_time + 12000;
- client -> new -> renewal += cur_time + 8000;
- client -> new -> rebind += cur_time + 10000;
-
- client -> state = S_REQUESTING;
-
- /* Bind to the address we received. */
- bind_lease (client);
- return;
- }
-
- /* Go to the REQUESTING state. */
- client -> destination = iaddr_broadcast;
- client -> state = S_REQUESTING;
- client -> first_sending = cur_time;
- client -> interval = client -> config -> initial_interval;
-
- /* Make a DHCPREQUEST packet from the lease we picked. */
- make_request (client, picked);
- client -> xid = client -> packet.xid;
-
- /* Toss the lease we picked - we'll get it back in a DHCPACK. */
- destroy_client_lease (picked);
-
- /* Add an immediate timeout to send the first DHCPREQUEST packet. */
- send_request (client);
-}
-
-/* state_requesting is called when we receive a DHCPACK message after
- having sent out one or more DHCPREQUEST packets. */
-
-void dhcpack (packet)
- struct packet *packet;
-{
- struct interface_info *ip = packet -> interface;
- struct client_state *client;
- uint32_t v6only_wait;
- struct client_lease *lease;
- struct option_cache *oc;
- struct data_string ds;
-
- /* If we're not receptive to an offer right now, or if the offer
- has an unrecognizable transaction id, then just drop it. */
- for (client = ip -> client; client; client = client -> next) {
- if (client -> xid == packet -> raw -> xid)
- break;
- }
- if (!client ||
- (packet -> interface -> hw_address.hlen - 1 !=
- packet -> raw -> hlen) ||
- (memcmp (&packet -> interface -> hw_address.hbuf [1],
- packet -> raw -> chaddr, packet -> raw -> hlen))) {
-#if defined (DEBUG)
- log_debug ("DHCPACK in wrong transaction.");
-#endif
- return;
- }
-
- if (client -> state != S_REBOOTING &&
- client -> state != S_REQUESTING &&
- client -> state != S_RENEWING &&
- client -> state != S_REBINDING) {
-#if defined (DEBUG)
- log_debug ("DHCPACK in wrong state.");
-#endif
- return;
- }
-
- log_info ("DHCPACK of %s from %s",
- inet_ntoa(packet->raw->yiaddr),
- piaddr (packet->client_addr));
-
- /* Check v6only first. */
- v6only_wait = check_v6only(packet, client);
- if (v6only_wait > 0) {
- log_info("v6 only preferred for %lu seconds.",
- (long unsigned)v6only_wait);
- cancel_timeout(send_request, client);
- start_v6only(client, v6only_wait);
- return;
- }
-
- lease = packet_to_lease (packet, client);
- if (!lease) {
- log_info ("packet_to_lease failed.");
- return;
- }
-
- client -> new = lease;
-
- /* Stop resending DHCPREQUEST. */
- cancel_timeout (send_request, client);
-
- /* Figure out the lease time. */
- oc = lookup_option (&dhcp_universe, client -> new -> options,
- DHO_DHCP_LEASE_TIME);
- memset (&ds, 0, sizeof ds);
- if (oc &&
- evaluate_option_cache (&ds, packet, (struct lease *)0, client,
- packet -> options, client -> new -> options,
- &global_scope, oc, MDL)) {
- if (ds.len > 3)
- client -> new -> expiry = getULong (ds.data);
- else
- client -> new -> expiry = 0;
- data_string_forget (&ds, MDL);
- } else
- client -> new -> expiry = 0;
-
- if (client->new->expiry == 0) {
- struct timeval tv;
-
- log_error ("no expiry time on offered lease.");
-
- /* Quench this (broken) server. Return to INIT to reselect. */
- add_reject(packet);
-
- /* 1/2 second delay to restart at INIT. */
- tv.tv_sec = cur_tv.tv_sec;
- tv.tv_usec = cur_tv.tv_usec + 500000;
-
- if (tv.tv_usec >= 1000000) {
- tv.tv_sec++;
- tv.tv_usec -= 1000000;
- }
-
- add_timeout(&tv, state_init, client, 0, 0);
- return;
- }
-
- /*
- * A number that looks negative here is really just very large,
- * because the lease expiry offset is unsigned.
- */
- if (client->new->expiry < 0)
- client->new->expiry = TIME_MAX;
-
- /* Take the server-provided renewal time if there is one. */
- oc = lookup_option (&dhcp_universe, client -> new -> options,
- DHO_DHCP_RENEWAL_TIME);
- if (oc &&
- evaluate_option_cache (&ds, packet, (struct lease *)0, client,
- packet -> options, client -> new -> options,
- &global_scope, oc, MDL)) {
- if (ds.len > 3)
- client -> new -> renewal = getULong (ds.data);
- else
- client -> new -> renewal = 0;
- data_string_forget (&ds, MDL);
- } else
- client -> new -> renewal = 0;
-
- /* If it wasn't specified by the server, calculate it. */
- if (!client -> new -> renewal)
- client -> new -> renewal = client -> new -> expiry / 2 + 1;
-
- if (client -> new -> renewal <= 0)
- client -> new -> renewal = TIME_MAX;
-
- /* Now introduce some randomness to the renewal time: */
- if (client->new->renewal <= ((TIME_MAX / 3) - 3))
- client->new->renewal = (((client->new->renewal * 3) + 3) / 4) +
- (((random() % client->new->renewal) + 3) / 4);
-
- /* Same deal with the rebind time. */
- oc = lookup_option (&dhcp_universe, client -> new -> options,
- DHO_DHCP_REBINDING_TIME);
- if (oc &&
- evaluate_option_cache (&ds, packet, (struct lease *)0, client,
- packet -> options, client -> new -> options,
- &global_scope, oc, MDL)) {
- if (ds.len > 3)
- client -> new -> rebind = getULong (ds.data);
- else
- client -> new -> rebind = 0;
- data_string_forget (&ds, MDL);
- } else
- client -> new -> rebind = 0;
-
- if (client -> new -> rebind <= 0) {
- if (client -> new -> expiry <= TIME_MAX / 7)
- client -> new -> rebind =
- client -> new -> expiry * 7 / 8;
- else
- client -> new -> rebind =
- client -> new -> expiry / 8 * 7;
- }
-
- /* Make sure our randomness didn't run the renewal time past the
- rebind time. */
- if (client -> new -> renewal > client -> new -> rebind) {
- if (client -> new -> rebind <= TIME_MAX / 3)
- client -> new -> renewal =
- client -> new -> rebind * 3 / 4;
- else
- client -> new -> renewal =
- client -> new -> rebind / 4 * 3;
- }
-
- client -> new -> expiry += cur_time;
- /* Lease lengths can never be negative. */
- if (client -> new -> expiry < cur_time)
- client -> new -> expiry = TIME_MAX;
- client -> new -> renewal += cur_time;
- if (client -> new -> renewal < cur_time)
- client -> new -> renewal = TIME_MAX;
- client -> new -> rebind += cur_time;
- if (client -> new -> rebind < cur_time)
- client -> new -> rebind = TIME_MAX;
-
- bind_lease (client);
-}
-
-void bind_lease (client)
- struct client_state *client;
-{
- struct timeval tv;
-
- /* Remember the medium. */
- client->new->medium = client->medium;
-
- /* Run the client script with the new parameters. */
- script_init(client, (client->state == S_REQUESTING ? "BOUND" :
- (client->state == S_RENEWING ? "RENEW" :
- (client->state == S_REBOOTING ? "REBOOT" :
- "REBIND"))),
- client->new->medium);
- if (client->active && client->state != S_REBOOTING)
- script_write_params(client, "old_", client->active);
- script_write_params(client, "new_", client->new);
- script_write_requested(client);
- if (client->alias)
- script_write_params(client, "alias_", client->alias);
-
- /* If the BOUND/RENEW code detects another machine using the
- offered address, then per our man page it should exit with
- a non-zero status, to which we send a DHCPDECLINE and toss
- the lease. A return value of less than zero indicates
- the script crashed (e.g. segfault) which script_go will log
- but we will ignore here. */
- if (script_go(client) > 0) {
- make_decline(client, client->new);
- send_decline(client);
- destroy_client_lease(client->new);
- client->new = NULL;
- if (onetry) {
- if (!quiet) {
- log_info("Unable to obtain a lease on first "
- "try (declined). Exiting.");
- }
-
-#if defined (CALL_SCRIPT_ON_ONETRY_FAIL)
- /* Let's call a script and we're done */
- script_init(client, "FAIL", (struct string_list *)0);
- script_go(client);
-#endif
- finish(2);
- } else {
- struct timeval tv;
- tv.tv_sec = cur_tv.tv_sec + decline_wait_time;
- tv.tv_usec = cur_tv.tv_usec;
- add_timeout(&tv, state_init, client, 0, 0);
- return;
- }
- }
-
- /* Write out the new lease if it has been long enough. */
- if (!client->last_write ||
- (cur_time - client->last_write) >= MIN_LEASE_WRITE)
- write_client_lease(client, client->new, 0, 1);
-
- /* Replace the old active lease with the new one. */
- if (client->active) {
- if (client->active->is_static) {
- // We need to preserve the fallback lease in case
- // we lose DHCP service again.
- add_to_tail(&client->leases, client->active);
- } else {
- destroy_client_lease(client->active);
- }
- }
-
- client->active = client->new;
- client->new = NULL;
-
- /* Set up a timeout to start the renewal process. */
- tv.tv_sec = client->active->renewal;
- tv.tv_usec = ((client->active->renewal - cur_tv.tv_sec) > 1) ?
- random() % 1000000 : cur_tv.tv_usec;
- add_timeout(&tv, state_bound, client, 0, 0);
-
- log_info("bound to %s -- renewal in %ld seconds.",
- piaddr(client->active->address),
- (long)(client->active->renewal - cur_time));
- client->state = S_BOUND;
- reinitialize_interfaces();
- detach();
-#if defined (NSUPDATE)
- if (client->config->do_forward_update)
- dhclient_schedule_updates(client, &client->active->address, 1);
-#endif /* defined NSUPDATE */
-
-}
-
-/* state_bound is called when we've successfully bound to a particular
- lease, but the renewal time on that lease has expired. We are
- expected to unicast a DHCPREQUEST to the server that gave us our
- original lease. */
-
-void state_bound (cpp)
- void *cpp;
-{
- struct client_state *client = cpp;
- struct option_cache *oc;
- struct data_string ds;
-
- ASSERT_STATE(state, S_BOUND);
-
- /* T1 has expired. */
- make_request (client, client -> active);
- client -> xid = client -> packet.xid;
-
- memset (&ds, 0, sizeof ds);
- oc = lookup_option (&dhcp_universe, client -> active -> options,
- DHO_DHCP_SERVER_IDENTIFIER);
- if (oc &&
- evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0,
- client, (struct option_state *)0,
- client -> active -> options,
- &global_scope, oc, MDL)) {
- if (ds.len > 3) {
- memcpy (client -> destination.iabuf, ds.data, 4);
- client -> destination.len = 4;
- } else
- client -> destination = iaddr_broadcast;
-
- data_string_forget (&ds, MDL);
- } else
- client -> destination = iaddr_broadcast;
-
- client -> first_sending = cur_time;
- client -> interval = client -> config -> initial_interval;
- client -> state = S_RENEWING;
-
- /* Send the first packet immediately. */
- send_request (client);
-}
-
-/* state_stop is called when we've been told to shut down. We unconfigure
- the interfaces, and then stop operating until told otherwise. */
-
-void state_stop (cpp)
- void *cpp;
-{
- struct client_state *client = cpp;
-
- client->pending = P_NONE;
-
- /* Cancel all timeouts. */
- cancel_timeout(state_selecting, client);
- cancel_timeout(send_discover, client);
- cancel_timeout(send_request, client);
- cancel_timeout(state_bound, client);
- cancel_timeout(finish_v6only, client);
-
- /* If we have an address, unconfigure it. */
- if (client->active) {
- script_init(client, "STOP", client->active->medium);
- script_write_params(client, "old_", client->active);
- script_write_requested(client);
- if (client->alias)
- script_write_params(client, "alias_", client->alias);
- script_go(client);
- }
-}
-
-int commit_leases ()
-{
- return 0;
-}
-
-int write_lease (lease)
- struct lease *lease;
-{
- return 0;
-}
-
-int write_host (host)
- struct host_decl *host;
-{
- return 0;
-}
-
-void db_startup (testp)
- int testp;
-{
-}
-
-void bootp (packet)
- struct packet *packet;
-{
- struct iaddrmatchlist *ap;
- char addrbuf[4*16];
- char maskbuf[4*16];
-
- if (packet -> raw -> op != BOOTREPLY)
- return;
-
- /* If there's a reject list, make sure this packet's sender isn't
- on it. */
- for (ap = packet -> interface -> client -> config -> reject_list;
- ap; ap = ap -> next) {
- if (addr_match(&packet->client_addr, &ap->match)) {
-
- /* piaddr() returns its result in a static
- buffer sized 4*16 (see common/inet.c). */
-
- strcpy(addrbuf, piaddr(ap->match.addr));
- strcpy(maskbuf, piaddr(ap->match.mask));
-
- log_info("BOOTREPLY from %s rejected by rule %s "
- "mask %s.", piaddr(packet->client_addr),
- addrbuf, maskbuf);
- return;
- }
- }
-
- dhcpoffer (packet);
-
-}
-
-void dhcp (packet)
- struct packet *packet;
-{
- struct iaddrmatchlist *ap;
- void (*handler) (struct packet *);
- const char *type;
- char addrbuf[4*16];
- char maskbuf[4*16];
-
- switch (packet -> packet_type) {
- case DHCPOFFER:
- handler = dhcpoffer;
- type = "DHCPOFFER";
- break;
-
- case DHCPNAK:
- handler = dhcpnak;
- type = "DHCPNACK";
- break;
-
- case DHCPACK:
- handler = dhcpack;
- type = "DHCPACK";
- break;
-
- default:
- return;
- }
-
- /* If there's a reject list, make sure this packet's sender isn't
- on it. */
- for (ap = packet -> interface -> client -> config -> reject_list;
- ap; ap = ap -> next) {
- if (addr_match(&packet->client_addr, &ap->match)) {
-
- /* piaddr() returns its result in a static
- buffer sized 4*16 (see common/inet.c). */
-
- strcpy(addrbuf, piaddr(ap->match.addr));
- strcpy(maskbuf, piaddr(ap->match.mask));
-
- log_info("%s from %s rejected by rule %s mask %s.",
- type, piaddr(packet->client_addr),
- addrbuf, maskbuf);
- return;
- }
- }
- (*handler) (packet);
-}
-
-#ifdef DHCPv6
-void
-dhcpv6(struct packet *packet) {
- struct iaddrmatchlist *ap;
- struct client_state *client;
- char addrbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
-
- /* Silently drop bogus messages. */
- if (packet->dhcpv6_msg_type >= dhcpv6_type_name_max)
- return;
-
- /* Discard, with log, packets from quenched sources. */
- for (ap = packet->interface->client->config->reject_list ;
- ap ; ap = ap->next) {
- if (addr_match(&packet->client_addr, &ap->match)) {
- strcpy(addrbuf, piaddr(packet->client_addr));
- log_info("%s from %s rejected by rule %s",
- dhcpv6_type_names[packet->dhcpv6_msg_type],
- addrbuf,
- piaddrmask(&ap->match.addr, &ap->match.mask));
- return;
- }
- }
-
- /* Screen out nonsensical messages. */
- switch(packet->dhcpv6_msg_type) {
-#ifdef DHCP4o6
- case DHCPV6_DHCPV4_RESPONSE:
- if (dhcpv4_over_dhcpv6) {
- log_info("RCV: %s message on %s from %s.",
- dhcpv6_type_names[packet->dhcpv6_msg_type],
- packet->interface->name,
- piaddr(packet->client_addr));
- forw_dhcpv4_response(packet);
- }
- return;
-#endif
- case DHCPV6_ADVERTISE:
- case DHCPV6_RECONFIGURE:
- if (stateless)
- return;
- /* Falls through */
- case DHCPV6_REPLY:
- log_info("RCV: %s message on %s from %s.",
- dhcpv6_type_names[packet->dhcpv6_msg_type],
- packet->interface->name, piaddr(packet->client_addr));
- break;
-
- default:
- return;
- }
-
- /* Find a client state that matches the incoming XID. */
- for (client = packet->interface->client ; client ;
- client = client->next) {
- if (memcmp(&client->dhcpv6_transaction_id,
- packet->dhcpv6_transaction_id, 3) == 0) {
- client->v6_handler(packet, client);
- return;
- }
- }
-
- /* XXX: temporary log for debugging */
- log_info("Packet received, but nothing done with it.");
-}
-
-#ifdef DHCP4o6
-/*
- * \brief Forward a DHCPv4-response to the DHCPv4 client.
- * (DHCPv6 client function)
- *
- * The DHCPv6 client receives a DHCPv4-response which is forwarded
- * to the DHCPv4 client.
- * Format: address:16 + DHCPv4 message content
- * (we have no state to keep the address so it is transported in
- * DHCPv6 <-> DHCPv6 inter-process messages)
- *
- * \param packet the DHCPv4-response packet
- */
-static void forw_dhcpv4_response(struct packet *packet)
-{
- struct option_cache *oc;
- struct data_string enc_opt_data;
- struct data_string ds;
- int cc;
-
- /*
- * Discard if relay is not ready.
- */
- if (dhcp4o6_state == -1) {
- log_info("forw_dhcpv4_response: not ready.");
- return;
- }
-
- if (packet->client_addr.len != 16) {
- log_error("forw_dhcpv4_response: bad address");
- return;
- }
-
- /*
- * Get our encapsulated DHCPv4 message.
- */
- oc = lookup_option(&dhcpv6_universe, packet->options, D6O_DHCPV4_MSG);
- if (oc == NULL) {
- log_info("DHCPv4-response from %s missing "
- "DHCPv4 Message option.",
- piaddr(packet->client_addr));
- return;
- }
-
- memset(&enc_opt_data, 0, sizeof(enc_opt_data));
- if (!evaluate_option_cache(&enc_opt_data, NULL, NULL, NULL,
- NULL, NULL, &global_scope, oc, MDL)) {
- log_error("forw_dhcpv4_response: error evaluating "
- "DHCPv4 message.");
- data_string_forget(&enc_opt_data, MDL);
- return;
- }
-
- if (enc_opt_data.len < DHCP_FIXED_NON_UDP) {
- log_error("forw_dhcpv4_response: "
- "no memory for encapsulated packet.");
- data_string_forget(&enc_opt_data, MDL);
- return;
- }
-
- /*
- * Append address.
- */
- memset(&ds, 0, sizeof(ds));
- if (!buffer_allocate(&ds.buffer, enc_opt_data.len + 16, MDL)) {
- log_error("forw_dhcpv4_response: no memory buffer.");
- data_string_forget(&enc_opt_data, MDL);
- return;
- }
- ds.data = ds.buffer->data;
- ds.len = enc_opt_data.len + 16;
- memcpy(ds.buffer->data, enc_opt_data.data, enc_opt_data.len);
- memcpy(ds.buffer->data + enc_opt_data.len,
- packet->client_addr.iabuf, 16);
- data_string_forget(&enc_opt_data, MDL);
-
- /*
- * Forward them.
- */
- cc = send(dhcp4o6_fd, ds.data, ds.len, 0);
- if (cc < 0)
- log_error("forw_dhcpv4_response: send(): %m");
-
- data_string_forget(&ds, MDL);
-}
-
-/*
- * \brief Receive a DHCPv4-response from the DHCPv6 client.
- * (DHCPv4 client function)
- *
- * The DHCPv4 client receives a DHCPv4-response forwarded
- * by the DHCPv6 client (using \ref forw_dhcpv4_response())
- *
- * \param raw the DHCPv4-response raw packet
- */
-static void recv_dhcpv4_response(struct data_string *raw)
-{
- struct packet *packet;
- struct iaddr from;
-
- if (interfaces == NULL) {
- log_error("recv_dhcpv4_response: no interfaces.");
- return;
- }
-
- from.len = 16;
- memcpy(from.iabuf, raw->data + (raw->len - 16), 16);
-
- /*
- * Build a packet structure.
- */
- packet = NULL;
- if (!packet_allocate(&packet, MDL)) {
- log_error("recv_dhcpv4_response: no memory for packet.");
- return;
- }
-
- packet->raw = (struct dhcp_packet *) raw->data;
- packet->packet_length = raw->len - 16;
- packet->client_port = remote_port;
- packet->client_addr = from;
- interface_reference(&packet->interface, interfaces, MDL);
-
- /* Allocate packet->options now so it is non-null for all packets */
- if (!option_state_allocate (&packet->options, MDL)) {
- log_error("recv_dhcpv4_response: no memory for options.");
- packet_dereference (&packet, MDL);
- return;
- }
-
- /* If there's an option buffer, try to parse it. */
- if (packet->packet_length >= DHCP_FIXED_NON_UDP + 4) {
- struct option_cache *op;
- if (!parse_options(packet)) {
- if (packet->options)
- option_state_dereference
- (&packet->options, MDL);
- packet_dereference (&packet, MDL);
- return;
- }
-
- if (packet->options_valid &&
- (op = lookup_option(&dhcp_universe,
- packet->options,
- DHO_DHCP_MESSAGE_TYPE))) {
- struct data_string dp;
- memset(&dp, 0, sizeof dp);
- evaluate_option_cache(&dp, packet, NULL, NULL,
- packet->options, NULL,
- NULL, op, MDL);
- if (dp.len > 0)
- packet->packet_type = dp.data[0];
- else
- packet->packet_type = 0;
- data_string_forget(&dp, MDL);
- }
- }
-
- if (validate_packet(packet) != 0) {
- if (packet->packet_type)
- dhcp(packet);
- else
- bootp(packet);
- }
-
- /* If the caller kept the packet, they'll have upped the refcnt. */
- packet_dereference(&packet, MDL);
-}
-#endif /* DHCP4o6 */
-#endif /* DHCPv6 */
-
-void dhcpoffer (packet)
- struct packet *packet;
-{
- struct interface_info *ip = packet -> interface;
- struct client_state *client;
- uint32_t v6only_wait;
- struct client_lease *lease, *lp;
- struct option **req;
- int i;
- int stop_selecting;
- const char *name = packet -> packet_type ? "DHCPOFFER" : "BOOTREPLY";
- char obuf [1024];
- struct timeval tv;
-
-#ifdef DEBUG_PACKET
- dump_packet (packet);
-#endif
-
- /* Find a client state that matches the xid... */
- for (client = ip -> client; client; client = client -> next)
- if (client -> xid == packet -> raw -> xid)
- break;
-
- /* If we're not receptive to an offer right now, or if the offer
- has an unrecognizable transaction id, then just drop it. */
- if (!client ||
- client -> state != S_SELECTING ||
- (packet -> interface -> hw_address.hlen - 1 !=
- packet -> raw -> hlen) ||
- (memcmp (&packet -> interface -> hw_address.hbuf [1],
- packet -> raw -> chaddr, packet -> raw -> hlen))) {
-#if defined (DEBUG)
- log_debug ("%s in wrong transaction.", name);
-#endif
- return;
- }
-
- sprintf (obuf, "%s of %s from %s", name,
- inet_ntoa(packet->raw->yiaddr),
- piaddr(packet->client_addr));
-
- /* Check v6only first. */
- v6only_wait = check_v6only(packet, client);
- if (v6only_wait > 0) {
- log_info("%s: v6 only preferred for %lu.", obuf,
- (long unsigned)v6only_wait);
- cancel_timeout(send_discover, client);
- start_v6only(client, v6only_wait);
- return;
- }
-
- /* If this lease doesn't supply the minimum required DHCPv4 parameters,
- * ignore it.
- */
- req = client->config->required_options;
- if (req != NULL) {
- for (i = 0 ; req[i] != NULL ; i++) {
- if ((req[i]->universe == &dhcp_universe) &&
- !lookup_option(&dhcp_universe, packet->options,
- req[i]->code)) {
- struct option *option = NULL;
- unsigned code = req[i]->code;
-
- option_code_hash_lookup(&option,
- dhcp_universe.code_hash,
- &code, 0, MDL);
-
- if (option)
- log_info("%s: no %s option.", obuf,
- option->name);
- else
- log_info("%s: no unknown-%u option.",
- obuf, code);
-
- option_dereference(&option, MDL);
-
- return;
- }
- }
- }
-
- /* If we've already seen this lease, don't record it again. */
- for (lease = client -> offered_leases; lease; lease = lease -> next) {
- if (lease -> address.len == sizeof packet -> raw -> yiaddr &&
- !memcmp (lease -> address.iabuf,
- &packet -> raw -> yiaddr, lease -> address.len)) {
- log_debug ("%s: already seen.", obuf);
- return;
- }
- }
-
- lease = packet_to_lease (packet, client);
- if (!lease) {
- log_info ("%s: packet_to_lease failed.", obuf);
- return;
- }
-
- /* log it now, so it emits before the request goes out */
- log_info("%s", obuf);
-
- /* If this lease was acquired through a BOOTREPLY, record that
- fact. */
- if (!packet -> options_valid || !packet -> packet_type)
- lease -> is_bootp = 1;
-
- /* Record the medium under which this lease was offered. */
- lease -> medium = client -> medium;
-
- /* Figure out when we're supposed to stop selecting. */
- stop_selecting = (client -> first_sending +
- client -> config -> select_interval);
-
- /* If this is the lease we asked for, put it at the head of the
- list, and don't mess with the arp request timeout. */
- if (lease -> address.len == client -> requested_address.len &&
- !memcmp (lease -> address.iabuf,
- client -> requested_address.iabuf,
- client -> requested_address.len)) {
- lease -> next = client -> offered_leases;
- client -> offered_leases = lease;
- } else {
- /* Put the lease at the end of the list. */
- lease -> next = (struct client_lease *)0;
- if (!client -> offered_leases)
- client -> offered_leases = lease;
- else {
- for (lp = client -> offered_leases; lp -> next;
- lp = lp -> next)
- ;
- lp -> next = lease;
- }
- }
-
- /* If the selecting interval has expired, go immediately to
- state_selecting(). Otherwise, time out into
- state_selecting at the select interval. */
- if (stop_selecting <= cur_tv.tv_sec)
- state_selecting (client);
- else {
- tv.tv_sec = stop_selecting;
- tv.tv_usec = cur_tv.tv_usec;
- add_timeout(&tv, state_selecting, client, 0, 0);
- cancel_timeout(send_discover, client);
- }
-}
-
-/* Allocate a client_lease structure and initialize it from the parameters
- in the specified packet. */
-
-struct client_lease *packet_to_lease (packet, client)
- struct packet *packet;
- struct client_state *client;
-{
- struct client_lease *lease;
- unsigned i;
- struct option_cache *oc;
- struct option *option = NULL;
- struct data_string data;
-
- lease = (struct client_lease *)new_client_lease (MDL);
-
- if (!lease) {
- log_error("packet_to_lease: no memory to record lease.\n");
- return NULL;
- }
-
- memset(lease, 0, sizeof(*lease));
-
- /* Copy the lease options. */
- option_state_reference(&lease->options, packet->options, MDL);
-
- lease->address.len = sizeof(packet->raw->yiaddr);
- memcpy(lease->address.iabuf, &packet->raw->yiaddr,
- lease->address.len);
-
- lease->next_srv_addr.len = sizeof(packet->raw->siaddr);
- memcpy(lease->next_srv_addr.iabuf, &packet->raw->siaddr,
- lease->next_srv_addr.len);
-
- memset(&data, 0, sizeof(data));
-
- if (client -> config -> vendor_space_name) {
- i = DHO_VENDOR_ENCAPSULATED_OPTIONS;
-
- /* See if there was a vendor encapsulation option. */
- oc = lookup_option (&dhcp_universe, lease -> options, i);
- if (oc &&
- client -> config -> vendor_space_name &&
- evaluate_option_cache (&data, packet,
- (struct lease *)0, client,
- packet -> options, lease -> options,
- &global_scope, oc, MDL)) {
- if (data.len) {
- if (!option_code_hash_lookup(&option,
- dhcp_universe.code_hash,
- &i, 0, MDL))
- log_fatal("Unable to find VENDOR "
- "option (%s:%d).", MDL);
- parse_encapsulated_suboptions
- (packet -> options, option,
- data.data, data.len, &dhcp_universe,
- client -> config -> vendor_space_name
- );
-
- option_dereference(&option, MDL);
- }
- data_string_forget (&data, MDL);
- }
- } else
- i = 0;
-
- /* Figure out the overload flag. */
- oc = lookup_option (&dhcp_universe, lease -> options,
- DHO_DHCP_OPTION_OVERLOAD);
- if (oc &&
- evaluate_option_cache (&data, packet, (struct lease *)0, client,
- packet -> options, lease -> options,
- &global_scope, oc, MDL)) {
- if (data.len > 0)
- i = data.data [0];
- else
- i = 0;
- data_string_forget (&data, MDL);
- } else
- i = 0;
-
- /* If the server name was filled out, copy it. */
- if (!(i & 2) && packet -> raw -> sname [0]) {
- unsigned len;
- /* Don't count on the NUL terminator. */
- for (len = 0; len < DHCP_SNAME_LEN; len++)
- if (!packet -> raw -> sname [len])
- break;
- lease -> server_name = dmalloc (len + 1, MDL);
- if (!lease -> server_name) {
- log_error ("dhcpoffer: no memory for server name.\n");
- destroy_client_lease (lease);
- return (struct client_lease *)0;
- } else {
- memcpy (lease -> server_name,
- packet -> raw -> sname, len);
- lease -> server_name [len] = 0;
- }
- }
-
- /* Ditto for the filename. */
- if (!(i & 1) && packet -> raw -> file [0]) {
- unsigned len;
- /* Don't count on the NUL terminator. */
- for (len = 0; len < DHCP_FILE_LEN; len++)
- if (!packet -> raw -> file [len])
- break;
- lease -> filename = dmalloc (len + 1, MDL);
- if (!lease -> filename) {
- log_error ("dhcpoffer: no memory for filename.\n");
- destroy_client_lease (lease);
- return (struct client_lease *)0;
- } else {
- memcpy (lease -> filename,
- packet -> raw -> file, len);
- lease -> filename [len] = 0;
- }
- }
-
- execute_statements_in_scope(NULL, (struct packet *)packet, NULL,
- client, lease->options, lease->options,
- &global_scope, client->config->on_receipt,
- NULL, NULL);
-
- return lease;
-}
-
-void dhcpnak (packet)
- struct packet *packet;
-{
- struct interface_info *ip = packet -> interface;
- struct client_state *client;
-
- /* Find a client state that matches the xid... */
- for (client = ip -> client; client; client = client -> next)
- if (client -> xid == packet -> raw -> xid)
- break;
-
- /* If we're not receptive to an offer right now, or if the offer
- has an unrecognizable transaction id, then just drop it. */
- if (!client ||
- (packet -> interface -> hw_address.hlen - 1 !=
- packet -> raw -> hlen) ||
- (memcmp (&packet -> interface -> hw_address.hbuf [1],
- packet -> raw -> chaddr, packet -> raw -> hlen))) {
-#if defined (DEBUG)
- log_debug ("DHCPNAK in wrong transaction.");
-#endif
- return;
- }
-
- if (client -> state != S_REBOOTING &&
- client -> state != S_REQUESTING &&
- client -> state != S_RENEWING &&
- client -> state != S_REBINDING) {
-#if defined (DEBUG)
- log_debug ("DHCPNAK in wrong state.");
-#endif
- return;
- }
-
- log_info ("DHCPNAK from %s", piaddr (packet -> client_addr));
-
- if (!client -> active) {
-#if defined (DEBUG)
- log_info ("DHCPNAK with no active lease.\n");
-#endif
- return;
- }
-
- /* If we get a DHCPNAK, we use the EXPIRE dhclient-script state
- * to indicate that we want all old bindings to be removed. (It
- * is possible that we may get a NAK while in the RENEW state,
- * so we might have bindings active at that time)
- */
- script_init(client, "EXPIRE", NULL);
- script_write_params(client, "old_", client->active);
- script_write_requested(client);
- if (client->alias)
- script_write_params(client, "alias_", client->alias);
- script_go(client);
-
- destroy_client_lease (client -> active);
- client -> active = (struct client_lease *)0;
-
- /* Stop sending DHCPREQUEST packets... */
- cancel_timeout (send_request, client);
-
- /* On some scripts, 'EXPIRE' causes the interface to be ifconfig'd
- * down (this expunges any routes and arp cache). This makes the
- * interface unusable by state_init(), which we call next. So, we
- * need to 'PREINIT' the interface to bring it back up.
- */
- script_init(client, "PREINIT", NULL);
- if (client->alias)
- script_write_params(client, "alias_", client->alias);
- script_go(client);
-
- client -> state = S_INIT;
- state_init (client);
-}
-
-/* Send out a DHCPDISCOVER packet, and set a timeout to send out another
- one after the right interval has expired. If we don't get an offer by
- the time we reach the panic interval, call the panic function. */
-
-void send_discover (cpp)
- void *cpp;
-{
- struct client_state *client = cpp;
-
- int result;
- int interval;
- int increase = 1;
- struct timeval tv;
-
- /* Figure out how long it's been since we started transmitting. */
- interval = cur_time - client -> first_sending;
-
- /* If we're past the panic timeout, call the script and tell it
- we haven't found anything for this interface yet. */
- if (interval > client -> config -> timeout) {
- state_panic (client);
- return;
- }
-
- /* If we're selecting media, try the whole list before doing
- the exponential backoff, but if we've already received an
- offer, stop looping, because we obviously have it right. */
- if (!client -> offered_leases &&
- client -> config -> media) {
- int fail = 0;
- again:
- if (client -> medium) {
- client -> medium = client -> medium -> next;
- increase = 0;
- }
- if (!client -> medium) {
- if (fail)
- log_fatal ("No valid media types for %s!",
- client -> interface -> name);
- client -> medium =
- client -> config -> media;
- increase = 1;
- }
-
- log_info ("Trying medium \"%s\" %d",
- client -> medium -> string, increase);
- script_init(client, "MEDIUM", client -> medium);
- if (script_go(client)) {
- fail = 1;
- goto again;
- }
- }
-
- /* If we're supposed to increase the interval, do so. If it's
- currently zero (i.e., we haven't sent any packets yet), set
- it to initial_interval; otherwise, add to it a random number
- between zero and two times itself. On average, this means
- that it will double with every transmission. */
- if (increase) {
- if (!client->interval)
- client->interval = client->config->initial_interval;
- else
- client->interval += random() % (2 * client->interval);
-
- /* Don't backoff past cutoff. */
- if (client->interval > client->config->backoff_cutoff)
- client->interval = (client->config->backoff_cutoff / 2)
- + (random() % client->config->backoff_cutoff);
- } else if (!client->interval)
- client->interval = client->config->initial_interval;
-
- /* If the backoff would take us to the panic timeout, just use that
- as the interval. */
- if (cur_time + client -> interval >
- client -> first_sending + client -> config -> timeout)
- client -> interval =
- (client -> first_sending +
- client -> config -> timeout) - cur_time + 1;
-
- /* Record the number of seconds since we started sending. */
- if (interval < 65536)
- client -> packet.secs = htons (interval);
- else
- client -> packet.secs = htons (65535);
- client -> secs = client -> packet.secs;
-
-#if defined(DHCPv6) && defined(DHCP4o6)
- if (dhcpv4_over_dhcpv6) {
- log_info ("DHCPDISCOVER interval %ld",
- (long)(client -> interval));
- } else
-#endif
- log_info ("DHCPDISCOVER on %s to %s port %d interval %ld",
- client -> name ? client -> name : client -> interface -> name,
- inet_ntoa (sockaddr_broadcast.sin_addr),
- ntohs (sockaddr_broadcast.sin_port), (long)(client -> interval));
-
- /* Send out a packet. */
-#if defined(DHCPv6) && defined(DHCP4o6)
- if (dhcpv4_over_dhcpv6) {
- result = send_dhcpv4_query(client, 1);
- } else
-#endif
- result = send_packet(client->interface, NULL, &client->packet,
- client->packet_length, inaddr_any,
- &sockaddr_broadcast, NULL);
- if (result < 0) {
-#if defined(DHCPv6) && defined(DHCP4o6)
- if (dhcpv4_over_dhcpv6) {
- log_error("%s:%d: Failed to send %d byte long packet.",
- MDL, client->packet_length);
- } else
-#endif
- log_error("%s:%d: Failed to send %d byte long packet over %s "
- "interface.", MDL, client->packet_length,
- client->interface->name);
- }
-
- /*
- * If we used 0 microseconds here, and there were other clients on the
- * same network with a synchronized local clock (ntp), and a similar
- * zero-microsecond-scheduler behavior, then we could be participating
- * in a sub-second DOS ttck.
- */
- tv.tv_sec = cur_tv.tv_sec + client->interval;
- tv.tv_usec = client->interval > 1 ? random() % 1000000 : cur_tv.tv_usec;
- add_timeout(&tv, send_discover, client, 0, 0);
-}
-
-
-/*
- * \brief Remove leases from a list of leases which duplicate a given lease
- *
- * Searches through a linked-list of leases, remove the first one matches the
- * given lease's address and value of is_static. The latter test is done
- * so we only remove leases that are from the same source (i.e server/lease file
- * vs config file). This ensures we do not discard "fallback" config file leases
- * that happen to match non-config file leases.
- *
- * \param lease_list list of leases to clean
- * \param lease lease for which duplicates should be removed
- */
-void discard_duplicate (struct client_lease** lease_list, struct client_lease* lease) {
- struct client_lease *cur, *prev, *next;
-
- if (!lease_list || !lease) {
- return;
- }
-
- prev = (struct client_lease *)0;
- for (cur = *lease_list; cur; cur = next) {
- next = cur->next;
- if ((cur->is_static == lease->is_static) &&
- (cur->address.len == lease->address.len &&
- !memcmp (cur->address.iabuf, lease->address.iabuf,
- lease->address.len))) {
- if (prev)
- prev->next = next;
- else
- *lease_list = next;
-
- destroy_client_lease (cur);
- break;
- } else {
- prev = cur;
- }
- }
-}
-
-/*
- * \brief Add a given lease to the end of list of leases
- *
- * Searches through a linked-list of leases, removing any that match the
- * given lease's address and value of is_static. The latter test is done
- * so we only remove leases that are from the same source (i.e server/lease file
- * vs config file). This ensures we do not discard "fallback" config file leases
- * that happen to match non-config file leases.
- *
- * \param lease_list list of leases to clean
- * \param lease lease for which duplicates should be removed
- */
-void add_to_tail(struct client_lease** lease_list,
- struct client_lease* lease)
-{
- if (!lease_list || !lease) {
- return;
- }
-
- /* If there is already a lease for this address and
- * is_static value, toss discard it. This ensures
- * we only keep one dynamic and/or one static lease
- * for a given address. */
- discard_duplicate(lease_list, lease);
-
- /* Find the tail */
- struct client_lease* tail;
- for (tail = *lease_list; tail && tail->next; tail = tail->next){};
-
- /* Ensure the tail points nowhere. */
- lease->next = NULL;
-
- /* Add to the tail. */
- if (!tail) {
- *lease_list = lease;
- } else {
- tail->next = lease;
- }
-}
-
-#if 0
-void dbg_print_lease(char *text, struct client_lease* lease) {
- if (!lease) {
- log_debug("%s, lease is null", text);
- } else {
- log_debug ("%s: %p addr:%s expires:%ld :is_static? %d",
- text, lease, piaddr (lease->address),
- (lease->expiry - cur_time),
- lease->is_static);
- }
-}
-#endif
-
-/* state_panic gets called if we haven't received any offers in a preset
- amount of time. When this happens, we try to use existing leases that
- haven't yet expired, and failing that, we call the client script and
- hope it can do something. */
-
-void state_panic (cpp)
- void *cpp;
-{
- struct client_state *client = cpp;
- struct client_lease *loop;
- struct client_lease *lp;
- struct timeval tv;
-
- loop = lp = client -> active;
-
- log_info ("No DHCPOFFERS received.");
-
- /* We may not have an active lease, but we may have some
- predefined leases that we can try. */
- if (!client -> active && client -> leases)
- goto activate_next;
-
- /* Run through the list of leases and see if one can be used. */
- while (client -> active) {
- if (client -> active -> expiry > cur_time) {
- log_info ("Trying %s lease %s",
- (client -> active -> is_static
- ? "fallback" : "recorded"),
- piaddr (client -> active -> address));
- /* Run the client script with the existing
- parameters. */
- script_init(client, "TIMEOUT",
- client -> active -> medium);
- script_write_params(client, "new_", client -> active);
- script_write_requested(client);
- if (client -> alias)
- script_write_params(client, "alias_",
- client -> alias);
-
- /* If the old lease is still good and doesn't
- yet need renewal, go into BOUND state and
- timeout at the renewal time. */
- if (!script_go(client)) {
- if (cur_time < client -> active -> renewal) {
- client -> state = S_BOUND;
- log_info ("bound: renewal in %ld %s.",
- (long)(client -> active -> renewal -
- cur_time), "seconds");
- tv.tv_sec = client->active->renewal;
- tv.tv_usec = ((client->active->renewal -
- cur_time) > 1) ?
- random() % 1000000 :
- cur_tv.tv_usec;
- add_timeout(&tv, state_bound, client, 0, 0);
- } else {
- client -> state = S_BOUND;
- log_info ("bound: immediate renewal.");
- state_bound (client);
- }
- reinitialize_interfaces ();
- detach ();
- return;
- }
- }
-
- /* If there are no other leases, give up. */
- if (!client -> leases) {
- client -> leases = client -> active;
- client -> active = (struct client_lease *)0;
- break;
- }
-
- activate_next:
- /* Otherwise, put the active lease at the end of the
- lease list, and try another lease.. */
- add_to_tail(&client->leases, client->active);
-
- client -> active = client -> leases;
- client -> leases = client -> leases -> next;
-
- /* If we already tried this lease, we've exhausted the
- set of leases, so we might as well give up for
- now. */
- if (client -> active == loop)
- break;
- else if (!loop)
- loop = client -> active;
- }
-
- /* No leases were available, or what was available didn't work, so
- tell the shell script that we failed to allocate an address,
- and try again later. */
- if (onetry) {
- if (!quiet) {
- log_info ("Unable to obtain a lease on first try.%s",
- " Exiting.");
- }
-
-#if defined (CALL_SCRIPT_ON_ONETRY_FAIL)
- /* Let's call a script and we're done */
- script_init(client, "FAIL", (struct string_list *)0);
- script_go(client);
-#endif
- finish(2);
- }
-
- log_info ("No working leases in persistent database - sleeping.");
- script_init(client, "FAIL", (struct string_list *)0);
- if (client -> alias)
- script_write_params(client, "alias_", client -> alias);
- script_go(client);
- client -> state = S_INIT;
- tv.tv_sec = cur_tv.tv_sec + ((client->config->retry_interval + 1) / 2 +
- (random() % client->config->retry_interval));
- tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ?
- random() % 1000000 : cur_tv.tv_usec;
- add_timeout(&tv, state_init, client, 0, 0);
- detach ();
-}
-
-void send_request (cpp)
- void *cpp;
-{
- struct client_state *client = cpp;
-
- int result;
- int interval;
- struct sockaddr_in destination;
- struct in_addr from;
- struct timeval tv;
- char rip_buf[128];
- const char* rip_str = "";
-
- /* Figure out how long it's been since we started transmitting. */
- interval = cur_time - client -> first_sending;
-
- /* If we're in the INIT-REBOOT or REQUESTING state and we're
- past the reboot timeout, go to INIT and see if we can
- DISCOVER an address... */
- /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
- means either that we're on a network with no DHCP server,
- or that our server is down. In the latter case, assuming
- that there is a backup DHCP server, DHCPDISCOVER will get
- us a new address, but we could also have successfully
- reused our old address. In the former case, we're hosed
- anyway. This is not a win-prone situation. */
- if ((client -> state == S_REBOOTING ||
- client -> state == S_REQUESTING) &&
- interval > client -> config -> reboot_timeout) {
- cancel:
- client -> state = S_INIT;
- cancel_timeout (send_request, client);
- state_init (client);
- return;
- }
-
- /* If we're in the reboot state, make sure the media is set up
- correctly. */
- if (client -> state == S_REBOOTING &&
- !client -> medium &&
- client -> active -> medium ) {
- script_init(client, "MEDIUM", client -> active -> medium);
-
- /* If the medium we chose won't fly, go to INIT state. */
- if (script_go(client))
- goto cancel;
-
- /* Record the medium. */
- client -> medium = client -> active -> medium;
- }
-
- /* If the lease has expired, relinquish the address and go back
- to the INIT state. */
- if (client -> state != S_REQUESTING &&
- cur_time > client -> active -> expiry) {
- /* Run the client script with the new parameters. */
- script_init(client, "EXPIRE", (struct string_list *)0);
- script_write_params(client, "old_", client -> active);
- script_write_requested(client);
- if (client -> alias)
- script_write_params(client, "alias_",
- client -> alias);
- script_go(client);
-
- /* Now do a preinit on the interface so that we can
- discover a new address. */
- script_init(client, "PREINIT", (struct string_list *)0);
- if (client -> alias)
- script_write_params(client, "alias_",
- client -> alias);
- script_go(client);
-
- client -> state = S_INIT;
- state_init (client);
- return;
- }
-
- /* Do the exponential backoff... */
- if (!client -> interval)
- client -> interval = client -> config -> initial_interval;
- else {
- client -> interval += ((random () >> 2) %
- (2 * client -> interval));
- }
-
- /* Don't backoff past cutoff. */
- if (client -> interval >
- client -> config -> backoff_cutoff)
- client -> interval =
- ((client -> config -> backoff_cutoff / 2)
- + ((random () >> 2) %
- client -> config -> backoff_cutoff));
-
- /* If the backoff would take us to the expiry time, just set the
- timeout to the expiry time. */
- if (client -> state != S_REQUESTING &&
- cur_time + client -> interval > client -> active -> expiry)
- client -> interval =
- client -> active -> expiry - cur_time + 1;
-
- /* If the lease T2 time has elapsed, or if we're not yet bound,
- broadcast the DHCPREQUEST rather than unicasting. */
- if (client -> state == S_REQUESTING ||
- client -> state == S_REBOOTING ||
- cur_time > client -> active -> rebind)
- destination.sin_addr = sockaddr_broadcast.sin_addr;
- else
- memcpy (&destination.sin_addr.s_addr,
- client -> destination.iabuf,
- sizeof destination.sin_addr.s_addr);
- destination.sin_port = remote_port;
- destination.sin_family = AF_INET;
-#ifdef HAVE_SA_LEN
- destination.sin_len = sizeof destination;
-#endif
-
- if (client -> state == S_RENEWING ||
- client -> state == S_REBINDING)
- memcpy (&from, client -> active -> address.iabuf,
- sizeof from);
- else
- from.s_addr = INADDR_ANY;
-
- /* Record the number of seconds since we started sending. */
- if (client -> state == S_REQUESTING)
- client -> packet.secs = client -> secs;
- else {
- if (interval < 65536)
- client -> packet.secs = htons (interval);
- else
- client -> packet.secs = htons (65535);
- }
-
-#if defined(DHCPv6) && defined(DHCP4o6)
- if (dhcpv4_over_dhcpv6) {
- log_info ("DHCPREQUEST");
- } else
-#endif
- memset(rip_buf, 0x0, sizeof(rip_buf));
- if (client->state == S_BOUND || client->state == S_RENEWING ||
- client->state == S_REBINDING) {
- rip_str = inet_ntoa(client->packet.ciaddr);
- } else {
- rip_str = piaddr(client->requested_address);
- }
-
- strncpy(rip_buf, rip_str, sizeof(rip_buf)-1);
- log_info ("DHCPREQUEST for %s on %s to %s port %d", rip_buf,
- client->name ? client->name : client->interface->name,
- inet_ntoa(destination.sin_addr),
- ntohs (destination.sin_port));
-
-#if defined(DHCPv6) && defined(DHCP4o6)
- if (dhcpv4_over_dhcpv6) {
- int broadcast = 0;
- if (destination.sin_addr.s_addr == INADDR_BROADCAST)
- broadcast = 1;
- result = send_dhcpv4_query(client, broadcast);
- if (result < 0) {
- log_error("%s:%d: Failed to send %d byte long packet.",
- MDL, client->packet_length);
- }
- } else
-#endif
- if (destination.sin_addr.s_addr != INADDR_BROADCAST &&
- fallback_interface) {
- result = send_packet(fallback_interface, NULL, &client->packet,
- client->packet_length, from, &destination,
- NULL);
- if (result < 0) {
- log_error("%s:%d: Failed to send %d byte long packet "
- "over %s interface.", MDL,
- client->packet_length,
- fallback_interface->name);
- }
- }
- else {
- /* Send out a packet. */
- result = send_packet(client->interface, NULL, &client->packet,
- client->packet_length, from, &destination,
- NULL);
- if (result < 0) {
- log_error("%s:%d: Failed to send %d byte long packet"
- " over %s interface.", MDL,
- client->packet_length,
- client->interface->name);
- }
- }
-
- tv.tv_sec = cur_tv.tv_sec + client->interval;
- tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ?
- random() % 1000000 : cur_tv.tv_usec;
- add_timeout(&tv, send_request, client, 0, 0);
-}
-
-void send_decline (cpp)
- void *cpp;
-{
- struct client_state *client = cpp;
-
- int result;
-
-#if defined(DHCPv6) && defined(DHCP4o6)
- if (dhcpv4_over_dhcpv6) {
- log_info ("DHCPDECLINE");
- } else
-#endif
- log_info ("DHCPDECLINE of %s on %s to %s port %d",
- piaddr(client->requested_address),
- (client->name ? client->name : client->interface->name),
- inet_ntoa(sockaddr_broadcast.sin_addr),
- ntohs(sockaddr_broadcast.sin_port));
-
- /* Send out a packet. */
-#if defined(DHCPv6) && defined(DHCP4o6)
- if (dhcpv4_over_dhcpv6) {
- result = send_dhcpv4_query(client, 1);
- } else
-#endif
- result = send_packet(client->interface, NULL, &client->packet,
- client->packet_length, inaddr_any,
- &sockaddr_broadcast, NULL);
- if (result < 0) {
-#if defined(DHCPv6) && defined(DHCP4o6)
- if (dhcpv4_over_dhcpv6) {
- log_error("%s:%d: Failed to send %d byte long packet.",
- MDL, client->packet_length);
- } else
-#endif
- log_error("%s:%d: Failed to send %d byte long packet over %s"
- " interface.", MDL, client->packet_length,
- client->interface->name);
- }
-}
-
-void send_release (cpp)
- void *cpp;
-{
- struct client_state *client = cpp;
-
- int result;
- struct sockaddr_in destination;
- struct in_addr from;
-
- memcpy (&from, client -> active -> address.iabuf,
- sizeof from);
- memcpy (&destination.sin_addr.s_addr,
- client -> destination.iabuf,
- sizeof destination.sin_addr.s_addr);
- destination.sin_port = remote_port;
- destination.sin_family = AF_INET;
-#ifdef HAVE_SA_LEN
- destination.sin_len = sizeof destination;
-#endif
-
- /* Set the lease to end now, so that we don't accidentally
- reuse it if we restart before the old expiry time. */
- client -> active -> expiry =
- client -> active -> renewal =
- client -> active -> rebind = cur_time;
- if (!write_client_lease (client, client -> active, 1, 1)) {
- log_error ("Can't release lease: lease write failed.");
- return;
- }
-
-#if defined(DHCPv6) && defined(DHCP4o6)
- if (dhcpv4_over_dhcpv6) {
- log_info ("DHCPRELEASE");
- } else
-#endif
- log_info ("DHCPRELEASE of %s on %s to %s port %d",
- piaddr(client->active->address),
- client->name ? client->name : client->interface->name,
- inet_ntoa (destination.sin_addr),
- ntohs (destination.sin_port));
-
-#if defined(DHCPv6) && defined(DHCP4o6)
- if (dhcpv4_over_dhcpv6) {
- int broadcast = 0;
- if (destination.sin_addr.s_addr == INADDR_BROADCAST)
- broadcast = 1;
- result = send_dhcpv4_query(client, broadcast);
- if (result < 0) {
- log_error("%s:%d: Failed to send %d byte long packet.",
- MDL, client->packet_length);
- }
- } else
-#endif
- if (fallback_interface) {
- result = send_packet(fallback_interface, NULL, &client->packet,
- client->packet_length, from, &destination,
- NULL);
- if (result < 0) {
- log_error("%s:%d: Failed to send %d byte long packet"
- " over %s interface.", MDL,
- client->packet_length,
- fallback_interface->name);
- }
- } else {
- /* Send out a packet. */
- result = send_packet(client->interface, NULL, &client->packet,
- client->packet_length, from, &destination,
- NULL);
- if (result < 0) {
- log_error ("%s:%d: Failed to send %d byte long packet"
- " over %s interface.", MDL,
- client->packet_length,
- client->interface->name);
- }
-
- }
-}
-
-#if defined(DHCPv6) && defined(DHCP4o6)
-/*
- * \brief Send a DHCPv4-query to the DHCPv6 client
- * (DHCPv4 client function)
- *
- * The DHCPv4 client sends a DHCPv4-query to the DHCPv6 client over
- * the inter-process communication socket.
- *
- * \param client the DHCPv4 client state
- * \param broadcast the broadcast flag
- * \return the sent byte count (-1 on error)
- */
-static int send_dhcpv4_query(struct client_state *client, int broadcast) {
- struct data_string ds;
- struct dhcpv4_over_dhcpv6_packet *query;
- int ofs, len, cc;
-
- if (dhcp4o6_state <= 0) {
- log_info("send_dhcpv4_query: not ready.");
- return -1;
- }
-
- /*
- * Compute buffer length and allocate it.
- */
- len = ofs = (int)(offsetof(struct dhcpv4_over_dhcpv6_packet, options));
- len += dhcpv6_universe.tag_size + dhcpv6_universe.length_size;
- len += client->packet_length;
- memset(&ds, 0, sizeof(ds));
- if (!buffer_allocate(&ds.buffer, len, MDL)) {
- log_error("Unable to allocate memory for DHCPv4-query.");
- return -1;
- }
- ds.data = ds.buffer->data;
- ds.len = len;
-
- /*
- * Fill header.
- */
- query = (struct dhcpv4_over_dhcpv6_packet *)ds.data;
- query->msg_type = DHCPV6_DHCPV4_QUERY;
- query->flags[0] = query->flags[1] = query->flags[2] = 0;
- if (!broadcast)
- query->flags[0] |= DHCP4O6_QUERY_UNICAST;
-
- /*
- * Append DHCPv4 message.
- */
- dhcpv6_universe.store_tag(ds.buffer->data + ofs, D6O_DHCPV4_MSG);
- ofs += dhcpv6_universe.tag_size;
- dhcpv6_universe.store_length(ds.buffer->data + ofs,
- client->packet_length);
- ofs += dhcpv6_universe.length_size;
- memcpy(ds.buffer->data + ofs, &client->packet, client->packet_length);
-
- /*
- * Send DHCPv6 message.
- */
- cc = send(dhcp4o6_fd, ds.data, ds.len, 0);
- if (cc < 0)
- log_error("send_dhcpv4_query: send(): %m");
-
- data_string_forget(&ds, MDL);
-
- return cc;
-}
-
-/*
- * \brief Forward a DHCPv4-query to all DHCPv4 over DHCPv6 server addresses.
- * (DHCPv6 client function)
- *
- * \param raw the DHCPv6 DHCPv4-query message raw content
- */
-static void forw_dhcpv4_query(struct data_string *raw) {
- struct interface_info *ip;
- struct client_state *client;
- struct dhc6_lease *lease;
- struct option_cache *oc;
- struct data_string addrs;
- struct sockaddr_in6 sin6;
- int i, send_ret, attempt, success;
-
- attempt = success = 0;
- memset(&sin6, 0, sizeof(sin6));
- sin6.sin6_family = AF_INET6;
- sin6.sin6_port = remote_port;
-#ifdef HAVE_SA_LEN
- sin6.sin6_len = sizeof(sin6);
-#endif
- memset(&addrs, 0, sizeof(addrs));
- for (ip = interfaces; ip != NULL; ip = ip->next) {
- for (client = ip->client; client != NULL;
- client = client->next) {
- if ((client->state != S_BOUND) &&
- (client->state != S_RENEWING) &&
- (client->state != S_REBINDING))
- continue;
- lease = client->active_lease;
- if ((lease == NULL) || lease->released)
- continue;
- oc = lookup_option(&dhcpv6_universe,
- lease->options,
- D6O_DHCP4_O_DHCP6_SERVER);
- if ((oc == NULL) ||
- !evaluate_option_cache(&addrs, NULL, NULL, NULL,
- lease->options, NULL,
- &global_scope, oc, MDL) ||
- ((addrs.len % sizeof(sin6.sin6_addr)) != 0)) {
- data_string_forget(&addrs, MDL);
- continue;
- }
- if (addrs.len == 0) {
- /* note there is nothing to forget */
- inet_pton(AF_INET6,
- All_DHCP_Relay_Agents_and_Servers,
- &sin6.sin6_addr);
- attempt++;
- send_ret = send_packet6(ip, raw->data,
- raw->len, &sin6);
- if (send_ret == raw->len)
- success++;
- continue;
- }
- for (i = 0; i < addrs.len;
- i += sizeof(sin6.sin6_addr)) {
- memcpy(&sin6.sin6_addr, addrs.data + i,
- sizeof(sin6.sin6_addr));
- attempt++;
- send_ret = send_packet6(ip, raw->data,
- raw->len, &sin6);
- if (send_ret == raw->len)
- success++;
- }
- data_string_forget(&addrs, MDL);
- }
- }
-
- log_info("forw_dhcpv4_query: sent(%d): %d/%d",
- raw->len, success, attempt);
-
- if (attempt == 0)
- dhcp4o6_stop();
-}
-#endif
-
-void
-make_client_options(struct client_state *client, struct client_lease *lease,
- u_int8_t *type, struct option_cache *sid,
- struct iaddr *rip, struct option **prl,
- struct option_state **op)
-{
- unsigned i;
- struct option_cache *oc;
- struct option *option = NULL;
- struct buffer *bp = NULL;
-
- /* If there are any leftover options, get rid of them. */
- if (*op)
- option_state_dereference(op, MDL);
-
- /* Allocate space for options. */
- option_state_allocate(op, MDL);
-
- /* Send the server identifier if provided. */
- if (sid)
- save_option(&dhcp_universe, *op, sid);
-
- oc = NULL;
-
- /* Send the requested address if provided. */
- if (rip) {
- client->requested_address = *rip;
- i = DHO_DHCP_REQUESTED_ADDRESS;
- if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash,
- &i, 0, MDL) &&
- make_const_option_cache(&oc, NULL, rip->iabuf, rip->len,
- option, MDL)))
- log_error ("can't make requested address cache.");
- else {
- save_option(&dhcp_universe, *op, oc);
- option_cache_dereference(&oc, MDL);
- }
- option_dereference(&option, MDL);
- } else {
- client->requested_address.len = 0;
- }
-
- i = DHO_DHCP_MESSAGE_TYPE;
- if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash, &i, 0,
- MDL) &&
- make_const_option_cache(&oc, NULL, type, 1, option, MDL)))
- log_error("can't make message type.");
- else {
- save_option(&dhcp_universe, *op, oc);
- option_cache_dereference(&oc, MDL);
- }
- option_dereference(&option, MDL);
-
- if (prl) {
- int len;
-
- /* Probe the length of the list. */
- len = 0;
- for (i = 0 ; prl[i] != NULL ; i++)
- if (prl[i]->universe == &dhcp_universe)
- len++;
-
- if (!buffer_allocate(&bp, len, MDL))
- log_error("can't make parameter list buffer.");
- else {
- unsigned code = DHO_DHCP_PARAMETER_REQUEST_LIST;
-
- len = 0;
- for (i = 0 ; prl[i] != NULL ; i++)
- if (prl[i]->universe == &dhcp_universe)
- bp->data[len++] = prl[i]->code;
-
- if (!(option_code_hash_lookup(&option,
- dhcp_universe.code_hash,
- &code, 0, MDL) &&
- make_const_option_cache(&oc, &bp, NULL, len,
- option, MDL))) {
- if (bp != NULL)
- buffer_dereference(&bp, MDL);
- log_error ("can't make option cache");
- } else {
- save_option(&dhcp_universe, *op, oc);
- option_cache_dereference(&oc, MDL);
- }
- option_dereference(&option, MDL);
- }
- }
-
- /*
- * If requested (duid_v4 == 1) add an RFC4361 compliant client-identifier
- * This can be overridden by including a client id in the configuration
- * file.
- */
- if (duid_v4 == 1) {
- struct data_string client_identifier;
- int hw_idx, hw_len;
-
- memset(&client_identifier, 0, sizeof(client_identifier));
- client_identifier.len = 1 + 4 + default_duid.len;
- if (!buffer_allocate(&client_identifier.buffer,
- client_identifier.len, MDL))
- log_fatal("no memory for default DUID!");
- client_identifier.data = client_identifier.buffer->data;
-
- i = DHO_DHCP_CLIENT_IDENTIFIER;
-
- /* Client-identifier type : 1 byte */
- *client_identifier.buffer->data = 255;
-
- /* IAID : 4 bytes
- * we use the low 4 bytes from the interface address
- */
- if (client->interface->hw_address.hlen > 4) {
- hw_idx = client->interface->hw_address.hlen - 4;
- hw_len = 4;
- } else {
- hw_idx = 0;
- hw_len = client->interface->hw_address.hlen;
- }
- memcpy(client_identifier.buffer->data + 5 - hw_len,
- client->interface->hw_address.hbuf + hw_idx,
- hw_len);
-
- /* Add the default duid */
- memcpy(client_identifier.buffer->data + (1 + 4),
- default_duid.data, default_duid.len);
-
- /* And save the option */
- if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash,
- &i, 0, MDL) &&
- make_const_option_cache(&oc, NULL,
- (u_int8_t *)client_identifier.data,
- client_identifier.len,
- option, MDL)))
- log_error ("can't make requested client id cache..");
- else {
- save_option (&dhcp_universe, *op, oc);
- option_cache_dereference (&oc, MDL);
- }
- option_dereference(&option, MDL);
- }
-
- /* Run statements that need to be run on transmission. */
- if (client->config->on_transmission)
- execute_statements_in_scope(NULL, NULL, NULL, client,
- (lease ? lease->options : NULL),
- *op, &global_scope,
- client->config->on_transmission,
- NULL, NULL);
-}
-
-void make_discover (client, lease)
- struct client_state *client;
- struct client_lease *lease;
-{
- unsigned char discover = DHCPDISCOVER;
- struct option_state *options = (struct option_state *)0;
-
- memset (&client -> packet, 0, sizeof (client -> packet));
-
- make_client_options (client,
- lease, &discover, (struct option_cache *)0,
- lease ? &lease -> address : (struct iaddr *)0,
- client -> config -> requested_options,
- &options);
-
- /* Set up the option buffer... */
- client -> packet_length =
- cons_options ((struct packet *)0, &client -> packet,
- (struct lease *)0, client,
- /* maximum packet size */1500,
- (struct option_state *)0,
- options,
- /* scope */ &global_scope,
- /* overload */ 0,
- /* terminate */0,
- /* bootpp */0,
- (struct data_string *)0,
- client -> config -> vendor_space_name);
-
- option_state_dereference (&options, MDL);
- if (client -> packet_length < BOOTP_MIN_LEN)
- client -> packet_length = BOOTP_MIN_LEN;
-
- client -> packet.op = BOOTREQUEST;
- client -> packet.htype = client -> interface -> hw_address.hbuf [0];
- /* Assumes hw_address is known, otherwise a random value may result */
- client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
- client -> packet.hops = 0;
- client -> packet.xid = random ();
- client -> packet.secs = 0; /* filled in by send_discover. */
-
- if (can_receive_unicast_unconfigured (client -> interface))
- client -> packet.flags = 0;
- else
- client -> packet.flags = htons (BOOTP_BROADCAST);
-
- memset (&(client -> packet.ciaddr),
- 0, sizeof client -> packet.ciaddr);
- memset (&(client -> packet.yiaddr),
- 0, sizeof client -> packet.yiaddr);
- memset (&(client -> packet.siaddr),
- 0, sizeof client -> packet.siaddr);
- client -> packet.giaddr = giaddr;
- if (client -> interface -> hw_address.hlen > 0)
- memcpy (client -> packet.chaddr,
- &client -> interface -> hw_address.hbuf [1],
- (unsigned)(client -> interface -> hw_address.hlen - 1));
-
-#ifdef DEBUG_PACKET
- dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
-#endif
-}
-
-
-void make_request (client, lease)
- struct client_state *client;
- struct client_lease *lease;
-{
- unsigned char request = DHCPREQUEST;
- struct option_cache *oc;
-
- memset (&client -> packet, 0, sizeof (client -> packet));
-
- if (client -> state == S_REQUESTING)
- oc = lookup_option (&dhcp_universe, lease -> options,
- DHO_DHCP_SERVER_IDENTIFIER);
- else
- oc = (struct option_cache *)0;
-
- if (client -> sent_options)
- option_state_dereference (&client -> sent_options, MDL);
-
- make_client_options (client, lease, &request, oc,
- ((client -> state == S_REQUESTING ||
- client -> state == S_REBOOTING)
- ? &lease -> address
- : (struct iaddr *)0),
- client -> config -> requested_options,
- &client -> sent_options);
-
- /* Set up the option buffer... */
- client -> packet_length =
- cons_options ((struct packet *)0, &client -> packet,
- (struct lease *)0, client,
- /* maximum packet size */1500,
- (struct option_state *)0,
- client -> sent_options,
- /* scope */ &global_scope,
- /* overload */ 0,
- /* terminate */0,
- /* bootpp */0,
- (struct data_string *)0,
- client -> config -> vendor_space_name);
-
- if (client -> packet_length < BOOTP_MIN_LEN)
- client -> packet_length = BOOTP_MIN_LEN;
-
- client -> packet.op = BOOTREQUEST;
- client -> packet.htype = client -> interface -> hw_address.hbuf [0];
- /* Assumes hw_address is known, otherwise a random value may result */
- client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
- client -> packet.hops = 0;
- client -> packet.xid = client -> xid;
- client -> packet.secs = 0; /* Filled in by send_request. */
-
- /* If we own the address we're requesting, put it in ciaddr;
- otherwise set ciaddr to zero. */
- if (client -> state == S_BOUND ||
- client -> state == S_RENEWING ||
- client -> state == S_REBINDING) {
- memcpy (&client -> packet.ciaddr,
- lease -> address.iabuf, lease -> address.len);
- client -> packet.flags = 0;
- } else {
- memset (&client -> packet.ciaddr, 0,
- sizeof client -> packet.ciaddr);
- if (can_receive_unicast_unconfigured (client -> interface))
- client -> packet.flags = 0;
- else
- client -> packet.flags = htons (BOOTP_BROADCAST);
- }
-
- memset (&client -> packet.yiaddr, 0,
- sizeof client -> packet.yiaddr);
- memset (&client -> packet.siaddr, 0,
- sizeof client -> packet.siaddr);
- if (client -> state != S_BOUND &&
- client -> state != S_RENEWING)
- client -> packet.giaddr = giaddr;
- else
- memset (&client -> packet.giaddr, 0,
- sizeof client -> packet.giaddr);
- if (client -> interface -> hw_address.hlen > 0)
- memcpy (client -> packet.chaddr,
- &client -> interface -> hw_address.hbuf [1],
- (unsigned)(client -> interface -> hw_address.hlen - 1));
-
-#ifdef DEBUG_PACKET
- dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
-#endif
-}
-
-void make_decline (client, lease)
- struct client_state *client;
- struct client_lease *lease;
-{
- unsigned char decline = DHCPDECLINE;
- struct option_cache *oc;
-
- struct option_state *options = (struct option_state *)0;
-
- /* Create the options cache. */
- oc = lookup_option (&dhcp_universe, lease -> options,
- DHO_DHCP_SERVER_IDENTIFIER);
- make_client_options(client, lease, &decline, oc, &lease->address,
- NULL, &options);
-
- /* Consume the options cache into the option buffer. */
- memset (&client -> packet, 0, sizeof (client -> packet));
- client -> packet_length =
- cons_options ((struct packet *)0, &client -> packet,
- (struct lease *)0, client, 0,
- (struct option_state *)0, options,
- &global_scope, 0, 0, 0, (struct data_string *)0,
- client -> config -> vendor_space_name);
-
- /* Destroy the options cache. */
- option_state_dereference (&options, MDL);
-
- if (client -> packet_length < BOOTP_MIN_LEN)
- client -> packet_length = BOOTP_MIN_LEN;
-
- client -> packet.op = BOOTREQUEST;
- client -> packet.htype = client -> interface -> hw_address.hbuf [0];
- /* Assumes hw_address is known, otherwise a random value may result */
- client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
- client -> packet.hops = 0;
- client -> packet.xid = client -> xid;
- client -> packet.secs = 0; /* Filled in by send_request. */
- if (can_receive_unicast_unconfigured (client -> interface))
- client -> packet.flags = 0;
- else
- client -> packet.flags = htons (BOOTP_BROADCAST);
-
- /* ciaddr must always be zero. */
- memset (&client -> packet.ciaddr, 0,
- sizeof client -> packet.ciaddr);
- memset (&client -> packet.yiaddr, 0,
- sizeof client -> packet.yiaddr);
- memset (&client -> packet.siaddr, 0,
- sizeof client -> packet.siaddr);
- client -> packet.giaddr = giaddr;
- memcpy (client -> packet.chaddr,
- &client -> interface -> hw_address.hbuf [1],
- client -> interface -> hw_address.hlen);
-
-#ifdef DEBUG_PACKET
- dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
-#endif
-}
-
-void make_release (client, lease)
- struct client_state *client;
- struct client_lease *lease;
-{
- unsigned char request = DHCPRELEASE;
- struct option_cache *oc;
-
- struct option_state *options = (struct option_state *)0;
-
- memset (&client -> packet, 0, sizeof (client -> packet));
-
- oc = lookup_option (&dhcp_universe, lease -> options,
- DHO_DHCP_SERVER_IDENTIFIER);
- make_client_options(client, lease, &request, oc, NULL, NULL, &options);
-
- /* Set up the option buffer... */
- client -> packet_length =
- cons_options ((struct packet *)0, &client -> packet,
- (struct lease *)0, client,
- /* maximum packet size */1500,
- (struct option_state *)0,
- options,
- /* scope */ &global_scope,
- /* overload */ 0,
- /* terminate */0,
- /* bootpp */0,
- (struct data_string *)0,
- client -> config -> vendor_space_name);
-
- if (client -> packet_length < BOOTP_MIN_LEN)
- client -> packet_length = BOOTP_MIN_LEN;
- option_state_dereference (&options, MDL);
-
- client -> packet.op = BOOTREQUEST;
- client -> packet.htype = client -> interface -> hw_address.hbuf [0];
- /* Assumes hw_address is known, otherwise a random value may result */
- client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
- client -> packet.hops = 0;
- client -> packet.xid = random ();
- client -> packet.secs = 0;
- client -> packet.flags = 0;
- memcpy (&client -> packet.ciaddr,
- lease -> address.iabuf, lease -> address.len);
- memset (&client -> packet.yiaddr, 0,
- sizeof client -> packet.yiaddr);
- memset (&client -> packet.siaddr, 0,
- sizeof client -> packet.siaddr);
- client -> packet.giaddr = giaddr;
- memcpy (client -> packet.chaddr,
- &client -> interface -> hw_address.hbuf [1],
- client -> interface -> hw_address.hlen);
-
-#ifdef DEBUG_PACKET
- dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
-#endif
-}
-
-void destroy_client_lease (lease)
- struct client_lease *lease;
-{
- if (lease -> server_name)
- dfree (lease -> server_name, MDL);
- if (lease -> filename)
- dfree (lease -> filename, MDL);
- option_state_dereference (&lease -> options, MDL);
- free_client_lease (lease, MDL);
-}
-
-FILE *leaseFile = NULL;
-int leases_written = 0;
-
-void rewrite_client_leases ()
-{
- struct interface_info *ip;
- struct client_state *client;
- struct client_lease *lp;
-
- if (leaseFile != NULL)
- fclose (leaseFile);
- leaseFile = fopen (path_dhclient_db, "w");
- if (leaseFile == NULL) {
- log_error ("can't create %s: %m", path_dhclient_db);
- return;
- }
-
- /* If there is a default duid, write it out. */
- if (default_duid.len != 0)
- write_duid(&default_duid);
-
- /* Write out all the leases attached to configured interfaces that
- we know about. */
- for (ip = interfaces; ip; ip = ip -> next) {
- for (client = ip -> client; client; client = client -> next) {
- for (lp = client -> leases; lp; lp = lp -> next) {
- write_client_lease (client, lp, 1, 0);
- }
- if (client -> active)
- write_client_lease (client,
- client -> active, 1, 0);
-
- if (client->active_lease != NULL)
- write_client6_lease(client,
- client->active_lease,
- 1, 0);
-
- /* Reset last_write after rewrites. */
- client->last_write = 0;
- }
- }
-
- /* Write out any leases that are attached to interfaces that aren't
- currently configured. */
- for (ip = dummy_interfaces; ip; ip = ip -> next) {
- for (client = ip -> client; client; client = client -> next) {
- for (lp = client -> leases; lp; lp = lp -> next) {
- write_client_lease (client, lp, 1, 0);
- }
- if (client -> active)
- write_client_lease (client,
- client -> active, 1, 0);
-
- if (client->active_lease != NULL)
- write_client6_lease(client,
- client->active_lease,
- 1, 0);
-
- /* Reset last_write after rewrites. */
- client->last_write = 0;
- }
- }
- fflush (leaseFile);
-}
-
-void write_lease_option (struct option_cache *oc,
- struct packet *packet, struct lease *lease,
- struct client_state *client_state,
- struct option_state *in_options,
- struct option_state *cfg_options,
- struct binding_scope **scope,
- struct universe *u, void *stuff)
-{
- const char *name, *dot;
- struct data_string ds;
- char *preamble = stuff;
-
- memset (&ds, 0, sizeof ds);
-
- if (u != &dhcp_universe) {
- name = u -> name;
- dot = ".";
- } else {
- name = "";
- dot = "";
- }
- if (evaluate_option_cache (&ds, packet, lease, client_state,
- in_options, cfg_options, scope, oc, MDL)) {
- /* The option name */
- fprintf(leaseFile, "%soption %s%s%s", preamble,
- name, dot, oc->option->name);
-
- /* The option value if there is one */
- if ((oc->option->format == NULL) ||
- (oc->option->format[0] != 'Z')) {
- fprintf(leaseFile, " %s",
- pretty_print_option(oc->option, ds.data,
- ds.len, 1, 1));
- }
-
- /* The closing semi-colon and newline */
- fprintf(leaseFile, ";\n");
-
- data_string_forget (&ds, MDL);
- }
-}
-
-/* Write an option cache to the lease store. */
-static void
-write_options(struct client_state *client, struct option_state *options,
- const char *preamble)
-{
- int i;
-
- for (i = 0; i < options->universe_count; i++) {
- option_space_foreach(NULL, NULL, client, NULL, options,
- &global_scope, universes[i],
- (char *)preamble, write_lease_option);
- }
-}
-
-/*
- * The "best" default DUID, since we cannot predict any information
- * about the system (such as whether or not the hardware addresses are
- * integrated into the motherboard or similar), is the "LLT", link local
- * plus time, DUID. For real stateless "LL" is better.
- *
- * Once generated, this duid is stored into the state database, and
- * retained across restarts.
- *
- * For the time being, there is probably a different state database for
- * every daemon, so this winds up being a per-interface identifier...which
- * is not how it is intended. Upcoming rearchitecting the client should
- * address this "one daemon model."
- */
-void
-form_duid(struct data_string *duid, const char *file, int line)
-{
- struct interface_info *ip;
- int len;
- char *str;
-
- /* For now, just use the first interface on the list. */
- ip = interfaces;
-
- if (ip == NULL)
- log_fatal("Impossible condition at %s:%d.", MDL);
-
- if ((ip->hw_address.hlen == 0) ||
- (ip->hw_address.hlen > sizeof(ip->hw_address.hbuf)))
- log_fatal("Impossible hardware address length at %s:%d.", MDL);
-
- if (duid_type == 0)
- duid_type = stateless ? DUID_LL : DUID_LLT;
-
- /*
- * 2 bytes for the 'duid type' field.
- * 2 bytes for the 'htype' field.
- * (DUID_LLT) 4 bytes for the 'current time'.
- * enough bytes for the hardware address (note that hw_address has
- * the 'htype' on byte zero).
- */
- len = 4 + (ip->hw_address.hlen - 1);
- if (duid_type == DUID_LLT)
- len += 4;
- if (!buffer_allocate(&duid->buffer, len, MDL))
- log_fatal("no memory for default DUID!");
- duid->data = duid->buffer->data;
- duid->len = len;
-
- /* Basic Link Local Address type of DUID. */
- if (duid_type == DUID_LLT) {
- putUShort(duid->buffer->data, DUID_LLT);
- putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]);
- putULong(duid->buffer->data + 4, cur_time - DUID_TIME_EPOCH);
- memcpy(duid->buffer->data + 8, ip->hw_address.hbuf + 1,
- ip->hw_address.hlen - 1);
- } else {
- putUShort(duid->buffer->data, DUID_LL);
- putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]);
- memcpy(duid->buffer->data + 4, ip->hw_address.hbuf + 1,
- ip->hw_address.hlen - 1);
- }
-
- /* Now format the output based on lease-id-format */
- str = format_lease_id(duid->data, duid->len,
- top_level_config.lease_id_format, MDL);
- if (str == NULL) {
- log_info("form_duid: Couldn't allocate memory to log duid!");
- } else {
- log_info("Created duid %s.", str);
- dfree(str, MDL);
- }
-}
-
-/* Write the default DUID to the lease store. */
-static isc_result_t
-write_duid(struct data_string *duid)
-{
- char *str;
- int stat;
-
- if ((duid == NULL) || (duid->len <= 2))
- return DHCP_R_INVALIDARG;
-
- if (leaseFile == NULL) { /* XXX? */
- leaseFile = fopen(path_dhclient_db, "w");
- if (leaseFile == NULL) {
- log_error("can't create %s: %m", path_dhclient_db);
- return ISC_R_IOERROR;
- }
- }
-
- /* Generate a formatted duid string per lease-id-format */
- str = format_lease_id(duid->data, duid->len,
- top_level_config.lease_id_format, MDL);
- if (str == NULL)
- return ISC_R_NOMEMORY;
-
- stat = fprintf(leaseFile, "default-duid %s;\n", str);
- dfree(str, MDL);
- if (stat <= 0)
- return ISC_R_IOERROR;
-
- if (fflush(leaseFile) != 0)
- return ISC_R_IOERROR;
-
- return ISC_R_SUCCESS;
-}
-
-/* Write a DHCPv6 lease to the store. */
-isc_result_t
-write_client6_lease(struct client_state *client, struct dhc6_lease *lease,
- int rewrite, int sync)
-{
- struct dhc6_ia *ia;
- struct dhc6_addr *addr;
- int stat;
- const char *ianame;
-
- /* This should include the current lease. */
- if (!rewrite && (leases_written++ > 20)) {
- rewrite_client_leases();
- leases_written = 0;
- return ISC_R_SUCCESS;
- }
-
- if (client == NULL || lease == NULL)
- return DHCP_R_INVALIDARG;
-
- if (leaseFile == NULL) { /* XXX? */
- leaseFile = fopen(path_dhclient_db, "w");
- if (leaseFile == NULL) {
- log_error("can't create %s: %m", path_dhclient_db);
- return ISC_R_IOERROR;
- }
- }
-
- stat = fprintf(leaseFile, "lease6 {\n");
- if (stat <= 0)
- return ISC_R_IOERROR;
-
- stat = fprintf(leaseFile, " interface \"%s\";\n",
- client->interface->name);
- if (stat <= 0)
- return ISC_R_IOERROR;
-
- for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
- switch (ia->ia_type) {
- case D6O_IA_NA:
- default:
- ianame = "ia-na";
- break;
- case D6O_IA_TA:
- ianame = "ia-ta";
- break;
- case D6O_IA_PD:
- ianame = "ia-pd";
- break;
- }
-
- /* For some reason IAID was never octal or hex, but string or
- * hex. Go figure. So for compatibilty's sake we will either
- * do hex or "legacy" i.e string rather than octal. What a
- * cluster. */
- switch(top_level_config.lease_id_format) {
- case TOKEN_HEX: {
- char* iaid_str = format_lease_id(
- (const unsigned char *) &ia->iaid, 4,
- top_level_config.lease_id_format, MDL);
-
- if (!iaid_str) {
- log_error("Can't format iaid");
- return ISC_R_IOERROR;
- }
-
- stat = fprintf(leaseFile, " %s %s {\n",
- ianame, iaid_str);
- dfree(iaid_str, MDL);
- break;
- }
-
- case TOKEN_OCTAL:
- default:
- stat = fprintf(leaseFile, " %s %s {\n", ianame,
- print_hex_1(4, ia->iaid, 12));
- break;
- }
-
- if (stat <= 0)
- return ISC_R_IOERROR;
-
- if (ia->ia_type != D6O_IA_TA)
- stat = fprintf(leaseFile, " starts %d;\n"
- " renew %u;\n"
- " rebind %u;\n",
- (int)ia->starts, ia->renew, ia->rebind);
- else
- stat = fprintf(leaseFile, " starts %d;\n",
- (int)ia->starts);
- if (stat <= 0)
- return ISC_R_IOERROR;
-
- for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
- if (ia->ia_type != D6O_IA_PD)
- stat = fprintf(leaseFile,
- " iaaddr %s {\n",
- piaddr(addr->address));
- else
- stat = fprintf(leaseFile,
- " iaprefix %s/%d {\n",
- piaddr(addr->address),
- (int)addr->plen);
- if (stat <= 0)
- return ISC_R_IOERROR;
-
- stat = fprintf(leaseFile, " starts %d;\n"
- " preferred-life %u;\n"
- " max-life %u;\n",
- (int)addr->starts, addr->preferred_life,
- addr->max_life);
- if (stat <= 0)
- return ISC_R_IOERROR;
-
- if (addr->options != NULL)
- write_options(client, addr->options, " ");
-
- stat = fprintf(leaseFile, " }\n");
- if (stat <= 0)
- return ISC_R_IOERROR;
- }
-
- if (ia->options != NULL)
- write_options(client, ia->options, " ");
-
- stat = fprintf(leaseFile, " }\n");
- if (stat <= 0)
- return ISC_R_IOERROR;
- }
-
- if (lease->released) {
- stat = fprintf(leaseFile, " released;\n");
- if (stat <= 0)
- return ISC_R_IOERROR;
- }
-
- if (lease->options != NULL)
- write_options(client, lease->options, " ");
-
- stat = fprintf(leaseFile, "}\n");
- if (stat <= 0)
- return ISC_R_IOERROR;
-
- if (fflush(leaseFile) != 0)
- return ISC_R_IOERROR;
-
- if (sync) {
- if (fsync(fileno(leaseFile)) < 0) {
- log_error("write_client_lease: fsync(): %m");
- return ISC_R_IOERROR;
- }
- }
-
- return ISC_R_SUCCESS;
-}
-
-int write_client_lease (client, lease, rewrite, makesure)
- struct client_state *client;
- struct client_lease *lease;
- int rewrite;
- int makesure;
-{
- struct data_string ds;
- int errors = 0;
- char *s;
- const char *tval;
-
- if (!rewrite) {
- if (leases_written++ > 20) {
- rewrite_client_leases ();
- leases_written = 0;
- }
- }
-
- /* If the lease came from the config file, we don't need to stash
- a copy in the lease database. */
- if (lease -> is_static)
- return 1;
-
- if (leaseFile == NULL) { /* XXX */
- leaseFile = fopen (path_dhclient_db, "w");
- if (leaseFile == NULL) {
- log_error ("can't create %s: %m", path_dhclient_db);
- return 0;
- }
- }
-
- errno = 0;
- fprintf (leaseFile, "lease {\n");
- if (lease -> is_bootp) {
- fprintf (leaseFile, " bootp;\n");
- if (errno) {
- ++errors;
- errno = 0;
- }
- }
- fprintf (leaseFile, " interface \"%s\";\n",
- client -> interface -> name);
- if (errno) {
- ++errors;
- errno = 0;
- }
- if (client -> name) {
- fprintf (leaseFile, " name \"%s\";\n", client -> name);
- if (errno) {
- ++errors;
- errno = 0;
- }
- }
- fprintf (leaseFile, " fixed-address %s;\n",
- piaddr (lease -> address));
- if (errno) {
- ++errors;
- errno = 0;
- }
- if (lease -> filename) {
- s = quotify_string (lease -> filename, MDL);
- if (s) {
- fprintf (leaseFile, " filename \"%s\";\n", s);
- if (errno) {
- ++errors;
- errno = 0;
- }
- dfree (s, MDL);
- } else
- errors++;
-
- }
- if (lease->server_name != NULL) {
- s = quotify_string(lease->server_name, MDL);
- if (s != NULL) {
- fprintf(leaseFile, " server-name \"%s\";\n", s);
- if (errno) {
- ++errors;
- errno = 0;
- }
- dfree(s, MDL);
- } else
- ++errors;
- }
- if (lease -> medium) {
- s = quotify_string (lease -> medium -> string, MDL);
- if (s) {
- fprintf (leaseFile, " medium \"%s\";\n", s);
- if (errno) {
- ++errors;
- errno = 0;
- }
- dfree (s, MDL);
- } else
- errors++;
- }
- if (errno != 0) {
- errors++;
- errno = 0;
- }
-
- memset (&ds, 0, sizeof ds);
-
- write_options(client, lease->options, " ");
-
- tval = print_time(lease->renewal);
- if (tval == NULL ||
- fprintf(leaseFile, " renew %s\n", tval) < 0)
- errors++;
-
- tval = print_time(lease->rebind);
- if (tval == NULL ||
- fprintf(leaseFile, " rebind %s\n", tval) < 0)
- errors++;
-
- tval = print_time(lease->expiry);
- if (tval == NULL ||
- fprintf(leaseFile, " expire %s\n", tval) < 0)
- errors++;
-
- if (fprintf(leaseFile, "}\n") < 0)
- errors++;
-
- if (fflush(leaseFile) != 0)
- errors++;
-
- client->last_write = cur_time;
-
- if (!errors && makesure) {
- if (fsync (fileno (leaseFile)) < 0) {
- log_info ("write_client_lease: %m");
- return 0;
- }
- }
-
- return errors ? 0 : 1;
-}
-
-/* Variables holding name of script and file pointer for writing to
- script. Needless to say, this is not reentrant - only one script
- can be invoked at a time. */
-char scriptName [256];
-FILE *scriptFile;
-
-/**
- * @brief Initializes basic variables for a script
- *
- * This function is called as an initial preparation for calling a script.
- * It sets up a number of common env. variables that will be passed to
- * the script. For actual script calling, see @ref script_go .
- *
- * @param client variables will be stored here (if null, the whole function
- * is no-op)
- * @param reason specified the reason for calling a script (must be non-null)
- * @param medium if specified, defines medium type (may be null)
- */
-void script_init(struct client_state *client, const char *reason,
- struct string_list *medium)
-{
- struct string_list *sl, *next;
-
- if (client) {
- for (sl = client -> env; sl; sl = next) {
- next = sl -> next;
- dfree (sl, MDL);
- }
- client -> env = (struct string_list *)0;
- client -> envc = 0;
-
- if (client -> interface) {
- client_envadd (client, "", "interface", "%s",
- client -> interface -> name);
- }
- if (client -> name)
- client_envadd (client,
- "", "client", "%s", client -> name);
- if (medium)
- client_envadd (client,
- "", "medium", "%s", medium -> string);
-
- client_envadd (client, "", "reason", "%s", reason);
- client_envadd (client, "", "pid", "%ld", (long int)getpid ());
-#if defined(DHCPv6)
- client_envadd (client, "", "dad_wait_time", "%ld",
- (long int)dad_wait_time);
-#endif
- }
-}
-
-void client_option_envadd (struct option_cache *oc,
- struct packet *packet, struct lease *lease,
- struct client_state *client_state,
- struct option_state *in_options,
- struct option_state *cfg_options,
- struct binding_scope **scope,
- struct universe *u, void *stuff)
-{
- struct envadd_state *es = stuff;
- struct data_string data;
- memset (&data, 0, sizeof data);
-
- if (evaluate_option_cache (&data, packet, lease, client_state,
- in_options, cfg_options, scope, oc, MDL)) {
- if (data.len) {
- char name [256];
- if (dhcp_option_ev_name (name, sizeof name,
- oc->option)) {
- const char *value;
- size_t length;
- value = pretty_print_option(oc->option,
- data.data,
- data.len, 0, 0);
- length = strlen(value);
-
- if (check_option_values(oc->option->universe,
- oc->option->code,
- value, length) == 0) {
- client_envadd(es->client, es->prefix,
- name, "%s", value);
- } else {
- log_error("suspect value in %s "
- "option - discarded",
- name);
- }
- }
- }
-
- data_string_forget (&data, MDL);
- }
-}
-
-/**
- * @brief Adds parameters to environment variables for a script
- *
- * This function add details of specified lease to a list of env. variables
- * to be passed to a script. The lease details will be prepended with
- * specified prefix (e.g. "old_") and added to the list stored in client.
- * Following variables may be set:
- * - ip_address
- * - next_server
- * - network_number
- * - broadcast_address
- * - filename
- * - server_name
- * - expiry
- *
- * @param client env. variables will be stored here
- * @param prefix textual prefix to be added to each variable (e.g. "old_")
- * @param lease lease details will be extracted from here
- */
-void script_write_params(struct client_state *client, const char *prefix,
- struct client_lease *lease)
-{
- int i;
- struct data_string data;
- struct option_cache *oc;
- struct envadd_state es;
-
- es.client = client;
- es.prefix = prefix;
-
- client_envadd (client,
- prefix, "ip_address", "%s", piaddr (lease -> address));
-
- /* If we've set the next server address in the lease structure
- put it into an environment variable for the script */
- if (lease->next_srv_addr.len != 0) {
- client_envadd(client, prefix, "next_server", "%s",
- piaddr(lease->next_srv_addr));
- }
-
- /* For the benefit of Linux (and operating systems which may
- have similar needs), compute the network address based on
- the supplied ip address and netmask, if provided. Also
- compute the broadcast address (the host address all ones
- broadcast address, not the host address all zeroes
- broadcast address). */
-
- memset (&data, 0, sizeof data);
- oc = lookup_option (&dhcp_universe, lease -> options, DHO_SUBNET_MASK);
- if (oc && evaluate_option_cache (&data, (struct packet *)0,
- (struct lease *)0, client,
- (struct option_state *)0,
- lease -> options,
- &global_scope, oc, MDL)) {
- if (data.len > 3) {
- struct iaddr netmask, subnet, broadcast;
-
- /*
- * No matter the length of the subnet-mask option,
- * use only the first four octets. Note that
- * subnet-mask options longer than 4 octets are not
- * in conformance with RFC 2132, but servers with this
- * flaw do exist.
- */
- memcpy(netmask.iabuf, data.data, 4);
- netmask.len = 4;
- data_string_forget (&data, MDL);
-
- subnet = subnet_number (lease -> address, netmask);
- if (subnet.len) {
- client_envadd (client, prefix, "network_number",
- "%s", piaddr (subnet));
-
- oc = lookup_option (&dhcp_universe,
- lease -> options,
- DHO_BROADCAST_ADDRESS);
- if (!oc ||
- !(evaluate_option_cache
- (&data, (struct packet *)0,
- (struct lease *)0, client,
- (struct option_state *)0,
- lease -> options,
- &global_scope, oc, MDL))) {
- broadcast = broadcast_addr (subnet, netmask);
- if (broadcast.len) {
- client_envadd (client,
- prefix, "broadcast_address",
- "%s", piaddr (broadcast));
- }
- }
- }
- }
- data_string_forget (&data, MDL);
- }
-
- if (lease->filename) {
- if (check_option_values(NULL, DHO_ROOT_PATH,
- lease->filename,
- strlen(lease->filename)) == 0) {
- client_envadd(client, prefix, "filename",
- "%s", lease->filename);
- } else {
- log_error("suspect value in %s "
- "option - discarded",
- lease->filename);
- }
- }
-
- if (lease->server_name) {
- if (check_option_values(NULL, DHO_HOST_NAME,
- lease->server_name,
- strlen(lease->server_name)) == 0 ) {
- client_envadd (client, prefix, "server_name",
- "%s", lease->server_name);
- } else {
- log_error("suspect value in %s "
- "option - discarded",
- lease->server_name);
- }
- }
-
- for (i = 0; i < lease -> options -> universe_count; i++) {
- option_space_foreach ((struct packet *)0, (struct lease *)0,
- client, (struct option_state *)0,
- lease -> options, &global_scope,
- universes [i],
- &es, client_option_envadd);
- }
-
- client_envadd (client, prefix, "expiry", "%lu",
- (unsigned long)(lease -> expiry));
-}
-
-/**
- * @brief Write out the environent variable the client requested.
- * Write out the environment variables for the objects that the
- * client requested. If the object was requested the variable will be:
- * requested_<option_name>=1
- * If it wasn't requested there won't be a variable.
- *
- * @param client client structure
- */
-void script_write_requested(struct client_state *client)
-{
- int i;
- struct option **req;
- char name[256];
- req = client->config->requested_options;
-
- if (req == NULL)
- return;
-
- for (i = 0 ; req[i] != NULL ; i++) {
- if ((req[i]->universe == &dhcp_universe) &&
- dhcp_option_ev_name(name, sizeof(name), req[i])) {
- client_envadd(client, "requested_", name, "%d", 1);
- }
- }
-}
-
-/**
- * @brief Calls external script.
- *
- * External script is specified either using -sf command line or
- * script parameter in the configuration file.
- *
- * @param client specifies client information (environment variables,
- * and other parameters will be extracted and passed to the script.
- * @return If positive, it contains exit code of the process running script.
- * If negative, returns the signal number that cause the script process
- * to terminate.
- */
-int script_go(struct client_state *client)
-{
- char *scriptName;
- char *argv [2];
- char **envp;
- char reason [] = "REASON=NBI";
- static char client_path [] = CLIENT_PATH;
- int i;
- struct string_list *sp, *next;
- int pid, wpid, wstatus;
-
- if (client)
- scriptName = client -> config -> script_name;
- else
- scriptName = top_level_config.script_name;
-
- envp = dmalloc (((client ? client -> envc : 2) +
- client_env_count + 2) * sizeof (char *), MDL);
- if (!envp) {
- log_error ("No memory for client script environment.");
- return 0;
- }
- i = 0;
- /* Copy out the environment specified on the command line,
- if any. */
- for (sp = client_env; sp; sp = sp -> next) {
- envp [i++] = sp -> string;
- }
- /* Copy out the environment specified by dhclient. */
- if (client) {
- for (sp = client -> env; sp; sp = sp -> next) {
- envp [i++] = sp -> string;
- }
- } else {
- envp [i++] = reason;
- }
- /* Set $PATH. */
- envp [i++] = client_path;
- envp [i] = (char *)0;
-
- argv [0] = scriptName;
- argv [1] = (char *)0;
-
- pid = fork ();
- if (pid < 0) {
- log_error ("fork: %m");
- wstatus = 0;
- } else if (pid) {
- do {
- wpid = wait (&wstatus);
- } while (wpid != pid && wpid > 0);
- if (wpid < 0) {
- log_error ("wait: %m");
- wstatus = 0;
- }
- } else {
- /* We don't want to pass an open file descriptor for
- * dhclient.leases when executing dhclient-script.
- */
- if (leaseFile != NULL)
- fclose(leaseFile);
- execve (scriptName, argv, envp);
- log_error ("execve (%s, ...): %m", scriptName);
- exit (0);
- }
-
- if (client) {
- for (sp = client -> env; sp; sp = next) {
- next = sp -> next;
- dfree (sp, MDL);
- }
- client -> env = (struct string_list *)0;
- client -> envc = 0;
- }
- dfree (envp, MDL);
- gettimeofday(&cur_tv, NULL);
-
- if (!WIFEXITED(wstatus)) {
- int sigval = WTERMSIG(wstatus);
- log_error ("script_go script: %s was terminated by signal %d", scriptName, sigval);
- return (-sigval);
- }
-
- return (WEXITSTATUS(wstatus));
-}
-
-void client_envadd (struct client_state *client,
- const char *prefix, const char *name, const char *fmt, ...)
-{
- char spbuf [1024];
- char *s;
- unsigned len;
- struct string_list *val;
- va_list list;
-
- va_start (list, fmt);
- len = vsnprintf (spbuf, sizeof spbuf, fmt, list);
- va_end (list);
-
- val = dmalloc (strlen (prefix) + strlen (name) + 1 /* = */ +
- len + sizeof *val, MDL);
- if (!val) {
- log_error ("client_envadd: cannot allocate space for variable");
- return;
- }
-
- s = val -> string;
- strcpy (s, prefix);
- strcat (s, name);
- s += strlen (s);
- *s++ = '=';
- if (len >= sizeof spbuf) {
- va_start (list, fmt);
- vsnprintf (s, len + 1, fmt, list);
- va_end (list);
- } else {
- strcpy (s, spbuf);
- }
-
- val -> next = client -> env;
- client -> env = val;
- client -> envc++;
-}
-
-int dhcp_option_ev_name (buf, buflen, option)
- char *buf;
- size_t buflen;
- struct option *option;
-{
- int i, j;
- const char *s;
-
- j = 0;
- if (option -> universe != &dhcp_universe) {
- s = option -> universe -> name;
- i = 0;
- } else {
- s = option -> name;
- i = 1;
- }
-
- do {
- while (*s) {
- if (j + 1 == buflen)
- return 0;
- if (*s == '-')
- buf [j++] = '_';
- else
- buf [j++] = *s;
- ++s;
- }
- if (!i) {
- s = option -> name;
- if (j + 1 == buflen)
- return 0;
- buf [j++] = '_';
- }
- ++i;
- } while (i != 2);
-
- buf [j] = 0;
- return 1;
-}
-
-void finish (char ret)
-{
- if (no_daemon || dfd[0] == -1 || dfd[1] == -1)
- exit((int)ret);
- if (write(dfd[1], &ret, 1) != 1)
- log_fatal("write to parent: %m");
- (void) close(dfd[1]);
- dfd[0] = dfd[1] = -1;
- exit((int)ret);
-}
-
-void detach ()
-{
- char buf = 0;
-
- /* Don't become a daemon if the user requested otherwise. */
- if (no_daemon) {
- write_client_pid_file ();
- return;
- }
-
- /* Only do it once. */
- if (dfd[0] == -1 || dfd[1] == -1)
- return;
-
- /* Signal parent we started successfully. */
- if (write(dfd[1], &buf, 1) != 1)
- log_fatal("write to parent: %m");
- (void) close(dfd[1]);
- dfd[0] = dfd[1] = -1;
-
- /* Stop logging to stderr... */
- log_perror = 0;
-
- /* Become session leader and get pid... */
- (void) setsid ();
-
- /* Close standard I/O descriptors. */
- (void) close(0);
- (void) close(1);
- (void) close(2);
-
- /* Reopen them on /dev/null. */
- (void) open("/dev/null", O_RDWR);
- (void) open("/dev/null", O_RDWR);
- (void) open("/dev/null", O_RDWR);
-
- write_client_pid_file ();
-
- IGNORE_RET (chdir("/"));
-
-}
-
-void write_client_pid_file ()
-{
- FILE *pf;
- int pfdesc;
-
- /* nothing to do if the user doesn't want a pid file */
- if (no_pid_file == ISC_TRUE) {
- return;
- }
-
- pfdesc = open (path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY, 0644);
-
- if (pfdesc < 0) {
- log_error ("Can't create %s: %m", path_dhclient_pid);
- return;
- }
-
- pf = fdopen (pfdesc, "w");
- if (!pf) {
- close(pfdesc);
- log_error ("Can't fdopen %s: %m", path_dhclient_pid);
- } else {
- fprintf (pf, "%ld\n", (long)getpid ());
- fclose (pf);
- }
-}
-
-void client_location_changed ()
-{
- struct interface_info *ip;
- struct client_state *client;
-
- for (ip = interfaces; ip; ip = ip -> next) {
- for (client = ip -> client; client; client = client -> next) {
- switch (client -> state) {
- case S_SELECTING:
- cancel_timeout (send_discover, client);
- break;
-
- case S_BOUND:
- cancel_timeout (state_bound, client);
- break;
-
- case S_REBOOTING:
- case S_REQUESTING:
- case S_RENEWING:
- cancel_timeout (send_request, client);
- break;
-
- case S_INIT:
- case S_REBINDING:
- case S_STOPPED:
- case S_DECLINING:
- case S_V6ONLY:
- break;
- }
- client -> state = S_INIT;
- state_reboot (client);
- }
- }
-}
-
-void do_release(client)
- struct client_state *client;
-{
- struct data_string ds;
- struct option_cache *oc;
-
-#if defined(DHCPv6) && defined(DHCP4o6)
- if (dhcpv4_over_dhcpv6 && (dhcp4o6_state <= 0)) {
- if (dhcp4o6_state < 0)
- dhcp4o6_poll(NULL);
- client->pending = P_RELEASE;
- return;
- }
-#endif
-
- /* Pick a random xid. */
- client -> xid = random ();
-
- /* is there even a lease to release? */
- if (client -> active) {
- /* Make a DHCPRELEASE packet, and set appropriate per-interface
- flags. */
- make_release (client, client -> active);
-
- memset (&ds, 0, sizeof ds);
- oc = lookup_option (&dhcp_universe,
- client -> active -> options,
- DHO_DHCP_SERVER_IDENTIFIER);
- if (oc &&
- evaluate_option_cache (&ds, (struct packet *)0,
- (struct lease *)0, client,
- (struct option_state *)0,
- client -> active -> options,
- &global_scope, oc, MDL)) {
- if (ds.len > 3) {
- memcpy (client -> destination.iabuf,
- ds.data, 4);
- client -> destination.len = 4;
- } else
- client -> destination = iaddr_broadcast;
-
- data_string_forget (&ds, MDL);
- } else
- client -> destination = iaddr_broadcast;
- client -> first_sending = cur_time;
- client -> interval = client -> config -> initial_interval;
-
- /* Zap the medium list... */
- client -> medium = (struct string_list *)0;
-
- /* Send out the first and only DHCPRELEASE packet. */
- send_release (client);
-
- /* Do the client script RELEASE operation. */
- script_init (client,
- "RELEASE", (struct string_list *)0);
- if (client -> alias)
- script_write_params(client, "alias_",
- client -> alias);
- script_write_params(client, "old_", client -> active);
- script_write_requested(client);
- script_go(client);
- }
-
- /* Cancel any timeouts. */
- cancel_timeout (state_bound, client);
- cancel_timeout (send_discover, client);
- cancel_timeout (state_init, client);
- cancel_timeout (send_request, client);
- cancel_timeout (state_reboot, client);
- cancel_timeout (finish_v6only, client);
- client -> state = S_STOPPED;
-
-#if defined(DHCPv6) && defined(DHCP4o6)
- if (dhcpv4_over_dhcpv6)
- finish(0);
-#endif
-}
-
-int dhclient_interface_shutdown_hook (struct interface_info *interface)
-{
- do_release (interface -> client);
-
- return 1;
-}
-
-int dhclient_interface_discovery_hook (struct interface_info *tmp)
-{
- struct interface_info *last, *ip;
- /* See if we can find the client from dummy_interfaces */
- last = 0;
- for (ip = dummy_interfaces; ip; ip = ip -> next) {
- if (!strcmp (ip -> name, tmp -> name)) {
- /* Remove from dummy_interfaces */
- if (last) {
- ip = (struct interface_info *)0;
- interface_reference (&ip, last -> next, MDL);
- interface_dereference (&last -> next, MDL);
- if (ip -> next) {
- interface_reference (&last -> next,
- ip -> next, MDL);
- interface_dereference (&ip -> next,
- MDL);
- }
- } else {
- ip = (struct interface_info *)0;
- interface_reference (&ip,
- dummy_interfaces, MDL);
- interface_dereference (&dummy_interfaces, MDL);
- if (ip -> next) {
- interface_reference (&dummy_interfaces,
- ip -> next, MDL);
- interface_dereference (&ip -> next,
- MDL);
- }
- }
- /* Copy "client" to tmp */
- if (ip -> client) {
- tmp -> client = ip -> client;
- tmp -> client -> interface = tmp;
- }
- interface_dereference (&ip, MDL);
- break;
- }
- last = ip;
- }
- return 1;
-}
-
-isc_result_t dhclient_interface_startup_hook (struct interface_info *interface)
-{
- struct interface_info *ip;
- struct client_state *client;
-
- /* This code needs some rethinking. It doesn't test against
- a signal name, and it just kind of bulls into doing something
- that may or may not be appropriate. */
-
- if (interfaces) {
- interface_reference (&interface -> next, interfaces, MDL);
- interface_dereference (&interfaces, MDL);
- }
- interface_reference (&interfaces, interface, MDL);
-
- discover_interfaces (DISCOVER_UNCONFIGURED);
-
- for (ip = interfaces; ip; ip = ip -> next) {
- /* If interfaces were specified, don't configure
- interfaces that weren't specified! */
- if (ip -> flags & INTERFACE_RUNNING ||
- (ip -> flags & (INTERFACE_REQUESTED |
- INTERFACE_AUTOMATIC)) !=
- INTERFACE_REQUESTED)
- continue;
- script_init (ip -> client,
- "PREINIT", (struct string_list *)0);
- if (ip -> client -> alias)
- script_write_params(ip -> client, "alias_",
- ip -> client -> alias);
- script_go(ip -> client);
- }
-
- discover_interfaces (interfaces_requested != 0
- ? DISCOVER_REQUESTED
- : DISCOVER_RUNNING);
-
- for (ip = interfaces; ip; ip = ip -> next) {
- if (ip -> flags & INTERFACE_RUNNING)
- continue;
- ip -> flags |= INTERFACE_RUNNING;
- for (client = ip->client ; client ; client = client->next) {
- client->state = S_INIT;
- state_reboot(client);
- }
- }
- return ISC_R_SUCCESS;
-}
-
-/* The client should never receive a relay agent information option,
- so if it does, log it and discard it. */
-
-int parse_agent_information_option (packet, len, data)
- struct packet *packet;
- int len;
- u_int8_t *data;
-{
- return 1;
-}
-
-/* The client never sends relay agent information options. */
-
-unsigned cons_agent_information_options (cfg_options, outpacket,
- agentix, length)
- struct option_state *cfg_options;
- struct dhcp_packet *outpacket;
- unsigned agentix;
- unsigned length;
-{
- return length;
-}
-
-static void shutdown_exit (void *foo)
-{
- /* get rid of the pid if we can */
- if (no_pid_file == ISC_FALSE)
- (void) unlink(path_dhclient_pid);
- finish(0);
-}
-
-#if defined (NSUPDATE)
-/*
- * If the first 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"
- */
-
-/* The first and second stages are pretty similar so we combine them */
-void
-client_dns_remove_action(dhcp_ddns_cb_t *ddns_cb,
- isc_result_t eresult)
-{
-
- isc_result_t result;
-
- if ((eresult == ISC_R_SUCCESS) &&
- (ddns_cb->state == DDNS_STATE_REM_FW_YXDHCID)) {
- /* Do the second stage of the FWD removal */
- ddns_cb->state = DDNS_STATE_REM_FW_NXRR;
-
- result = ddns_modify_fwd(ddns_cb, MDL);
- if (result == ISC_R_SUCCESS) {
- return;
- }
- }
-
- /* If we are done or have an error clean up */
- dhclient_ddns_cb_free(ddns_cb, MDL);
- return;
-}
-
-void
-client_dns_remove(struct client_state *client,
- struct iaddr *addr)
-{
- dhcp_ddns_cb_t *ddns_cb;
- isc_result_t result;
-
- /* if we have an old ddns request for this client, cancel it */
- if (client->ddns_cb != NULL) {
- ddns_cancel(client->ddns_cb, MDL);
- client->ddns_cb = NULL;
- }
-
- ddns_cb = ddns_cb_alloc(MDL);
- if (ddns_cb != NULL) {
- ddns_cb->address = *addr;
- ddns_cb->timeout = 0;
-
- ddns_cb->state = DDNS_STATE_REM_FW_YXDHCID;
- ddns_cb->flags = DDNS_UPDATE_ADDR;
- ddns_cb->cur_func = client_dns_remove_action;
-
- result = client_dns_update(client, ddns_cb);
-
- if (result != ISC_R_TIMEDOUT) {
- dhclient_ddns_cb_free(ddns_cb, MDL);
- }
- }
-}
-#endif /* defined NSUPDATE */
-
-
-isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
- control_object_state_t newstate)
-{
- struct interface_info *ip;
- struct client_state *client;
- struct timeval tv;
-
- if (newstate == server_shutdown) {
- /* Re-entry */
- if (shutdown_signal == SIGUSR1)
- return ISC_R_SUCCESS;
- /* Log shutdown on signal. */
- if ((shutdown_signal == SIGINT) ||
- (shutdown_signal == SIGTERM)) {
- log_info("Received signal %d, initiating shutdown.",
- shutdown_signal);
- }
- /* Mark it was called. */
- shutdown_signal = SIGUSR1;
- }
-
- /* Do the right thing for each interface. */
- for (ip = interfaces; ip; ip = ip -> next) {
- for (client = ip -> client; client; client = client -> next) {
- switch (newstate) {
- case server_startup:
- return ISC_R_SUCCESS;
-
- case server_running:
- return ISC_R_SUCCESS;
-
- case server_shutdown:
- if (client -> active &&
- client -> active -> expiry > cur_time) {
-#if defined (NSUPDATE)
- if (client->config->do_forward_update) {
- client_dns_remove(client,
- &client->active->address);
- }
-#endif /* defined NSUPDATE */
-
- do_release (client);
- }
- break;
-
- case server_hibernate:
- state_stop (client);
- break;
-
- case server_awaken:
- state_reboot (client);
- break;
- }
- }
- }
-
- if (newstate == server_shutdown) {
- tv.tv_sec = cur_tv.tv_sec;
- tv.tv_usec = cur_tv.tv_usec + 1;
- add_timeout(&tv, shutdown_exit, 0, 0, 0);
- }
- return ISC_R_SUCCESS;
-}
-
-#if defined (NSUPDATE)
-/*
- * Called after a timeout if the DNS update failed on the previous try.
- * Starts the retry process. If the retry times out it will schedule
- * this routine to run again after a 10x wait.
- */
-void
-client_dns_update_timeout (void *cp)
-{
- dhcp_ddns_cb_t *ddns_cb = (dhcp_ddns_cb_t *)cp;
- struct client_state *client = (struct client_state *)ddns_cb->lease;
- isc_result_t status = ISC_R_FAILURE;
-
- if ((client != NULL) &&
- ((client->active != NULL) ||
- (client->active_lease != NULL)))
- status = client_dns_update(client, ddns_cb);
-
- /*
- * A status of timedout indicates that we started the update and
- * have released control of the control block. Any other status
- * indicates that we should clean up the control block. We either
- * got a success which indicates that we didn't really need to
- * send an update or some other error in which case we weren't able
- * to start the update process. In both cases we still own
- * the control block and should free it.
- */
- if (status != ISC_R_TIMEDOUT) {
- dhclient_ddns_cb_free(ddns_cb, MDL);
- }
-}
-
-/*
- * If the first query 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 the second 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"
- */
-
-/* The first and second stages are pretty similar so we combine them */
-void
-client_dns_update_action(dhcp_ddns_cb_t *ddns_cb,
- isc_result_t eresult)
-{
- isc_result_t result;
- struct timeval tv;
-
- switch(eresult) {
- case ISC_R_SUCCESS:
- default:
- /* Either we succeeded or broke in a bad way, clean up */
- break;
-
- case DNS_R_YXRRSET:
- /*
- * This is the only difference between the two stages,
- * check to see if it is the first stage, in which case
- * start the second stage
- */
- if (ddns_cb->state == DDNS_STATE_ADD_FW_NXDOMAIN) {
- ddns_cb->state = DDNS_STATE_ADD_FW_YXDHCID;
- ddns_cb->cur_func = client_dns_update_action;
-
- result = ddns_modify_fwd(ddns_cb, MDL);
- if (result == ISC_R_SUCCESS) {
- return;
- }
- }
- break;
-
- case ISC_R_TIMEDOUT:
- /*
- * We got a timeout response from the DNS module. Schedule
- * another attempt for later. We forget the name, dhcid and
- * zone so if it gets changed we will get the new information.
- */
- data_string_forget(&ddns_cb->fwd_name, MDL);
- data_string_forget(&ddns_cb->dhcid, MDL);
- if (ddns_cb->zone != NULL) {
- forget_zone((struct dns_zone **)&ddns_cb->zone);
- }
-
- /* Reset to doing the first stage */
- ddns_cb->state = DDNS_STATE_ADD_FW_NXDOMAIN;
- ddns_cb->cur_func = client_dns_update_action;
-
- /* and update our timer */
- if (ddns_cb->timeout < 3600)
- ddns_cb->timeout *= 10;
- tv.tv_sec = cur_tv.tv_sec + ddns_cb->timeout;
- tv.tv_usec = cur_tv.tv_usec;
- add_timeout(&tv, client_dns_update_timeout,
- ddns_cb, NULL, NULL);
- return;
- }
-
- dhclient_ddns_cb_free(ddns_cb, MDL);
- return;
-}
-
-/* See if we should do a DNS update, and if so, do it. */
-
-isc_result_t
-client_dns_update(struct client_state *client, dhcp_ddns_cb_t *ddns_cb)
-{
- struct data_string client_identifier;
- struct option_cache *oc;
- int ignorep;
- int result;
- int ddns_v4_type;
- isc_result_t rcode;
-
- /* If we didn't send an FQDN option, we certainly aren't going to
- be doing an update. */
- if (!client -> sent_options)
- return ISC_R_SUCCESS;
-
- /* If we don't have a lease, we can't do an update. */
- if ((client->active == NULL) && (client->active_lease == NULL))
- return ISC_R_SUCCESS;
-
- /* If we set the no client update flag, don't do the update. */
- if ((oc = lookup_option (&fqdn_universe, client -> sent_options,
- FQDN_NO_CLIENT_UPDATE)) &&
- evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
- (struct lease *)0, client,
- client -> sent_options,
- (struct option_state *)0,
- &global_scope, oc, MDL))
- return ISC_R_SUCCESS;
-
- /* If we set the "server, please update" flag, or didn't set it
- to false, don't do the update. */
- if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
- FQDN_SERVER_UPDATE)) ||
- evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
- (struct lease *)0, client,
- client -> sent_options,
- (struct option_state *)0,
- &global_scope, oc, MDL))
- return ISC_R_SUCCESS;
-
- /* If no FQDN option was supplied, don't do the update. */
- if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
- FQDN_FQDN)) ||
- !evaluate_option_cache (&ddns_cb->fwd_name, (struct packet *)0,
- (struct lease *)0, client,
- client -> sent_options,
- (struct option_state *)0,
- &global_scope, oc, MDL))
- return ISC_R_SUCCESS;
-
- /*
- * Construct the DHCID value for use in the DDNS update process
- * We have the newer standard version and the older interim version
- * chosen by the '-I' option. The interim version is left as is
- * for backwards compatibility. The standard version is based on
- * RFC 4701 section 3.3
- */
-
- result = 0;
- POST(result);
- memset(&client_identifier, 0, sizeof(client_identifier));
-
- if (std_dhcid == 1) {
- /* standard style */
- ddns_cb->dhcid_class = dns_rdatatype_dhcid;
- ddns_v4_type = 1;
- } else {
- /* interim style */
- ddns_cb->dhcid_class = dns_rdatatype_txt;
- /* for backwards compatibility */
- ddns_v4_type = DHO_DHCP_CLIENT_IDENTIFIER;
- }
- if (client->active_lease != NULL) {
- /* V6 request, get the client identifier, then
- * construct the dhcid for either standard
- * or interim */
- if (((oc = lookup_option(&dhcpv6_universe,
- client->sent_options,
- D6O_CLIENTID)) != NULL) &&
- evaluate_option_cache(&client_identifier, NULL,
- NULL, client,
- client->sent_options, NULL,
- &global_scope, oc, MDL)) {
- result = get_dhcid(ddns_cb, 2,
- client_identifier.data,
- client_identifier.len);
- data_string_forget(&client_identifier, MDL);
- } else
- log_fatal("Impossible condition at %s:%d.", MDL);
- } else {
- /*
- * V4 request, use the client id if there is one or the
- * mac address if there isn't. If we have a client id
- * we check to see if it is an embedded DUID.
- */
- if (((oc = lookup_option(&dhcp_universe,
- client->sent_options,
- DHO_DHCP_CLIENT_IDENTIFIER)) != NULL) &&
- evaluate_option_cache(&client_identifier, NULL,
- NULL, client,
- client->sent_options, NULL,
- &global_scope, oc, MDL)) {
- if ((std_dhcid == 1) && (duid_v4 == 1) &&
- (client_identifier.data[0] == 255)) {
- /*
- * This appears to be an embedded DUID,
- * extract it and treat it as such
- */
- if (client_identifier.len <= 5)
- log_fatal("Impossible condition at %s:%d.",
- MDL);
- result = get_dhcid(ddns_cb, 2,
- client_identifier.data + 5,
- client_identifier.len - 5);
- } else {
- result = get_dhcid(ddns_cb, ddns_v4_type,
- client_identifier.data,
- client_identifier.len);
- }
- data_string_forget(&client_identifier, MDL);
- } else
- result = get_dhcid(ddns_cb, 0,
- client->interface->hw_address.hbuf,
- client->interface->hw_address.hlen);
- }
-
- if (!result) {
- return ISC_R_SUCCESS;
- }
-
- /*
- * Perform updates.
- */
- if (ddns_cb->fwd_name.len && ddns_cb->dhcid.len) {
- rcode = ddns_modify_fwd(ddns_cb, MDL);
- } else
- rcode = ISC_R_FAILURE;
-
- /*
- * A success from the modify routine means we are performing
- * async processing, for which we use the timedout error message.
- */
- if (rcode == ISC_R_SUCCESS) {
- rcode = ISC_R_TIMEDOUT;
- }
-
- return rcode;
-}
-
-
-/*
- * Schedule the first update. They will continue to retry occasionally
- * until they no longer time out (or fail).
- */
-void
-dhclient_schedule_updates(struct client_state *client,
- struct iaddr *addr,
- int offset)
-{
- dhcp_ddns_cb_t *ddns_cb;
- struct timeval tv;
-
- if (!client->config->do_forward_update)
- return;
-
- /* cancel any outstanding ddns requests */
- if (client->ddns_cb != NULL) {
- ddns_cancel(client->ddns_cb, MDL);
- client->ddns_cb = NULL;
- }
-
- ddns_cb = ddns_cb_alloc(MDL);
-
- if (ddns_cb != NULL) {
- ddns_cb->lease = (void *)client;
- ddns_cb->address = *addr;
- ddns_cb->timeout = 1;
-
- /*
- * XXX: DNS TTL is a problem we need to solve properly.
- * Until that time, 300 is a placeholder default for
- * something that is less insane than a value scaled
- * by lease timeout.
- */
- ddns_cb->ttl = 300;
-
- ddns_cb->state = DDNS_STATE_ADD_FW_NXDOMAIN;
- ddns_cb->cur_func = client_dns_update_action;
- ddns_cb->flags = DDNS_UPDATE_ADDR | DDNS_INCLUDE_RRSET;
-
- client->ddns_cb = ddns_cb;
- tv.tv_sec = cur_tv.tv_sec + offset;
- tv.tv_usec = cur_tv.tv_usec;
- add_timeout(&tv, client_dns_update_timeout,
- ddns_cb, NULL, NULL);
- } else {
- log_error("Unable to allocate dns update state for %s",
- piaddr(*addr));
- }
-}
-#endif /* defined NSUPDATE */
-
-void
-dhcpv4_client_assignments(void)
-{
- struct servent *ent;
-
- if (path_dhclient_pid == NULL)
- path_dhclient_pid = _PATH_DHCLIENT_PID;
- if (path_dhclient_db == NULL)
- path_dhclient_db = _PATH_DHCLIENT_DB;
-
- /* Default to the DHCP/BOOTP port. */
- if (!local_port) {
- /* If we're faking a relay agent, and we're not using loopback,
- use the server port, not the client port. */
- if (mockup_relay && giaddr.s_addr != htonl(INADDR_LOOPBACK)) {
- local_port = htons(67);
- } else {
- ent = getservbyname("dhcpc", "udp");
- if (ent == NULL)
- ent = getservbyname("bootpc", "udp");
- if (ent == NULL)
- local_port = htons(68);
- else
- local_port = ent->s_port;
-#ifndef __CYGWIN32__
- endservent ();
-#endif
- }
- }
-
- /* If we're faking a relay agent, and we're not using loopback,
- we're using the server port, not the client port. */
- if (mockup_relay && giaddr.s_addr != htonl(INADDR_LOOPBACK)) {
- remote_port = local_port;
- } else
- remote_port = htons(ntohs(local_port) - 1); /* XXX */
-}
-
-/*
- * The following routines are used to check that certain
- * strings are reasonable before we pass them to the scripts.
- * This avoids some problems with scripts treating the strings
- * as commands - see ticket 23722
- * The domain checking code should be done as part of assembling
- * the string but we are doing it here for now due to time
- * constraints.
- */
-
-static int check_domain_name(const char *ptr, size_t len, int dots)
-{
- const char *p;
-
- /* not empty or complete length not over 255 characters */
- if ((len == 0) || (len > 256))
- return(-1);
-
- /* consists of [[:alnum:]-]+ labels separated by [.] */
- /* a [_] is against RFC but seems to be "widely used"... */
- for (p=ptr; (*p != 0) && (len-- > 0); p++) {
- if ((*p == '-') || (*p == '_')) {
- /* not allowed at begin or end of a label */
- if (((p - ptr) == 0) || (len == 0) || (p[1] == '.'))
- return(-1);
- } else if (*p == '.') {
- /* each label has to be 1-63 characters;
- we allow [.] at the end ('foo.bar.') */
- size_t d = p - ptr;
- if ((d <= 0) || (d >= 64))
- return(-1);
- ptr = p + 1; /* jump to the next label */
- if ((dots > 0) && (len > 0))
- dots--;
- } else if (isalnum((unsigned char)*p) == 0) {
- /* also numbers at the begin are fine */
- return(-1);
- }
- }
- return(dots ? -1 : 0);
-}
-
-static int check_domain_name_list(const char *ptr, size_t len, int dots)
-{
- const char *p;
- int ret = -1; /* at least one needed */
-
- if ((ptr == NULL) || (len == 0))
- return(-1);
-
- for (p=ptr; (*p != 0) && (len > 0); p++, len--) {
- if (*p != ' ')
- continue;
- if (p > ptr) {
- if (check_domain_name(ptr, p - ptr, dots) != 0)
- return(-1);
- ret = 0;
- }
- ptr = p + 1;
- }
- if (p > ptr)
- return(check_domain_name(ptr, p - ptr, dots));
- else
- return(ret);
-}
-
-static int check_option_values(struct universe *universe,
- unsigned int opt,
- const char *ptr,
- size_t len)
-{
- if (ptr == NULL)
- return(-1);
-
- /* just reject options we want to protect, will be escaped anyway */
- if ((universe == NULL) || (universe == &dhcp_universe)) {
- switch(opt) {
- case DHO_DOMAIN_NAME:
-#ifdef ACCEPT_LIST_IN_DOMAIN_NAME
- return check_domain_name_list(ptr, len, 0);
-#else
- return check_domain_name(ptr, len, 0);
-#endif
- case DHO_HOST_NAME:
- case DHO_NIS_DOMAIN:
- case DHO_NETBIOS_SCOPE:
- return check_domain_name(ptr, len, 0);
- break;
- case DHO_DOMAIN_SEARCH:
- return check_domain_name_list(ptr, len, 0);
- break;
- case DHO_ROOT_PATH:
- if (len == 0)
- return(-1);
- for (; (*ptr != 0) && (len-- > 0); ptr++) {
- if(!(isalnum((unsigned char)*ptr) ||
- *ptr == '#' || *ptr == '%' ||
- *ptr == '+' || *ptr == '-' ||
- *ptr == '_' || *ptr == ':' ||
- *ptr == '.' || *ptr == ',' ||
- *ptr == '@' || *ptr == '~' ||
- *ptr == '\\' || *ptr == '/' ||
- *ptr == '[' || *ptr == ']' ||
- *ptr == '=' || *ptr == ' '))
- return(-1);
- }
- return(0);
- break;
- }
- }
-
-#ifdef DHCPv6
- if (universe == &dhcpv6_universe) {
- switch(opt) {
- case D6O_SIP_SERVERS_DNS:
- case D6O_DOMAIN_SEARCH:
- case D6O_NIS_DOMAIN_NAME:
- case D6O_NISP_DOMAIN_NAME:
- return check_domain_name_list(ptr, len, 0);
- break;
- }
- }
-#endif
-
- return(0);
-}
-
-static void
-add_reject(struct packet *packet) {
- struct iaddrmatchlist *list;
-
- list = dmalloc(sizeof(struct iaddrmatchlist), MDL);
- if (!list)
- log_fatal ("no memory for reject list!");
-
- /*
- * client_addr is misleading - it is set to source address in common
- * code.
- */
- list->match.addr = packet->client_addr;
- /* Set mask to indicate host address. */
- list->match.mask.len = list->match.addr.len;
- memset(list->match.mask.iabuf, 0xff, sizeof(list->match.mask.iabuf));
-
- /* Append to reject list for the source interface. */
- list->next = packet->interface->client->config->reject_list;
- packet->interface->client->config->reject_list = list;
-
- /*
- * We should inform user that we won't be accepting this server
- * anymore.
- */
- log_info("Server added to list of rejected servers.");
-}
-
-#if defined(NSUPDATE)
-/* Wrapper function around common ddns_cb_free function that ensures
- * we set the client_state pointer to the control block to NULL. */
-static void
-dhclient_ddns_cb_free(dhcp_ddns_cb_t *ddns_cb, char* file, int line) {
- if (ddns_cb) {
- struct client_state *client = (struct client_state *)ddns_cb->lease;
- if (client != NULL) {
- client->ddns_cb = NULL;
- }
-
- ddns_cb_free(ddns_cb, file, line);
- }
-}
-#endif /* defined NSUPDATE */
-
-#if defined(DHCPv6) && defined(DHCP4o6)
-/*
- * \brief Omapi I/O handler
- *
- * The inter-process communication receive handler.
- *
- * On the DHCPv6 side, the message is either a POLL (which is answered
- * by a START or a STOP) or a DHCPv4-QUERY (which is forwarded to
- * DHCPv4 over DHCPv6 servers by forw_dhcpv4_query()).
- *
- * On the DHCPv4 side, the message is either a START, a STOP
- * (both for the DHCP4 over DHCPv6 state machine) or a DHCPv4-RESPONSE
- * (which is processed by recv_dhcpv4_response()).
- *
- * \param h the OMAPI object
- * \return a result for I/O success or error (used by the I/O subsystem)
- */
-isc_result_t dhcpv4o6_handler(omapi_object_t *h) {
- char buf[65536];
- char start_msg[5] = { 'S', 'T', 'A', 'R', 'T' };
- char stop_msg[4] = { 'S', 'T', 'O', 'P' };
- char poll_msg[4] = { 'P', 'O', 'L', 'L' };
- struct data_string raw;
- int cc;
-
- if (h->type != dhcp4o6_type)
- return DHCP_R_INVALIDARG;
-
- cc = recv(dhcp4o6_fd, buf, sizeof(buf), 0);
- if (cc <= 0)
- return ISC_R_UNEXPECTED;
-
- if (local_family == AF_INET6) {
- if ((cc == 4) &&
- (memcmp(buf, poll_msg, sizeof(poll_msg)) == 0)) {
- log_info("RCV: POLL");
- if (dhcp4o6_state < 0)
- cc = send(dhcp4o6_fd, stop_msg,
- sizeof(stop_msg), 0);
- else
- cc = send(dhcp4o6_fd, start_msg,
- sizeof(start_msg), 0);
- if (cc < 0) {
- log_error("dhcpv4o6_handler: send(): %m");
- return ISC_R_IOERROR;
- }
- } else {
- if (cc < DHCP_FIXED_NON_UDP + 8)
- return ISC_R_UNEXPECTED;
- memset(&raw, 0, sizeof(raw));
- if (!buffer_allocate(&raw.buffer, cc, MDL)) {
- log_error("dhcpv4o6_handler: "
- "no memory buffer.");
- return ISC_R_NOMEMORY;
- }
- raw.data = raw.buffer->data;
- raw.len = cc;
- memcpy(raw.buffer->data, buf, cc);
-
- forw_dhcpv4_query(&raw);
-
- data_string_forget(&raw, MDL);
- }
- } else {
- if ((cc == 4) &&
- (memcmp(buf, stop_msg, sizeof(stop_msg)) == 0)) {
- log_info("RCV: STOP");
- if (dhcp4o6_state > 0) {
- dhcp4o6_state = 0;
- dhcp4o6_poll(NULL);
- }
- } else if ((cc == 5) &&
- (memcmp(buf, start_msg, sizeof(start_msg)) == 0)) {
- log_info("RCV: START");
- if (dhcp4o6_state == 0)
- cancel_timeout(dhcp4o6_poll, NULL);
- dhcp4o6_state = 1;
- dhcp4o6_resume();
- } else {
- if (cc < DHCP_FIXED_NON_UDP + 16)
- return ISC_R_UNEXPECTED;
- memset(&raw, 0, sizeof(raw));
- if (!buffer_allocate(&raw.buffer, cc, MDL)) {
- log_error("dhcpv4o6_handler: "
- "no memory buffer.");
- return ISC_R_NOMEMORY;
- }
- raw.data = raw.buffer->data;
- raw.len = cc;
- memcpy(raw.buffer->data, buf, cc);
-
- recv_dhcpv4_response(&raw);
-
- data_string_forget(&raw, MDL);
- }
- }
-
- return ISC_R_SUCCESS;
-}
-
-/*
- * \brief Poll the DHCPv6 client
- * (DHCPv4 client function)
- *
- * A POLL message is sent to the DHCPv6 client periodically to check
- * if the DHCPv6 is ready (i.e., has a valid DHCPv4-over-DHCPv6 server
- * address option).
- */
-static void dhcp4o6_poll(void *dummy) {
- char msg[4] = { 'P', 'O', 'L', 'L' };
- struct timeval tv;
- int cc;
-
- IGNORE_UNUSED(dummy);
-
- if (dhcp4o6_state < 0)
- dhcp4o6_state = 0;
-
- log_info("POLL");
-
- cc = send(dhcp4o6_fd, msg, sizeof(msg), 0);
- if (cc < 0)
- log_error("dhcp4o6_poll: send(): %m");
-
- tv.tv_sec = cur_time + 60;
- tv.tv_usec = random() % 1000000;
-
- add_timeout(&tv, dhcp4o6_poll, NULL, 0, 0);
-}
-
-/*
- * \brief Resume pending operations
- * (DHCPv4 client function)
- *
- * A START message was received from the DHCPv6 client so pending
- * operations (RELEASE or REBOOT) must be resumed.
- */
-static void dhcp4o6_resume() {
- struct interface_info *ip;
- struct client_state *client;
-
- for (ip = interfaces; ip != NULL; ip = ip->next) {
- for (client = ip->client; client != NULL;
- client = client->next) {
- if (client->pending == P_RELEASE)
- do_release(client);
- else if (client->pending == P_REBOOT)
- state_reboot(client);
- }
- }
-}
-
-/*
- * \brief Send a START to the DHCPv4 client
- * (DHCPv6 client function)
- *
- * First check if there is a valid DHCPv4-over-DHCPv6 server address option,
- * and when found go UP and on a transition from another state send
- * a START message to the DHCPv4 client.
- */
-void dhcp4o6_start() {
- struct interface_info *ip;
- struct client_state *client;
- struct dhc6_lease *lease;
- struct option_cache *oc;
- struct data_string addrs;
- char msg[5] = { 'S', 'T', 'A', 'R', 'T' };
- int cc;
-
- memset(&addrs, 0, sizeof(addrs));
- for (ip = interfaces; ip != NULL; ip = ip->next) {
- for (client = ip->client; client != NULL;
- client = client->next) {
- if ((client->state != S_BOUND) &&
- (client->state != S_RENEWING) &&
- (client->state != S_REBINDING))
- continue;
- lease = client->active_lease;
- if ((lease == NULL) || lease->released)
- continue;
- oc = lookup_option(&dhcpv6_universe,
- lease->options,
- D6O_DHCP4_O_DHCP6_SERVER);
- if ((oc == NULL) ||
- !evaluate_option_cache(&addrs, NULL, NULL, NULL,
- lease->options, NULL,
- &global_scope, oc, MDL))
- continue;
- if ((addrs.len % 16) != 0) {
- data_string_forget(&addrs, MDL);
- continue;
- }
- data_string_forget(&addrs, MDL);
- goto found;
- }
- }
- log_info("dhcp4o6_start: failed");
- dhcp4o6_stop();
- return;
-
-found:
- if (dhcp4o6_state == 1)
- return;
- log_info("dhcp4o6_start: go to UP");
- dhcp4o6_state = 1;
-
- cc = send(dhcp4o6_fd, msg, sizeof(msg), 0);
- if (cc < 0)
- log_info("dhcp4o6_start: send(): %m");
-}
-
-/*
- * Send a STOP to the DHCPv4 client
- * (DHCPv6 client function)
- *
- * Go DOWN and on a transition from another state send a STOP message
- * to the DHCPv4 client.
- */
-static void dhcp4o6_stop() {
- char msg[4] = { 'S', 'T', 'O', 'P' };
- int cc;
-
- if (dhcp4o6_state == -1)
- return;
-
- log_info("dhcp4o6_stop: go to DOWN");
- dhcp4o6_state = -1;
-
- cc = send(dhcp4o6_fd, msg, sizeof(msg), 0);
- if (cc < 0)
- log_error("dhcp4o6_stop: send(): %m");
-}
-#endif /* DHCPv6 && DHCP4o6 */
diff --git a/client/dhclient.conf.5 b/client/dhclient.conf.5
deleted file mode 100644
index dbe6f7e8..00000000
--- a/client/dhclient.conf.5
+++ /dev/null
@@ -1,786 +0,0 @@
-.\" $Id: dhclient.conf.5,v 1.34 2012/01/24 22:23:39 sar Exp $
-.\"
-.\" Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
-.\" Copyright (c) 1996-2003 by Internet Software Consortium
-.\"
-.\" This Source Code Form is subject to the terms of the Mozilla Public
-.\" License, v. 2.0. If a copy of the MPL was not distributed with this
-.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
-.\"
-.\" 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.
-.\" PO Box 360
-.\" Newmarket, NH 03857 USA
-.\" <info@isc.org>
-.\" https://www.isc.org/
-.\"
-.\" Support and other services are available for ISC products - see
-.\" https://www.isc.org for more information or to learn more about ISC.
-.\"
-.TH dhclient.conf 5
-.SH NAME
-dhclient.conf - DHCP client configuration file
-.SH DESCRIPTION
-The dhclient.conf file contains configuration information for
-.IR dhclient,
-the Internet Systems Consortium DHCP Client.
-.PP
-The dhclient.conf file is a free-form ASCII text file. It is parsed by
-the recursive-descent parser built into dhclient. The file may contain
-extra tabs and newlines for formatting purposes. Keywords in the file
-are case-insensitive. Comments may be placed anywhere within the
-file (except within quotes). Comments begin with the # character and
-end at the end of the line.
-.PP
-The dhclient.conf file can be used to configure the behaviour of the
-client in a wide variety of ways: protocol timing, information
-requested from the server, information required of the server,
-defaults to use if the server does not provide certain information,
-values with which to override information provided by the server, or
-values to prepend or append to information provided by the server.
-The configuration file can also be preinitialized with addresses to
-use on networks that don't have DHCP servers.
-.SH PROTOCOL TIMING
-The timing behaviour of the client need not be configured by the user.
-If no timing configuration is provided by the user, a fairly
-reasonable timing behaviour will be used by default - one which
-results in fairly timely updates without placing an inordinate load on
-the server.
-.PP
-If required the following statements can be used to adjust the timing
-behaviour of the DHCPv4 client. The DHCPv6 protocol provides values
-to use and they are not currently configurable.
-.PP
-.I The
-.B timeout
-.I statement
-.PP
- \fBtimeout \fItime\fR\fB;\fR
-.PP
-The
-.I timeout
-statement determines the amount of time that must pass between the
-time that the client begins to try to determine its address and the
-time that it decides that it's not going to be able to contact a
-server. By default, this timeout is sixty seconds. After the
-timeout has passed, if there are any static leases defined in the
-configuration file, or any leases remaining in the lease database that
-have not yet expired, the client will loop through these leases
-attempting to validate them, and if it finds one that appears to be
-valid, it will use that lease's address. If there are no valid
-static leases or unexpired leases in the lease database, the client
-will restart the protocol after the defined retry interval.
-.PP
-.I The
-.B retry
-.I statement
-.PP
- \fBretry \fItime\fR\fB;\fR
-.PP
-The
-.I retry
-statement determines the time that must pass after the client has
-determined that there is no DHCP server present before it tries again
-to contact a DHCP server. By default, this is five minutes.
-.PP
-.I The
-.B select-timeout
-.I statement
-.PP
- \fBselect-timeout \fItime\fR\fB;\fR
-.PP
-It is possible (some might say desirable) for there to be more than
-one DHCP server serving any given network. In this case, it is
-possible that a client may be sent more than one offer in response to
-its initial lease discovery message. It may be that one of these
-offers is preferable to the other (e.g., one offer may have the
-address the client previously used, and the other may not).
-.PP
-The
-.I select-timeout
-is the time after the client sends its first lease discovery request
-at which it stops waiting for offers from servers, assuming that it
-has received at least one such offer. If no offers have been
-received by the time the
-.I select-timeout
-has expired, the client will accept the first offer that arrives.
-.PP
-By default, the select-timeout is zero seconds - that is, the client
-will take the first offer it sees.
-.PP
-.I The
-.B reboot
-.I statement
-.PP
- \fBreboot \fItime\fR\fB;\fR
-.PP
-When the client is restarted, it first tries to reacquire the last
-address it had. This is called the INIT-REBOOT state. If it is
-still attached to the same network it was attached to when it last
-ran, this is the quickest way to get started. The
-.I reboot
-statement sets the time that must elapse after the client first tries
-to reacquire its old address before it gives up and tries to discover
-a new address. By default, the reboot timeout is ten seconds.
-.PP
-.I The
-.B backoff-cutoff
-.I statement
-.PP
- \fBbackoff-cutoff \fItime\fR\fB;\fR
-.PP
-The client uses an exponential backoff algorithm with some randomness,
-so that if many clients try to configure themselves at the same time,
-they will not make their requests in lockstep. The
-.I backoff-cutoff
-statement determines the maximum amount of time that the client is
-allowed to back off, the actual value will be evaluated randomly between
-1/2 to 1 1/2 times the \fItime\fR specified. It defaults to fifteen
-seconds.
-.PP
-.I The
-.B initial-interval
-.I statement
-.PP
- \fBinitial-interval \fItime\fR\fB;\fR
-.PP
-The
-.I initial-interval
-statement sets the amount of time between the first attempt to reach a
-server and the second attempt to reach a server. Each time a message
-is sent, the interval between messages is incremented by twice the
-current interval multiplied by a random number between zero and one.
-If it is greater than the backoff-cutoff amount, it is set to that
-amount. It defaults to ten seconds.
-.PP
-.I The initial-delay
-.I statement
-.PP
- \fBinitial-delay \fItime\fR\fB;\fR
-.PP
-.I initial-delay
-parameter sets the maximum time client can wait after start before
-commencing first transmission.
-According to RFC2131 Section 4.4.1, client should wait a random time between
-startup and the actual first transmission. Previous versions of ISC DHCP
-client used to wait random time up to 5 seconds, but that was unwanted
-due to impact on startup time. As such, new versions have the default
-initial delay set to 0. To restore old behavior, please set initial-delay
-to 5.
-.SH DHCPv6 LEASE SELECTION
-In the DHCPv6 protocol the client will wait a small amount of time to
-allow ADVERTISE messages from multiple servers to arrive. It will then
-need to choose from all of the messages that may have arrived before
-proceeding to making a request of the selected server.
-
-The first selection criteria is the set of options and addresses
-in the message. Messages that don't include an option specified
-as required will be given a score of 0 and not used. If the
-\fI-R\fR option is given on the command line then messages that
-don't include the correct number of bindings (IA-NA, IA-TA or
-IA-PD) will be discarded.
-
-The next criteria is the preference value from the message. With
-the highest preference value being used even if leases with better
-addresses or options are available.
-
-Finally the lease is scored and the lease with the highest score
-is selected. A lease's score is based on the number of bindings,
-number of addresses and number of options it contains:
-.nf
- bindings * X + addresses * Y + options
-.fi
-By default X = 10000 and Y = 100, this will cause the client to
-select a lease with more bindings over a lease with less bindings
-but more addresses. The weightings were changed as part of
-implementing RFC 7550. Previously they were X = 50 and Y = 100
-meaning more addresses were preferred over more bindings. If
-you wish to continue using the old style you may do so by editing
-the file includes/site.h and uncommenting the define for
-USE_ORIGINAL_CLIENT_LEASE_WEIGHTS.
-.SH LEASE REQUIREMENTS AND REQUESTS
-The DHCP protocol allows the client to request that the server send it
-specific information, and not send it other information that it is not
-prepared to accept. The protocol also allows the client to reject
-offers from servers if they don't contain information the client
-needs, or if the information provided is not satisfactory.
-.PP
-There is a variety of data contained in offers that DHCP servers send
-to DHCP clients. The data that can be specifically requested is what
-are called \fIDHCP Options\fR. DHCP Options are defined in
- \fBdhcp-options(5)\fR.
-.PP
-.I The
-.B request
-.I statement
-.PP
- \fB[ also ] request [ [ \fIoption-space\fR . ] \fIoption\fR ] [\fB,\fI ... ]\fB;\fR
-.PP
-The request statement causes the client to request that any server
-responding to the client send the client its values for the specified
-options. Only the option names should be specified in the request
-statement - not option parameters. By default, the DHCPv4 client
-requests the subnet-mask, broadcast-address, time-offset, routers,
-domain-name, domain-name-servers and host-name options while the DHCPv6
-client requests the dhcp6 name-servers and domain-search options. Note
-that if you enter a \'request\' statement, you over-ride these defaults
-and these options will not be requested.
-.PP
-In some cases, it may be desirable to send no parameter request list
-at all. To do this, simply write the request statement but specify
-no parameters:
-.PP
-.nf
- request;
-.fi
-.PP
-In most cases, it is desirable to simply add one option to the request
-list which is of interest to the client in question. In this case, it
-is best to \'also request\' the additional options:
-.PP
-.nf
- also request domain-search, dhcp6.sip-servers-addresses;
-.fi
-.PP
-.I The
-.B require
-.I statement
-.PP
- \fB[ also ] require [ [ \fIoption-space\fR . ] \fIoption\fR ] [\fB,\fI ... ]\fB;\fR
-.PP
-The require statement lists options that must be sent in order for an
-offer to be accepted. Offers that do not contain all the listed
-options will be ignored. There is no default require list.
-.PP
-.nf
- require name-servers;
-
- interface eth0 {
- also require domain-search;
- }
-.fi
-.PP
-.I The
-.B send
-.I statement
-.PP
- \fBsend [ \fIoption declaration\fR ] \fB;\fR
-.PP
-The send statement causes the client to send the specified option to
-the server with the specified value. This is a full option
-declaration as described in \fBdhcp-options(5)\fR. Options that are
-always sent in the DHCP protocol should not be specified here, except
-that the client can specify a requested \fBdhcp-lease-time\fR option other
-than the default requested lease time, which is two hours. The other
-obvious use for this statement is to send information to the server
-that will allow it to differentiate between this client and other
-clients or kinds of clients.
-.SH DYNAMIC DNS
-The client now has some very limited support for doing DNS updates
-when a lease is acquired. This is prototypical, and probably doesn't
-do what you want. It also only works if you happen to have control
-over your DNS server, which isn't very likely.
-.PP
-Note that everything in this section is true whether you are using DHCPv4
-or DHCPv6. The exact same syntax is used for both.
-.PP
-To make it work, you have to declare a key and zone as in the DHCP
-server (see \fBdhcpd.conf\fR(5) for details). You also need to
-configure the \fIfqdn\fR option on the client, as follows:
-.PP
-.nf
- send fqdn.fqdn "grosse.example.com.";
- send fqdn.encoded on;
- send fqdn.server-update off;
- also request fqdn, dhcp6.fqdn;
-.fi
-.PP
-The \fIfqdn.fqdn\fR option \fBMUST\fR be a fully-qualified domain
-name. You \fBMUST\fR define a zone statement for the zone to be
-updated. The \fIfqdn.encoded\fR option may need to be set to
-\fIon\fR or \fIoff\fR, depending on the DHCP server you are using.
-.PP
-.I The
-.B do-forward-updates
-.I statement
-.PP
- \fBdo-forward-updates [ \fIflag\fR ] \fB;\fR
-.PP
-If you want to do DNS updates in the DHCP client
-script (see \fBdhclient-script(8)\fR) rather than having the
-DHCP client do the update directly (for example, if you want to
-use SIG(0) authentication, which is not supported directly by the
-DHCP client, you can instruct the client not to do the update using
-the \fBdo-forward-updates\fR statement. \fIFlag\fR should be \fBtrue\fR
-if you want the DHCP client to do the update, and \fBfalse\fR if
-you don't want the DHCP client to do the update. By default, the DHCP
-client will do the DNS update.
-.SH OPTION MODIFIERS
-In some cases, a client may receive option data from the server which
-is not really appropriate for that client, or may not receive
-information that it needs, and for which a useful default value
-exists. It may also receive information which is useful, but which
-needs to be supplemented with local information. To handle these
-needs, several option modifiers are available.
-.PP
-.I The
-.B default
-.I statement
-.PP
- \fBdefault [ \fIoption declaration\fR ] \fB;\fR
-.PP
-If for some option the client should use the value supplied by
-the server, but needs to use some default value if no value was supplied
-by the server, these values can be defined in the
-.B default
-statement.
-.PP
-.I The
-.B supersede
-.I statement
-.PP
- \fBsupersede [ \fIoption declaration\fR ] \fB;\fR
-.PP
-If for some option the client should always use a locally-configured
-value or values rather than whatever is supplied by the server, these
-values can be defined in the
-.B supersede
-statement.
-.PP
-.I The
-.B prepend
-.I statement
-.PP
- \fBprepend [ \fIoption declaration\fR ] \fB;\fR
-.PP
-If for some set of options the client should use a value you
-supply, and then use the values supplied by
-the server, if any, these values can be defined in the
-.B prepend
-statement. The
-.B prepend
-statement can only be used for options which
-allow more than one value to be given. This restriction is not
-enforced - if you ignore it, the behaviour will be unpredictable.
-.PP
-.I The
-.B append
-.I statement
-.PP
- \fBappend [ \fIoption declaration\fR ] \fB;\fR
-.PP
-If for some set of options the client should first use the values
-supplied by the server, if any, and then use values you supply, these
-values can be defined in the
-.B append
-statement. The
-.B append
-statement can only be used for options which
-allow more than one value to be given. This restriction is not
-enforced - if you ignore it, the behaviour will be unpredictable.
-.SH LEASE DECLARATIONS
-.PP
-.I The
-.B lease
-.I declaration
-.PP
- \fBlease {\fR \fIlease-declaration\fR [ ... \fIlease-declaration ] \fB}\fR
-.PP
-The DHCP client may decide after some period of time (see \fBPROTOCOL
-TIMING\fR) that it is not going to succeed in contacting a
-server. At that time, it consults its own database of old leases and
-tests each one that has not yet timed out by pinging the listed router
-for that lease to see if that lease could work. It is possible to
-define one or more \fIfixed\fR leases in the client configuration file
-for networks where there is no DHCP or BOOTP service, so that the
-client can still automatically configure its address. This is done
-with the
-.B lease
-statement.
-.PP
-NOTE: the lease statement is also used in the dhclient.leases file in
-order to record leases that have been received from DHCP servers.
-Some of the syntax for leases as described below is only needed in the
-dhclient.leases file. Such syntax is documented here for
-completeness.
-.PP
-A lease statement consists of the lease keyword, followed by a left
-curly brace, followed by one or more lease declaration statements,
-followed by a right curly brace. The following lease declarations
-are possible:
-.PP
- \fBbootp;\fR
-.PP
-The
-.B bootp
-statement is used to indicate that the lease was acquired using the
-BOOTP protocol rather than the DHCP protocol. It is never necessary
-to specify this in the client configuration file. The client uses
-this syntax in its lease database file.
-.PP
- \fBinterface\fR \fB"\fR\fIstring\fR\fB";\fR
-.PP
-The
-.B interface
-lease statement is used to indicate the interface on which the lease
-is valid. If set, this lease will only be tried on a particular
-interface. When the client receives a lease from a server, it always
-records the interface number on which it received that lease.
-If predefined leases are specified in the dhclient.conf file, the
-interface should also be specified, although this is not required.
-.PP
- \fBfixed-address\fR \fIip-address\fR\fB;\fR
-.PP
-The
-.B fixed-address
-statement is used to set the ip address of a particular lease. This
-is required for all lease statements. The IP address must be
-specified as a dotted quad (e.g., 12.34.56.78).
-.PP
- \fBfilename "\fR\fIstring\fR\fB";\fR
-.PP
-The
-.B filename
-statement specifies the name of the boot filename to use. This is
-not used by the standard client configuration script, but is included
-for completeness.
-.PP
- \fBserver-name "\fR\fIstring\fR\fB";\fR
-.PP
-The
-.B server-name
-statement specifies the name of the boot server name to use. This is
-also not used by the standard client configuration script.
-.PP
- \fBoption\fR \fIoption-declaration\fR\fB;\fR
-.PP
-The
-.B option
-statement is used to specify the value of an option supplied by the
-server, or, in the case of predefined leases declared in
-dhclient.conf, the value that the user wishes the client configuration
-script to use if the predefined lease is used.
-.PP
- \fBscript "\fIscript-name\fB";\fR
-.PP
-The
-.B script
-statement is used to specify the pathname of the dhcp client
-configuration script. This script is used by the dhcp client to set
-each interface's initial configuration prior to requesting an address,
-to test the address once it has been offered, and to set the
-interface's final configuration once a lease has been acquired. If
-no lease is acquired, the script is used to test predefined leases, if
-any, and also called once if no valid lease can be identified. For
-more information, see
-.B dhclient-script(8).
-.PP
- \fBvendor option space "\fIname\fB";\fR
-.PP
-The
-.B vendor option space
-statement is used to specify which option space should be used for
-decoding the vendor-encapsulate-options option if one is received.
-The \fIdhcp-vendor-identifier\fR can be used to request a specific
-class of vendor options from the server. See
-.B dhcp-options(5)
-for details.
-.PP
- \fBmedium "\fImedia setup\fB";\fR
-.PP
-The
-.B medium
-statement can be used on systems where network interfaces cannot
-automatically determine the type of network to which they are
-connected. The media setup string is a system-dependent parameter
-which is passed to the dhcp client configuration script when
-initializing the interface. On Unix and Unix-like systems, the
-argument is passed on the ifconfig command line when configuring the
-interface.
-.PP
-The dhcp client automatically declares this parameter if it uses a
-media type (see the
-.B media
-statement) when configuring the interface in order to obtain a lease.
-This statement should be used in predefined leases only if the network
-interface requires media type configuration.
-.PP
- \fBrenew\fR \fIdate\fB;\fR
-.PP
- \fBrebind\fR \fIdate\fB;\fR
-.PP
- \fBexpire\fR \fIdate\fB;\fR
-.PP
-The \fBrenew\fR statement defines the time at which the dhcp client
-should begin trying to contact its server to renew a lease that it is
-using. The \fBrebind\fR statement defines the time at which the dhcp
-client should begin to try to contact \fIany\fR dhcp server in order
-to renew its lease. The \fBexpire\fR statement defines the time at
-which the dhcp client must stop using a lease if it has not been able
-to contact a server in order to renew it.
-.PP
-These declarations are automatically set in leases acquired by the
-DHCP client, but must also be configured in predefined leases - a
-predefined lease whose expiry time has passed will not be used by the
-DHCP client.
-.PP
-Dates are specified in one of two ways. The software will output times in
-these two formats depending on if the \fBdb-time-format\fR configuration
-parameter has been set to \fIdefault\fR or \fIlocal\fR.
-.PP
-If it is set to \fIdefault\fR, then \fIdate\fR values appear as follows:
-.PP
- \fI<weekday> <year>\fB/\fI<month>\fB/\fI<day>
-<hour>\fB:\fI<minute>\fB:\fI<second>\fR
-.PP
-The weekday is present to make it easy for a human to tell when a
-lease expires - it's specified as a number from zero to six, with zero
-being Sunday. When declaring a predefined lease, it can always be
-specified as zero. The year is specified with the century, so it
-should generally be four digits except for really long leases. The
-month is specified as a number starting with 1 for January. The day
-of the month is likewise specified starting with 1. The hour is a
-number between 0 and 23, the minute a number between 0 and 59, and the
-second also a number between 0 and 59.
-.PP
-If the \fBdb-time-format\fR configuration was set to \fIlocal\fR, then
-the \fIdate\fR values appear as follows:
-.PP
- \fBepoch\fR \fI<seconds-since-epoch>\fR\fB; #\fR \fI<day-name> <month-name>
-<day-number> <hours>\fR\fB:\fR\fI<minutes>\fR\fB:\fR\fI<seconds> <year>\fR
-.PP
-The \fIseconds-since-epoch\fR is as according to the system's local clock (often
-referred to as "unix time"). The \fB#\fR symbol supplies a comment that
-describes what actual time this is as according to the system's configured
-timezone, at the time the value was written. It is provided only for human
-inspection, the epoch time is the only recommended value for machine
-inspection.
-.PP
-Note that when defining a static lease, one may use either time format one
-wishes, and need not include the comment or values after it.
-.PP
-If the time is infinite in duration, then the \fIdate\fR is \fBnever\fR
-instead of an actual date.
-.SH ALIAS DECLARATIONS
- \fBalias { \fI declarations ... \fB}\fR
-.PP
-Some DHCP clients running TCP/IP roaming protocols may require that in
-addition to the lease they may acquire via DHCP, their interface also
-be configured with a predefined IP alias so that they can have a
-permanent IP address even while roaming. The Internet Systems
-Consortium DHCP client doesn't support roaming with fixed addresses
-directly, but in order to facilitate such experimentation, the dhcp
-client can be set up to configure an IP alias using the
-.B alias
-declaration.
-.PP
-The alias declaration resembles a lease declaration, except that
-options other than the subnet-mask option are ignored by the standard
-client configuration script, and expiry times are ignored. A typical
-alias declaration includes an interface declaration, a fixed-address
-declaration for the IP alias address, and a subnet-mask option
-declaration. A medium statement should never be included in an alias
-declaration.
-.SH OTHER DECLARATIONS
- \fBdb-time-format\fR [ \fIdefault\fR | \fIlocal\fR ] \fB;\fR
-.PP
-The \fBdb-time-format\fR option determines which of two output methods are
-used for printing times in leases files. The \fIdefault\fR format provides
-day-and-time in UTC, whereas \fIlocal\fR uses a seconds-since-epoch to store
-the time value, and helpfully places a local timezone time in a comment on
-the same line. The formats are described in detail in this manpage, within
-the LEASE DECLARATIONS section.
-.PP
-The
-.I lease-id-format
-parameter
-.RS 0.25i
-.PP
-.B lease-id-format \fIformat\fB;\fR
-.PP
-The \fIformat\fR parameter must be either \fBoctal\fR or \fBhex\fR.
-This parameter governs the format used to write certain values to lease
-files. With the default format, octal, values are written as quoted strings in
-which non-printable characters are represented as octal escapes -
-a backslash character followed by three octal digits. When the hex format
-is specified, values are written as an unquoted series of hexadecimal digit
-pairs, separated by colons.
-
-Currently, the values written out based on lease-id-format are the default-duid
-and the IAID value (DHCPv6 only). The client automatically reads the values
-in either format. Note that when the format is octal, rather than as an octal
-string, IAID is output as hex if it contains no printable characters or as a
-string if contains only printable characters. This is done to maintain backward
-compatibility.
-.PP
- \fBreject \fIcidr-ip-address\fR [\fB,\fR \fI...\fB \fIcidr-ip-address\fR ] \fB;\fR
-.PP
-The
-.B reject
-statement causes the DHCP client to reject offers from
-servers whose server identifier matches any of the specified hosts or
-subnets. This can be used to avoid being configured by rogue or
-misconfigured dhcp servers, although it should be a last resort -
-better to track down the bad DHCP server and fix it.
-.PP
-The \fIcidr-ip-address\fR configuration type is of the
-form \fIip-address\fR[\fB/\fIprefixlen\fR], where \fIip-address\fR is a
-dotted quad IP address, and \fRprefixlen\fR is the CIDR prefix length of
-the subnet, counting the number of significant bits in the netmask starting
-from the leftmost end. Example configuration syntax:
-.PP
-.I \fIreject\fR 192.168.0.0\fB/\fR16\fB,\fR 10.0.0.5\fB;\fR
-.PP
-The above example would cause offers from any server identifier in the
-entire RFC 1918 "Class C" network 192.168.0.0/16, or the specific
-single address 10.0.0.5, to be rejected.
-.PP
- \fBinterface "\fIname\fB" { \fIdeclarations ... \fB }
-.PP
-A client with more than one network interface may require different
-behaviour depending on which interface is being configured. All
-timing parameters and declarations other than lease and alias
-declarations can be enclosed in an interface declaration, and those
-parameters will then be used only for the interface that matches the
-specified name. Interfaces for which there is no interface
-declaration will use the parameters declared outside of any interface
-declaration, or the default settings.
-.PP
-.B Note well:
-ISC dhclient only maintains one list of interfaces, which is either
-determined at startup from command line arguments, or otherwise is
-autodetected. If you supplied the list of interfaces on the command
-line, this configuration clause will add the named interface to the
-list in such a way that will cause it to be configured by DHCP. Which
-may not be the result you had intended. This is an undesirable side
-effect that will be addressed in a future release.
-.PP
- \fBpseudo "\fIname\fR" "\fIreal-name\fB" { \fIdeclarations ... \fB }
-.PP
-Under some circumstances it can be useful to declare a pseudo-interface
-and have the DHCP client acquire a configuration for that interface.
-Each interface that the DHCP client is supporting normally has a DHCP
-client state machine running on it to acquire and maintain its lease.
-A pseudo-interface is just another state machine running on the
-interface named \fIreal-name\fR, with its own lease and its own
-state. If you use this feature, you must provide a client identifier
-for both the pseudo-interface and the actual interface, and the two
-identifiers must be different. You must also provide a separate
-client script for the pseudo-interface to do what you want with the IP
-address. For example:
-.PP
-.nf
- interface "ep0" {
- send dhcp-client-identifier "my-client-ep0";
- }
- pseudo "secondary" "ep0" {
- send dhcp-client-identifier "my-client-ep0-secondary";
- script "/etc/dhclient-secondary";
- }
-.fi
-.PP
-The client script for the pseudo-interface should not configure the
-interface up or down - essentially, all it needs to handle are the
-states where a lease has been acquired or renewed, and the states
-where a lease has expired. See \fBdhclient-script(8)\fR for more
-information.
-.PP
- \fBmedia "\fImedia setup\fB"\fI [ \fB, "\fImedia setup\fB", \fI... ]\fB;\fR
-.PP
-The
-.B media
-statement defines one or more media configuration parameters which may
-be tried while attempting to acquire an IP address. The dhcp client
-will cycle through each media setup string on the list, configuring
-the interface using that setup and attempting to boot, and then trying
-the next one. This can be used for network interfaces which aren't
-capable of sensing the media type unaided - whichever media type
-succeeds in getting a request to the server and hearing the reply is
-probably right (no guarantees).
-.PP
-The media setup is only used for the initial phase of address
-acquisition (the DHCPDISCOVER and DHCPOFFER packets). Once an
-address has been acquired, the dhcp client will record it in its lease
-database and will record the media type used to acquire the address.
-Whenever the client tries to renew the lease, it will use that same
-media type. The lease must expire before the client will go back to
-cycling through media types.
-.PP
- \fBhardware\fR \fIlink-type mac-address\fR\fB;\fR
-.PP
-The
-.B hardware
-statement defines the hardware MAC address to use for this interface,
-for DHCP servers or relays to direct their replies. dhclient will determine
-the interface's MAC address automatically, so use of this parameter
-is not recommended. The \fIlink-type\fR corresponds to the interface's
-link layer type (example: \'ethernet\'), while the \fImac-address\fR is
-a string of colon-separated hexadecimal values for octets.
-.PP
- \fBanycast-mac\fR \fIlink-type mac-address\fR\fB;\fR
-.PP
-The
-.B anycast-mac
-statement over-rides the all-ones broadcast MAC address dhclient will use
-when it is transmitting packets to the all-ones limited broadcast IPv4
-address. This configuration parameter is useful to reduce the number of
-broadcast packets transmitted by DHCP clients, but is only useful if you
-know the DHCP service(s) anycast MAC address prior to configuring your
-client. The \fIlink-type\fR and \fImac-address\fR parameters are configured
-in a similar manner to the \fBhardware\fR statement.
-.PP
-.SH SAMPLE
-The following configuration file was used on a laptop running NetBSD
-1.3, though the domains have been modified.
-The laptop has an IP alias of 192.5.5.213, and has one
-interface, ep0 (a 3com 3C589C). Booting intervals have been
-shortened somewhat from the default, because the client is known to
-spend most of its time on networks with little DHCP activity. The
-laptop does roam to multiple networks.
-
-.nf
-
-timeout 60;
-retry 60;
-reboot 10;
-select-timeout 5;
-initial-interval 2;
-reject 192.33.137.209;
-
-interface "ep0" {
- send host-name "andare.example.com";
- hardware ethernet 00:a0:24:ab:fb:9c;
- send dhcp-client-identifier 1:0:a0:24:ab:fb:9c;
- send dhcp-lease-time 3600;
- supersede domain-search "example.com", "rc.isc.org", "home.isc.org";
- prepend domain-name-servers 127.0.0.1;
- request subnet-mask, broadcast-address, time-offset, routers,
- domain-name, domain-name-servers, host-name;
- require subnet-mask, domain-name-servers;
- script "CLIENTBINDIR/dhclient-script";
- media "media 10baseT/UTP", "media 10base2/BNC";
-}
-
-alias {
- interface "ep0";
- fixed-address 192.5.5.213;
- option subnet-mask 255.255.255.255;
-}
-.fi
-This is a very complicated dhclient.conf file - in general, yours
-should be much simpler. In many cases, it's sufficient to just
-create an empty dhclient.conf file - the defaults are usually fine.
-.SH SEE ALSO
-dhcp-options(5), dhcp-eval(5), dhclient.leases(5), dhcpd(8), dhcpd.conf(5),
-RFC2132, RFC2131.
-.SH AUTHOR
-.B dhclient(8)
-Information about Internet Systems Consortium can be found at
-.B https://www.isc.org.
diff --git a/client/dhclient.conf.example b/client/dhclient.conf.example
deleted file mode 100644
index 2c35d248..00000000
--- a/client/dhclient.conf.example
+++ /dev/null
@@ -1,36 +0,0 @@
-send host-name = pick-first-value(gethostname(), "ISC-dhclient");
-send dhcp-client-identifier 1:0:a0:24:ab:fb:9c;
-send dhcp-lease-time 3600;
-supersede domain-search "example.com", "isc.org";
-prepend domain-name-servers 127.0.0.1;
-request subnet-mask, broadcast-address, time-offset, routers,
- domain-name, domain-name-servers, host-name;
-require subnet-mask, domain-name-servers;
-timeout 60;
-retry 60;
-reboot 10;
-select-timeout 5;
-initial-interval 2;
-script "/etc/dhclient-script";
-media "-link0 -link1 -link2", "link0 link1";
-reject 192.33.137.209;
-
-alias {
- interface "ep0";
- fixed-address 192.5.5.213;
- option subnet-mask 255.255.255.255;
-}
-
-lease {
- interface "ep0";
- fixed-address 192.33.137.200;
- medium "link0 link1";
- option host-name "andare.example.com";
- option subnet-mask 255.255.255.0;
- option broadcast-address 192.33.137.255;
- option routers 192.33.137.250;
- option domain-name-servers 127.0.0.1;
- renew 2 2000/1/12 00:00:01;
- rebind 2 2000/1/12 00:00:01;
- expire 2 2000/1/12 00:00:01;
-}
diff --git a/client/dhclient.leases.5 b/client/dhclient.leases.5
deleted file mode 100644
index 4d9c3d62..00000000
--- a/client/dhclient.leases.5
+++ /dev/null
@@ -1,50 +0,0 @@
-.\" $Id: dhclient.leases.5,v 1.8 2011/02/23 23:50:55 sar Exp $
-.\"
-.\" Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
-.\" Copyright (c) 1997-2003 by Internet Software Consortium
-.\"
-.\" This Source Code Form is subject to the terms of the Mozilla Public
-.\" License, v. 2.0. If a copy of the MPL was not distributed with this
-.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
-.\"
-.\" 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.
-.\" PO Box 360
-.\" Newmarket, NH 03857 USA
-.\" <info@isc.org>
-.\" https://www.isc.org/
-.\"
-.\" Support and other services are available for ISC products - see
-.\" https://www.isc.org for more information or to learn more about ISC.
-.\"
-.\" $Id: dhclient.leases.5,v 1.8 2011/02/23 23:50:55 sar Exp $
-.\"
-.TH dhclient.leases 5
-.SH NAME
-dhclient.leases - DHCP client lease database
-.SH DESCRIPTION
-The Internet Systems Consortium DHCP client keeps a persistent
-database of leases that it has acquired that are still valid. The
-database is a free-form ASCII file containing one valid declaration
-per lease. If more than one declaration appears for a given lease,
-the last one in the file is used. The file is written as a log, so
-this is not an unusual occurrence.
-.PP
-The format of the lease declarations is described in
-.B dhclient.conf(5).
-.SH FILES
-.B DBDIR/dhclient.leases
-.SH SEE ALSO
-dhclient(8), dhcp-options(5), dhclient.conf(5), dhcpd(8),
-dhcpd.conf(5), RFC2132, RFC2131.
-.SH AUTHOR
-.B dhclient(8)
-Information about Internet Systems Consortium can be found at
-.B https://www.isc.org.
diff --git a/client/scripts/bsdos b/client/scripts/bsdos
deleted file mode 100755
index d69d0d86..00000000
--- a/client/scripts/bsdos
+++ /dev/null
@@ -1,324 +0,0 @@
-#!/bin/sh
-
-make_resolv_conf() {
- if [ x"$new_domain_name_servers" != x ]; then
- cat /dev/null > /etc/resolv.conf.dhclient
- if [ "x$new_domain_search" != x ]; then
- echo search $new_domain_search >> /etc/resolv.conf.dhclient
- elif [ "x$new_domain_name" != x ]; then
- # Note that the DHCP 'Domain Name Option' is really just a domain
- # name, and that this practice of using the domain name option as
- # a search path is both nonstandard and deprecated.
- echo search $new_domain_name >> /etc/resolv.conf.dhclient
- fi
- for nameserver in $new_domain_name_servers; do
- echo nameserver $nameserver >> /etc/resolv.conf.dhclient
- done
-
- mv /etc/resolv.conf.dhclient /etc/resolv.conf
- elif [ "x${new_dhcp6_name_servers}" != x ] ; then
- cat /dev/null > /etc/resolv.conf.dhclient6
- chmod 644 /etc/resolv.conf.dhclient6
-
- if [ "x${new_dhcp6_domain_search}" != x ] ; then
- echo search ${new_dhcp6_domain_search} >> /etc/resolv.conf.dhclient6
- fi
- for nameserver in ${new_dhcp6_name_servers} ; do
- # If the nameserver has a link-local address
- # add a <zone_id> (interface name) to it.
- case $nameserver in
- fe80:*) zone_id="%$interface";;
- FE80:*) zone_id="%$interface";;
- *) zone_id="";;
- esac
- echo nameserver ${nameserver}$zone_id >> /etc/resolv.conf.dhclient6
- done
-
- mv /etc/resolv.conf.dhclient6 /etc/resolv.conf
- fi
-}
-
-# Must be used on exit. Invokes the local dhcp client exit hooks, if any.
-exit_with_hooks() {
- exit_status=$1
- if [ -f /etc/dhclient-exit-hooks ]; then
- . /etc/dhclient-exit-hooks
- fi
-# probably should do something with exit status of the local script
- exit $exit_status
-}
-
-# Invoke the local dhcp client enter hooks, if they exist.
-if [ -f /etc/dhclient-enter-hooks ]; then
- exit_status=0
- . /etc/dhclient-enter-hooks
- # allow the local script to abort processing of this state
- # local script must set exit_status variable to nonzero.
- if [ $exit_status -ne 0 ]; then
- exit $exit_status
- fi
-fi
-
-if [ x$new_network_number != x ]; then
- echo New Network Number: $new_network_number
-fi
-
-if [ x$new_broadcast_address != x ]; then
- echo New Broadcast Address: $new_broadcast_address
- new_broadcast_arg="broadcast $new_broadcast_address"
-fi
-if [ x$old_broadcast_address != x ]; then
- old_broadcast_arg="broadcast $old_broadcast_address"
-fi
-if [ x$new_subnet_mask != x ]; then
- new_netmask_arg="netmask $new_subnet_mask"
-fi
-if [ x$old_subnet_mask != x ]; then
- old_netmask_arg="netmask $old_subnet_mask"
-fi
-if [ x$alias_subnet_mask != x ]; then
- alias_subnet_arg="netmask $alias_subnet_mask"
-fi
-if [ x$new_interface_mtu != x ]; then
- mtu_arg="mtu $new_interface_mtu"
-fi
-if [ x$IF_METRIC != x ]; then
- metric_arg="metric $IF_METRIC"
-fi
-
-if [ x$reason = xMEDIUM ]; then
- eval "ifconfig $interface $medium"
- eval "ifconfig $interface inet -alias 0.0.0.0 $medium" >/dev/null 2>&1
- sleep 1
- exit_with_hooks 0
-fi
-
-###
-### DHCPv4 Handlers
-###
-
-if [ x$reason = xPREINIT ]; then
- if [ x$alias_ip_address != x ]; then
- ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
- fi
- ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 \
- broadcast 255.255.255.255 up
- exit_with_hooks 0
-fi
-
-if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then
- exit_with_hooks 0;
-fi
-
-if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \
- [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then
- current_hostname=`hostname`
- if [ x$current_hostname = x ] || \
- [ x$current_hostname = x$old_host_name ]; then
- if [ x$current_hostname = x ] || \
- [ x$new_host_name != x$old_host_name ]; then
- hostname $new_host_name
- fi
- fi
-
- if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \
- [ x$alias_ip_address != x$old_ip_address ]; then
- ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
- fi
- if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]
- then
- eval "ifconfig $interface inet -alias $old_ip_address $medium"
- route delete $old_ip_address 127.1 >/dev/null 2>&1
- for router in $old_routers; do
- route delete default $router >/dev/null 2>&1
- done
- if [ "$old_static_routes" != "" ]; then
- set $old_static_routes
- while [ $# -gt 1 ]; do
- route delete $1 $2
- shift; shift
- done
- fi
- arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' |sh
- fi
- if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \
- [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then
- eval "ifconfig $interface inet $new_ip_address $new_netmask_arg \
- $new_broadcast_arg $mtu_arg $metric_arg $medium"
- route add $new_ip_address 127.1 >/dev/null 2>&1
- for router in $new_routers; do
- route add default $router >/dev/null 2>&1
- done
- if [ "$new_static_routes" != "" ]; then
- set $new_static_routes
- while [ $# -gt 1 ]; do
- route add $1 $2
- shift; shift
- done
- fi
- else
- # we haven't changed the address, have we changed other options
- # that we wish to update?
- if [ x$new_routers != x ] && [ x$new_routers != x$old_routers ] ; then
- # if we've changed routers delete the old and add the new.
- $LOGGER "New Routers: $new_routers"
- for router in $old_routers; do
- route delete default $router >/dev/null 2>&1
- done
- for router in $new_routers; do
- route add default $router >/dev/null 2>&1
- done
- fi
- fi
- if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ];
- then
- ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg
- route add $alias_ip_address 127.0.0.1
- fi
- make_resolv_conf
- exit_with_hooks 0
-fi
-
-if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ] || [ x$reason = xRELEASE ] \
- || [ x$reason = xSTOP ]; then
- if [ x$alias_ip_address != x ]; then
- ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
- fi
- if [ x$old_ip_address != x ]; then
- eval "ifconfig $interface inet -alias $old_ip_address $medium"
- route delete $old_ip_address 127.1 >/dev/null 2>&1
- for router in $old_routers; do
- route delete default $router >/dev/null 2>&1
- done
- if [ "$old_static_routes" != "" ]; then
- set $old_static_routes
- while [ $# -gt 1 ]; do
- route delete $1 $2
- shift; shift
- done
- fi
- arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' \
- |sh >/dev/null 2>&1
- fi
- if [ x$alias_ip_address != x ]; then
- ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg
- route add $alias_ip_address 127.0.0.1
- fi
- exit_with_hooks 0
-fi
-
-if [ x$reason = xTIMEOUT ]; then
- if [ x$alias_ip_address != x ]; then
- ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
- fi
- eval "ifconfig $interface inet $new_ip_address $new_netmask_arg \
- $new_broadcast_arg $mtu_arg $metric_arg $medium"
- sleep 1
- if [ "$new_routers" != "" ]; then
- set $new_routers
- if ping -q -c 1 -w 1 $1; then
- if [ x$new_ip_address != x$alias_ip_address ] && \
- [ x$alias_ip_address != x ]; then
- ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg
- route add $alias_ip_address 127.0.0.1
- fi
- route add $new_ip_address 127.1 >/dev/null 2>&1
- for router in $new_routers; do
- route add default $router >/dev/null 2>&1
- done
- set $new_static_routes
- while [ $# -gt 1 ]; do
- route add $0 $1
- shift; shift
- done
- make_resolv_conf
- exit_with_hooks 0
- fi
- fi
- eval "ifconfig $interface inet -alias $new_ip_address $medium"
- for router in $old_routers; do
- route delete default $router >/dev/null 2>&1
- done
- if [ "$old_static_routes" != "" ]; then
- set $old_static_routes
- while [ $# -gt 1 ]; do
- route delete $1 $2
- shift; shift
- done
- fi
- arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' \
- |sh >/dev/null 2>&1
- exit_with_hooks 1
-fi
-
-###
-### DHCPv6 Handlers
-###
-
-if [ ${reason} = PREINIT6 ] ; then
- # Ensure interface is up.
- ifconfig ${interface} up
-
- # XXX: Remove any stale addresses from aborted clients.
-
- exit_with_hooks 0
-fi
-
-if [ x${old_ip6_prefix} != x ] || [ x${new_ip6_prefix} != x ] ; then
- echo Prefix ${reason} old=${old_ip6_prefix} new=${new_ip6_prefix}
-
- exit_with_hooks 0
-fi
-
-if [ ${reason} = BOUND6 ] ; then
- if [ x${new_ip6_address} = x ] || [ x${new_ip6_prefixlen} = x ] ; then
- exit_with_hooks 2;
- fi
-
- ifconfig ${interface} inet6 add ${new_ip6_address}/${new_ip6_prefixlen}
-
- # Check for nameserver options.
- make_resolv_conf
-
- exit_with_hooks 0
-fi
-
-if [ ${reason} = RENEW6 ] || [ ${reason} = REBIND6 ] ; then
- # Make sure nothing has moved around on us.
-
- # Nameservers/domains/etc.
- if [ "x${new_dhcp6_name_servers}" != "x${old_dhcp6_name_servers}" ] ||
- [ "x${new_dhcp6_domain_search}" != "x${old_dhcp6_domain_search}" ] ; then
- make_resolv_conf
- fi
-
- exit_with_hooks 0
-fi
-
-if [ ${reason} = DEPREF6 ] ; then
- if [ x${new_ip6_prefixlen} = x ] ; then
- exit_with_hooks 2;
- fi
-
- # XXX:
- # There doesn't appear to be a way to update an addr to indicate
- # preference.
-
- exit_with_hooks 0
-fi
-
-if [ ${reason} = EXPIRE6 -o ${reason} = RELEASE6 -o ${reason} = STOP6 ] ; then
- if [ x${old_ip6_address} = x ] || [ x${old_ip6_prefixlen} = x ] ; then
- exit_with_hooks 2;
- fi
-
- ifconfig ${interface} inet6 delete ${old_ip6_address}/${old_ip6_prefixlen}
-
- exit_with_hooks 0
-fi
-
-exit_with_hooks 0
diff --git a/client/scripts/freebsd b/client/scripts/freebsd
deleted file mode 100755
index 7c073f86..00000000
--- a/client/scripts/freebsd
+++ /dev/null
@@ -1,474 +0,0 @@
-#!/bin/sh
-#
-# $Id: freebsd,v 1.24 2011/05/18 19:55:44 sar Exp $
-#
-# $FreeBSD$
-
-if [ -x /usr/bin/logger ]; then
- LOGGER="/usr/bin/logger -s -p user.notice -t dhclient"
-else
- LOGGER=echo
-fi
-
-make_resolv_conf() {
- if [ x"$new_domain_name_servers" != x ]; then
- ( cat /dev/null > /etc/resolv.conf.dhclient )
- exit_status=$?
- if [ $exit_status -ne 0 ]; then
- $LOGGER "Unable to create /etc/resolv.conf.dhclient: Error $exit_status"
- else
- if [ "x$new_domain_search" != x ]; then
- ( echo search $new_domain_search >> /etc/resolv.conf.dhclient )
- exit_status=$?
- elif [ "x$new_domain_name" != x ]; then
- # Note that the DHCP 'Domain Name Option' is really just a domain
- # name, and that this practice of using the domain name option as
- # a search path is both nonstandard and deprecated.
- ( echo search $new_domain_name >> /etc/resolv.conf.dhclient )
- exit_status=$?
- fi
- for nameserver in $new_domain_name_servers; do
- if [ $exit_status -ne 0 ]; then
- break
- fi
- ( echo nameserver $nameserver >>/etc/resolv.conf.dhclient )
- exit_status=$?
- done
-
- # If there were no errors, attempt to mv the new file into place.
- if [ $exit_status -eq 0 ]; then
- ( mv /etc/resolv.conf.dhclient /etc/resolv.conf )
- exit_status=$?
- fi
-
- if [ $exit_status -ne 0 ]; then
- $LOGGER "Error while writing new /etc/resolv.conf."
- fi
- fi
- elif [ "x${new_dhcp6_name_servers}" != x ] ; then
- ( cat /dev/null > /etc/resolv.conf.dhclient6 )
- exit_status=$?
- if [ $exit_status -ne 0 ] ; then
- $LOGGER "Unable to create /etc/resolv.conf.dhclient6: Error $exit_status"
- else
- if [ "x${new_dhcp6_domain_search}" != x ] ; then
- ( echo search ${new_dhcp6_domain_search} >> /etc/resolv.conf.dhclient6 )
- exit_status=$?
- fi
- for nameserver in ${new_dhcp6_name_servers} ; do
- if [ $exit_status -ne 0 ] ; then
- break
- fi
- # If the nameserver has a link-local address
- # add a <zone_id> (interface name) to it.
- case $nameserver in
- fe80:*) zone_id="%$interface";;
- FE80:*) zone_id="%$interface";;
- *) zone_id="";;
- esac
- ( echo nameserver ${nameserver}$zone_id >> /etc/resolv.conf.dhclient6 )
- exit_status=$?
- done
-
- if [ $exit_status -eq 0 ] ; then
- ( mv /etc/resolv.conf.dhclient6 /etc/resolv.conf )
- exit_status=$?
- fi
-
- if [ $exit_status -ne 0 ] ; then
- $LOGGER "Error while writing new /etc/resolv.conf."
- fi
- fi
- fi
-}
-
-# Must be used on exit. Invokes the local dhcp client exit hooks, if any.
-exit_with_hooks() {
- exit_status=$1
- if [ -f /etc/dhclient-exit-hooks ]; then
- . /etc/dhclient-exit-hooks
- fi
-# probably should do something with exit status of the local script
- exit $exit_status
-}
-
-# This function was largely borrowed from dhclient-script that
-# ships with Centos, authored by Jiri Popelka and David Cantrell
-# of Redhat. Thanks guys.
-add_ipv6_addr_with_DAD() {
- ifconfig ${interface} inet6 ${new_ip6_address}/${new_ip6_prefixlen} alias
-
- if [ ${dad_wait_time} -le 0 ]
- then
- # if we're not waiting for DAD, assume we're good
- return 0
- fi
-
- # Repeatedly test whether newly added address passed
- # duplicate address detection (DAD)
- for i in $(seq 1 ${dad_wait_time}); do
- sleep 1 # give the DAD some time
-
- addr=$(ifconfig ${interface} \
- | grep "${new_ip6_address} prefixlen ${new_ip6_prefixlen}")
-
- # tentative flag == DAD is still not complete
- tentative=$(echo "${addr}" | grep tentative)
- # dadfailed flag == address is already in use somewhere else
- dadfailed=$(echo "${addr}" | grep duplicated)
-
- if [ -n "${dadfailed}" ] ; then
- # dad failed, remove the address
- ifconfig ${interface} inet6 ${new_ip6_address}/${new_ip6_prefixlen} -alias
- exit_with_hooks 3
- fi
-
- if [ -z "${tentative}" ] ; then
- if [ -n "${addr}" ]; then
- # DAD is over
- return 0
- else
- # address was auto-removed (or not added at all)
- exit_with_hooks 3
- fi
- fi
- done
-
- return 0
-}
-
-# Invoke the local dhcp client enter hooks, if they exist.
-if [ -f /etc/dhclient-enter-hooks ]; then
- exit_status=0
- . /etc/dhclient-enter-hooks
- # allow the local script to abort processing of this state
- # local script must set exit_status variable to nonzero.
- if [ $exit_status -ne 0 ]; then
- exit $exit_status
- fi
-fi
-
-if [ x$new_network_number != x ]; then
- $LOGGER New Network Number: $new_network_number
-fi
-
-if [ x$new_broadcast_address != x ]; then
- $LOGGER New Broadcast Address: $new_broadcast_address
- new_broadcast_arg="broadcast $new_broadcast_address"
-fi
-if [ x$old_broadcast_address != x ]; then
- old_broadcast_arg="broadcast $old_broadcast_address"
-fi
-if [ x$new_subnet_mask != x ]; then
- new_netmask_arg="netmask $new_subnet_mask"
-fi
-if [ x$old_subnet_mask != x ]; then
- old_netmask_arg="netmask $old_subnet_mask"
-fi
-if [ x$alias_subnet_mask != x ]; then
- alias_subnet_arg="netmask $alias_subnet_mask"
-fi
-if [ x$new_interface_mtu != x ]; then
- mtu_arg="mtu $new_interface_mtu"
-fi
-if [ x$IF_METRIC != x ]; then
- metric_arg="metric $IF_METRIC"
-fi
-
-if [ x$reason = xMEDIUM ]; then
- eval "ifconfig $interface $medium"
- eval "ifconfig $interface inet -alias 0.0.0.0 $medium" >/dev/null 2>&1
- sleep 1
- exit_with_hooks 0
-fi
-
-###
-### DHCPv4 Handlers
-###
-
-if [ x$reason = xPREINIT ]; then
- if [ x$alias_ip_address != x ]; then
- ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
- fi
- ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 \
- broadcast 255.255.255.255 up
- exit_with_hooks 0
-fi
-
-if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then
- exit_with_hooks 0;
-fi
-
-if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \
- [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then
- current_hostname=`/bin/hostname`
- if [ x$current_hostname = x ] || \
- [ x$current_hostname = x$old_host_name ]; then
- if [ x$current_hostname = x ] || \
- [ x$new_host_name != x$old_host_name ]; then
- $LOGGER "New Hostname: $new_host_name"
- hostname $new_host_name
- fi
- fi
- if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \
- [ x$alias_ip_address != x$old_ip_address ]; then
- ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
- fi
- if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]
- then
- eval "ifconfig $interface inet -alias $old_ip_address $medium"
- route delete $old_ip_address 127.1 >/dev/null 2>&1
- for router in $old_routers; do
- route delete default $router >/dev/null 2>&1
- done
- if [ -n "$old_static_routes" ]; then
- set -- $old_static_routes
- while [ $# -gt 1 ]; do
- route delete $1 $2
- shift; shift
- done
- fi
- arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -d \1/p' |sh
- fi
- if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \
- [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then
- eval "ifconfig $interface inet $new_ip_address $new_netmask_arg \
- $new_broadcast_arg $mtu_arg $metric_arg $medium"
- $LOGGER "New IP Address ($interface): $new_ip_address"
- $LOGGER "New Subnet Mask ($interface): $new_subnet_mask"
- $LOGGER "New Broadcast Address ($interface): $new_broadcast_address"
- if [ -n "$new_routers" ]; then
- $LOGGER "New Routers: $new_routers"
- fi
- route add $new_ip_address 127.1 >/dev/null 2>&1
- for router in $new_routers; do
- # If the subnet is captive, eg the netmask is /32 but the default
- # gateway is (obviously) outside of this, then we need to produce a
- # host route to reach the gateway.
- if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then
- route add -host $router -interface $interface
- fi
- route add default $router >/dev/null 2>&1
- done
- if [ -n "$new_static_routes" ]; then
- $LOGGER "New Static Routes: $new_static_routes"
- set -- $new_static_routes
- while [ $# -gt 1 ]; do
- route add $1 $2
- shift; shift
- done
- fi
- else
- # we haven't changed the address, have we changed other options
- # that we wish to update?
- if [ x$new_routers != x ] && [ x$new_routers != x$old_routers ] ; then
- # if we've changed routers delete the old and add the new.
- $LOGGER "New Routers: $new_routers"
- for router in $old_routers; do
- route delete default $router >/dev/null 2>&1
- done
- for router in $new_routers; do
- # If the subnet is captive, eg the netmask is /32 but the default
- # gateway is (obviously) outside of this, then we need to produce a
- # host route to reach the gateway.
- if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then
- route add -host $router -interface $interface
- fi
- route add default $router >/dev/null 2>&1
- done
- fi
- fi
- if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ];
- then
- ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg
- route add $alias_ip_address 127.0.0.1
- fi
- make_resolv_conf
- exit_with_hooks 0
-fi
-
-if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ] || [ x$reason = xRELEASE ] \
- || [ x$reason = xSTOP ]; then
- if [ x$alias_ip_address != x ]; then
- ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
- fi
- if [ x$old_ip_address != x ]; then
- eval "ifconfig $interface inet -alias $old_ip_address $medium"
- route delete $old_ip_address 127.1 >/dev/null 2>&1
- for router in $old_routers; do
- route delete default $router >/dev/null 2>&1
- done
- if [ -n "$old_static_routes" ]; then
- set -- $old_static_routes
- while [ $# -gt 1 ]; do
- route delete $1 $2
- shift; shift
- done
- fi
- arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -d \1/p' \
- |sh >/dev/null 2>&1
- fi
- if [ x$alias_ip_address != x ]; then
- ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg
- route add $alias_ip_address 127.0.0.1
- fi
- exit_with_hooks 0
-fi
-
-if [ x$reason = xTIMEOUT ]; then
- if [ x$alias_ip_address != x ]; then
- ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
- fi
- eval "ifconfig $interface inet $new_ip_address $new_netmask_arg \
- $new_broadcast_arg $mtu_arg $metric_arg $medium"
- $LOGGER "New IP Address ($interface): $new_ip_address"
- $LOGGER "New Subnet Mask ($interface): $new_subnet_mask"
- $LOGGER "New Broadcast Address ($interface): $new_broadcast_address"
- sleep 1
- if [ -n "$new_routers" ]; then
- $LOGGER "New Routers: $new_routers"
- set -- $new_routers
- if ping -q -c 1 $1; then
- if [ x$new_ip_address != x$alias_ip_address ] && \
- [ x$alias_ip_address != x ]; then
- ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg
- route add $alias_ip_address 127.0.0.1
- fi
- route add $new_ip_address 127.1 >/dev/null 2>&1
- for router in $new_routers; do
- if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then
- route add -host $router -interface $interface
- fi
- route add default $router >/dev/null 2>&1
- done
- set -- $new_static_routes
- while [ $# -gt 1 ]; do
- route add $1 $2
- shift; shift
- done
- make_resolv_conf
- exit_with_hooks 0
- fi
- fi
- eval "ifconfig $interface inet -alias $new_ip_address $medium"
- for router in $old_routers; do
- route delete default $router >/dev/null 2>&1
- done
- if [ -n "$old_static_routes" ]; then
- set -- $old_static_routes
- while [ $# -gt 1 ]; do
- route delete $1 $2
- shift; shift
- done
- fi
- arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -d \1/p' \
- |sh >/dev/null 2>&1
- exit_with_hooks 1
-fi
-
-###
-### DHCPv6 Handlers
-###
-
-if [ ${reason} = PREINIT6 ] ; then
- # Ensure interface is up.
- ifconfig ${interface} up
-
- # XXX: Remove any stale addresses from aborted clients.
-
- # We need to give the kernel some time to active interface
- interface_up_wait_time=5
- for i in $(seq 0 ${interface_up_wait_time})
- do
- ifconfig ${interface} | grep inactive >/dev/null 2>&1
- if [ $? -ne 0 ]; then
- break;
- fi
- sleep 1
- done
-
- # Wait for duplicate address detection for this interface if the
- # --dad-wait-time parameter has been specified and is greater than
- # zero.
- if [ ${dad_wait_time} -gt 0 ]; then
- # Check if any IPv6 address on this interface is marked as
- # tentative.
- ifconfig ${interface} | grep inet6 | grep tentative \
- >/dev/null 2>&1
- if [ $? -eq 0 ]; then
- # Wait for duplicate address detection to complete or for
- # the timeout specified as --dad-wait-time.
- for i in $(seq 0 $dad_wait_time)
- do
- # We're going to poll for the tentative flag every second.
- sleep 1
- ifconfig ${interface} | grep inet6 | grep tentative \
- >/dev/null 2>&1
- if [ $? -ne 0 ]; then
- break;
- fi
- done
- fi
- fi
-
-
- exit_with_hooks 0
-fi
-
-if [ x${old_ip6_prefix} != x ] || [ x${new_ip6_prefix} != x ] ; then
- echo Prefix ${reason} old=${old_ip6_prefix} new=${new_ip6_prefix}
-
- exit_with_hooks 0
-fi
-
-if [ ${reason} = BOUND6 ] ; then
- if [ x${new_ip6_address} = x ] || [ x${new_ip6_prefixlen} = x ] ; then
- exit_with_hooks 2;
- fi
-
- # Add address to interface, check for DAD if dad_wait_time > 0
- add_ipv6_addr_with_DAD
-
- # Check for nameserver options.
- make_resolv_conf
-
- exit_with_hooks 0
-fi
-
-if [ ${reason} = RENEW6 ] || [ ${reason} = REBIND6 ] ; then
- # Make sure nothing has moved around on us.
-
- # Nameservers/domains/etc.
- if [ "x${new_dhcp6_name_servers}" != "x${old_dhcp6_name_servers}" ] ||
- [ "x${new_dhcp6_domain_search}" != "x${old_dhcp6_domain_search}" ] ; then
- make_resolv_conf
- fi
-
- exit_with_hooks 0
-fi
-
-if [ ${reason} = DEPREF6 ] ; then
- if [ x${new_ip6_address} = x ] ; then
- exit_with_hooks 2;
- fi
-
- ifconfig ${interface} inet6 ${new_ip6_address} deprecated
-
- exit_with_hooks 0
-fi
-
-if [ ${reason} = EXPIRE6 -o ${reason} = RELEASE6 -o ${reason} = STOP6 ] ; then
- if [ x${old_ip6_address} = x ] || [ x${old_ip6_prefixlen} = x ] ; then
- exit_with_hooks 2;
- fi
-
- ifconfig ${interface} inet6 ${old_ip6_address}/${old_ip6_prefixlen} -alias
-
- exit_with_hooks 0
-fi
-
-exit_with_hooks 0
diff --git a/client/scripts/linux b/client/scripts/linux
deleted file mode 100755
index c4e51f6d..00000000
--- a/client/scripts/linux
+++ /dev/null
@@ -1,496 +0,0 @@
-#!/bin/bash
-# dhclient-script for Linux. Dan Halbert, March, 1997.
-# Updated for Linux 2.[12] by Brian J. Murrell, January 1999.
-# No guarantees about this. I'm a novice at the details of Linux
-# networking.
-
-# Notes:
-
-# 0. This script is based on the netbsd script supplied with dhcp-970306.
-
-# 1. ifconfig down apparently deletes all relevant routes and flushes
-# the arp cache, so this doesn't need to be done explicitly.
-
-# 2. The alias address handling here has not been tested AT ALL.
-# I'm just going by the doc of modern Linux ip aliasing, which uses
-# notations like eth0:0, eth0:1, for each alias.
-
-# 3. I have to calculate the network address, and calculate the broadcast
-# address if it is not supplied. This might be much more easily done
-# by the dhclient C code, and passed on.
-
-# 4. TIMEOUT not tested. ping has a flag I don't know, and I'm suspicious
-# of the $1 in its args.
-
-# 5. Script refresh in 2017. The aliasing code was too convoluted and needs
-# to go away. Migrated DHCPv4 script to ip command from iproute2 suite.
-# This is based on Debian script with some tweaks. ifconfig is no longer
-# used. Everything is done using ip tool from ip-route2.
-
-# 'ip' just looks too weird. Also, we now have unit-tests! Those unit-tests
-# overwirte this line to use a fake ip-echo tool. It's also convenient
-# if your system holds ip tool in a non-standard location.
-ip=/sbin/ip
-
-# update /etc/resolv.conf based on received values
-# This updated version mostly follows Debian script by Andrew Pollock et al.
-make_resolv_conf() {
- local new_resolv_conf
-
- # DHCPv4
- if [ -n "$new_domain_search" ] || [ -n "$new_domain_name" ] ||
- [ -n "$new_domain_name_servers" ]; then
- new_resolv_conf=/etc/resolv.conf.dhclient-new
- rm -f $new_resolv_conf
-
- if [ -n "$new_domain_name" ]; then
- echo domain ${new_domain_name%% *} >>$new_resolv_conf
- fi
-
- if [ -n "$new_domain_search" ]; then
- if [ -n "$new_domain_name" ]; then
- domain_in_search_list=""
- for domain in $new_domain_search; do
- if [ "$domain" = "${new_domain_name}" ] ||
- [ "$domain" = "${new_domain_name}." ]; then
- domain_in_search_list="Yes"
- fi
- done
- if [ -z "$domain_in_search_list" ]; then
- new_domain_search="$new_domain_name $new_domain_search"
- fi
- fi
- echo "search ${new_domain_search}" >> $new_resolv_conf
- elif [ -n "$new_domain_name" ]; then
- echo "search ${new_domain_name}" >> $new_resolv_conf
- fi
-
- if [ -n "$new_domain_name_servers" ]; then
- for nameserver in $new_domain_name_servers; do
- echo nameserver $nameserver >>$new_resolv_conf
- done
- else # keep 'old' nameservers
- sed -n /^\w*[Nn][Aa][Mm][Ee][Ss][Ee][Rr][Vv][Ee][Rr]/p /etc/resolv.conf >>$new_resolv_conf
- fi
-
- if [ -f /etc/resolv.conf ]; then
- chown --reference=/etc/resolv.conf $new_resolv_conf
- chmod --reference=/etc/resolv.conf $new_resolv_conf
- fi
- mv -f $new_resolv_conf /etc/resolv.conf
- # DHCPv6
- elif [ -n "$new_dhcp6_domain_search" ] || [ -n "$new_dhcp6_name_servers" ]; then
- new_resolv_conf=/etc/resolv.conf.dhclient-new
- rm -f $new_resolv_conf
-
- if [ -n "$new_dhcp6_domain_search" ]; then
- echo "search ${new_dhcp6_domain_search}" >> $new_resolv_conf
- fi
-
- if [ -n "$new_dhcp6_name_servers" ]; then
- for nameserver in $new_dhcp6_name_servers; do
- # append %interface to link-local-address nameservers
- if [ "${nameserver##fe80::}" != "$nameserver" ] ||
- [ "${nameserver##FE80::}" != "$nameserver" ]; then
- nameserver="${nameserver}%${interface}"
- fi
- echo nameserver $nameserver >>$new_resolv_conf
- done
- else # keep 'old' nameservers
- sed -n /^\w*[Nn][Aa][Mm][Ee][Ss][Ee][Rr][Vv][Ee][Rr]/p /etc/resolv.conf >>$new_resolv_conf
- fi
-
- if [ -f /etc/resolv.conf ]; then
- chown --reference=/etc/resolv.conf $new_resolv_conf
- chmod --reference=/etc/resolv.conf $new_resolv_conf
- fi
- mv -f $new_resolv_conf /etc/resolv.conf
- fi
-}
-
-# set host name
-set_hostname() {
- local current_hostname
-
- if [ -n "$new_host_name" ]; then
- current_hostname=$(hostname)
-
- # current host name is empty, '(none)' or 'localhost' or differs from new one from DHCP
- if [ -z "$current_hostname" ] ||
- [ "$current_hostname" = '(none)' ] ||
- [ "$current_hostname" = 'localhost' ] ||
- [ "$current_hostname" = "$old_host_name" ]; then
- if [ "$new_host_name" != "$old_host_name" ]; then
- hostname "$new_host_name"
- fi
- fi
- fi
-}
-
-# run given script
-run_hook() {
- local script
- local exit_status
- script="$1"
-
- if [ -f $script ]; then
- . $script
- fi
-
- if [ -n "$exit_status" ] && [ "$exit_status" -ne 0 ]; then
- logger -p daemon.err "$script returned non-zero exit status $exit_status"
- fi
-
- return $exit_status
-}
-
-# run scripts in given directory
-run_hookdir() {
- local dir
- local exit_status
- dir="$1"
-
- if [ -d "$dir" ]; then
- for script in $(run-parts --list $dir); do
- run_hook $script || true
- exit_status=$?
- done
- fi
-
- return $exit_status
-}
-
-# Must be used on exit. Invokes the local dhcp client exit hooks, if any.
-exit_with_hooks() {
- exit_status=$1
-
- # Source the documented exit-hook script, if it exists
- if ! run_hook /etc/dhclient-exit-hooks; then
- exit_status=$?
- fi
-
- # Now run scripts in the Debian-specific directory.
- if ! run_hookdir /etc/dhclient-exit-hooks.d; then
- exit_status=$?
- fi
-
- exit $exit_status
-}
-
-# This function was largely borrowed from dhclient-script that
-# ships with Centos, authored by Jiri Popelka and David Cantrell
-# of Redhat. Thanks guys.
-add_ipv6_addr_with_DAD() {
- ${ip} -6 addr replace ${new_ip6_address}/${new_ip6_prefixlen} \
- dev ${interface} scope global valid_lft ${new_max_life} \
- preferred_lft ${new_preferred_life}
-
- if [ ${dad_wait_time} -le 0 ]
- then
- # if we're not waiting for DAD, assume we're good
- return 0
- fi
-
- # Repeatedly test whether newly added address passed
- # duplicate address detection (DAD)
- for i in $(seq 1 ${dad_wait_time}); do
- sleep 1 # give the DAD some time
-
- addr=$(${ip} -6 addr show dev ${interface} \
- | grep ${new_ip6_address}/${new_ip6_prefixlen})
-
- # tentative flag == DAD is still not complete
- tentative=$(echo "${addr}" | grep tentative)
- # dadfailed flag == address is already in use somewhere else
- dadfailed=$(echo "${addr}" | grep dadfailed)
-
- if [ -n "${dadfailed}" ] ; then
- # address was added with valid_lft/preferred_lft 'forever',
- # remove it
- ${ip} -6 addr del ${new_ip6_address}/${new_ip6_prefixlen} \
- dev ${interface}
-
- exit_with_hooks 3
- fi
-
- if [ -z "${tentative}" ] ; then
- if [ -n "${addr}" ]; then
- # DAD is over
- return 0
- else
- # address was auto-removed (or not added at all)
- exit_with_hooks 3
- fi
- fi
- done
-
- return 0
-}
-
-# Invoke the local dhcp client enter hooks, if they exist.
-run_hook /etc/dhclient-enter-hooks
-run_hookdir /etc/dhclient-enter-hooks.d
-
-# Execute the operation
-case "$reason" in
-
- ### DHCPv4 Handlers
-
- MEDIUM|ARPCHECK|ARPSEND)
- # Do nothing
- ;;
- PREINIT)
- # The DHCP client is requesting that an interface be
- # configured as required in order to send packets prior to
- # receiving an actual address. - dhclient-script(8)
-
- # ensure interface is up
- ${ip} link set dev ${interface} up
-
- if [ -n "$alias_ip_address" ]; then
- # flush alias IP from interface
- ${ip} -4 addr flush dev ${interface} label ${interface}:0
- fi
-
- ;;
-
- BOUND|RENEW|REBIND|REBOOT)
- set_hostname
-
- if [ -n "$old_ip_address" ] && [ -n "$alias_ip_address" ] &&
- [ "$alias_ip_address" != "$old_ip_address" ]; then
- # alias IP may have changed => flush it
- ${ip} -4 addr flush dev ${interface} label ${interface}:0
- fi
-
- if [ -n "$old_ip_address" ] &&
- [ "$old_ip_address" != "$new_ip_address" ]; then
- # leased IP has changed => flush it
- ${ip} -4 addr flush dev ${interface} label ${interface}
- fi
-
- if [ -z "$old_ip_address" ] ||
- [ "$old_ip_address" != "$new_ip_address" ] ||
- [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
- # new IP has been leased or leased IP changed => set it
- ${ip} -4 addr add ${new_ip_address}${new_subnet_mask:+/$new_subnet_mask} \
- ${new_broadcast_address:+broadcast $new_broadcast_address} \
- dev ${interface} label ${interface}
-
- if [ -n "$new_interface_mtu" ]; then
- # set MTU
- ${ip} link set dev ${interface} mtu ${new_interface_mtu}
- fi
-
- # if we have $new_rfc3442_classless_static_routes then we have to
- # ignore $new_routers entirely
- if [ ! "$new_rfc3442_classless_static_routes" ]; then
- # set if_metric if IF_METRIC is set or there's more than one router
- if_metric="$IF_METRIC"
- if [ "${new_routers%% *}" != "${new_routers}" ]; then
- if_metric=${if_metric:-1}
- fi
-
- for router in $new_routers; do
- if [ "$new_subnet_mask" = "255.255.255.255" ]; then
- # point-to-point connection => set explicit route
- ${ip} -4 route add ${router} dev $interface >/dev/null 2>&1
- fi
-
- # set default route
- ${ip} -4 route add default via ${router} dev ${interface} \
- ${if_metric:+metric $if_metric} >/dev/null 2>&1
-
- if [ -n "$if_metric" ]; then
- if_metric=$((if_metric+1))
- fi
- done
- fi
- fi
-
- if [ -n "$alias_ip_address" ] &&
- [ "$new_ip_address" != "$alias_ip_address" ]; then
- # separate alias IP given, which may have changed
- # => flush it, set it & add host route to it
- ${ip} -4 addr flush dev ${interface} label ${interface}:0
- ${ip} -4 addr add ${alias_ip_address}${alias_subnet_mask:+/$alias_subnet_mask} \
- dev ${interface} label ${interface}:0
- ${ip} -4 route add ${alias_ip_address} dev ${interface} >/dev/null 2>&1
- fi
-
- # update /etc/resolv.conf
- make_resolv_conf
-
- ;;
-
- EXPIRE|FAIL|RELEASE|STOP)
- if [ -n "$alias_ip_address" ]; then
- # flush alias IP
- ${ip} -4 addr flush dev ${interface} label ${interface}:0
- fi
-
- if [ -n "$old_ip_address" ]; then
- # flush leased IP
- ${ip} -4 addr flush dev ${interface} label ${interface}
- fi
-
- if [ -n "$alias_ip_address" ]; then
- # alias IP given => set it & add host route to it
- ${ip} -4 addr add ${alias_ip_address}${alias_subnet_mask:+/$alias_subnet_mask} \
- dev ${interface} label ${interface}:0
- ${ip} -4 route add ${alias_ip_address} dev ${interface} >/dev/null 2>&1
- fi
-
- ;;
-
- TIMEOUT)
- if [ -n "$alias_ip_address" ]; then
- # flush alias IP
- ${ip} -4 addr flush dev ${interface} label ${interface}:0
- fi
-
- # set IP from recorded lease
- ${ip} -4 addr add ${new_ip_address}${new_subnet_mask:+/$new_subnet_mask} \
- ${new_broadcast_address:+broadcast $new_broadcast_address} \
- dev ${interface} label ${interface}
-
- if [ -n "$new_interface_mtu" ]; then
- # set MTU
- ${ip} link set dev ${interface} mtu ${new_interface_mtu}
- fi
-
- # if there is no router recorded in the lease or the 1st router answers pings
- if [ -z "$new_routers" ] || ping -q -c 1 "${new_routers%% *}"; then
- # if we have $new_rfc3442_classless_static_routes then we have to
- # ignore $new_routers entirely
- if [ ! "$new_rfc3442_classless_static_routes" ]; then
- if [ -n "$alias_ip_address" ] &&
- [ "$new_ip_address" != "$alias_ip_address" ]; then
- # separate alias IP given => set up the alias IP & add host route to it
- ${ip} -4 addr add \
- ${alias_ip_address}${alias_subnet_mask:+/$alias_subnet_mask} \
- dev ${interface} label ${interface}:0
- ${ip} -4 route add ${alias_ip_address} dev ${interface} >/dev/null 2>&1
- fi
-
- # set if_metric if IF_METRIC is set or there's more than one router
- if_metric="$IF_METRIC"
- if [ "${new_routers%% *}" != "${new_routers}" ]; then
- if_metric=${if_metric:-1}
- fi
-
- # set default route
- for router in $new_routers; do
- ${ip} -4 route add default via ${router} dev ${interface} \
- ${if_metric:+metric $if_metric} >/dev/null 2>&1
-
- if [ -n "$if_metric" ]; then
- if_metric=$((if_metric+1))
- fi
- done
- fi
-
- # update /etc/resolv.conf
- make_resolv_conf
- else
- # flush all IPs from interface
- ip -4 addr flush dev ${interface}
- exit_with_hooks 2
- fi
-
- ;;
-
- V6ONLY)
- if [ -n "$old_ip_address" ]; then
- # flush leased IP
- ${ip} -4 addr flush dev ${interface} label ${interface}
- fi
-
- ;;
-
- ### DHCPv6 Handlers
- # TODO handle prefix change: ?based on ${old_ip6_prefix} and ${new_ip6_prefix}?
-
- PREINIT6)
- # ensure interface is up
- ${ip} link set ${interface} up
-
- # We need to give the kernel some time to active interface
- interface_up_wait_time=5
- for i in $(seq 0 ${interface_up_wait_time})
- do
- ${ip} link show dev ${interface} | grep -q LOWER_UP 2>&1
- if [ $? -eq 0 ]; then
- break;
- fi
- sleep 1
- done
-
- # flush any stale global permanent IPs from interface
- ${ip} -6 addr flush dev ${interface} scope global permanent
-
- # Wait for duplicate address detection for this interface if the
- # --dad-wait-time parameter has been specified and is greater than
- # zero.
- if [ ${dad_wait_time} -gt 0 ]; then
- # Check if any IPv6 address on this interface is marked as
- # tentative.
- ${ip} addr show ${interface} | grep inet6 | grep tentative \
- &> /dev/null
- if [ $? -eq 0 ]; then
- # Wait for duplicate address detection to complete or for
- # the timeout specified as --dad-wait-time.
- for i in $(seq 0 $dad_wait_time)
- do
- # We're going to poll for the tentative flag every second.
- sleep 1
- ${ip} addr show ${interface} | grep inet6 | grep tentative \
- &> /dev/null
- if [ $? -ne 0 ]; then
- break;
- fi
- done
- fi
- fi
-
- ;;
-
- BOUND6|RENEW6|REBIND6)
- if [ "${new_ip6_address}" ] && [ "${new_ip6_prefixlen}" ]; then
- # set leased IP
- add_ipv6_addr_with_DAD
- fi
-
- # update /etc/resolv.conf
- if [ "${reason}" = BOUND6 ] ||
- [ "${new_dhcp6_name_servers}" != "${old_dhcp6_name_servers}" ] ||
- [ "${new_dhcp6_domain_search}" != "${old_dhcp6_domain_search}" ]; then
- make_resolv_conf
- fi
-
- ;;
-
- DEPREF6)
- if [ -z "${cur_ip6_prefixlen}" ]; then
- exit_with_hooks 2
- fi
-
- # set preferred lifetime of leased IP to 0
- ${ip} -6 addr change ${cur_ip6_address}/${cur_ip6_prefixlen} \
- dev ${interface} scope global preferred_lft 0
-
- ;;
-
- EXPIRE6|RELEASE6|STOP6)
- if [ -z "${old_ip6_address}" ] || [ -z "${old_ip6_prefixlen}" ]; then
- exit_with_hooks 2
- fi
-
- # delete leased IP
- ${ip} -6 addr del ${old_ip6_address}/${old_ip6_prefixlen} \
- dev ${interface}
-
- ;;
-esac
-
-exit_with_hooks 0
diff --git a/client/scripts/macos b/client/scripts/macos
deleted file mode 100755
index 0164b1f0..00000000
--- a/client/scripts/macos
+++ /dev/null
@@ -1,288 +0,0 @@
-#!/bin/sh
-#
-# $Id: macos,v 1.4 2011/09/20 16:59:54 sar Exp $
-#
-# automous run of this script will commit the DNS setting
-#
-
-if [ -x /usr/bin/logger ]; then
- LOGGER="/usr/bin/logger -s -p user.notice -t dhclient"
-else
- LOGGER=echo
-fi
-
-to_commit="yes"
-
-make_resolv_conf() {
- to_commit="no"
- if [ "x${new_dhcp6_name_servers}" != x ]; then
- ( cat /dev/null > /var/run/resolv.conf.dhclient6 )
- exit_status=$?
- if [ $exit_status -ne 0 ]; then
- $LOGGER "Unable to create /var/run/resolv.conf.dhclient6: Error $exit_status"
- else
- if [ "x${new_dhcp6_domain_search}" != x ]; then
- ( echo search ${new_dhcp6_domain_search} >> /var/run/resolv.conf.dhclient6 )
- exit_status=$?
- fi
- for nameserver in ${new_dhcp6_name_servers} ; do
- if [ $exit_status -ne 0 ]; then
- break
- fi
- # If the nameserver has a link-local address
- # add a <zone_id> (interface name) to it.
- case $nameserver in
- fe80:*) zone_id="%$interface";;
- FE80:*) zone_id="%$interface";;
- *) zone_id="";;
- esac
- ( echo nameserver ${nameserver}$zone_id >> /etc/resolv.conf.dhclient6 )
- exit_status=$?
- done
-
- if [ $exit_status -eq 0 ]; then
- to_commit="force"
- commit_resolv_conf
- fi
- fi
- fi
-}
-
-# Try to commit /var/run/resolv.conf.dhclient6 contents to
-# System Configuration framework's Dynamic Store.
-# Note this will be cleared by the next location change
-# or preempted by IPv4.
-#
-# The System Configuration agent "IPMonitor" gets the DNS configuration
-# from the IPv4 or IPv6 primary service in the Dynamic Store
-# (managed by configd).
-commit_resolv_conf() {
- if [ -f /var/run/resolv.conf.dhclient6 ]; then
- if [ -x /usr/sbin/scutil ]; then
- serviceID=`echo show State:/Network/Global/IPv6 | \
- /usr/sbin/scutil | \
- awk '/PrimaryService/ { print $3 }'`
- echo $serviceID
- if [ x$serviceID = x ]; then
- $LOGGER "Can't find the primary IPv6 service"
- else
- tmp=`mktemp SC_dhclient6.XXXXXXXXXX`
- echo list | /usr/sbin/scutil > /tmp/$tmp
- grep -q State:/Network/Service/$serviceID/DNS /tmp/$tmp
- grep_status=$?
- if [ $grep_status -eq 0 ]; then
- $LOGGER "DNS service already set in primary IPv6 service"
- rm /tmp/$tmp
- else
- res=/var/run/resolv.conf.dhclient6
- cp /dev/null /tmp/$tmp
- grep -q '^nameserver' $res
- grep_status=$?
- if [ $grep_status -eq 0 ]; then
- echo d.add ServerAddresses '*' \
- `awk 'BEGIN { n="" } \
- /^nameserver/ { n=n " " $2 } \
- END { print n}' < $res` >> /tmp/$tmp
- fi
- grep -q '^search' $res
- grep_status=$?
- if [ $grep_status -eq 0 ]; then
- echo d.add SearchDomains '*' \
- `sed 's/^search//' < $res` >> /tmp/$tmp
- fi
- echo set State:/Network/Service/$serviceID/DNS >> /tmp/$tmp
- echo quit >> /tmp/$tmp
- cat /tmp/$tmp
- /usr/sbin/scutil < /tmp/$tmp
- rm /tmp/$tmp
- fi
- fi
- else
- $LOGGER "Can't find SystemConfiguration tools."
- fi
- else
- if [ $to_commit = force ]; then
- $LOGGER "Can't find /var/run/resolv.conf.dhclient6"
- fi
- fi
- to_commit="done"
-}
-
-# This function was largely borrowed from dhclient-script that
-# ships with Centos, authored by Jiri Popelka and David Cantrell
-# of Redhat. Thanks guys.
-add_ipv6_addr_with_DAD() {
- ifconfig ${interface} inet6 ${new_ip6_address}/${new_ip6_prefixlen} alias
-
- if [ ${dad_wait_time} -le 0 ]
- then
- # if we're not waiting for DAD, assume we're good
- return 0
- fi
-
- # Repeatedly test whether newly added address passed
- # duplicate address detection (DAD)
- for i in $(seq 1 ${dad_wait_time}); do
- sleep 1 # give the DAD some time
-
- addr=$(ifconfig ${interface} \
- | grep "${new_ip6_address} prefixlen ${new_ip6_prefixlen}")
-
- # tentative flag == DAD is still not complete
- tentative=$(echo "${addr}" | grep tentative)
- # dadfailed flag == address is already in use somewhere else
- dadfailed=$(echo "${addr}" | grep duplicated)
-
- if [ -n "${dadfailed}" ] ; then
- # dad failed, remove the address
- ifconfig ${interface} inet6 ${new_ip6_address}/${new_ip6_prefixlen} -alias
- exit_with_hooks 3
- fi
-
- if [ -z "${tentative}" ] ; then
- if [ -n "${addr}" ]; then
- # DAD is over
- return 0
- else
- # address was auto-removed (or not added at all)
- exit_with_hooks 3
- fi
- fi
- done
-
- return 0
-}
-
-# Must be used on exit. Invokes the local dhcp client exit hooks, if any.
-exit_with_hooks() {
- exit_status=$1
- if [ -f /etc/dhclient-exit-hooks ]; then
- . /etc/dhclient-exit-hooks
- fi
-# probably should do something with exit status of the local script
- exit $exit_status
-}
-
-# Invoke the local dhcp client enter hooks, if they exist.
-if [ -f /etc/dhclient-enter-hooks ]; then
- exit_status=0
- . /etc/dhclient-enter-hooks
- # allow the local script to abort processing of this state
- # local script must set exit_status variable to nonzero.
- if [ $exit_status -ne 0 ]; then
- exit $exit_status
- fi
-fi
-
-if [ x$reason = xMEDIUM ]; then
- eval "ifconfig $interface $medium"
- eval "ifconfig $interface inet -alias 0.0.0.0 $medium" >/dev/null 2>&1
- sleep 1
- exit_with_hooks 0
-fi
-
-###
-### DHCPv6 Handlers
-###
-
-if [ x$reason = xPREINIT6 ]; then
- # Ensure interface is up.
- ifconfig ${interface} up
-
- # We need to give the kernel some time to active interface
- interface_up_wait_time=5
- for i in $(seq 0 ${interface_up_wait_time})
- do
- ifconfig ${interface} | grep inactive &> /dev/null
- if [ $? -ne 0 ]; then
- break;
- fi
- sleep 1
- done
-
- # XXX: Remove any stale addresses from aborted clients.
-
- # Wait for duplicate address detection for this interface if the
- # --dad-wait-time parameter has been specified and is greater than
- # zero.
- if [ ${dad_wait_time} -gt 0 ]; then
- # Check if any IPv6 address on this interface is marked as
- # tentative.
- ifconfig ${interface} | grep inet6 | grep tentative \
- &> /dev/null
- if [ $? -eq 0 ]; then
- # Wait for duplicate address detection to complete or for
- # the timeout specified as --dad-wait-time.
- for i in $(seq 0 $dad_wait_time)
- do
- # We're going to poll for the tentative flag every second.
- sleep 1
- ifconfig ${interface} | grep inet6 | grep tentative \
- &> /dev/null
- if [ $? -ne 0 ]; then
- break;
- fi
- done
- fi
- fi
-
- exit_with_hooks 0
-fi
-
-if [ x${old_ip6_prefix} != x ] || [ x${new_ip6_prefix} != x ]; then
- echo Prefix $reason old=${old_ip6_prefix} new=${new_ip6_prefix}
-
- exit_with_hooks 0
-fi
-
-if [ x$reason = xBOUND6 ]; then
- if [ x${new_ip6_address} = x ] || [ x${new_ip6_prefixlen} = x ]; then
- exit_with_hooks 2;
- fi
-
- # Add address to interface, check for DAD if dad_wait_time > 0
- add_ipv6_addr_with_DAD
-
- # Check for nameserver options.
- make_resolv_conf
-
- exit_with_hooks 0
-fi
-
-if [ x$reason = xRENEW6 ] || [ x$reason = xREBIND6 ]; then
- # Make sure nothing has moved around on us.
-
- # Nameservers/domains/etc.
- if [ "x${new_dhcp6_name_servers}" != "x${old_dhcp6_name_servers}" ] ||
- [ "x${new_dhcp6_domain_search}" != "x${old_dhcp6_domain_search}" ]; then
- make_resolv_conf
- fi
-
- exit_with_hooks 0
-fi
-
-if [ x$reason = xDEPREF6 ]; then
- if [ x${new_ip6_address} = x ]; then
- exit_with_hooks 2;
- fi
-
- ifconfig ${interface} inet6 ${new_ip6_address} deprecated
-
- exit_with_hooks 0
-fi
-
-if [ x$reason = xEXPIRE6 -o x$reason = xRELEASE6 -o x$reason = xSTOP6 ]; then
- if [ x${old_ip6_address} = x ] || [ x${old_ip6_prefixlen} = x ]; then
- exit_with_hooks 2;
- fi
-
- ifconfig ${interface} inet6 ${old_ip6_address}/${old_ip6_prefixlen} -alias
-
- exit_with_hooks 0
-fi
-
-if [ $to_commit = yes ]; then
- commit_resolv_conf
-fi
-
-exit_with_hooks 0
diff --git a/client/scripts/netbsd b/client/scripts/netbsd
deleted file mode 100755
index fa086376..00000000
--- a/client/scripts/netbsd
+++ /dev/null
@@ -1,405 +0,0 @@
-#!/bin/sh
-
-make_resolv_conf() {
- if [ "x$new_domain_name" != x ] && [ x"$new_domain_name_servers" != x ]; then
- cat /dev/null > /etc/resolv.conf.dhclient
- if [ "x$new_domain_search" != x ]; then
- echo search $new_domain_search >> /etc/resolv.conf.dhclient
- elif [ "x$new_domain_name" != x ]; then
- # Note that the DHCP 'Domain Name Option' is really just a domain
- # name, and that this practice of using the domain name option as
- # a search path is both nonstandard and deprecated.
- echo search $new_domain_name >> /etc/resolv.conf.dhclient
- fi
- for nameserver in $new_domain_name_servers; do
- echo nameserver $nameserver >>/etc/resolv.conf.dhclient
- done
-
- mv /etc/resolv.conf.dhclient /etc/resolv.conf
- elif [ "x${new_dhcp6_name_servers}" != x ] ; then
- cat /dev/null > /etc/resolv.conf.dhclient6
- chmod 644 /etc/resolv.conf.dhclient6
-
- if [ "x${new_dhcp6_domain_search}" != x ] ; then
- echo search ${new_dhcp6_domain_search} >> /etc/resolv.conf.dhclient6
- fi
- for nameserver in ${new_dhcp6_name_servers} ; do
- # If the nameserver has a link-local address
- # add a <zone_id> (interface name) to it.
- case $nameserver in
- fe80:*) zone_id="%$interface";;
- FE80:*) zone_id="%$interface";;
- *) zone_id="";;
- esac
- echo nameserver ${nameserver}$zone_id >> /etc/resolv.conf.dhclient6
- done
-
- mv /etc/resolv.conf.dhclient6 /etc/resolv.conf
- fi
-}
-
-# Must be used on exit. Invokes the local dhcp client exit hooks, if any.
-exit_with_hooks() {
- exit_status=$1
- if [ -f /etc/dhclient-exit-hooks ]; then
- . /etc/dhclient-exit-hooks
- fi
-# probably should do something with exit status of the local script
- exit $exit_status
-}
-
-# This function was largely borrowed from dhclient-script that
-# ships with Centos, authored by Jiri Popelka and David Cantrell
-# of Redhat. Thanks guys.
-add_ipv6_addr_with_DAD() {
- ifconfig ${interface} inet6 ${new_ip6_address}/${new_ip6_prefixlen} alias
-
- if [ ${dad_wait_time} -le 0 ]
- then
- # if we're not waiting for DAD, assume we're good
- return 0
- fi
-
- # Repeatedly test whether newly added address passed
- # duplicate address detection (DAD)
- for i in $(seq 1 ${dad_wait_time}); do
- sleep 1 # give the DAD some time
-
- addr=$(ifconfig ${interface} \
- | grep "${new_ip6_address} prefixlen ${new_ip6_prefixlen}")
-
- # tentative flag == DAD is still not complete
- tentative=$(echo "${addr}" | grep tentative)
- # dadfailed flag == address is already in use somewhere else
- dadfailed=$(echo "${addr}" | grep duplicated)
-
- if [ -n "${dadfailed}" ] ; then
- # dad failed, remove the address
- ifconfig ${interface} inet6 ${new_ip6_address}/${new_ip6_prefixlen} -alias
- exit_with_hooks 3
- fi
-
- if [ -z "${tentative}" ] ; then
- if [ -n "${addr}" ]; then
- # DAD is over
- return 0
- else
- # address was auto-removed (or not added at all)
- exit_with_hooks 3
- fi
- fi
- done
-
- return 0
-}
-
-# Invoke the local dhcp client enter hooks, if they exist.
-if [ -f /etc/dhclient-enter-hooks ]; then
- exit_status=0
- . /etc/dhclient-enter-hooks
- # allow the local script to abort processing of this state
- # local script must set exit_status variable to nonzero.
- if [ $exit_status -ne 0 ]; then
- exit $exit_status
- fi
-fi
-
-if [ x$new_network_number != x ]; then
- echo New Network Number: $new_network_number
-fi
-
-if [ x$new_broadcast_address != x ]; then
- echo New Broadcast Address: $new_broadcast_address
- new_broadcast_arg="broadcast $new_broadcast_address"
-fi
-if [ x$old_broadcast_address != x ]; then
- old_broadcast_arg="broadcast $old_broadcast_address"
-fi
-if [ x$new_subnet_mask != x ]; then
- new_netmask_arg="netmask $new_subnet_mask"
-fi
-if [ x$old_subnet_mask != x ]; then
- old_netmask_arg="netmask $old_subnet_mask"
-fi
-if [ x$alias_subnet_mask != x ]; then
- alias_subnet_arg="netmask $alias_subnet_mask"
-fi
- if [ x$new_interface_mtu != x ]; then
- mtu_arg="mtu $new_interface_mtu"
- fi
-if [ x$IF_METRIC != x ]; then
- metric_arg="metric $IF_METRIC"
-fi
-
-if [ x$reason = xMEDIUM ]; then
- eval "ifconfig $interface $medium"
- eval "ifconfig $interface inet -alias 0.0.0.0 $medium" >/dev/null 2>&1
- sleep 1
- exit_with_hooks 0
-fi
-
-###
-### DHCPv4 Handlers
-###
-
-if [ x$reason = xPREINIT ]; then
- if [ x$alias_ip_address != x ]; then
- ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
- fi
- ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 \
- broadcast 255.255.255.255 up
- exit_with_hooks 0
-fi
-
-if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then
- exit_with_hooks 0
-fi
-
-if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \
- [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then
- current_hostname=`hostname`
- if [ x$current_hostname = x ] || \
- [ x$current_hostname = x$old_host_name ]; then
- if [ x$current_hostname = x ] || \
- [ x$new_host_name != x$old_host_name ]; then
- hostname $new_host_name
- fi
- fi
-
- if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \
- [ x$alias_ip_address != x$old_ip_address ]; then
- ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
- fi
- if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]
- then
- eval "ifconfig $interface inet -alias $old_ip_address $medium"
- route delete $old_ip_address 127.1 >/dev/null 2>&1
- for router in $old_routers; do
- route delete default $router >/dev/null 2>&1
- done
- if [ "$old_static_routes" != "" ]; then
- set $old_static_routes
- while [ $# -gt 1 ]; do
- route delete $1 $2
- shift; shift
- done
- fi
- arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' |sh
- fi
- if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \
- [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then
- eval "ifconfig $interface inet $new_ip_address $new_netmask_arg \
- $new_broadcast_arg $mtu_arg $metric_arg $medium"
- route add $new_ip_address 127.1 >/dev/null 2>&1
- for router in $new_routers; do
- route add default $router >/dev/null 2>&1
- done
- if [ "$new_static_routes" != "" ]; then
- set $new_static_routes
- while [ $# -gt 1 ]; do
- route add $1 $2
- shift; shift
- done
- fi
- else
- # we haven't changed the address, have we changed other options
- # that we wish to update?
- if [ x$new_routers != x ] && [ x$new_routers != x$old_routers ] ; then
- # if we've changed routers delete the old and add the new.
- $LOGGER "New Routers: $new_routers"
- for router in $old_routers; do
- route delete default $router >/dev/null 2>&1
- done
- for router in $new_routers; do
- route add default $router >/dev/null 2>&1
- done
- fi
- fi
- if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ];
- then
- ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg
- route add $alias_ip_address 127.0.0.1
- fi
- make_resolv_conf
- exit_with_hooks 0
-fi
-
-if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ] || [ x$reason = xRELEASE ] \
- || [ x$reason = xSTOP ]; then
- if [ x$alias_ip_address != x ]; then
- ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
- fi
- if [ x$old_ip_address != x ]; then
- eval "ifconfig $interface inet -alias $old_ip_address $medium"
- route delete $old_ip_address 127.1 >/dev/null 2>&1
- for router in $old_routers; do
- route delete default $router >/dev/null 2>&1
- done
- if [ "$old_static_routes" != "" ]; then
- set $old_static_routes
- while [ $# -gt 1 ]; do
- route delete $1 $2
- shift; shift
- done
- fi
- arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' \
- |sh >/dev/null 2>&1
- fi
- if [ x$alias_ip_address != x ]; then
- ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg
- route add $alias_ip_address 127.0.0.1
- fi
- exit_with_hooks 0
-fi
-
-if [ x$reason = xTIMEOUT ]; then
- if [ x$alias_ip_address != x ]; then
- ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
- fi
- eval "ifconfig $interface inet $new_ip_address $new_netmask_arg \
- $new_broadcast_arg $mtu_arg $metric_arg $medium"
- sleep 1
- if [ "$new_routers" != "" ]; then
- set $new_routers
- if ping -q -c 1 -w 1 $1; then
- if [ x$new_ip_address != x$alias_ip_address ] && \
- [ x$alias_ip_address != x ]; then
- ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg
- route add $alias_ip_address 127.0.0.1
- fi
- route add $new_ip_address 127.1 >/dev/null 2>&1
- for router in $new_routers; do
- route add default $router >/dev/null 2>&1
- done
- set $new_static_routes
- while [ $# -gt 1 ]; do
- route add $0 $1
- shift; shift
- done
- make_resolv_conf
- exit_with_hooks 0
- fi
- fi
- eval "ifconfig $interface inet -alias $new_ip_address $medium"
- for router in $old_routers; do
- route delete default $router >/dev/null 2>&1
- done
- if [ "$old_static_routes" != "" ]; then
- set $old_static_routes
- while [ $# -gt 1 ]; do
- route delete $1 $2
- shift; shift
- done
- fi
- arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' \
- |sh >/dev/null 2>&1
- exit_with_hooks 1
-fi
-
-###
-### DHCPv6 Handlers
-###
-
-if [ ${reason} = PREINIT6 ] ; then
- # Ensure interface is up.
- ifconfig ${interface} up
-
- # XXX: Remove any stale addresses from aborted clients.
-
- # We need to give the kernel some time to active interface
- interface_up_wait_time=5
- for i in $(seq 0 ${interface_up_wait_time})
- do
- ifconfig ${interface} | grep inactive >/dev/null 2>&1
- if [ $? -ne 0 ]; then
- break;
- fi
- sleep 1
- done
-
- # Wait for duplicate address detection for this interface if the
- # --dad-wait-time parameter has been specified and is greater than
- # zero.
- if [ ${dad_wait_time} -gt 0 ]; then
- # Check if any IPv6 address on this interface is marked as
- # tentative.
- ifconfig ${interface} | grep inet6 | grep tentative \
- >/dev/null 2>&1
- if [ $? -eq 0 ]; then
- # Wait for duplicate address detection to complete or for
- # the timeout specified as --dad-wait-time.
- for i in $(seq 0 $dad_wait_time)
- do
- # We're going to poll for the tentative flag every second.
- sleep 1
- ifconfig ${interface} | grep inet6 | grep tentative \
- >/dev/null 2>&1
- if [ $? -ne 0 ]; then
- break;
- fi
- done
- fi
- fi
-
- exit_with_hooks 0
-fi
-
-if [ x${old_ip6_prefix} != x ] || [ x${new_ip6_prefix} != x ] ; then
- echo Prefix ${reason} old=${old_ip6_prefix} new=${new_ip6_prefix}
-
- exit_with_hooks 0
-fi
-
-if [ ${reason} = BOUND6 ] ; then
- if [ x${new_ip6_address} = x ] || [ x${new_ip6_prefixlen} = x ] ; then
- exit_with_hooks 2;
- fi
-
- # Add address to interface, check for DAD if dad_wait_time > 0
- add_ipv6_addr_with_DAD
-
- # Check for nameserver options.
- make_resolv_conf
-
- exit_with_hooks 0
-fi
-
-if [ ${reason} = RENEW6 ] || [ ${reason} = REBIND6 ] ; then
- # Make sure nothing has moved around on us.
-
- # Nameservers/domains/etc.
- if [ "x${new_dhcp6_name_servers}" != "x${old_dhcp6_name_servers}" ] ||
- [ "x${new_dhcp6_domain_search}" != "x${old_dhcp6_domain_search}" ] ; then
- make_resolv_conf
- fi
-
- exit_with_hooks 0
-fi
-
-if [ ${reason} = DEPREF6 ] ; then
- if [ x${new_ip6_prefixlen} = x ] ; then
- exit_with_hooks 2;
- fi
-
- # XXX:
- # There doesn't appear to be a way to update an addr to indicate
- # preference.
-
- exit_with_hooks 0
-fi
-
-if [ ${reason} = EXPIRE6 -o ${reason} = RELEASE6 -o ${reason} = STOP6 ] ; then
- if [ x${old_ip6_address} = x ] || [ x${old_ip6_prefixlen} = x ] ; then
- exit_with_hooks 2;
- fi
-
- ifconfig ${interface} inet6 -alias ${old_ip6_address}/${old_ip6_prefixlen}
-
- exit_with_hooks 0
-fi
-
-exit_with_hooks 0
diff --git a/client/scripts/nextstep b/client/scripts/nextstep
deleted file mode 100644
index 9273c5a7..00000000
--- a/client/scripts/nextstep
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/bin/sh
-#
-# simplified dhclient-script for NeXTSTEP/OPENSTEP
-#
-# removed a lot of the cruft from the netbsd version since NeXTSTEP doesn't
-# support aliases and lots of things were breaking for no good reason
-#
-# 14 Sep 1997, David W. Young
-#
-if [ x$reason = xPREINIT ]; then
- ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 up >/dev/null 2>&1
- exit 0
-fi
-if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \
- [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then
- current_hostname=`hostname`
- if [ x$current_hostname = x ] || \
- [ x$current_hostname = x$old_host_name ]; then
- if [ x$current_hostname = x ] || \
- [ x$new_host_name != x$old_host_name ]; then
- hostname $new_host_name
- fi
- fi
-
- if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]
- then
- ifconfig $interface $new_ip_address netmask $new_subnet_mask \
- >/dev/null 2>&1
- route add $new_ip_address 127.1 0 >/dev/null 2>&1
- for router in $new_routers ; do
- route add default $router 1 >/dev/null 2>&1
- done
- fi
- if [ x"$new_domain_name_servers" != x ]; then
- cat /dev/null > /etc/resolv.conf.dhclient
- if [ "x$new_domain_search" != x ]; then
- echo search $new_domain_search >> /etc/resolv.conf.dhclient
- elif [ "x$new_domain_name" != x ]; then
- # Note that the DHCP 'Domain Name Option' is really just a domain
- # name, and that this practice of using the domain name option as
- # a search path is both nonstandard and deprecated.
- echo search $new_domain_name >> /etc/resolv.conf.dhclient
- fi
- for nameserver in $new_domain_name_servers; do
- echo nameserver $nameserver >>/etc/resolv.conf.dhclient
- done
-
- mv /etc/resolv.conf.dhclient /etc/resolv.conf
- fi
- exit 0
-fi
-if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ] || [ x$reason = xRELEASE ] \
- || [ x$reason = xSTOP ]; then
- if [ x$old_ip_address != x ]; then
- route delete $old_ip_address 127.1 >/dev/null 2>&1
- for $router in $old_routers ; do
- route delete default $router >/dev/null 2>&1
- done
- fi
- exit 0
-fi
diff --git a/client/scripts/openbsd b/client/scripts/openbsd
deleted file mode 100755
index afb79241..00000000
--- a/client/scripts/openbsd
+++ /dev/null
@@ -1,403 +0,0 @@
-#!/bin/sh
-
-make_resolv_conf() {
- if [ x"$new_domain_name_servers" != x ]; then
- cat /dev/null > /etc/resolv.conf.dhclient
- if [ x"$new_domain_search" != x ]; then
- echo search $new_domain_search >> /etc/resolv.conf.dhclient
- elif [ x"$new_domain_name" != x ]; then
- # Note that the DHCP 'Domain Name Option' is really just a domain
- # name, and that this practice of using the domain name option as
- # a search path is both nonstandard and deprecated.
- echo search $new_domain_name >> /etc/resolv.conf.dhclient
- fi
- for nameserver in $new_domain_name_servers; do
- echo nameserver $nameserver >>/etc/resolv.conf.dhclient
- done
-
- mv /etc/resolv.conf.dhclient /etc/resolv.conf
- elif [ "x${new_dhcp6_name_servers}" != x ] ; then
- cat /dev/null > /etc/resolv.conf.dhclient6
- chmod 644 /etc/resolv.conf.dhclient6
-
- if [ "x${new_dhcp6_domain_search}" != x ] ; then
- echo search ${new_dhcp6_domain_search} >> /etc/resolv.conf.dhclient6
- fi
- for nameserver in ${new_dhcp6_name_servers} ; do
- # If the nameserver has a link-local address
- # add a <zone_id> (interface name) to it.
- case $nameserver in
- fe80:*) zone_id="%$interface";;
- FE80:*) zone_id="%$interface";;
- *) zone_id="";;
- esac
- echo nameserver ${nameserver}$zone_id >> /etc/resolv.conf.dhclient6
- done
-
- mv /etc/resolv.conf.dhclient6 /etc/resolv.conf
- fi
-}
-
-# Must be used on exit. Invokes the local dhcp client exit hooks, if any.
-exit_with_hooks() {
- exit_status=$1
- if [ -f /etc/dhclient-exit-hooks ]; then
- . /etc/dhclient-exit-hooks
- fi
-# probably should do something with exit status of the local script
- exit $exit_status
-}
-
-# This function was largely borrowed from dhclient-script that
-# ships with Centos, authored by Jiri Popelka and David Cantrell
-# of Redhat. Thanks guys.
-add_ipv6_addr_with_DAD() {
- ifconfig ${interface} inet6 ${new_ip6_address}/${new_ip6_prefixlen} alias
-
- if [ ${dad_wait_time} -le 0 ]
- then
- # if we're not waiting for DAD, assume we're good
- return 0
- fi
-
- # Repeatedly test whether newly added address passed
- # duplicate address detection (DAD)
- i=0
- while [ $i -lt ${dad_wait_time} ]; do
- sleep 1 # give the DAD some time
-
- addr=$(ifconfig ${interface} \
- | grep "${new_ip6_address} prefixlen ${new_ip6_prefixlen}")
-
- # tentative flag == DAD is still not complete
- tentative=$(echo "${addr}" | grep tentative)
- # dadfailed flag == address is already in use somewhere else
- dadfailed=$(echo "${addr}" | grep duplicated)
-
- if [ -n "${dadfailed}" ] ; then
- # dad failed, remove the address
- ifconfig ${interface} inet6 ${new_ip6_address}/${new_ip6_prefixlen} -alias
- exit_with_hooks 3
- fi
-
- if [ -z "${tentative}" ] ; then
- if [ -n "${addr}" ]; then
- # DAD is over
- return 0
- else
- # address was auto-removed (or not added at all)
- exit_with_hooks 3
- fi
- fi
- true $(( i++ ))
- done
-
- return 0
-}
-
-# Invoke the local dhcp client enter hooks, if they exist.
-if [ -f /etc/dhclient-enter-hooks ]; then
- exit_status=0
- . /etc/dhclient-enter-hooks
- # allow the local script to abort processing of this state
- # local script must set exit_status variable to nonzero.
- if [ $exit_status -ne 0 ]; then
- exit $exit_status
- fi
-fi
-
-if [ x$new_network_number != x ]; then
- echo New Network Number: $new_network_number
-fi
-
-if [ x$new_broadcast_address != x ]; then
- echo New Broadcast Address: $new_broadcast_address
- new_broadcast_arg="broadcast $new_broadcast_address"
-fi
-if [ x$old_broadcast_address != x ]; then
- old_broadcast_arg="broadcast $old_broadcast_address"
-fi
-if [ x$new_subnet_mask != x ]; then
- new_netmask_arg="netmask $new_subnet_mask"
-fi
-if [ x$old_subnet_mask != x ]; then
- old_netmask_arg="netmask $old_subnet_mask"
-fi
-if [ x$alias_subnet_mask != x ]; then
- alias_subnet_arg="netmask $alias_subnet_mask"
-fi
-
-if [ x$reason = xMEDIUM ]; then
- eval "ifconfig $interface $medium"
- eval "ifconfig $interface inet -alias 0.0.0.0 $medium" >/dev/null 2>&1
- sleep 1
- exit_with_hooks 0
-fi
-
-###
-### DHCPv4 Handlers
-###
-
-if [ x$reason = xPREINIT ]; then
- if [ x$alias_ip_address != x ]; then
- ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
- fi
- ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 \
- broadcast 255.255.255.255 up
- exit_with_hooks 0
-fi
-
-if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then
- exit_with_hooks 0;
-fi
-
-if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \
- [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then
- current_hostname=`hostname`
- if [ x$current_hostname = x ] || \
- [ x$current_hostname = x$old_host_name ]; then
- if [ x$current_hostname = x ] || \
- [ x$new_host_name != x$old_host_name ]; then
- hostname $new_host_name
- fi
- fi
-
- if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \
- [ x$alias_ip_address != x$old_ip_address ]; then
- ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
- fi
- if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]
- then
- eval "ifconfig $interface inet -alias $old_ip_address $medium"
- route delete $old_ip_address 127.1 >/dev/null 2>&1
- for router in $old_routers; do
- route delete default $router >/dev/null 2>&1
- done
- if [ "$old_static_routes" != "" ]; then
- set $old_static_routes
- while [ $# -gt 1 ]; do
- route delete $1 $2
- shift; shift
- done
- fi
- arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' |sh
- fi
- if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \
- [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then
- eval "ifconfig $interface inet $new_ip_address $new_netmask_arg \
- $new_broadcast_arg $medium"
- route add $new_ip_address 127.1 >/dev/null 2>&1
- for router in $new_routers; do
- route add default $router >/dev/null 2>&1
- done
- if [ "$new_static_routes" != "" ]; then
- set $new_static_routes
- while [ $# -gt 1 ]; do
- route add $1 $2
- shift; shift
- done
- fi
- else
- # we haven't changed the address, have we changed other options
- # that we wish to update?
- if [ x$new_routers != x ] && [ x$new_routers != x$old_routers ] ; then
- # if we've changed routers delete the old and add the new.
- $LOGGER "New Routers: $new_routers"
- for router in $old_routers; do
- route delete default $router >/dev/null 2>&1
- done
- for router in $new_routers; do
- route add default $router >/dev/null 2>&1
- done
- fi
- fi
- if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ];
- then
- ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg
- route add $alias_ip_address 127.0.0.1
- fi
- make_resolv_conf
- exit_with_hooks 0
-fi
-
-if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ] || [ x$reason = xRELEASE ] \
- || [ x$reason = xSTOP ]; then
- if [ x$alias_ip_address != x ]; then
- ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
- fi
- if [ x$old_ip_address != x ]; then
- eval "ifconfig $interface inet -alias $old_ip_address $medium"
- route delete $old_ip_address 127.1 >/dev/null 2>&1
- for router in $old_routers; do
- route delete default $router >/dev/null 2>&1
- done
- if [ "$old_static_routes" != "" ]; then
- set $old_static_routes
- while [ $# -gt 1 ]; do
- route delete $1 $2
- shift; shift
- done
- fi
- arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' \
- |sh >/dev/null 2>&1
- fi
- if [ x$alias_ip_address != x ]; then
- ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg
- route add $alias_ip_address 127.0.0.1
- fi
- exit_with_hooks 0
-fi
-
-if [ x$reason = xTIMEOUT ]; then
- if [ x$alias_ip_address != x ]; then
- ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
- fi
- eval "ifconfig $interface inet $new_ip_address $new_netmask_arg \
- $new_broadcast_arg $medium"
- sleep 1
- if [ "$new_routers" != "" ]; then
- set $new_routers
- if ping -q -c 1 -w 1 $1; then
- if [ x$new_ip_address != x$alias_ip_address ] && \
- [ x$alias_ip_address != x ]; then
- ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg
- route add $alias_ip_address 127.0.0.1
- fi
- route add $new_ip_address 127.1 >/dev/null 2>&1
- for router in $new_routers; do
- route add default $router >/dev/null 2>&1
- done
- set $new_static_routes
- while [ $# -gt 1 ]; do
- route add $0 $1
- shift; shift
- done
- make_resolv_conf
- exit_with_hooks 0
- fi
- fi
- eval "ifconfig $interface inet -alias $new_ip_address $medium"
- for router in $old_routers; do
- route delete default $router >/dev/null 2>&1
- done
- if [ "$old_static_routes" != "" ]; then
- set $old_static_routes
- while [ $# -gt 1 ]; do
- route delete $1 $2
- shift; shift
- done
- fi
- arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' \
- |sh >/dev/null 2>&1
- exit_with_hooks 1
-fi
-
-###
-### DHCPv6 Handlers
-###
-
-if [ ${reason} = PREINIT6 ] ; then
- # Ensure interface is up.
- ifconfig ${interface} up
-
- # XXX: Remove any stale addresses from aborted clients.
-
- # We need to give the kernel some time to active interface
- interface_up_wait_time=5
- i=0
- while [ $i -lt ${interface_up_wait_time} ]; do
- ifconfig ${interface} | grep inactive >/dev/null 2>&1
- if [ $? -ne 0 ]; then
- break;
- fi
- sleep 1
- true $(( i++ ))
- done
-
- # Wait for duplicate address detection for this interface if the
- # --dad-wait-time parameter has been specified and is greater than
- # zero.
- if [ ${dad_wait_time} -gt 0 ]; then
- # Check if any IPv6 address on this interface is marked as
- # tentative.
- ifconfig ${interface} | grep inet6 | grep tentative \
- >/dev/null 2>&1
- if [ $? -eq 0 ]; then
- # Wait for duplicate address detection to complete or for
- # the timeout specified as --dad-wait-time.
- i=0
- while [ $i -lt ${dad_wait_time} ]; do
- # We're going to poll for the tentative flag every second.
- sleep 1
- ifconfig ${interface} | grep inet6 | grep tentative \
- >/dev/null 2>&1
- if [ $? -ne 0 ]; then
- break;
- fi
- true $(( i++ ))
- done
- fi
- fi
-
- exit_with_hooks 0
-fi
-
-if [ x${old_ip6_prefix} != x ] || [ x${new_ip6_prefix} != x ] ; then
- echo Prefix ${reason} old=${old_ip6_prefix} new=${new_ip6_prefix}
-
- exit_with_hooks 0
-fi
-
-if [ ${reason} = BOUND6 ] ; then
- if [ x${new_ip6_address} = x ] || [ x${new_ip6_prefixlen} = x ] ; then
- exit_with_hooks 2;
- fi
-
- # Add address to interface, check for DAD if dad_wait_time > 0
- add_ipv6_addr_with_DAD
-
- # Check for nameserver options.
- make_resolv_conf
-
- exit_with_hooks 0
-fi
-
-if [ ${reason} = RENEW6 ] || [ ${reason} = REBIND6 ] ; then
- # Make sure nothing has moved around on us.
-
- # Nameservers/domains/etc.
- if [ "x${new_dhcp6_name_servers}" != "x${old_dhcp6_name_servers}" ] ||
- [ "x${new_dhcp6_domain_search}" != "x${old_dhcp6_domain_search}" ] ; then
- make_resolv_conf
- fi
-
- exit_with_hooks 0
-fi
-
-if [ ${reason} = DEPREF6 ] ; then
- if [ x${new_ip6_prefixlen} = x ] ; then
- exit_with_hooks 2;
- fi
-
- # XXX:
- # There doesn't appear to be a way to update an addr to indicate
- # preference.
-
- exit_with_hooks 0
-fi
-
-if [ ${reason} = EXPIRE6 -o ${reason} = RELEASE6 -o ${reason} = STOP6 ] ; then
- if [ x${old_ip6_address} = x ] || [ x${old_ip6_prefixlen} = x ] ; then
- exit_with_hooks 2;
- fi
-
- ifconfig ${interface} inet6 -alias ${old_ip6_address}/${old_ip6_prefixlen}
-
- exit_with_hooks 0
-fi
-
-exit_with_hooks 0
diff --git a/client/scripts/openwrt b/client/scripts/openwrt
deleted file mode 100755
index 55a4aa96..00000000
--- a/client/scripts/openwrt
+++ /dev/null
@@ -1,285 +0,0 @@
-#!/bin/sh
-
-# 'ip' just looks too weird. /sbin/ip looks less weird.
-ip=/usr/sbin/ip
-
-make_resolv_conf() {
- if [ x"$new_domain_name_servers" != x ]; then
- cat /dev/null > /etc/resolv.conf.dhclient
- chmod 644 /etc/resolv.conf.dhclient
- if [ x"$new_domain_search" != x ]; then
- echo search $new_domain_search >> /etc/resolv.conf.dhclient
- elif [ x"$new_domain_name" != x ]; then
- # Note that the DHCP 'Domain Name Option' is really just a domain
- # name, and that this practice of using the domain name option as
- # a search path is both nonstandard and deprecated.
- echo search $new_domain_name >> /etc/resolv.conf.dhclient
- fi
- for nameserver in $new_domain_name_servers; do
- echo nameserver $nameserver >>/etc/resolv.conf.dhclient
- done
-
- mv /etc/resolv.conf.dhclient /etc/resolv.conf
- elif [ "x${new_dhcp6_name_servers}" != x ] ; then
- cat /dev/null > /etc/resolv.conf.dhclient6
- chmod 644 /etc/resolv.conf.dhclient6
-
- if [ "x${new_dhcp6_domain_search}" != x ] ; then
- echo search ${new_dhcp6_domain_search} >> /etc/resolv.conf.dhclient6
- fi
- for nameserver in ${new_dhcp6_name_servers} ; do
- # If the nameserver has a link-local address
- # add a <zone_id> (interface name) to it.
- case $nameserver in
- fe80:*) zone_id="%$interface";;
- FE80:*) zone_id="%$interface";;
- *) zone_id="";;
- esac
- echo nameserver ${nameserver}$zone_id >> /etc/resolv.conf.dhclient6
- done
-
- mv /etc/resolv.conf.dhclient6 /etc/resolv.conf
- fi
-}
-
-# Must be used on exit. Invokes the local dhcp client exit hooks, if any.
-exit_with_hooks() {
- exit_status=$1
- if [ -f /etc/dhclient-exit-hooks ]; then
- . /etc/dhclient-exit-hooks
- fi
-# probably should do something with exit status of the local script
- exit $exit_status
-}
-
-# Invoke the local dhcp client enter hooks, if they exist.
-if [ -f /etc/dhclient-enter-hooks ]; then
- exit_status=0
- . /etc/dhclient-enter-hooks
- # allow the local script to abort processing of this state
- # local script must set exit_status variable to nonzero.
- if [ $exit_status -ne 0 ]; then
- exit $exit_status
- fi
-fi
-
-###
-### DHCPv4 Handlers
-###
-
-if [ x$new_broadcast_address != x ]; then
- new_broadcast_arg="broadcast $new_broadcast_address"
-fi
-if [ x$new_subnet_mask != x ]; then
- new_subnet_arg="netmask $new_subnet_mask"
-fi
-if [ x$alias_subnet_mask != x ]; then
- alias_subnet_arg="netmask $alias_subnet_mask"
-fi
-if [ x$new_interface_mtu != x ]; then
- mtu_arg="mtu $new_interface_mtu"
-fi
-if [ x$IF_METRIC != x ]; then
- metric_arg="metric $IF_METRIC"
-fi
-
-if [ x$reason = xMEDIUM ]; then
- # Linux doesn't do mediums (ok, ok, media).
- exit_with_hooks 0
-fi
-
-if [ x$reason = xPREINIT ]; then
- if [ x$alias_ip_address != x ]; then
- # Bring down alias interface. Its routes will disappear too.
- ifconfig $interface:0- 0.0.0.0
- fi
- ifconfig $interface 0.0.0.0 up
-
- # We need to give the kernel some time to get the interface up.
- sleep 1
-
- exit_with_hooks 0
-fi
-
-if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then
- exit_with_hooks 0
-fi
-
-if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \
- [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then
- current_hostname=`hostname`
- if [ x$current_hostname = x ] || \
- [ x$current_hostname = x$old_host_name ]; then
- if [ x$current_hostname = x ] || \
- [ x$new_host_name != x$old_host_name ]; then
- hostname $new_host_name
- fi
- fi
-
- if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \
- [ x$alias_ip_address != x$old_ip_address ]; then
- # Possible new alias. Remove old alias.
- ifconfig $interface:0- 0.0.0.0
- fi
- if [ x$old_ip_address != x ] && \
- [ x$old_ip_address != x$new_ip_address ]; then
- # IP address changed. Bringing down the interface will delete all routes,
- # and clear the ARP cache.
- ifconfig $interface 0.0.0.0 down
-
- fi
- if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \
- [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then
-
- ifconfig $interface $new_ip_address $new_subnet_arg \
- $new_broadcast_arg $mtu_arg
- for router in $new_routers; do
- if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then
- route add -host $router dev $interface
- fi
- route add default gw $router $metric_arg dev $interface
- done
- else
- # we haven't changed the address, have we changed other options
- # that we wish to update?
- if [ x$new_routers != x ] && [ x$new_routers != x$old_routers ] ; then
- # if we've changed routers delete the old and add the new.
- $LOGGER "New Routers: $new_routers"
- for router in $old_routers; do
- route del default gw $router
- done
- for router in $new_routers; do
- if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then
- route add -host $router dev $interface
- fi
- route add default gw $router $metric_arg dev $interface
- done
- fi
- fi
- if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ];
- then
- ifconfig $interface:0- 0.0.0.0
- ifconfig $interface:0 $alias_ip_address $alias_subnet_arg
- route add -host $alias_ip_address $interface:0
- fi
- make_resolv_conf
- exit_with_hooks 0
-fi
-
-if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ] || [ x$reason = xRELEASE ] \
- || [ x$reason = xSTOP ]; then
- if [ x$alias_ip_address != x ]; then
- # Turn off alias interface.
- ifconfig $interface:0- 0.0.0.0
- fi
- if [ x$old_ip_address != x ]; then
- # Shut down interface, which will delete routes and clear arp cache.
- ifconfig $interface 0.0.0.0 down
- fi
- if [ x$alias_ip_address != x ]; then
- ifconfig $interface:0 $alias_ip_address $alias_subnet_arg
- route add -host $alias_ip_address $interface:0
- fi
- exit_with_hooks 0
-fi
-
-if [ x$reason = xTIMEOUT ]; then
- if [ x$alias_ip_address != x ]; then
- ifconfig $interface:0- 0.0.0.0
- fi
- ifconfig $interface $new_ip_address $new_subnet_arg \
- $new_broadcast_arg $mtu_arg
- set $new_routers
- if ping -q -c 1 $1; then
- if [ x$new_ip_address != x$alias_ip_address ] && \
- [ x$alias_ip_address != x ]; then
- ifconfig $interface:0 $alias_ip_address $alias_subnet_arg
- route add -host $alias_ip_address dev $interface:0
- fi
- for router in $new_routers; do
- if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then
- route add -host $router dev $interface
- fi
- route add default gw $router $metric_arg dev $interface
- done
- make_resolv_conf
- exit_with_hooks 0
- fi
- ifconfig $interface 0.0.0.0 down
- exit_with_hooks 1
-fi
-
-###
-### DHCPv6 Handlers
-###
-
-if [ x$reason = xPREINIT6 ]; then
- # Ensure interface is up.
- ${ip} link set ${interface} up
-
- # Remove any stale addresses from aborted clients.
- ${ip} -f inet6 addr flush dev ${interface} scope global permanent
-
- exit_with_hooks 0
-fi
-
-if [ x${old_ip6_prefix} != x ] || [ x${new_ip6_prefix} != x ] ; then
- echo Prefix ${reason} old=${old_ip6_prefix} new=${new_ip6_prefix}
-
- exit_with_hooks 0
-fi
-
-if [ x$reason = xBOUND6 ]; then
- if [ x${new_ip6_address} = x ] || [ x${new_ip6_prefixlen} = x ] ; then
- exit_with_hooks 2;
- fi
-
- ${ip} -f inet6 addr add ${new_ip6_address}/${new_ip6_prefixlen} \
- dev ${interface} scope global
-
- # Check for nameserver options.
- make_resolv_conf
-
- exit_with_hooks 0
-fi
-
-if [ x$reason = xRENEW6 ] || [ x$reason = xREBIND6 ]; then
- if [ x${new_ip6_address} != x ] && [ x${new_ip6_prefixlen} != x ] ; then
- ${ip} -f inet6 addr add ${new_ip6_address}/${new_ip6_prefixlen} \
- dev ${interface} scope global
- fi
-
- # Make sure nothing has moved around on us.
-
- # Nameservers/domains/etc.
- if [ "x${new_dhcp6_name_servers}" != "x${old_dhcp6_name_servers}" ] ||
- [ "x${new_dhcp6_domain_search}" != "x${old_dhcp6_domain_search}" ] ; then
- make_resolv_conf
- fi
-
- exit_with_hooks 0
-fi
-
-if [ x$reason = xDEPREF6 ]; then
- if [ x${new_ip6_prefixlen} = x ] ; then
- exit_with_hooks 2;
- fi
-
- ${ip} -f inet6 addr change ${new_ip6_address}/${new_ip6_prefixlen} \
- dev ${interface} scope global preferred_lft 0
-
- exit_with_hooks 0
-fi
-
-if [ x$reason = xEXPIRE6 -o x$reason = xRELEASE6 -o x$reason = xSTOP6 ]; then
- if [ x${old_ip6_address} = x ] || [ x${old_ip6_prefixlen} = x ] ; then
- exit_with_hooks 2;
- fi
-
- ${ip} -f inet6 addr del ${old_ip6_address}/${old_ip6_prefixlen} \
- dev ${interface}
-
- exit_with_hooks 0
-fi
-
-exit_with_hooks 0
diff --git a/client/scripts/solaris b/client/scripts/solaris
deleted file mode 100755
index af553b9d..00000000
--- a/client/scripts/solaris
+++ /dev/null
@@ -1,203 +0,0 @@
-#!/bin/sh
-
-make_resolv_conf() {
- if [ x"$new_domain_name_servers" != x ]; then
- cat /dev/null > /etc/resolv.conf.dhclient
- if [ x"$new_domain_search" != x ]; then
- echo search $new_domain_search >> /etc/resolv.conf.dhclient
- elif [ x"$new_domain_name" != x ]; then
- # Note that the DHCP 'Domain Name Option' is really just a domain
- # name, and that this practice of using the domain name option as
- # a search path is both nonstandard and deprecated.
- echo search $new_domain_name >> /etc/resolv.conf.dhclient
- fi
- for nameserver in $new_domain_name_servers; do
- echo nameserver $nameserver >>/etc/resolv.conf.dhclient
- done
-
- mv /etc/resolv.conf.dhclient /etc/resolv.conf
- fi
-}
-
-# Must be used on exit. Invokes the local dhcp client exit hooks, if any.
-exit_with_hooks() {
- exit_status=$1
- if [ -f /etc/dhclient-exit-hooks ]; then
- . /etc/dhclient-exit-hooks
- fi
-# probably should do something with exit status of the local script
- exit $exit_status
-}
-
-# Invoke the local dhcp client enter hooks, if they exist.
-if [ -f /etc/dhclient-enter-hooks ]; then
- exit_status=0
- . /etc/dhclient-enter-hooks
- # allow the local script to abort processing of this state
- # local script must set exit_status variable to nonzero.
- if [ $exit_status -ne 0 ]; then
- exit $exit_status
- fi
-fi
-
-if [ x$new_broadcast_address != x ]; then
- new_broadcast_arg="broadcast $new_broadcast_address"
-fi
-if [ x$old_broadcast_address != x ]; then
- old_broadcast_arg="broadcast $old_broadcast_address"
-fi
-if [ x$new_subnet_mask != x ]; then
- new_netmask_arg="netmask $new_subnet_mask"
-fi
-if [ x$old_subnet_mask != x ]; then
- old_netmask_arg="netmask $old_subnet_mask"
-fi
-if [ x$alias_subnet_mask != x ]; then
- alias_subnet_arg="netmask $alias_subnet_mask"
-fi
- if [ x$new_interface_mtu != x ]; then
- mtu_arg="mtu $new_interface_mtu"
- fi
-if [ x$IF_METRIC != x ]; then
- metric_arg="metric $IF_METRIC"
-fi
-
-ifconfig=/sbin/ifconfig
-
-release=`uname -r`
-release=`expr $release : '\(.*\)\..*'`
-relmajor=`echo $release |sed -e 's/^\([^\.]*\)\..*$/\1/'`
-relminor=`echo $release |sed -e 's/^.*\.\([^\.]*\)$/\1/'`
-
-if [ x$reason = xMEDIUM ]; then
- eval "$ifconfig $interface $medium"
- $ifconfig $interface
- sleep 1
- exit_with_hooks 0
-fi
-
-if [ x$reason = xPREINIT ]; then
- if [ x$alias_ip_address != x ]; then
- $ifconfig ${interface}:1 0 down > /dev/null 2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
- fi
- if [ $relmajor -gt 5 ] || ( [ $relmajor -eq 5 ] && [ $relminor -ge 5 ] )
- then
- # Turn the interface on
- $ifconfig $interface plumb
- $ifconfig $interface up
- else
- $ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 \
- broadcast 255.255.255.255 up
- fi
- exit_with_hooks 0
-fi
-
-if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then
- exit_with_hooks 0;
-fi
-
-if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \
- [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then
- current_hostname=`hostname`
- if [ x$current_hostname = x ] || \
- [ x$current_hostname = x$old_host_name ]; then
- if [ x$current_hostname = x ] || \
- [ x$new_host_name != x$old_host_name ]; then
- hostname $new_host_name
- fi
- fi
-
- if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \
- [ x$alias_ip_address != x$old_ip_address ]; then
- $ifconfig ${interface}:1 inet 0 down > /dev/null 2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
- fi
- if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]; then
- $ifconfig ${interface} inet 0 down
- route delete $old_ip_address 127.1 >/dev/null 2>&1
- for router in $old_routers; do
- route delete default $router >/dev/null 2>&1
- done
- fi
- if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \
- [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then
- eval "$ifconfig $interface inet $new_ip_address $new_netmask_arg \
- $new_broadcast_arg $mtu_arg $metric_arg $medium"
- route add $new_ip_address 127.1 1 >/dev/null 2>&1
- for router in $new_routers; do
- route add default $router 1 >/dev/null 2>&1
- done
- else
- # we haven't changed the address, have we changed other options
- # that we wish to update?
- if [ x$new_routers != x ] && [ x$new_routers != x$old_routers ] ; then
- # if we've changed routers delete the old and add the new.
- $LOGGER "New Routers: $new_routers"
- for router in $old_routers; do
- route delete default $router >/dev/null 2>&1
- done
- for router in $new_routers; do
- route add default $router 1 >/dev/null 2>&1
- done
- fi
- fi
- if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ];
- then
- $ifconfig ${interface}:1 inet $alias_ip_address $alias_subnet_arg
- route add $alias_ip_address 127.0.0.1 1
- fi
- make_resolv_conf
- exit_with_hooks 0
-fi
-
-if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ] || [ x$reason = xRELEASE ] \
- || [ x$reason = xSTOP ]; then
- if [ x$alias_ip_address != x ]; then
- $ifconfig ${interface}:1 0 down > /dev/null 2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
- fi
- if [ x$old_ip_address != x ]; then
- $ifconfig $interface inet 0 down
- route delete $old_ip_address 127.1 >/dev/null 2>&1
- for router in $old_routers; do
- route delete default $router >/dev/null 2>&1
- done
- fi
- if [ x$alias_ip_address != x ]; then
- $ifconfig ${interface}:1 inet $alias_ip_address $alias_subnet_arg
- route add $alias_ip_address 127.0.0.1 1
- fi
- exit_with_hooks 0
-fi
-
-if [ x$reason = xTIMEOUT ]; then
- if [ x$alias_ip_address != x ]; then
- $ifconfig ${interface}:1 0 down > /dev/null 2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
- fi
- eval "$ifconfig $interface inet $new_ip_address $new_netmask_arg \
- $new_broadcast_arg $mtu_arg $metric_arg $medium"
- sleep 1
- set $new_routers
- if ping -s -n -I 1 $1 64 1; then
- if [ x$new_ip_address != x$alias_ip_address ] && \
- [ x$alias_ip_address != x ]; then
- $ifconfig ${interface}:1 inet $alias_ip_address $alias_subnet_arg
- route add $alias_ip_address 127.0.0.1 1
- fi
- route add $new_ip_address 127.1 1 >/dev/null 2>&1
- for router in $new_routers; do
- route add default $router 1 >/dev/null 2>&1
- done
- make_resolv_conf
- exit_with_hooks 0
- fi
- $ifconfig $interface inet 0 down
- for router in $old_routers; do
- route delete default $router >/dev/null 2>&1
- done
- exit_with_hooks 1
-fi
-
-exit_with_hooks 0
diff --git a/client/tests/Atffile b/client/tests/Atffile
deleted file mode 100644
index b2fdc0f1..00000000
--- a/client/tests/Atffile
+++ /dev/null
@@ -1,5 +0,0 @@
-Content-Type: application/X-atf-atffile; version="1"
-
-prop: test-suite = dhcp4
-
-tp-glob: *_unittests
diff --git a/client/tests/Kyuafile b/client/tests/Kyuafile
deleted file mode 100644
index 5bcdf214..00000000
--- a/client/tests/Kyuafile
+++ /dev/null
@@ -1,4 +0,0 @@
-syntax(2)
-test_suite('isc-dhcp')
-
-atf_test_program{name='duid_unittests'}
diff --git a/client/tests/Makefile.am b/client/tests/Makefile.am
deleted file mode 100644
index 8f1f0587..00000000
--- a/client/tests/Makefile.am
+++ /dev/null
@@ -1,58 +0,0 @@
-SUBDIRS = .
-
-AM_CPPFLAGS = $(ATF_CFLAGS) -DUNIT_TEST -I$(top_srcdir)/includes
-AM_CPPFLAGS += -I@BINDDIR@/include -I$(top_srcdir)
-AM_CPPFLAGS += -DLOCALSTATEDIR='"."'
-AM_CPPFLAGS += -DCLIENT_PATH='"."'
-
-EXTRA_DIST = Atffile Kyuafile
-EXTRA_DIST += duid0_test.txt duid1_test.txt duid2_test.txt duid3_test.txt
-
-# for autotools debugging only
-info:
- @echo "ATF_CFLAGS=$(ATF_CFLAGS)"
- @echo "ATF_LDFLAGS=$(ATF_LDFLAGS)"
- @echo "ATF_LIBS=$(ATF_LIBS)"
-
-DHCPSRC = ../clparse.c ../dhc6.c ../dhclient.c
-
-DHCPLIBS = $(top_builddir)/common/libdhcp.@A@ \
- $(top_builddir)/omapip/libomapi.@A@ \
- $(top_builddir)/dhcpctl/libdhcpctl.@A@ \
- @BINDLIBIRSDIR@/libirs.@A@ \
- @BINDLIBDNSDIR@/libdns.@A@ \
- @BINDLIBISCCFGDIR@/libisccfg.@A@ \
- @BINDLIBISCDIR@/libisc.@A@
-
-ATF_TESTS =
-if HAVE_ATF
-
-ATF_TESTS += duid_unittests
-
-duid_unittests_SOURCES = $(DHCPSRC)
-duid_unittests_SOURCES += duid_unittest.c
-
-duid_unittests_LDADD = $(ATF_LDFLAGS)
-duid_unittests_LDADD += $(DHCPLIBS)
-
-check: $(ATF_TESTS)
- @if test $(top_srcdir) != ${top_builddir}; then \
- cp $(top_srcdir)/client/tests/Atffile Atffile; \
- cp $(top_srcdir)/client/tests/Kyuafile Kyuafile; \
- cp $(top_srcdir)/client/tests/duid0_test.txt duid0_test.txt; \
- cp $(top_srcdir)/client/tests/duid1_test.txt duid1_test.txt; \
- cp $(top_srcdir)/client/tests/duid2_test.txt duid2_test.txt; \
- cp $(top_srcdir)/client/tests/duid3_test.txt duid3_test.txt; \
- fi
- sh ${top_builddir}/tests/unittest.sh
-
-distclean-local:
- @if test $(top_srcdir) != ${top_builddir}; then \
- rm -f Atffile Kyuafile; \
- rm -f duid0_test.txt duid1_test.txt; \
- rm -f duid2_test.txt duid3_test.txt; \
- fi
-
-endif
-
-check_PROGRAMS = $(ATF_TESTS)
diff --git a/client/tests/Makefile.in b/client/tests/Makefile.in
deleted file mode 100644
index ce335dff..00000000
--- a/client/tests/Makefile.in
+++ /dev/null
@@ -1,787 +0,0 @@
-# Makefile.in generated by automake 1.16.5 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2021 Free Software Foundation, Inc.
-
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-VPATH = @srcdir@
-am__is_gnu_make = { \
- if test -z '$(MAKELEVEL)'; then \
- false; \
- elif test -n '$(MAKE_HOST)'; then \
- true; \
- elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
- true; \
- else \
- false; \
- fi; \
-}
-am__make_running_with_option = \
- case $${target_option-} in \
- ?) ;; \
- *) echo "am__make_running_with_option: internal error: invalid" \
- "target option '$${target_option-}' specified" >&2; \
- exit 1;; \
- esac; \
- has_opt=no; \
- sane_makeflags=$$MAKEFLAGS; \
- if $(am__is_gnu_make); then \
- sane_makeflags=$$MFLAGS; \
- else \
- case $$MAKEFLAGS in \
- *\\[\ \ ]*) \
- bs=\\; \
- sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
- | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
- esac; \
- fi; \
- skip_next=no; \
- strip_trailopt () \
- { \
- flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
- }; \
- for flg in $$sane_makeflags; do \
- test $$skip_next = yes && { skip_next=no; continue; }; \
- case $$flg in \
- *=*|--*) continue;; \
- -*I) strip_trailopt 'I'; skip_next=yes;; \
- -*I?*) strip_trailopt 'I';; \
- -*O) strip_trailopt 'O'; skip_next=yes;; \
- -*O?*) strip_trailopt 'O';; \
- -*l) strip_trailopt 'l'; skip_next=yes;; \
- -*l?*) strip_trailopt 'l';; \
- -[dEDm]) skip_next=yes;; \
- -[JT]) skip_next=yes;; \
- esac; \
- case $$flg in \
- *$$target_option*) has_opt=yes; break;; \
- esac; \
- done; \
- test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-@HAVE_ATF_TRUE@am__append_1 = duid_unittests
-check_PROGRAMS = $(am__EXEEXT_2)
-subdir = client/tests
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/includes/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-@HAVE_ATF_TRUE@am__EXEEXT_1 = duid_unittests$(EXEEXT)
-am__EXEEXT_2 = $(am__EXEEXT_1)
-am__duid_unittests_SOURCES_DIST = ../clparse.c ../dhc6.c ../dhclient.c \
- duid_unittest.c
-am__objects_1 = clparse.$(OBJEXT) dhc6.$(OBJEXT) dhclient.$(OBJEXT)
-@HAVE_ATF_TRUE@am_duid_unittests_OBJECTS = $(am__objects_1) \
-@HAVE_ATF_TRUE@ duid_unittest.$(OBJEXT)
-duid_unittests_OBJECTS = $(am_duid_unittests_OBJECTS)
-am__DEPENDENCIES_1 =
-am__DEPENDENCIES_2 = $(top_builddir)/common/libdhcp.@A@ \
- $(top_builddir)/omapip/libomapi.@A@ \
- $(top_builddir)/dhcpctl/libdhcpctl.@A@
-@HAVE_ATF_TRUE@duid_unittests_DEPENDENCIES = $(am__DEPENDENCIES_1) \
-@HAVE_ATF_TRUE@ $(am__DEPENDENCIES_2)
-AM_V_P = $(am__v_P_@AM_V@)
-am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo " GEN " $@;
-am__v_GEN_1 =
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/includes
-depcomp = $(SHELL) $(top_srcdir)/depcomp
-am__maybe_remake_depfiles = depfiles
-am__depfiles_remade = ./$(DEPDIR)/clparse.Po ./$(DEPDIR)/dhc6.Po \
- ./$(DEPDIR)/dhclient.Po ./$(DEPDIR)/duid_unittest.Po
-am__mv = mv -f
-AM_V_lt = $(am__v_lt_@AM_V@)
-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
-am__v_lt_0 = --silent
-am__v_lt_1 =
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo " CC " $@;
-am__v_CC_1 =
-CCLD = $(CC)
-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo " CCLD " $@;
-am__v_CCLD_1 =
-SOURCES = $(duid_unittests_SOURCES)
-DIST_SOURCES = $(am__duid_unittests_SOURCES_DIST)
-RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
- ctags-recursive dvi-recursive html-recursive info-recursive \
- install-data-recursive install-dvi-recursive \
- install-exec-recursive install-html-recursive \
- install-info-recursive install-pdf-recursive \
- install-ps-recursive install-recursive installcheck-recursive \
- installdirs-recursive pdf-recursive ps-recursive \
- tags-recursive uninstall-recursive
-am__can_run_installinfo = \
- case $$AM_UPDATE_INFO_DIR in \
- n|no|NO) false;; \
- *) (install-info --version) >/dev/null 2>&1;; \
- esac
-RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
- distclean-recursive maintainer-clean-recursive
-am__recursive_targets = \
- $(RECURSIVE_TARGETS) \
- $(RECURSIVE_CLEAN_TARGETS) \
- $(am__extra_recursive_targets)
-AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
- distdir distdir-am
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-# Read a list of newline-separated strings from the standard input,
-# and print each of them once, without duplicates. Input order is
-# *not* preserved.
-am__uniquify_input = $(AWK) '\
- BEGIN { nonempty = 0; } \
- { items[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in items) print i; }; } \
-'
-# Make sure the list of sources is unique. This is necessary because,
-# e.g., the same source file might be shared among _SOURCES variables
-# for different programs/libraries.
-am__define_uniq_tagged_files = \
- list='$(am__tagged_files)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | $(am__uniquify_input)`
-DIST_SUBDIRS = $(SUBDIRS)
-am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-am__relativize = \
- dir0=`pwd`; \
- sed_first='s,^\([^/]*\)/.*$$,\1,'; \
- sed_rest='s,^[^/]*/*,,'; \
- sed_last='s,^.*/\([^/]*\)$$,\1,'; \
- sed_butlast='s,/*[^/]*$$,,'; \
- while test -n "$$dir1"; do \
- first=`echo "$$dir1" | sed -e "$$sed_first"`; \
- if test "$$first" != "."; then \
- if test "$$first" = ".."; then \
- dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
- dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
- else \
- first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
- if test "$$first2" = "$$first"; then \
- dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
- else \
- dir2="../$$dir2"; \
- fi; \
- dir0="$$dir0"/"$$first"; \
- fi; \
- fi; \
- dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
- done; \
- reldir="$$dir2"
-A = @A@
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-ATF_BIN = @ATF_BIN@
-ATF_CFLAGS = @ATF_CFLAGS@
-ATF_LDFLAGS = @ATF_LDFLAGS@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-BINDCONFIG = @BINDCONFIG@
-BINDDIR = @BINDDIR@
-BINDIOMUX = @BINDIOMUX@
-BINDLIBDNSDIR = @BINDLIBDNSDIR@
-BINDLIBIRSDIR = @BINDLIBIRSDIR@
-BINDLIBISCCFGDIR = @BINDLIBISCCFGDIR@
-BINDLIBISCDIR = @BINDLIBISCDIR@
-BINDLT = @BINDLT@
-BINDSRCDIR = @BINDSRCDIR@
-BINDSUBDIR = @BINDSUBDIR@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CSCOPE = @CSCOPE@
-CTAGS = @CTAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DHLIBS = @DHLIBS@
-DISTCHECK_ATF_CONFIGURE_FLAG = @DISTCHECK_ATF_CONFIGURE_FLAG@
-DISTCHECK_LIBBIND_CONFIGURE_FLAG = @DISTCHECK_LIBBIND_CONFIGURE_FLAG@
-DISTCHECK_LIBTOOL_CONFIGURE_FLAG = @DISTCHECK_LIBTOOL_CONFIGURE_FLAG@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-ETAGS = @ETAGS@
-EXEEXT = @EXEEXT@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LDAP_CFLAGS = @LDAP_CFLAGS@
-LDAP_LIBS = @LDAP_LIBS@
-LDFLAGS = @LDFLAGS@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-MKDIR_P = @MKDIR_P@
-OBJEXT = @OBJEXT@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-Q = @Q@
-RANLIB = @RANLIB@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-UNITTESTS = @UNITTESTS@
-VERSION = @VERSION@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_CC = @ac_ct_CC@
-ac_prefix_program = @ac_prefix_program@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-byte_order = @byte_order@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-pkgcfg_found = @pkgcfg_found@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-SUBDIRS = .
-AM_CPPFLAGS = $(ATF_CFLAGS) -DUNIT_TEST -I$(top_srcdir)/includes \
- -I@BINDDIR@/include -I$(top_srcdir) -DLOCALSTATEDIR='"."' \
- -DCLIENT_PATH='"."'
-EXTRA_DIST = Atffile Kyuafile duid0_test.txt duid1_test.txt \
- duid2_test.txt duid3_test.txt
-DHCPSRC = ../clparse.c ../dhc6.c ../dhclient.c
-DHCPLIBS = $(top_builddir)/common/libdhcp.@A@ \
- $(top_builddir)/omapip/libomapi.@A@ \
- $(top_builddir)/dhcpctl/libdhcpctl.@A@ \
- @BINDLIBIRSDIR@/libirs.@A@ \
- @BINDLIBDNSDIR@/libdns.@A@ \
- @BINDLIBISCCFGDIR@/libisccfg.@A@ \
- @BINDLIBISCDIR@/libisc.@A@
-
-ATF_TESTS = $(am__append_1)
-@HAVE_ATF_TRUE@duid_unittests_SOURCES = $(DHCPSRC) duid_unittest.c
-@HAVE_ATF_TRUE@duid_unittests_LDADD = $(ATF_LDFLAGS) $(DHCPLIBS)
-all: all-recursive
-
-.SUFFIXES:
-.SUFFIXES: .c .o .obj
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
- @for dep in $?; do \
- case '$(am__configure_deps)' in \
- *$$dep*) \
- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
- && { if test -f $@; then exit 0; else break; fi; }; \
- exit 1;; \
- esac; \
- done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign client/tests/Makefile'; \
- $(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --foreign client/tests/Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- @case '$?' in \
- *config.status*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
- *) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
- esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(am__aclocal_m4_deps):
-
-clean-checkPROGRAMS:
- -test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS)
-
-duid_unittests$(EXEEXT): $(duid_unittests_OBJECTS) $(duid_unittests_DEPENDENCIES) $(EXTRA_duid_unittests_DEPENDENCIES)
- @rm -f duid_unittests$(EXEEXT)
- $(AM_V_CCLD)$(LINK) $(duid_unittests_OBJECTS) $(duid_unittests_LDADD) $(LIBS)
-
-mostlyclean-compile:
- -rm -f *.$(OBJEXT)
-
-distclean-compile:
- -rm -f *.tab.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clparse.Po@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dhc6.Po@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dhclient.Po@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/duid_unittest.Po@am__quote@ # am--include-marker
-
-$(am__depfiles_remade):
- @$(MKDIR_P) $(@D)
- @echo '# dummy' >$@-t && $(am__mv) $@-t $@
-
-am--depfiles: $(am__depfiles_remade)
-
-.c.o:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
-
-.c.obj:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
-
-clparse.o: ../clparse.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clparse.o -MD -MP -MF $(DEPDIR)/clparse.Tpo -c -o clparse.o `test -f '../clparse.c' || echo '$(srcdir)/'`../clparse.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/clparse.Tpo $(DEPDIR)/clparse.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../clparse.c' object='clparse.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clparse.o `test -f '../clparse.c' || echo '$(srcdir)/'`../clparse.c
-
-clparse.obj: ../clparse.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clparse.obj -MD -MP -MF $(DEPDIR)/clparse.Tpo -c -o clparse.obj `if test -f '../clparse.c'; then $(CYGPATH_W) '../clparse.c'; else $(CYGPATH_W) '$(srcdir)/../clparse.c'; fi`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/clparse.Tpo $(DEPDIR)/clparse.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../clparse.c' object='clparse.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clparse.obj `if test -f '../clparse.c'; then $(CYGPATH_W) '../clparse.c'; else $(CYGPATH_W) '$(srcdir)/../clparse.c'; fi`
-
-dhc6.o: ../dhc6.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dhc6.o -MD -MP -MF $(DEPDIR)/dhc6.Tpo -c -o dhc6.o `test -f '../dhc6.c' || echo '$(srcdir)/'`../dhc6.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dhc6.Tpo $(DEPDIR)/dhc6.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../dhc6.c' object='dhc6.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dhc6.o `test -f '../dhc6.c' || echo '$(srcdir)/'`../dhc6.c
-
-dhc6.obj: ../dhc6.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dhc6.obj -MD -MP -MF $(DEPDIR)/dhc6.Tpo -c -o dhc6.obj `if test -f '../dhc6.c'; then $(CYGPATH_W) '../dhc6.c'; else $(CYGPATH_W) '$(srcdir)/../dhc6.c'; fi`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dhc6.Tpo $(DEPDIR)/dhc6.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../dhc6.c' object='dhc6.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dhc6.obj `if test -f '../dhc6.c'; then $(CYGPATH_W) '../dhc6.c'; else $(CYGPATH_W) '$(srcdir)/../dhc6.c'; fi`
-
-dhclient.o: ../dhclient.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dhclient.o -MD -MP -MF $(DEPDIR)/dhclient.Tpo -c -o dhclient.o `test -f '../dhclient.c' || echo '$(srcdir)/'`../dhclient.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dhclient.Tpo $(DEPDIR)/dhclient.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../dhclient.c' object='dhclient.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dhclient.o `test -f '../dhclient.c' || echo '$(srcdir)/'`../dhclient.c
-
-dhclient.obj: ../dhclient.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dhclient.obj -MD -MP -MF $(DEPDIR)/dhclient.Tpo -c -o dhclient.obj `if test -f '../dhclient.c'; then $(CYGPATH_W) '../dhclient.c'; else $(CYGPATH_W) '$(srcdir)/../dhclient.c'; fi`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dhclient.Tpo $(DEPDIR)/dhclient.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../dhclient.c' object='dhclient.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dhclient.obj `if test -f '../dhclient.c'; then $(CYGPATH_W) '../dhclient.c'; else $(CYGPATH_W) '$(srcdir)/../dhclient.c'; fi`
-
-# This directory's subdirectories are mostly independent; you can cd
-# into them and run 'make' without going through this Makefile.
-# To change the values of 'make' variables: instead of editing Makefiles,
-# (1) if the variable is set in 'config.status', edit 'config.status'
-# (which will cause the Makefiles to be regenerated when you run 'make');
-# (2) otherwise, pass the desired values on the 'make' command line.
-$(am__recursive_targets):
- @fail=; \
- if $(am__make_keepgoing); then \
- failcom='fail=yes'; \
- else \
- failcom='exit 1'; \
- fi; \
- dot_seen=no; \
- target=`echo $@ | sed s/-recursive//`; \
- case "$@" in \
- distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
- *) list='$(SUBDIRS)' ;; \
- esac; \
- for subdir in $$list; do \
- echo "Making $$target in $$subdir"; \
- if test "$$subdir" = "."; then \
- dot_seen=yes; \
- local_target="$$target-am"; \
- else \
- local_target="$$target"; \
- fi; \
- ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
- || eval $$failcom; \
- done; \
- if test "$$dot_seen" = "no"; then \
- $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
- fi; test -z "$$fail"
-
-ID: $(am__tagged_files)
- $(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-recursive
-TAGS: tags
-
-tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
- set x; \
- here=`pwd`; \
- if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
- include_option=--etags-include; \
- empty_fix=.; \
- else \
- include_option=--include; \
- empty_fix=; \
- fi; \
- list='$(SUBDIRS)'; for subdir in $$list; do \
- if test "$$subdir" = .; then :; else \
- test ! -f $$subdir/TAGS || \
- set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
- fi; \
- done; \
- $(am__define_uniq_tagged_files); \
- shift; \
- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
- test -n "$$unique" || unique=$$empty_fix; \
- if test $$# -gt 0; then \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- "$$@" $$unique; \
- else \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$unique; \
- fi; \
- fi
-ctags: ctags-recursive
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
- $(am__define_uniq_tagged_files); \
- test -z "$(CTAGS_ARGS)$$unique" \
- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$unique
-
-GTAGS:
- here=`$(am__cd) $(top_builddir) && pwd` \
- && $(am__cd) $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-recursive
-
-cscopelist-am: $(am__tagged_files)
- list='$(am__tagged_files)'; \
- case "$(srcdir)" in \
- [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
- *) sdir=$(subdir)/$(srcdir) ;; \
- esac; \
- for i in $$list; do \
- if test -f "$$i"; then \
- echo "$(subdir)/$$i"; \
- else \
- echo "$$sdir/$$i"; \
- fi; \
- done >> $(top_builddir)/cscope.files
-
-distclean-tags:
- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-distdir: $(BUILT_SOURCES)
- $(MAKE) $(AM_MAKEFLAGS) distdir-am
-
-distdir-am: $(DISTFILES)
- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- list='$(DISTFILES)'; \
- dist_files=`for file in $$list; do echo $$file; done | \
- sed -e "s|^$$srcdirstrip/||;t" \
- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
- case $$dist_files in \
- */*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
- sort -u` ;; \
- esac; \
- for file in $$dist_files; do \
- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
- if test -d $$d/$$file; then \
- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
- if test -d "$(distdir)/$$file"; then \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
- else \
- test -f "$(distdir)/$$file" \
- || cp -p $$d/$$file "$(distdir)/$$file" \
- || exit 1; \
- fi; \
- done
- @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
- if test "$$subdir" = .; then :; else \
- $(am__make_dryrun) \
- || test -d "$(distdir)/$$subdir" \
- || $(MKDIR_P) "$(distdir)/$$subdir" \
- || exit 1; \
- dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
- $(am__relativize); \
- new_distdir=$$reldir; \
- dir1=$$subdir; dir2="$(top_distdir)"; \
- $(am__relativize); \
- new_top_distdir=$$reldir; \
- echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
- echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
- ($(am__cd) $$subdir && \
- $(MAKE) $(AM_MAKEFLAGS) \
- top_distdir="$$new_top_distdir" \
- distdir="$$new_distdir" \
- am__remove_distdir=: \
- am__skip_length_check=: \
- am__skip_mode_fix=: \
- distdir) \
- || exit 1; \
- fi; \
- done
-check-am: all-am
- $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
-check: check-recursive
-all-am: Makefile
-installdirs: installdirs-recursive
-installdirs-am:
-install: install-recursive
-install-exec: install-exec-recursive
-install-data: install-data-recursive
-uninstall: uninstall-recursive
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-recursive
-install-strip:
- if test -z '$(STRIP)'; then \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- install; \
- else \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
- fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
-@HAVE_ATF_FALSE@distclean-local:
-clean: clean-recursive
-
-clean-am: clean-checkPROGRAMS clean-generic mostlyclean-am
-
-distclean: distclean-recursive
- -rm -f ./$(DEPDIR)/clparse.Po
- -rm -f ./$(DEPDIR)/dhc6.Po
- -rm -f ./$(DEPDIR)/dhclient.Po
- -rm -f ./$(DEPDIR)/duid_unittest.Po
- -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
- distclean-local distclean-tags
-
-dvi: dvi-recursive
-
-dvi-am:
-
-html: html-recursive
-
-html-am:
-
-info-am:
-
-install-data-am:
-
-install-dvi: install-dvi-recursive
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-recursive
-
-install-html-am:
-
-install-info: install-info-recursive
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-recursive
-
-install-pdf-am:
-
-install-ps: install-ps-recursive
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-recursive
- -rm -f ./$(DEPDIR)/clparse.Po
- -rm -f ./$(DEPDIR)/dhc6.Po
- -rm -f ./$(DEPDIR)/dhclient.Po
- -rm -f ./$(DEPDIR)/duid_unittest.Po
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-recursive
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic
-
-pdf: pdf-recursive
-
-pdf-am:
-
-ps: ps-recursive
-
-ps-am:
-
-uninstall-am:
-
-.MAKE: $(am__recursive_targets) check-am install-am install-strip
-
-.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
- am--depfiles check check-am clean clean-checkPROGRAMS \
- clean-generic cscopelist-am ctags ctags-am distclean \
- distclean-compile distclean-generic distclean-local \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-ps install-ps-am \
- install-strip installcheck installcheck-am installdirs \
- installdirs-am maintainer-clean maintainer-clean-generic \
- mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
- ps ps-am tags tags-am uninstall uninstall-am
-
-.PRECIOUS: Makefile
-
-
-# for autotools debugging only
-info:
- @echo "ATF_CFLAGS=$(ATF_CFLAGS)"
- @echo "ATF_LDFLAGS=$(ATF_LDFLAGS)"
- @echo "ATF_LIBS=$(ATF_LIBS)"
-
-@HAVE_ATF_TRUE@check: $(ATF_TESTS)
-@HAVE_ATF_TRUE@ @if test $(top_srcdir) != ${top_builddir}; then \
-@HAVE_ATF_TRUE@ cp $(top_srcdir)/client/tests/Atffile Atffile; \
-@HAVE_ATF_TRUE@ cp $(top_srcdir)/client/tests/Kyuafile Kyuafile; \
-@HAVE_ATF_TRUE@ cp $(top_srcdir)/client/tests/duid0_test.txt duid0_test.txt; \
-@HAVE_ATF_TRUE@ cp $(top_srcdir)/client/tests/duid1_test.txt duid1_test.txt; \
-@HAVE_ATF_TRUE@ cp $(top_srcdir)/client/tests/duid2_test.txt duid2_test.txt; \
-@HAVE_ATF_TRUE@ cp $(top_srcdir)/client/tests/duid3_test.txt duid3_test.txt; \
-@HAVE_ATF_TRUE@ fi
-@HAVE_ATF_TRUE@ sh ${top_builddir}/tests/unittest.sh
-
-@HAVE_ATF_TRUE@distclean-local:
-@HAVE_ATF_TRUE@ @if test $(top_srcdir) != ${top_builddir}; then \
-@HAVE_ATF_TRUE@ rm -f Atffile Kyuafile; \
-@HAVE_ATF_TRUE@ rm -f duid0_test.txt duid1_test.txt; \
-@HAVE_ATF_TRUE@ rm -f duid2_test.txt duid3_test.txt; \
-@HAVE_ATF_TRUE@ fi
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/client/tests/duid0_test.txt b/client/tests/duid0_test.txt
deleted file mode 100644
index 75e8d452..00000000
--- a/client/tests/duid0_test.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-lease {
- interface "em1";
- fixed-address 172.16.132.152;
- option subnet-mask 255.255.255.0;
- option dhcp-lease-time 60;
- option routers 17.132.16.200;
- option dhcp-message-type 5;
- option dhcp-server-identifier 172.16.132.200;
- option dhcp-renewal-time 30;
- option dhcp-rebinding-time 45;
- option domain-name "example.org";
- renew 2 2014/05/13 23:11:53;
- rebind 2 2014/05/13 23:11:53;
- expire 2 2014/05/13 23:11:53;
-}
-default-duid "\000\001";
-
-lease6 {
- interface "em1";
- ia-na 56:32:02:02 {
- starts 1399436400;
- renew 3;
- rebind 15;
- iaaddr 2000::37a {
- starts 1399436400;
- preferred-life 18;
- max-life 30;
- }
- }
- option dhcp6.client-id 0:1:0:1:1a:1:2d:7c:0:50:56:32:2:2;
- option dhcp6.server-id 0:1:0:1:19:fd:aa:20:0:50:56:2f:de:8a;
- option dhcp6.name-servers 2000::2;
-}
diff --git a/client/tests/duid1_test.txt b/client/tests/duid1_test.txt
deleted file mode 100644
index 38761858..00000000
--- a/client/tests/duid1_test.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-default-duid "\000\001\000\001\001\002\003\004\005\006\007\010\011\012";
-
-
diff --git a/client/tests/duid2_test.txt b/client/tests/duid2_test.txt
deleted file mode 100644
index 6837e9ab..00000000
--- a/client/tests/duid2_test.txt
+++ /dev/null
@@ -1,66 +0,0 @@
-default-duid "\000\003\000\001\005\006\007\010\011\012";
-
-lease {
- interface "em1";
- fixed-address 172.16.132.152;
- option subnet-mask 255.255.255.0;
- option dhcp-lease-time 60;
- option routers 17.132.16.200;
- option dhcp-message-type 5;
- option dhcp-server-identifier 172.16.132.200;
- option dhcp-renewal-time 30;
- option dhcp-rebinding-time 45;
- option domain-name "example.org";
- renew 2 2014/05/13 22:11:53;
- rebind 2 2014/05/13 22:11:53;
- expire 2 2014/05/13 22:11:53;
-}
-
-lease {
- interface "em1";
- fixed-address 172.16.132.152;
- option subnet-mask 255.255.255.0;
- option dhcp-lease-time 60;
- option routers 17.132.16.200;
- option dhcp-message-type 5;
- option dhcp-server-identifier 172.16.132.200;
- option dhcp-renewal-time 30;
- option dhcp-rebinding-time 45;
- option domain-name "example.org";
- foooo;
-}
-
-lease {
- interface "em1";
- fixed-address 172.16.132.152;
- option subnet-mask 255.255.255.0;
- option dhcp-lease-time 60;
- option routers 17.132.16.200;
- option dhcp-message-type 5;
- option dhcp-server-identifier 172.16.132.200;
- option dhcp-renewal-time 30;
- option dhcp-rebinding-time 45;
- option domain-name "example.org";
- renew 2 2014/05/13 23:11:53;
- rebind 2 2014/05/13 23:11:53;
- expire 2 2014/05/13 23:11:53;
-}
-
-lease6 {
- interface "em1";
- ia-na 56:32:02:02 {
- starts 1399436400;
- renew 3;
- rebind 15;
- iaaddr 2000::37a {
- starts 1399436400;
- preferred-life 18;
- max-life 30;
- }
- }
- option dhcp6.client-id 0:1:0:1:1a:1:2d:7c:0:50:56:32:2:2;
- option dhcp6.server-id 0:1:0:1:19:fd:aa:20:0:50:56:2f:de:8a;
- option dhcp6.name-servers 2000::2;
-}
-
-default-duid "\000\003\000\001\017\020\021\022\023\024";
diff --git a/client/tests/duid3_test.txt b/client/tests/duid3_test.txt
deleted file mode 100644
index 87c9f4d9..00000000
--- a/client/tests/duid3_test.txt
+++ /dev/null
@@ -1,66 +0,0 @@
-default-duid "\000\003\000\001\005\006\007\010\011\012";
-
-lease {
- interface "em1";
- fixed-address 172.16.132.152;
- option subnet-mask 255.255.255.0;
- option dhcp-lease-time 60;
- option routers 17.132.16.200;
- option dhcp-message-type 5;
- option dhcp-server-identifier 172.16.132.200;
- option dhcp-renewal-time 30;
- option dhcp-rebinding-time 45;
- option domain-name "example.org";
- renew 2 2014/05/13 22:11:53;
- rebind 2 2014/05/13 22:11:53;
- expire 2 2014/05/13 22:11:53;
-}
-
-lease {
- interface "em1";
- fixed-address 172.16.132.152;
- option subnet-mask 255.255.255.0;
- option dhcp-lease-time 60;
- option routers 17.132.16.200;
- option dhcp-message-type 5;
- option dhcp-server-identifier 172.16.132.200;
- option dhcp-renewal-time 30;
- option dhcp-rebinding-time 45;
- option domain-name "example.org";
-
-
-lease {
- interface "em1";
- fixed-address 172.16.132.152;
- option subnet-mask 255.255.255.0;
- option dhcp-lease-time 60;
- option routers 17.132.16.200;
- option dhcp-message-type 5;
- option dhcp-server-identifier 172.16.132.200;
- option dhcp-renewal-time 30;
- option dhcp-rebinding-time 45;
- option domain-name "example.org";
- renew 2 2014/05/13 23:11:53;
- rebind 2 2014/05/13 23:11:53;
- expire 2 2014/05/13 23:11:53;
-}
-default-duid "\000\001";
-
-lease6 {
- interface "em1";
- ia-na 56:32:02:02 {
- starts 1399436400;
- renew 3;
- rebind 15;
- iaaddr 2000::37a {
- starts 1399436400;
- preferred-life 18;
- max-life 30;
- }
- }
- option dhcp6.client-id 0:1:0:1:1a:1:2d:7c:0:50:56:32:2:2;
- option dhcp6.server-id 0:1:0:1:19:fd:aa:20:0:50:56:2f:de:8a;
- option dhcp6.name-servers 2000::2;
-}
-
-default-duid "\000\001\000\001\025\026\027\030\031\032\033\034\035\036";
diff --git a/client/tests/duid_unittest.c b/client/tests/duid_unittest.c
deleted file mode 100644
index f3e9bdc3..00000000
--- a/client/tests/duid_unittest.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2017-2022 Internet Systems Consortium, Inc. ("ISC")
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * 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.
- * PO Box 360
- * Newmarket, NH 03857 USA
- * <info@isc.org>
- * https://www.isc.org/
- *
- */
-
-#include "config.h"
-#include <atf-c.h>
-#include <omapip/omapip_p.h>
-#include "dhcpd.h"
-
-
-/* Tests to see if the routine to read a secondary lease file
- * for the DUID works properly. The tests:
- * Test file x:
- * no test file - should result in no duid
- * Test filx 0:
- * A test file but no DUID def, no duid
- * Test file 1:
- * Can it read a single DUID in the file?
- * Test file 2:
- * Can it find a second DUID in the file after a good lease and
- * a badly formatted lease?
- * Test file 3:
- * Can it find a later DUID after a good one and a bad one?
- * and to give a bit more coverage test file 1 should use LLT
- * test file 2 should use LL and test file 3 should use LL for
- * the first one and LLT for the third one.
- */
-
-int duidx_len = 0;
-
-int duid0_len = 0;
-
-int duid1_len = 14;
-char duid1_data[] = {0, 1, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-
-int duid2_len = 10;
-char duid2_data[] = {0, 3, 0, 1, 15, 16, 17, 18, 19, 20};
-
-int duid3_len = 14;
-char duid3_data[] = {0, 1, 0, 1, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30};
-
-ATF_TC(read_duid_test);
-
-ATF_TC_HEAD(read_duid_test, tc) {
- atf_tc_set_md_var(tc, "descr", "read secondary file looking for duid");
-}
-
-ATF_TC_BODY(read_duid_test, tc) {
-
- static const char *srcdir;
- char duid_fname[1024];
-
- /* Get the srcidr so we can find our test files */
- if (atf_tc_has_config_var(tc, "srcdir"))
- srcdir = atf_tc_get_config_var(tc, "srcdir");
- /* point the duid file at our filename space
- We will update it per test below */
- path_dhclient_duid = duid_fname;
-
- /* Initialize client globals. */
- memset(&default_duid, 0, sizeof(default_duid));
-
- /* Try to read a nonexistent test file
- */
- sprintf(duid_fname, "%s/duidx_test.txt", srcdir);
- read_client_duid();
- if (default_duid.len != duidx_len) {
- atf_tc_fail("failed to properly read duid1");
- }
-
- /* Try to read test file 0
- * This doesn't have a DUID.
- */
- sprintf(duid_fname, "%s/duid0_test.txt", srcdir);
- read_client_duid();
- if (default_duid.len != duid0_len) {
- atf_tc_fail("failed to properly read duid0");
- }
-
- /* Try to read test file 1
- * This has a single good LLT DUID in it
- */
- sprintf(duid_fname, "%s/duid1_test.txt", srcdir);
- read_client_duid();
- if ((default_duid.len != duid1_len) ||
- (memcmp(default_duid.data, duid1_data, duid1_len) != 0)) {
- atf_tc_fail("failed to properly read duid1");
- }
-
- /* Try to read test file 2
- * This has two good LL DUIDs in it with several good and bad leases between them.
- */
- sprintf(duid_fname, "%s/duid2_test.txt", srcdir);
- read_client_duid();
- if ((default_duid.len != duid2_len) ||
- (memcmp(default_duid.data, duid2_data, duid2_len) != 0)) {
- atf_tc_fail("failed to properly read duid2");
- }
-
- /* Try to read test file 3
- * This has a good LL DUID, a bad LLT DUID and a good LLT DUID
- */
- sprintf(duid_fname, "%s/duid3_test.txt", srcdir);
- read_client_duid();
- if ((default_duid.len != duid3_len) ||
- (memcmp(default_duid.data, duid3_data, duid3_len) != 0)) {
- atf_tc_fail("failed to properly read duid3");
- }
-
-}
-
-
-ATF_TP_ADD_TCS(tp) {
- ATF_TP_ADD_TC(tp, read_duid_test);
-
- return (atf_no_error());
-}
diff --git a/relay/.cvsignore b/relay/.cvsignore
deleted file mode 100644
index f45af85c..00000000
--- a/relay/.cvsignore
+++ /dev/null
@@ -1,4 +0,0 @@
-.deps
-Makefile
-dhcrelay
-dhcrelay.man8
diff --git a/relay/Makefile.am b/relay/Makefile.am
deleted file mode 100644
index 5562b694..00000000
--- a/relay/Makefile.am
+++ /dev/null
@@ -1,13 +0,0 @@
-SUBDIRS = . tests
-
-AM_CPPFLAGS = -DLOCALSTATEDIR='"@localstatedir@"'
-
-sbin_PROGRAMS = dhcrelay
-dhcrelay_SOURCES = dhcrelay.c
-dhcrelay_LDADD = ../common/libdhcp.@A@ ../omapip/libomapi.@A@ \
- @BINDLIBIRSDIR@/libirs.@A@ \
- @BINDLIBDNSDIR@/libdns.@A@ \
- @BINDLIBISCCFGDIR@/libisccfg.@A@ \
- @BINDLIBISCDIR@/libisc.@A@
-man_MANS = dhcrelay.8
-EXTRA_DIST = $(man_MANS)
diff --git a/relay/Makefile.in b/relay/Makefile.in
deleted file mode 100644
index 955a068d..00000000
--- a/relay/Makefile.in
+++ /dev/null
@@ -1,810 +0,0 @@
-# Makefile.in generated by automake 1.16.5 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2021 Free Software Foundation, Inc.
-
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-VPATH = @srcdir@
-am__is_gnu_make = { \
- if test -z '$(MAKELEVEL)'; then \
- false; \
- elif test -n '$(MAKE_HOST)'; then \
- true; \
- elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
- true; \
- else \
- false; \
- fi; \
-}
-am__make_running_with_option = \
- case $${target_option-} in \
- ?) ;; \
- *) echo "am__make_running_with_option: internal error: invalid" \
- "target option '$${target_option-}' specified" >&2; \
- exit 1;; \
- esac; \
- has_opt=no; \
- sane_makeflags=$$MAKEFLAGS; \
- if $(am__is_gnu_make); then \
- sane_makeflags=$$MFLAGS; \
- else \
- case $$MAKEFLAGS in \
- *\\[\ \ ]*) \
- bs=\\; \
- sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
- | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
- esac; \
- fi; \
- skip_next=no; \
- strip_trailopt () \
- { \
- flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
- }; \
- for flg in $$sane_makeflags; do \
- test $$skip_next = yes && { skip_next=no; continue; }; \
- case $$flg in \
- *=*|--*) continue;; \
- -*I) strip_trailopt 'I'; skip_next=yes;; \
- -*I?*) strip_trailopt 'I';; \
- -*O) strip_trailopt 'O'; skip_next=yes;; \
- -*O?*) strip_trailopt 'O';; \
- -*l) strip_trailopt 'l'; skip_next=yes;; \
- -*l?*) strip_trailopt 'l';; \
- -[dEDm]) skip_next=yes;; \
- -[JT]) skip_next=yes;; \
- esac; \
- case $$flg in \
- *$$target_option*) has_opt=yes; break;; \
- esac; \
- done; \
- test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-sbin_PROGRAMS = dhcrelay$(EXEEXT)
-subdir = relay
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/includes/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"
-PROGRAMS = $(sbin_PROGRAMS)
-am_dhcrelay_OBJECTS = dhcrelay.$(OBJEXT)
-dhcrelay_OBJECTS = $(am_dhcrelay_OBJECTS)
-dhcrelay_DEPENDENCIES = ../common/libdhcp.@A@ ../omapip/libomapi.@A@
-AM_V_P = $(am__v_P_@AM_V@)
-am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo " GEN " $@;
-am__v_GEN_1 =
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/includes
-depcomp = $(SHELL) $(top_srcdir)/depcomp
-am__maybe_remake_depfiles = depfiles
-am__depfiles_remade = ./$(DEPDIR)/dhcrelay.Po
-am__mv = mv -f
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo " CC " $@;
-am__v_CC_1 =
-CCLD = $(CC)
-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo " CCLD " $@;
-am__v_CCLD_1 =
-SOURCES = $(dhcrelay_SOURCES)
-DIST_SOURCES = $(dhcrelay_SOURCES)
-RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
- ctags-recursive dvi-recursive html-recursive info-recursive \
- install-data-recursive install-dvi-recursive \
- install-exec-recursive install-html-recursive \
- install-info-recursive install-pdf-recursive \
- install-ps-recursive install-recursive installcheck-recursive \
- installdirs-recursive pdf-recursive ps-recursive \
- tags-recursive uninstall-recursive
-am__can_run_installinfo = \
- case $$AM_UPDATE_INFO_DIR in \
- n|no|NO) false;; \
- *) (install-info --version) >/dev/null 2>&1;; \
- esac
-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
-am__vpath_adj = case $$p in \
- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
- *) f=$$p;; \
- esac;
-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
-am__install_max = 40
-am__nobase_strip_setup = \
- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
-am__nobase_strip = \
- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
-am__nobase_list = $(am__nobase_strip_setup); \
- for p in $$list; do echo "$$p $$p"; done | \
- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
- if (++n[$$2] == $(am__install_max)) \
- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
- END { for (dir in files) print dir, files[dir] }'
-am__base_list = \
- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__uninstall_files_from_dir = { \
- test -z "$$files" \
- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
- $(am__cd) "$$dir" && rm -f $$files; }; \
- }
-man8dir = $(mandir)/man8
-NROFF = nroff
-MANS = $(man_MANS)
-RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
- distclean-recursive maintainer-clean-recursive
-am__recursive_targets = \
- $(RECURSIVE_TARGETS) \
- $(RECURSIVE_CLEAN_TARGETS) \
- $(am__extra_recursive_targets)
-AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
- distdir distdir-am
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-# Read a list of newline-separated strings from the standard input,
-# and print each of them once, without duplicates. Input order is
-# *not* preserved.
-am__uniquify_input = $(AWK) '\
- BEGIN { nonempty = 0; } \
- { items[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in items) print i; }; } \
-'
-# Make sure the list of sources is unique. This is necessary because,
-# e.g., the same source file might be shared among _SOURCES variables
-# for different programs/libraries.
-am__define_uniq_tagged_files = \
- list='$(am__tagged_files)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | $(am__uniquify_input)`
-DIST_SUBDIRS = $(SUBDIRS)
-am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-am__relativize = \
- dir0=`pwd`; \
- sed_first='s,^\([^/]*\)/.*$$,\1,'; \
- sed_rest='s,^[^/]*/*,,'; \
- sed_last='s,^.*/\([^/]*\)$$,\1,'; \
- sed_butlast='s,/*[^/]*$$,,'; \
- while test -n "$$dir1"; do \
- first=`echo "$$dir1" | sed -e "$$sed_first"`; \
- if test "$$first" != "."; then \
- if test "$$first" = ".."; then \
- dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
- dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
- else \
- first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
- if test "$$first2" = "$$first"; then \
- dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
- else \
- dir2="../$$dir2"; \
- fi; \
- dir0="$$dir0"/"$$first"; \
- fi; \
- fi; \
- dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
- done; \
- reldir="$$dir2"
-A = @A@
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-ATF_BIN = @ATF_BIN@
-ATF_CFLAGS = @ATF_CFLAGS@
-ATF_LDFLAGS = @ATF_LDFLAGS@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-BINDCONFIG = @BINDCONFIG@
-BINDDIR = @BINDDIR@
-BINDIOMUX = @BINDIOMUX@
-BINDLIBDNSDIR = @BINDLIBDNSDIR@
-BINDLIBIRSDIR = @BINDLIBIRSDIR@
-BINDLIBISCCFGDIR = @BINDLIBISCCFGDIR@
-BINDLIBISCDIR = @BINDLIBISCDIR@
-BINDLT = @BINDLT@
-BINDSRCDIR = @BINDSRCDIR@
-BINDSUBDIR = @BINDSUBDIR@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CSCOPE = @CSCOPE@
-CTAGS = @CTAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DHLIBS = @DHLIBS@
-DISTCHECK_ATF_CONFIGURE_FLAG = @DISTCHECK_ATF_CONFIGURE_FLAG@
-DISTCHECK_LIBBIND_CONFIGURE_FLAG = @DISTCHECK_LIBBIND_CONFIGURE_FLAG@
-DISTCHECK_LIBTOOL_CONFIGURE_FLAG = @DISTCHECK_LIBTOOL_CONFIGURE_FLAG@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-ETAGS = @ETAGS@
-EXEEXT = @EXEEXT@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LDAP_CFLAGS = @LDAP_CFLAGS@
-LDAP_LIBS = @LDAP_LIBS@
-LDFLAGS = @LDFLAGS@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-MKDIR_P = @MKDIR_P@
-OBJEXT = @OBJEXT@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-Q = @Q@
-RANLIB = @RANLIB@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-UNITTESTS = @UNITTESTS@
-VERSION = @VERSION@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_CC = @ac_ct_CC@
-ac_prefix_program = @ac_prefix_program@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-byte_order = @byte_order@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-pkgcfg_found = @pkgcfg_found@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-SUBDIRS = . tests
-AM_CPPFLAGS = -DLOCALSTATEDIR='"@localstatedir@"'
-dhcrelay_SOURCES = dhcrelay.c
-dhcrelay_LDADD = ../common/libdhcp.@A@ ../omapip/libomapi.@A@ \
- @BINDLIBIRSDIR@/libirs.@A@ \
- @BINDLIBDNSDIR@/libdns.@A@ \
- @BINDLIBISCCFGDIR@/libisccfg.@A@ \
- @BINDLIBISCDIR@/libisc.@A@
-
-man_MANS = dhcrelay.8
-EXTRA_DIST = $(man_MANS)
-all: all-recursive
-
-.SUFFIXES:
-.SUFFIXES: .c .o .obj
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
- @for dep in $?; do \
- case '$(am__configure_deps)' in \
- *$$dep*) \
- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
- && { if test -f $@; then exit 0; else break; fi; }; \
- exit 1;; \
- esac; \
- done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign relay/Makefile'; \
- $(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --foreign relay/Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- @case '$?' in \
- *config.status*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
- *) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
- esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(am__aclocal_m4_deps):
-install-sbinPROGRAMS: $(sbin_PROGRAMS)
- @$(NORMAL_INSTALL)
- @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
- if test -n "$$list"; then \
- echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
- fi; \
- for p in $$list; do echo "$$p $$p"; done | \
- sed 's/$(EXEEXT)$$//' | \
- while read p p1; do if test -f $$p \
- ; then echo "$$p"; echo "$$p"; else :; fi; \
- done | \
- sed -e 'p;s,.*/,,;n;h' \
- -e 's|.*|.|' \
- -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
- sed 'N;N;N;s,\n, ,g' | \
- $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
- { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
- if ($$2 == $$4) files[d] = files[d] " " $$1; \
- else { print "f", $$3 "/" $$4, $$1; } } \
- END { for (d in files) print "f", d, files[d] }' | \
- while read type dir files; do \
- if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
- test -z "$$files" || { \
- echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
- $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
- } \
- ; done
-
-uninstall-sbinPROGRAMS:
- @$(NORMAL_UNINSTALL)
- @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
- files=`for p in $$list; do echo "$$p"; done | \
- sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
- -e 's/$$/$(EXEEXT)/' \
- `; \
- test -n "$$list" || exit 0; \
- echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
- cd "$(DESTDIR)$(sbindir)" && rm -f $$files
-
-clean-sbinPROGRAMS:
- -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS)
-
-dhcrelay$(EXEEXT): $(dhcrelay_OBJECTS) $(dhcrelay_DEPENDENCIES) $(EXTRA_dhcrelay_DEPENDENCIES)
- @rm -f dhcrelay$(EXEEXT)
- $(AM_V_CCLD)$(LINK) $(dhcrelay_OBJECTS) $(dhcrelay_LDADD) $(LIBS)
-
-mostlyclean-compile:
- -rm -f *.$(OBJEXT)
-
-distclean-compile:
- -rm -f *.tab.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dhcrelay.Po@am__quote@ # am--include-marker
-
-$(am__depfiles_remade):
- @$(MKDIR_P) $(@D)
- @echo '# dummy' >$@-t && $(am__mv) $@-t $@
-
-am--depfiles: $(am__depfiles_remade)
-
-.c.o:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
-
-.c.obj:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
-install-man8: $(man_MANS)
- @$(NORMAL_INSTALL)
- @list1=''; \
- list2='$(man_MANS)'; \
- test -n "$(man8dir)" \
- && test -n "`echo $$list1$$list2`" \
- || exit 0; \
- echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
- { for i in $$list1; do echo "$$i"; done; \
- if test -n "$$list2"; then \
- for i in $$list2; do echo "$$i"; done \
- | sed -n '/\.8[a-z]*$$/p'; \
- fi; \
- } | while read p; do \
- if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
- echo "$$d$$p"; echo "$$p"; \
- done | \
- sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
- -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
- sed 'N;N;s,\n, ,g' | { \
- list=; while read file base inst; do \
- if test "$$base" = "$$inst"; then list="$$list $$file"; else \
- echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
- $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
- fi; \
- done; \
- for i in $$list; do echo "$$i"; done | $(am__base_list) | \
- while read files; do \
- test -z "$$files" || { \
- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
- $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
- done; }
-
-uninstall-man8:
- @$(NORMAL_UNINSTALL)
- @list=''; test -n "$(man8dir)" || exit 0; \
- files=`{ for i in $$list; do echo "$$i"; done; \
- l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
- sed -n '/\.8[a-z]*$$/p'; \
- } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
- -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
- dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
-
-# This directory's subdirectories are mostly independent; you can cd
-# into them and run 'make' without going through this Makefile.
-# To change the values of 'make' variables: instead of editing Makefiles,
-# (1) if the variable is set in 'config.status', edit 'config.status'
-# (which will cause the Makefiles to be regenerated when you run 'make');
-# (2) otherwise, pass the desired values on the 'make' command line.
-$(am__recursive_targets):
- @fail=; \
- if $(am__make_keepgoing); then \
- failcom='fail=yes'; \
- else \
- failcom='exit 1'; \
- fi; \
- dot_seen=no; \
- target=`echo $@ | sed s/-recursive//`; \
- case "$@" in \
- distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
- *) list='$(SUBDIRS)' ;; \
- esac; \
- for subdir in $$list; do \
- echo "Making $$target in $$subdir"; \
- if test "$$subdir" = "."; then \
- dot_seen=yes; \
- local_target="$$target-am"; \
- else \
- local_target="$$target"; \
- fi; \
- ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
- || eval $$failcom; \
- done; \
- if test "$$dot_seen" = "no"; then \
- $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
- fi; test -z "$$fail"
-
-ID: $(am__tagged_files)
- $(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-recursive
-TAGS: tags
-
-tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
- set x; \
- here=`pwd`; \
- if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
- include_option=--etags-include; \
- empty_fix=.; \
- else \
- include_option=--include; \
- empty_fix=; \
- fi; \
- list='$(SUBDIRS)'; for subdir in $$list; do \
- if test "$$subdir" = .; then :; else \
- test ! -f $$subdir/TAGS || \
- set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
- fi; \
- done; \
- $(am__define_uniq_tagged_files); \
- shift; \
- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
- test -n "$$unique" || unique=$$empty_fix; \
- if test $$# -gt 0; then \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- "$$@" $$unique; \
- else \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$unique; \
- fi; \
- fi
-ctags: ctags-recursive
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
- $(am__define_uniq_tagged_files); \
- test -z "$(CTAGS_ARGS)$$unique" \
- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$unique
-
-GTAGS:
- here=`$(am__cd) $(top_builddir) && pwd` \
- && $(am__cd) $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-recursive
-
-cscopelist-am: $(am__tagged_files)
- list='$(am__tagged_files)'; \
- case "$(srcdir)" in \
- [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
- *) sdir=$(subdir)/$(srcdir) ;; \
- esac; \
- for i in $$list; do \
- if test -f "$$i"; then \
- echo "$(subdir)/$$i"; \
- else \
- echo "$$sdir/$$i"; \
- fi; \
- done >> $(top_builddir)/cscope.files
-
-distclean-tags:
- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-distdir: $(BUILT_SOURCES)
- $(MAKE) $(AM_MAKEFLAGS) distdir-am
-
-distdir-am: $(DISTFILES)
- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- list='$(DISTFILES)'; \
- dist_files=`for file in $$list; do echo $$file; done | \
- sed -e "s|^$$srcdirstrip/||;t" \
- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
- case $$dist_files in \
- */*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
- sort -u` ;; \
- esac; \
- for file in $$dist_files; do \
- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
- if test -d $$d/$$file; then \
- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
- if test -d "$(distdir)/$$file"; then \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
- else \
- test -f "$(distdir)/$$file" \
- || cp -p $$d/$$file "$(distdir)/$$file" \
- || exit 1; \
- fi; \
- done
- @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
- if test "$$subdir" = .; then :; else \
- $(am__make_dryrun) \
- || test -d "$(distdir)/$$subdir" \
- || $(MKDIR_P) "$(distdir)/$$subdir" \
- || exit 1; \
- dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
- $(am__relativize); \
- new_distdir=$$reldir; \
- dir1=$$subdir; dir2="$(top_distdir)"; \
- $(am__relativize); \
- new_top_distdir=$$reldir; \
- echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
- echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
- ($(am__cd) $$subdir && \
- $(MAKE) $(AM_MAKEFLAGS) \
- top_distdir="$$new_top_distdir" \
- distdir="$$new_distdir" \
- am__remove_distdir=: \
- am__skip_length_check=: \
- am__skip_mode_fix=: \
- distdir) \
- || exit 1; \
- fi; \
- done
-check-am: all-am
-check: check-recursive
-all-am: Makefile $(PROGRAMS) $(MANS)
-installdirs: installdirs-recursive
-installdirs-am:
- for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"; do \
- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
- done
-install: install-recursive
-install-exec: install-exec-recursive
-install-data: install-data-recursive
-uninstall: uninstall-recursive
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-recursive
-install-strip:
- if test -z '$(STRIP)'; then \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- install; \
- else \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
- fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
-clean: clean-recursive
-
-clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am
-
-distclean: distclean-recursive
- -rm -f ./$(DEPDIR)/dhcrelay.Po
- -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
- distclean-tags
-
-dvi: dvi-recursive
-
-dvi-am:
-
-html: html-recursive
-
-html-am:
-
-info: info-recursive
-
-info-am:
-
-install-data-am: install-man
-
-install-dvi: install-dvi-recursive
-
-install-dvi-am:
-
-install-exec-am: install-sbinPROGRAMS
-
-install-html: install-html-recursive
-
-install-html-am:
-
-install-info: install-info-recursive
-
-install-info-am:
-
-install-man: install-man8
-
-install-pdf: install-pdf-recursive
-
-install-pdf-am:
-
-install-ps: install-ps-recursive
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-recursive
- -rm -f ./$(DEPDIR)/dhcrelay.Po
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-recursive
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic
-
-pdf: pdf-recursive
-
-pdf-am:
-
-ps: ps-recursive
-
-ps-am:
-
-uninstall-am: uninstall-man uninstall-sbinPROGRAMS
-
-uninstall-man: uninstall-man8
-
-.MAKE: $(am__recursive_targets) install-am install-strip
-
-.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
- am--depfiles check check-am clean clean-generic \
- clean-sbinPROGRAMS cscopelist-am ctags ctags-am distclean \
- distclean-compile distclean-generic distclean-tags distdir dvi \
- dvi-am html html-am info info-am install install-am \
- install-data install-data-am install-dvi install-dvi-am \
- install-exec install-exec-am install-html install-html-am \
- install-info install-info-am install-man install-man8 \
- install-pdf install-pdf-am install-ps install-ps-am \
- install-sbinPROGRAMS install-strip installcheck \
- installcheck-am installdirs installdirs-am maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
- uninstall-am uninstall-man uninstall-man8 \
- uninstall-sbinPROGRAMS
-
-.PRECIOUS: Makefile
-
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/relay/dhcrelay.8 b/relay/dhcrelay.8
deleted file mode 100644
index 9667e608..00000000
--- a/relay/dhcrelay.8
+++ /dev/null
@@ -1,355 +0,0 @@
-.\" dhcrelay.8
-.\"
-.\" Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
-.\" Copyright (c) 1997-2003 by Internet Software Consortium
-.\"
-.\" This Source Code Form is subject to the terms of the Mozilla Public
-.\" License, v. 2.0. If a copy of the MPL was not distributed with this
-.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
-.\"
-.\" 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.
-.\" PO Box 360
-.\" Newmarket, NH 03857 USA
-.\" <info@isc.org>
-.\" https://www.isc.org/
-.\"
-.\" This software has been written for Internet Systems Consortium
-.\" by Ted Lemon in cooperation with Vixie Enterprises.
-.\"
-.\" Support and other services are available for ISC products - see
-.\" https://www.isc.org for more information or to learn more about ISC.
-.\"
-.\" $Id: dhcrelay.8,v 1.20 2012/05/14 23:17:43 sar Exp $
-.\"
-.TH dhcrelay 8
-.SH NAME
-dhcrelay - Dynamic Host Configuration Protocol Relay Agent
-.SH SYNOPSIS
-.B dhcrelay
-[
-.B -4
-]
-[
-.B -dqaD
-]
-[
-.B -p
-.I port
-|
-.B -rp
-.I relay-port
-]
-[
-.B -c
-.I count
-]
-[
-.B -A
-.I length
-]
-[
-.B -pf
-.I pid-file
-]
-[
-.B --no-pid
-]
-[
-.B -m
-.I append
-|
-.I replace
-|
-.I forward
-|
-.I discard
-]
-[
-.B -i
-.I interface0
-[
-.B ...
-.B -i
-.I interfaceN
-]
-]
-[
-.B -iu
-.I interface0
-[
-.B ...
-.B -iu
-.I interfaceN
-]
-]
-[
-.B -id
-.I interface0
-[
-.B ...
-.B -id
-.I interfaceN
-]
-]
-[
-.B -U
-.I interface
-]
-[
-.B -g
-.I ipaddr
-]
-.I server0
-[
-.I ...serverN
-]
-.PP
-.B dhcrelay -6
-[
-.B -dqI
-]
-[
-.B -p
-.I port
-|
-.B -rp
-.I relay-port
-]
-[
-.B -c
-.I count
-]
-[
-.B -pf
-.I pid-file
-]
-[
-.B --no-pid
-]
-[
-.B -s
-.I subscriber-id
-]
-.B -l
-.I lower0
-[
-.B ...
-.B -l
-.I lowerN
-]
-.B -u
-.I upper0
-[
-.B ...
-.B -u
-.I upperN
-]
-.SH DESCRIPTION
-The Internet Systems Consortium DHCP Relay Agent, dhcrelay, provides a
-means for relaying DHCP and BOOTP requests from a subnet to which
-no DHCP server is directly connected to one or more DHCP servers on
-other subnets. It supports both DHCPv4/BOOTP and DHCPv6 protocols.
-.SH OPERATION
-.PP
-The DHCP Relay Agent listens for DHCPv4 or DHCPv6 queries from clients or
-other relay agents on one or more interfaces, passing them along to
-``upstream'' servers or relay agents as specified on the command line.
-When a reply is received from upstream, it is multicast or unicast back
-downstream to the source of the original request.
-.SH COMMAND LINE
-.PP
-\fIProtocol selection options:\fR
-.TP
--6
-Run dhcrelay as a DHCPv6 relay agent. Incompatible with the \fB-4\fR
-option.
-.TP
--4
-Run dhcrelay as a DHCPv4/BOOTP relay agent. This is the default mode of
-operation, so the argument is not necessary, but may be specified for
-clarity. Incompatible with \fB-6\fR.
-.PP
-\fISpecifying DHCPv4/BOOTP servers\fR
-.PP
-In DHCPv4 mode, a list of one or more server addresses must be specified on
-the command line, to which DHCP/BOOTP queries should be relayed.
-.PP
-\fIOptions available for both DHCPv4 and DHCPv6:\fR
-.TP
--c \fIcount\fR
-Maximum hop count. When forwarding packets, dhcrelay discards packets
-which have reached a hop count of COUNT. Default is 10. Maximum is 255.
-.TP
--d
-Force dhcrelay to run as a foreground process. Useful when running
-dhcrelay under a debugger, or running out of inittab on System V systems.
-.TP
--p \fIport\fR
-Listen and transmit on port PORT. This is mostly useful for debugging
-purposes. Default is port 67 for DHCPv4/BOOTP, or port 547 for DHCPv6.
-Incompatible with \fB-rp\fR.
-.TP
--rp \fIrelay-port\fR
-Alternative source port for upstream (i.e toward the server) messages
-with DHCPv4 RAI relay-port sub-option or DHCPv6 relay-source-port
-option. Relay port support is only available if the code was compiled
-with (./configure --enable-relay-port) and requires LPF or BPF link
-layer access.
-.TP
--q
-Quiet mode. Prevents dhcrelay6 from printing its network configuration
-on startup.
-.TP
--pf pid-file
-Path to alternate pid file.
-.TP
---no-pid
-Option to disable writing pid files. By default the program
-will write a pid file.
-.PP
-\fIOptions available in DHCPv4 mode only:\fR
-.TP
--a
-Append an agent option field to each request before forwarding it to
-the server. Agent option fields in responses sent from servers to
-clients will be stripped before forwarding such responses back to the
-client. The agent option field will contain two agent options: the Circuit
-ID suboption and the Remote ID suboption. Currently, the Circuit ID will
-be the printable name of the interface on which the client request was
-received. The client supports inclusion of a Remote ID suboption as well,
-but this is not used by default.
-.TP
--A \fIlength\fR
-Specify the maximum packet size to send to a DHCPv4/BOOTP server. This
-might be done to allow sufficient space for addition of relay agent
-options while still fitting into the Ethernet MTU size.
-.TP
--D
-Drop packets from upstream servers if they contain Relay Agent
-Information options that indicate they were generated in response to
-a query that came via a different relay agent. If this option is not
-specified, such packets will be relayed anyway.
-.TP
--g \fIipaddr\fR
-When a package gets sent back to the client, replace the gateway's IP
-address (giaddr) with the given \fIipaddr\fR. This can be used as a
-workaround for bogus clients like Solaris 11 grub, which use the giaddr
-instead of the announced router (3) to setup its default route.
-.TP
--i \fIifname\fR
-Listen for DHCPv4/BOOTP traffic on interface \fIifname\fR. Multiple
-interfaces may be specified by using more than one \fB-i\fR option. If
-no interfaces are specified on the command line, dhcrelay will identify
-all network interfaces, eliminating non-broadcast interfaces if possible,
-and attempt to listen on all of them.
-.TP
--iu \fIifname\fR
-Specifies an upstream network interface: an interface from which replies
-from servers and other relay agents will be accepted. Multiple interfaces
-may be specified by using more than one \fB-iu\fR option. This argument is
- intended to be used in conjunction with one or more -i or -id arguments.
-.TP
--id \fIifname\fR
-Specifies a downstream network interface: an interface from which requests
-from clients and other relay agents will be accepted. Multiple interfaces
-may be specified by using more than one \fB-id\fR option. This argument is
-intended to be used in conjunction with one or more -i or -iu arguments.
-.TP
--m \fIappend\fR|\fIreplace\fR|\fIforward\fR|\fIdiscard\fR
-Control the handling of incoming DHCPv4 packets which already contain
-relay agent options. If such a packet does not have \fIgiaddr\fR set in
-its header, the DHCP standard requires that the packet be discarded.
-However, if \fIgiaddr\fR is set, the relay agent may handle the situation
-in four ways: It may \fIappend\fR its own set of relay options to the
-packet, leaving the supplied option field intact; it may \fIreplace\fR the
-existing agent option field; it may \fIforward\fR the packet unchanged; or,
-it may \fIdiscard\fR it.
-.TP
--U \fIifname\fR
-Enables the addition of a RFC 3527 compliant link selection suboption for
-clients directly connected to the relay. This RFC allows a relay to
-specify two different IP addresses: one for the server to use when
-communicating with the relay (giaddr) the other for choosing the subnet
-for the client (the suboption). This can be useful if the server is
-unable to send packets to the relay via the address used for the subnet.
-
-When enabled, dhcrelay will add an agent option (as per \fB-a\fR above) that
-includes the link selection suboption to the forwarded packet. This will only
-be done to packets received from clients that are directly connected to the
-relay (i.e. giaddr is zero). The address used in the suboption will be that
-of the link upon which the inbound packet was received (which would otherwise
-be used for giaddr). The value of giaddr will be set to that of interface
-\fIifname\fR.
-
-Only one interface should be marked in this fashion. Currently enabling
-this option on an interface causes the relay to process all DHCP traffic
-similar to the \fI-i\fR option, in the future we may split the two more
-completely.
-
-This option is off by default. Note that enabling this option automatically
-enables the \fB-a\fR option.
-
-Keep in mind that using options such as \fB-m replace\fR or \fB-m discard\fR
-on relays upstream from one using \fB-U\fR can pose problems. The upstream
-relay will wipe out the initial agent option containing the link selection
-while leaving the re-purposed giaddr value in place, causing packets to go
-astray.
-
-.PP
-\fIOptions available in DHCPv6 mode only:\fR
-.TP
--I
-Force use of the DHCPv6 Interface-ID option. This option is
-automatically sent when there are two or more downstream interfaces
-in use, to disambiguate between them. The \fB-I\fR option causes
-dhcrelay to send the option even if there is only one downstream
-interface.
-.TP
--s subscriber-id
-Add an option with the specified subscriber-id into the packet. This
-feature is for testing rather than production as it will put the same
-subscriber-id into the packet for all clients.
-.TP
--l [\fIaddress%\fR]\fIifname\fR[\fI#index\fR]
-Specifies the ``lower'' network interface for DHCPv6 relay mode: the
-interface on which queries will be received from clients or from other
-relay agents. At least one \fB-l\fR option must be included in the command
-line when running in DHCPv6 mode. The interface name \fIifname\fR is a
-mandatory parameter. The link address can be specified by \fIaddress%\fR;
-if it isn't, dhcrelay will use the first non-link-local address configured
-on the interface. The optional \fI#index\fR parameter specifies the
-interface index.
-.TP
--u [\fIaddress%\fR]\fIifname\fR
-Specifies the ``upper'' network interface for DHCPv6 relay mode: the
-interface to which queries from clients and other relay agents should be
-forwarded. At least one \fB-u\fR option must be included in the command
-line when running in DHCPv6 mode. The interface name \fIifname\fR is a
-mandatory parameter. The destination unicast or multicast address can be
-specified by \fIaddress%\fR; if not specified, the relay agent will forward
-to the DHCPv6 \fIAll_DHCP_Relay_Agents_and_Servers\fR multicast address.
-.PP
-It is possible to specify the same interface with different addresses
-more than once, and even, when the system supports it, to use the same
-interface as both upper and lower interfaces.
-.SH SEE ALSO
-dhclient(8), dhcpd(8), RFC3315, RFC2132, RFC2131.
-.SH BUGS
-.PP
-Using the same interface on both upper and lower sides may cause
-loops, so when running this way, the maximum hop count should be set
-to a low value.
-.PP
-The loopback interface is not (yet) recognized as a valid interface.
-.SH AUTHOR
-.B dhcrelay(8)
-To learn more about Internet Systems Consortium, see
-.B https://www.isc.org
diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c
deleted file mode 100644
index 946ef1b0..00000000
--- a/relay/dhcrelay.c
+++ /dev/null
@@ -1,2173 +0,0 @@
-/* dhcrelay.c
-
- DHCP/BOOTP Relay Agent. */
-
-/*
- * Copyright(c) 2004-2022 by Internet Systems Consortium, Inc.("ISC")
- * Copyright(c) 1997-2003 by Internet Software Consortium
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * 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.
- * PO Box 360
- * Newmarket, NH 03857 USA
- * <info@isc.org>
- * https://www.isc.org/
- *
- */
-
-#include "dhcpd.h"
-#include <syslog.h>
-#include <signal.h>
-#include <sys/time.h>
-#include <isc/file.h>
-
-TIME default_lease_time = 43200; /* 12 hours... */
-TIME max_lease_time = 86400; /* 24 hours... */
-struct tree_cache *global_options[256];
-
-struct option *requested_opts[2];
-
-/* Needed to prevent linking against conflex.c. */
-int lexline;
-int lexchar;
-char *token_line;
-char *tlname;
-
-const char *path_dhcrelay_pid = _PATH_DHCRELAY_PID;
-isc_boolean_t no_dhcrelay_pid = ISC_FALSE;
-/* False (default) => we write and use a pid file */
-isc_boolean_t no_pid_file = ISC_FALSE;
-
-int bogus_agent_drops = 0; /* Packets dropped because agent option
- field was specified and we're not relaying
- packets that already have an agent option
- specified. */
-int bogus_giaddr_drops = 0; /* Packets sent to us to relay back to a
- client, but with a bogus giaddr. */
-int client_packets_relayed = 0; /* Packets relayed from client to server. */
-int server_packet_errors = 0; /* Errors sending packets to servers. */
-int server_packets_relayed = 0; /* Packets relayed from server to client. */
-int client_packet_errors = 0; /* Errors sending packets to clients. */
-
-int add_agent_options = 0; /* If nonzero, add relay agent options. */
-int add_rfc3527_suboption = 0; /* If nonzero, add RFC3527 link selection sub-option. */
-
-int agent_option_errors = 0; /* Number of packets forwarded without
- agent options because there was no room. */
-int drop_agent_mismatches = 0; /* If nonzero, drop server replies that
- don't have matching circuit-id's. */
-int corrupt_agent_options = 0; /* Number of packets dropped because
- relay agent information option was bad. */
-int missing_agent_option = 0; /* Number of packets dropped because no
- RAI option matching our ID was found. */
-int bad_circuit_id = 0; /* Circuit ID option in matching RAI option
- did not match any known circuit ID. */
-int missing_circuit_id = 0; /* Circuit ID option in matching RAI option
- was missing. */
-int max_hop_count = 10; /* Maximum hop count */
-
-int no_daemon = 0;
-int dfd[2] = { -1, -1 };
-
-#ifdef DHCPv6
- /* Force use of DHCPv6 interface-id option. */
-isc_boolean_t use_if_id = ISC_FALSE;
-#endif
-
- /* Maximum size of a packet with agent options added. */
-int dhcp_max_agent_option_packet_length = DHCP_MTU_MIN;
-
- /* What to do about packets we're asked to relay that
- already have a relay option: */
-enum { forward_and_append, /* Forward and append our own relay option. */
- forward_and_replace, /* Forward, but replace theirs with ours. */
- forward_untouched, /* Forward without changes. */
- discard } agent_relay_mode = forward_and_replace;
-
-extern u_int16_t local_port;
-extern u_int16_t remote_port;
-
-/* Relay agent server list. */
-struct server_list {
- struct server_list *next;
- struct sockaddr_in to;
-} *servers;
-
-struct interface_info *uplink = NULL;
-isc_boolean_t use_fake_gw = ISC_FALSE;
-struct in_addr gw = {0};
-
-#ifdef DHCPv6
-struct stream_list {
- struct stream_list *next;
- struct interface_info *ifp;
- struct sockaddr_in6 link;
- int id;
-} *downstreams, *upstreams;
-
-#ifndef UNIT_TEST
-static struct stream_list *parse_downstream(char *);
-static struct stream_list *parse_upstream(char *);
-static void setup_streams(void);
-#endif /* UNIT_TEST */
-
-/*
- * A pointer to a subscriber id to add to the message we forward.
- * This is primarily for testing purposes as we only have one id
- * for the entire relay and don't determine one per client which
- * would be more useful.
- */
-char *dhcrelay_sub_id = NULL;
-#endif
-
-#ifndef UNIT_TEST
-static void do_relay4(struct interface_info *, struct dhcp_packet *,
- unsigned int, unsigned int, struct iaddr,
- struct hardware *);
-#endif /* UNIT_TEST */
-
-extern int add_relay_agent_options(struct interface_info *,
- struct dhcp_packet *, unsigned,
- struct in_addr);
-extern int find_interface_by_agent_option(struct dhcp_packet *,
- struct interface_info **, u_int8_t *, int);
-
-extern int strip_relay_agent_options(struct interface_info *,
- struct interface_info **,
- struct dhcp_packet *, unsigned);
-
-#ifndef UNIT_TEST
-static void request_v4_interface(const char* name, int flags);
-
-static const char copyright[] =
-"Copyright 2004-2022 Internet Systems Consortium.";
-static const char arr[] = "All rights reserved.";
-static const char message[] =
-"Internet Systems Consortium DHCP Relay Agent";
-static const char url[] =
-"For info, please visit https://www.isc.org/software/dhcp/";
-
-char *progname;
-
-#ifdef DHCPv6
-#ifdef RELAY_PORT
-#define DHCRELAY_USAGE \
-"Usage: %s [-4] [-d] [-q] [-a] [-D]\n" \
-" [-A <length>] [-c <hops>]\n" \
-" [-p <port> | -rp <relay-port>]\n" \
-" [-pf <pid-file>] [--no-pid]\n"\
-" [-m append|replace|forward|discard]\n" \
-" [-i interface0 [ ... -i interfaceN]\n" \
-" [-iu interface0 [ ... -iu interfaceN]\n" \
-" [-id interface0 [ ... -id interfaceN]\n" \
-" [-U interface] [-g <ip-address>]\n" \
-" server0 [ ... serverN]\n\n" \
-" %s -6 [-d] [-q] [-I] [-c <hops>]\n" \
-" [-p <port> | -rp <relay-port>]\n" \
-" [-pf <pid-file>] [--no-pid]\n" \
-" [-s <subscriber-id>]\n" \
-" -l lower0 [ ... -l lowerN]\n" \
-" -u upper0 [ ... -u upperN]\n" \
-" lower (client link): [address%%]interface[#index]\n" \
-" upper (server link): [address%%]interface\n\n" \
-" %s {--version|--help|-h}"
-#else
-#define DHCRELAY_USAGE \
-"Usage: %s [-4] [-d] [-q] [-a] [-D]\n" \
-" [-A <length>] [-c <hops>] [-p <port>]\n" \
-" [-pf <pid-file>] [--no-pid]\n"\
-" [-m append|replace|forward|discard]\n" \
-" [-i interface0 [ ... -i interfaceN]\n" \
-" [-iu interface0 [ ... -iu interfaceN]\n" \
-" [-id interface0 [ ... -id interfaceN]\n" \
-" [-U interface] [-g <ip-address>]\n" \
-" server0 [ ... serverN]\n\n" \
-" %s -6 [-d] [-q] [-I] [-c <hops>] [-p <port>]\n" \
-" [-pf <pid-file>] [--no-pid]\n" \
-" [-s <subscriber-id>]\n" \
-" -l lower0 [ ... -l lowerN]\n" \
-" -u upper0 [ ... -u upperN]\n" \
-" lower (client link): [address%%]interface[#index]\n" \
-" upper (server link): [address%%]interface\n\n" \
-" %s {--version|--help|-h}"
-#endif
-#else /* !DHCPv6 */
-#ifdef RELAY_PORT
-#define DHCRELAY_USAGE \
-"Usage: %s [-d] [-q] [-a] [-D] [-A <length>] [-c <hops>]\n" \
-" [-p <port> | -rp <relay-port>]\n" \
-" [-pf <pid-file>] [--no-pid]\n" \
-" [-m append|replace|forward|discard]\n" \
-" [-i interface0 [ ... -i interfaceN]\n" \
-" [-iu interface0 [ ... -iu interfaceN]\n" \
-" [-id interface0 [ ... -id interfaceN]\n" \
-" [-U interface] [-g <ip-address>]\n" \
-" server0 [ ... serverN]\n\n" \
-" %s {--version|--help|-h}"
-#else
-#define DHCRELAY_USAGE \
-"Usage: %s [-d] [-q] [-a] [-D] [-A <length>] [-c <hops>] [-p <port>]\n" \
-" [-pf <pid-file>] [--no-pid]\n" \
-" [-m append|replace|forward|discard]\n" \
-" [-i interface0 [ ... -i interfaceN]\n" \
-" [-iu interface0 [ ... -iu interfaceN]\n" \
-" [-id interface0 [ ... -id interfaceN]\n" \
-" [-U interface] [-g <ip-address>]\n" \
-" server0 [ ... serverN]\n\n" \
-" %s {--version|--help|-h}"
-#endif
-#endif
-
-/*!
- *
- * \brief Print the generic usage message
- *
- * If the user has provided an incorrect command line print out
- * the description of the command line. The arguments provide
- * a way for the caller to request more specific information about
- * the error be printed as well. Mostly this will be that some
- * command doesn't include its argument.
- *
- * \param sfmt - The basic string and format for the specific error
- * \param sarg - Generally the offending argument from the command line.
- *
- * \return Nothing
- */
-static const char use_noarg[] = "No argument for command: %s";
-#ifdef RELAY_PORT
-static const char use_port_defined[] = "Port already set, %s inappropriate";
-#if !defined (USE_BPF_RECEIVE) && !defined (USE_LPF_RECEIVE)
-static const char bpf_sock_support[] = "Only LPF and BPF are supported: %s";
-#endif
-#endif
-#ifdef DHCPv6
-static const char use_badproto[] = "Protocol already set, %s inappropriate";
-static const char use_v4command[] = "Command not used for DHCPv6: %s";
-static const char use_v6command[] = "Command not used for DHCPv4: %s";
-#endif
-
-static void
-usage(const char *sfmt, const char *sarg) {
- log_info("%s %s", message, PACKAGE_VERSION);
- log_info(copyright);
- log_info(arr);
- log_info(url);
-
- /* If desired print out the specific error message */
-#ifdef PRINT_SPECIFIC_CL_ERRORS
- if (sfmt != NULL)
- log_error(sfmt, sarg);
-#endif
-
- log_fatal(DHCRELAY_USAGE,
-#ifdef DHCPv6
- isc_file_basename(progname),
-#endif
- isc_file_basename(progname),
- isc_file_basename(progname));
-}
-
-int
-main(int argc, char **argv) {
- isc_result_t status;
- struct servent *ent;
- struct server_list *sp = NULL;
- char *service_local = NULL, *service_remote = NULL;
- u_int16_t port_local = 0, port_remote = 0;
- int quiet = 0;
- int fd;
- int i;
-#ifdef RELAY_PORT
- int port_defined = 0;
-#endif
-#ifdef DHCPv6
- struct stream_list *sl = NULL;
- int local_family_set = 0;
-#endif
-
-#ifdef OLD_LOG_NAME
- progname = "dhcrelay";
-#else
- progname = argv[0];
-#endif
-
- /* Make sure that file descriptors 0(stdin), 1,(stdout), and
- 2(stderr) are open. To do this, we assume that when we
- open a file the lowest available file descriptor is used. */
- fd = open("/dev/null", O_RDWR);
- if (fd == 0)
- fd = open("/dev/null", O_RDWR);
- if (fd == 1)
- fd = open("/dev/null", O_RDWR);
- if (fd == 2)
- log_perror = 0; /* No sense logging to /dev/null. */
- else if (fd != -1)
- close(fd);
-
- openlog(isc_file_basename(progname), DHCP_LOG_OPTIONS, LOG_DAEMON);
-
-#if !defined(DEBUG)
- setlogmask(LOG_UPTO(LOG_INFO));
-#endif
-
- /* Parse arguments changing no_daemon */
- for (i = 1; i < argc; i++) {
- if (!strcmp(argv[i], "-d")) {
- no_daemon = 1;
- } else if (!strcmp(argv[i], "--version")) {
- log_info("isc-dhcrelay-%s", PACKAGE_VERSION);
- exit(0);
- } else if (!strcmp(argv[i], "--help") ||
- !strcmp(argv[i], "-h")) {
- log_info(DHCRELAY_USAGE,
-#ifdef DHCPv6
- isc_file_basename(progname),
-#endif
- isc_file_basename(progname),
- isc_file_basename(progname));
- exit(0);
- }
- }
- /* When not forbidden prepare to become a daemon */
- if (!no_daemon) {
- int pid;
-
- if (pipe(dfd) == -1)
- log_fatal("Can't get pipe: %m");
- if ((pid = fork ()) < 0)
- log_fatal("Can't fork daemon: %m");
- if (pid != 0) {
- /* Parent: wait for the child to start */
- int n;
-
- (void) close(dfd[1]);
- do {
- char buf;
-
- n = read(dfd[0], &buf, 1);
- if (n == 1)
- _exit(0);
- } while (n == -1 && errno == EINTR);
- _exit(1);
- }
- /* Child */
- (void) close(dfd[0]);
- }
-
-
- /* Set up the isc and dns library managers */
- status = dhcp_context_create(DHCP_CONTEXT_PRE_DB, NULL, NULL);
- if (status != ISC_R_SUCCESS)
- log_fatal("Can't initialize context: %s",
- isc_result_totext(status));
-
- /* Set up the OMAPI. */
- status = omapi_init();
- if (status != ISC_R_SUCCESS)
- log_fatal("Can't initialize OMAPI: %s",
- isc_result_totext(status));
-
- /* Set up the OMAPI wrappers for the interface object. */
- interface_setup();
-
- for (i = 1; i < argc; i++) {
- if (!strcmp(argv[i], "-4")) {
-#ifdef DHCPv6
- if (local_family_set && (local_family == AF_INET6)) {
- usage(use_badproto, "-4");
- }
- local_family_set = 1;
- local_family = AF_INET;
- } else if (!strcmp(argv[i], "-6")) {
- if (local_family_set && (local_family == AF_INET)) {
- usage(use_badproto, "-6");
- }
- local_family_set = 1;
- local_family = AF_INET6;
-#endif
- } else if (!strcmp(argv[i], "-d")) {
- /* no_daemon = 1; */
- } else if (!strcmp(argv[i], "-q")) {
- quiet = 1;
- quiet_interface_discovery = 1;
- } else if (!strcmp(argv[i], "-p")) {
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
-#ifdef RELAY_PORT
- if (port_defined)
- usage(use_port_defined, argv[i-1]);
- port_defined = 1;
-#endif
- local_port = validate_port(argv[i]);
- log_debug("binding to user-specified port %d",
- ntohs(local_port));
-#ifdef RELAY_PORT
- } else if (!strcmp(argv[i], "-rp")) {
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
- if (port_defined)
- usage(use_port_defined, argv[i-1]);
- port_defined = 1;
- relay_port = validate_port(argv[i]);
- log_debug("binding to user-specified relay port %d",
- ntohs(relay_port));
- add_agent_options = 1;
-#endif
- } else if (!strcmp(argv[i], "-c")) {
- int hcount;
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
- hcount = atoi(argv[i]);
- if (hcount <= 255)
- max_hop_count= hcount;
- else
- usage("Bad hop count to -c: %s", argv[i]);
- } else if (!strcmp(argv[i], "-i")) {
-#ifdef DHCPv6
- if (local_family_set && (local_family == AF_INET6)) {
- usage(use_v4command, argv[i]);
- }
- local_family_set = 1;
- local_family = AF_INET;
-#endif
- if (++i == argc) {
- usage(use_noarg, argv[i-1]);
- }
-
- request_v4_interface(argv[i], INTERFACE_STREAMS);
- } else if (!strcmp(argv[i], "-iu")) {
-#ifdef DHCPv6
- if (local_family_set && (local_family == AF_INET6)) {
- usage(use_v4command, argv[i]);
- }
- local_family_set = 1;
- local_family = AF_INET;
-#endif
- if (++i == argc) {
- usage(use_noarg, argv[i-1]);
- }
-
- request_v4_interface(argv[i], INTERFACE_UPSTREAM);
- } else if (!strcmp(argv[i], "-id")) {
-#ifdef DHCPv6
- if (local_family_set && (local_family == AF_INET6)) {
- usage(use_v4command, argv[i]);
- }
- local_family_set = 1;
- local_family = AF_INET;
-#endif
- if (++i == argc) {
- usage(use_noarg, argv[i-1]);
- }
-
- request_v4_interface(argv[i], INTERFACE_DOWNSTREAM);
- } else if (!strcmp(argv[i], "-a")) {
-#ifdef DHCPv6
- if (local_family_set && (local_family == AF_INET6)) {
- usage(use_v4command, argv[i]);
- }
- local_family_set = 1;
- local_family = AF_INET;
-#endif
- add_agent_options = 1;
- } else if (!strcmp(argv[i], "-A")) {
-#ifdef DHCPv6
- if (local_family_set && (local_family == AF_INET6)) {
- usage(use_v4command, argv[i]);
- }
- local_family_set = 1;
- local_family = AF_INET;
-#endif
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
-
- dhcp_max_agent_option_packet_length = atoi(argv[i]);
-
- if (dhcp_max_agent_option_packet_length > DHCP_MTU_MAX)
- log_fatal("%s: packet length exceeds "
- "longest possible MTU\n",
- argv[i]);
- } else if (!strcmp(argv[i], "-m")) {
-#ifdef DHCPv6
- if (local_family_set && (local_family == AF_INET6)) {
- usage(use_v4command, argv[i]);
- }
- local_family_set = 1;
- local_family = AF_INET;
-#endif
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
- if (!strcasecmp(argv[i], "append")) {
- agent_relay_mode = forward_and_append;
- } else if (!strcasecmp(argv[i], "replace")) {
- agent_relay_mode = forward_and_replace;
- } else if (!strcasecmp(argv[i], "forward")) {
- agent_relay_mode = forward_untouched;
- } else if (!strcasecmp(argv[i], "discard")) {
- agent_relay_mode = discard;
- } else
- usage("Unknown argument to -m: %s", argv[i]);
- } else if (!strcmp(argv [i], "-U")) {
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
-
- if (uplink) {
- usage("more than one uplink (-U) specified: %s"
- ,argv[i]);
- }
-
- /* Allocate the uplink interface */
- status = interface_allocate(&uplink, MDL);
- if (status != ISC_R_SUCCESS) {
- log_fatal("%s: uplink interface_allocate: %s",
- argv[i], isc_result_totext(status));
- }
-
- if (strlen(argv[i]) >= sizeof(uplink->name)) {
- log_fatal("%s: uplink name too long,"
- " it cannot exceed: %ld characters",
- argv[i], (long)(sizeof(uplink->name) - 1));
- }
-
- uplink->name[sizeof(uplink->name) - 1] = 0x00;
- strncpy(uplink->name, argv[i],
- sizeof(uplink->name) - 1);
- interface_snorf(uplink, (INTERFACE_REQUESTED |
- INTERFACE_STREAMS));
-
- /* Turn on -a, in case they don't do so explicitly */
- add_agent_options = 1;
- add_rfc3527_suboption = 1;
- } else if (!strcmp(argv[i], "-g")) {
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
-#ifdef DHCPv6
- if (local_family_set && (local_family == AF_INET6)) {
- usage(use_v4command, argv[i]);
- }
- local_family_set = 1;
- local_family = AF_INET;
-#endif
- if (inet_pton(AF_INET, argv[i], &gw) <= 0) {
- usage("Invalid gateway address '%s'", argv[i]);
- } else {
- use_fake_gw = ISC_TRUE;
- }
- } else if (!strcmp(argv[i], "-D")) {
-#ifdef DHCPv6
- if (local_family_set && (local_family == AF_INET6)) {
- usage(use_v4command, argv[i]);
- }
- local_family_set = 1;
- local_family = AF_INET;
-#endif
- drop_agent_mismatches = 1;
-#ifdef DHCPv6
- } else if (!strcmp(argv[i], "-I")) {
- if (local_family_set && (local_family == AF_INET)) {
- usage(use_v6command, argv[i]);
- }
- local_family_set = 1;
- local_family = AF_INET6;
- use_if_id = ISC_TRUE;
- } else if (!strcmp(argv[i], "-l")) {
- if (local_family_set && (local_family == AF_INET)) {
- usage(use_v6command, argv[i]);
- }
- local_family_set = 1;
- local_family = AF_INET6;
- if (downstreams != NULL)
- use_if_id = ISC_TRUE;
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
- sl = parse_downstream(argv[i]);
- sl->next = downstreams;
- downstreams = sl;
- } else if (!strcmp(argv[i], "-u")) {
- if (local_family_set && (local_family == AF_INET)) {
- usage(use_v6command, argv[i]);
- }
- local_family_set = 1;
- local_family = AF_INET6;
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
- sl = parse_upstream(argv[i]);
- sl->next = upstreams;
- upstreams = sl;
- } else if (!strcmp(argv[i], "-s")) {
- if (local_family_set && (local_family == AF_INET)) {
- usage(use_v6command, argv[i]);
- }
- local_family_set = 1;
- local_family = AF_INET6;
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
- dhcrelay_sub_id = argv[i];
-#endif
- } else if (!strcmp(argv[i], "-pf")) {
- if (++i == argc)
- usage(use_noarg, argv[i-1]);
- path_dhcrelay_pid = argv[i];
- no_dhcrelay_pid = ISC_TRUE;
- } else if (!strcmp(argv[i], "--no-pid")) {
- no_pid_file = ISC_TRUE;
- } else if (argv[i][0] == '-') {
- usage("Unknown command: %s", argv[i]);
- } else {
- struct hostent *he;
- struct in_addr ia, *iap = NULL;
-
-#ifdef DHCPv6
- if (local_family_set && (local_family == AF_INET6)) {
- usage(use_v4command, argv[i]);
- }
- local_family_set = 1;
- local_family = AF_INET;
-#endif
- if (inet_aton(argv[i], &ia)) {
- iap = &ia;
- } else {
- he = gethostbyname(argv[i]);
- if (!he) {
- log_error("%s: host unknown", argv[i]);
- } else {
- iap = ((struct in_addr *)
- he->h_addr_list[0]);
- }
- }
-
- if (iap) {
- sp = ((struct server_list *)
- dmalloc(sizeof *sp, MDL));
- if (!sp)
- log_fatal("no memory for server.\n");
- sp->next = servers;
- servers = sp;
- memcpy(&sp->to.sin_addr, iap, sizeof *iap);
- }
- }
- }
-
-#if defined(RELAY_PORT) && \
- !defined (USE_BPF_RECEIVE) && !defined (USE_LPF_RECEIVE)
- if (relay_port && (local_family == AF_INET))
- usage(bpf_sock_support, "-rp");
-#endif
-
- /*
- * If the user didn't specify a pid file directly
- * find one from environment variables or defaults
- */
- if (no_dhcrelay_pid == ISC_FALSE) {
- if (local_family == AF_INET) {
- path_dhcrelay_pid = getenv("PATH_DHCRELAY_PID");
- if (path_dhcrelay_pid == NULL)
- path_dhcrelay_pid = _PATH_DHCRELAY_PID;
- }
-#ifdef DHCPv6
- else {
- path_dhcrelay_pid = getenv("PATH_DHCRELAY6_PID");
- if (path_dhcrelay_pid == NULL)
- path_dhcrelay_pid = _PATH_DHCRELAY6_PID;
- }
-#endif
- }
-
- if (!quiet) {
- log_info("%s %s", message, PACKAGE_VERSION);
- log_info(copyright);
- log_info(arr);
- log_info(url);
- } else
- log_perror = 0;
-
- /* Set default port */
- if (local_family == AF_INET) {
- service_local = "bootps";
- service_remote = "bootpc";
- port_local = htons(67);
- port_remote = htons(68);
- }
-#ifdef DHCPv6
- else {
- service_local = "dhcpv6-server";
- service_remote = "dhcpv6-client";
- port_local = htons(547);
- port_remote = htons(546);
- }
-#endif
-
- if (!local_port) {
- ent = getservbyname(service_local, "udp");
- if (ent)
- local_port = ent->s_port;
- else
- local_port = port_local;
-
- ent = getservbyname(service_remote, "udp");
- if (ent)
- remote_port = ent->s_port;
- else
- remote_port = port_remote;
-
- endservent();
- }
-
- if (local_family == AF_INET) {
- /* We need at least one server */
- if (servers == NULL) {
- log_fatal("No servers specified.");
- }
-
-
- /* Set up the server sockaddrs. */
- for (sp = servers; sp; sp = sp->next) {
- sp->to.sin_port = local_port;
- sp->to.sin_family = AF_INET;
-#ifdef HAVE_SA_LEN
- sp->to.sin_len = sizeof sp->to;
-#endif
- }
- }
-#ifdef DHCPv6
- else {
- unsigned code;
-
- /* We need at least one upstream and one downstream interface */
- if (upstreams == NULL || downstreams == NULL) {
- log_info("Must specify at least one lower "
- "and one upper interface.\n");
- usage(NULL, NULL);
- }
-
- /* Set up the initial dhcp option universe. */
- initialize_common_option_spaces();
-
- /* Check requested options. */
- code = D6O_RELAY_MSG;
- if (!option_code_hash_lookup(&requested_opts[0],
- dhcpv6_universe.code_hash,
- &code, 0, MDL))
- log_fatal("Unable to find the RELAY_MSG "
- "option definition.");
- code = D6O_INTERFACE_ID;
- if (!option_code_hash_lookup(&requested_opts[1],
- dhcpv6_universe.code_hash,
- &code, 0, MDL))
- log_fatal("Unable to find the INTERFACE_ID "
- "option definition.");
- }
-#endif
-
- /* Get the current time... */
- gettimeofday(&cur_tv, NULL);
-
- /* Discover all the network interfaces. */
- discover_interfaces(DISCOVER_RELAY);
-
-#ifdef DHCPv6
- if (local_family == AF_INET6)
- setup_streams();
-#endif
-
- /* Become a daemon... */
- if (!no_daemon) {
- char buf = 0;
- FILE *pf;
- int pfdesc;
-
- log_perror = 0;
-
- /* Signal parent we started successfully. */
- if (dfd[0] != -1 && dfd[1] != -1) {
- if (write(dfd[1], &buf, 1) != 1)
- log_fatal("write to parent: %m");
- (void) close(dfd[1]);
- dfd[0] = dfd[1] = -1;
- }
-
- /* Create the pid file. */
- if (no_pid_file == ISC_FALSE) {
- pfdesc = open(path_dhcrelay_pid,
- O_CREAT | O_TRUNC | O_WRONLY, 0644);
-
- if (pfdesc < 0) {
- log_error("Can't create %s: %m",
- path_dhcrelay_pid);
- } else {
- pf = fdopen(pfdesc, "w");
- if (!pf)
- log_error("Can't fdopen %s: %m",
- path_dhcrelay_pid);
- else {
- fprintf(pf, "%ld\n",(long)getpid());
- fclose(pf);
- }
- }
- }
-
- (void) close(0);
- (void) close(1);
- (void) close(2);
- (void) setsid();
-
- IGNORE_RET (chdir("/"));
- }
-
- /* Set up the packet handler... */
- if (local_family == AF_INET)
- bootp_packet_handler = do_relay4;
-#ifdef DHCPv6
- else
- dhcpv6_packet_handler = do_packet6;
-#endif
-
-#if defined(ENABLE_GENTLE_SHUTDOWN)
- /* no signal handlers until we deal with the side effects */
- /* install signal handlers */
- signal(SIGINT, dhcp_signal_handler); /* control-c */
- signal(SIGTERM, dhcp_signal_handler); /* kill */
-#endif
-
- /* Start dispatching packets and timeouts... */
- dispatch();
-
- /* In fact dispatch() never returns. */
- return (0);
-}
-
-static void
-do_relay4(struct interface_info *ip, struct dhcp_packet *packet,
- unsigned int length, unsigned int from_port, struct iaddr from,
- struct hardware *hfrom) {
- struct server_list *sp;
- struct sockaddr_in to;
- struct interface_info *out;
- struct hardware hto, *htop;
-
- if (packet->hlen > sizeof packet->chaddr) {
- log_info("Discarding packet with invalid hlen, received on "
- "%s interface.", ip->name);
- return;
- }
- if (ip->address_count < 1 || ip->addresses == NULL) {
- log_info("Discarding packet received on %s interface that "
- "has no IPv4 address assigned.", ip->name);
- return;
- }
-
- /* Find the interface that corresponds to the giaddr
- in the packet. */
- if (packet->giaddr.s_addr) {
- for (out = interfaces; out; out = out->next) {
- int i;
-
- for (i = 0 ; i < out->address_count ; i++ ) {
- if (out->addresses[i].s_addr ==
- packet->giaddr.s_addr) {
- i = -1;
- break;
- }
- }
-
- if (i == -1)
- break;
- }
- } else {
- out = NULL;
- }
-
- /* If it's a bootreply, forward it to the client. */
- if (packet->op == BOOTREPLY) {
- if (!(ip->flags & INTERFACE_UPSTREAM)) {
- log_debug("Dropping reply received on %s", ip->name);
- return;
- }
-
- log_debug("BOOTREPLY giaddr: %s\n", inet_ntoa(packet->giaddr));
- if (!(packet->flags & htons(BOOTP_BROADCAST)) &&
- can_unicast_without_arp(out)) {
- to.sin_addr = packet->yiaddr;
- to.sin_port = remote_port;
-
- /* and hardware address is not broadcast */
- htop = &hto;
- } else {
- to.sin_addr.s_addr = htonl(INADDR_BROADCAST);
- to.sin_port = remote_port;
-
- /* hardware address is broadcast */
- htop = NULL;
- }
- to.sin_family = AF_INET;
-#ifdef HAVE_SA_LEN
- to.sin_len = sizeof to;
-#endif
-
- memcpy(&hto.hbuf[1], packet->chaddr, packet->hlen);
- hto.hbuf[0] = packet->htype;
- hto.hlen = packet->hlen + 1;
-
- /* Wipe out the agent relay options and, if possible, figure
- out which interface to use based on the contents of the
- option that we put on the request to which the server is
- replying. */
- if (!(length =
- strip_relay_agent_options(ip, &out, packet, length)))
- return;
-
- if (!out) {
- log_error("Packet to bogus giaddr %s.\n",
- inet_ntoa(packet->giaddr));
- ++bogus_giaddr_drops;
- return;
- }
-
- if (use_fake_gw) {
- packet->giaddr = gw;
- }
-
- if (send_packet(out, NULL, packet, length, out->addresses[0],
- &to, htop) < 0) {
- ++server_packet_errors;
- } else {
- log_debug("Forwarded BOOTREPLY for %s to %s",
- print_hw_addr(packet->htype, packet->hlen,
- packet->chaddr),
- inet_ntoa(to.sin_addr));
-
- ++server_packets_relayed;
- }
- return;
- }
-
- /* If giaddr matches one of our addresses, ignore the packet -
- we just sent it. */
- if (out)
- return;
-
- if (!(ip->flags & INTERFACE_DOWNSTREAM)) {
- log_debug("Dropping request received on %s", ip->name);
- return;
- }
-
- /* Add relay agent options if indicated. If something goes wrong,
- * drop the packet. Note this may set packet->giaddr if RFC3527
- * is enabled. */
- if (!(length = add_relay_agent_options(ip, packet, length,
- ip->addresses[0])))
- return;
-
- /* If giaddr is not already set, Set it so the server can
- figure out what net it's from and so that we can later
- forward the response to the correct net. If it's already
- set, the response will be sent directly to the relay agent
- that set giaddr, so we won't see it. */
- if (!packet->giaddr.s_addr)
- packet->giaddr = ip->addresses[0];
- if (packet->hops < max_hop_count)
- packet->hops = packet->hops + 1;
- else
- return;
-
- /* Otherwise, it's a BOOTREQUEST, so forward it to all the
- servers. */
- for (sp = servers; sp; sp = sp->next) {
- if (send_packet((fallback_interface
- ? fallback_interface : interfaces),
- NULL, packet, length, ip->addresses[0],
- &sp->to, NULL) < 0) {
- ++client_packet_errors;
- } else {
- log_debug("Forwarded BOOTREQUEST for %s to %s",
- print_hw_addr(packet->htype, packet->hlen,
- packet->chaddr),
- inet_ntoa(sp->to.sin_addr));
- ++client_packets_relayed;
- }
- }
-
-}
-
-#endif /* UNIT_TEST */
-
-/* Strip any Relay Agent Information options from the DHCP packet
- option buffer. If there is a circuit ID suboption, look up the
- outgoing interface based upon it. */
-
-int
-strip_relay_agent_options(struct interface_info *in,
- struct interface_info **out,
- struct dhcp_packet *packet,
- unsigned length) {
- int is_dhcp = 0;
- u_int8_t *op, *nextop, *sp, *max;
- int good_agent_option = 0;
- int status;
-
- /* If we're not adding agent options to packets, we're not taking
- them out either. */
- if (!add_agent_options)
- return (length);
-
- /* If there's no cookie, it's a bootp packet, so we should just
- forward it unchanged. */
- if (memcmp(packet->options, DHCP_OPTIONS_COOKIE, 4))
- return (length);
-
- max = ((u_int8_t *)packet) + length;
- sp = op = &packet->options[4];
-
- while (op < max) {
- switch(*op) {
- /* Skip padding... */
- case DHO_PAD:
- if (sp != op)
- *sp = *op;
- ++op;
- ++sp;
- continue;
-
- /* If we see a message type, it's a DHCP packet. */
- case DHO_DHCP_MESSAGE_TYPE:
- is_dhcp = 1;
- goto skip;
- break;
-
- /* Quit immediately if we hit an End option. */
- case DHO_END:
- if (sp != op)
- *sp++ = *op++;
- goto out;
-
- case DHO_DHCP_AGENT_OPTIONS:
- /* We shouldn't see a relay agent option in a
- packet before we've seen the DHCP packet type,
- but if we do, we have to leave it alone. */
- if (!is_dhcp)
- goto skip;
-
- /* Do not process an agent option if it exceeds the
- * buffer. Fail this packet.
- */
- nextop = op + op[1] + 2;
- if (nextop > max)
- return (0);
-
- status = find_interface_by_agent_option(packet,
- out, op + 2,
- op[1]);
- if (status == -1 && drop_agent_mismatches)
- return (0);
- if (status)
- good_agent_option = 1;
- op = nextop;
- break;
-
- skip:
- /* Skip over other options. */
- default:
- /* Fail if processing this option will exceed the
- * buffer(op[1] is malformed).
- */
- nextop = op + op[1] + 2;
- if (nextop > max)
- return (0);
-
- if (sp != op) {
- size_t mlen = op[1] + 2;
- memmove(sp, op, mlen);
- sp += mlen;
- if (sp > max) {
- return (0);
- }
-
- op = nextop;
- } else
- op = sp = nextop;
-
- break;
- }
- }
- out:
-
- /* If it's not a DHCP packet, we're not supposed to touch it. */
- if (!is_dhcp)
- return (length);
-
- /* If none of the agent options we found matched, or if we didn't
- find any agent options, count this packet as not having any
- matching agent options, and if we're relying on agent options
- to determine the outgoing interface, drop the packet. */
-
- if (!good_agent_option) {
- ++missing_agent_option;
- if (drop_agent_mismatches)
- return (0);
- }
-
- /* Adjust the length... */
- if (sp != op) {
- length = sp -((u_int8_t *)packet);
-
- /* Make sure the packet isn't short(this is unlikely,
- but WTH) */
- if (length < BOOTP_MIN_LEN) {
- memset(sp, DHO_PAD, BOOTP_MIN_LEN - length);
- length = BOOTP_MIN_LEN;
- }
- }
- return (length);
-}
-
-
-/* Find an interface that matches the circuit ID specified in the
- Relay Agent Information option. If one is found, store it through
- the pointer given; otherwise, leave the existing pointer alone.
-
- We actually deviate somewhat from the current specification here:
- if the option buffer is corrupt, we suggest that the caller not
- respond to this packet. If the circuit ID doesn't match any known
- interface, we suggest that the caller to drop the packet. Only if
- we find a circuit ID that matches an existing interface do we tell
- the caller to go ahead and process the packet. */
-
-int
-find_interface_by_agent_option(struct dhcp_packet *packet,
- struct interface_info **out,
- u_int8_t *buf, int len) {
- int i = 0;
- u_int8_t *circuit_id = 0;
- unsigned circuit_id_len = 0;
- struct interface_info *ip;
-
- while (i < len) {
- /* If the next agent option overflows the end of the
- packet, the agent option buffer is corrupt. */
- if (i + 1 == len ||
- i + buf[i + 1] + 2 > len) {
- ++corrupt_agent_options;
- return (-1);
- }
- switch(buf[i]) {
- /* Remember where the circuit ID is... */
- case RAI_CIRCUIT_ID:
- circuit_id = &buf[i + 2];
- circuit_id_len = buf[i + 1];
- i += circuit_id_len + 2;
- continue;
-
- default:
- i += buf[i + 1] + 2;
- break;
- }
- }
-
- /* If there's no circuit ID, it's not really ours, tell the caller
- it's no good. */
- if (!circuit_id) {
- ++missing_circuit_id;
- return (-1);
- }
-
- /* Scan the interface list looking for an interface whose
- name matches the one specified in circuit_id. */
-
- for (ip = interfaces; ip; ip = ip->next) {
- if (ip->circuit_id &&
- ip->circuit_id_len == circuit_id_len &&
- !memcmp(ip->circuit_id, circuit_id, circuit_id_len))
- break;
- }
-
- /* If we got a match, use it. */
- if (ip) {
- *out = ip;
- return (1);
- }
-
- /* If we didn't get a match, the circuit ID was bogus. */
- ++bad_circuit_id;
- return (-1);
-}
-
-/*
- * Examine a packet to see if it's a candidate to have a Relay
- * Agent Information option tacked onto its tail. If it is, tack
- * the option on.
- */
-int
-add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet,
- unsigned length, struct in_addr giaddr) {
- int is_dhcp = 0, mms;
- unsigned optlen;
- u_int8_t *op, *nextop, *sp, *max, *end_pad = NULL;
- int adding_link_select;
-
- /* If we're not adding agent options to packets, we can skip
- this. */
- if (!add_agent_options)
- return (length);
-
- /* If there's no cookie, it's a bootp packet, so we should just
- forward it unchanged. */
- if (memcmp(packet->options, DHCP_OPTIONS_COOKIE, 4))
- return (length);
-
- max = ((u_int8_t *)packet) + dhcp_max_agent_option_packet_length;
-
- /* Add link selection suboption if enabled and we're the first relay */
- adding_link_select = (add_rfc3527_suboption
- && (packet->giaddr.s_addr == 0));
-
- /* Commence processing after the cookie. */
- sp = op = &packet->options[4];
-
- while (op < max) {
- switch(*op) {
- /* Skip padding... */
- case DHO_PAD:
- /* Remember the first pad byte so we can commandeer
- * padded space.
- *
- * XXX: Is this really a good idea? Sure, we can
- * seemingly reduce the packet while we're looking,
- * but if the packet was signed by the client then
- * this padding is part of the checksum(RFC3118),
- * and its nonpresence would break authentication.
- */
- if (end_pad == NULL)
- end_pad = sp;
-
- if (sp != op)
- *sp++ = *op++;
- else
- sp = ++op;
-
- continue;
-
- /* If we see a message type, it's a DHCP packet. */
- case DHO_DHCP_MESSAGE_TYPE:
- is_dhcp = 1;
- goto skip;
-
- /*
- * If there's a maximum message size option, we
- * should pay attention to it
- */
- case DHO_DHCP_MAX_MESSAGE_SIZE:
- mms = ntohs(*(op + 2));
- if (mms < dhcp_max_agent_option_packet_length &&
- mms >= DHCP_MTU_MIN)
- max = ((u_int8_t *)packet) + mms;
- goto skip;
-
- /* Quit immediately if we hit an End option. */
- case DHO_END:
- goto out;
-
- case DHO_DHCP_AGENT_OPTIONS:
- /* We shouldn't see a relay agent option in a
- packet before we've seen the DHCP packet type,
- but if we do, we have to leave it alone. */
- if (!is_dhcp)
- goto skip;
-
- end_pad = NULL;
-
- /* There's already a Relay Agent Information option
- in this packet. How embarrassing. Decide what
- to do based on the mode the user specified. */
-
- switch(agent_relay_mode) {
- case forward_and_append:
- goto skip;
- case forward_untouched:
- return (length);
- case discard:
- return (0);
- case forward_and_replace:
- default:
- break;
- }
-
- /* Skip over the agent option and start copying
- if we aren't copying already. */
- op += op[1] + 2;
- break;
-
- skip:
- /* Skip over other options. */
- default:
- /* Fail if processing this option will exceed the
- * buffer(op[1] is malformed).
- */
- nextop = op + op[1] + 2;
- if (nextop > max)
- return (0);
-
- end_pad = NULL;
-
- if (sp != op) {
- size_t mlen = op[1] + 2;
- memmove(sp, op, mlen);
- sp += mlen;
- if (sp > max) {
- return (0);
- }
-
- op = nextop;
- } else
- op = sp = nextop;
-
- break;
- }
- }
- out:
-
- /* If it's not a DHCP packet, we're not supposed to touch it. */
- if (!is_dhcp)
- return (length);
-
- /* If the packet was padded out, we can store the agent option
- at the beginning of the padding. */
-
- if (end_pad != NULL)
- sp = end_pad;
-
-#if 0
- /* Remember where the end of the packet was after parsing
- it. */
- op = sp;
-#endif
-
- /* Sanity check. Had better not ever happen. */
- if ((ip->circuit_id_len > 255) ||(ip->circuit_id_len < 1))
- log_fatal("Circuit ID length %d out of range [1-255] on "
- "%s\n", ip->circuit_id_len, ip->name);
- optlen = ip->circuit_id_len + 2; /* RAI_CIRCUIT_ID + len */
-
- if (ip->remote_id) {
- if (ip->remote_id_len > 255 || ip->remote_id_len < 1)
- log_fatal("Remote ID length %d out of range [1-255] "
- "on %s\n", ip->remote_id_len, ip->name);
- optlen += ip->remote_id_len + 2; /* RAI_REMOTE_ID + len */
- }
-
- if (adding_link_select) {
- optlen += 6;
- }
-
-#ifdef RELAY_PORT
- if (relay_port) {
- optlen += 2;
- }
-#endif
-
- /* We do not support relay option fragmenting(multiple options to
- * support an option data exceeding 255 bytes).
- */
- if ((optlen < 3) ||(optlen > 255))
- log_fatal("Total agent option length(%u) out of range "
- "[3 - 255] on %s\n", optlen, ip->name);
-
- /*
- * Is there room for the option, its code+len, and DHO_END?
- * If not, forward without adding the option.
- */
- if (max - sp >= optlen + 3) {
- log_debug("Adding %d-byte relay agent option", optlen + 3);
-
- /* Okay, cons up *our* Relay Agent Information option. */
- *sp++ = DHO_DHCP_AGENT_OPTIONS;
- *sp++ = optlen;
-
- /* Copy in the circuit id... */
- *sp++ = RAI_CIRCUIT_ID;
- *sp++ = ip->circuit_id_len;
- memcpy(sp, ip->circuit_id, ip->circuit_id_len);
- sp += ip->circuit_id_len;
-
- /* Copy in remote ID... */
- if (ip->remote_id) {
- *sp++ = RAI_REMOTE_ID;
- *sp++ = ip->remote_id_len;
- memcpy(sp, ip->remote_id, ip->remote_id_len);
- sp += ip->remote_id_len;
- }
-
- /* RFC3527: Use the inbound packet's interface address in
- * the link selection suboption and set the outbound giaddr
- * to the uplink address. */
- if (adding_link_select) {
- *sp++ = RAI_LINK_SELECT;
- *sp++ = 4u;
- memcpy(sp, &giaddr.s_addr, 4);
- sp += 4;
- packet->giaddr = uplink->addresses[0];
- log_debug ("Adding link selection suboption"
- " with addr: %s", inet_ntoa(giaddr));
- }
-
-#ifdef RELAY_PORT
- /* draft-ietf-dhc-relay-port-10.txt section 5.1 */
- if (relay_port) {
- *sp++ = RAI_RELAY_PORT;
- *sp++ = 0u;
- }
-#endif
- } else {
- ++agent_option_errors;
- log_error("No room in packet (used %d of %d) "
- "for %d-byte relay agent option: omitted",
- (int) (sp - ((u_int8_t *) packet)),
- (int) (max - ((u_int8_t *) packet)),
- optlen + 3);
- }
-
- /*
- * Deposit an END option unless the packet is full (shouldn't
- * be possible).
- */
- if (sp < max)
- *sp++ = DHO_END;
-
- /* Recalculate total packet length. */
- length = sp -((u_int8_t *)packet);
-
- /* Make sure the packet isn't short(this is unlikely, but WTH) */
- if (length < BOOTP_MIN_LEN) {
- memset(sp, DHO_PAD, BOOTP_MIN_LEN - length);
- return (BOOTP_MIN_LEN);
- }
-
- return (length);
-}
-
-#ifdef DHCPv6
-#ifndef UNIT_TEST
-/*
- * Parse a downstream argument: [address%]interface[#index].
- */
-static struct stream_list *
-parse_downstream(char *arg) {
- struct stream_list *dp, *up;
- struct interface_info *ifp = NULL;
- char *ifname, *addr, *iid;
- isc_result_t status;
-
- if (!supports_multiple_interfaces(ifp) &&
- (downstreams != NULL))
- log_fatal("No support for multiple interfaces.");
-
- /* Decode the argument. */
- ifname = strchr(arg, '%');
- if (ifname == NULL) {
- ifname = arg;
- addr = NULL;
- } else {
- *ifname++ = '\0';
- addr = arg;
- }
- iid = strchr(ifname, '#');
- if (iid != NULL) {
- *iid++ = '\0';
- }
- if (strlen(ifname) >= sizeof(ifp->name)) {
- usage("Interface name '%s' too long", ifname);
- }
-
- /* Don't declare twice. */
- for (dp = downstreams; dp; dp = dp->next) {
- if (strcmp(ifname, dp->ifp->name) == 0)
- log_fatal("Down interface '%s' declared twice.",
- ifname);
- }
-
- /* Share with up side? */
- for (up = upstreams; up; up = up->next) {
- if (strcmp(ifname, up->ifp->name) == 0) {
- log_info("parse_downstream: Interface '%s' is "
- "both down and up.", ifname);
- ifp = up->ifp;
- break;
- }
- }
-
- /* New interface. */
- if (ifp == NULL) {
- status = interface_allocate(&ifp, MDL);
- if (status != ISC_R_SUCCESS)
- log_fatal("%s: interface_allocate: %s",
- arg, isc_result_totext(status));
- strcpy(ifp->name, ifname);
- if (interfaces) {
- interface_reference(&ifp->next, interfaces, MDL);
- interface_dereference(&interfaces, MDL);
- }
- interface_reference(&interfaces, ifp, MDL);
- }
- ifp->flags |= INTERFACE_REQUESTED | INTERFACE_DOWNSTREAM;
-
- /* New downstream. */
- dp = (struct stream_list *) dmalloc(sizeof(*dp), MDL);
- if (!dp)
- log_fatal("No memory for downstream.");
- dp->ifp = ifp;
- if (iid != NULL) {
- dp->id = atoi(iid);
- } else {
- dp->id = -1;
- }
- /* !addr case handled by setup. */
- if (addr && (inet_pton(AF_INET6, addr, &dp->link.sin6_addr) <= 0))
- log_fatal("Bad link address '%s'", addr);
-
- return dp;
-}
-
-/*
- * Parse an upstream argument: [address]%interface.
- */
-static struct stream_list *
-parse_upstream(char *arg) {
- struct stream_list *up, *dp;
- struct interface_info *ifp = NULL;
- char *ifname, *addr;
- isc_result_t status;
-
- /* Decode the argument. */
- ifname = strchr(arg, '%');
- if (ifname == NULL) {
- ifname = arg;
- addr = All_DHCP_Servers;
- } else {
- *ifname++ = '\0';
- addr = arg;
- }
- if (strlen(ifname) >= sizeof(ifp->name)) {
- log_fatal("Interface name '%s' too long", ifname);
- }
-
- /* Shared up interface? */
- for (up = upstreams; up; up = up->next) {
- if (strcmp(ifname, up->ifp->name) == 0) {
- ifp = up->ifp;
- break;
- }
- }
- for (dp = downstreams; dp; dp = dp->next) {
- if (strcmp(ifname, dp->ifp->name) == 0) {
- log_info("parse_upstream: Interface '%s' is "
- "both down and up.", ifname);
- ifp = dp->ifp;
- break;
- }
- }
-
- /* New interface. */
- if (ifp == NULL) {
- status = interface_allocate(&ifp, MDL);
- if (status != ISC_R_SUCCESS)
- log_fatal("%s: interface_allocate: %s",
- arg, isc_result_totext(status));
- strcpy(ifp->name, ifname);
- if (interfaces) {
- interface_reference(&ifp->next, interfaces, MDL);
- interface_dereference(&interfaces, MDL);
- }
- interface_reference(&interfaces, ifp, MDL);
- }
- ifp->flags |= INTERFACE_REQUESTED | INTERFACE_UPSTREAM;
-
- /* New upstream. */
- up = (struct stream_list *) dmalloc(sizeof(*up), MDL);
- if (up == NULL)
- log_fatal("No memory for upstream.");
-
- up->ifp = ifp;
-
- if (inet_pton(AF_INET6, addr, &up->link.sin6_addr) <= 0)
- log_fatal("Bad address %s", addr);
-
- return up;
-}
-
-/*
- * Setup downstream interfaces.
- */
-static void
-setup_streams(void) {
- struct stream_list *dp, *up;
- int i;
- isc_boolean_t link_is_set;
-
- for (dp = downstreams; dp; dp = dp->next) {
- /* Check interface */
- if (dp->ifp->v6address_count == 0)
- log_fatal("Interface '%s' has no IPv6 addresses.",
- dp->ifp->name);
-
- /* Check/set link. */
- if (IN6_IS_ADDR_UNSPECIFIED(&dp->link.sin6_addr))
- link_is_set = ISC_FALSE;
- else
- link_is_set = ISC_TRUE;
- for (i = 0; i < dp->ifp->v6address_count; i++) {
- if (IN6_IS_ADDR_LINKLOCAL(&dp->ifp->v6addresses[i]))
- continue;
- if (!link_is_set)
- break;
- if (!memcmp(&dp->ifp->v6addresses[i],
- &dp->link.sin6_addr,
- sizeof(dp->link.sin6_addr)))
- break;
- }
- if (i == dp->ifp->v6address_count)
- log_fatal("Interface %s does not have global IPv6 "
- "address assigned.", dp->ifp->name);
- if (!link_is_set)
- memcpy(&dp->link.sin6_addr,
- &dp->ifp->v6addresses[i],
- sizeof(dp->link.sin6_addr));
-
- /* Set interface-id. */
- if (dp->id == -1)
- dp->id = dp->ifp->index;
- }
-
- for (up = upstreams; up; up = up->next) {
- up->link.sin6_port = local_port;
- up->link.sin6_family = AF_INET6;
-#ifdef HAVE_SA_LEN
- up->link.sin6_len = sizeof(up->link);
-#endif
-
- if (up->ifp->v6address_count == 0)
- log_fatal("Interface '%s' has no IPv6 addresses.",
- up->ifp->name);
-
- /* RFC 3315 Sec 20 - "If the relay agent relays messages to
- * the All_DHCP_Servers address or other multicast addresses,
- * it sets the Hop Limit field to 32." */
- if (IN6_IS_ADDR_MULTICAST(&up->link.sin6_addr)) {
- set_multicast_hop_limit(up->ifp, HOP_COUNT_LIMIT);
- }
- }
-}
-
-/*
- * Add DHCPv6 agent options here.
- */
-static const int required_forw_opts[] = {
- D6O_INTERFACE_ID,
- D6O_SUBSCRIBER_ID,
-#if defined(RELAY_PORT)
- D6O_RELAY_SOURCE_PORT,
-#endif
- D6O_RELAY_MSG,
- 0
-};
-
-/*
- * Process a packet upwards, i.e., from client to server.
- */
-static void
-process_up6(struct packet *packet, struct stream_list *dp) {
- char forw_data[65535];
- unsigned cursor;
- struct dhcpv6_relay_packet *relay;
- struct option_state *opts;
- struct stream_list *up;
- u_int16_t relay_client_port = 0;
-
- /* Check if the message should be relayed to the server. */
- switch (packet->dhcpv6_msg_type) {
- case DHCPV6_SOLICIT:
- case DHCPV6_REQUEST:
- case DHCPV6_CONFIRM:
- case DHCPV6_RENEW:
- case DHCPV6_REBIND:
- case DHCPV6_RELEASE:
- case DHCPV6_DECLINE:
- case DHCPV6_INFORMATION_REQUEST:
- case DHCPV6_RELAY_FORW:
- case DHCPV6_LEASEQUERY:
- case DHCPV6_DHCPV4_QUERY:
- log_info("Relaying %s from %s port %d going up.",
- dhcpv6_type_names[packet->dhcpv6_msg_type],
- piaddr(packet->client_addr),
- ntohs(packet->client_port));
- break;
-
- case DHCPV6_ADVERTISE:
- case DHCPV6_REPLY:
- case DHCPV6_RECONFIGURE:
- case DHCPV6_RELAY_REPL:
- case DHCPV6_LEASEQUERY_REPLY:
- case DHCPV6_DHCPV4_RESPONSE:
- log_info("Discarding %s from %s port %d going up.",
- dhcpv6_type_names[packet->dhcpv6_msg_type],
- piaddr(packet->client_addr),
- ntohs(packet->client_port));
- return;
-
- default:
- log_info("Unknown %d type from %s port %d going up.",
- packet->dhcpv6_msg_type,
- piaddr(packet->client_addr),
- ntohs(packet->client_port));
- return;
- }
-
- /* Build the relay-forward header. */
- relay = (struct dhcpv6_relay_packet *) forw_data;
- cursor = offsetof(struct dhcpv6_relay_packet, options);
- relay->msg_type = DHCPV6_RELAY_FORW;
- if (packet->dhcpv6_msg_type == DHCPV6_RELAY_FORW) {
- if (packet->dhcpv6_hop_count >= max_hop_count) {
- log_info("Hop count exceeded,");
- return;
- }
- relay->hop_count = packet->dhcpv6_hop_count + 1;
- if (dp) {
- memcpy(&relay->link_address, &dp->link.sin6_addr, 16);
- } else {
- /* On smart relay add: && !global. */
- if (!use_if_id && downstreams->next) {
- log_info("Shan't get back the interface.");
- return;
- }
- memset(&relay->link_address, 0, 16);
- }
-
- if (packet->client_port != htons(547)) {
- relay_client_port = packet->client_port;
- }
- } else {
- relay->hop_count = 0;
- if (!dp)
- return;
- memcpy(&relay->link_address, &dp->link.sin6_addr, 16);
- }
- memcpy(&relay->peer_address, packet->client_addr.iabuf, 16);
-
- /* Get an option state. */
- opts = NULL;
- if (!option_state_allocate(&opts, MDL)) {
- log_fatal("No memory for upwards options.");
- }
-
- /* Add an interface-id (if used). */
- if (use_if_id) {
- int if_id;
-
- if (dp) {
- if_id = dp->id;
- } else if (!downstreams->next) {
- if_id = downstreams->id;
- } else {
- log_info("Don't know the interface.");
- option_state_dereference(&opts, MDL);
- return;
- }
-
- if (!save_option_buffer(&dhcpv6_universe, opts,
- NULL, (unsigned char *) &if_id,
- sizeof(int),
- D6O_INTERFACE_ID, 0)) {
- log_error("Can't save interface-id.");
- option_state_dereference(&opts, MDL);
- return;
- }
- }
-
- /* Add a subscriber-id if desired. */
- /* This is for testing rather than general use */
- if (dhcrelay_sub_id != NULL) {
- if (!save_option_buffer(&dhcpv6_universe, opts, NULL,
- (unsigned char *) dhcrelay_sub_id,
- strlen(dhcrelay_sub_id),
- D6O_SUBSCRIBER_ID, 0)) {
- log_error("Can't save subsriber-id.");
- option_state_dereference(&opts, MDL);
- return;
- }
- }
-
-
-#if defined(RELAY_PORT)
- /*
- * If we use a non-547 UDP source port or if we have received
- * from a downstream relay agent uses a non-547 port, we need
- * to include the RELAY-SOURCE-PORT option. The "Downstream
- * UDP Port" field value in the option allow us to send
- * relay-reply message back to the downstream relay agent
- * with the correct UDP source port.
- */
- if (relay_port || relay_client_port) {
- if (!save_option_buffer(&dhcpv6_universe, opts, NULL,
- (unsigned char *) &relay_client_port,
- sizeof(u_int16_t),
- D6O_RELAY_SOURCE_PORT, 0)) {
- log_error("Can't save relay-source-port.");
- option_state_dereference(&opts, MDL);
- return;
- }
- }
-#else
- /* Avoid unused but set warning, */
- (void)(relay_client_port);
-#endif
-
- /* Add the relay-msg carrying the packet. */
- if (!save_option_buffer(&dhcpv6_universe, opts,
- NULL, (unsigned char *) packet->raw,
- packet->packet_length,
- D6O_RELAY_MSG, 0)) {
- log_error("Can't save relay-msg.");
- option_state_dereference(&opts, MDL);
- return;
- }
-
- /* Finish the relay-forward message. */
- cursor += store_options6(forw_data + cursor,
- sizeof(forw_data) - cursor,
- opts, packet,
- required_forw_opts, NULL);
- option_state_dereference(&opts, MDL);
-
- /* Send it to all upstreams. */
- for (up = upstreams; up; up = up->next) {
- send_packet6(up->ifp, (unsigned char *) forw_data,
- (size_t) cursor, &up->link);
- }
-}
-
-/*
- * Process a packet downwards, i.e., from server to client.
- */
-static void
-process_down6(struct packet *packet) {
- struct stream_list *dp;
- struct option_cache *oc;
- struct data_string relay_msg;
- const struct dhcpv6_packet *msg;
- struct data_string if_id;
-#if defined(RELAY_PORT)
- struct data_string down_port;
-#endif
- struct sockaddr_in6 to;
- struct iaddr peer;
-
- /* The packet must be a relay-reply message. */
- if (packet->dhcpv6_msg_type != DHCPV6_RELAY_REPL) {
- if (packet->dhcpv6_msg_type < dhcpv6_type_name_max)
- log_info("Discarding %s from %s port %d going down.",
- dhcpv6_type_names[packet->dhcpv6_msg_type],
- piaddr(packet->client_addr),
- ntohs(packet->client_port));
- else
- log_info("Unknown %d type from %s port %d going down.",
- packet->dhcpv6_msg_type,
- piaddr(packet->client_addr),
- ntohs(packet->client_port));
- return;
- }
-
- /* Inits. */
- memset(&relay_msg, 0, sizeof(relay_msg));
- memset(&if_id, 0, sizeof(if_id));
-#if defined(RELAY_PORT)
- memset(&down_port, 0, sizeof(down_port));
-#endif
- memset(&to, 0, sizeof(to));
- to.sin6_family = AF_INET6;
-#ifdef HAVE_SA_LEN
- to.sin6_len = sizeof(to);
-#endif
- to.sin6_port = remote_port;
- peer.len = 16;
-
- /* Get the relay-msg option (carrying the message to relay). */
- oc = lookup_option(&dhcpv6_universe, packet->options, D6O_RELAY_MSG);
- if (oc == NULL) {
- log_info("No relay-msg.");
- return;
- }
- if (!evaluate_option_cache(&relay_msg, packet, NULL, NULL,
- packet->options, NULL,
- &global_scope, oc, MDL) ||
- (relay_msg.len < offsetof(struct dhcpv6_packet, options))) {
- log_error("Can't evaluate relay-msg.");
- goto cleanup;
- }
- msg = (const struct dhcpv6_packet *) relay_msg.data;
-
- /* Get the interface-id (if exists) and the downstream. */
- oc = lookup_option(&dhcpv6_universe, packet->options,
- D6O_INTERFACE_ID);
- if (oc != NULL) {
- int if_index;
-
- if (!evaluate_option_cache(&if_id, packet, NULL, NULL,
- packet->options, NULL,
- &global_scope, oc, MDL) ||
- (if_id.len != sizeof(int))) {
- log_info("Can't evaluate interface-id.");
- goto cleanup;
- }
- memcpy(&if_index, if_id.data, sizeof(int));
- for (dp = downstreams; dp; dp = dp->next) {
- if (dp->id == if_index)
- break;
- }
- } else {
- if (use_if_id) {
- /* Require an interface-id. */
- log_info("No interface-id.");
- goto cleanup;
- }
- for (dp = downstreams; dp; dp = dp->next) {
- /* Get the first matching one. */
- if (!memcmp(&dp->link.sin6_addr,
- &packet->dhcpv6_link_address,
- sizeof(struct in6_addr)))
- break;
- }
- }
- /* Why bother when there is no choice. */
- if (!dp && downstreams && !downstreams->next)
- dp = downstreams;
- if (!dp) {
- log_info("Can't find the down interface.");
- goto cleanup;
- }
- memcpy(peer.iabuf, &packet->dhcpv6_peer_address, peer.len);
- to.sin6_addr = packet->dhcpv6_peer_address;
-
- /* Check if we should relay the carried message. */
- switch (msg->msg_type) {
- /* Relay-Reply of for another relay, not a client. */
- case DHCPV6_RELAY_REPL:
- to.sin6_port = local_port;
-
-#if defined(RELAY_PORT)
- oc = lookup_option(&dhcpv6_universe, packet->options,
- D6O_RELAY_SOURCE_PORT);
- if (oc != NULL) {
- u_int16_t down_relay_port;
-
- memset(&down_port, 0, sizeof(down_port));
- if (!evaluate_option_cache(&down_port, packet, NULL,
- NULL, packet->options, NULL,
- &global_scope, oc, MDL) ||
- (down_port.len != sizeof(u_int16_t))) {
- log_info("Can't evaluate down "
- "relay-source-port.");
- goto cleanup;
- }
- memcpy(&down_relay_port, down_port.data,
- sizeof(u_int16_t));
- /*
- * If the down_relay_port value is non-zero,
- * that means our downstream relay agent uses
- * a non-547 UDP source port sending
- * relay-forw message to us. We need to use
- * the same UDP port sending reply back.
- */
- if (down_relay_port) {
- to.sin6_port = down_relay_port;
- }
- }
-#endif
-
- /* Fall into: */
-
- case DHCPV6_ADVERTISE:
- case DHCPV6_REPLY:
- case DHCPV6_RECONFIGURE:
- case DHCPV6_RELAY_FORW:
- case DHCPV6_LEASEQUERY_REPLY:
- case DHCPV6_DHCPV4_RESPONSE:
- log_info("Relaying %s to %s port %d down.",
- dhcpv6_type_names[msg->msg_type],
- piaddr(peer),
- ntohs(to.sin6_port));
- break;
-
- case DHCPV6_SOLICIT:
- case DHCPV6_REQUEST:
- case DHCPV6_CONFIRM:
- case DHCPV6_RENEW:
- case DHCPV6_REBIND:
- case DHCPV6_RELEASE:
- case DHCPV6_DECLINE:
- case DHCPV6_INFORMATION_REQUEST:
- case DHCPV6_LEASEQUERY:
- case DHCPV6_DHCPV4_QUERY:
- log_info("Discarding %s to %s port %d down.",
- dhcpv6_type_names[msg->msg_type],
- piaddr(peer),
- ntohs(to.sin6_port));
- goto cleanup;
-
- default:
- log_info("Unknown %d type to %s port %d down.",
- msg->msg_type,
- piaddr(peer),
- ntohs(to.sin6_port));
- goto cleanup;
- }
-
- /* Send the message to the downstream. */
- send_packet6(dp->ifp, (unsigned char *) relay_msg.data,
- (size_t) relay_msg.len, &to);
-
- cleanup:
- if (relay_msg.data != NULL)
- data_string_forget(&relay_msg, MDL);
- if (if_id.data != NULL)
- data_string_forget(&if_id, MDL);
-}
-#endif /* UNIT_TEST */
-
-/*
- * Called by the dispatch packet handler with a decoded packet.
- */
-void
-dhcpv6(struct packet *packet) {
-#ifndef UNIT_TEST
- struct stream_list *dp;
-
- /* Try all relay-replies downwards. */
- if (packet->dhcpv6_msg_type == DHCPV6_RELAY_REPL) {
- process_down6(packet);
- return;
- }
- /* Others are candidates to go up if they come from down. */
- for (dp = downstreams; dp; dp = dp->next) {
- if (packet->interface != dp->ifp)
- continue;
- process_up6(packet, dp);
- return;
- }
- /* Relay-forward could work from an unknown interface. */
- if (packet->dhcpv6_msg_type == DHCPV6_RELAY_FORW) {
- process_up6(packet, NULL);
- return;
- }
-
- log_info("Can't process packet from interface '%s'.",
- packet->interface->name);
-#endif /* UNIT_TEST */
-}
-#endif /* DHCPv6 */
-
-/* Stub routines needed for linking with DHCP libraries. */
-void
-bootp(struct packet *packet) {
- return;
-}
-
-void
-dhcp(struct packet *packet) {
- return;
-}
-
-#if defined(DHCPv6) && defined(DHCP4o6)
-isc_result_t dhcpv4o6_handler(omapi_object_t *h)
-{
- return ISC_R_NOTIMPLEMENTED;
-}
-#endif
-
-void
-classify(struct packet *p, struct class *c) {
- return;
-}
-
-int
-check_collection(struct packet *p, struct lease *l, struct collection *c) {
- return 0;
-}
-
-isc_result_t
-find_class(struct class **class, const char *c1, const char *c2, int i) {
- return ISC_R_NOTFOUND;
-}
-
-int
-parse_allow_deny(struct option_cache **oc, struct parse *p, int i) {
- return 0;
-}
-
-isc_result_t
-dhcp_set_control_state(control_object_state_t oldstate,
- control_object_state_t newstate) {
- char buf = 0;
-
- if (newstate != server_shutdown)
- return ISC_R_SUCCESS;
-
- /* Log shutdown on signal. */
- log_info("Received signal %d, initiating shutdown.", shutdown_signal);
-
- if (no_pid_file == ISC_FALSE)
- (void) unlink(path_dhcrelay_pid);
-
- if (!no_daemon && dfd[0] != -1 && dfd[1] != -1) {
- IGNORE_RET(write(dfd[1], &buf, 1));
- (void) close(dfd[1]);
- dfd[0] = dfd[1] = -1;
- }
- exit(0);
-}
-
-/*!
- *
- * \brief Allocate an interface as requested with a given set of flags
- *
- * The requested interface is allocated, its flags field is set to
- * INTERFACE_REQUESTED OR'd with the given flags, and then added to
- * the list of interfaces.
- *
- * \param name - name of the requested interface
- * \param flags - additional flags for the interface
- *
- * \return Nothing
- */
-void request_v4_interface(const char* name, int flags) {
- struct interface_info *tmp = NULL;
- int len = strlen(name);
- isc_result_t status;
-
- if (len >= sizeof(tmp->name)) {
- log_fatal("%s: interface name too long (is %d)", name, len);
- }
-
- status = interface_allocate(&tmp, MDL);
- if (status != ISC_R_SUCCESS) {
- log_fatal("%s: interface_allocate: %s", name,
- isc_result_totext(status));
- }
-
- log_debug("Requesting: %s as upstream: %c downstream: %c", name,
- (flags & INTERFACE_UPSTREAM ? 'Y' : 'N'),
- (flags & INTERFACE_DOWNSTREAM ? 'Y' : 'N'));
-
- memcpy(tmp->name, name, len);
- interface_snorf(tmp, (INTERFACE_REQUESTED | flags));
- interface_dereference(&tmp, MDL);
-}
diff --git a/relay/tests/Atffile b/relay/tests/Atffile
deleted file mode 100644
index c854582c..00000000
--- a/relay/tests/Atffile
+++ /dev/null
@@ -1,5 +0,0 @@
-Content-Type: application/X-atf-atffile; version="1"
-
-prop: test-suite = dhcrelay
-
-tp-glob: *_unittests
diff --git a/relay/tests/Kyuafile b/relay/tests/Kyuafile
deleted file mode 100644
index f0aa5b3b..00000000
--- a/relay/tests/Kyuafile
+++ /dev/null
@@ -1,4 +0,0 @@
-syntax(2)
-test_suite('dhcrelay')
-
-atf_test_program{name='relay_unittests'}
diff --git a/relay/tests/Makefile.am b/relay/tests/Makefile.am
deleted file mode 100644
index fce3115a..00000000
--- a/relay/tests/Makefile.am
+++ /dev/null
@@ -1,49 +0,0 @@
-SUBDIRS = .
-
-AM_CPPFLAGS = $(ATF_CFLAGS) -DUNIT_TEST -I$(top_srcdir)/includes
-AM_CPPFLAGS += -I@BINDDIR@/include -I$(top_srcdir)
-AM_CPPFLAGS += -DLOCALSTATEDIR='"."'
-
-EXTRA_DIST = Atffile Kyuafile
-
-# for autotools debugging only
-info:
- @echo "ATF_CFLAGS=$(ATF_CFLAGS)"
- @echo "ATF_LDFLAGS=$(ATF_LDFLAGS)"
- @echo "ATF_LIBS=$(ATF_LIBS)"
-
-DHCPSRC = ../dhcrelay.c
-
-DHCPLIBS = $(top_builddir)/common/libdhcp.@A@ \
- $(top_builddir)/omapip/libomapi.@A@ \
- @BINDLIBIRSDIR@/libirs.@A@ \
- @BINDLIBDNSDIR@/libdns.@A@ \
- @BINDLIBISCCFGDIR@/libisccfg.@A@ \
- @BINDLIBISCDIR@/libisc.@A@
-
-ATF_TESTS =
-if HAVE_ATF
-
-ATF_TESTS += relay_unittests
-
-relay_unittests_SOURCES = $(DHCPSRC)
-relay_unittests_SOURCES += relay_unittests.c
-
-relay_unittests_LDADD = $(ATF_LDFLAGS)
-relay_unittests_LDADD += $(DHCPLIBS)
-
-check: $(ATF_TESTS)
- @if test $(top_srcdir) != ${top_builddir}; then \
- cp $(top_srcdir)/relay/tests/Atffile Atffile; \
- cp $(top_srcdir)/relay/tests/Kyuafile Kyuafile; \
- fi
- sh ${top_builddir}/tests/unittest.sh
-
-distclean-local:
- @if test $(top_srcdir) != ${top_builddir}; then \
- rm -f Atffile Kyuafile; \
- fi
-
-endif
-
-check_PROGRAMS = $(ATF_TESTS)
diff --git a/relay/tests/Makefile.in b/relay/tests/Makefile.in
deleted file mode 100644
index caef4fa1..00000000
--- a/relay/tests/Makefile.in
+++ /dev/null
@@ -1,742 +0,0 @@
-# Makefile.in generated by automake 1.16.5 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2021 Free Software Foundation, Inc.
-
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-VPATH = @srcdir@
-am__is_gnu_make = { \
- if test -z '$(MAKELEVEL)'; then \
- false; \
- elif test -n '$(MAKE_HOST)'; then \
- true; \
- elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
- true; \
- else \
- false; \
- fi; \
-}
-am__make_running_with_option = \
- case $${target_option-} in \
- ?) ;; \
- *) echo "am__make_running_with_option: internal error: invalid" \
- "target option '$${target_option-}' specified" >&2; \
- exit 1;; \
- esac; \
- has_opt=no; \
- sane_makeflags=$$MAKEFLAGS; \
- if $(am__is_gnu_make); then \
- sane_makeflags=$$MFLAGS; \
- else \
- case $$MAKEFLAGS in \
- *\\[\ \ ]*) \
- bs=\\; \
- sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
- | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
- esac; \
- fi; \
- skip_next=no; \
- strip_trailopt () \
- { \
- flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
- }; \
- for flg in $$sane_makeflags; do \
- test $$skip_next = yes && { skip_next=no; continue; }; \
- case $$flg in \
- *=*|--*) continue;; \
- -*I) strip_trailopt 'I'; skip_next=yes;; \
- -*I?*) strip_trailopt 'I';; \
- -*O) strip_trailopt 'O'; skip_next=yes;; \
- -*O?*) strip_trailopt 'O';; \
- -*l) strip_trailopt 'l'; skip_next=yes;; \
- -*l?*) strip_trailopt 'l';; \
- -[dEDm]) skip_next=yes;; \
- -[JT]) skip_next=yes;; \
- esac; \
- case $$flg in \
- *$$target_option*) has_opt=yes; break;; \
- esac; \
- done; \
- test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-@HAVE_ATF_TRUE@am__append_1 = relay_unittests
-check_PROGRAMS = $(am__EXEEXT_2)
-subdir = relay/tests
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/includes/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-@HAVE_ATF_TRUE@am__EXEEXT_1 = relay_unittests$(EXEEXT)
-am__EXEEXT_2 = $(am__EXEEXT_1)
-am__relay_unittests_SOURCES_DIST = ../dhcrelay.c relay_unittests.c
-am__objects_1 = dhcrelay.$(OBJEXT)
-@HAVE_ATF_TRUE@am_relay_unittests_OBJECTS = $(am__objects_1) \
-@HAVE_ATF_TRUE@ relay_unittests.$(OBJEXT)
-relay_unittests_OBJECTS = $(am_relay_unittests_OBJECTS)
-am__DEPENDENCIES_1 =
-am__DEPENDENCIES_2 = $(top_builddir)/common/libdhcp.@A@ \
- $(top_builddir)/omapip/libomapi.@A@
-@HAVE_ATF_TRUE@relay_unittests_DEPENDENCIES = $(am__DEPENDENCIES_1) \
-@HAVE_ATF_TRUE@ $(am__DEPENDENCIES_2)
-AM_V_P = $(am__v_P_@AM_V@)
-am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo " GEN " $@;
-am__v_GEN_1 =
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 =
-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/includes
-depcomp = $(SHELL) $(top_srcdir)/depcomp
-am__maybe_remake_depfiles = depfiles
-am__depfiles_remade = ./$(DEPDIR)/dhcrelay.Po \
- ./$(DEPDIR)/relay_unittests.Po
-am__mv = mv -f
-AM_V_lt = $(am__v_lt_@AM_V@)
-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
-am__v_lt_0 = --silent
-am__v_lt_1 =
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo " CC " $@;
-am__v_CC_1 =
-CCLD = $(CC)
-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo " CCLD " $@;
-am__v_CCLD_1 =
-SOURCES = $(relay_unittests_SOURCES)
-DIST_SOURCES = $(am__relay_unittests_SOURCES_DIST)
-RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
- ctags-recursive dvi-recursive html-recursive info-recursive \
- install-data-recursive install-dvi-recursive \
- install-exec-recursive install-html-recursive \
- install-info-recursive install-pdf-recursive \
- install-ps-recursive install-recursive installcheck-recursive \
- installdirs-recursive pdf-recursive ps-recursive \
- tags-recursive uninstall-recursive
-am__can_run_installinfo = \
- case $$AM_UPDATE_INFO_DIR in \
- n|no|NO) false;; \
- *) (install-info --version) >/dev/null 2>&1;; \
- esac
-RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
- distclean-recursive maintainer-clean-recursive
-am__recursive_targets = \
- $(RECURSIVE_TARGETS) \
- $(RECURSIVE_CLEAN_TARGETS) \
- $(am__extra_recursive_targets)
-AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
- distdir distdir-am
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-# Read a list of newline-separated strings from the standard input,
-# and print each of them once, without duplicates. Input order is
-# *not* preserved.
-am__uniquify_input = $(AWK) '\
- BEGIN { nonempty = 0; } \
- { items[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in items) print i; }; } \
-'
-# Make sure the list of sources is unique. This is necessary because,
-# e.g., the same source file might be shared among _SOURCES variables
-# for different programs/libraries.
-am__define_uniq_tagged_files = \
- list='$(am__tagged_files)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | $(am__uniquify_input)`
-DIST_SUBDIRS = $(SUBDIRS)
-am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-am__relativize = \
- dir0=`pwd`; \
- sed_first='s,^\([^/]*\)/.*$$,\1,'; \
- sed_rest='s,^[^/]*/*,,'; \
- sed_last='s,^.*/\([^/]*\)$$,\1,'; \
- sed_butlast='s,/*[^/]*$$,,'; \
- while test -n "$$dir1"; do \
- first=`echo "$$dir1" | sed -e "$$sed_first"`; \
- if test "$$first" != "."; then \
- if test "$$first" = ".."; then \
- dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
- dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
- else \
- first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
- if test "$$first2" = "$$first"; then \
- dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
- else \
- dir2="../$$dir2"; \
- fi; \
- dir0="$$dir0"/"$$first"; \
- fi; \
- fi; \
- dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
- done; \
- reldir="$$dir2"
-A = @A@
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-ATF_BIN = @ATF_BIN@
-ATF_CFLAGS = @ATF_CFLAGS@
-ATF_LDFLAGS = @ATF_LDFLAGS@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-BINDCONFIG = @BINDCONFIG@
-BINDDIR = @BINDDIR@
-BINDIOMUX = @BINDIOMUX@
-BINDLIBDNSDIR = @BINDLIBDNSDIR@
-BINDLIBIRSDIR = @BINDLIBIRSDIR@
-BINDLIBISCCFGDIR = @BINDLIBISCCFGDIR@
-BINDLIBISCDIR = @BINDLIBISCDIR@
-BINDLT = @BINDLT@
-BINDSRCDIR = @BINDSRCDIR@
-BINDSUBDIR = @BINDSUBDIR@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CSCOPE = @CSCOPE@
-CTAGS = @CTAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DHLIBS = @DHLIBS@
-DISTCHECK_ATF_CONFIGURE_FLAG = @DISTCHECK_ATF_CONFIGURE_FLAG@
-DISTCHECK_LIBBIND_CONFIGURE_FLAG = @DISTCHECK_LIBBIND_CONFIGURE_FLAG@
-DISTCHECK_LIBTOOL_CONFIGURE_FLAG = @DISTCHECK_LIBTOOL_CONFIGURE_FLAG@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-ETAGS = @ETAGS@
-EXEEXT = @EXEEXT@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LDAP_CFLAGS = @LDAP_CFLAGS@
-LDAP_LIBS = @LDAP_LIBS@
-LDFLAGS = @LDFLAGS@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-MKDIR_P = @MKDIR_P@
-OBJEXT = @OBJEXT@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-Q = @Q@
-RANLIB = @RANLIB@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-UNITTESTS = @UNITTESTS@
-VERSION = @VERSION@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_CC = @ac_ct_CC@
-ac_prefix_program = @ac_prefix_program@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-byte_order = @byte_order@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-pkgcfg_found = @pkgcfg_found@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-SUBDIRS = .
-AM_CPPFLAGS = $(ATF_CFLAGS) -DUNIT_TEST -I$(top_srcdir)/includes \
- -I@BINDDIR@/include -I$(top_srcdir) -DLOCALSTATEDIR='"."'
-EXTRA_DIST = Atffile Kyuafile
-DHCPSRC = ../dhcrelay.c
-DHCPLIBS = $(top_builddir)/common/libdhcp.@A@ \
- $(top_builddir)/omapip/libomapi.@A@ \
- @BINDLIBIRSDIR@/libirs.@A@ \
- @BINDLIBDNSDIR@/libdns.@A@ \
- @BINDLIBISCCFGDIR@/libisccfg.@A@ \
- @BINDLIBISCDIR@/libisc.@A@
-
-ATF_TESTS = $(am__append_1)
-@HAVE_ATF_TRUE@relay_unittests_SOURCES = $(DHCPSRC) relay_unittests.c
-@HAVE_ATF_TRUE@relay_unittests_LDADD = $(ATF_LDFLAGS) $(DHCPLIBS)
-all: all-recursive
-
-.SUFFIXES:
-.SUFFIXES: .c .o .obj
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
- @for dep in $?; do \
- case '$(am__configure_deps)' in \
- *$$dep*) \
- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
- && { if test -f $@; then exit 0; else break; fi; }; \
- exit 1;; \
- esac; \
- done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign relay/tests/Makefile'; \
- $(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --foreign relay/tests/Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- @case '$?' in \
- *config.status*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
- *) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
- esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(am__aclocal_m4_deps):
-
-clean-checkPROGRAMS:
- -test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS)
-
-relay_unittests$(EXEEXT): $(relay_unittests_OBJECTS) $(relay_unittests_DEPENDENCIES) $(EXTRA_relay_unittests_DEPENDENCIES)
- @rm -f relay_unittests$(EXEEXT)
- $(AM_V_CCLD)$(LINK) $(relay_unittests_OBJECTS) $(relay_unittests_LDADD) $(LIBS)
-
-mostlyclean-compile:
- -rm -f *.$(OBJEXT)
-
-distclean-compile:
- -rm -f *.tab.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dhcrelay.Po@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/relay_unittests.Po@am__quote@ # am--include-marker
-
-$(am__depfiles_remade):
- @$(MKDIR_P) $(@D)
- @echo '# dummy' >$@-t && $(am__mv) $@-t $@
-
-am--depfiles: $(am__depfiles_remade)
-
-.c.o:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
-
-.c.obj:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
-
-dhcrelay.o: ../dhcrelay.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dhcrelay.o -MD -MP -MF $(DEPDIR)/dhcrelay.Tpo -c -o dhcrelay.o `test -f '../dhcrelay.c' || echo '$(srcdir)/'`../dhcrelay.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dhcrelay.Tpo $(DEPDIR)/dhcrelay.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../dhcrelay.c' object='dhcrelay.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dhcrelay.o `test -f '../dhcrelay.c' || echo '$(srcdir)/'`../dhcrelay.c
-
-dhcrelay.obj: ../dhcrelay.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dhcrelay.obj -MD -MP -MF $(DEPDIR)/dhcrelay.Tpo -c -o dhcrelay.obj `if test -f '../dhcrelay.c'; then $(CYGPATH_W) '../dhcrelay.c'; else $(CYGPATH_W) '$(srcdir)/../dhcrelay.c'; fi`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dhcrelay.Tpo $(DEPDIR)/dhcrelay.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../dhcrelay.c' object='dhcrelay.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dhcrelay.obj `if test -f '../dhcrelay.c'; then $(CYGPATH_W) '../dhcrelay.c'; else $(CYGPATH_W) '$(srcdir)/../dhcrelay.c'; fi`
-
-# This directory's subdirectories are mostly independent; you can cd
-# into them and run 'make' without going through this Makefile.
-# To change the values of 'make' variables: instead of editing Makefiles,
-# (1) if the variable is set in 'config.status', edit 'config.status'
-# (which will cause the Makefiles to be regenerated when you run 'make');
-# (2) otherwise, pass the desired values on the 'make' command line.
-$(am__recursive_targets):
- @fail=; \
- if $(am__make_keepgoing); then \
- failcom='fail=yes'; \
- else \
- failcom='exit 1'; \
- fi; \
- dot_seen=no; \
- target=`echo $@ | sed s/-recursive//`; \
- case "$@" in \
- distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
- *) list='$(SUBDIRS)' ;; \
- esac; \
- for subdir in $$list; do \
- echo "Making $$target in $$subdir"; \
- if test "$$subdir" = "."; then \
- dot_seen=yes; \
- local_target="$$target-am"; \
- else \
- local_target="$$target"; \
- fi; \
- ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
- || eval $$failcom; \
- done; \
- if test "$$dot_seen" = "no"; then \
- $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
- fi; test -z "$$fail"
-
-ID: $(am__tagged_files)
- $(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-recursive
-TAGS: tags
-
-tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
- set x; \
- here=`pwd`; \
- if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
- include_option=--etags-include; \
- empty_fix=.; \
- else \
- include_option=--include; \
- empty_fix=; \
- fi; \
- list='$(SUBDIRS)'; for subdir in $$list; do \
- if test "$$subdir" = .; then :; else \
- test ! -f $$subdir/TAGS || \
- set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
- fi; \
- done; \
- $(am__define_uniq_tagged_files); \
- shift; \
- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
- test -n "$$unique" || unique=$$empty_fix; \
- if test $$# -gt 0; then \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- "$$@" $$unique; \
- else \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$unique; \
- fi; \
- fi
-ctags: ctags-recursive
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
- $(am__define_uniq_tagged_files); \
- test -z "$(CTAGS_ARGS)$$unique" \
- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$unique
-
-GTAGS:
- here=`$(am__cd) $(top_builddir) && pwd` \
- && $(am__cd) $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-recursive
-
-cscopelist-am: $(am__tagged_files)
- list='$(am__tagged_files)'; \
- case "$(srcdir)" in \
- [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
- *) sdir=$(subdir)/$(srcdir) ;; \
- esac; \
- for i in $$list; do \
- if test -f "$$i"; then \
- echo "$(subdir)/$$i"; \
- else \
- echo "$$sdir/$$i"; \
- fi; \
- done >> $(top_builddir)/cscope.files
-
-distclean-tags:
- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-distdir: $(BUILT_SOURCES)
- $(MAKE) $(AM_MAKEFLAGS) distdir-am
-
-distdir-am: $(DISTFILES)
- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- list='$(DISTFILES)'; \
- dist_files=`for file in $$list; do echo $$file; done | \
- sed -e "s|^$$srcdirstrip/||;t" \
- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
- case $$dist_files in \
- */*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
- sort -u` ;; \
- esac; \
- for file in $$dist_files; do \
- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
- if test -d $$d/$$file; then \
- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
- if test -d "$(distdir)/$$file"; then \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
- else \
- test -f "$(distdir)/$$file" \
- || cp -p $$d/$$file "$(distdir)/$$file" \
- || exit 1; \
- fi; \
- done
- @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
- if test "$$subdir" = .; then :; else \
- $(am__make_dryrun) \
- || test -d "$(distdir)/$$subdir" \
- || $(MKDIR_P) "$(distdir)/$$subdir" \
- || exit 1; \
- dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
- $(am__relativize); \
- new_distdir=$$reldir; \
- dir1=$$subdir; dir2="$(top_distdir)"; \
- $(am__relativize); \
- new_top_distdir=$$reldir; \
- echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
- echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
- ($(am__cd) $$subdir && \
- $(MAKE) $(AM_MAKEFLAGS) \
- top_distdir="$$new_top_distdir" \
- distdir="$$new_distdir" \
- am__remove_distdir=: \
- am__skip_length_check=: \
- am__skip_mode_fix=: \
- distdir) \
- || exit 1; \
- fi; \
- done
-check-am: all-am
- $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
-check: check-recursive
-all-am: Makefile
-installdirs: installdirs-recursive
-installdirs-am:
-install: install-recursive
-install-exec: install-exec-recursive
-install-data: install-data-recursive
-uninstall: uninstall-recursive
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-recursive
-install-strip:
- if test -z '$(STRIP)'; then \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- install; \
- else \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
- fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
-@HAVE_ATF_FALSE@distclean-local:
-clean: clean-recursive
-
-clean-am: clean-checkPROGRAMS clean-generic mostlyclean-am
-
-distclean: distclean-recursive
- -rm -f ./$(DEPDIR)/dhcrelay.Po
- -rm -f ./$(DEPDIR)/relay_unittests.Po
- -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
- distclean-local distclean-tags
-
-dvi: dvi-recursive
-
-dvi-am:
-
-html: html-recursive
-
-html-am:
-
-info-am:
-
-install-data-am:
-
-install-dvi: install-dvi-recursive
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-recursive
-
-install-html-am:
-
-install-info: install-info-recursive
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-recursive
-
-install-pdf-am:
-
-install-ps: install-ps-recursive
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-recursive
- -rm -f ./$(DEPDIR)/dhcrelay.Po
- -rm -f ./$(DEPDIR)/relay_unittests.Po
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-recursive
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic
-
-pdf: pdf-recursive
-
-pdf-am:
-
-ps: ps-recursive
-
-ps-am:
-
-uninstall-am:
-
-.MAKE: $(am__recursive_targets) check-am install-am install-strip
-
-.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
- am--depfiles check check-am clean clean-checkPROGRAMS \
- clean-generic cscopelist-am ctags ctags-am distclean \
- distclean-compile distclean-generic distclean-local \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-ps install-ps-am \
- install-strip installcheck installcheck-am installdirs \
- installdirs-am maintainer-clean maintainer-clean-generic \
- mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
- ps ps-am tags tags-am uninstall uninstall-am
-
-.PRECIOUS: Makefile
-
-
-# for autotools debugging only
-info:
- @echo "ATF_CFLAGS=$(ATF_CFLAGS)"
- @echo "ATF_LDFLAGS=$(ATF_LDFLAGS)"
- @echo "ATF_LIBS=$(ATF_LIBS)"
-
-@HAVE_ATF_TRUE@check: $(ATF_TESTS)
-@HAVE_ATF_TRUE@ @if test $(top_srcdir) != ${top_builddir}; then \
-@HAVE_ATF_TRUE@ cp $(top_srcdir)/relay/tests/Atffile Atffile; \
-@HAVE_ATF_TRUE@ cp $(top_srcdir)/relay/tests/Kyuafile Kyuafile; \
-@HAVE_ATF_TRUE@ fi
-@HAVE_ATF_TRUE@ sh ${top_builddir}/tests/unittest.sh
-
-@HAVE_ATF_TRUE@distclean-local:
-@HAVE_ATF_TRUE@ @if test $(top_srcdir) != ${top_builddir}; then \
-@HAVE_ATF_TRUE@ rm -f Atffile Kyuafile; \
-@HAVE_ATF_TRUE@ fi
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/relay/tests/relay_unittests.c b/relay/tests/relay_unittests.c
deleted file mode 100644
index ceb409f6..00000000
--- a/relay/tests/relay_unittests.c
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * Copyright (C) 2019-2022 Internet Systems Consortium, Inc. ("ISC")
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * 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.
- * PO Box 360
- * Newmarket, NH 03857 USA
- * <info@isc.org>
- * https://www.isc.org/
- *
- */
-
-#include "config.h"
-#include <atf-c.h>
-#include <omapip/omapip_p.h>
-#include "dhcpd.h"
-
-/* @brief Externs for dhcrelay.c functions under test */
-extern int add_agent_options;
-extern int add_relay_agent_options(struct interface_info *,
- struct dhcp_packet *, unsigned,
- struct in_addr);
-
-extern int find_interface_by_agent_option(struct dhcp_packet *,
- struct interface_info **,
- u_int8_t *, int);
-
-extern int strip_relay_agent_options(struct interface_info *,
- struct interface_info **,
- struct dhcp_packet *, unsigned);
-
-/* @brief Add the given option data to a DHCPv4 packet
-*
-* It first fills the packet.options buffer with the given pad character.
-* Next it copies the DHCP magic cookie value into the beginning of the
-* options buffer. Finally it appends the given data after the cookie.
-*
-* @param packet pointer to the packet
-* @param data pointer to the option data to copy into the packet's options
-* buffer
-* @param len length of the option data to copy
-* @param pad byte value with which to initialize the packet's options buffer
-*
-* @return returns the new length of the packet
-*/
-unsigned set_packet_options(struct dhcp_packet *packet,
- unsigned char* data, unsigned len,
- unsigned char pad) {
- unsigned new_len;
- memset(packet->options, pad, DHCP_MAX_OPTION_LEN);
-
- // Add the COOKIE
- new_len = 4;
- memcpy(packet->options, DHCP_OPTIONS_COOKIE, new_len);
-
- new_len += len;
- if (new_len > DHCP_MAX_OPTION_LEN) {
- return(0);
- }
-
- memcpy(&packet->options[4], data, len);
- return(new_len + DHCP_FIXED_NON_UDP);
-}
-
-/* @brief Checks two sets of option data for equalit
-*
-* It constructs the expected options content by creating an options buffer
-* filled with the pad value. Next it copies the DHCP magic cookie value
-* into the beginning of the buffer and then appends the expected data after
-* the cookie. It the compares this buffer to the actual buffer passed in
-* for equality and returns the result.
-*
-* @param actual_options pointer to the packet::options to be checked
-* @param expected_data pointer to the expected options data (everything after
-* the DHCP cookie)
-* @param data_len length of the expected options data
-* @param pad byte value with which to initialize the packet's options buffer
-*
-* @return zero it the sets of data match, non-zero otherwise
-*/
-int check_with_pad(unsigned char* actual_options,
- unsigned char *expected_data,
- unsigned data_len, unsigned char pad) {
-
- unsigned char exp_options[DHCP_MAX_OPTION_LEN];
- unsigned new_len;
-
- memset(exp_options, pad, DHCP_MAX_OPTION_LEN);
- new_len = 4;
- memcpy(exp_options, DHCP_OPTIONS_COOKIE, new_len);
-
- new_len += data_len;
- if (new_len > DHCP_MAX_OPTION_LEN) {
- return(-1);
- }
-
- memcpy(&exp_options[4], expected_data, data_len);
- return (memcmp(actual_options, exp_options, DHCP_MAX_OPTION_LEN));
-}
-
-ATF_TC(strip_relay_agent_options_test);
-
-ATF_TC_HEAD(strip_relay_agent_options_test, tc) {
- atf_tc_set_md_var(tc, "descr", "tests strip_relay-agent_options");
-}
-
-/* This Test exercises strip_relay_agent_options() function */
-ATF_TC_BODY(strip_relay_agent_options_test, tc) {
-
- struct interface_info ifaces;
- struct interface_info *matched;
- struct dhcp_packet packet;
- unsigned len;
- int ret;
-
- memset(&ifaces, 0x0, sizeof(ifaces));
- matched = 0;
- memset(&packet, 0x0, sizeof(packet));
- len = 0;
-
- /* Make sure an empty packet is harmless. We set add_agent_options = 1
- * to avoid early return when it's 0. */
- add_agent_options = 1;
- ret = strip_relay_agent_options(&ifaces, &matched, &packet, len);
- if (ret != 0) {
- atf_tc_fail("empty packet failed");
- }
-
- {
- /*
- * Uses valid input option data to verify that:
- * - When add_agent_options is false, the output option data is the
- * the same as the input option data (i.e. nothing removed)
- * - When add_agent_options is true, 0 length relay agent option has
- * been removed from the output option data
- * - When add_agent_options is true, a relay agent option has
- * been removed from the output option data
- *
- */
-
- unsigned char input_data[] = {
- 0x35, 0x00, /* DHCP_TYPE = DISCOVER */
- 0x52, 0x08, 0x01, 0x06, 0x65, /* Relay Agent Option, len = 8 */
- 0x6e, 0x70, 0x30, 0x73, 0x4f,
-
- 0x42, 0x02, 0x00, 0x10, /* Opt 0x42, len = 2 */
- 0x43, 0x00 /* Opt 0x43, len = 0 */
- };
-
- unsigned char input_data2[] = {
- 0x35, 0x00, /* DHCP_TYPE = DISCOVER */
- 0x52, 0x00, /* Relay Agent Option, len = 0 */
- 0x42, 0x02, 0x00, 0x10, /* Opt 0x42, len = 2 */
- 0x43, 0x00 /* Opt 0x43, len = 0 */
- };
-
- unsigned char output_data[] = {
- 0x35, 0x00, /* DHCP_TYPE = DISCOVER */
- 0x42, 0x02, 0x00, 0x10, /* Opt 0x42, len = 2 */
- 0x43, 0x00 /* Opt 0x43, len = 0 */
- };
-
- unsigned char pad = 0x0;
- len = set_packet_options(&packet, input_data, sizeof(input_data), pad);
- if (len == 0) {
- atf_tc_fail("input_data: set_packet_options failed");
- }
-
- /* When add_agent_options = 0, no change should occur */
- add_agent_options = 0;
- ret = strip_relay_agent_options(&ifaces, &matched, &packet, len);
- if (ret != len) {
- atf_tc_fail("expected unchanged len %d, returned %d", len, ret);
- }
-
- if (check_with_pad(packet.options, input_data, sizeof(input_data),
- pad) != 0) {
- atf_tc_fail("expected unchanged data, does not match");
- }
-
- /* When add_agent_options = 1, it should remove the eight byte
- * relay agent option. */
- add_agent_options = 1;
-
- /* Beause the inbound option data is less than the BOOTP_MIN_LEN,
- * the output data should get padded out to BOOTP_MIN_LEN
- * padded out to BOOTP_MIN_LEN */
- ret = strip_relay_agent_options(&ifaces, &matched, &packet, len);
- if (ret != BOOTP_MIN_LEN) {
- atf_tc_fail("input_data: len of %d, returned %d",
- BOOTP_MIN_LEN, ret);
- }
-
- if (check_with_pad(packet.options, output_data, sizeof(output_data),
- pad) != 0) {
- atf_tc_fail("input_data: expected data does not match");
- }
-
- /* Now let's repeat it with a relay agent option 0 bytes in length. */
- len = set_packet_options(&packet, input_data2, sizeof(input_data2), pad);
- if (len == 0) {
- atf_tc_fail("input_data2 set_packet_options failed");
- }
-
- /* Because the inbound option data is less than the BOOTP_MIN_LEN,
- * the output data should get padded out to BOOTP_MIN_LEN
- * padded out to BOOTP_MIN_LEN */
- ret = strip_relay_agent_options(&ifaces, &matched, &packet, len);
- if (ret != BOOTP_MIN_LEN) {
- atf_tc_fail("input_data2: len of %d, returned %d",
- BOOTP_MIN_LEN, ret);
- }
-
- if (check_with_pad(packet.options, output_data, sizeof(output_data),
- pad) != 0) {
- atf_tc_fail("input_data2: expected output does not match");
- }
- }
-
- {
- /* Verify that oversized packet filled with long options does not
- * cause overrun */
-
- /* We borrowed this union from discover.c:got_one() */
- union {
- unsigned char packbuf [4095]; /* Packet input buffer.
- * Must be as large as largest
- * possible MTU. */
- struct dhcp_packet packet;
- } u;
-
- unsigned char input_data[] = {
- 0x35, 0x00, /* DHCP_TYPE = DISCOVER */
- 0x52, 0x00, /* Relay Agent Option, len = 0 */
- 0x42, 0x02, 0x00, 0x10, /* Opt 0x42, len = 2 */
- 0x43, 0x00 /* Opt 0x43, len = 0 */
- };
-
- /* We'll pad it 0xFE, that way wherever we hit for "length" we'll
- * have length of 254. Increasing the odds we'll push over the end. */
- unsigned char pad = 0xFE;
- memset(u.packbuf, pad, 4095);
-
- len = set_packet_options(&u.packet, input_data, sizeof(input_data), pad);
- if (len == 0) {
- atf_tc_fail("overrun: set_packet_options failed");
- }
-
- /* Enable option stripping by setting add_agent_options = 1 */
- add_agent_options = 1;
-
- /* strip_relay_agent_options() should detect the overrun and return 0 */
- ret = strip_relay_agent_options(&ifaces, &matched, &u.packet, 4095);
- if (ret != 0) {
- atf_tc_fail("overrun expected return len = 0, we got %d", ret);
- }
- }
-}
-
-ATF_TC(add_relay_agent_options_test);
-
-ATF_TC_HEAD(add_relay_agent_options_test, tc) {
- atf_tc_set_md_var(tc, "descr", "tests agent_relay-agent_options");
-}
-
-/* This Test exercises add_relay_agent_options() function */
-ATF_TC_BODY(add_relay_agent_options_test, tc) {
-
- struct interface_info ifc;
- struct dhcp_packet packet;
- unsigned len;
- int ret;
- struct in_addr giaddr;
-
- giaddr.s_addr = inet_addr("192.0.1.1");
-
- u_int8_t circuit_id[] = { 0x01,0x02,0x03,0x04,0x05,0x06 };
- u_int8_t remote_id[] = { 0x11,0x22,0x33,0x44,0x55,0x66 };
-
- memset(&ifc, 0x0, sizeof(ifc));
- ifc.circuit_id = circuit_id;
- ifc.circuit_id_len = sizeof(circuit_id);
- ifc.remote_id = remote_id;
- ifc.remote_id_len = sizeof(remote_id);
-
- memset(&packet, 0x0, sizeof(packet));
- len = 0;
-
- /* Make sure an empty packet is harmless */
- ret = add_relay_agent_options(&ifc, &packet, len, giaddr);
- if (ret != 0) {
- atf_tc_fail("empty packet failed");
- }
-
- {
- /*
- * Uses valid input option data to verify that:
- * - When add_agent_options is false, the output option data is the
- * the same as the input option data (i.e. nothing removed)
- * - When add_agent_options is true, the relay agent option has
- * been removed from the output option data
- * - When add_agent_options is true, 0 length relay agent option has
- * been removed from the output option data
- *
- */
-
- unsigned char input_data[] = {
- 0x35, 0x00, /* DHCP_TYPE = DISCOVER */
- 0x52, 0x08, 0x01, 0x06, 0x65, /* Relay Agent Option, len = 8 */
- 0x6e, 0x70, 0x30, 0x73, 0x4f,
- 0x42, 0x02, 0x00, 0x10, /* Opt 0x42, len = 2 */
- 0x43, 0x00 /* Opt 0x43, len = 0 */
- };
-
- unsigned char input_data2[] = {
- 0x35, 0x00, /* DHCP_TYPE = DISCOVER */
- 0x52, 0x00, /* Relay Agent Option, len = 0 */
- 0x42, 0x02, 0x00, 0x10, /* Opt 0x42, len = 2 */
- 0x43, 0x00 /* Opt 0x43, len = 0 */
- };
-
- unsigned char output_data[] = {
- 0x35, 0x00, /* DHCP_TYPE = DISCOVER */
- 0x42, 0x02, 0x00, 0x10, /* Opt 0x42, len = 2 */
- 0x43, 0x00, /* Opt 0x43, len = 0 */
- 0x52, 0x10, /* Relay Agent, len = 16 */
- 0x1, 0x6, /* Circuit id, len = 6 */
- 0x1, 0x2, 0x3, 0x4, 0x5, 0x6,
- 0x2, 0x6, /* Remete id, len = 6 */
- 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xff
- };
-
- unsigned char pad = 0x0;
- len = set_packet_options(&packet, input_data, sizeof(input_data), pad);
- if (len == 0) {
- atf_tc_fail("input_data: set_packet_options failed");
- }
-
- /* When add_agent_options = 0, no change should occur */
- add_agent_options = 0;
- ret = add_relay_agent_options(&ifc, &packet, len, giaddr);
- if (ret != len) {
- atf_tc_fail("expected unchanged len %d, returned %d", len, ret);
- }
-
- if (check_with_pad(packet.options, input_data, sizeof(input_data),
- pad) != 0) {
- atf_tc_fail("expected unchanged data, does not match");
- }
-
- /* When add_agent_options = 1, it should remove the eight byte
- * relay agent option. */
- add_agent_options = 1;
-
- /* Because the inbound option data is less than the BOOTP_MIN_LEN,
- * the output data should get padded out to BOOTP_MIN_LEN
- * padded out to BOOTP_MIN_LEN */
- ret = add_relay_agent_options(&ifc, &packet, len, giaddr);
- if (ret != BOOTP_MIN_LEN) {
- atf_tc_fail("input_data: len of %d, returned %d",
- BOOTP_MIN_LEN, ret);
- }
-
- if (check_with_pad(packet.options, output_data, sizeof(output_data),
- pad) != 0) {
- atf_tc_fail("input_data: expected data does not match");
- }
-
- /* Now let's repeat it with a relay agent option 0 bytes in length. */
- len = set_packet_options(&packet, input_data2, sizeof(input_data2),
- pad);
- if (len == 0) {
- atf_tc_fail("input_data2 set_packet_options failed");
- }
-
- /* Because the inbound option data is less than the BOOTP_MIN_LEN,
- * the output data should get padded out to BOOTP_MIN_LEN
- * padded out to BOOTP_MIN_LEN */
- ret = add_relay_agent_options(&ifc, &packet, len, giaddr);
- if (ret != BOOTP_MIN_LEN) {
- atf_tc_fail("input_data2: len of %d, returned %d",
- BOOTP_MIN_LEN, ret);
- }
-
- if (check_with_pad(packet.options, output_data, sizeof(output_data),
- pad) != 0) {
- atf_tc_fail("input_data2: expected output does not match");
- }
- }
-}
-
-ATF_TC(gwaddr_override_test);
-
-ATF_TC_HEAD(gwaddr_override_test, tc) {
- atf_tc_set_md_var(tc, "descr", "tests that gateway addr (giaddr) field can be overridden");
-}
-
-extern isc_boolean_t use_fake_gw;
-extern struct in_addr gw;
-
-/* This basic test checks if the new gwaddr override (-g) option is disabled by default */
-ATF_TC_BODY(gwaddr_override_test, tc) {
-
- if (use_fake_gw == ISC_TRUE) {
- atf_tc_fail("the gwaddr override should be disabled by default");
- }
- char txt[16] = {0};
- inet_ntop(AF_INET, &gw, txt, sizeof(txt));
- if (strncmp(txt, "0.0.0.0", 8) != 0) {
- atf_tc_fail("the default gwaddr override value should be 0.0.0.0, but is %s", txt);
- }
-}
-
-ATF_TP_ADD_TCS(tp) {
- ATF_TP_ADD_TC(tp, strip_relay_agent_options_test);
- ATF_TP_ADD_TC(tp, add_relay_agent_options_test);
- ATF_TP_ADD_TC(tp, gwaddr_override_test);
-
- return (atf_no_error());
-}