summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Markwalder <tmark@isc.org>2020-01-23 16:21:52 -0500
committerThomas Markwalder <tmark@isc.org>2022-01-20 16:30:49 -0500
commit7f1524669755d7a6e6cd1c3fb80084df273f3dc1 (patch)
tree6a377a3ccee3135da05adf12e138aec3c3e40d4e
parent7de26fe7a1a2822f667ccaf7c633673cb2d0cead (diff)
downloadisc-dhcp-7f1524669755d7a6e6cd1c3fb80084df273f3dc1.tar.gz
[#76] Initial implemention to dhcpctl_timed_wait_for_completion
common/conflex.c includes/dhctoken.h dhcpctl/omshell.c Added support for "disconnect" dhcpctl/cltest.2 - new file that exercizes timed waits and disconnect dhcpctl/Makefile.am.in Added cltest2.c dhcpctl/dhcpctl.* dhcpctl_timed_wait_for_completion() - new function dhcpctl_disconnect() - new function Added debug logging omapip/dispatch.c Added protocol logging omapi_wait_for_completion() Fixed dangling waiter reference omapi_one_dispatch() Added logic to skip emit writefds from select list omapip/support.c Changed annoying DEBUG logs to DEBUG_PROTOCOL
-rw-r--r--common/conflex.c2
-rw-r--r--dhcpctl/Makefile.am9
-rw-r--r--dhcpctl/Makefile.am.in9
-rw-r--r--dhcpctl/Makefile.in179
-rw-r--r--dhcpctl/cltest2.c285
-rw-r--r--dhcpctl/dhcpctl.c145
-rw-r--r--dhcpctl/dhcpctl.h8
-rw-r--r--dhcpctl/omshell.c23
-rw-r--r--includes/dhctoken.h3
-rw-r--r--includes/omapip/omapip_p.h3
-rw-r--r--omapip/connection.c2
-rw-r--r--omapip/dispatch.c73
-rw-r--r--omapip/support.c4
13 files changed, 637 insertions, 108 deletions
diff --git a/common/conflex.c b/common/conflex.c
index 7b671560..db1e1a09 100644
--- a/common/conflex.c
+++ b/common/conflex.c
@@ -954,6 +954,8 @@ intern(char *atom, enum dhcp_token dfv) {
if (!atom [6])
return DEFINE;
}
+ if (!strcasecmp (atom + 1, "isconnect"))
+ return DISCONNECT;
break;
case 'e':
if (isascii (atom [1]) &&
diff --git a/dhcpctl/Makefile.am b/dhcpctl/Makefile.am
index 0d669715..9e623375 100644
--- a/dhcpctl/Makefile.am
+++ b/dhcpctl/Makefile.am
@@ -5,7 +5,7 @@ BINDLIBISCDIR=@BINDLIBISCDIR@
bin_PROGRAMS = omshell
lib_LIBRARIES = libdhcpctl.a
-noinst_PROGRAMS = cltest
+noinst_PROGRAMS = cltest cltest2
man_MANS = omshell.1 dhcpctl.3
EXTRA_DIST = $(man_MANS)
@@ -24,3 +24,10 @@ cltest_LDADD = libdhcpctl.a ../common/libdhcp.a ../omapip/libomapi.a \
$(BINDLIBDNSDIR)/libdns.a \
$(BINDLIBISCCFGDIR)/libisccfg.a \
$(BINDLIBISCDIR)/libisc.a
+
+cltest2_SOURCES = cltest2.c
+cltest2_LDADD = libdhcpctl.a ../common/libdhcp.a ../omapip/libomapi.a \
+ $(BINDLIBIRSDIR)/libirs.a \
+ $(BINDLIBDNSDIR)/libdns.a \
+ $(BINDLIBISCCFGDIR)/libisccfg.a \
+ $(BINDLIBISCDIR)/libisc.a
diff --git a/dhcpctl/Makefile.am.in b/dhcpctl/Makefile.am.in
index 0d77ffc6..28333cef 100644
--- a/dhcpctl/Makefile.am.in
+++ b/dhcpctl/Makefile.am.in
@@ -5,7 +5,7 @@ BINDLIBISCDIR=@Q@BINDLIBISCDIR@Q@
bin_PROGRAMS = omshell
lib_@DHLIBS@ = libdhcpctl.@A@
-noinst_PROGRAMS = cltest
+noinst_PROGRAMS = cltest cltest2
man_MANS = omshell.1 dhcpctl.3
EXTRA_DIST = $(man_MANS)
@@ -24,3 +24,10 @@ cltest_LDADD = libdhcpctl.@A@ ../common/libdhcp.@A@ ../omapip/libomapi.@A@ \
$(BINDLIBDNSDIR)/libdns.@A@ \
$(BINDLIBISCCFGDIR)/libisccfg.@A@ \
$(BINDLIBISCDIR)/libisc.@A@
+
+cltest2_SOURCES = cltest2.c
+cltest2_LDADD = libdhcpctl.@A@ ../common/libdhcp.@A@ ../omapip/libomapi.@A@ \
+ $(BINDLIBIRSDIR)/libirs.@A@ \
+ $(BINDLIBDNSDIR)/libdns.@A@ \
+ $(BINDLIBISCCFGDIR)/libisccfg.@A@ \
+ $(BINDLIBISCDIR)/libisc.@A@
diff --git a/dhcpctl/Makefile.in b/dhcpctl/Makefile.in
index 3c8232d1..e1da56a5 100644
--- a/dhcpctl/Makefile.in
+++ b/dhcpctl/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.13.4 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# 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,
@@ -16,17 +16,7 @@
VPATH = @srcdir@
-am__is_gnu_make = { \
- if test -z '$(MAKELEVEL)'; then \
- false; \
- elif test -n '$(MAKE_HOST)'; then \
- true; \
- elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
- true; \
- else \
- false; \
- fi; \
-}
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
@@ -90,20 +80,18 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
bin_PROGRAMS = omshell$(EXEEXT)
-noinst_PROGRAMS = cltest$(EXEEXT)
+noinst_PROGRAMS = cltest$(EXEEXT) cltest2$(EXEEXT)
subdir = dhcpctl
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.am.in $(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)
-DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/includes/config.h
CONFIG_CLEAN_FILES = Makefile.am
CONFIG_CLEAN_VPATH_FILES =
-am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)" \
- "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man3dir)"
-PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
@@ -131,6 +119,8 @@ am__uninstall_files_from_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)
ARFLAGS = cru
AM_V_AR = $(am__v_AR_@AM_V@)
@@ -142,12 +132,19 @@ 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 $(BINDLIBIRSDIR)/libirs.a \
$(BINDLIBDNSDIR)/libdns.a $(BINDLIBISCCFGDIR)/libisccfg.a \
$(BINDLIBISCDIR)/libisc.a
+am_cltest2_OBJECTS = cltest2.$(OBJEXT)
+cltest2_OBJECTS = $(am_cltest2_OBJECTS)
+cltest2_DEPENDENCIES = libdhcpctl.a ../common/libdhcp.a \
+ ../omapip/libomapi.a $(BINDLIBIRSDIR)/libirs.a \
+ $(BINDLIBDNSDIR)/libdns.a $(BINDLIBISCCFGDIR)/libisccfg.a \
+ $(BINDLIBISCDIR)/libisc.a
am_omshell_OBJECTS = omshell.$(OBJEXT)
omshell_OBJECTS = $(am_omshell_OBJECTS)
omshell_DEPENDENCIES = libdhcpctl.a ../common/libdhcp.a \
@@ -168,10 +165,7 @@ am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/includes
depcomp = $(SHELL) $(top_srcdir)/depcomp
-am__maybe_remake_depfiles = depfiles
-am__depfiles_remade = ./$(DEPDIR)/callback.Po ./$(DEPDIR)/cltest.Po \
- ./$(DEPDIR)/dhcpctl.Po ./$(DEPDIR)/omshell.Po \
- ./$(DEPDIR)/remote.Po
+am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -185,9 +179,10 @@ 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) \
+SOURCES = $(libdhcpctl_a_SOURCES) $(cltest_SOURCES) $(cltest2_SOURCES) \
$(omshell_SOURCES)
+DIST_SOURCES = $(libdhcpctl_a_SOURCES) $(cltest_SOURCES) \
+ $(cltest2_SOURCES) $(omshell_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -216,8 +211,6 @@ am__define_uniq_tagged_files = \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
-am__DIST_COMMON = $(srcdir)/Makefile.am.in $(srcdir)/Makefile.in \
- $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
A = @A@
ACLOCAL = @ACLOCAL@
@@ -360,6 +353,13 @@ cltest_LDADD = libdhcpctl.a ../common/libdhcp.a ../omapip/libomapi.a \
$(BINDLIBISCCFGDIR)/libisccfg.a \
$(BINDLIBISCDIR)/libisc.a
+cltest2_SOURCES = cltest2.c
+cltest2_LDADD = libdhcpctl.a ../common/libdhcp.a ../omapip/libomapi.a \
+ $(BINDLIBIRSDIR)/libirs.a \
+ $(BINDLIBDNSDIR)/libdns.a \
+ $(BINDLIBISCCFGDIR)/libisccfg.a \
+ $(BINDLIBISCDIR)/libisc.a
+
all: all-am
.SUFFIXES:
@@ -376,13 +376,14 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
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__maybe_remake_depfiles)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ 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)
@@ -395,6 +396,42 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(am__aclocal_m4_deps):
Makefile.am: $(top_builddir)/config.status $(srcdir)/Makefile.am.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+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=; \
@@ -440,47 +477,15 @@ clean-binPROGRAMS:
clean-noinstPROGRAMS:
-test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
-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
cltest$(EXEEXT): $(cltest_OBJECTS) $(cltest_DEPENDENCIES) $(EXTRA_cltest_DEPENDENCIES)
@rm -f cltest$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(cltest_OBJECTS) $(cltest_LDADD) $(LIBS)
+cltest2$(EXEEXT): $(cltest2_OBJECTS) $(cltest2_DEPENDENCIES) $(EXTRA_cltest2_DEPENDENCIES)
+ @rm -f cltest2$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(cltest2_OBJECTS) $(cltest2_LDADD) $(LIBS)
+
omshell$(EXEEXT): $(omshell_OBJECTS) $(omshell_DEPENDENCIES) $(EXTRA_omshell_DEPENDENCIES)
@rm -f omshell$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(omshell_OBJECTS) $(omshell_LDADD) $(LIBS)
@@ -491,31 +496,26 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/callback.Po@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cltest.Po@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dhcpctl.Po@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omshell.Po@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/remote.Po@am__quote@ # am--include-marker
-
-$(am__depfiles_remade):
- @$(MKDIR_P) $(@D)
- @echo '# dummy' >$@-t && $(am__mv) $@-t $@
-
-am--depfiles: $(am__depfiles_remade)
+@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)/cltest2.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 $@ $<
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
.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) '$<'`
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
install-man1: $(man_MANS)
@$(NORMAL_INSTALL)
@list1=''; \
@@ -655,10 +655,7 @@ cscopelist-am: $(am__tagged_files)
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-distdir: $(BUILT_SOURCES)
- $(MAKE) $(AM_MAKEFLAGS) distdir-am
-
-distdir-am: $(DISTFILES)
+distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
@@ -690,9 +687,9 @@ distdir-am: $(DISTFILES)
done
check-am: all-am
check: check-am
-all-am: Makefile $(PROGRAMS) $(LIBRARIES) $(MANS)
+all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(MANS)
installdirs:
- for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man3dir)"; do \
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man3dir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
@@ -731,11 +728,7 @@ clean-am: clean-binPROGRAMS clean-generic clean-libLIBRARIES \
clean-noinstPROGRAMS mostlyclean-am
distclean: distclean-am
- -rm -f ./$(DEPDIR)/callback.Po
- -rm -f ./$(DEPDIR)/cltest.Po
- -rm -f ./$(DEPDIR)/dhcpctl.Po
- -rm -f ./$(DEPDIR)/omshell.Po
- -rm -f ./$(DEPDIR)/remote.Po
+ -rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@@ -781,11 +774,7 @@ install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
- -rm -f ./$(DEPDIR)/callback.Po
- -rm -f ./$(DEPDIR)/cltest.Po
- -rm -f ./$(DEPDIR)/dhcpctl.Po
- -rm -f ./$(DEPDIR)/omshell.Po
- -rm -f ./$(DEPDIR)/remote.Po
+ -rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
@@ -808,7 +797,7 @@ uninstall-man: uninstall-man1 uninstall-man3
.MAKE: install-am install-strip
-.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+.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 \
@@ -825,8 +814,6 @@ uninstall-man: uninstall-man1 uninstall-man3
uninstall-libLIBRARIES uninstall-man uninstall-man1 \
uninstall-man3
-.PRECIOUS: Makefile
-
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/dhcpctl/cltest2.c b/dhcpctl/cltest2.c
new file mode 100644
index 00000000..26249a3e
--- /dev/null
+++ b/dhcpctl/cltest2.c
@@ -0,0 +1,285 @@
+/* cltest2.c
+
+ Example program that uses the dhcpctl library. */
+
+/*
+ * Copyright (c) 2020 by Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Internet Systems Consortium, Inc.
+ * 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 "config.h"
+
+#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"
+#include "dhcpd.h"
+
+int main (int, char **);
+
+static void usage (char *s) {
+ fprintf (stderr,
+ "Usage: %s [-s <server ip>] [-p <port>]", s);
+ exit (1);
+}
+
+static void fail_on_error(isc_result_t status, const char* message) {
+ if (status != ISC_R_SUCCESS) {
+ fprintf (stderr, "%s: %s\n",
+ message, isc_result_totext (status));
+ exit (1);
+ }
+}
+
+isc_result_t wait_with_retry(dhcpctl_handle handle, struct timeval* timeout, int retries);
+
+void print_object(char *msg, dhcpctl_handle handle);
+
+/* Simple test program that exercises dhcpctl calls as follows:
+ *
+ * 1. Connect to the given server
+ * 2. Create a local host object with hostname "cltest2.host"
+ * 3. Attempt to open the remote host object
+ * 4. If the host does not exist, add a client id and create it
+ * 5. Disconnect
+ * 6. Reconnect
+ * 7. Refresh the host object
+ *
+ * Note that this program tests dhcpctl_timed_wait_for_completion() by calling
+ * it with extremely small timeouts.
+*/
+
+int main (argc, argv)
+ int argc;
+ char **argv;
+{
+ isc_result_t status;
+ dhcpctl_handle connection;
+ dhcpctl_handle host;
+ char* ip_address = "127.0.0.1";
+ int port = 7911;
+ char* hostname = "cltest2.host";
+ struct timeval timeout;
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp (argv[i], "-s")) {
+ ip_address = argv[i];
+ } else if (!strcmp (argv [i], "-p")) {
+ port=atoi(argv[i]);
+ } else if (argv[i][0] == '-') {
+ usage(argv[0]);
+ }
+ }
+
+ /* Initialize dhcpctl */
+ status = dhcpctl_initialize ();
+ fail_on_error(status ,"can't initialize dhcpctl");
+
+ /* Connect */
+ connection = 0;
+ status = dhcpctl_connect (&connection, ip_address, port, 0);
+ fail_on_error(status ,"connect failed");
+
+ /* Create the host object */
+ host = 0;
+ status = dhcpctl_new_object (&host, connection, "host");
+ fail_on_error(status ,"new oject failed");
+
+ status = dhcpctl_set_string_value (host, hostname, "name");
+ fail_on_error(status ,"cant set host name");
+
+ /* Attempt to open the object */
+ status = dhcpctl_open_object (host, connection, 0);
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 20;
+ status = wait_with_retry(host, &timeout, 2);
+ switch (status) {
+ case ISC_R_NOTFOUND:
+ /* Host doesn't exist add it. We set an id so the create will be valid. */
+ status = dhcpctl_set_string_value (host, "abcdefg", "dhcp-client-identifier");
+ fail_on_error(status ,"can't set client id");
+
+ status = dhcpctl_open_object (host, connection,
+ DHCPCTL_CREATE | DHCPCTL_EXCL);
+ fail_on_error(status, "open(create) failed");
+
+ status = wait_with_retry(host, &timeout, 2);
+ fail_on_error(status, "wait after open(create)");
+
+ print_object("Host created", host);
+ break;
+
+ case ISC_R_SUCCESS:
+ print_object("Host exists", host);
+ break;
+
+ default:
+ fail_on_error(status, "initial open failed, waiting for completion");
+ break;
+ }
+
+
+ /* Now we'll test disconnect */
+ status = dhcpctl_disconnect(&connection, 0);
+ fail_on_error(status, "can't disconnect");
+
+ /* Reconnect */
+ status = dhcpctl_connect (&connection, ip_address, port, 0);
+ fail_on_error(status ,"can't reconnect");
+
+ /* Refresh the object */
+ status = dhcpctl_object_refresh (connection, host);
+ fail_on_error(status , "can't refresh");
+
+ status = wait_with_retry(host, &timeout, 2);
+ fail_on_error(status , "wait after refresh failed");
+
+ print_object("After reconnect/refresh", host);
+
+ exit (0);
+}
+
+/* Function to call and optionally retry dhcp_timed_wait_for_completion() */
+isc_result_t wait_with_retry(dhcpctl_handle handle, struct timeval* timeout, int retries) {
+ isc_result_t status;
+ isc_result_t waitstatus;
+ struct timeval use_timeout;
+
+ if (timeout) {
+ use_timeout.tv_sec = timeout->tv_sec;
+ use_timeout.tv_usec = timeout->tv_usec;
+ } else {
+ retries = 0;
+ }
+
+ int tries = 0;
+ do {
+ if (tries++) {
+ printf ("wait retry #%d\n", tries);
+ /* Set the timeout value to 30 secs */
+ use_timeout.tv_sec = 30;
+ use_timeout.tv_usec = 0;
+ }
+
+ // Call timed wait.
+ status = dhcpctl_timed_wait_for_completion (handle, &waitstatus,
+ (timeout ? &use_timeout: 0));
+ if (status == ISC_R_SUCCESS) {
+ return(waitstatus);
+ }
+
+ if (status != ISC_R_TIMEDOUT) {
+ fprintf (stderr, "timed wait failed: %s\n", isc_result_totext (status));
+ exit (1);
+ }
+ } while (--retries > 0);
+
+ return (ISC_R_TIMEDOUT);
+}
+
+/* Function to print out the values contained in an object. Largely
+ * stolen from omshell.c */
+void print_object(char* msg, dhcpctl_handle handle) {
+ dhcpctl_remote_object_t *r = (dhcpctl_remote_object_t *)handle;
+ omapi_generic_object_t *object = (omapi_generic_object_t *)(r->inner);
+ char hex_buf[4096];
+ int i;
+
+ printf ("%s:\n",msg);
+ for (i = 0; i < object->nvalues; i++) {
+ omapi_value_t *v = object->values[i];
+
+ if (!object->values[i])
+ continue;
+
+ printf ("\t%.*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;
+ }
+ }
+}
+
+/* Dummy functions to appease linker */
+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
+void dhcpv6(struct packet *packet) { }
+
+#ifdef DHCP4o6
+isc_result_t dhcpv4o6_handler(omapi_object_t *h)
+{
+ return ISC_R_NOTIMPLEMENTED;
+}
+#endif /* DHCP4o6 */
+#endif /* DHCPv6 */
+
+int check_collection (struct packet *p, struct lease *l, struct collection *c)
+{
+ return 0;
+}
+void classify (struct packet *packet, struct class *class) { }
+
+isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
+ control_object_state_t newstate)
+{
+ return ISC_R_SUCCESS;
+}
+
diff --git a/dhcpctl/dhcpctl.c b/dhcpctl/dhcpctl.c
index 3c78bc19..e8834382 100644
--- a/dhcpctl/dhcpctl.c
+++ b/dhcpctl/dhcpctl.c
@@ -29,6 +29,10 @@
#include "dhcpd.h"
#include <omapip/omapip_p.h>
#include "dhcpctl.h"
+#include <sys/time.h>
+
+
+/* #define DEBUG_DHCPCTL 1 */
omapi_object_type_t *dhcpctl_callback_type;
omapi_object_type_t *dhcpctl_remote_type;
@@ -97,6 +101,9 @@ dhcpctl_status dhcpctl_connect (dhcpctl_handle *connection,
dhcpctl_handle authinfo)
{
isc_result_t status;
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_connect(%s:%d)", server_name, port);
+#endif
status = omapi_generic_new (connection, MDL);
if (status != ISC_R_SUCCESS) {
@@ -105,19 +112,35 @@ dhcpctl_status dhcpctl_connect (dhcpctl_handle *connection,
status = omapi_protocol_connect (*connection, server_name,
(unsigned)port, authinfo);
- if (status == ISC_R_SUCCESS)
+ if (status == ISC_R_SUCCESS) {
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_connect success");
+#endif
return status;
+ }
+
if (status != DHCP_R_INCOMPLETE) {
omapi_object_dereference (connection, MDL);
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_connect failed:%s",
+ isc_result_totext (status));
+#endif
return status;
}
status = omapi_wait_for_completion (*connection, 0);
if (status != ISC_R_SUCCESS) {
omapi_object_dereference (connection, MDL);
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_connect, wait failed:%s",
+ isc_result_totext (status));
+#endif
return status;
}
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_connect success");
+#endif
return status;
}
@@ -137,8 +160,58 @@ dhcpctl_status dhcpctl_connect (dhcpctl_handle *connection,
dhcpctl_status dhcpctl_wait_for_completion (dhcpctl_handle h,
dhcpctl_status *s)
{
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_wait_for_completion");
+#endif
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_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_timed_wait_for_completion (dhcpctl_handle h,
+ dhcpctl_status *s,
+ struct timeval *t)
+{
+ isc_result_t status;
+ struct timeval adjusted_t;
+
+#ifdef DEBUG_DHCPCTL
+ if (t) {
+ log_debug ("dhcpctl_timed_wait_for_completion(%u.%u secs.usecs)",
+ (unsigned int)(t->tv_sec),
+ (unsigned int)(t->tv_usec));
+ } else {
+ log_debug ("dhcpctl_timed_wait_for_completion(no timeout)");
+ }
+#endif
+
+ if (t) {
+ struct timeval now;
+ gettimeofday (&now, (struct timezone *)0);
+ adjusted_t.tv_sec = now.tv_sec + t->tv_sec;
+ adjusted_t.tv_usec = now.tv_usec + t->tv_usec;
+ }
+
+ status = omapi_wait_for_completion (h, (t ? &adjusted_t : 0));
if (status != ISC_R_SUCCESS)
return status;
if (h -> type == dhcpctl_remote_type)
@@ -146,6 +219,7 @@ dhcpctl_status dhcpctl_wait_for_completion (dhcpctl_handle h,
return ISC_R_SUCCESS;
}
+
/* dhcpctl_get_value
synchronous
@@ -168,6 +242,9 @@ dhcpctl_status dhcpctl_get_value (dhcpctl_data_string *result,
omapi_value_t *tv = (omapi_value_t *)0;
unsigned len;
int ip;
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_get_value(%s)", value_name);
+#endif
status = omapi_get_value_str (h, (omapi_object_t *)0, value_name, &tv);
if (status != ISC_R_SUCCESS)
@@ -232,6 +309,10 @@ dhcpctl_status dhcpctl_get_boolean (int *result,
isc_result_t status;
dhcpctl_data_string data = (dhcpctl_data_string)0;
int rv;
+
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_get_boolean(%s)", value_name);
+#endif
status = dhcpctl_get_value (&data, h, value_name);
if (status != ISC_R_SUCCESS)
@@ -258,6 +339,9 @@ dhcpctl_status dhcpctl_set_value (dhcpctl_handle h, dhcpctl_data_string value,
isc_result_t status;
omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
omapi_data_string_t *name = (omapi_data_string_t *)0;
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_set_value(%s)", value_name);
+#endif
status = omapi_data_string_new (&name, strlen (value_name), MDL);
if (status != ISC_R_SUCCESS)
@@ -291,6 +375,9 @@ dhcpctl_status dhcpctl_set_string_value (dhcpctl_handle h, const char *value,
isc_result_t status;
omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
omapi_data_string_t *name = (omapi_data_string_t *)0;
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_set_string_value(%s)", value_name);
+#endif
status = omapi_data_string_new (&name, strlen (value_name), MDL);
if (status != ISC_R_SUCCESS)
@@ -324,6 +411,9 @@ dhcpctl_status dhcpctl_set_data_value (dhcpctl_handle h,
omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
omapi_data_string_t *name = (omapi_data_string_t *)0;
unsigned ll;
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_set_data_value(%s)", value_name);
+#endif
ll = strlen (value_name);
status = omapi_data_string_new (&name, ll, MDL);
@@ -355,6 +445,9 @@ dhcpctl_status dhcpctl_set_null_value (dhcpctl_handle h,
isc_result_t status;
omapi_data_string_t *name = (omapi_data_string_t *)0;
unsigned ll;
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_set_null_value(%s)", value_name);
+#endif
ll = strlen (value_name);
status = omapi_data_string_new (&name, ll, MDL);
@@ -379,6 +472,9 @@ dhcpctl_status dhcpctl_set_boolean_value (dhcpctl_handle h, int value,
isc_result_t status;
omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
omapi_data_string_t *name = (omapi_data_string_t *)0;
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_set_boolean_value(%s)", value_name);
+#endif
status = omapi_data_string_new (&name, strlen (value_name), MDL);
if (status != ISC_R_SUCCESS)
@@ -408,6 +504,9 @@ dhcpctl_status dhcpctl_set_int_value (dhcpctl_handle h, int value,
isc_result_t status;
omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
omapi_data_string_t *name = (omapi_data_string_t *)0;
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_set_int_value(%s)", value_name);
+#endif
status = omapi_data_string_new (&name, strlen (value_name), MDL);
if (status != ISC_R_SUCCESS)
@@ -438,6 +537,9 @@ dhcpctl_status dhcpctl_object_update (dhcpctl_handle connection,
isc_result_t status;
omapi_object_t *message = (omapi_object_t *)0;
dhcpctl_remote_object_t *ro;
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_object_update");
+#endif
if (h -> type != dhcpctl_remote_type)
return DHCP_R_INVALIDARG;
@@ -487,6 +589,9 @@ dhcpctl_status dhcpctl_object_refresh (dhcpctl_handle connection,
isc_result_t status;
omapi_object_t *message = (omapi_object_t *)0;
dhcpctl_remote_object_t *ro;
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_object_refresh");
+#endif
if (h -> type != dhcpctl_remote_type)
return DHCP_R_INVALIDARG;
@@ -540,6 +645,9 @@ dhcpctl_status dhcpctl_object_remove (dhcpctl_handle connection,
isc_result_t status;
omapi_object_t *message = (omapi_object_t *)0;
dhcpctl_remote_object_t *ro;
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_object_remove");
+#endif
if (h -> type != dhcpctl_remote_type)
return DHCP_R_INVALIDARG;
@@ -582,5 +690,40 @@ dhcpctl_status dhcpctl_object_remove (dhcpctl_handle connection,
isc_result_t dhcpctl_data_string_dereference (dhcpctl_data_string *vp,
const char *file, int line)
{
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_data_string_dereference");
+#endif
return omapi_data_string_dereference (vp, file, line);
}
+
+dhcpctl_status dhcpctl_disconnect (dhcpctl_handle *connection,
+ int force)
+{
+ isc_result_t status;
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_disconnect()");
+#endif
+ if (!connection || !((*connection)->outer) ||
+ !((*connection)->outer->type) ||
+ ((*connection)->outer->type != omapi_type_protocol) ||
+ !((*connection)->outer->outer)) {
+ log_debug("dhcpctl_disconnect detected invalid arg");
+ return DHCP_R_INVALIDARG;
+ }
+
+ status = omapi_disconnect ((*connection)->outer->outer, force);
+ if (status == ISC_R_SUCCESS) {
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_disconnect success");
+#endif
+ omapi_object_dereference (connection, MDL);
+ return status;
+ }
+
+#ifdef DEBUG_DHCPCTL
+ log_debug("dhcpctl_disconnect failed:%s",
+ isc_result_totext (status));
+#endif
+ return status;
+}
+
diff --git a/dhcpctl/dhcpctl.h b/dhcpctl/dhcpctl.h
index 3c0da74b..0f779bd8 100644
--- a/dhcpctl/dhcpctl.h
+++ b/dhcpctl/dhcpctl.h
@@ -63,6 +63,11 @@ 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_timed_wait_for_completion (dhcpctl_handle h,
+ dhcpctl_status *s,
+ struct timeval *t);
+
dhcpctl_status dhcpctl_get_value (dhcpctl_data_string *,
dhcpctl_handle, const char *);
dhcpctl_status dhcpctl_get_boolean (int *, dhcpctl_handle, const char *);
@@ -116,4 +121,7 @@ isc_result_t dhcpctl_remote_stuff_values (omapi_object_t *,
omapi_object_t *);
isc_result_t dhcpctl_data_string_dereference (dhcpctl_data_string *,
const char *, int);
+
+dhcpctl_status dhcpctl_disconnect (dhcpctl_handle *, int);
+
#endif /* _DHCPCTL_H_ */
diff --git a/dhcpctl/omshell.c b/dhcpctl/omshell.c
index d5d31aa8..785f59a6 100644
--- a/dhcpctl/omshell.c
+++ b/dhcpctl/omshell.c
@@ -208,6 +208,7 @@ main(int argc, char **argv) {
printf (" server <server address>\n");
printf (" key <key name> <key value>\n");
printf (" connect\n");
+ printf (" disconnect\n");
printf (" new <object-type>\n");
printf (" set <name> = <value>\n");
printf (" create\n");
@@ -427,6 +428,28 @@ main(int argc, char **argv) {
connected = 1;
break;
+ case DISCONNECT:
+ token = next_token (&val, (unsigned *)0, cfile);
+ if (token != END_OF_FILE && token != EOL) {
+ printf ("usage: disconnect\n");
+ skip_to_semi (cfile);
+ break;
+ }
+
+ if (!connected || !connection) {
+ fprintf (stderr, "not connected\n");
+ break;
+ }
+
+ status = dhcpctl_disconnect (&connection, 0);
+ if (status != ISC_R_SUCCESS) {
+ fprintf (stderr, "dhcpctl_disconnect: %s\n",
+ isc_result_totext (status));
+ break;
+ }
+ connected = 0;
+ break;
+
case TOKEN_NEW:
token = next_token (&val, (unsigned *)0, cfile);
if ((!is_identifier (token) && token != STRING)) {
diff --git a/includes/dhctoken.h b/includes/dhctoken.h
index 6bf50e88..223e1110 100644
--- a/includes/dhctoken.h
+++ b/includes/dhctoken.h
@@ -376,7 +376,8 @@ enum dhcp_token {
LEASE_ID_FORMAT = 676,
TOKEN_HEX = 677,
TOKEN_OCTAL = 678,
- KEY_ALGORITHM = 679
+ KEY_ALGORITHM = 679,
+ DISCONNECT = 680
};
#define is_identifier(x) ((x) >= FIRST_TOKEN && \
diff --git a/includes/omapip/omapip_p.h b/includes/omapip/omapip_p.h
index b744a5ce..323bba3e 100644
--- a/includes/omapip/omapip_p.h
+++ b/includes/omapip/omapip_p.h
@@ -60,6 +60,9 @@
#include <dst/dst.h>
#include "result.h"
+/* Uncomment this to enable protocol level debug logs */
+/* #define DEBUG_PROTOCOL 1 */
+
#include <omapip/convert.h>
#include <omapip/hash.h>
#include <omapip/omapip.h>
diff --git a/omapip/connection.c b/omapip/connection.c
index 07b60a09..f1207757 100644
--- a/omapip/connection.c
+++ b/omapip/connection.c
@@ -461,7 +461,7 @@ isc_result_t omapi_disconnect (omapi_object_t *h,
omapi_connection_object_t *c;
#ifdef DEBUG_PROTOCOL
- log_debug ("omapi_disconnect(%s)", force ? "force" : "");
+ log_debug ("omapi_disconnect(force=%d)", force);
#endif
c = (omapi_connection_object_t *)h;
diff --git a/omapip/dispatch.c b/omapip/dispatch.c
index 426455ef..c730094c 100644
--- a/omapip/dispatch.c
+++ b/omapip/dispatch.c
@@ -413,13 +413,26 @@ isc_result_t omapi_unregister_io_object (omapi_object_t *h)
isc_result_t omapi_dispatch (struct timeval *t)
{
+#ifdef DEBUG_PROTOCOL
+ log_debug("omapi_dispatch()");
+#endif
return omapi_wait_for_completion ((omapi_object_t *)&omapi_io_states,
+
t);
}
isc_result_t omapi_wait_for_completion (omapi_object_t *object,
struct timeval *t)
{
+#ifdef DEBUG_PROTOCOL
+ if (t) {
+ log_debug ("omapi_wait_for_completion(%u.%u secs)",
+ (unsigned int)(t->tv_sec),
+ (unsigned int)(t->tv_usec));
+ } else {
+ log_debug ("omapi_wait_for_completion(no timeout)");
+ }
+#endif
isc_result_t status;
omapi_waiter_object_t *waiter;
omapi_object_t *inner;
@@ -453,10 +466,17 @@ isc_result_t omapi_wait_for_completion (omapi_object_t *object,
do {
status = omapi_one_dispatch ((omapi_object_t *)waiter, t);
- if (status != ISC_R_SUCCESS)
- return status;
+ if (status != ISC_R_SUCCESS) {
+#ifdef DEBUG_PROTOCOL
+ log_debug ("- call to omapi_one_dispatch failed: %s",
+ isc_result_totext (status));
+#endif
+ /* Break out on failure, to ensure we free up the waiter(s) */
+ break;
+ }
} while (!waiter || !waiter -> ready);
+
if (waiter -> outer) {
if (waiter -> outer -> inner) {
omapi_object_dereference (&waiter -> outer -> inner,
@@ -471,7 +491,12 @@ isc_result_t omapi_wait_for_completion (omapi_object_t *object,
if (waiter -> inner)
omapi_object_dereference (&waiter -> inner, MDL);
- status = waiter -> waitstatus;
+ if (status == ISC_R_SUCCESS) {
+ /* If the invocation worked, return the server's
+ * execution status */
+ status = waiter -> waitstatus;
+ }
+
omapi_waiter_dereference (&waiter, MDL);
return status;
}
@@ -479,6 +504,9 @@ isc_result_t omapi_wait_for_completion (omapi_object_t *object,
isc_result_t omapi_one_dispatch (omapi_object_t *wo,
struct timeval *t)
{
+#ifdef DEBUG_PROTOCOL
+ log_debug ("omapi_one_dispatch()");
+#endif
fd_set r, w, x, rr, ww, xx;
int max = 0;
int count;
@@ -549,6 +577,25 @@ isc_result_t omapi_one_dispatch (omapi_object_t *wo,
/* Same deal for write fdets. */
if (io -> writefd && io -> inner &&
(desc = (*(io -> writefd)) (io -> inner)) >= 0) {
+ /* This block avoids adding writefds that are already connected
+ * but that do not have data waiting to write. This avoids
+ * select() calls dropping immediately simply because the
+ * the writefd is ready to write. Without this synchronous
+ * waiting becomes CPU intensive polling */
+ if (io->inner && io->inner->type == omapi_type_connection) {
+ omapi_connection_object_t* c;
+ c = (omapi_connection_object_t *)(io->inner);
+ if (c->state == omapi_connection_connected && c->out_bytes == 0) {
+ /* We are already connected and have no data waiting to
+ * be written, so we avoid registering the fd. */
+#ifdef DEBUG_PROTOCOL
+ log_debug ("--- Connected, nothing to write, skip writefd\n");
+#endif
+ continue;
+ }
+ }
+
+
FD_SET (desc, &w);
if (desc > max)
max = desc;
@@ -571,6 +618,14 @@ isc_result_t omapi_one_dispatch (omapi_object_t *wo,
r = rr;
w = ww;
x = xx;
+
+#ifdef DEBUG_PROTOCOL
+ if (t) {
+ log_debug (" calling select with timout: %u.%u secs",
+ (unsigned int)(to.tv_sec),
+ (unsigned int)(to.tv_usec));
+ }
+#endif
count = select(max + 1, &r, &w, &x, t ? &to : NULL);
}
@@ -681,16 +736,18 @@ isc_result_t omapi_one_dispatch (omapi_object_t *wo,
see if we got input on that socket. */
if (io -> readfd &&
(desc = (*(io -> readfd)) (tmp)) >= 0) {
- if (FD_ISSET (desc, &r))
+ if (FD_ISSET (desc, &r)) {
((*(io -> reader)) (tmp));
+ }
}
/* Same deal for write descriptors. */
if (io -> writefd &&
(desc = (*(io -> writefd)) (tmp)) >= 0)
{
- if (FD_ISSET (desc, &w))
+ if (FD_ISSET (desc, &w)) {
((*(io -> writer)) (tmp));
+ }
}
omapi_object_dereference (&tmp, MDL);
}
@@ -837,6 +894,9 @@ isc_result_t omapi_io_destroy (omapi_object_t *h, const char *file, int line)
isc_result_t omapi_io_signal_handler (omapi_object_t *h,
const char *name, va_list ap)
{
+#ifdef DEBUG_PROTOCOL
+ log_debug ("omapi_io_signal_handler(%s)", name);
+#endif
if (h -> type != omapi_type_io_object)
return DHCP_R_INVALIDARG;
@@ -864,6 +924,9 @@ isc_result_t omapi_waiter_signal_handler (omapi_object_t *h,
{
omapi_waiter_object_t *waiter;
+#ifdef DEBUG_PROTOCOL
+ log_debug ("omapi_waiter_signal_handler(%s)", name);
+#endif
if (h -> type != omapi_type_waiter)
return DHCP_R_INVALIDARG;
diff --git a/omapip/support.c b/omapip/support.c
index f3791de0..92000a17 100644
--- a/omapip/support.c
+++ b/omapip/support.c
@@ -308,7 +308,7 @@ isc_result_t omapi_set_value (omapi_object_t *h,
omapi_object_t *outer;
isc_result_t status;
-#if defined (DEBUG)
+#if defined (DEBUG_PROTOCOL)
if (!value) {
log_info ("omapi_set_value (%.*s, NULL)",
(int)name -> len, name -> value);
@@ -343,7 +343,7 @@ isc_result_t omapi_set_value (omapi_object_t *h,
id, name, value);
else
status = ISC_R_NOTFOUND;
-#if defined (DEBUG)
+#if defined (DEBUG_PROTOCOL)
log_info (" ==> %s", isc_result_totext (status));
#endif
return status;