diff options
Diffstat (limited to 'dhcpctl')
-rw-r--r-- | dhcpctl/Makefile.am | 15 | ||||
-rw-r--r-- | dhcpctl/Makefile.in | 770 | ||||
-rw-r--r-- | dhcpctl/callback.c | 162 | ||||
-rw-r--r-- | dhcpctl/cltest.c | 179 | ||||
-rw-r--r-- | dhcpctl/dhcpctl.3 | 495 | ||||
-rw-r--r-- | dhcpctl/dhcpctl.c | 586 | ||||
-rw-r--r-- | dhcpctl/dhcpctl.h | 119 | ||||
-rw-r--r-- | dhcpctl/omshell.1 | 328 | ||||
-rw-r--r-- | dhcpctl/omshell.c | 738 | ||||
-rw-r--r-- | dhcpctl/remote.c | 355 |
10 files changed, 3747 insertions, 0 deletions
diff --git a/dhcpctl/Makefile.am b/dhcpctl/Makefile.am new file mode 100644 index 0000000..61049be --- /dev/null +++ b/dhcpctl/Makefile.am @@ -0,0 +1,15 @@ +bin_PROGRAMS = omshell +lib_LIBRARIES = libdhcpctl.a +noinst_PROGRAMS = cltest +man_MANS = omshell.1 dhcpctl.3 +EXTRA_DIST = $(man_MANS) + +omshell_SOURCES = omshell.c +omshell_LDADD = libdhcpctl.a ../common/libdhcp.a ../omapip/libomapi.a \ + ../bind/lib/libdns.a ../bind/lib/libisc.a + +libdhcpctl_a_SOURCES = dhcpctl.c callback.c remote.c + +cltest_SOURCES = cltest.c +cltest_LDADD = libdhcpctl.a ../common/libdhcp.a ../omapip/libomapi.a \ + ../bind/lib/libdns.a ../bind/lib/libisc.a
\ No newline at end of file diff --git a/dhcpctl/Makefile.in b/dhcpctl/Makefile.in new file mode 100644 index 0000000..31b3142 --- /dev/null +++ b/dhcpctl/Makefile.in @@ -0,0 +1,770 @@ +# Makefile.in generated by automake 1.14 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 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 = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +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@ +bin_PROGRAMS = omshell$(EXEEXT) +noinst_PROGRAMS = cltest$(EXEEXT) +subdir = dhcpctl +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp +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) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/includes/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +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; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ + "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man3dir)" +LIBRARIES = $(lib_LIBRARIES) +AR = ar +ARFLAGS = cru +AM_V_AR = $(am__v_AR_@AM_V@) +am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) +am__v_AR_0 = @echo " AR " $@; +am__v_AR_1 = +libdhcpctl_a_AR = $(AR) $(ARFLAGS) +libdhcpctl_a_LIBADD = +am_libdhcpctl_a_OBJECTS = dhcpctl.$(OBJEXT) callback.$(OBJEXT) \ + remote.$(OBJEXT) +libdhcpctl_a_OBJECTS = $(am_libdhcpctl_a_OBJECTS) +PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) +am_cltest_OBJECTS = cltest.$(OBJEXT) +cltest_OBJECTS = $(am_cltest_OBJECTS) +cltest_DEPENDENCIES = libdhcpctl.a ../common/libdhcp.a \ + ../omapip/libomapi.a ../bind/lib/libdns.a ../bind/lib/libisc.a +am_omshell_OBJECTS = omshell.$(OBJEXT) +omshell_OBJECTS = $(am_omshell_OBJECTS) +omshell_DEPENDENCIES = libdhcpctl.a ../common/libdhcp.a \ + ../omapip/libomapi.a ../bind/lib/libdns.a ../bind/lib/libisc.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__depfiles_maybe = depfiles +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 = $(libdhcpctl_a_SOURCES) $(cltest_SOURCES) $(omshell_SOURCES) +DIST_SOURCES = $(libdhcpctl_a_SOURCES) $(cltest_SOURCES) \ + $(omshell_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +man1dir = $(mandir)/man1 +man3dir = $(mandir)/man3 +NROFF = nroff +MANS = $(man_MANS) +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)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +ATF_BIN = @ATF_BIN@ +ATF_CFLAGS = @ATF_CFLAGS@ +ATF_LDFLAGS = @ATF_LDFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +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@ +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@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +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@ +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@ +lib_LIBRARIES = libdhcpctl.a +man_MANS = omshell.1 dhcpctl.3 +EXTRA_DIST = $(man_MANS) +omshell_SOURCES = omshell.c +omshell_LDADD = libdhcpctl.a ../common/libdhcp.a ../omapip/libomapi.a \ + ../bind/lib/libdns.a ../bind/lib/libisc.a + +libdhcpctl_a_SOURCES = dhcpctl.c callback.c remote.c +cltest_SOURCES = cltest.c +cltest_LDADD = libdhcpctl.a ../common/libdhcp.a ../omapip/libomapi.a \ + ../bind/lib/libdns.a ../bind/lib/libisc.a + +all: all-am + +.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 dhcpctl/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign dhcpctl/Makefile +.PRECIOUS: 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__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + 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-libLIBRARIES: $(lib_LIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(INSTALL_DATA) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(INSTALL_DATA) $$list2 "$(DESTDIR)$(libdir)" || exit $$?; } + @$(POST_INSTALL) + @list='$(lib_LIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + if test -f $$p; then \ + $(am__strip_dir) \ + echo " ( cd '$(DESTDIR)$(libdir)' && $(RANLIB) $$f )"; \ + ( cd "$(DESTDIR)$(libdir)" && $(RANLIB) $$f ) || exit $$?; \ + else :; fi; \ + done + +uninstall-libLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LIBRARIES)'; test -n "$(libdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libdir)'; $(am__uninstall_files_from_dir) + +clean-libLIBRARIES: + -test -z "$(lib_LIBRARIES)" || rm -f $(lib_LIBRARIES) + +libdhcpctl.a: $(libdhcpctl_a_OBJECTS) $(libdhcpctl_a_DEPENDENCIES) $(EXTRA_libdhcpctl_a_DEPENDENCIES) + $(AM_V_at)-rm -f libdhcpctl.a + $(AM_V_AR)$(libdhcpctl_a_AR) libdhcpctl.a $(libdhcpctl_a_OBJECTS) $(libdhcpctl_a_LIBADD) + $(AM_V_at)$(RANLIB) libdhcpctl.a +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || 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)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || 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)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) + +clean-noinstPROGRAMS: + -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) + +cltest$(EXEEXT): $(cltest_OBJECTS) $(cltest_DEPENDENCIES) $(EXTRA_cltest_DEPENDENCIES) + @rm -f cltest$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(cltest_OBJECTS) $(cltest_LDADD) $(LIBS) + +omshell$(EXEEXT): $(omshell_OBJECTS) $(omshell_DEPENDENCIES) $(EXTRA_omshell_DEPENDENCIES) + @rm -f omshell$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(omshell_OBJECTS) $(omshell_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/callback.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cltest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dhcpctl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omshell.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/remote.Po@am__quote@ + +.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-man1: $(man_MANS) + @$(NORMAL_INSTALL) + @list1=''; \ + list2='$(man_MANS)'; \ + test -n "$(man1dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man1dir)" || 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 '/\.1[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,^[^1][0-9a-z]*$$,1,;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)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$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)$(man1dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ + done; } + +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man1dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.1[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) +install-man3: $(man_MANS) + @$(NORMAL_INSTALL) + @list1=''; \ + list2='$(man_MANS)'; \ + test -n "$(man3dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man3dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man3dir)" || 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 '/\.3[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,^[^3][0-9a-z]*$$,3,;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)$(man3dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$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)$(man3dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \ + done; } + +uninstall-man3: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man3dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.3[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man3dir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(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-am + +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-am + +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: $(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 +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(MANS) +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man3dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +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-am + +clean-am: clean-binPROGRAMS clean-generic clean-libLIBRARIES \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS install-libLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man1 install-man3 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-libLIBRARIES \ + uninstall-man + +uninstall-man: uninstall-man1 uninstall-man3 + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ + clean-binPROGRAMS clean-generic clean-libLIBRARIES \ + clean-noinstPROGRAMS 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-binPROGRAMS 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-libLIBRARIES install-man install-man1 install-man3 \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \ + uninstall-libLIBRARIES uninstall-man uninstall-man1 \ + uninstall-man3 + + +# 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/dhcpctl/callback.c b/dhcpctl/callback.c new file mode 100644 index 0000000..2027a2d --- /dev/null +++ b/dhcpctl/callback.c @@ -0,0 +1,162 @@ +/* callback.c + + The dhcpctl callback object. */ + +/* + * Copyright (c) 2004,2007,2009,2014 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999-2003 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * <info@isc.org> + * https://www.isc.org/ + * + */ + +#include "dhcpd.h" +#include <omapip/omapip_p.h> +#include "dhcpctl.h" + +/* dhcpctl_set_callback + + synchronous, with asynchronous aftereffect + handle is some object upon which some kind of process has been + started - e.g., an open, an update or a refresh. + data is an anonymous pointer containing some information that + the callback will use to figure out what event completed. + return value of 0 means callback was successfully set, a nonzero + status code is returned otherwise. + Upon completion of whatever task is in process, the callback + will be passed the handle to the object, a status code + indicating what happened, and the anonymous pointer passed to */ + +dhcpctl_status dhcpctl_set_callback (dhcpctl_handle h, void *data, + void (*func) (dhcpctl_handle, + dhcpctl_status, void *)) +{ + dhcpctl_callback_object_t *callback; + omapi_object_t *inner; + + callback = dmalloc (sizeof *callback, MDL); + if (!callback) + return ISC_R_NOMEMORY; + + /* Tie the callback object to the innermost object in the chain. */ + for (inner = h; inner -> inner; inner = inner -> inner) + ; + omapi_object_reference (&inner -> inner, + (omapi_object_t *)callback, MDL); + omapi_object_reference ((omapi_object_t **)&callback -> outer, + inner, MDL); + + /* Save the actual handle pointer we were passed for the callback. */ + omapi_object_reference (&callback -> object, h, MDL); + callback -> data = data; + callback -> callback = func; + + return ISC_R_SUCCESS; +} + +/* Callback methods (not meant to be called directly) */ + +isc_result_t dhcpctl_callback_set_value (omapi_object_t *h, + omapi_object_t *id, + omapi_data_string_t *name, + omapi_typed_data_t *value) +{ + if (h -> type != dhcpctl_callback_type) + return DHCP_R_INVALIDARG; + + if (h -> inner && h -> inner -> type -> set_value) + return (*(h -> inner -> type -> set_value)) + (h -> inner, id, name, value); + return ISC_R_NOTFOUND; +} + +isc_result_t dhcpctl_callback_get_value (omapi_object_t *h, + omapi_object_t *id, + omapi_data_string_t *name, + omapi_value_t **value) +{ + if (h -> type != dhcpctl_callback_type) + return DHCP_R_INVALIDARG; + + if (h -> inner && h -> inner -> type -> get_value) + return (*(h -> inner -> type -> get_value)) + (h -> inner, id, name, value); + return ISC_R_NOTFOUND; +} + +isc_result_t dhcpctl_callback_signal_handler (omapi_object_t *o, + const char *name, va_list ap) +{ + dhcpctl_callback_object_t *p; + isc_result_t waitstatus; + + if (o -> type != dhcpctl_callback_type) + return DHCP_R_INVALIDARG; + p = (dhcpctl_callback_object_t *)o; + + /* Not a signal we recognize? */ + if (strcmp (name, "ready")) { + if (p -> inner && p -> inner -> type -> signal_handler) + return (*(p -> inner -> type -> signal_handler)) + (p -> inner, name, ap); + return ISC_R_NOTFOUND; + } + + if (p -> object -> type == dhcpctl_remote_type) { + waitstatus = (((dhcpctl_remote_object_t *) + (p -> object)) -> waitstatus); + } else + waitstatus = ISC_R_SUCCESS; + + /* Do the callback. */ + if (p -> callback) + (*(p -> callback)) (p -> object, waitstatus, p -> data); + + return ISC_R_SUCCESS; +} + +isc_result_t dhcpctl_callback_destroy (omapi_object_t *h, + const char *file, int line) +{ + dhcpctl_callback_object_t *p; + if (h -> type != dhcpctl_callback_type) + return DHCP_R_INVALIDARG; + p = (dhcpctl_callback_object_t *)h; + if (p -> handle) + omapi_object_dereference ((omapi_object_t **)&p -> handle, + file, line); + return ISC_R_SUCCESS; +} + +/* Write all the published values associated with the object through the + specified connection. */ + +isc_result_t dhcpctl_callback_stuff_values (omapi_object_t *c, + omapi_object_t *id, + omapi_object_t *p) +{ + if (p -> type != dhcpctl_callback_type) + return DHCP_R_INVALIDARG; + + if (p -> inner && p -> inner -> type -> stuff_values) + return (*(p -> inner -> type -> stuff_values)) (c, id, + p -> inner); + return ISC_R_SUCCESS; +} + diff --git a/dhcpctl/cltest.c b/dhcpctl/cltest.c new file mode 100644 index 0000000..dfc2c87 --- /dev/null +++ b/dhcpctl/cltest.c @@ -0,0 +1,179 @@ +/* cltest.c + + Example program that uses the dhcpctl library. */ + +/* + * Copyright (c) 2004,2007,2009 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2000-2003 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * <info@isc.org> + * https://www.isc.org/ + * + * This software was contributed to Internet Systems Consortium + * by Brian Murrell. + */ + +#include <time.h> +#include <sys/time.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include "omapip/result.h" +#include "dhcpctl.h" + +int main (int, char **); + +enum modes { up, down, undefined }; + +static void usage (char *s) { + fprintf (stderr, + "Usage: %s [-n <username>] [-p <password>] [-a <algorithm>]" + "(-u | -d) <if>\n", s); + exit (1); +} + +int main (argc, argv) + int argc; + char **argv; +{ + isc_result_t status, waitstatus; + dhcpctl_handle authenticator; + dhcpctl_handle connection; + dhcpctl_handle interface_handle; + dhcpctl_data_string result; + int i; + int mode = undefined; + const char *interface = 0; + const char *action; + + for (i = 1; i < argc; i++) { + if (!strcmp (argv[i], "-u")) { + mode = up; + } else if (!strcmp (argv [i], "-d")) { + mode = down; + } else if (argv[i][0] == '-') { + usage(argv[0]); + } else { + interface = argv[i]; + } + } + + if (!interface) + usage(argv[0]); + if (mode == undefined) + usage(argv[0]); + + status = dhcpctl_initialize (); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_initialize: %s\n", + isc_result_totext (status)); + exit (1); + } + + authenticator = dhcpctl_null_handle; + connection = dhcpctl_null_handle; + + status = dhcpctl_connect (&connection, "127.0.0.1", 7911, + authenticator); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_connect: %s\n", + isc_result_totext (status)); + exit (1); + } + + interface_handle = dhcpctl_null_handle; + status = dhcpctl_new_object (&interface_handle, + connection, "interface"); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_new_object: %s\n", + isc_result_totext (status)); + exit (1); + } + + status = dhcpctl_set_string_value (interface_handle, + interface, "name"); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_set_value: %s\n", + isc_result_totext (status)); + exit (1); + } + + if (mode == up) { + /* "up" the interface */ + printf ("upping interface %s\n", interface); + action = "create"; + status = dhcpctl_open_object (interface_handle, connection, + DHCPCTL_CREATE | DHCPCTL_EXCL); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_open_object: %s\n", + isc_result_totext (status)); + exit (1); + } + } else { + /* down the interface */ + printf ("downing interface %s\n", interface); + action = "remove"; + status = dhcpctl_open_object (interface_handle, connection, 0); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_open_object: %s\n", + isc_result_totext (status)); + exit (1); + } + status = dhcpctl_wait_for_completion (interface_handle, + &waitstatus); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_wait_for_completion: %s\n", + isc_result_totext (status)); + exit (1); + } + if (waitstatus != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_wait_for_completion: %s\n", + isc_result_totext (waitstatus)); + exit (1); + } + status = dhcpctl_object_remove (connection, interface_handle); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_open_object: %s\n", + isc_result_totext (status)); + exit (1); + } + } + + status = dhcpctl_wait_for_completion (interface_handle, &waitstatus); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_wait_for_completion: %s\n", + isc_result_totext (status)); + exit (1); + } + if (waitstatus != ISC_R_SUCCESS) { + fprintf (stderr, "interface object %s: %s\n", action, + isc_result_totext (waitstatus)); + exit (1); + } + + memset (&result, 0, sizeof result); + status = dhcpctl_get_value (&result, interface_handle, "state"); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_get_value: %s\n", + isc_result_totext (status)); + exit (1); + } + + exit (0); +} diff --git a/dhcpctl/dhcpctl.3 b/dhcpctl/dhcpctl.3 new file mode 100644 index 0000000..ae42a71 --- /dev/null +++ b/dhcpctl/dhcpctl.3 @@ -0,0 +1,495 @@ +.\" -*- nroff -*- +.\" +.\" Project: DHCP +.\" File: dhcpctl.3 +.\" RCSId: $Id: dhcpctl.3,v 1.7.24.2 2011/04/25 23:49:52 sar Exp $ +.\" +.\" Copyright (c) 2011,2014 by Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (c) 2004,2009 by Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (c) 2000-2003 by Internet Software Consortium +.\" Copyright (c) 2000 Nominum, Inc. +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +.\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.\" Internet Systems Consortium, Inc. +.\" 950 Charter Street +.\" Redwood City, CA 94063 +.\" <info@isc.org> +.\" https://www.isc.org/ +.\" +.\" Description: dhcpctl man page. +.\" +.\" +.Dd Nov 15, 2000 +.Dt DHCPCTL 3 +.Os DHCP 3 +.ds vT DHCP Programmer's Manual +.\" +.\" +.\" +.Sh NAME +.Nm dhcpctl_initialize +.Nd dhcpctl library initialization. +.\" +.\" +.\" +.Sh SYNOPSIS +.Fd #include <dhcpctl/dhcpctl.h> +.Ft dhcpctl_status +.Fo dhcpctl_initialize +.Fa void +.Fc +.\" +.Ft dhcpctl_status +.Fo dhcpctl_connect +.Fa "dhcpctl_handle *cxn" +.Fa "const char *host" +.Fa "int port" +.Fa "dhcpctl_handle auth" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_wait_for_completion +.Fa "dhcpctl_handle object" +.Fa "dhcpctl_status *status" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_get_value +.Fa "dhcpctl_data_string *value" +.Fa "dhcpctl_handle object" +.Fa "const char *name" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_get_boolean +.Fa "int *value" +.Fa "dhcpctl_handle object" +.Fa "const char *name" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_set_value +.Fa "dhcpctl_handle object" +.Fa "dhcpctl_data_string value" +.Fa "const char *name" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_set_string_value +.Fa "dhcpctl_handle object" +.Fa "const char *value" +.Fa "const char *name" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_set_boolean_value +.Fa "dhcpctl_handle object" +.Fa "int value" +.Fa "const char *name" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_set_int_value +.Fa "dhcpctl_handle object" +.Fa "int value" +.Fa "const char *name" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_object_update +.Fa "dhcpctl_handle connection" +.Fa "dhcpctl_handle object" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_object_refresh +.Fa "dhcpctl_handle connection" +.Fa "dhcpctl_handle object" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_object_remove +.Fa "dhcpctl_handle connection" +.Fa "dhcpctl_handle object" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_set_callback +.Fa "dhcpctl_handle object" +.Fa "void *data" +.Fa "void (*function) (dhcpctl_handle, dhcpctl_status, void *)" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_new_authenticator +.Fa "dhcpctl_handle *object" +.Fa "const char *name" +.Fa "const char *algorithm" +.Fa "const char *secret" +.Fa "unsigned secret_len" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_new_object +.Fa "dhcpctl_handle *object" +.Fa "dhcpctl_handle connection" +.Fa "const char *object_type" +.Fc +.\" +.\" +.\" +.Ft dhcpctl_status +.Fo dhcpctl_open_object +.Fa "dhcpctl_handle object" +.Fa "dhcpctl_handle connection" +.Fa "int flags" +.Fc +.\" +.\" +.\" +.Ft isc_result_t +.Fo omapi_data_string_new +.Fa dhcpctl_data_string *data +.Fa unsigned int length +.Fa const char *filename, +.Fa int lineno +.Fc +.\" +.\" +.\" +.Ft isc_result_t +.Fo dhcpctl_data_string_dereference +.Fa "dhcpctl_data_string *" +.Fa "const char *" +.Fa "int" +.Fc +.Sh DESCRIPTION +The dhcpctl set of functions provide an API that can be used to communicate +with and manipulate a running ISC DHCP server. All functions return a value of +.Dv isc_result_t . +The return values reflects the result of operations to local data +structures. If an operation fails on the server for any reason, then the error +result will be returned through the +second parameter of the +.Fn dhcpctl_wait_for_completion +call. +.\" +.\" +.\" +.Pp +.Fn dhcpctl_initialize +sets up the data structures the library needs to do its work. This function +must be called once before any other. +.Pp +.Fn dhcpctl_connect +opens a connection to the DHCP server at the given host and port. If an +authenticator has been created for the connection, then it is given as the 4th +argument. On a successful return the address pointed at by the first +argument will have a new connection object assigned to it. +.Pp +For example: +.Bd -literal -offset indent +s = dhcpctl_connect(&cxn, "127.0.0.1", 7911, NULL); +.Ed +.Pp +connects to the DHCP server on the localhost via port 7911 (the standard +OMAPI port). No authentication is used for the connection. +.\" +.\" +.\" +.Pp +.Fn dhcpctl_wait_for_completion +flushes a pending message to the server and waits for the response. The result +of the request as processed on the server is returned via the second +parameter. +.Bd -literal -offset indent +s = dhcpctl_wait_for_completion(cxn, &wv); +if (s != ISC_R_SUCCESS) + local_failure(s); +else if (wv != ISC_R_SUCCESS) + server_failure(wc); +.Ed +.Pp +The call to +.Fn dhcpctl_wait_for_completion +won't return until the remote message processing completes or the connection +to the server is lost. +.\" +.\" +.\" +.Pp +.Fn dhcpctl_get_value +extracts a value of an attribute from the handle. The value can be of any +length and is treated as a sequence of bytes. The handle must have been +created first with +.Fn dhcpctl_new_object +and opened with +.Fn dhcpctl_open_object . +The value is returned via the parameter named +.Dq value . +The last parameter is the name of attribute to retrieve. +.Bd -literal -offset indent +dhcpctl_data_string value = NULL; +dhcpctl_handle lease; +time_t thetime; + +s = dhcpctl_get_value (&value, lease, "ends"); +assert(s == ISC_R_SUCCESS && value->len == sizeof(thetime)); +memcpy(&thetime, value->value, value->len); +.Ed +.\" +.\" +.\" +.Pp +.Fn dhcpctl_get_boolean +extracts a boolean valued attribute from the object handle. +.\" +.\" +.\" +.Pp +The +.Fn dhcpctl_set_value , +.Fn dhcpctl_set_string_value , +.Fn dhcpctl_set_boolean_value , +and +.Fn dhcpctl_set_int_value +functions all set a value on the object handle. +.\" +.\" +.\" +.Pp +.Fn dhcpctl_object_update +function queues a request for +all the changes made to the object handle be sent to the remote +for processing. The changes made to the attributes on the handle will be +applied to remote object if permitted. +.\" +.\" +.\" +.Pp +.Fn dhcpctl_object_refresh +queues up a request for a fresh copy of all the attribute values to be sent +from the remote to +refresh the values in the local object handle. +.\" +.\" +.\" +.Pp +.Fn dhcpctl_object_remove +queues a request for the removal on the server of the object referenced by the +handle. +.\" +.\" +.\" +.Pp +The +.Fn dhcpctl_set_callback +function sets up a user-defined function to be called when an event completes +on the given object handle. This is needed for asynchronous handling of +events, versus the synchronous handling given by +.Fn dhcpctl_wait_for_completion . +When the function is called the first parameter is the object the event +arrived for, the second is the status of the message that was processed, the +third is the same value as the second parameter given to +.Fn dhcpctl_set_callback . +.\" +.\" +.\" +.Pp +The +.Fn dhcpctl_new_authenticator +creates a new authenticator object to be used for signing the messages +that cross over the network. The +.Dq name , +.Dq algorithm , +and +.Dq secret +values must all match what the server uses and are defined in its +configuration file. The created object is returned through the first parameter +and must be used as the 4th parameter to +.Fn dhcpctl_connect . +Note that the 'secret' value must not be base64 encoded, which is different +from how the value appears in the dhcpd.conf file. +.\" +.\" +.\" +.Pp +.Fn dhcpctl_new_object +creates a local handle for an object on the server. The +.Dq object_type +parameter is the ascii name of the type of object being accessed. e.g. +.Qq lease . +This function only sets up local data structures, it does not queue any +messages +to be sent to the remote side, +.Fn dhcpctl_open_object +does that. +.\" +.\" +.\" +.Pp +.Fn dhcpctl_open_object +builds and queues the request to the remote side. This function is used with +handle created via +.Fn dhcpctl_new_object . +The flags argument is a bit mask with the following values available for +setting: +.Bl -tag -offset indent -width 20 +.It DHCPCTL_CREATE +if the object does not exist then the remote will create it +.It DHCPCTL_UPDATE +update the object on the remote side using the +attributes already set in the handle. +.It DHCPCTL_EXCL +return and error if the object exists and DHCPCTL_CREATE +was also specified +.El +.\" +.\" +.\" +.Pp +The +.Fn omapi_data_string_new +function allocates a new +.Ft dhcpctl_data_string +object. The data string will be large enough to hold +.Dq length +bytes of data. The +.Dq file +and +.Dq lineno +arguments are the source file location the call is made from, typically by +using the +.Dv __FILE__ +and +.Dv __LINE__ +macros or the +.Dv MDL +macro defined in +. +.\" +.\" +.\" +.Pp +.Fn dhcpctl_data_string_dereference +deallocates a data string created by +.Fn omapi_data_string_new . +The memory for the object won't be freed until the last reference is +released. +.Sh EXAMPLES +.Pp +The following program will connect to the DHCP server running on the local +host and will get the details of the existing lease for IP address +10.0.0.101. It will then print out the time the lease is due to expire. Note +that most error checking has been omitted for brevity. +.Bd -literal -offset indent +#include <sys/time.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> + +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "omapip/result.h" +#include "dhcpctl.h" + +int main (int argc, char **argv) { + dhcpctl_data_string ipaddrstring = NULL; + dhcpctl_data_string value = NULL; + dhcpctl_handle connection = NULL; + dhcpctl_handle lease = NULL; + isc_result_t waitstatus; + struct in_addr convaddr; + time_t thetime; + + dhcpctl_initialize (); + + dhcpctl_connect (&connection, "127.0.0.1", + 7911, 0); + + dhcpctl_new_object (&lease, connection, + "lease"); + + memset (&ipaddrstring, 0, sizeof + ipaddrstring); + + inet_pton(AF_INET, "10.0.0.101", + &convaddr); + + omapi_data_string_new (&ipaddrstring, + 4, MDL); + memcpy(ipaddrstring->value, &convaddr.s_addr, 4); + + dhcpctl_set_value (lease, ipaddrstring, + "ip-address"); + + dhcpctl_open_object (lease, connection, 0); + + dhcpctl_wait_for_completion (lease, + &waitstatus); + if (waitstatus != ISC_R_SUCCESS) { + /* server not authoritative */ + exit (0); + } + + dhcpctl_data_string_dereference(&ipaddrstring, + MDL); + + dhcpctl_get_value (&value, lease, "ends"); + + memcpy(&thetime, value->value, value->len); + + dhcpctl_data_string_dereference(&value, MDL); + + fprintf (stdout, "ending time is %s", + ctime(&thetime)); +} +.Ed +.Sh SEE ALSO +omapi(3), omshell(1), dhcpd(8), dhclient(8), dhcpd.conf(5), dhclient.conf(5). +.Sh AUTHOR +.Em dhcpctl +is maintained by ISC. To learn more about Internet Systems Consortium, +see +.B https://www.isc.org + diff --git a/dhcpctl/dhcpctl.c b/dhcpctl/dhcpctl.c new file mode 100644 index 0000000..511197e --- /dev/null +++ b/dhcpctl/dhcpctl.c @@ -0,0 +1,586 @@ +/* dhcpctl.c + + Subroutines providing general support for objects. */ + +/* + * Copyright (c) 2009,2013,2014 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2004,2007 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999-2003 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * <info@isc.org> + * https://www.isc.org/ + * + */ + +#include "dhcpd.h" +#include <omapip/omapip_p.h> +#include "dhcpctl.h" + +omapi_object_type_t *dhcpctl_callback_type; +omapi_object_type_t *dhcpctl_remote_type; + +/* dhcpctl_initialize () + + Must be called before any other dhcpctl function. */ + +dhcpctl_status dhcpctl_initialize () +{ + isc_result_t status; + + /* Set up the isc and dns library managers */ + status = dhcp_context_create(); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_init(); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_object_type_register (&dhcpctl_callback_type, + "dhcpctl-callback", + dhcpctl_callback_set_value, + dhcpctl_callback_get_value, + dhcpctl_callback_destroy, + dhcpctl_callback_signal_handler, + dhcpctl_callback_stuff_values, + 0, 0, 0, 0, 0, 0, + sizeof + (dhcpctl_callback_object_t), 0, + RC_MISC); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_object_type_register (&dhcpctl_remote_type, + "dhcpctl-remote", + dhcpctl_remote_set_value, + dhcpctl_remote_get_value, + dhcpctl_remote_destroy, + dhcpctl_remote_signal_handler, + dhcpctl_remote_stuff_values, + 0, 0, 0, 0, 0, 0, + sizeof (dhcpctl_remote_object_t), + 0, RC_MISC); + if (status != ISC_R_SUCCESS) + return status; + + return ISC_R_SUCCESS; +} + +/* dhcpctl_connect + + synchronous + returns nonzero status code if it didn't connect, zero otherwise + stores connection handle through connection, which can be used + for subsequent access to the specified server. + server_name is the name of the server, and port is the TCP + port on which it is listening. + authinfo is the handle to an object containing authentication + information. */ + +dhcpctl_status dhcpctl_connect (dhcpctl_handle *connection, + const char *server_name, int port, + dhcpctl_handle authinfo) +{ + isc_result_t status; + + status = omapi_generic_new (connection, MDL); + if (status != ISC_R_SUCCESS) { + return status; + } + + status = omapi_protocol_connect (*connection, server_name, + (unsigned)port, authinfo); + if (status == ISC_R_SUCCESS) + return status; + if (status != DHCP_R_INCOMPLETE) { + omapi_object_dereference (connection, MDL); + return status; + } + + status = omapi_wait_for_completion (*connection, 0); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (connection, MDL); + return status; + } + + return status; +} + +/* dhcpctl_wait_for_completion + + synchronous + returns zero if the callback completes, a nonzero status if + there was some problem relating to the wait operation. The + status of the queued request will be stored through s, and + will also be either zero for success or nonzero for some kind + of failure. Never returns until completion or until the + connection to the server is lost. This performs the same + function as dhcpctl_set_callback and the subsequent callback, + for programs that want to do inline execution instead of using + callbacks. */ + +dhcpctl_status dhcpctl_wait_for_completion (dhcpctl_handle h, + dhcpctl_status *s) +{ + isc_result_t status; + status = omapi_wait_for_completion (h, 0); + if (status != ISC_R_SUCCESS) + return status; + if (h -> type == dhcpctl_remote_type) + *s = ((dhcpctl_remote_object_t *)h) -> waitstatus; + return ISC_R_SUCCESS; +} + +/* dhcpctl_get_value + + synchronous + returns zero if the call succeeded, a nonzero status code if + it didn't. + result is the address of an empty data string (initialized + with bzero or cleared with data_string_forget). On + successful completion, the addressed data string will contain + the value that was fetched. + dhcpctl_handle refers to some dhcpctl item + value_name refers to some value related to that item - e.g., + for a handle associated with a completed host lookup, value + could be one of "hardware-address", "dhcp-client-identifier", + "known" or "client-hostname". */ + +dhcpctl_status dhcpctl_get_value (dhcpctl_data_string *result, + dhcpctl_handle h, const char *value_name) +{ + isc_result_t status; + omapi_value_t *tv = (omapi_value_t *)0; + unsigned len; + int ip; + + status = omapi_get_value_str (h, (omapi_object_t *)0, value_name, &tv); + if (status != ISC_R_SUCCESS) + return status; + + switch (tv -> value -> type) { + case omapi_datatype_int: + len = sizeof (int); + break; + + case omapi_datatype_string: + case omapi_datatype_data: + len = tv -> value -> u.buffer.len; + break; + + case omapi_datatype_object: + len = sizeof (omapi_handle_t); + break; + + default: + omapi_typed_data_dereference (&tv -> value, MDL); + return ISC_R_UNEXPECTED; + } + + status = omapi_data_string_new (result, len, MDL); + if (status != ISC_R_SUCCESS) { + omapi_typed_data_dereference (&tv -> value, MDL); + return status; + } + + switch (tv -> value -> type) { + case omapi_datatype_int: + ip = htonl (tv -> value -> u.integer); + memcpy ((*result) -> value, &ip, sizeof ip); + break; + + case omapi_datatype_string: + case omapi_datatype_data: + memcpy ((*result) -> value, + tv -> value -> u.buffer.value, + tv -> value -> u.buffer.len); + break; + + case omapi_datatype_object: + ip = htonl (tv -> value -> u.object -> handle); + memcpy ((*result) -> value, &ip, sizeof ip); + break; + } + + omapi_value_dereference (&tv, MDL); + return ISC_R_SUCCESS; +} + +/* dhcpctl_get_boolean + + like dhcpctl_get_value, but more convenient for boolean + values, since no data_string needs to be dealt with. */ + +dhcpctl_status dhcpctl_get_boolean (int *result, + dhcpctl_handle h, const char *value_name) +{ + isc_result_t status; + dhcpctl_data_string data = (dhcpctl_data_string)0; + int rv; + + status = dhcpctl_get_value (&data, h, value_name); + if (status != ISC_R_SUCCESS) + return status; + if (data -> len != sizeof rv) { + omapi_data_string_dereference (&data, MDL); + return ISC_R_UNEXPECTED; + } + memcpy (&rv, data -> value, sizeof rv); + *result = ntohl (rv); + omapi_data_string_dereference (&data, MDL); + return ISC_R_SUCCESS; +} + +/* dhcpctl_set_value + + Sets a value on an object referred to by a dhcpctl_handle. + The opposite of dhcpctl_get_value. Does not update the + server - just sets the value on the handle. */ + +dhcpctl_status dhcpctl_set_value (dhcpctl_handle h, dhcpctl_data_string value, + const char *value_name) +{ + isc_result_t status; + omapi_typed_data_t *tv = (omapi_typed_data_t *)0; + omapi_data_string_t *name = (omapi_data_string_t *)0; + + status = omapi_data_string_new (&name, strlen (value_name), MDL); + if (status != ISC_R_SUCCESS) + return status; + memcpy (name -> value, value_name, strlen (value_name)); + + status = omapi_typed_data_new (MDL, &tv, omapi_datatype_data, + value -> len); + if (status != ISC_R_SUCCESS) { + omapi_data_string_dereference (&name, MDL); + return status; + } + memcpy (tv -> u.buffer.value, value -> value, value -> len); + + status = omapi_set_value (h, (omapi_object_t *)0, name, tv); + omapi_data_string_dereference (&name, MDL); + omapi_typed_data_dereference (&tv, MDL); + return status; +} + +/* dhcpctl_set_string_value + + Sets a NUL-terminated ASCII value on an object referred to by + a dhcpctl_handle. like dhcpctl_set_value, but saves the + trouble of creating a data_string for a NUL-terminated string. + Does not update the server - just sets the value on the handle. */ + +dhcpctl_status dhcpctl_set_string_value (dhcpctl_handle h, const char *value, + const char *value_name) +{ + isc_result_t status; + omapi_typed_data_t *tv = (omapi_typed_data_t *)0; + omapi_data_string_t *name = (omapi_data_string_t *)0; + + status = omapi_data_string_new (&name, strlen (value_name), MDL); + if (status != ISC_R_SUCCESS) + return status; + memcpy (name -> value, value_name, strlen (value_name)); + + status = omapi_typed_data_new (MDL, &tv, omapi_datatype_string, value); + if (status != ISC_R_SUCCESS) { + omapi_data_string_dereference (&name, MDL); + return status; + } + + status = omapi_set_value (h, (omapi_object_t *)0, name, tv); + omapi_data_string_dereference (&name, MDL); + omapi_typed_data_dereference (&tv, MDL); + return status; +} + +/* dhcpctl_set_buffer_value + + Sets a value on an object referred to by a dhcpctl_handle. like + dhcpctl_set_value, but saves the trouble of creating a data_string + for string for which we have a buffer and length. Does not update + the server - just sets the value on the handle. */ + +dhcpctl_status dhcpctl_set_data_value (dhcpctl_handle h, + const char *value, unsigned len, + const char *value_name) +{ + isc_result_t status; + omapi_typed_data_t *tv = (omapi_typed_data_t *)0; + omapi_data_string_t *name = (omapi_data_string_t *)0; + unsigned ll; + + ll = strlen (value_name); + status = omapi_data_string_new (&name, ll, MDL); + if (status != ISC_R_SUCCESS) + return status; + memcpy (name -> value, value_name, ll); + + status = omapi_typed_data_new (MDL, &tv, + omapi_datatype_data, len, value); + if (status != ISC_R_SUCCESS) { + omapi_data_string_dereference (&name, MDL); + return status; + } + memcpy (tv -> u.buffer.value, value, len); + + status = omapi_set_value (h, (omapi_object_t *)0, name, tv); + omapi_data_string_dereference (&name, MDL); + omapi_typed_data_dereference (&tv, MDL); + return status; +} + +/* dhcpctl_set_null_value + + Sets a null value on an object referred to by a dhcpctl_handle. */ + +dhcpctl_status dhcpctl_set_null_value (dhcpctl_handle h, + const char *value_name) +{ + isc_result_t status; + omapi_data_string_t *name = (omapi_data_string_t *)0; + unsigned ll; + + ll = strlen (value_name); + status = omapi_data_string_new (&name, ll, MDL); + if (status != ISC_R_SUCCESS) + return status; + memcpy (name -> value, value_name, ll); + + status = omapi_set_value (h, (omapi_object_t *)0, name, + (omapi_typed_data_t *)0); + omapi_data_string_dereference (&name, MDL); + return status; +} + +/* dhcpctl_set_boolean_value + + Sets a boolean value on an object - like dhcpctl_set_value, + only more convenient for booleans. */ + +dhcpctl_status dhcpctl_set_boolean_value (dhcpctl_handle h, int value, + const char *value_name) +{ + isc_result_t status; + omapi_typed_data_t *tv = (omapi_typed_data_t *)0; + omapi_data_string_t *name = (omapi_data_string_t *)0; + + status = omapi_data_string_new (&name, strlen (value_name), MDL); + if (status != ISC_R_SUCCESS) + return status; + memcpy (name -> value, value_name, strlen (value_name)); + + status = omapi_typed_data_new (MDL, &tv, omapi_datatype_int, value); + if (status != ISC_R_SUCCESS) { + omapi_data_string_dereference (&name, MDL); + return status; + } + + status = omapi_set_value (h, (omapi_object_t *)0, name, tv); + omapi_data_string_dereference (&name, MDL); + omapi_typed_data_dereference (&tv, MDL); + return status; +} + +/* dhcpctl_set_int_value + + Sets a boolean value on an object - like dhcpctl_set_value, + only more convenient for booleans. */ + +dhcpctl_status dhcpctl_set_int_value (dhcpctl_handle h, int value, + const char *value_name) +{ + isc_result_t status; + omapi_typed_data_t *tv = (omapi_typed_data_t *)0; + omapi_data_string_t *name = (omapi_data_string_t *)0; + + status = omapi_data_string_new (&name, strlen (value_name), MDL); + if (status != ISC_R_SUCCESS) + return status; + memcpy (name -> value, value_name, strlen (value_name)); + + status = omapi_typed_data_new (MDL, &tv, omapi_datatype_int, value); + if (status != ISC_R_SUCCESS) { + omapi_data_string_dereference (&name, MDL); + return status; + } + + status = omapi_set_value (h, (omapi_object_t *)0, name, tv); + omapi_data_string_dereference (&name, MDL); + omapi_typed_data_dereference (&tv, MDL); + return status; +} + +/* dhcpctl_object_update + + Queues an update on the object referenced by the handle (there + can't be any other work in progress on the handle). An + update means local parameters will be sent to the server. */ + +dhcpctl_status dhcpctl_object_update (dhcpctl_handle connection, + dhcpctl_handle h) +{ + isc_result_t status; + omapi_object_t *message = (omapi_object_t *)0; + dhcpctl_remote_object_t *ro; + + if (h -> type != dhcpctl_remote_type) + return DHCP_R_INVALIDARG; + ro = (dhcpctl_remote_object_t *)h; + + status = omapi_message_new (&message, MDL); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + status = omapi_set_int_value (message, (omapi_object_t *)0, + "op", OMAPI_OP_UPDATE); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + + status = omapi_set_object_value (message, (omapi_object_t *)0, + "object", h); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + + status = omapi_set_int_value (message, (omapi_object_t *)0, "handle", + (int)(ro -> remote_handle)); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + + omapi_message_register (message); + status = omapi_protocol_send_message (connection -> outer, + (omapi_object_t *)0, + message, (omapi_object_t *)0); + omapi_object_dereference (&message, MDL); + return status; +} + +/* Requests a refresh on the object referenced by the handle (there + can't be any other work in progress on the handle). A + refresh means local parameters are updated from the server. */ + +dhcpctl_status dhcpctl_object_refresh (dhcpctl_handle connection, + dhcpctl_handle h) +{ + isc_result_t status; + omapi_object_t *message = (omapi_object_t *)0; + dhcpctl_remote_object_t *ro; + + if (h -> type != dhcpctl_remote_type) + return DHCP_R_INVALIDARG; + ro = (dhcpctl_remote_object_t *)h; + + status = omapi_message_new (&message, MDL); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + status = omapi_set_int_value (message, (omapi_object_t *)0, + "op", OMAPI_OP_REFRESH); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + status = omapi_set_int_value (message, (omapi_object_t *)0, + "handle", (int)(ro -> remote_handle)); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + + omapi_message_register (message); + status = omapi_protocol_send_message (connection -> outer, + (omapi_object_t *)0, + message, (omapi_object_t *)0); + + /* We don't want to send the contents of the object down the + wire, but we do need to reference it so that we know what + to do with the update. */ + status = omapi_set_object_value (message, (omapi_object_t *)0, + "object", h); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + + omapi_object_dereference (&message, MDL); + return status; +} + +/* Requests the removal of the object referenced by the handle (there + can't be any other work in progress on the handle). A + removal means that all searchable references to the object on the + server are deleted. */ + +dhcpctl_status dhcpctl_object_remove (dhcpctl_handle connection, + dhcpctl_handle h) +{ + isc_result_t status; + omapi_object_t *message = (omapi_object_t *)0; + dhcpctl_remote_object_t *ro; + + if (h -> type != dhcpctl_remote_type) + return DHCP_R_INVALIDARG; + ro = (dhcpctl_remote_object_t *)h; + + status = omapi_message_new (&message, MDL); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + status = omapi_set_int_value (message, (omapi_object_t *)0, + "op", OMAPI_OP_DELETE); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + + status = omapi_set_int_value (message, (omapi_object_t *)0, "handle", + (int)(ro -> remote_handle)); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + + status = omapi_set_object_value (message, (omapi_object_t *)0, + "notify-object", h); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + + omapi_message_register (message); + status = omapi_protocol_send_message (connection -> outer, + (omapi_object_t *)0, + message, (omapi_object_t *)0); + omapi_object_dereference (&message, MDL); + return status; +} + +isc_result_t dhcpctl_data_string_dereference (dhcpctl_data_string *vp, + const char *file, int line) +{ + return omapi_data_string_dereference (vp, file, line); +} diff --git a/dhcpctl/dhcpctl.h b/dhcpctl/dhcpctl.h new file mode 100644 index 0000000..bfdb0cb --- /dev/null +++ b/dhcpctl/dhcpctl.h @@ -0,0 +1,119 @@ +/* $Id: dhcpctl.h,v 1.17.24.1 2009/11/20 01:49:01 sar Exp $ + + Subroutines providing general support for objects. */ + +/* + * Copyright (c) 2004,2009,2014 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999-2003 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * <info@isc.org> + * https://www.isc.org/ + * + */ + +#ifndef _DHCPCTL_H_ +#define _DHCPCTL_H_ + +#include <omapip/omapip.h> + +typedef isc_result_t dhcpctl_status; +typedef omapi_object_t *dhcpctl_handle; +typedef omapi_data_string_t *dhcpctl_data_string; + +#define dhcpctl_null_handle ((dhcpctl_handle) 0) + +#define DHCPCTL_CREATE OMAPI_CREATE +#define DHCPCTL_UPDATE OMAPI_UPDATE +#define DHCPCTL_EXCL OMAPI_EXCL + +typedef struct { + OMAPI_OBJECT_PREAMBLE; + omapi_object_t *object; + void *data; + void (*callback) (dhcpctl_handle, dhcpctl_status, void *); +} dhcpctl_callback_object_t; + +typedef struct { + OMAPI_OBJECT_PREAMBLE; + omapi_typed_data_t *rtype; + isc_result_t waitstatus; + omapi_typed_data_t *message; + omapi_handle_t remote_handle; +} dhcpctl_remote_object_t; + +extern omapi_object_type_t *dhcpctl_callback_type; +extern omapi_object_type_t *dhcpctl_remote_type; + +dhcpctl_status dhcpctl_initialize (void); +dhcpctl_status dhcpctl_connect (dhcpctl_handle *, + const char *, int, dhcpctl_handle); +dhcpctl_status dhcpctl_wait_for_completion (dhcpctl_handle, dhcpctl_status *); +dhcpctl_status dhcpctl_get_value (dhcpctl_data_string *, + dhcpctl_handle, const char *); +dhcpctl_status dhcpctl_get_boolean (int *, dhcpctl_handle, const char *); +dhcpctl_status dhcpctl_set_value (dhcpctl_handle, + dhcpctl_data_string, const char *); +dhcpctl_status dhcpctl_set_string_value (dhcpctl_handle, const char *, + const char *); +dhcpctl_status dhcpctl_set_data_value (dhcpctl_handle, + const char *, unsigned, const char *); +dhcpctl_status dhcpctl_set_null_value (dhcpctl_handle, const char *); +dhcpctl_status dhcpctl_set_boolean_value (dhcpctl_handle, int, const char *); +dhcpctl_status dhcpctl_set_int_value (dhcpctl_handle, int, const char *); +dhcpctl_status dhcpctl_object_update (dhcpctl_handle, dhcpctl_handle); +dhcpctl_status dhcpctl_object_refresh (dhcpctl_handle, dhcpctl_handle); +dhcpctl_status dhcpctl_object_remove (dhcpctl_handle, dhcpctl_handle); + +dhcpctl_status dhcpctl_set_callback (dhcpctl_handle, void *, + void (*) (dhcpctl_handle, + dhcpctl_status, void *)); +isc_result_t dhcpctl_callback_set_value (omapi_object_t *, omapi_object_t *, + omapi_data_string_t *, + omapi_typed_data_t *); +isc_result_t dhcpctl_callback_get_value (omapi_object_t *, omapi_object_t *, + omapi_data_string_t *, + omapi_value_t **); +isc_result_t dhcpctl_callback_destroy (omapi_object_t *, const char *, int); +isc_result_t dhcpctl_callback_signal_handler (omapi_object_t *, + const char *, va_list); +isc_result_t dhcpctl_callback_stuff_values (omapi_object_t *, + omapi_object_t *, + omapi_object_t *); + +dhcpctl_status dhcpctl_new_authenticator (dhcpctl_handle *, + const char *, const char *, + const unsigned char *, unsigned); + +dhcpctl_status dhcpctl_open_object (dhcpctl_handle, dhcpctl_handle, int); +dhcpctl_status dhcpctl_new_object (dhcpctl_handle *, + dhcpctl_handle, const char *); +isc_result_t dhcpctl_remote_set_value (omapi_object_t *, omapi_object_t *, + omapi_data_string_t *, + omapi_typed_data_t *); +isc_result_t dhcpctl_remote_get_value (omapi_object_t *, omapi_object_t *, + omapi_data_string_t *, + omapi_value_t **); +isc_result_t dhcpctl_remote_destroy (omapi_object_t *, const char *, int); +isc_result_t dhcpctl_remote_signal_handler (omapi_object_t *, + const char *, va_list); +isc_result_t dhcpctl_remote_stuff_values (omapi_object_t *, + omapi_object_t *, + omapi_object_t *); +isc_result_t dhcpctl_data_string_dereference (dhcpctl_data_string *, + const char *, int); +#endif /* _DHCPCTL_H_ */ diff --git a/dhcpctl/omshell.1 b/dhcpctl/omshell.1 new file mode 100644 index 0000000..af6fa49 --- /dev/null +++ b/dhcpctl/omshell.1 @@ -0,0 +1,328 @@ +.\" $Id: omshell.1,v 1.5.24.1 2009/11/20 01:49:01 sar Exp $ +.\" +.\" Copyright (c) 2012,2014 by Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (c) 2004,2009 by Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (c) 2001-2003 by Internet Software Consortium +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +.\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.\" Internet Systems Consortium, Inc. +.\" 950 Charter Street +.\" Redwood City, CA 94063 +.\" <info@isc.org> +.\" https://www.isc.org/ +.\" +.TH omshell 1 +.SH NAME +omshell - OMAPI Command Shell +.SH SYNOPSIS +.B omshell +.SH DESCRIPTION +The OMAPI Command Shell, omshell, provides an interactive way to connect to, +query, and possibly change, the ISC DHCP Server's state via OMAPI, the Object +Management API. By using OMAPI and omshell, you do not have to stop, make +changes, and then restart the DHCP server, but can make the changes +while the server is running. Omshell provides a way of accessing +OMAPI. +.PP +OMAPI is simply a communications mechanism that allows you to +manipulate objects. In order to actually \fIuse\fR omshell, you +.I must +understand what objects are available and how to use them. +Documentation for OMAPI objects can be found in the documentation for +the server that provides them - for example, in the \fBdhcpd(1)\fR +manual page and the \fBdhclient(1)\fR manual page. +.SH CONTRIBUTIONS +.PP +This software is free software. At various times its development has +been underwritten by various organizations, including the ISC and +Vixie Enterprises. The development of 3.0 has been funded almost +entirely by Nominum, Inc. +.PP +At this point development is hosted by the ISC, but the future of +this project depends on you. If you have features you want, please +consider implementing them. +.SH LOCAL AND REMOTE OBJECTS +.PP +Throughout this document, there are references to local and remote objects. +Local objects are ones created in omshell with the \fBnew\fR command. Remote +objects are ones on the server: leases, hosts, and groups that the DHCP +server knows about. Local and remote objects are associated together to +enable viewing and modification of object attributes. Also, new remote +objects can be created to match local objects. +.SH OPENING A CONNECTION +.PP +omshell is started from the command line. Once omshell is started, there are +several commands that can be issued: +.PP +.B server \fIaddress\fR +.RS 0.5i +where address is the IP address of the DHCP server to connect to. If this is +not specified, the default server is 127.0.0.1 (localhost). +.RE +.PP +.B port \fInumber\fR +.RS 0.5i +where number is the port that OMAPI listens on. By default, this is 7911. +.RE +.PP +.B key \fIname secret\fR +.RS 0.5i +This specifies the TSIG key to use to authenticate the OMAPI transactions. +\fIname\fR is the name of a key defined in \fIdhcpd.conf\fR with the +\fBomapi-key\fR statement. The \fIsecret\fR is the secret key generated from +\fBdnssec-keygen\fR or another key generation program. +.RE +.PP +.B connect +.RS 0.5i +This starts the OMAPI connection to the server as specified by the \fIserver\fR +statement. +.SH CREATING LOCAL OBJECTS +.PP +Any object defined in OMAPI can be created, queried, and/or modified. The +object types available to OMAPI are defined in \fBdhcpd(8)\fR and +\fBdhclient(8)\fR. When using omshell, objects are first defined locally, +manipulated as desired, and then associated with an object on the server. +Only one object can be manipulated at a time. To create a local object, use +.PP +.B new \fIobject-type\fR +.RS 0.5i +\fIobject-type\fR is one of group, host, or lease. +.RE +.PP +At this point, you now have an object that you can set properties on. For +example, if a new lease object was created with \fInew lease\fR, any of a +lease's attributes can be set as follows: +.PP +.B set \fIattribute-name = value\fR +.RS 0.5i +\fBAttribute\fR names are defined in \fBdhcpd(8)\fR and \fBdhclient(8)\fR. +Values should be quoted if they are strings. So, to set a lease's IP address, +you would do the following: +\fB set ip-address = 192.168.4.50\fR +.SH ASSOCIATING LOCAL AND REMOTE OBJECTS +.PP +At this point, you can query the server for information about this lease, by +.PP +.B open +.PP +Now, the local lease object you created and set the IP address for is associated +with the corresponding lease object on the DHCP server. All of the lease +attributes from the DHCP server are now also the attributes on the local +object, and will be shown in omshell. +.SH VIEWING A REMOTE OBJECT +.PP +To query a lease of address 192.168.4.50, and find out its attributes, after +connecting to the server, take the following steps: +.PP +.B new "lease" +.PP +This creates a new local lease object. +.PP +.B set ip-address = 192.168.4.50 +.PP +This sets the \fIlocal\fR object's IP address to be 192.168.4.50 +.PP +.B open +.PP +Now, if a lease with that IP address exists, you will see all the information +the DHCP server has about that particular lease. Any data that isn't readily +printable text will show up in colon-separated hexadecimal values. In this +example, output back from the server for the entire transaction might look +like this: +.nf +.sp 1 +> new "lease" +obj: lease +> set ip-address = 192.168.4.50 +obj: lease +ip-address = c0:a8:04:32 +> open +obj: lease +ip-address = c0:a8:04:32 +state = 00:00:00:02 +dhcp-client-identifier = 01:00:10:a4:b2:36:2c +client-hostname = "wendelina" +subnet = 00:00:00:06 +pool = 00:00:00:07 +hardware-address = 00:10:a4:b2:36:2c +hardware-type = 00:00:00:01 +ends = dc:d9:0d:3b +starts = 5c:9f:04:3b +tstp = 00:00:00:00 +tsfp = 00:00:00:00 +cltt = 00:00:00:00 +.fi +.PP +As you can see here, the IP address is represented in hexadecimal, as are the +starting and ending times of the lease. +.SH MODIFYING A REMOTE OBJECT +.PP +Attributes of remote objects are updated by using the \fBset\fR command as +before, and then issuing an \fBupdate\fR command. The \fBset\fR command sets +the attributes on the current local object, and the \fBupdate\fR command +pushes those changes out to the server. +.PP +Continuing with the previous example, if a \fBset client-hostname = +"something-else"\fR was issued, followed by an \fBupdate\fR command, the +output would look about like this: +.nf +.sp 1 +> set client-hostname = "something-else" +obj: lease +ip-address = c0:a8:04:32 +state = 00:00:00:02 +dhcp-client-identifier = 01:00:10:a4:b2:36:2c +client-hostname = "something-else" +subnet = 00:00:00:06 +pool = 00:00:00:07 +hardware-address = 00:10:a4:b2:36:2c +hardware-type = 00:00:00:01 +ends = dc:d9:0d:3b +starts = 5c:9f:04:3b +tstp = 00:00:00:00 +tsfp = 00:00:00:00 +cltt = 00:00:00:00 +> update +obj: lease +ip-address = c0:a8:04:32 +state = 00:00:00:02 +dhcp-client-identifier = 01:00:10:a4:b2:36:2c +client-hostname = "something-else" +subnet = 00:00:00:06 +pool = 00:00:00:07 +hardware-address = 00:10:a4:b2:36:2c +hardware-type = 00:00:00:01 +ends = dc:d9:0d:3b +starts = 5c:9f:04:3b +tstp = 00:00:00:00 +tsfp = 00:00:00:00 +cltt = 00:00:00:00 +.fi +.SH NEW REMOTE OBJECTS +.PP +New remote objects are created much in the same way that existing server +objects are modified. Create a local object using \fBnew\fR, set the +attributes as you'd wish them to be, and then create the remote object with +the same properties by using +.PP +.B create +.PP +Now a new object exists on the DHCP server which matches the properties that +you gave your local object. Objects created via OMAPI are saved into the +dhcpd.leases file. +.PP +For example, if a new host with the IP address of 192.168.4.40 needs to be +created it would be done as follows: +.nf +.sp 1 +> new host +obj: host +> set name = "some-host" +obj: host +name = "some-host" +> set hardware-address = 00:80:c7:84:b1:94 +obj: host +name = "some-host" +hardware-address = 00:80:c7:84:b1:94 +> set hardware-type = 1 +obj: host +name = "some-host" +hardware-address = 00:80:c7:84:b1:94 +hardware-type = 1 +> set ip-address = 192.168.4.40 +obj: host +name = "some-host" +hardware-address = 00:80:c7:84:b1:94 +hardware-type = 1 +ip-address = c0:a8:04:28 +> create +obj: host +name = "some-host" +hardware-address = 00:80:c7:84:b1:94 +hardware-type = 00:00:00:01 +ip-address = c0:a8:04:28 +> +.fi +.PP +Your dhcpd.leases file would then have an entry like this in it: +.nf +.sp 1 +host some-host { + dynamic; + hardware ethernet 00:80:c7:84:b1:94; + fixed-address 192.168.4.40; +} +.fi +.PP +The \fIdynamic;\fR line is to denote that this host entry did not come from +dhcpd.conf, but was created dynamically via OMAPI. +.SH RESETTING ATTRIBUTES +.PP +If you want to remove an attribute from an object, you can do this with the +\fBunset\fR command. Once you have unset an attribute, you must use the +\fBupdate\fR command to update the remote object. So, if the host "some-host" +from the previous example will not have a static IP address anymore, the +commands in omshell would look like this: +.nf +.sp 1 +obj: host +name = "some-host" +hardware-address = 00:80:c7:84:b1:94 +hardware-type = 00:00:00:01 +ip-address = c0:a8:04:28 +> unset ip-address +obj: host +name = "some-host" +hardware-address = 00:80:c7:84:b1:94 +hardware-type = 00:00:00:01 +ip-address = <null> +> +.fi +.SH REFRESHING OBJECTS +.PP +A local object may be refreshed with the current remote object properties +using the \fBrefresh\fR command. This is useful for object that change +periodically, like leases, to see if they have been updated. This isn't +particularly useful for hosts. +.SH DELETING OBJECTS +.PP +Any remote object that can be created can also be destroyed. This is done by +creating a new local object, setting attributes, associating the local and +remote object using \fBopen\fR, and then using the \fBremove\fR command. +If the host "some-host" from before was created in error, this could be +corrected as follows: +.nf +.sp 1 +obj: host +name = "some-host" +hardware-address = 00:80:c7:84:b1:94 +hardware-type = 00:00:00:01 +ip-address = c0:a8:04:28 +> remove +obj: <null> +> +.fi +.SH HELP +.PP +The \fBhelp\fR command will print out all of the commands available in +omshell, with some syntax pointers. +.SH SEE ALSO +dhcpctl(3), omapi(3), dhcpd(8), dhclient(8), dhcpd.conf(5), dhclient.conf(5). +.SH AUTHOR +.B omshell +is maintained by ISC. To learn more about Internet Systems Consortium, +see +.B https://www.isc.org + diff --git a/dhcpctl/omshell.c b/dhcpctl/omshell.c new file mode 100644 index 0000000..44fd272 --- /dev/null +++ b/dhcpctl/omshell.c @@ -0,0 +1,738 @@ +/* omshell.c + + Examine and modify omapi objects. */ + +/* + * Copyright (c) 2009-2011,2013,2014 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2001-2003 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * <info@isc.org> + * https://www.isc.org/ + * + */ + +#include "config.h" + +#include <time.h> +#include <sys/time.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +//#include "result.h" +#include <syslog.h> +#include "dhcpctl.h" +#include "dhcpd.h" + +/* Fixups */ +isc_result_t find_class (struct class **c, const char *n, const char *f, int l) +{ + return 0; +} +int parse_allow_deny (struct option_cache **oc, struct parse *cfile, int flag) +{ + return 0; +} +void dhcp (struct packet *packet) { } +void bootp (struct packet *packet) { } + +#ifdef DHCPv6 +/* XXX: should we warn or something here? */ +void dhcpv6(struct packet *packet) { } +#endif /* DHCPv6 */ + +int check_collection (struct packet *p, struct lease *l, struct collection *c) +{ + return 0; +} +void classify (struct packet *packet, struct class *class) { } + +static void usage (char *s) { + fprintf (stderr, "Usage: %s\n", s); + exit (1); +} + +static void check (isc_result_t status, const char *func) { + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "%s: %s\n", func, isc_result_totext (status)); + exit (1); + } +} + +int +main(int argc, char **argv) { + isc_result_t status, waitstatus; + dhcpctl_handle connection; + dhcpctl_handle authenticator; + dhcpctl_handle oh; + struct data_string secret; + const char *name = 0, *algorithm = "hmac-md5"; + int i; + int port = 7911; + const char *server = "127.0.0.1"; + struct parse *cfile; + enum dhcp_token token; + const char *val; + char *s; + char buf[1024]; + char s1[1024]; + int connected = 0; + char hex_buf[1025]; + + for (i = 1; i < argc; i++) { + usage(argv[0]); + } + + /* Initially, log errors to stderr as well as to syslogd. */ + openlog ("omshell", DHCP_LOG_OPTIONS, DHCPD_LOG_FACILITY); + status = dhcpctl_initialize (); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_initialize: %s\n", + isc_result_totext (status)); + exit (1); + } + + memset (&oh, 0, sizeof oh); + + do { + if (!connected) { + } else if (oh == NULL) { + printf ("obj: <null>\n"); + } else { + dhcpctl_remote_object_t *r = (dhcpctl_remote_object_t *)oh; + omapi_generic_object_t *g = + (omapi_generic_object_t *)(r -> inner); + + printf ("obj: "); + + if (r -> rtype -> type != omapi_datatype_string) { + printf ("?\n"); + } else { + printf ("%.*s\n", + (int)(r -> rtype -> u . buffer . len), + r -> rtype -> u . buffer . value); + } + + for (i = 0; i < g -> nvalues; i++) { + omapi_value_t *v = g -> values [i]; + + if (!g -> values [i]) + continue; + + printf ("%.*s = ", (int)v -> name -> len, + v -> name -> value); + + if (!v -> value) { + printf ("<null>\n"); + continue; + } + switch (v -> value -> type) { + case omapi_datatype_int: + printf ("%d\n", + v -> value -> u . integer); + break; + + case omapi_datatype_string: + printf ("\"%.*s\"\n", + (int) v -> value -> u.buffer.len, + v -> value -> u.buffer.value); + break; + + case omapi_datatype_data: + print_hex_or_string(v->value->u.buffer.len, + v->value->u.buffer.value, + sizeof(hex_buf), hex_buf); + printf("%s\n", hex_buf); + break; + + case omapi_datatype_object: + printf ("<obj>\n"); + break; + } + } + } + + fputs ("> ", stdout); + fflush (stdout); + if (fgets (buf, sizeof(buf), stdin) == NULL) + break; + + status = new_parse (&cfile, -1, buf, strlen(buf), "<STDIN>", 1); + check(status, "new_parse()"); + + token = next_token (&val, (unsigned *)0, cfile); + switch (token) { + default: + parse_warn (cfile, "unknown token: %s", val); + skip_to_semi (cfile); + break; + + case END_OF_FILE: + case ENDOFLINE: /* EOL: */ + break; + + case TOKEN_HELP: + case QUESTIONMARK: /* '?': */ + printf ("Commands:\n"); + printf (" port <server omapi port>\n"); + printf (" server <server address>\n"); + printf (" key <key name> <key value>\n"); + printf (" connect\n"); + printf (" new <object-type>\n"); + printf (" set <name> = <value>\n"); + printf (" create\n"); + printf (" open\n"); + printf (" update\n"); + printf (" unset <name>\n"); + printf (" refresh\n"); + printf (" remove\n"); + skip_to_semi (cfile); + break; + + case PORT: + token = next_token (&val, (unsigned *)0, cfile); + if (is_identifier (token)) { + struct servent *se; + se = getservbyname (val, "tcp"); + if (se) + port = ntohs (se -> s_port); + else { + printf ("unknown service name: %s\n", val); + break; + } + } else if (token == NUMBER) { + port = atoi (val); + } else { + skip_to_semi (cfile); + printf ("usage: port <port>\n"); + break; + } + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) { + printf ("usage: port <server>\n"); + skip_to_semi (cfile); + break; + } + break; + + case TOKEN_SERVER: + token = next_token (&val, (unsigned *)0, cfile); + if (token == NUMBER) { + int alen = (sizeof buf) - 1; + int len; + + s = &buf [0]; + len = strlen (val); + if (len + 1 > alen) { + baddq: + printf ("usage: server <server>\n"); + skip_to_semi (cfile); + break; + } strcpy (buf, val); + s += len; + token = next_token (&val, (unsigned *)0, cfile); + if (token != DOT) + goto baddq; + *s++ = '.'; + token = next_token (&val, (unsigned *)0, cfile); + if (token != NUMBER) + goto baddq; + len = strlen (val); + if (len + 1 > alen) + goto baddq; + strcpy (s, val); + s += len; + token = next_token (&val, (unsigned *)0, cfile); + if (token != DOT) + goto baddq; + *s++ = '.'; + token = next_token (&val, (unsigned *)0, cfile); + if (token != NUMBER) + goto baddq; + len = strlen (val); + if (len + 1 > alen) + goto baddq; + strcpy (s, val); + s += len; + token = next_token (&val, (unsigned *)0, cfile); + if (token != DOT) + goto baddq; + *s++ = '.'; + token = next_token (&val, (unsigned *)0, cfile); + if (token != NUMBER) + goto baddq; + len = strlen (val); + if (len + 1 > alen) + goto baddq; + strcpy (s, val); + val = &buf [0]; + } else if (is_identifier (token)) { + /* Use val directly. */ + } else { + printf ("usage: server <server>\n"); + skip_to_semi (cfile); + break; + } + + s = dmalloc (strlen (val) + 1, MDL); + if (!server) { + printf ("no memory to store server name.\n"); + skip_to_semi (cfile); + break; + } + strcpy (s, val); + server = s; + + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) { + printf ("usage: server <server>\n"); + skip_to_semi (cfile); + break; + } + break; + + case KEY: + token = peek_token(&val, (unsigned *)0, cfile); + if (token == STRING) { + token = next_token (&val, (unsigned *)0, cfile); + if (!is_identifier (token)) { + printf ("usage: key <name> <value>\n"); + skip_to_semi (cfile); + break; + } + s = dmalloc (strlen (val) + 1, MDL); + if (!s) { + printf ("no memory for key name.\n"); + skip_to_semi (cfile); + break; + } + strcpy (s, val); + } else { + s = parse_host_name(cfile); + if (s == NULL) { + printf ("usage: key <name> <value>\n"); + skip_to_semi(cfile); + break; + } + } + name = s; + + memset (&secret, 0, sizeof secret); + if (!parse_base64 (&secret, cfile)) { + skip_to_semi (cfile); + break; + } + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) { + printf ("usage: key <name> <secret>\n"); + skip_to_semi (cfile); + break; + } + break; + + case CONNECT: + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) { + printf ("usage: connect\n"); + skip_to_semi (cfile); + break; + } + + authenticator = dhcpctl_null_handle; + + if (name) { + status = dhcpctl_new_authenticator (&authenticator, + name, algorithm, + secret.data, + secret.len); + + if (status != ISC_R_SUCCESS) { + fprintf (stderr, + "Cannot create authenticator: %s\n", + isc_result_totext (status)); + break; + } + } + + memset (&connection, 0, sizeof connection); + status = dhcpctl_connect (&connection, + server, port, authenticator); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "dhcpctl_connect: %s\n", + isc_result_totext (status)); + break; + } + connected = 1; + break; + + case TOKEN_NEW: + token = next_token (&val, (unsigned *)0, cfile); + if ((!is_identifier (token) && token != STRING)) { + printf ("usage: new <object-type>\n"); + break; + } + + if (oh) { + printf ("an object is already open.\n"); + skip_to_semi (cfile); + break; + } + + if (!connected) { + printf ("not connected.\n"); + skip_to_semi (cfile); + break; + } + + status = dhcpctl_new_object (&oh, connection, val); + if (status != ISC_R_SUCCESS) { + printf ("can't create object: %s\n", + isc_result_totext (status)); + break; + } + + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) { + printf ("usage: new <object-type>\n"); + skip_to_semi (cfile); + break; + } + break; + + case TOKEN_CLOSE: + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) { + printf ("usage: close\n"); + skip_to_semi (cfile); + break; + } + + if (!connected) { + printf ("not connected.\n"); + skip_to_semi (cfile); + break; + } + + if (!oh) { + printf ("not open.\n"); + skip_to_semi (cfile); + break; + } + omapi_object_dereference (&oh, MDL); + + break; + + case TOKEN_SET: + token = next_token (&val, (unsigned *)0, cfile); + + if ((!is_identifier (token) && token != STRING)) { + set_usage: + printf ("usage: set <name> = <value>\n"); + skip_to_semi (cfile); + break; + } + + if (oh == NULL) { + printf ("no open object.\n"); + skip_to_semi (cfile); + break; + } + + if (!connected) { + printf ("not connected.\n"); + skip_to_semi (cfile); + break; + } + +#ifdef HAVE_STRLCPY + strlcpy (s1, val, sizeof(s1)); +#else + s1[0] = 0; + strncat (s1, val, sizeof(s1)-strlen(s1)-1); +#endif + + token = next_token (&val, (unsigned *)0, cfile); + if (token != EQUAL) + goto set_usage; + + token = next_token (&val, (unsigned *)0, cfile); + switch (token) { + case STRING: + dhcpctl_set_string_value (oh, val, s1); + token = next_token (&val, (unsigned *)0, cfile); + break; + + case NUMBER: + strcpy (buf, val); + token = peek_token (&val, (unsigned *)0, cfile); + /* Colon-separated hex list? */ + if (token == COLON) + goto cshl; + else if (token == DOT) { + s = buf; + val = buf; + do { + int intval = atoi (val); + if (intval > 255) { + parse_warn (cfile, + "dotted octet > 255: %s", + val); + skip_to_semi (cfile); + goto badnum; + } + *s++ = intval; + token = next_token (&val, + (unsigned *)0, cfile); + if (token != DOT) + break; + /* DOT is zero. */ + while ((token = next_token (&val, + (unsigned *)0, cfile)) == DOT) + *s++ = 0; + } while (token == NUMBER); + dhcpctl_set_data_value (oh, buf, + (unsigned)(s - buf), + s1); + break; + } + dhcpctl_set_int_value (oh, atoi (buf), s1); + token = next_token (&val, (unsigned *)0, cfile); + badnum: + break; + + case NUMBER_OR_NAME: + strcpy (buf, val); + cshl: + s = buf; + val = buf; + do { + convert_num (cfile, (unsigned char *)s, + val, 16, 8); + ++s; + token = next_token (&val, + (unsigned *)0, cfile); + if (token != COLON) + break; + token = next_token (&val, + (unsigned *)0, cfile); + } while (token == NUMBER || + token == NUMBER_OR_NAME); + dhcpctl_set_data_value (oh, buf, + (unsigned)(s - buf), s1); + break; + + default: + printf ("invalid value.\n"); + skip_to_semi (cfile); + } + + if (token != END_OF_FILE && token != EOL) + goto set_usage; + break; + + case UNSET: + token = next_token (&val, (unsigned *)0, cfile); + + if ((!is_identifier (token) && token != STRING)) { + unset_usage: + printf ("usage: unset <name>\n"); + skip_to_semi (cfile); + break; + } + + if (!oh) { + printf ("no open object.\n"); + skip_to_semi (cfile); + break; + } + + if (!connected) { + printf ("not connected.\n"); + skip_to_semi (cfile); + break; + } + +#if HAVE_STRLCPY + strlcpy (s1, val, sizeof(s1)); +#else + s1[0] = 0; + strncat (s1, val, sizeof(s1)-strlen(s1)-1); +#endif + + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) + goto unset_usage; + + dhcpctl_set_null_value (oh, s1); + break; + + + case TOKEN_CREATE: + case TOKEN_OPEN: + i = token; + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) { + printf ("usage: %s\n", val); + skip_to_semi (cfile); + break; + } + + if (!connected) { + printf ("not connected.\n"); + skip_to_semi (cfile); + break; + } + + if (!oh) { + printf ("you must make a new object first!\n"); + skip_to_semi (cfile); + break; + } + + if (i == TOKEN_CREATE) + i = DHCPCTL_CREATE | DHCPCTL_EXCL; + else + i = 0; + + status = dhcpctl_open_object (oh, connection, i); + if (status == ISC_R_SUCCESS) + status = dhcpctl_wait_for_completion + (oh, &waitstatus); + if (status == ISC_R_SUCCESS) + status = waitstatus; + if (status != ISC_R_SUCCESS) { + printf ("can't open object: %s\n", + isc_result_totext (status)); + break; + } + + break; + + case UPDATE: + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) { + printf ("usage: %s\n", val); + skip_to_semi (cfile); + break; + } + + if (!connected) { + printf ("not connected.\n"); + skip_to_semi (cfile); + break; + } + + if (!oh) { + printf ("you haven't opened an object yet!\n"); + skip_to_semi (cfile); + break; + } + + status = dhcpctl_object_update(connection, oh); + if (status == ISC_R_SUCCESS) + status = dhcpctl_wait_for_completion + (oh, &waitstatus); + if (status == ISC_R_SUCCESS) + status = waitstatus; + if (status != ISC_R_SUCCESS) { + printf ("can't update object: %s\n", + isc_result_totext (status)); + break; + } + + break; + + case REMOVE: + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) { + printf ("usage: remove\n"); + skip_to_semi (cfile); + break; + } + + if (!connected) { + printf ("not connected.\n"); + break; + } + + if (!oh) { + printf ("no object.\n"); + break; + } + + status = dhcpctl_object_remove(connection, oh); + if (status == ISC_R_SUCCESS) + status = dhcpctl_wait_for_completion + (oh, &waitstatus); + if (status == ISC_R_SUCCESS) + status = waitstatus; + if (status != ISC_R_SUCCESS) { + printf ("can't destroy object: %s\n", + isc_result_totext (status)); + break; + } + omapi_object_dereference (&oh, MDL); + break; + + case REFRESH: + token = next_token (&val, (unsigned *)0, cfile); + if (token != END_OF_FILE && token != EOL) { + printf ("usage: refresh\n"); + skip_to_semi (cfile); + break; + } + + if (!connected) { + printf ("not connected.\n"); + break; + } + + if (!oh) { + printf ("no object.\n"); + break; + } + + status = dhcpctl_object_refresh(connection, oh); + if (status == ISC_R_SUCCESS) + status = dhcpctl_wait_for_completion + (oh, &waitstatus); + if (status == ISC_R_SUCCESS) + status = waitstatus; + if (status != ISC_R_SUCCESS) { + printf ("can't refresh object: %s\n", + isc_result_totext (status)); + break; + } + + break; + } + end_parse (&cfile); + } while (1); + + exit (0); +} + +/* Sigh */ +isc_result_t dhcp_set_control_state (control_object_state_t oldstate, + control_object_state_t newstate) +{ + if (newstate != server_shutdown) + return ISC_R_SUCCESS; + exit (0); +} diff --git a/dhcpctl/remote.c b/dhcpctl/remote.c new file mode 100644 index 0000000..c8f278d --- /dev/null +++ b/dhcpctl/remote.c @@ -0,0 +1,355 @@ +/* remote.c + + The dhcpctl remote object. */ + +/* + * Copyright (c) 2004,2007,2009,2014 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999-2003 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * <info@isc.org> + * https://www.isc.org/ + * + */ + +#include "dhcpd.h" +#include <omapip/omapip_p.h> +#include "dhcpctl.h" + +/* dhcpctl_new_authenticator + + synchronous - creates an authenticator object. + returns nonzero status code if the object couldn't be created + stores handle to authenticator through h if successful, and returns zero. + name is the authenticator name (NUL-terminated string). + algorithm is the NUL-terminated string name of the algorithm to use + (currently, only "hmac-md5" is supported). + secret and secret_len is the key secret. */ + +dhcpctl_status dhcpctl_new_authenticator (dhcpctl_handle *h, + const char *name, + const char *algorithm, + const unsigned char *secret, + unsigned secret_len) +{ + struct auth_key *key = (struct auth_key *)0; + isc_result_t status; + + status = omapi_auth_key_new (&key, MDL); + if (status != ISC_R_SUCCESS) + return status; + + key -> name = dmalloc (strlen (name) + 1, MDL); + if (!key -> name) { + omapi_auth_key_dereference (&key, MDL); + return ISC_R_NOMEMORY; + } + strcpy (key -> name, name); + + /* If the algorithm name isn't an FQDN, tack on the + .SIG-ALG.REG.NET. domain. */ + if (strchr (algorithm, '.') == 0) { + static char add[] = ".SIG-ALG.REG.INT."; + key -> algorithm = dmalloc (strlen (algorithm) + + sizeof (add), MDL); + if (!key -> algorithm) { + omapi_auth_key_dereference (&key, MDL); + return ISC_R_NOMEMORY; + } + strcpy (key -> algorithm, algorithm); + strcat (key -> algorithm, add); + } else { + key -> algorithm = dmalloc (strlen (algorithm) + 1, MDL); + if (!key -> algorithm) { + omapi_auth_key_dereference (&key, MDL); + return ISC_R_NOMEMORY; + } + strcpy (key -> algorithm, algorithm); + } + + status = omapi_data_string_new (&key -> key, secret_len, MDL); + if (status != ISC_R_SUCCESS) { + omapi_auth_key_dereference (&key, MDL); + return status; + } + memcpy (key -> key -> value, secret, secret_len); + key -> key -> len = secret_len; + + *h = (dhcpctl_handle) key; + return ISC_R_SUCCESS; +} + + +/* dhcpctl_new_object + + synchronous - creates a local handle for a host entry. + returns nonzero status code if the local host entry couldn't + be created + stores handle to host through h if successful, and returns zero. + object_type is a pointer to a NUL-terminated string containing + the ascii name of the type of object being accessed - e.g., "host" */ + +dhcpctl_status dhcpctl_new_object (dhcpctl_handle *h, + dhcpctl_handle connection, + const char *object_type) +{ + dhcpctl_remote_object_t *m; + omapi_object_t *g; + isc_result_t status; + + m = (dhcpctl_remote_object_t *)0; + status = omapi_object_allocate((omapi_object_t **)&m, + dhcpctl_remote_type, 0, MDL); + if (status != ISC_R_SUCCESS) + return status; + + g = (omapi_object_t *)0; + status = omapi_generic_new (&g, MDL); + if (status != ISC_R_SUCCESS) { + dfree (m, MDL); + return status; + } + status = omapi_object_reference (&m -> inner, g, MDL); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference ((omapi_object_t **)&m, MDL); + omapi_object_dereference (&g, MDL); + return status; + } + status = omapi_object_reference (&g -> outer, + (omapi_object_t *)m, MDL); + + if (status != ISC_R_SUCCESS) { + omapi_object_dereference ((omapi_object_t **)&m, MDL); + omapi_object_dereference (&g, MDL); + return status; + } + + status = omapi_typed_data_new (MDL, &m -> rtype, + omapi_datatype_string, + object_type); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference ((omapi_object_t **)&m, MDL); + omapi_object_dereference (&g, MDL); + return status; + } + + status = omapi_object_reference (h, (omapi_object_t *)m, MDL); + omapi_object_dereference ((omapi_object_t **)&m, MDL); + omapi_object_dereference (&g, MDL); + if (status != ISC_R_SUCCESS) + return status; + + return status; +} + +/* asynchronous - just queues the request + returns nonzero status code if open couldn't be queued + returns zero if open was queued + h is a handle to an object created by dhcpctl_new_object + connection is a connection to a DHCP server + flags include: + DHCPCTL_CREATE - if the object doesn't exist, create it + DHCPCTL_UPDATE - update the object on the server using the + attached parameters + DHCPCTL_EXCL - error if the object exists and DHCPCTL_CREATE + was also specified */ + +dhcpctl_status dhcpctl_open_object (dhcpctl_handle h, + dhcpctl_handle connection, + int flags) +{ + isc_result_t status; + omapi_object_t *message = (omapi_object_t *)0; + dhcpctl_remote_object_t *remote; + + if (h -> type != dhcpctl_remote_type) + return DHCP_R_INVALIDARG; + remote = (dhcpctl_remote_object_t *)h; + + status = omapi_message_new (&message, MDL); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_set_int_value (message, (omapi_object_t *)0, + "op", OMAPI_OP_OPEN); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + status = omapi_set_object_value (message, (omapi_object_t *)0, + "object", h); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + if (flags & DHCPCTL_CREATE) { + status = omapi_set_boolean_value (message, (omapi_object_t *)0, + "create", 1); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + } + if (flags & DHCPCTL_UPDATE) { + status = omapi_set_boolean_value (message, (omapi_object_t *)0, + "update", 1); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + } + if (flags & DHCPCTL_EXCL) { + status = omapi_set_boolean_value (message, (omapi_object_t *)0, + "exclusive", 1); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + } + + if (remote -> rtype) { + status = omapi_set_value_str (message, (omapi_object_t *)0, + "type", remote -> rtype); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + } + + status = omapi_message_register (message); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&message, MDL); + return status; + } + + status = omapi_protocol_send_message (connection -> outer, + (omapi_object_t *)0, + message, (omapi_object_t *)0); + + if (status != ISC_R_SUCCESS) + omapi_message_unregister (message); + + omapi_object_dereference (&message, MDL); + return status; +} + +/* Callback methods (not meant to be called directly) */ + +isc_result_t dhcpctl_remote_set_value (omapi_object_t *h, + omapi_object_t *id, + omapi_data_string_t *name, + omapi_typed_data_t *value) +{ + dhcpctl_remote_object_t *ro; + unsigned long rh; + isc_result_t status; + + if (h -> type != dhcpctl_remote_type) + return DHCP_R_INVALIDARG; + ro = (dhcpctl_remote_object_t *)h; + + if (!omapi_ds_strcmp (name, "remote-handle")) { + status = omapi_get_int_value (&rh, value); + if (status == ISC_R_SUCCESS) + ro -> remote_handle = rh; + return status; + } + + if (h -> inner && h -> inner -> type -> set_value) + return (*(h -> inner -> type -> set_value)) + (h -> inner, id, name, value); + return ISC_R_NOTFOUND; +} + +isc_result_t dhcpctl_remote_get_value (omapi_object_t *h, + omapi_object_t *id, + omapi_data_string_t *name, + omapi_value_t **value) +{ + if (h -> type != dhcpctl_remote_type) + return DHCP_R_INVALIDARG; + + if (h -> inner && h -> inner -> type -> get_value) + return (*(h -> inner -> type -> get_value)) + (h -> inner, id, name, value); + return ISC_R_NOTFOUND; +} + +isc_result_t dhcpctl_remote_signal_handler (omapi_object_t *o, + const char *name, va_list ap) +{ + dhcpctl_remote_object_t *p; + omapi_typed_data_t *tv; + + if (o -> type != dhcpctl_remote_type) + return DHCP_R_INVALIDARG; + p = (dhcpctl_remote_object_t *)o; + + if (!strcmp (name, "updated")) { + p -> waitstatus = ISC_R_SUCCESS; + if (o -> inner -> type == omapi_type_generic) + omapi_generic_clear_flags (o -> inner); + return omapi_signal_in (o -> inner, "ready"); + } + if (!strcmp (name, "status")) { + p -> waitstatus = va_arg (ap, isc_result_t); + if (p -> message) + omapi_typed_data_dereference (&p -> message, MDL); + tv = va_arg (ap, omapi_typed_data_t *); + if (tv) + omapi_typed_data_reference (&p -> message, tv, MDL); + return omapi_signal_in (o -> inner, "ready"); + } + + if (p -> inner && p -> inner -> type -> signal_handler) + return (*(p -> inner -> type -> signal_handler)) + (p -> inner, name, ap); + + return ISC_R_SUCCESS; +} + +isc_result_t dhcpctl_remote_destroy (omapi_object_t *h, + const char *file, int line) +{ + dhcpctl_remote_object_t *p; + if (h -> type != dhcpctl_remote_type) + return DHCP_R_INVALIDARG; + p = (dhcpctl_remote_object_t *)h; + if (p -> handle) + omapi_object_dereference ((omapi_object_t **)&p -> handle, + file, line); + if (p -> rtype) + omapi_typed_data_dereference ((omapi_typed_data_t **)&p->rtype, + file, line); + return ISC_R_SUCCESS; +} + +/* Write all the published values associated with the object through the + specified connection. */ + +isc_result_t dhcpctl_remote_stuff_values (omapi_object_t *c, + omapi_object_t *id, + omapi_object_t *p) +{ + if (p -> type != dhcpctl_remote_type) + return DHCP_R_INVALIDARG; + + if (p -> inner && p -> inner -> type -> stuff_values) + return (*(p -> inner -> type -> stuff_values)) (c, id, + p -> inner); + return ISC_R_SUCCESS; +} + |