diff options
author | Tomek Mrugalski <tomek@isc.org> | 2022-03-30 15:56:52 +0200 |
---|---|---|
committer | Tomek Mrugalski <tomek@isc.org> | 2022-03-30 15:56:52 +0200 |
commit | 5f89e214d36d5b0b38a15d9dcdeaff9f571e0be3 (patch) | |
tree | 2731b1c01e399952f91017f9ef0884702e8e06ec | |
parent | 33226f2d76b6b7a06df6b76abbb3526100f5ae2d (diff) | |
download | isc-dhcp-5f89e214d36d5b0b38a15d9dcdeaff9f571e0be3.tar.gz |
[#227] client and relay code removed
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(©->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(©->options, lease->options, file, line); - - insert_ia = ©->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(©, 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 = ©->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(©, file, line); - return NULL; - } - - insert_addr = &(*insert_addr)->next; - } - - if (ia->options != NULL) - option_state_reference(©->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(©->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(©->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()); -} |