diff options
Diffstat (limited to 'src/libcharon/plugins/ha')
-rw-r--r-- | src/libcharon/plugins/ha/Makefile.am | 12 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/Makefile.in | 159 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_attribute.c | 46 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_cache.c | 24 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_cache.h | 2 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_child.c | 16 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_ctl.c | 15 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_dispatcher.c | 266 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_ike.c | 160 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_kernel.c | 3 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_message.c | 20 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_message.h | 18 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_plugin.c | 67 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_segments.c | 132 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_socket.c | 3 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_tunnel.c | 14 |
16 files changed, 753 insertions, 204 deletions
diff --git a/src/libcharon/plugins/ha/Makefile.am b/src/libcharon/plugins/ha/Makefile.am index bc1b49d48..c10f7f903 100644 --- a/src/libcharon/plugins/ha/Makefile.am +++ b/src/libcharon/plugins/ha/Makefile.am @@ -1,8 +1,11 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon \ + -DIPSEC_PIDDIR=\"${piddir}\" -INCLUDES = -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon - -AM_CFLAGS = -rdynamic -DIPSEC_PIDDIR=\"${piddir}\" +AM_CFLAGS = \ + -rdynamic if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-ha.la @@ -24,4 +27,3 @@ libstrongswan_ha_la_SOURCES = \ ha_child.h ha_child.c \ ha_attribute.h ha_attribute.c libstrongswan_ha_la_LDFLAGS = -module -avoid-version - diff --git a/src/libcharon/plugins/ha/Makefile.in b/src/libcharon/plugins/ha/Makefile.in index c66a550cd..302ad0fab 100644 --- a/src/libcharon/plugins/ha/Makefile.in +++ b/src/libcharon/plugins/ha/Makefile.in @@ -1,9 +1,9 @@ -# Makefile.in generated by automake 1.11.1 from Makefile.am. +# Makefile.in generated by automake 1.11.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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. @@ -16,6 +16,23 @@ @SET_MAKE@ VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -45,10 +62,11 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ $(top_srcdir)/m4/macros/with.m4 \ $(top_srcdir)/m4/macros/enable-disable.m4 \ $(top_srcdir)/m4/macros/add-plugin.m4 \ - $(top_srcdir)/configure.in + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; @@ -72,6 +90,12 @@ am__nobase_list = $(am__nobase_strip_setup); \ 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)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) libstrongswan_ha_la_LIBADD = @@ -80,47 +104,76 @@ am_libstrongswan_ha_la_OBJECTS = ha_plugin.lo ha_message.lo \ ha_cache.lo ha_kernel.lo ha_ctl.lo ha_ike.lo ha_child.lo \ ha_attribute.lo libstrongswan_ha_la_OBJECTS = $(am_libstrongswan_ha_la_OBJECTS) -libstrongswan_ha_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(libstrongswan_ha_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +libstrongswan_ha_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_ha_la_LDFLAGS) \ + $(LDFLAGS) -o $@ @MONOLITHIC_FALSE@am_libstrongswan_ha_la_rpath = -rpath $(plugindir) @MONOLITHIC_TRUE@am_libstrongswan_ha_la_rpath = -DEFAULT_INCLUDES = -I.@am__isrc@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) 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) -LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=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_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ CCLD = $(CC) -LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ - $(LDFLAGS) -o $@ +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=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_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; SOURCES = $(libstrongswan_ha_la_SOURCES) DIST_SOURCES = $(libstrongswan_ha_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ +BFDLIB = @BFDLIB@ BTLIB = @BTLIB@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ +CHECK_CFLAGS = @CHECK_CFLAGS@ +CHECK_LIBS = @CHECK_LIBS@ +COVERAGE_CFLAGS = @COVERAGE_CFLAGS@ +COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLIB = @DLLIB@ +DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ @@ -129,13 +182,16 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +GENHTML = @GENHTML@ GPERF = @GPERF@ +GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ @@ -148,6 +204,7 @@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQLCFLAG = @MYSQLCFLAG@ MYSQLCONFIG = @MYSQLCONFIG@ @@ -175,11 +232,13 @@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ RUBYINCLUDE = @RUBYINCLUDE@ +RUBYLIB = @RUBYLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOCKLIB = @SOCKLIB@ STRIP = @STRIP@ +UNWINDLIB = @UNWINDLIB@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ @@ -187,6 +246,7 @@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ @@ -195,8 +255,6 @@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ attest_plugins = @attest_plugins@ -axis2c_CFLAGS = @axis2c_CFLAGS@ -axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -205,14 +263,19 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +charon_natt_port = @charon_natt_port@ +charon_plugins = @charon_plugins@ +charon_udp_port = @charon_udp_port@ clearsilver_LIBS = @clearsilver_LIBS@ +cmd_plugins = @cmd_plugins@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ -default_pkcs11 = @default_pkcs11@ +dev_headers = @dev_headers@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ +fips_mode = @fips_mode@ gtk_CFLAGS = @gtk_CFLAGS@ gtk_LIBS = @gtk_LIBS@ h_plugins = @h_plugins@ @@ -226,17 +289,17 @@ imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ +ipsec_script = @ipsec_script@ +ipsec_script_upper = @ipsec_script_upper@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ -libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ libexecdir = @libexecdir@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ -lt_ECHO = @lt_ECHO@ maemo_CFLAGS = @maemo_CFLAGS@ maemo_LIBS = @maemo_LIBS@ manager_plugins = @manager_plugins@ @@ -246,16 +309,15 @@ mkdir_p = @mkdir_p@ nm_CFLAGS = @nm_CFLAGS@ nm_LIBS = @nm_LIBS@ nm_ca_dir = @nm_ca_dir@ +nm_plugins = @nm_plugins@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ -p_plugins = @p_plugins@ pcsclite_CFLAGS = @pcsclite_CFLAGS@ pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ plugindir = @plugindir@ -pluto_plugins = @pluto_plugins@ pool_plugins = @pool_plugins@ prefix = @prefix@ program_transform_name = @program_transform_name@ @@ -283,10 +345,15 @@ top_srcdir = @top_srcdir@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon \ + -DIPSEC_PIDDIR=\"${piddir}\" + +AM_CFLAGS = \ + -rdynamic -AM_CFLAGS = -rdynamic -DIPSEC_PIDDIR=\"${piddir}\" @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-ha.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-ha.la libstrongswan_ha_la_SOURCES = \ @@ -349,7 +416,6 @@ clean-noinstLTLIBRARIES: done install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) - test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ @@ -357,6 +423,8 @@ install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) else :; fi; \ done; \ test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } @@ -378,8 +446,8 @@ clean-pluginLTLIBRARIES: echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done -libstrongswan-ha.la: $(libstrongswan_ha_la_OBJECTS) $(libstrongswan_ha_la_DEPENDENCIES) - $(libstrongswan_ha_la_LINK) $(am_libstrongswan_ha_la_rpath) $(libstrongswan_ha_la_OBJECTS) $(libstrongswan_ha_la_LIBADD) $(LIBS) +libstrongswan-ha.la: $(libstrongswan_ha_la_OBJECTS) $(libstrongswan_ha_la_DEPENDENCIES) $(EXTRA_libstrongswan_ha_la_DEPENDENCIES) + $(AM_V_CCLD)$(libstrongswan_ha_la_LINK) $(am_libstrongswan_ha_la_rpath) $(libstrongswan_ha_la_OBJECTS) $(libstrongswan_ha_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -401,25 +469,25 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_tunnel.Plo@am__quote@ .c.o: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@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@ $(COMPILE) -c $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@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@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: -@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo @@ -526,10 +594,15 @@ install-am: all-am installcheck: installcheck-am install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install + 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: diff --git a/src/libcharon/plugins/ha/ha_attribute.c b/src/libcharon/plugins/ha/ha_attribute.c index b08abe1a9..d26c38325 100644 --- a/src/libcharon/plugins/ha/ha_attribute.c +++ b/src/libcharon/plugins/ha/ha_attribute.c @@ -15,7 +15,7 @@ #include "ha_attribute.h" -#include <utils/linked_list.h> +#include <collections/linked_list.h> #include <threading/mutex.h> typedef struct private_ha_attribute_t private_ha_attribute_t; @@ -170,17 +170,29 @@ static bool responsible_for(private_ha_attribute_t *this, int bit) } METHOD(attribute_provider_t, acquire_address, host_t*, - private_ha_attribute_t *this, char *name, identification_t *id, + private_ha_attribute_t *this, linked_list_t *pools, identification_t *id, host_t *requested) { - pool_t *pool; + enumerator_t *enumerator; + pool_t *pool = NULL; int offset = -1, byte, bit; host_t *address; + char *name; + enumerator = pools->create_enumerator(pools); this->mutex->lock(this->mutex); - pool = get_pool(this, name); - if (pool) + while (enumerator->enumerate(enumerator, &name)) { + pool = get_pool(this, name); + if (!pool) + { + continue; + } + if (pool->base->get_family(pool->base) != + requested->get_family(requested)) + { + continue; + } for (byte = 0; byte < pool->size / 8; byte++) { if (pool->mask[byte] != 0xFF) @@ -208,6 +220,8 @@ METHOD(attribute_provider_t, acquire_address, host_t*, } } this->mutex->unlock(this->mutex); + enumerator->destroy(enumerator); + if (offset != -1) { address = offset2host(pool, offset); @@ -218,26 +232,40 @@ METHOD(attribute_provider_t, acquire_address, host_t*, } METHOD(attribute_provider_t, release_address, bool, - private_ha_attribute_t *this, char *name, host_t *address, + private_ha_attribute_t *this, linked_list_t *pools, host_t *address, identification_t *id) { + enumerator_t *enumerator; pool_t *pool; int offset; + char *name; bool found = FALSE; + enumerator = pools->create_enumerator(pools); this->mutex->lock(this->mutex); - pool = get_pool(this, name); - if (pool) + while (enumerator->enumerate(enumerator, &name)) { + pool = get_pool(this, name); + if (!pool) + { + continue; + } + if (pool->base->get_family(pool->base) != address->get_family(address)) + { + continue; + } offset = host2offset(pool, address); if (offset > 0 && offset < pool->size) { pool->mask[offset / 8] &= ~(1 << (offset % 8)); DBG1(DBG_CFG, "released address %H to HA pool '%s'", address, name); found = TRUE; + break; } } this->mutex->unlock(this->mutex); + enumerator->destroy(enumerator); + return found; } @@ -281,7 +309,7 @@ static void load_pools(private_ha_attribute_t *this) pool_t *pool; enumerator = lib->settings->create_key_value_enumerator(lib->settings, - "charon.plugins.ha.pools"); + "%s.plugins.ha.pools", charon->name); while (enumerator->enumerate(enumerator, &name, &net)) { net = strdup(net); diff --git a/src/libcharon/plugins/ha/ha_cache.c b/src/libcharon/plugins/ha/ha_cache.c index 970a8a2b9..ce1afe6f9 100644 --- a/src/libcharon/plugins/ha/ha_cache.c +++ b/src/libcharon/plugins/ha/ha_cache.c @@ -15,8 +15,8 @@ #include "ha_cache.h" -#include <utils/hashtable.h> -#include <utils/linked_list.h> +#include <collections/hashtable.h> +#include <collections/linked_list.h> #include <threading/mutex.h> #include <processing/jobs/callback_job.h> @@ -88,6 +88,8 @@ typedef struct { ha_message_t *midi; /* last responder mid */ ha_message_t *midr; + /* last IV update */ + ha_message_t *iv; } entry_t; /** @@ -114,6 +116,7 @@ static void entry_destroy(entry_t *entry) entry->add->destroy(entry->add); DESTROY_IF(entry->midi); DESTROY_IF(entry->midr); + DESTROY_IF(entry->iv); free(entry); } @@ -164,6 +167,16 @@ METHOD(ha_cache_t, cache, void, } message->destroy(message); break; + case HA_IKE_IV: + entry = this->cache->get(this->cache, ike_sa); + if (entry) + { + DESTROY_IF(entry->iv); + entry->iv = message; + break; + } + message->destroy(message); + break; case HA_IKE_DELETE: entry = this->cache->remove(this->cache, ike_sa); if (entry) @@ -212,7 +225,8 @@ static status_t rekey_children(ike_sa_t *ike_sa) DBG1(DBG_CFG, "resyncing CHILD_SA using a delete"); status = ike_sa->delete_child_sa(ike_sa, child_sa->get_protocol(child_sa), - child_sa->get_spi(child_sa, TRUE)); + child_sa->get_spi(child_sa, TRUE), + FALSE); } else { @@ -308,6 +322,10 @@ METHOD(ha_cache_t, resync, void, { this->socket->push(this->socket, entry->midr); } + if (entry->iv) + { + this->socket->push(this->socket, entry->iv); + } } } enumerator->destroy(enumerator); diff --git a/src/libcharon/plugins/ha/ha_cache.h b/src/libcharon/plugins/ha/ha_cache.h index 39f1947a8..5e3936a20 100644 --- a/src/libcharon/plugins/ha/ha_cache.h +++ b/src/libcharon/plugins/ha/ha_cache.h @@ -27,7 +27,7 @@ typedef struct ha_cache_t ha_cache_t; #include "ha_kernel.h" #include "ha_socket.h" -#include <utils/enumerator.h> +#include <collections/enumerator.h> #include <sa/ike_sa.h> diff --git a/src/libcharon/plugins/ha/ha_child.c b/src/libcharon/plugins/ha/ha_child.c index 707add94d..c166d72ac 100644 --- a/src/libcharon/plugins/ha/ha_child.c +++ b/src/libcharon/plugins/ha/ha_child.c @@ -103,18 +103,22 @@ METHOD(listener_t, child_keys, bool, chunk_clear(&secret); } - local_ts = child_sa->get_traffic_selectors(child_sa, TRUE); - enumerator = local_ts->create_enumerator(local_ts); + local_ts = linked_list_create(); + remote_ts = linked_list_create(); + + enumerator = child_sa->create_ts_enumerator(child_sa, TRUE); while (enumerator->enumerate(enumerator, &ts)) { m->add_attribute(m, HA_LOCAL_TS, ts); + local_ts->insert_last(local_ts, ts); } enumerator->destroy(enumerator); - remote_ts = child_sa->get_traffic_selectors(child_sa, FALSE); - enumerator = remote_ts->create_enumerator(remote_ts); + + enumerator = child_sa->create_ts_enumerator(child_sa, FALSE); while (enumerator->enumerate(enumerator, &ts)) { m->add_attribute(m, HA_REMOTE_TS, ts); + remote_ts->insert_last(remote_ts, ts); } enumerator->destroy(enumerator); @@ -128,6 +132,9 @@ METHOD(listener_t, child_keys, bool, seg_i, this->segments->is_active(this->segments, seg_i) ? "*" : "", seg_o, this->segments->is_active(this->segments, seg_o) ? "*" : ""); + local_ts->destroy(local_ts); + remote_ts->destroy(remote_ts); + this->socket->push(this->socket, m); m->destroy(m); @@ -195,4 +202,3 @@ ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel, return &this->public; } - diff --git a/src/libcharon/plugins/ha/ha_ctl.c b/src/libcharon/plugins/ha/ha_ctl.c index 9c99807ed..178a0349b 100644 --- a/src/libcharon/plugins/ha/ha_ctl.c +++ b/src/libcharon/plugins/ha/ha_ctl.c @@ -48,11 +48,6 @@ struct private_ha_ctl_t { * Resynchronization message cache */ ha_cache_t *cache; - - /** - * FIFO reader thread - */ - callback_job_t *job; }; /** @@ -105,7 +100,6 @@ static job_requeue_t dispatch_fifo(private_ha_ctl_t *this) METHOD(ha_ctl_t, destroy, void, private_ha_ctl_t *this) { - this->job->cancel(this->job); free(this); } @@ -135,15 +129,16 @@ ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache) } umask(old); } - if (chown(HA_FIFO, charon->uid, charon->gid) != 0) + if (chown(HA_FIFO, lib->caps->get_uid(lib->caps), + lib->caps->get_gid(lib->caps)) != 0) { DBG1(DBG_CFG, "changing HA FIFO permissions failed: %s", strerror(errno)); } - this->job = callback_job_create_with_prio((callback_job_cb_t)dispatch_fifo, - this, NULL, NULL, JOB_PRIO_CRITICAL); - lib->processor->queue_job(lib->processor, (job_t*)this->job); + lib->processor->queue_job(lib->processor, + (job_t*)callback_job_create_with_prio((callback_job_cb_t)dispatch_fifo, + this, NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL)); return &this->public; } diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c index 994f91d20..1ce9d3a16 100644 --- a/src/libcharon/plugins/ha/ha_dispatcher.c +++ b/src/libcharon/plugins/ha/ha_dispatcher.c @@ -16,9 +16,13 @@ #include "ha_dispatcher.h" #include <daemon.h> +#include <sa/ikev2/keymat_v2.h> +#include <sa/ikev1/keymat_v1.h> #include <processing/jobs/callback_job.h> +#include <processing/jobs/adopt_children_job.h> typedef struct private_ha_dispatcher_t private_ha_dispatcher_t; +typedef struct ha_diffie_hellman_t ha_diffie_hellman_t; /** * Private data of an ha_dispatcher_t object. @@ -54,20 +58,66 @@ struct private_ha_dispatcher_t { * HA enabled pool */ ha_attribute_t *attr; +}; + +/** + * DH implementation for HA synced DH values + */ +struct ha_diffie_hellman_t { + + /** + * Implements diffie_hellman_t + */ + diffie_hellman_t dh; /** - * Dispatcher job + * Shared secret */ - callback_job_t *job; + chunk_t secret; + + /** + * Own public value + */ + chunk_t pub; }; +METHOD(diffie_hellman_t, dh_get_shared_secret, status_t, + ha_diffie_hellman_t *this, chunk_t *secret) +{ + *secret = chunk_clone(this->secret); + return SUCCESS; +} + +METHOD(diffie_hellman_t, dh_get_my_public_value, void, + ha_diffie_hellman_t *this, chunk_t *value) +{ + *value = chunk_clone(this->pub); +} + +METHOD(diffie_hellman_t, dh_destroy, void, + ha_diffie_hellman_t *this) +{ + free(this); +} + /** - * Quick and dirty hack implementation of diffie_hellman_t.get_shared_secret + * Create a HA synced DH implementation */ -static status_t get_shared_secret(diffie_hellman_t *this, chunk_t *secret) +static diffie_hellman_t *ha_diffie_hellman_create(chunk_t secret, chunk_t pub) { - *secret = chunk_clone((*(chunk_t*)this->destroy)); - return SUCCESS; + ha_diffie_hellman_t *this; + + INIT(this, + .dh = { + .get_shared_secret = _dh_get_shared_secret, + .get_my_public_value = _dh_get_my_public_value, + .destroy = _dh_destroy, + }, + .secret = secret, + .pub = pub, + ); + + return &this->dh; } /** @@ -79,9 +129,12 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message ha_message_value_t value; enumerator_t *enumerator; ike_sa_t *ike_sa = NULL, *old_sa = NULL; + ike_version_t version = IKEV2; u_int16_t encr = 0, len = 0, integ = 0, prf = 0, old_prf = PRF_UNDEFINED; chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty; chunk_t secret = chunk_empty, old_skd = chunk_empty; + chunk_t dh_local = chunk_empty, dh_remote = chunk_empty, psk = chunk_empty; + bool ok = FALSE; enumerator = message->create_attribute_enumerator(message); while (enumerator->enumerate(enumerator, &attribute, &value)) @@ -89,12 +142,16 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message switch (attribute) { case HA_IKE_ID: - ike_sa = ike_sa_create(value.ike_sa_id); + ike_sa = ike_sa_create(value.ike_sa_id, + value.ike_sa_id->is_initiator(value.ike_sa_id), version); break; case HA_IKE_REKEY_ID: old_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, value.ike_sa_id); break; + case HA_IKE_VERSION: + version = value.u8; + break; case HA_NONCE_I: nonce_i = value.chunk; break; @@ -104,6 +161,15 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message case HA_SECRET: secret = value.chunk; break; + case HA_LOCAL_DH: + dh_local = value.chunk; + break; + case HA_REMOTE_DH: + dh_remote = value.chunk; + break; + case HA_PSK: + psk = value.chunk; + break; case HA_OLD_SKD: old_skd = value.chunk; break; @@ -131,13 +197,9 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message if (ike_sa) { proposal_t *proposal; - keymat_t *keymat; - /* quick and dirty hack of a DH implementation ;-) */ - diffie_hellman_t dh = { .get_shared_secret = get_shared_secret, - .destroy = (void*)&secret }; + diffie_hellman_t *dh; proposal = proposal_create(PROTO_IKE, 0); - keymat = ike_sa->get_keymat(ike_sa); if (integ) { proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, integ, 0); @@ -151,8 +213,35 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, prf, 0); } charon->bus->set_sa(charon->bus, ike_sa); - if (keymat->derive_ike_keys(keymat, proposal, &dh, nonce_i, nonce_r, - ike_sa->get_id(ike_sa), old_prf, old_skd)) + dh = ha_diffie_hellman_create(secret, dh_local); + if (ike_sa->get_version(ike_sa) == IKEV2) + { + keymat_v2_t *keymat_v2 = (keymat_v2_t*)ike_sa->get_keymat(ike_sa); + + ok = keymat_v2->derive_ike_keys(keymat_v2, proposal, dh, nonce_i, + nonce_r, ike_sa->get_id(ike_sa), old_prf, old_skd); + } + if (ike_sa->get_version(ike_sa) == IKEV1) + { + keymat_v1_t *keymat_v1 = (keymat_v1_t*)ike_sa->get_keymat(ike_sa); + shared_key_t *shared = NULL; + auth_method_t method = AUTH_RSA; + + if (psk.len) + { + method = AUTH_PSK; + shared = shared_key_create(SHARED_IKE, chunk_clone(psk)); + } + if (keymat_v1->create_hasher(keymat_v1, proposal)) + { + ok = keymat_v1->derive_ike_keys(keymat_v1, proposal, + dh, dh_remote, nonce_i, nonce_r, + ike_sa->get_id(ike_sa), method, shared); + } + DESTROY_IF(shared); + } + dh->destroy(dh); + if (ok) { if (old_sa) { @@ -168,6 +257,7 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message old_sa = NULL; } ike_sa->set_state(ike_sa, IKE_CONNECTING); + ike_sa->set_proposal(ike_sa, proposal); this->cache->cache(this->cache, ike_sa, message); message = NULL; charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); @@ -220,7 +310,7 @@ static void process_ike_update(private_ha_dispatcher_t *this, ike_sa_t *ike_sa = NULL; peer_cfg_t *peer_cfg = NULL; auth_cfg_t *auth; - bool received_vip = FALSE, first_peer_addr = TRUE; + bool received_vip = FALSE, first_local_vip = TRUE, first_peer_addr = TRUE; enumerator = message->create_attribute_enumerator(message); while (enumerator->enumerate(enumerator, &attribute, &value)) @@ -254,10 +344,19 @@ static void process_ike_update(private_ha_dispatcher_t *this, ike_sa->set_other_host(ike_sa, value.host->clone(value.host)); break; case HA_LOCAL_VIP: - ike_sa->set_virtual_ip(ike_sa, TRUE, value.host); + if (first_local_vip) + { + ike_sa->clear_virtual_ips(ike_sa, TRUE); + first_local_vip = FALSE; + } + ike_sa->add_virtual_ip(ike_sa, TRUE, value.host); break; case HA_REMOTE_VIP: - ike_sa->set_virtual_ip(ike_sa, FALSE, value.host); + if (!received_vip) + { + ike_sa->clear_virtual_ips(ike_sa, FALSE); + } + ike_sa->add_virtual_ip(ike_sa, FALSE, value.host); received_vip = TRUE; break; case HA_PEER_ADDR: @@ -289,6 +388,8 @@ static void process_ike_update(private_ha_dispatcher_t *this, set_extension(ike_sa, value.u32, EXT_STRONGSWAN); set_extension(ike_sa, value.u32, EXT_EAP_ONLY_AUTHENTICATION); set_extension(ike_sa, value.u32, EXT_MS_WINDOWS); + set_extension(ike_sa, value.u32, EXT_XAUTH); + set_extension(ike_sa, value.u32, EXT_DPD); break; case HA_CONDITIONS: set_condition(ike_sa, value.u32, COND_NAT_ANY); @@ -299,6 +400,8 @@ static void process_ike_update(private_ha_dispatcher_t *this, set_condition(ike_sa, value.u32, COND_CERTREQ_SEEN); set_condition(ike_sa, value.u32, COND_ORIGINAL_INITIATOR); set_condition(ike_sa, value.u32, COND_STALE); + set_condition(ike_sa, value.u32, COND_INIT_CONTACT_SEEN); + set_condition(ike_sa, value.u32, COND_XAUTH_AUTHENTICATED); break; default: break; @@ -319,20 +422,31 @@ static void process_ike_update(private_ha_dispatcher_t *this, } if (received_vip) { + enumerator_t *pools, *vips; host_t *vip; char *pool; peer_cfg = ike_sa->get_peer_cfg(ike_sa); - vip = ike_sa->get_virtual_ip(ike_sa, FALSE); - if (peer_cfg && vip) + if (peer_cfg) { - pool = peer_cfg->get_pool(peer_cfg); - if (pool) + pools = peer_cfg->create_pool_enumerator(peer_cfg); + while (pools->enumerate(pools, &pool)) { - this->attr->reserve(this->attr, pool, vip); + vips = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE); + while (vips->enumerate(vips, &vip)) + { + this->attr->reserve(this->attr, pool, vip); + } + vips->destroy(vips); } + pools->destroy(pools); } } + if (ike_sa->get_version(ike_sa) == IKEV1) + { + lib->processor->queue_job(lib->processor, (job_t*) + adopt_children_job_create(ike_sa->get_id(ike_sa))); + } this->cache->cache(this->cache, ike_sa, message); charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } @@ -389,6 +503,59 @@ static void process_ike_mid(private_ha_dispatcher_t *this, } /** + * Process messages of type IKE_IV + */ +static void process_ike_iv(private_ha_dispatcher_t *this, ha_message_t *message) +{ + ha_message_attribute_t attribute; + ha_message_value_t value; + enumerator_t *enumerator; + ike_sa_t *ike_sa = NULL; + chunk_t iv = chunk_empty; + + enumerator = message->create_attribute_enumerator(message); + while (enumerator->enumerate(enumerator, &attribute, &value)) + { + switch (attribute) + { + case HA_IKE_ID: + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + value.ike_sa_id); + break; + case HA_IV: + iv = value.chunk; + break; + default: + break; + } + } + enumerator->destroy(enumerator); + + if (ike_sa) + { + if (ike_sa->get_version(ike_sa) == IKEV1) + { + if (iv.len) + { + keymat_v1_t *keymat; + + keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa); + if (keymat->update_iv(keymat, 0, iv)) + { + keymat->confirm_iv(keymat, 0); + } + } + } + this->cache->cache(this->cache, ike_sa, message); + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + else + { + message->destroy(message); + } +} + +/** * Process messages of type IKE_DELETE */ static void process_ike_delete(private_ha_dispatcher_t *this, @@ -465,8 +632,7 @@ static void process_child_add(private_ha_dispatcher_t *this, child_cfg_t *config = NULL; child_sa_t *child_sa; proposal_t *proposal; - keymat_t *keymat; - bool initiator = FALSE, failed = FALSE; + bool initiator = FALSE, failed = FALSE, ok = FALSE; u_int32_t inbound_spi = 0, outbound_spi = 0; u_int16_t inbound_cpi = 0, outbound_cpi = 0; u_int8_t mode = MODE_TUNNEL, ipcomp = 0; @@ -476,9 +642,7 @@ static void process_child_add(private_ha_dispatcher_t *this, chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty; chunk_t encr_i, integ_i, encr_r, integ_r; linked_list_t *local_ts, *remote_ts; - /* quick and dirty hack of a DH implementation */ - diffie_hellman_t dh = { .get_shared_secret = get_shared_secret, - .destroy = (void*)&secret }; + diffie_hellman_t *dh = NULL; enumerator = message->create_attribute_enumerator(message); while (enumerator->enumerate(enumerator, &attribute, &value)) @@ -572,10 +736,30 @@ static void process_child_add(private_ha_dispatcher_t *this, proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len); } proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, esn, 0); - keymat = ike_sa->get_keymat(ike_sa); + if (secret.len) + { + dh = ha_diffie_hellman_create(secret, chunk_empty); + } + if (ike_sa->get_version(ike_sa) == IKEV2) + { + keymat_v2_t *keymat_v2 = (keymat_v2_t*)ike_sa->get_keymat(ike_sa); - if (!keymat->derive_child_keys(keymat, proposal, secret.ptr ? &dh : NULL, - nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r)) + ok = keymat_v2->derive_child_keys(keymat_v2, proposal, dh, + nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r); + } + if (ike_sa->get_version(ike_sa) == IKEV1) + { + keymat_v1_t *keymat_v1 = (keymat_v1_t*)ike_sa->get_keymat(ike_sa); + u_int32_t spi_i, spi_r; + + spi_i = initiator ? inbound_spi : outbound_spi; + spi_r = initiator ? outbound_spi : inbound_spi; + + ok = keymat_v1->derive_child_keys(keymat_v1, proposal, dh, spi_i, spi_r, + nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r); + } + DESTROY_IF(dh); + if (!ok) { DBG1(DBG_CHD, "HA CHILD_SA key derivation failed"); child_sa->destroy(child_sa); @@ -610,9 +794,11 @@ static void process_child_add(private_ha_dispatcher_t *this, if (initiator) { if (child_sa->install(child_sa, encr_r, integ_r, inbound_spi, - inbound_cpi, TRUE, TRUE, local_ts, remote_ts) != SUCCESS || + inbound_cpi, initiator, TRUE, TRUE, + local_ts, remote_ts) != SUCCESS || child_sa->install(child_sa, encr_i, integ_i, outbound_spi, - outbound_cpi, FALSE, TRUE, local_ts, remote_ts) != SUCCESS) + outbound_cpi, initiator, FALSE, TRUE, + local_ts, remote_ts) != SUCCESS) { failed = TRUE; } @@ -620,9 +806,11 @@ static void process_child_add(private_ha_dispatcher_t *this, else { if (child_sa->install(child_sa, encr_i, integ_i, inbound_spi, - inbound_cpi, TRUE, TRUE, local_ts, remote_ts) != SUCCESS || + inbound_cpi, initiator, TRUE, TRUE, + local_ts, remote_ts) != SUCCESS || child_sa->install(child_sa, encr_r, integ_r, outbound_spi, - outbound_cpi, FALSE, TRUE, local_ts, remote_ts) != SUCCESS) + outbound_cpi, initiator, FALSE, TRUE, + local_ts, remote_ts) != SUCCESS) { failed = TRUE; } @@ -825,6 +1013,9 @@ static job_requeue_t dispatch(private_ha_dispatcher_t *this) case HA_IKE_MID_RESPONDER: process_ike_mid(this, message, FALSE); break; + case HA_IKE_IV: + process_ike_iv(this, message); + break; case HA_IKE_DELETE: process_ike_delete(this, message); break; @@ -857,7 +1048,6 @@ static job_requeue_t dispatch(private_ha_dispatcher_t *this) METHOD(ha_dispatcher_t, destroy, void, private_ha_dispatcher_t *this) { - this->job->cancel(this->job); free(this); } @@ -881,9 +1071,9 @@ ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket, .kernel = kernel, .attr = attr, ); - this->job = callback_job_create_with_prio((callback_job_cb_t)dispatch, - this, NULL, NULL, JOB_PRIO_CRITICAL); - lib->processor->queue_job(lib->processor, (job_t*)this->job); + lib->processor->queue_job(lib->processor, + (job_t*)callback_job_create_with_prio((callback_job_cb_t)dispatch, this, + NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL)); return &this->public; } diff --git a/src/libcharon/plugins/ha/ha_ike.c b/src/libcharon/plugins/ha/ha_ike.c index e818aec9c..442a3a23d 100644 --- a/src/libcharon/plugins/ha/ha_ike.c +++ b/src/libcharon/plugins/ha/ha_ike.c @@ -15,6 +15,9 @@ #include "ha_ike.h" +#include <sa/ikev2/keymat_v2.h> +#include <sa/ikev1/keymat_v1.h> + typedef struct private_ha_ike_t private_ha_ike_t; /** @@ -69,7 +72,8 @@ static ike_extension_t copy_extension(ike_sa_t *ike_sa, ike_extension_t ext) METHOD(listener_t, ike_keys, bool, private_ha_ike_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh, - chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey) + chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey, + shared_key_t *shared) { ha_message_t *m; chunk_t secret; @@ -86,14 +90,15 @@ METHOD(listener_t, ike_keys, bool, } m = ha_message_create(HA_IKE_ADD); + m->add_attribute(m, HA_IKE_VERSION, ike_sa->get_version(ike_sa)); m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); - if (rekey) + if (rekey && rekey->get_version(rekey) == IKEV2) { chunk_t skd; - keymat_t *keymat; + keymat_v2_t *keymat; - keymat = rekey->get_keymat(rekey); + keymat = (keymat_v2_t*)rekey->get_keymat(rekey); m->add_attribute(m, HA_IKE_REKEY_ID, rekey->get_id(rekey)); m->add_attribute(m, HA_ALG_OLD_PRF, keymat->get_skd(keymat, &skd)); m->add_attribute(m, HA_OLD_SKD, skd); @@ -120,6 +125,17 @@ METHOD(listener_t, ike_keys, bool, m->add_attribute(m, HA_NONCE_R, nonce_r); m->add_attribute(m, HA_SECRET, secret); chunk_clear(&secret); + if (ike_sa->get_version(ike_sa) == IKEV1) + { + dh->get_my_public_value(dh, &secret); + m->add_attribute(m, HA_LOCAL_DH, secret); + chunk_free(&secret); + m->add_attribute(m, HA_REMOTE_DH, dh_other); + if (shared) + { + m->add_attribute(m, HA_PSK, shared->get_key(shared)); + } + } this->socket->push(this->socket, m); this->cache->cache(this->cache, ike_sa, m); @@ -159,7 +175,9 @@ METHOD(listener_t, ike_updown, bool, | copy_condition(ike_sa, COND_EAP_AUTHENTICATED) | copy_condition(ike_sa, COND_CERTREQ_SEEN) | copy_condition(ike_sa, COND_ORIGINAL_INITIATOR) - | copy_condition(ike_sa, COND_STALE); + | copy_condition(ike_sa, COND_STALE) + | copy_condition(ike_sa, COND_INIT_CONTACT_SEEN) + | copy_condition(ike_sa, COND_XAUTH_AUTHENTICATED); extension = copy_extension(ike_sa, EXT_NATT) | copy_extension(ike_sa, EXT_MOBIKE) @@ -167,7 +185,9 @@ METHOD(listener_t, ike_updown, bool, | copy_extension(ike_sa, EXT_MULTIPLE_AUTH) | copy_extension(ike_sa, EXT_STRONGSWAN) | copy_extension(ike_sa, EXT_EAP_ONLY_AUTHENTICATION) - | copy_extension(ike_sa, EXT_MS_WINDOWS); + | copy_extension(ike_sa, EXT_MS_WINDOWS) + | copy_extension(ike_sa, EXT_XAUTH) + | copy_extension(ike_sa, EXT_DPD); id = ike_sa->get_id(ike_sa); @@ -221,49 +241,125 @@ METHOD(listener_t, ike_state_change, bool, return TRUE; } +/** + * Send a virtual IP sync message for remote VIPs + */ +static void sync_vips(private_ha_ike_t *this, ike_sa_t *ike_sa) +{ + ha_message_t *m = NULL; + enumerator_t *enumerator; + host_t *vip; + + enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE); + while (enumerator->enumerate(enumerator, &vip)) + { + if (!m) + { + m = ha_message_create(HA_IKE_UPDATE); + m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); + } + m->add_attribute(m, HA_REMOTE_VIP, vip); + } + enumerator->destroy(enumerator); + + if (m) + { + this->socket->push(this->socket, m); + this->cache->cache(this->cache, ike_sa, m); + } +} + METHOD(listener_t, message_hook, bool, - private_ha_ike_t *this, ike_sa_t *ike_sa, message_t *message, bool incoming) + private_ha_ike_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming, bool plain) { if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa)) { /* do not sync SA between nodes */ return TRUE; } - if (message->get_exchange_type(message) != IKE_SA_INIT && - message->get_request(message)) - { /* we sync on requests, but skip it on IKE_SA_INIT */ + if (plain && ike_sa->get_version(ike_sa) == IKEV2) + { + if (message->get_exchange_type(message) != IKE_SA_INIT && + message->get_request(message)) + { /* we sync on requests, but skip it on IKE_SA_INIT */ + ha_message_t *m; + + if (incoming) + { + m = ha_message_create(HA_IKE_MID_RESPONDER); + } + else + { + m = ha_message_create(HA_IKE_MID_INITIATOR); + } + m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); + m->add_attribute(m, HA_MID, message->get_message_id(message) + 1); + this->socket->push(this->socket, m); + this->cache->cache(this->cache, ike_sa, m); + } + if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED && + message->get_exchange_type(message) == IKE_AUTH && + !message->get_request(message)) + { /* After IKE_SA has been established, sync peers virtual IP. + * We cannot sync it in the state_change hook, it is installed later. + * TODO: where to sync local VIP? */ + sync_vips(this, ike_sa); + } + } + if (!plain && ike_sa->get_version(ike_sa) == IKEV1) + { ha_message_t *m; + keymat_v1_t *keymat; + u_int32_t mid; + chunk_t iv; - if (incoming) + mid = message->get_message_id(message); + if (mid == 0) { - m = ha_message_create(HA_IKE_MID_RESPONDER); + keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa); + if (keymat->get_iv(keymat, mid, &iv)) + { + m = ha_message_create(HA_IKE_IV); + m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); + m->add_attribute(m, HA_IV, iv); + this->socket->push(this->socket, m); + this->cache->cache(this->cache, ike_sa, m); + } } - else + if (!incoming && message->get_exchange_type(message) == TRANSACTION) { - m = ha_message_create(HA_IKE_MID_INITIATOR); + sync_vips(this, ike_sa); } - m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); - m->add_attribute(m, HA_MID, message->get_message_id(message) + 1); - this->socket->push(this->socket, m); - this->cache->cache(this->cache, ike_sa, m); } - if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED && - message->get_exchange_type(message) == IKE_AUTH && - !message->get_request(message)) - { /* After IKE_SA has been established, sync peers virtual IP. - * We cannot sync it in the state_change hook, it is installed later. - * TODO: where to sync local VIP? */ + if (plain && ike_sa->get_version(ike_sa) == IKEV1 && + message->get_exchange_type(message) == INFORMATIONAL_V1) + { ha_message_t *m; - host_t *vip; + notify_payload_t *notify; + chunk_t data; + u_int32_t seq; - vip = ike_sa->get_virtual_ip(ike_sa, FALSE); - if (vip) + notify = message->get_notify(message, DPD_R_U_THERE); + if (notify) { - m = ha_message_create(HA_IKE_UPDATE); - m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); - m->add_attribute(m, HA_REMOTE_VIP, vip); - this->socket->push(this->socket, m); - this->cache->cache(this->cache, ike_sa, m); + data = notify->get_notification_data(notify); + if (data.len == 4) + { + seq = untoh32(data.ptr); + if (incoming) + { + m = ha_message_create(HA_IKE_MID_RESPONDER); + } + else + { + m = ha_message_create(HA_IKE_MID_INITIATOR); + } + m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); + m->add_attribute(m, HA_MID, seq + 1); + this->socket->push(this->socket, m); + this->cache->cache(this->cache, ike_sa, m); + } } } return TRUE; diff --git a/src/libcharon/plugins/ha/ha_kernel.c b/src/libcharon/plugins/ha/ha_kernel.c index 2377a2630..eed89e0bf 100644 --- a/src/libcharon/plugins/ha/ha_kernel.c +++ b/src/libcharon/plugins/ha/ha_kernel.c @@ -316,7 +316,8 @@ static void disable_all(private_ha_kernel_t *this) { while (enumerator->enumerate(enumerator, NULL, &file, NULL)) { - if (chown(file, charon->uid, charon->gid) != 0) + if (chown(file, lib->caps->get_uid(lib->caps), + lib->caps->get_gid(lib->caps)) != 0) { DBG1(DBG_CFG, "changing ClusterIP permissions failed: %s", strerror(errno)); diff --git a/src/libcharon/plugins/ha/ha_message.c b/src/libcharon/plugins/ha/ha_message.c index 810109a5d..6b00ed83f 100644 --- a/src/libcharon/plugins/ha/ha_message.c +++ b/src/libcharon/plugins/ha/ha_message.c @@ -46,7 +46,7 @@ struct private_ha_message_t { chunk_t buf; }; -ENUM(ha_message_type_names, HA_IKE_ADD, HA_RESYNC, +ENUM(ha_message_type_names, HA_IKE_ADD, HA_IKE_IV, "IKE_ADD", "IKE_UPDATE", "IKE_MID_INITIATOR", @@ -58,6 +58,7 @@ ENUM(ha_message_type_names, HA_IKE_ADD, HA_RESYNC, "SEGMENT_TAKE", "STATUS", "RESYNC", + "IKE_IV", ); typedef struct ike_sa_id_encoding_t ike_sa_id_encoding_t; @@ -66,6 +67,7 @@ typedef struct ike_sa_id_encoding_t ike_sa_id_encoding_t; * Encoding if an ike_sa_id_t */ struct ike_sa_id_encoding_t { + u_int8_t ike_version; u_int64_t initiator_spi; u_int64_t responder_spi; u_int8_t initiator; @@ -156,6 +158,7 @@ METHOD(ha_message_t, add_attribute, void, enc = (ike_sa_id_encoding_t*)(this->buf.ptr + this->buf.len); this->buf.len += sizeof(ike_sa_id_encoding_t); enc->initiator = id->is_initiator(id); + enc->ike_version = id->get_ike_version(id); enc->initiator_spi = id->get_initiator_spi(id); enc->responder_spi = id->get_responder_spi(id); break; @@ -213,6 +216,7 @@ METHOD(ha_message_t, add_attribute, void, break; } /* u_int8_t */ + case HA_IKE_VERSION: case HA_INITIATOR: case HA_IPSEC_MODE: case HA_IPCOMP: @@ -263,6 +267,10 @@ METHOD(ha_message_t, add_attribute, void, case HA_NONCE_I: case HA_NONCE_R: case HA_SECRET: + case HA_LOCAL_DH: + case HA_REMOTE_DH: + case HA_PSK: + case HA_IV: case HA_OLD_SKD: { chunk_t chunk; @@ -351,8 +359,9 @@ METHOD(enumerator_t, attribute_enumerate, bool, return FALSE; } enc = (ike_sa_id_encoding_t*)(this->buf.ptr); - value->ike_sa_id = ike_sa_id_create(enc->initiator_spi, - enc->responder_spi, enc->initiator); + value->ike_sa_id = ike_sa_id_create(enc->ike_version, + enc->initiator_spi, enc->responder_spi, + enc->initiator); *attr_out = attr; this->cleanup = (void*)value->ike_sa_id->destroy; this->cleanup_data = value->ike_sa_id; @@ -426,6 +435,7 @@ METHOD(enumerator_t, attribute_enumerate, bool, return TRUE; } /* u_int8_t */ + case HA_IKE_VERSION: case HA_INITIATOR: case HA_IPSEC_MODE: case HA_IPCOMP: @@ -479,6 +489,10 @@ METHOD(enumerator_t, attribute_enumerate, bool, case HA_NONCE_I: case HA_NONCE_R: case HA_SECRET: + case HA_LOCAL_DH: + case HA_REMOTE_DH: + case HA_PSK: + case HA_IV: case HA_OLD_SKD: { size_t len; diff --git a/src/libcharon/plugins/ha/ha_message.h b/src/libcharon/plugins/ha/ha_message.h index d0323d7a0..2ccb1fc55 100644 --- a/src/libcharon/plugins/ha/ha_message.h +++ b/src/libcharon/plugins/ha/ha_message.h @@ -22,7 +22,7 @@ #define HA_MESSAGE_H_ #include <library.h> -#include <utils/host.h> +#include <networking/host.h> #include <utils/identification.h> #include <sa/ike_sa_id.h> #include <selectors/traffic_selector.h> @@ -30,7 +30,7 @@ /** * Protocol version of this implementation */ -#define HA_MESSAGE_VERSION 2 +#define HA_MESSAGE_VERSION 3 typedef struct ha_message_t ha_message_t; typedef enum ha_message_type_t ha_message_type_t; @@ -63,6 +63,8 @@ enum ha_message_type_t { HA_STATUS, /** segments the receiving node is requested to resync */ HA_RESYNC, + /** IV synchronization for IKEv1 Main/Aggressive mode */ + HA_IKE_IV, }; /** @@ -76,7 +78,7 @@ extern enum_name_t *ha_message_type_names; enum ha_message_attribute_t { /** ike_sa_id_t*, to identify IKE_SA */ HA_IKE_ID = 1, - /** ike_Sa_id_t*, identifies IKE_SA which gets rekeyed */ + /** ike_sa_id_t*, identifies IKE_SA which gets rekeyed */ HA_IKE_REKEY_ID, /** identification_t*, local identity */ HA_LOCAL_ID, @@ -142,6 +144,16 @@ enum ha_message_attribute_t { HA_SEGMENT, /** u_int16_t, Extended Sequence numbers */ HA_ESN, + /** u_int8_t, IKE version */ + HA_IKE_VERSION, + /** chunk_t, own DH public value */ + HA_LOCAL_DH, + /** chunk_t, remote DH public value */ + HA_REMOTE_DH, + /** chunk_t, shared secret for IKEv1 key derivation */ + HA_PSK, + /** chunk_t, IV for next IKEv1 message */ + HA_IV, }; /** diff --git a/src/libcharon/plugins/ha/ha_plugin.c b/src/libcharon/plugins/ha/ha_plugin.c index b4bde5ea5..5d4cc6184 100644 --- a/src/libcharon/plugins/ha/ha_plugin.c +++ b/src/libcharon/plugins/ha/ha_plugin.c @@ -97,14 +97,46 @@ METHOD(plugin_t, get_name, char*, return "ha"; } +/** + * Register listener + */ +static bool plugin_cb(private_ha_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + charon->bus->add_listener(charon->bus, &this->segments->listener); + charon->bus->add_listener(charon->bus, &this->ike->listener); + charon->bus->add_listener(charon->bus, &this->child->listener); + hydra->attributes->add_provider(hydra->attributes, + &this->attr->provider); + } + else + { + hydra->attributes->remove_provider(hydra->attributes, + &this->attr->provider); + charon->bus->remove_listener(charon->bus, &this->segments->listener); + charon->bus->remove_listener(charon->bus, &this->ike->listener); + charon->bus->remove_listener(charon->bus, &this->child->listener); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_ha_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "ha"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_ha_plugin_t *this) { DESTROY_IF(this->ctl); - hydra->attributes->remove_provider(hydra->attributes, &this->attr->provider); - charon->bus->remove_listener(charon->bus, &this->segments->listener); - charon->bus->remove_listener(charon->bus, &this->ike->listener); - charon->bus->remove_listener(charon->bus, &this->child->listener); this->ike->destroy(this->ike); this->child->destroy(this->child); this->dispatcher->destroy(this->dispatcher); @@ -128,30 +160,37 @@ plugin_t *ha_plugin_create() bool fifo, monitor, resync; local = lib->settings->get_str(lib->settings, - "charon.plugins.ha.local", NULL); + "%s.plugins.ha.local", NULL, charon->name); remote = lib->settings->get_str(lib->settings, - "charon.plugins.ha.remote", NULL); + "%s.plugins.ha.remote", NULL, charon->name); secret = lib->settings->get_str(lib->settings, - "charon.plugins.ha.secret", NULL); + "%s.plugins.ha.secret", NULL, charon->name); fifo = lib->settings->get_bool(lib->settings, - "charon.plugins.ha.fifo_interface", TRUE); + "%s.plugins.ha.fifo_interface", TRUE, charon->name); monitor = lib->settings->get_bool(lib->settings, - "charon.plugins.ha.monitor", TRUE); + "%s.plugins.ha.monitor", TRUE, charon->name); resync = lib->settings->get_bool(lib->settings, - "charon.plugins.ha.resync", TRUE); + "%s.plugins.ha.resync", TRUE, charon->name); count = min(SEGMENTS_MAX, lib->settings->get_int(lib->settings, - "charon.plugins.ha.segment_count", 1)); + "%s.plugins.ha.segment_count", 1, charon->name)); if (!local || !remote) { DBG1(DBG_CFG, "HA config misses local/remote address"); return NULL; } + if (!lib->caps->keep(lib->caps, CAP_CHOWN)) + { /* required to chown(2) control socket, ha_kernel also needs it at + * runtime */ + DBG1(DBG_CFG, "ha plugin requires CAP_CHOWN capability"); + return NULL; + } + INIT(this, .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, @@ -182,10 +221,6 @@ plugin_t *ha_plugin_create() this->ike = ha_ike_create(this->socket, this->tunnel, this->cache); this->child = ha_child_create(this->socket, this->tunnel, this->segments, this->kernel); - charon->bus->add_listener(charon->bus, &this->segments->listener); - charon->bus->add_listener(charon->bus, &this->ike->listener); - charon->bus->add_listener(charon->bus, &this->child->listener); - hydra->attributes->add_provider(hydra->attributes, &this->attr->provider); return &this->public.plugin; } diff --git a/src/libcharon/plugins/ha/ha_segments.c b/src/libcharon/plugins/ha/ha_segments.c index c5a180683..cab38c63d 100644 --- a/src/libcharon/plugins/ha/ha_segments.c +++ b/src/libcharon/plugins/ha/ha_segments.c @@ -17,7 +17,7 @@ #include <threading/mutex.h> #include <threading/condvar.h> -#include <utils/linked_list.h> +#include <collections/linked_list.h> #include <threading/thread.h> #include <processing/jobs/callback_job.h> @@ -62,11 +62,6 @@ struct private_ha_segments_t { condvar_t *condvar; /** - * Job checking for heartbeats - */ - callback_job_t *job; - - /** * Total number of ClusterIP segments */ u_int count; @@ -82,6 +77,11 @@ struct private_ha_segments_t { u_int node; /** + * Are we checking for heartbeats? + */ + bool heartbeat_active; + + /** * Interval we send hearbeats */ int heartbeat_delay; @@ -90,6 +90,11 @@ struct private_ha_segments_t { * Timeout for heartbeats received from other node */ int heartbeat_timeout; + + /** + * Interval to check for autobalance, 0 to disable + */ + int autobalance; }; /** @@ -237,7 +242,7 @@ METHOD(listener_t, alert_hook, bool, { if (alert == ALERT_SHUTDOWN_SIGNAL) { - if (this->job) + if (this->heartbeat_active) { DBG1(DBG_CFG, "HA heartbeat active, dropping all segments"); deactivate(this, 0, TRUE); @@ -269,7 +274,7 @@ static job_requeue_t watchdog(private_ha_segments_t *this) DBG1(DBG_CFG, "no heartbeat received, taking all segments"); activate(this, 0, TRUE); /* disable heartbeat detection util we get one */ - this->job = NULL; + this->heartbeat_active = FALSE; return JOB_REQUEUE_NONE; } return JOB_REQUEUE_DIRECT; @@ -280,20 +285,22 @@ static job_requeue_t watchdog(private_ha_segments_t *this) */ static void start_watchdog(private_ha_segments_t *this) { - this->job = callback_job_create_with_prio((callback_job_cb_t)watchdog, - this, NULL, NULL, JOB_PRIO_CRITICAL); - lib->processor->queue_job(lib->processor, (job_t*)this->job); + this->heartbeat_active = TRUE; + lib->processor->queue_job(lib->processor, + (job_t*)callback_job_create_with_prio((callback_job_cb_t)watchdog, this, + NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL)); } METHOD(ha_segments_t, handle_status, void, private_ha_segments_t *this, segment_mask_t mask) { - segment_mask_t missing; + segment_mask_t missing, twice; int i; this->mutex->lock(this->mutex); missing = ~(this->active | mask); + twice = this->active & mask; for (i = 1; i <= this->count; i++) { @@ -310,12 +317,25 @@ METHOD(ha_segments_t, handle_status, void, enable_disable(this, i, FALSE, TRUE); } } + if (twice & SEGMENTS_BIT(i)) + { + if (this->node == i % 2) + { + DBG1(DBG_CFG, "HA segment %d was handled twice, taking", i); + enable_disable(this, i, TRUE, TRUE); + } + else + { + DBG1(DBG_CFG, "HA segment %d was handled twice, dropping", i); + enable_disable(this, i, FALSE, TRUE); + } + } } - this->mutex->unlock(this->mutex); this->condvar->signal(this->condvar); + this->mutex->unlock(this->mutex); - if (!this->job) + if (!this->heartbeat_active) { DBG1(DBG_CFG, "received heartbeat, reenabling watchdog"); start_watchdog(this); @@ -332,6 +352,7 @@ static job_requeue_t send_status(private_ha_segments_t *this) message = ha_message_create(HA_STATUS); + this->mutex->lock(this->mutex); for (i = 1; i <= this->count; i++) { if (this->active & SEGMENTS_BIT(i)) @@ -339,17 +360,71 @@ static job_requeue_t send_status(private_ha_segments_t *this) message->add_attribute(message, HA_SEGMENT, i); } } + this->mutex->unlock(this->mutex); this->socket->push(this->socket, message); message->destroy(message); /* schedule next invocation */ - lib->scheduler->schedule_job_ms(lib->scheduler, (job_t*) - callback_job_create((callback_job_cb_t) - send_status, this, NULL, NULL), - this->heartbeat_delay); + return JOB_RESCHEDULE_MS(this->heartbeat_delay); +} + +/** + * Start the heartbeat sending task + */ +static void start_heartbeat(private_ha_segments_t *this) +{ + lib->processor->queue_job(lib->processor, + (job_t*)callback_job_create_with_prio((callback_job_cb_t)send_status, + this, NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL)); +} + +/** + * Take a segment if we are handling less than half of segments + */ +static job_requeue_t autobalance(private_ha_segments_t *this) +{ + int i, active = 0; + + this->mutex->lock(this->mutex); - return JOB_REQUEUE_NONE; + for (i = 1; i <= this->count; i++) + { + if (this->active & SEGMENTS_BIT(i)) + { + active++; + } + } + if (active < this->count / 2) + { + for (i = 1; i <= this->count; i++) + { + if (!(this->active & SEGMENTS_BIT(i))) + { + DBG1(DBG_CFG, "autobalancing HA (%d/%d active), taking %d", + active, this->count, i); + enable_disable(this, i, TRUE, TRUE); + /* we claim only one in each interval */ + break; + } + } + } + + this->mutex->unlock(this->mutex); + + return JOB_RESCHEDULE(this->autobalance); +} + +/** + * Schedule autobalancing + */ +static void start_autobalance(private_ha_segments_t *this) +{ + DBG1(DBG_CFG, "scheduling HA autobalance every %ds", this->autobalance); + lib->scheduler->schedule_job(lib->scheduler, + (job_t*)callback_job_create_with_prio((callback_job_cb_t)autobalance, + this, NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL), + this->autobalance); } METHOD(ha_segments_t, is_active, bool, @@ -361,10 +436,6 @@ METHOD(ha_segments_t, is_active, bool, METHOD(ha_segments_t, destroy, void, private_ha_segments_t *this) { - if (this->job) - { - this->job->cancel(this->job); - } this->mutex->destroy(this->mutex); this->condvar->destroy(this->condvar); free(this); @@ -398,19 +469,26 @@ ha_segments_t *ha_segments_create(ha_socket_t *socket, ha_kernel_t *kernel, .mutex = mutex_create(MUTEX_TYPE_DEFAULT), .condvar = condvar_create(CONDVAR_TYPE_DEFAULT), .heartbeat_delay = lib->settings->get_int(lib->settings, - "charon.plugins.ha.heartbeat_delay", DEFAULT_HEARTBEAT_DELAY), + "%s.plugins.ha.heartbeat_delay", DEFAULT_HEARTBEAT_DELAY, + charon->name), .heartbeat_timeout = lib->settings->get_int(lib->settings, - "charon.plugins.ha.heartbeat_timeout", DEFAULT_HEARTBEAT_TIMEOUT), + "%s.plugins.ha.heartbeat_timeout", DEFAULT_HEARTBEAT_TIMEOUT, + charon->name), + .autobalance = lib->settings->get_int(lib->settings, + "%s.plugins.ha.autobalance", 0, charon->name), ); if (monitor) { DBG1(DBG_CFG, "starting HA heartbeat, delay %dms, timeout %dms", this->heartbeat_delay, this->heartbeat_timeout); - send_status(this); + start_heartbeat(this); start_watchdog(this); } + if (this->autobalance) + { + start_autobalance(this); + } return &this->public; } - diff --git a/src/libcharon/plugins/ha/ha_socket.c b/src/libcharon/plugins/ha/ha_socket.c index c02cf1021..e41e78bbf 100644 --- a/src/libcharon/plugins/ha/ha_socket.c +++ b/src/libcharon/plugins/ha/ha_socket.c @@ -22,7 +22,7 @@ #include <unistd.h> #include <daemon.h> -#include <utils/host.h> +#include <networking/host.h> #include <threading/thread.h> #include <processing/jobs/callback_job.h> @@ -138,6 +138,7 @@ METHOD(ha_socket_t, pull, ha_message_t*, DBG1(DBG_CFG, "pulling HA message failed: %s", strerror(errno)); sleep(1); + continue; } } message = ha_message_parse(chunk_create(buf, len)); diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c index 299053ec1..4e656e73b 100644 --- a/src/libcharon/plugins/ha/ha_tunnel.c +++ b/src/libcharon/plugins/ha/ha_tunnel.c @@ -203,12 +203,13 @@ static void setup_tunnel(private_ha_tunnel_t *this, lib->credmgr->add_set(lib->credmgr, &this->creds.public); /* create config and backend */ - ike_cfg = ike_cfg_create(FALSE, FALSE, local, IKEV2_UDP_PORT, - remote, IKEV2_UDP_PORT); + ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE, local, FALSE, + charon->socket->get_port(charon->socket, FALSE), + remote, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); - peer_cfg = peer_cfg_create("ha", 2, ike_cfg, CERT_NEVER_SEND, - UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, 30, - NULL, NULL, FALSE, NULL, NULL); + peer_cfg = peer_cfg_create("ha", ike_cfg, CERT_NEVER_SEND, + UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, FALSE, 30, + 0, FALSE, NULL, NULL); auth_cfg = auth_cfg_create(); auth_cfg->add(auth_cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK); @@ -244,7 +245,7 @@ static void setup_tunnel(private_ha_tunnel_t *this, charon->backends->add_backend(charon->backends, &this->backend.public); /* install an acquiring trap */ - this->trap = charon->traps->install(charon->traps, peer_cfg, child_cfg); + this->trap = charon->traps->install(charon->traps, peer_cfg, child_cfg, 0); } METHOD(ha_tunnel_t, destroy, void, @@ -287,4 +288,3 @@ ha_tunnel_t *ha_tunnel_create(char *local, char *remote, char *secret) return &this->public; } - |