]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
[#76] Initial implemention to dhcpctl_timed_wait_for_completion
authorThomas Markwalder <tmark@isc.org>
Thu, 23 Jan 2020 21:21:52 +0000 (16:21 -0500)
committerThomas Markwalder <tmark@isc.org>
Thu, 20 Jan 2022 21:30:49 +0000 (16:30 -0500)
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

13 files changed:
common/conflex.c
dhcpctl/Makefile.am
dhcpctl/Makefile.am.in
dhcpctl/Makefile.in
dhcpctl/cltest2.c [new file with mode: 0644]
dhcpctl/dhcpctl.c
dhcpctl/dhcpctl.h
dhcpctl/omshell.c
includes/dhctoken.h
includes/omapip/omapip_p.h
omapip/connection.c
omapip/dispatch.c
omapip/support.c

index 7b671560cfdbaea3060246c1e1e3e689292d9ca5..db1e1a09af111d50b530c6bf20533de38e640eb9 100644 (file)
@@ -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]) &&
index 0d669715ce8ec35db78ec780152d6ac10946c50b..9e623375b22954371741dd00f9585afe31ea886e 100644 (file)
@@ -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
index 0d77ffc673ffaabc0c2882fe4fd31914c542b6ee..28333cef8ca5bf4976871717ad03a98098186c4f 100644 (file)
@@ -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@
index 3c8232d1820f5b0339195e190fd41020c8c8c4ee..e1da56a5dc31a2742194ed4dba73e2c560c19841 100644 (file)
@@ -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,
 
 
 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 (file)
index 0000000..26249a3
--- /dev/null
@@ -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;
+}
+
index 3c78bc19a67d96ee4d0b5d1580870432095130b1..e8834382eadecb854e613df621d7914198585d7f 100644 (file)
 #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;
+}
+
index 3c0da74ba9a11825bce6a209be86e278a39a97f6..0f779bd802574e591b806ae290fcc4860455860e 100644 (file)
@@ -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_ */
index d5d31aa8ed4fd042ed6752384ec98175dc466d28..785f59a6652d6ad474a7d5b83f387de4d2e33dfa 100644 (file)
@@ -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)) {
index 6bf50e8819db97818572c213492cec680caab876..223e11101705f8216783de1f137cc68688e99e91 100644 (file)
@@ -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 &&  \
index b744a5ce831c285ad51e51338248ef01d64c9fcf..323bba3ea8523e3fceb473f5dcdefbe83dcde11d 100644 (file)
@@ -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>
index 07b60a0964001ee1e0d4a10651701f58e48739d4..f1207757562b5a55d56f23d0b464449f666ac7a3 100644 (file)
@@ -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;
index 426455efd316b9a23478bdd9ac5b00550c036c8d..c730094cd191a31749bdfe47c65935824efc2a20 100644 (file)
@@ -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;
 
index f3791de0688c2408103dc8658617472e90256cf8..92000a1776925636e7cfe9affa53860d33029e8e 100644 (file)
@@ -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;