summaryrefslogtreecommitdiff
path: root/src/libcharon/plugins/ha
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/plugins/ha')
-rw-r--r--src/libcharon/plugins/ha/Makefile.am12
-rw-r--r--src/libcharon/plugins/ha/Makefile.in159
-rw-r--r--src/libcharon/plugins/ha/ha_attribute.c46
-rw-r--r--src/libcharon/plugins/ha/ha_cache.c24
-rw-r--r--src/libcharon/plugins/ha/ha_cache.h2
-rw-r--r--src/libcharon/plugins/ha/ha_child.c16
-rw-r--r--src/libcharon/plugins/ha/ha_ctl.c15
-rw-r--r--src/libcharon/plugins/ha/ha_dispatcher.c266
-rw-r--r--src/libcharon/plugins/ha/ha_ike.c160
-rw-r--r--src/libcharon/plugins/ha/ha_kernel.c3
-rw-r--r--src/libcharon/plugins/ha/ha_message.c20
-rw-r--r--src/libcharon/plugins/ha/ha_message.h18
-rw-r--r--src/libcharon/plugins/ha/ha_plugin.c67
-rw-r--r--src/libcharon/plugins/ha/ha_segments.c132
-rw-r--r--src/libcharon/plugins/ha/ha_socket.c3
-rw-r--r--src/libcharon/plugins/ha/ha_tunnel.c14
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;
}
-