summaryrefslogtreecommitdiff
path: root/src/libcharon/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/plugins')
-rw-r--r--src/libcharon/plugins/addrblock/Makefile.am2
-rw-r--r--src/libcharon/plugins/addrblock/Makefile.in8
-rw-r--r--src/libcharon/plugins/android_dns/Makefile.am2
-rw-r--r--src/libcharon/plugins/android_dns/Makefile.in8
-rw-r--r--src/libcharon/plugins/android_log/Makefile.am2
-rw-r--r--src/libcharon/plugins/android_log/Makefile.in8
-rw-r--r--src/libcharon/plugins/certexpire/Makefile.am2
-rw-r--r--src/libcharon/plugins/certexpire/Makefile.in8
-rw-r--r--src/libcharon/plugins/coupling/Makefile.am2
-rw-r--r--src/libcharon/plugins/coupling/Makefile.in8
-rw-r--r--src/libcharon/plugins/coupling/coupling_validator.c10
-rw-r--r--src/libcharon/plugins/dhcp/Makefile.am2
-rw-r--r--src/libcharon/plugins/dhcp/Makefile.in8
-rw-r--r--src/libcharon/plugins/dnscert/Makefile.am2
-rw-r--r--src/libcharon/plugins/dnscert/Makefile.in8
-rw-r--r--src/libcharon/plugins/duplicheck/Makefile.am2
-rw-r--r--src/libcharon/plugins/duplicheck/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_aka/Makefile.am2
-rw-r--r--src/libcharon/plugins/eap_aka/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/Makefile.am2
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_dynamic/Makefile.am2
-rw-r--r--src/libcharon/plugins/eap_dynamic/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_gtc/Makefile.am2
-rw-r--r--src/libcharon/plugins/eap_gtc/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_gtc/eap_gtc.c6
-rw-r--r--src/libcharon/plugins/eap_identity/Makefile.am2
-rw-r--r--src/libcharon/plugins/eap_identity/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_md5/Makefile.am2
-rw-r--r--src/libcharon/plugins/eap_md5/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_mschapv2/Makefile.am2
-rw-r--r--src/libcharon/plugins/eap_mschapv2/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_peap/Makefile.am2
-rw-r--r--src/libcharon/plugins/eap_peap/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_peap/eap_peap_avp.c15
-rw-r--r--src/libcharon/plugins/eap_radius/Makefile.am2
-rw-r--r--src/libcharon/plugins/eap_radius/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_accounting.c2
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_forward.c7
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_xauth.c10
-rw-r--r--src/libcharon/plugins/eap_sim/Makefile.am2
-rw-r--r--src/libcharon/plugins/eap_sim/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_sim_file/Makefile.am2
-rw-r--r--src/libcharon/plugins/eap_sim_file/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_sim_pcsc/Makefile.am2
-rw-r--r--src/libcharon/plugins/eap_sim_pcsc/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am2
-rw-r--r--src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_simaka_reauth/Makefile.am2
-rw-r--r--src/libcharon/plugins/eap_simaka_reauth/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_simaka_sql/Makefile.am2
-rw-r--r--src/libcharon/plugins/eap_simaka_sql/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_tls/Makefile.am2
-rw-r--r--src/libcharon/plugins/eap_tls/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_tnc/Makefile.am2
-rw-r--r--src/libcharon/plugins/eap_tnc/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_tnc/eap_tnc.c54
-rw-r--r--src/libcharon/plugins/eap_tnc/eap_tnc.h28
-rw-r--r--src/libcharon/plugins/eap_tnc/eap_tnc_plugin.c8
-rw-r--r--src/libcharon/plugins/eap_ttls/Makefile.am2
-rw-r--r--src/libcharon/plugins/eap_ttls/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_ttls/eap_ttls_server.c30
-rw-r--r--src/libcharon/plugins/error_notify/Makefile.am2
-rw-r--r--src/libcharon/plugins/error_notify/Makefile.in8
-rw-r--r--src/libcharon/plugins/farp/Makefile.am2
-rw-r--r--src/libcharon/plugins/farp/Makefile.in8
-rw-r--r--src/libcharon/plugins/ha/Makefile.am2
-rw-r--r--src/libcharon/plugins/ha/Makefile.in8
-rw-r--r--src/libcharon/plugins/ha/ha_dispatcher.c10
-rw-r--r--src/libcharon/plugins/ha/ha_tunnel.c2
-rw-r--r--src/libcharon/plugins/ipseckey/Makefile.am2
-rw-r--r--src/libcharon/plugins/ipseckey/Makefile.in8
-rw-r--r--src/libcharon/plugins/kernel_iph/Makefile.am20
-rw-r--r--src/libcharon/plugins/kernel_iph/Makefile.in768
-rw-r--r--src/libcharon/plugins/kernel_iph/kernel_iph_net.c775
-rw-r--r--src/libcharon/plugins/kernel_iph/kernel_iph_net.h46
-rw-r--r--src/libcharon/plugins/kernel_iph/kernel_iph_plugin.c76
-rw-r--r--src/libcharon/plugins/kernel_iph/kernel_iph_plugin.h42
-rw-r--r--src/libcharon/plugins/kernel_libipsec/Makefile.am2
-rw-r--r--src/libcharon/plugins/kernel_libipsec/Makefile.in8
-rw-r--r--src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c9
-rw-r--r--src/libcharon/plugins/kernel_wfp/Makefile.am33
-rw-r--r--src/libcharon/plugins/kernel_wfp/Makefile.in801
-rw-r--r--src/libcharon/plugins/kernel_wfp/ipsecdump.c666
-rw-r--r--src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.c157
-rw-r--r--src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.h205
-rw-r--r--src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c2551
-rw-r--r--src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.h47
-rw-r--r--src/libcharon/plugins/kernel_wfp/kernel_wfp_plugin.c77
-rw-r--r--src/libcharon/plugins/kernel_wfp/kernel_wfp_plugin.h43
-rw-r--r--src/libcharon/plugins/kernel_wfp/mingw-w64-4.8.1.diff26
-rw-r--r--src/libcharon/plugins/led/Makefile.am2
-rw-r--r--src/libcharon/plugins/led/Makefile.in8
-rw-r--r--src/libcharon/plugins/load_tester/Makefile.am2
-rw-r--r--src/libcharon/plugins/load_tester/Makefile.in8
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_config.c4
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_creds.c26
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_ipsec.c9
-rw-r--r--src/libcharon/plugins/lookip/Makefile.am2
-rw-r--r--src/libcharon/plugins/lookip/Makefile.in8
-rw-r--r--src/libcharon/plugins/maemo/Makefile.am2
-rw-r--r--src/libcharon/plugins/maemo/Makefile.in8
-rw-r--r--src/libcharon/plugins/maemo/maemo_service.c2
-rw-r--r--src/libcharon/plugins/medcli/Makefile.am2
-rw-r--r--src/libcharon/plugins/medcli/Makefile.in8
-rw-r--r--src/libcharon/plugins/medcli/medcli_config.c4
-rw-r--r--src/libcharon/plugins/medsrv/Makefile.am2
-rw-r--r--src/libcharon/plugins/medsrv/Makefile.in8
-rw-r--r--src/libcharon/plugins/medsrv/medsrv_config.c1
-rw-r--r--src/libcharon/plugins/osx_attr/Makefile.am2
-rw-r--r--src/libcharon/plugins/osx_attr/Makefile.in8
-rw-r--r--src/libcharon/plugins/radattr/Makefile.am2
-rw-r--r--src/libcharon/plugins/radattr/Makefile.in8
-rw-r--r--src/libcharon/plugins/radattr/radattr_listener.c4
-rw-r--r--src/libcharon/plugins/smp/Makefile.am2
-rw-r--r--src/libcharon/plugins/smp/Makefile.in8
-rw-r--r--src/libcharon/plugins/socket_default/Makefile.am2
-rw-r--r--src/libcharon/plugins/socket_default/Makefile.in8
-rw-r--r--src/libcharon/plugins/socket_dynamic/Makefile.am2
-rw-r--r--src/libcharon/plugins/socket_dynamic/Makefile.in8
-rw-r--r--src/libcharon/plugins/socket_win/Makefile.am21
-rw-r--r--src/libcharon/plugins/socket_win/Makefile.in769
-rw-r--r--src/libcharon/plugins/socket_win/socket_win_plugin.c76
-rw-r--r--src/libcharon/plugins/socket_win/socket_win_plugin.h42
-rw-r--r--src/libcharon/plugins/socket_win/socket_win_socket.c501
-rw-r--r--src/libcharon/plugins/socket_win/socket_win_socket.h44
-rw-r--r--src/libcharon/plugins/sql/Makefile.am2
-rw-r--r--src/libcharon/plugins/sql/Makefile.in8
-rw-r--r--src/libcharon/plugins/sql/sql_config.c2
-rw-r--r--src/libcharon/plugins/stroke/Makefile.am2
-rw-r--r--src/libcharon/plugins/stroke/Makefile.in8
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.c6
-rw-r--r--src/libcharon/plugins/stroke/stroke_socket.c90
-rw-r--r--src/libcharon/plugins/systime_fix/Makefile.in6
-rw-r--r--src/libcharon/plugins/tnc_ifmap/Makefile.am2
-rw-r--r--src/libcharon/plugins/tnc_ifmap/Makefile.in8
-rw-r--r--src/libcharon/plugins/tnc_pdp/Makefile.am2
-rw-r--r--src/libcharon/plugins/tnc_pdp/Makefile.in8
-rw-r--r--src/libcharon/plugins/tnc_pdp/tnc_pdp.c91
-rw-r--r--src/libcharon/plugins/uci/Makefile.am2
-rw-r--r--src/libcharon/plugins/uci/Makefile.in8
-rw-r--r--src/libcharon/plugins/unit_tester/Makefile.am2
-rw-r--r--src/libcharon/plugins/unit_tester/Makefile.in8
-rw-r--r--src/libcharon/plugins/unity/Makefile.am2
-rw-r--r--src/libcharon/plugins/unity/Makefile.in8
-rw-r--r--src/libcharon/plugins/updown/Makefile.am2
-rw-r--r--src/libcharon/plugins/updown/Makefile.in8
-rw-r--r--src/libcharon/plugins/updown/updown_listener.c4
-rw-r--r--src/libcharon/plugins/vici/Makefile.am69
-rw-r--r--src/libcharon/plugins/vici/Makefile.in1183
-rw-r--r--src/libcharon/plugins/vici/README.md176
-rw-r--r--src/libcharon/plugins/vici/libvici.c764
-rw-r--r--src/libcharon/plugins/vici/libvici.h459
-rw-r--r--src/libcharon/plugins/vici/suites/test_event.c224
-rw-r--r--src/libcharon/plugins/vici/suites/test_message.c407
-rw-r--r--src/libcharon/plugins/vici/suites/test_request.c247
-rw-r--r--src/libcharon/plugins/vici/suites/test_socket.c133
-rw-r--r--src/libcharon/plugins/vici/vici_attribute.c713
-rw-r--r--src/libcharon/plugins/vici/vici_attribute.h54
-rw-r--r--src/libcharon/plugins/vici/vici_builder.c253
-rw-r--r--src/libcharon/plugins/vici/vici_builder.h129
-rw-r--r--src/libcharon/plugins/vici/vici_config.c2006
-rw-r--r--src/libcharon/plugins/vici/vici_config.h53
-rw-r--r--src/libcharon/plugins/vici/vici_control.c496
-rw-r--r--src/libcharon/plugins/vici/vici_control.h47
-rw-r--r--src/libcharon/plugins/vici/vici_cred.c330
-rw-r--r--src/libcharon/plugins/vici/vici_cred.h47
-rw-r--r--src/libcharon/plugins/vici/vici_dispatcher.c524
-rw-r--r--src/libcharon/plugins/vici/vici_dispatcher.h122
-rw-r--r--src/libcharon/plugins/vici/vici_logger.c130
-rw-r--r--src/libcharon/plugins/vici/vici_logger.h54
-rw-r--r--src/libcharon/plugins/vici/vici_message.c727
-rw-r--r--src/libcharon/plugins/vici/vici_message.h248
-rw-r--r--src/libcharon/plugins/vici/vici_plugin.c169
-rw-r--r--src/libcharon/plugins/vici/vici_plugin.h42
-rw-r--r--src/libcharon/plugins/vici/vici_query.c1039
-rw-r--r--src/libcharon/plugins/vici/vici_query.h47
-rw-r--r--src/libcharon/plugins/vici/vici_socket.c679
-rw-r--r--src/libcharon/plugins/vici/vici_socket.h95
-rw-r--r--src/libcharon/plugins/vici/vici_tests.c46
-rw-r--r--src/libcharon/plugins/vici/vici_tests.h19
-rw-r--r--src/libcharon/plugins/whitelist/Makefile.am2
-rw-r--r--src/libcharon/plugins/whitelist/Makefile.in8
-rw-r--r--src/libcharon/plugins/xauth_eap/Makefile.am2
-rw-r--r--src/libcharon/plugins/xauth_eap/Makefile.in8
-rw-r--r--src/libcharon/plugins/xauth_eap/xauth_eap.c6
-rw-r--r--src/libcharon/plugins/xauth_generic/Makefile.am2
-rw-r--r--src/libcharon/plugins/xauth_generic/Makefile.in8
-rw-r--r--src/libcharon/plugins/xauth_generic/xauth_generic.c12
-rw-r--r--src/libcharon/plugins/xauth_noauth/Makefile.am2
-rw-r--r--src/libcharon/plugins/xauth_noauth/Makefile.in8
-rw-r--r--src/libcharon/plugins/xauth_pam/Makefile.am2
-rw-r--r--src/libcharon/plugins/xauth_pam/Makefile.in8
-rw-r--r--src/libcharon/plugins/xauth_pam/xauth_pam.c13
-rw-r--r--src/libcharon/plugins/xauth_pam/xauth_pam_listener.h2
195 files changed, 20234 insertions, 306 deletions
diff --git a/src/libcharon/plugins/addrblock/Makefile.am b/src/libcharon/plugins/addrblock/Makefile.am
index 407f22d71..33ee60d86 100644
--- a/src/libcharon/plugins/addrblock/Makefile.am
+++ b/src/libcharon/plugins/addrblock/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-addrblock.la
diff --git a/src/libcharon/plugins/addrblock/Makefile.in b/src/libcharon/plugins/addrblock/Makefile.in
index 0aa635a43..0655959ca 100644
--- a/src/libcharon/plugins/addrblock/Makefile.in
+++ b/src/libcharon/plugins/addrblock/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-addrblock.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-addrblock.la
diff --git a/src/libcharon/plugins/android_dns/Makefile.am b/src/libcharon/plugins/android_dns/Makefile.am
index ebad963bb..1a0d6e6f2 100644
--- a/src/libcharon/plugins/android_dns/Makefile.am
+++ b/src/libcharon/plugins/android_dns/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-android-dns.la
diff --git a/src/libcharon/plugins/android_dns/Makefile.in b/src/libcharon/plugins/android_dns/Makefile.in
index f44734cc6..287c94acc 100644
--- a/src/libcharon/plugins/android_dns/Makefile.in
+++ b/src/libcharon/plugins/android_dns/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-android-dns.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-android-dns.la
diff --git a/src/libcharon/plugins/android_log/Makefile.am b/src/libcharon/plugins/android_log/Makefile.am
index 4d8b4850b..79c61b51e 100644
--- a/src/libcharon/plugins/android_log/Makefile.am
+++ b/src/libcharon/plugins/android_log/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-android-log.la
diff --git a/src/libcharon/plugins/android_log/Makefile.in b/src/libcharon/plugins/android_log/Makefile.in
index 361b36187..9fd515073 100644
--- a/src/libcharon/plugins/android_log/Makefile.in
+++ b/src/libcharon/plugins/android_log/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-android-log.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-android-log.la
diff --git a/src/libcharon/plugins/certexpire/Makefile.am b/src/libcharon/plugins/certexpire/Makefile.am
index 2bfad9497..b8c241dfb 100644
--- a/src/libcharon/plugins/certexpire/Makefile.am
+++ b/src/libcharon/plugins/certexpire/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
-DIPSEC_PIDDIR=\"${piddir}\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-certexpire.la
diff --git a/src/libcharon/plugins/certexpire/Makefile.in b/src/libcharon/plugins/certexpire/Makefile.in
index e218c8a4f..edda93e77 100644
--- a/src/libcharon/plugins/certexpire/Makefile.in
+++ b/src/libcharon/plugins/certexpire/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -419,7 +423,7 @@ AM_CPPFLAGS = \
-DIPSEC_PIDDIR=\"${piddir}\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-certexpire.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-certexpire.la
diff --git a/src/libcharon/plugins/coupling/Makefile.am b/src/libcharon/plugins/coupling/Makefile.am
index cbc06a6b7..badc7b7b2 100644
--- a/src/libcharon/plugins/coupling/Makefile.am
+++ b/src/libcharon/plugins/coupling/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-coupling.la
diff --git a/src/libcharon/plugins/coupling/Makefile.in b/src/libcharon/plugins/coupling/Makefile.in
index bb951264f..5670f4323 100644
--- a/src/libcharon/plugins/coupling/Makefile.in
+++ b/src/libcharon/plugins/coupling/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-coupling.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-coupling.la
diff --git a/src/libcharon/plugins/coupling/coupling_validator.c b/src/libcharon/plugins/coupling/coupling_validator.c
index fc35462e3..0686e0f31 100644
--- a/src/libcharon/plugins/coupling/coupling_validator.c
+++ b/src/libcharon/plugins/coupling/coupling_validator.c
@@ -202,6 +202,7 @@ METHOD(coupling_validator_t, destroy, void,
coupling_validator_t *coupling_validator_create()
{
private_coupling_validator_t *this;
+ hash_algorithm_t alg;
char *path, *hash;
INIT(this,
@@ -219,8 +220,13 @@ coupling_validator_t *coupling_validator_create()
hash = lib->settings->get_str(lib->settings,
"%s.plugins.coupling.hash", "sha1", lib->ns);
- this->hasher = lib->crypto->create_hasher(lib->crypto,
- enum_from_name(hash_algorithm_short_names, hash));
+ if (!enum_from_name(hash_algorithm_short_names, hash, &alg))
+ {
+ DBG1(DBG_CFG, "unknown coupling hash algorithm: %s", hash);
+ destroy(this);
+ return NULL;
+ }
+ this->hasher = lib->crypto->create_hasher(lib->crypto, alg);
if (!this->hasher)
{
DBG1(DBG_CFG, "unsupported coupling hash algorithm: %s", hash);
diff --git a/src/libcharon/plugins/dhcp/Makefile.am b/src/libcharon/plugins/dhcp/Makefile.am
index e0e857eed..3c09db016 100644
--- a/src/libcharon/plugins/dhcp/Makefile.am
+++ b/src/libcharon/plugins/dhcp/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-dhcp.la
diff --git a/src/libcharon/plugins/dhcp/Makefile.in b/src/libcharon/plugins/dhcp/Makefile.in
index 81f2b7868..da364b06e 100644
--- a/src/libcharon/plugins/dhcp/Makefile.in
+++ b/src/libcharon/plugins/dhcp/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -264,6 +264,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -282,6 +283,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -309,6 +311,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -400,6 +403,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -416,7 +420,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-dhcp.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-dhcp.la
diff --git a/src/libcharon/plugins/dnscert/Makefile.am b/src/libcharon/plugins/dnscert/Makefile.am
index 51d542b30..145562522 100644
--- a/src/libcharon/plugins/dnscert/Makefile.am
+++ b/src/libcharon/plugins/dnscert/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-dnscert.la
diff --git a/src/libcharon/plugins/dnscert/Makefile.in b/src/libcharon/plugins/dnscert/Makefile.in
index d9eeddf70..d408cd24e 100644
--- a/src/libcharon/plugins/dnscert/Makefile.in
+++ b/src/libcharon/plugins/dnscert/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-dnscert.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-dnscert.la
diff --git a/src/libcharon/plugins/duplicheck/Makefile.am b/src/libcharon/plugins/duplicheck/Makefile.am
index 4ea2becf3..338a114fe 100644
--- a/src/libcharon/plugins/duplicheck/Makefile.am
+++ b/src/libcharon/plugins/duplicheck/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
-DIPSEC_PIDDIR=\"${piddir}\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-duplicheck.la
diff --git a/src/libcharon/plugins/duplicheck/Makefile.in b/src/libcharon/plugins/duplicheck/Makefile.in
index 0b12cf320..97432f1b1 100644
--- a/src/libcharon/plugins/duplicheck/Makefile.in
+++ b/src/libcharon/plugins/duplicheck/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -273,6 +273,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -291,6 +292,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -318,6 +320,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -409,6 +412,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -426,7 +430,7 @@ AM_CPPFLAGS = \
-DIPSEC_PIDDIR=\"${piddir}\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-duplicheck.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-duplicheck.la
diff --git a/src/libcharon/plugins/eap_aka/Makefile.am b/src/libcharon/plugins/eap_aka/Makefile.am
index ba6e66039..75e8eafb2 100644
--- a/src/libcharon/plugins/eap_aka/Makefile.am
+++ b/src/libcharon/plugins/eap_aka/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libsimaka
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-eap-aka.la
diff --git a/src/libcharon/plugins/eap_aka/Makefile.in b/src/libcharon/plugins/eap_aka/Makefile.in
index 9e771ae46..5b20fe5a6 100644
--- a/src/libcharon/plugins/eap_aka/Makefile.in
+++ b/src/libcharon/plugins/eap_aka/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -267,6 +267,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -285,6 +286,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -312,6 +314,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -403,6 +406,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -420,7 +424,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libsimaka
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-aka.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-aka.la
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am
index 4e2b207d2..ec145a39e 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am
+++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libsimaka
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
libstrongswan_eap_aka_3gpp2_la_LDFLAGS = -module -avoid-version
libstrongswan_eap_aka_3gpp2_la_LIBADD = -lgmp
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
index 91c4bb10b..d0ee19899 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
+++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -268,6 +268,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -286,6 +287,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -313,6 +315,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -404,6 +407,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -421,7 +425,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libsimaka
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
libstrongswan_eap_aka_3gpp2_la_LDFLAGS = -module -avoid-version
libstrongswan_eap_aka_3gpp2_la_LIBADD = -lgmp $(am__append_1)
diff --git a/src/libcharon/plugins/eap_dynamic/Makefile.am b/src/libcharon/plugins/eap_dynamic/Makefile.am
index 13b4d10b1..58b827a78 100644
--- a/src/libcharon/plugins/eap_dynamic/Makefile.am
+++ b/src/libcharon/plugins/eap_dynamic/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-eap-dynamic.la
diff --git a/src/libcharon/plugins/eap_dynamic/Makefile.in b/src/libcharon/plugins/eap_dynamic/Makefile.in
index 16d0b4203..78b66ac96 100644
--- a/src/libcharon/plugins/eap_dynamic/Makefile.in
+++ b/src/libcharon/plugins/eap_dynamic/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-dynamic.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-dynamic.la
diff --git a/src/libcharon/plugins/eap_gtc/Makefile.am b/src/libcharon/plugins/eap_gtc/Makefile.am
index 811366a94..c3a12ba3e 100644
--- a/src/libcharon/plugins/eap_gtc/Makefile.am
+++ b/src/libcharon/plugins/eap_gtc/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-eap-gtc.la
diff --git a/src/libcharon/plugins/eap_gtc/Makefile.in b/src/libcharon/plugins/eap_gtc/Makefile.in
index 1c8d51b94..7f18792c4 100644
--- a/src/libcharon/plugins/eap_gtc/Makefile.in
+++ b/src/libcharon/plugins/eap_gtc/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -265,6 +265,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -283,6 +284,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -310,6 +312,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -401,6 +404,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -417,7 +421,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-gtc.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-gtc.la
diff --git a/src/libcharon/plugins/eap_gtc/eap_gtc.c b/src/libcharon/plugins/eap_gtc/eap_gtc.c
index e751b51b6..5fcd9ebc9 100644
--- a/src/libcharon/plugins/eap_gtc/eap_gtc.c
+++ b/src/libcharon/plugins/eap_gtc/eap_gtc.c
@@ -161,11 +161,11 @@ METHOD(eap_method_t, process_server, status_t,
{
/* assume that "out" contains username/password attributes */
co->destroy(co);
- ci = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
+ ci = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REPLY);
ci->add_attribute(ci, configuration_attribute_create_chunk(
- CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, user));
+ PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME, user));
ci->add_attribute(ci, configuration_attribute_create_chunk(
- CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, pass));
+ PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_PASSWORD, pass));
switch (xauth->process(xauth, ci, &co))
{
case SUCCESS:
diff --git a/src/libcharon/plugins/eap_identity/Makefile.am b/src/libcharon/plugins/eap_identity/Makefile.am
index 1c155866d..6c5b43f00 100644
--- a/src/libcharon/plugins/eap_identity/Makefile.am
+++ b/src/libcharon/plugins/eap_identity/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-eap-identity.la
diff --git a/src/libcharon/plugins/eap_identity/Makefile.in b/src/libcharon/plugins/eap_identity/Makefile.in
index 4c536b2a0..5275a348c 100644
--- a/src/libcharon/plugins/eap_identity/Makefile.in
+++ b/src/libcharon/plugins/eap_identity/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-identity.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-identity.la
diff --git a/src/libcharon/plugins/eap_md5/Makefile.am b/src/libcharon/plugins/eap_md5/Makefile.am
index 583598342..16aa1919b 100644
--- a/src/libcharon/plugins/eap_md5/Makefile.am
+++ b/src/libcharon/plugins/eap_md5/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-eap-md5.la
diff --git a/src/libcharon/plugins/eap_md5/Makefile.in b/src/libcharon/plugins/eap_md5/Makefile.in
index d9938dd00..5dd623d6e 100644
--- a/src/libcharon/plugins/eap_md5/Makefile.in
+++ b/src/libcharon/plugins/eap_md5/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -265,6 +265,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -283,6 +284,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -310,6 +312,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -401,6 +404,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -417,7 +421,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-md5.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-md5.la
diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.am b/src/libcharon/plugins/eap_mschapv2/Makefile.am
index 030682d3e..4276a082d 100644
--- a/src/libcharon/plugins/eap_mschapv2/Makefile.am
+++ b/src/libcharon/plugins/eap_mschapv2/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-eap-mschapv2.la
diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.in b/src/libcharon/plugins/eap_mschapv2/Makefile.in
index 7caac9c76..c0e42198c 100644
--- a/src/libcharon/plugins/eap_mschapv2/Makefile.in
+++ b/src/libcharon/plugins/eap_mschapv2/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-mschapv2.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-mschapv2.la
diff --git a/src/libcharon/plugins/eap_peap/Makefile.am b/src/libcharon/plugins/eap_peap/Makefile.am
index 19410a408..8960b84bd 100644
--- a/src/libcharon/plugins/eap_peap/Makefile.am
+++ b/src/libcharon/plugins/eap_peap/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libtls
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-eap-peap.la
diff --git a/src/libcharon/plugins/eap_peap/Makefile.in b/src/libcharon/plugins/eap_peap/Makefile.in
index 29d8c8bb0..615a916c1 100644
--- a/src/libcharon/plugins/eap_peap/Makefile.in
+++ b/src/libcharon/plugins/eap_peap/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -267,6 +267,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -285,6 +286,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -312,6 +314,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -403,6 +406,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -420,7 +424,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libtls
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-peap.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-peap.la
diff --git a/src/libcharon/plugins/eap_peap/eap_peap_avp.c b/src/libcharon/plugins/eap_peap/eap_peap_avp.c
index f7f634a53..3f541ba23 100644
--- a/src/libcharon/plugins/eap_peap/eap_peap_avp.c
+++ b/src/libcharon/plugins/eap_peap/eap_peap_avp.c
@@ -25,8 +25,6 @@ static const chunk_t MS_AVP_Success = chunk_from_chars(
0x80, 0x03, 0x00, 0x02, 0x00, 0x01);
static const chunk_t MS_AVP_Failure = chunk_from_chars(
0x80, 0x03, 0x00, 0x02, 0x00, 0x02);
-static const chunk_t MS_SoH_Request = chunk_from_chars(
- 0x00, 0x01, 0x37, 0x00, 0x00, 0x00, 0x21, 0x00, 0x02, 0x00, 0x00);
typedef struct private_eap_peap_avp_t private_eap_peap_avp_t;
@@ -64,19 +62,6 @@ METHOD(eap_peap_avp_t, build, void,
writer->write_uint8(writer, EAP_MSTLV);
avp_data = (pkt->code == EAP_SUCCESS) ? MS_AVP_Success : MS_AVP_Failure;
}
- /**
- * Still trying to form a correct MS SoH Request
- *
- else if (pkt->type == EAP_MSCHAPV2)
- {
- code = (this->is_server) ? EAP_REQUEST : EAP_RESPONSE;
- writer->write_uint8(writer, code);
- writer->write_uint8(writer, pkt->identifier);
- writer->write_uint16(writer, 16);
- writer->write_uint8(writer, EAP_EXPANDED);
- avp_data = MS_SoH_Request;
- }
- */
else
{
avp_data = chunk_skip(data, 4);
diff --git a/src/libcharon/plugins/eap_radius/Makefile.am b/src/libcharon/plugins/eap_radius/Makefile.am
index 6fdb0d099..bc7a7765d 100644
--- a/src/libcharon/plugins/eap_radius/Makefile.am
+++ b/src/libcharon/plugins/eap_radius/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libradius
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-eap-radius.la
diff --git a/src/libcharon/plugins/eap_radius/Makefile.in b/src/libcharon/plugins/eap_radius/Makefile.in
index fbce3127f..cd4355dfa 100644
--- a/src/libcharon/plugins/eap_radius/Makefile.in
+++ b/src/libcharon/plugins/eap_radius/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -268,6 +268,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -286,6 +287,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -313,6 +315,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -404,6 +407,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -421,7 +425,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libradius
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-radius.la
@MONOLITHIC_FALSE@libstrongswan_eap_radius_la_LIBADD = $(top_builddir)/src/libradius/libradius.la
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
index 5fb1bbb75..0020c5d57 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
@@ -210,7 +210,7 @@ static void add_ike_sa_parameters(private_eap_radius_accounting_t *this,
{
enumerator_t *enumerator;
host_t *vip, *host;
- char buf[128];
+ char buf[MAX_RADIUS_ATTRIBUTE_SIZE + 1];
chunk_t data;
u_int32_t value;
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_forward.c b/src/libcharon/plugins/eap_radius/eap_radius_forward.c
index 54d52a98c..52ea84070 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_forward.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_forward.c
@@ -232,8 +232,8 @@ static void ike2queue(message_t *message, linked_list_t *queue,
enumerator = message->create_payload_enumerator(message);
while (enumerator->enumerate(enumerator, &payload))
{
- if (payload->get_type(payload) == NOTIFY ||
- payload->get_type(payload) == NOTIFY_V1)
+ if (payload->get_type(payload) == PLV2_NOTIFY ||
+ payload->get_type(payload) == PLV1_NOTIFY)
{
notify = (notify_payload_t*)payload;
if (notify->get_notify_type(notify) == RADIUS_ATTRIBUTE)
@@ -362,8 +362,7 @@ static linked_list_t* parse_selector(char *selector)
vendor = atoi(token);
token = pos;
}
- type = enum_from_name(radius_attribute_type_names, token);
- if (type == -1)
+ if (!enum_from_name(radius_attribute_type_names, token, &type))
{
type = atoi(token);
}
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_xauth.c b/src/libcharon/plugins/eap_radius/eap_radius_xauth.c
index d00f6bb2c..0fea50919 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_xauth.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_xauth.c
@@ -87,12 +87,12 @@ static bool build_round(private_eap_radius_xauth_t *this, cp_payload_t *cp)
return FALSE;
}
cp->add_attribute(cp, configuration_attribute_create_chunk(
- CONFIGURATION_ATTRIBUTE_V1, this->round.type, chunk_empty));
+ PLV1_CONFIGURATION_ATTRIBUTE, this->round.type, chunk_empty));
if (this->round.message && strlen(this->round.message))
{
cp->add_attribute(cp, configuration_attribute_create_chunk(
- CONFIGURATION_ATTRIBUTE_V1, XAUTH_MESSAGE,
+ PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_MESSAGE,
chunk_from_str(this->round.message)));
}
return TRUE;
@@ -103,10 +103,10 @@ METHOD(xauth_method_t, initiate, status_t,
{
cp_payload_t *cp;
- cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
+ cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REQUEST);
/* first message always comes with username */
cp->add_attribute(cp, configuration_attribute_create_chunk(
- CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, chunk_empty));
+ PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME, chunk_empty));
if (build_round(this, cp))
{
@@ -211,7 +211,7 @@ METHOD(xauth_method_t, process, status_t,
{
return verify_radius(this);
}
- cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
+ cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REQUEST);
if (build_round(this, cp))
{
*out = cp;
diff --git a/src/libcharon/plugins/eap_sim/Makefile.am b/src/libcharon/plugins/eap_sim/Makefile.am
index 2e9dad1b8..f68138579 100644
--- a/src/libcharon/plugins/eap_sim/Makefile.am
+++ b/src/libcharon/plugins/eap_sim/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libsimaka
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-eap-sim.la
diff --git a/src/libcharon/plugins/eap_sim/Makefile.in b/src/libcharon/plugins/eap_sim/Makefile.in
index 10b881f59..494efd99a 100644
--- a/src/libcharon/plugins/eap_sim/Makefile.in
+++ b/src/libcharon/plugins/eap_sim/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -267,6 +267,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -285,6 +286,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -312,6 +314,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -403,6 +406,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -420,7 +424,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libsimaka
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-sim.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-sim.la
diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.am b/src/libcharon/plugins/eap_sim_file/Makefile.am
index 0d4da07d5..c38e55e2c 100644
--- a/src/libcharon/plugins/eap_sim_file/Makefile.am
+++ b/src/libcharon/plugins/eap_sim_file/Makefile.am
@@ -6,7 +6,7 @@ AM_CPPFLAGS = \
-DIPSEC_CONFDIR=\"${sysconfdir}\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-eap-sim-file.la
diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.in b/src/libcharon/plugins/eap_sim_file/Makefile.in
index e4552d196..82e7561f8 100644
--- a/src/libcharon/plugins/eap_sim_file/Makefile.in
+++ b/src/libcharon/plugins/eap_sim_file/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -268,6 +268,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -286,6 +287,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -313,6 +315,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -404,6 +407,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -422,7 +426,7 @@ AM_CPPFLAGS = \
-DIPSEC_CONFDIR=\"${sysconfdir}\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-sim-file.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-sim-file.la
diff --git a/src/libcharon/plugins/eap_sim_pcsc/Makefile.am b/src/libcharon/plugins/eap_sim_pcsc/Makefile.am
index e5e9d01ca..22922049d 100644
--- a/src/libcharon/plugins/eap_sim_pcsc/Makefile.am
+++ b/src/libcharon/plugins/eap_sim_pcsc/Makefile.am
@@ -6,7 +6,7 @@ AM_CPPFLAGS = \
AM_CFLAGS = \
${pcsclite_CFLAGS} \
- -rdynamic
+ $(PLUGIN_CFLAGS)
libstrongswan_eap_sim_pcsc_la_LDFLAGS = -module -avoid-version
libstrongswan_eap_sim_pcsc_la_LIBADD = ${pcsclite_LIBS}
diff --git a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
index 628f5372a..9a7a1909e 100644
--- a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
+++ b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -269,6 +269,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -287,6 +288,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -314,6 +316,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -405,6 +408,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -423,7 +427,7 @@ AM_CPPFLAGS = \
AM_CFLAGS = \
${pcsclite_CFLAGS} \
- -rdynamic
+ $(PLUGIN_CFLAGS)
libstrongswan_eap_sim_pcsc_la_LDFLAGS = -module -avoid-version
libstrongswan_eap_sim_pcsc_la_LIBADD = ${pcsclite_LIBS} \
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am
index 0f21c6849..f40efbd6f 100644
--- a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libsimaka
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-eap-simaka-pseudonym.la
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
index 4a8127fc1..886b0c575 100644
--- a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -269,6 +269,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -287,6 +288,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -314,6 +316,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -405,6 +408,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -422,7 +426,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libsimaka
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-simaka-pseudonym.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-simaka-pseudonym.la
diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.am b/src/libcharon/plugins/eap_simaka_reauth/Makefile.am
index be000c6d5..0fb622220 100644
--- a/src/libcharon/plugins/eap_simaka_reauth/Makefile.am
+++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libsimaka
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-eap-simaka-reauth.la
diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
index 8ac480d48..57c64246b 100644
--- a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -268,6 +268,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -286,6 +287,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -313,6 +315,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -404,6 +407,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -421,7 +425,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libsimaka
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-simaka-reauth.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-simaka-reauth.la
diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.am b/src/libcharon/plugins/eap_simaka_sql/Makefile.am
index 9a52bd8ab..b7d6fd43e 100644
--- a/src/libcharon/plugins/eap_simaka_sql/Makefile.am
+++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.am
@@ -6,7 +6,7 @@ AM_CPPFLAGS = \
-DIPSEC_CONFDIR=\"${sysconfdir}\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-eap-simaka-sql.la
diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.in b/src/libcharon/plugins/eap_simaka_sql/Makefile.in
index 79b45a9c1..eb4d3fa95 100644
--- a/src/libcharon/plugins/eap_simaka_sql/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -267,6 +267,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -285,6 +286,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -312,6 +314,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -403,6 +406,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -421,7 +425,7 @@ AM_CPPFLAGS = \
-DIPSEC_CONFDIR=\"${sysconfdir}\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-simaka-sql.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-simaka-sql.la
diff --git a/src/libcharon/plugins/eap_tls/Makefile.am b/src/libcharon/plugins/eap_tls/Makefile.am
index c4944fca1..825beb841 100644
--- a/src/libcharon/plugins/eap_tls/Makefile.am
+++ b/src/libcharon/plugins/eap_tls/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libtls
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-eap-tls.la
diff --git a/src/libcharon/plugins/eap_tls/Makefile.in b/src/libcharon/plugins/eap_tls/Makefile.in
index c2b8b4feb..c63d56b53 100644
--- a/src/libcharon/plugins/eap_tls/Makefile.in
+++ b/src/libcharon/plugins/eap_tls/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -419,7 +423,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libtls
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-tls.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-tls.la
diff --git a/src/libcharon/plugins/eap_tnc/Makefile.am b/src/libcharon/plugins/eap_tnc/Makefile.am
index 9586bef14..6fc78bc9a 100644
--- a/src/libcharon/plugins/eap_tnc/Makefile.am
+++ b/src/libcharon/plugins/eap_tnc/Makefile.am
@@ -7,7 +7,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libtnccs
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-eap-tnc.la
diff --git a/src/libcharon/plugins/eap_tnc/Makefile.in b/src/libcharon/plugins/eap_tnc/Makefile.in
index 1f2ace21d..97552dfd0 100644
--- a/src/libcharon/plugins/eap_tnc/Makefile.in
+++ b/src/libcharon/plugins/eap_tnc/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -267,6 +267,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -285,6 +286,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -312,6 +314,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -403,6 +406,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -422,7 +426,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libtnccs
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-tnc.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-tnc.la
diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.c b/src/libcharon/plugins/eap_tnc/eap_tnc.c
index 2147c0482..62d23d064 100644
--- a/src/libcharon/plugins/eap_tnc/eap_tnc.c
+++ b/src/libcharon/plugins/eap_tnc/eap_tnc.c
@@ -47,6 +47,11 @@ struct private_eap_tnc_t {
eap_tnc_t public;
/**
+ * Inner EAP authentication type
+ */
+ eap_type_t type;
+
+ /**
* Outer EAP authentication type
*/
eap_type_t auth_type;
@@ -124,7 +129,7 @@ METHOD(eap_method_t, initiate, status_t,
private_eap_tnc_t *this, eap_payload_t **out)
{
chunk_t data;
- u_int32_t auth_type;
+ uint32_t auth_type;
/* Determine TNC Client Authentication Type */
switch (this->auth_type)
@@ -175,10 +180,10 @@ METHOD(eap_method_t, process, status_t,
}
METHOD(eap_method_t, get_type, eap_type_t,
- private_eap_tnc_t *this, u_int32_t *vendor)
+ private_eap_tnc_t *this, uint32_t *vendor)
{
*vendor = 0;
- return EAP_TNC;
+ return this->type;
}
METHOD(eap_method_t, get_msk, status_t,
@@ -192,14 +197,14 @@ METHOD(eap_method_t, get_msk, status_t,
return FAILED;
}
-METHOD(eap_method_t, get_identifier, u_int8_t,
+METHOD(eap_method_t, get_identifier, uint8_t,
private_eap_tnc_t *this)
{
return this->tls_eap->get_identifier(this->tls_eap);
}
METHOD(eap_method_t, set_identifier, void,
- private_eap_tnc_t *this, u_int8_t identifier)
+ private_eap_tnc_t *this, uint8_t identifier)
{
this->tls_eap->set_identifier(this->tls_eap, identifier);
}
@@ -214,7 +219,7 @@ METHOD(eap_method_t, destroy, void,
private_eap_tnc_t *this)
{
chunk_t pdp_server;
- u_int16_t pdp_port;
+ uint16_t pdp_port;
tls_t *tls;
pdp_server = this->tnccs->get_pdp_server(this->tnccs, &pdp_port);
@@ -245,13 +250,14 @@ METHOD(eap_inner_method_t, set_auth_type, void,
* Generic private constructor
*/
static eap_tnc_t *eap_tnc_create(identification_t *server,
- identification_t *peer, bool is_server)
+ identification_t *peer, bool is_server,
+ eap_type_t type)
{
private_eap_tnc_t *this;
int max_msg_count;
char* protocol;
tnccs_t *tnccs;
- tnccs_type_t type;
+ tnccs_type_t tnccs_type;
INIT(this,
.public = {
@@ -270,24 +276,25 @@ static eap_tnc_t *eap_tnc_create(identification_t *server,
.set_auth_type = _set_auth_type,
},
},
+ .type = type,
);
max_msg_count = lib->settings->get_int(lib->settings,
"%s.plugins.eap-tnc.max_message_count",
EAP_TNC_MAX_MESSAGE_COUNT, lib->ns);
protocol = lib->settings->get_str(lib->settings,
- "%s.plugins.eap-tnc.protocol", "tnccs-1.1", lib->ns);
+ "%s.plugins.eap-tnc.protocol", "tnccs-2.0", lib->ns);
if (strcaseeq(protocol, "tnccs-2.0"))
{
- type = TNCCS_2_0;
+ tnccs_type = TNCCS_2_0;
}
else if (strcaseeq(protocol, "tnccs-1.1"))
{
- type = TNCCS_1_1;
+ tnccs_type = TNCCS_1_1;
}
else if (strcaseeq(protocol, "tnccs-dynamic") && is_server)
{
- type = TNCCS_DYNAMIC;
+ tnccs_type = TNCCS_DYNAMIC;
}
else
{
@@ -295,8 +302,9 @@ static eap_tnc_t *eap_tnc_create(identification_t *server,
free(this);
return NULL;
}
- tnccs = tnc->tnccs->create_instance(tnc->tnccs, type,
- is_server, server, peer, TNC_IFT_EAP_1_1,
+ tnccs = tnc->tnccs->create_instance(tnc->tnccs, tnccs_type,
+ is_server, server, peer,
+ (type == EAP_TNC) ? TNC_IFT_EAP_1_1 : TNC_IFT_EAP_2_0,
is_server ? enforce_recommendation : NULL);
if (!tnccs)
{
@@ -305,7 +313,7 @@ static eap_tnc_t *eap_tnc_create(identification_t *server,
return NULL;
}
this->tnccs = tnccs->get_ref(tnccs);
- this->tls_eap = tls_eap_create(EAP_TNC, &tnccs->tls,
+ this->tls_eap = tls_eap_create(type, &tnccs->tls,
EAP_TNC_MAX_MESSAGE_LEN,
max_msg_count, FALSE);
if (!this->tls_eap)
@@ -319,11 +327,23 @@ static eap_tnc_t *eap_tnc_create(identification_t *server,
eap_tnc_t *eap_tnc_create_server(identification_t *server,
identification_t *peer)
{
- return eap_tnc_create(server, peer, TRUE);
+ return eap_tnc_create(server, peer, TRUE, EAP_TNC);
}
eap_tnc_t *eap_tnc_create_peer(identification_t *server,
identification_t *peer)
{
- return eap_tnc_create(server, peer, FALSE);
+ return eap_tnc_create(server, peer, FALSE, EAP_TNC);
+}
+
+eap_tnc_t *eap_tnc_pt_create_server(identification_t *server,
+ identification_t *peer)
+{
+ return eap_tnc_create(server, peer, TRUE, EAP_PT_EAP);
+}
+
+eap_tnc_t *eap_tnc_pt_create_peer(identification_t *server,
+ identification_t *peer)
+{
+ return eap_tnc_create(server, peer, FALSE, EAP_PT_EAP);
}
diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.h b/src/libcharon/plugins/eap_tnc/eap_tnc.h
index 8c881f6cf..d7ea9f4bb 100644
--- a/src/libcharon/plugins/eap_tnc/eap_tnc.h
+++ b/src/libcharon/plugins/eap_tnc/eap_tnc.h
@@ -26,7 +26,7 @@ typedef struct eap_tnc_t eap_tnc_t;
#include <sa/eap/eap_inner_method.h>
/**
- * Implementation of the eap_method_t interface using EAP-TNC.
+ * Implementation of the eap_method_t interface using EAP-TNC or PT-EAP.
*/
struct eap_tnc_t {
@@ -43,7 +43,8 @@ struct eap_tnc_t {
* @param peer ID of the EAP client
* @return eap_tnc_t object
*/
-eap_tnc_t *eap_tnc_create_server(identification_t *server, identification_t *peer);
+eap_tnc_t *eap_tnc_create_server(identification_t *server,
+ identification_t *peer);
/**
* Creates the EAP method EAP-TNC acting as peer.
@@ -52,6 +53,27 @@ eap_tnc_t *eap_tnc_create_server(identification_t *server, identification_t *pee
* @param peer ID of the EAP client
* @return eap_tnc_t object
*/
-eap_tnc_t *eap_tnc_create_peer(identification_t *server, identification_t *peer);
+eap_tnc_t *eap_tnc_create_peer(identification_t *server,
+ identification_t *peer);
+
+/**
+ * Creates the EAP method PT-EAP acting as server.
+ *
+ * @param server ID of the EAP server
+ * @param peer ID of the EAP client
+ * @return eap_tnc_t object
+ */
+eap_tnc_t *eap_tnc_pt_create_server(identification_t *server,
+ identification_t *peer);
+
+/**
+ * Creates the EAP method PT-EAP acting as peer.
+ *
+ * @param server ID of the EAP server
+ * @param peer ID of the EAP client
+ * @return eap_tnc_t object
+ */
+eap_tnc_t *eap_tnc_pt_create_peer(identification_t *server,
+ identification_t *peer);
#endif /** EAP_TNC_H_ @}*/
diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc_plugin.c b/src/libcharon/plugins/eap_tnc/eap_tnc_plugin.c
index 813a75f48..d0f79fa43 100644
--- a/src/libcharon/plugins/eap_tnc/eap_tnc_plugin.c
+++ b/src/libcharon/plugins/eap_tnc/eap_tnc_plugin.c
@@ -36,6 +36,14 @@ METHOD(plugin_t, get_features, int,
PLUGIN_PROVIDE(EAP_PEER, EAP_TNC),
PLUGIN_DEPENDS(EAP_PEER, EAP_TTLS),
PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
+ PLUGIN_CALLBACK(eap_method_register, eap_tnc_pt_create_server),
+ PLUGIN_PROVIDE(EAP_SERVER, EAP_PT_EAP),
+ PLUGIN_DEPENDS(EAP_SERVER, EAP_TTLS),
+ PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
+ PLUGIN_CALLBACK(eap_method_register, eap_tnc_pt_create_peer),
+ PLUGIN_PROVIDE(EAP_PEER, EAP_PT_EAP),
+ PLUGIN_DEPENDS(EAP_PEER, EAP_TTLS),
+ PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
};
*features = f;
return countof(f);
diff --git a/src/libcharon/plugins/eap_ttls/Makefile.am b/src/libcharon/plugins/eap_ttls/Makefile.am
index 81776d800..3a7a8cda3 100644
--- a/src/libcharon/plugins/eap_ttls/Makefile.am
+++ b/src/libcharon/plugins/eap_ttls/Makefile.am
@@ -6,7 +6,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libradius
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-eap-ttls.la
diff --git a/src/libcharon/plugins/eap_ttls/Makefile.in b/src/libcharon/plugins/eap_ttls/Makefile.in
index b6937877d..70cc18405 100644
--- a/src/libcharon/plugins/eap_ttls/Makefile.in
+++ b/src/libcharon/plugins/eap_ttls/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -268,6 +268,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -286,6 +287,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -313,6 +315,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -404,6 +407,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -422,7 +426,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libradius
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-ttls.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-ttls.la
diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_server.c b/src/libcharon/plugins/eap_ttls/eap_ttls_server.c
index 88c2b88c6..9d145ea91 100644
--- a/src/libcharon/plugins/eap_ttls/eap_ttls_server.c
+++ b/src/libcharon/plugins/eap_ttls/eap_ttls_server.c
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2010 Andreas Steffen
- * Copyright (C) 2010 HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2010-2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -107,22 +107,34 @@ static status_t start_phase2_auth(private_eap_ttls_server_t *this)
}
/**
- * If configured, start EAP-TNC protocol
+ * If configured, start PT-EAP or legacy EAP-TNC protocol
*/
static status_t start_phase2_tnc(private_eap_ttls_server_t *this,
eap_type_t auth_type)
{
eap_inner_method_t *inner_method;
+ eap_type_t type;
+ char *eap_type_str;
if (this->start_phase2_tnc && lib->settings->get_bool(lib->settings,
"%s.plugins.eap-ttls.phase2_tnc", FALSE, lib->ns))
{
- DBG1(DBG_IKE, "phase2 method %N selected", eap_type_names, EAP_TNC);
- this->method = charon->eap->create_instance(charon->eap, EAP_TNC,
+ eap_type_str = lib->settings->get_str(lib->settings,
+ "%s.plugins.eap-ttls.phase2_tnc_method", "pt",
+ lib->ns);
+ type = eap_type_from_string(eap_type_str);
+ if (type == 0)
+ {
+ DBG1(DBG_IKE, "unrecognized phase2 EAP TNC method \"%s\"",
+ eap_type_str);
+ return FAILED;
+ }
+ DBG1(DBG_IKE, "phase2 method %N selected", eap_type_names, type);
+ this->method = charon->eap->create_instance(charon->eap, type,
0, EAP_SERVER, this->server, this->peer);
if (this->method == NULL)
{
- DBG1(DBG_IKE, "%N method not available", eap_type_names, EAP_TNC);
+ DBG1(DBG_IKE, "%N method not available", eap_type_names, type);
return FAILED;
}
inner_method = (eap_inner_method_t *)this->method;
@@ -135,7 +147,7 @@ static status_t start_phase2_tnc(private_eap_ttls_server_t *this,
}
else
{
- DBG1(DBG_IKE, "%N method failed", eap_type_names, EAP_TNC);
+ DBG1(DBG_IKE, "%N method failed", eap_type_names, type);
return FAILED;
}
}
@@ -151,7 +163,7 @@ METHOD(tls_application_t, process, status_t,
eap_payload_t *in;
eap_code_t code;
eap_type_t type = EAP_NAK, received_type;
- u_int32_t vendor, received_vendor;
+ uint32_t vendor, received_vendor;
status = this->avp->process(this->avp, reader, &data);
switch (status)
@@ -297,7 +309,7 @@ METHOD(tls_application_t, build, status_t,
chunk_t data;
eap_code_t code;
eap_type_t type;
- u_int32_t vendor;
+ uint32_t vendor;
if (this->method == NULL && this->start_phase2 &&
lib->settings->get_bool(lib->settings,
diff --git a/src/libcharon/plugins/error_notify/Makefile.am b/src/libcharon/plugins/error_notify/Makefile.am
index 980fe1fbd..1c64bd2cc 100644
--- a/src/libcharon/plugins/error_notify/Makefile.am
+++ b/src/libcharon/plugins/error_notify/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
-DIPSEC_PIDDIR=\"${piddir}\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-error-notify.la
diff --git a/src/libcharon/plugins/error_notify/Makefile.in b/src/libcharon/plugins/error_notify/Makefile.in
index 8dd787569..0782dde53 100644
--- a/src/libcharon/plugins/error_notify/Makefile.in
+++ b/src/libcharon/plugins/error_notify/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -274,6 +274,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -292,6 +293,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -319,6 +321,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -410,6 +413,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -427,7 +431,7 @@ AM_CPPFLAGS = \
-DIPSEC_PIDDIR=\"${piddir}\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-error-notify.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-error-notify.la
diff --git a/src/libcharon/plugins/farp/Makefile.am b/src/libcharon/plugins/farp/Makefile.am
index 95e57d8e6..0d862b0a9 100644
--- a/src/libcharon/plugins/farp/Makefile.am
+++ b/src/libcharon/plugins/farp/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-farp.la
diff --git a/src/libcharon/plugins/farp/Makefile.in b/src/libcharon/plugins/farp/Makefile.in
index 13f0e5260..75ff158a8 100644
--- a/src/libcharon/plugins/farp/Makefile.in
+++ b/src/libcharon/plugins/farp/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -264,6 +264,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -282,6 +283,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -309,6 +311,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -400,6 +403,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -416,7 +420,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-farp.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-farp.la
diff --git a/src/libcharon/plugins/ha/Makefile.am b/src/libcharon/plugins/ha/Makefile.am
index c10f7f903..50d342389 100644
--- a/src/libcharon/plugins/ha/Makefile.am
+++ b/src/libcharon/plugins/ha/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
-DIPSEC_PIDDIR=\"${piddir}\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-ha.la
diff --git a/src/libcharon/plugins/ha/Makefile.in b/src/libcharon/plugins/ha/Makefile.in
index d7a77ee17..cec73620a 100644
--- a/src/libcharon/plugins/ha/Makefile.in
+++ b/src/libcharon/plugins/ha/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -419,7 +423,7 @@ AM_CPPFLAGS = \
-DIPSEC_PIDDIR=\"${piddir}\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-ha.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-ha.la
diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c
index 1ce9d3a16..6ff24c334 100644
--- a/src/libcharon/plugins/ha/ha_dispatcher.c
+++ b/src/libcharon/plugins/ha/ha_dispatcher.c
@@ -245,13 +245,8 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
{
if (old_sa)
{
- peer_cfg_t *peer_cfg = old_sa->get_peer_cfg(old_sa);
-
- if (peer_cfg)
- {
- ike_sa->set_peer_cfg(ike_sa, peer_cfg);
- ike_sa->inherit(ike_sa, old_sa);
- }
+ ike_sa->inherit_pre(ike_sa, old_sa);
+ ike_sa->inherit_post(ike_sa, old_sa);
charon->ike_sa_manager->checkin_and_destroy(
charon->ike_sa_manager, old_sa);
old_sa = NULL;
@@ -1077,4 +1072,3 @@ ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket,
return &this->public;
}
-
diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c
index 74147e553..dd2399366 100644
--- a/src/libcharon/plugins/ha/ha_tunnel.c
+++ b/src/libcharon/plugins/ha/ha_tunnel.c
@@ -207,6 +207,7 @@ static void setup_tunnel(private_ha_tunnel_t *this,
charon->socket->get_port(charon->socket, FALSE),
remote, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+ ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
peer_cfg = peer_cfg_create("ha", ike_cfg, CERT_NEVER_SEND,
UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, FALSE,
TRUE, 30, 0, FALSE, NULL, NULL);
@@ -235,6 +236,7 @@ static void setup_tunnel(private_ha_tunnel_t *this,
ts = traffic_selector_create_dynamic(IPPROTO_ICMP, 0, 65535);
child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
+ child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
peer_cfg->add_child_cfg(peer_cfg, child_cfg);
this->backend.cfg = peer_cfg;
diff --git a/src/libcharon/plugins/ipseckey/Makefile.am b/src/libcharon/plugins/ipseckey/Makefile.am
index 3a69e521f..aed63c122 100644
--- a/src/libcharon/plugins/ipseckey/Makefile.am
+++ b/src/libcharon/plugins/ipseckey/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-ipseckey.la
diff --git a/src/libcharon/plugins/ipseckey/Makefile.in b/src/libcharon/plugins/ipseckey/Makefile.in
index 1f62f4026..da2e8d7fb 100644
--- a/src/libcharon/plugins/ipseckey/Makefile.in
+++ b/src/libcharon/plugins/ipseckey/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-ipseckey.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-ipseckey.la
diff --git a/src/libcharon/plugins/kernel_iph/Makefile.am b/src/libcharon/plugins/kernel_iph/Makefile.am
new file mode 100644
index 000000000..56946ae1f
--- /dev/null
+++ b/src/libcharon/plugins/kernel_iph/Makefile.am
@@ -0,0 +1,20 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-kernel-iph.la
+else
+plugin_LTLIBRARIES = libstrongswan-kernel-iph.la
+endif
+
+libstrongswan_kernel_iph_la_SOURCES = \
+ kernel_iph_plugin.h kernel_iph_plugin.c \
+ kernel_iph_net.h kernel_iph_net.c
+
+libstrongswan_kernel_iph_la_LDFLAGS = -module -avoid-version
+libstrongswan_kernel_iph_la_LIBADD = -liphlpapi
diff --git a/src/libcharon/plugins/kernel_iph/Makefile.in b/src/libcharon/plugins/kernel_iph/Makefile.in
new file mode 100644
index 000000000..460c7b730
--- /dev/null
+++ b/src/libcharon/plugins/kernel_iph/Makefile.in
@@ -0,0 +1,768 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libcharon/plugins/kernel_iph
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/split-package-version.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(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'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_kernel_iph_la_DEPENDENCIES =
+am_libstrongswan_kernel_iph_la_OBJECTS = kernel_iph_plugin.lo \
+ kernel_iph_net.lo
+libstrongswan_kernel_iph_la_OBJECTS = \
+ $(am_libstrongswan_kernel_iph_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+libstrongswan_kernel_iph_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_kernel_iph_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_kernel_iph_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_kernel_iph_la_rpath =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+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) $(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_CC_1 =
+CCLD = $(CC)
+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_CCLD_1 =
+SOURCES = $(libstrongswan_kernel_iph_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_kernel_iph_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+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@
+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@
+ECHO_N = @ECHO_N@
+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@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
+PTHREADLIB = @PTHREADLIB@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+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@
+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@
+aikgen_plugins = @aikgen_plugins@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+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@
+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@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+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@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-kernel-iph.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-kernel-iph.la
+libstrongswan_kernel_iph_la_SOURCES = \
+ kernel_iph_plugin.h kernel_iph_plugin.c \
+ kernel_iph_net.h kernel_iph_net.c
+
+libstrongswan_kernel_iph_la_LDFLAGS = -module -avoid-version
+libstrongswan_kernel_iph_la_LIBADD = -liphlpapi
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/kernel_iph/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/kernel_iph/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(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)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libstrongswan-kernel-iph.la: $(libstrongswan_kernel_iph_la_OBJECTS) $(libstrongswan_kernel_iph_la_DEPENDENCIES) $(EXTRA_libstrongswan_kernel_iph_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libstrongswan_kernel_iph_la_LINK) $(am_libstrongswan_kernel_iph_la_rpath) $(libstrongswan_kernel_iph_la_OBJECTS) $(libstrongswan_kernel_iph_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_iph_net.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_iph_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-pluginLTLIBRARIES install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/kernel_iph/kernel_iph_net.c b/src/libcharon/plugins/kernel_iph/kernel_iph_net.c
new file mode 100644
index 000000000..a4be4041e
--- /dev/null
+++ b/src/libcharon/plugins/kernel_iph/kernel_iph_net.c
@@ -0,0 +1,775 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/* Windows 7, for some iphlpapi.h functionality */
+#define _WIN32_WINNT 0x0601
+#include <winsock2.h>
+#include <ws2ipdef.h>
+#include <windows.h>
+#include <ntddndis.h>
+#include <naptypes.h>
+#include <iphlpapi.h>
+
+#include "kernel_iph_net.h"
+
+#include <hydra.h>
+#include <threading/mutex.h>
+#include <collections/linked_list.h>
+#include <processing/jobs/callback_job.h>
+
+
+/** delay before firing roam events (ms) */
+#define ROAM_DELAY 500
+
+typedef struct private_kernel_iph_net_t private_kernel_iph_net_t;
+
+/**
+ * Private data of kernel_iph_net implementation.
+ */
+struct private_kernel_iph_net_t {
+
+ /**
+ * Public interface.
+ */
+ kernel_iph_net_t public;
+
+ /**
+ * NotifyIpInterfaceChange() handle
+ */
+ HANDLE changes;
+
+ /**
+ * EnableRouter() OVERLAPPED
+ */
+ OVERLAPPED router;
+
+ /**
+ * Mutex to access interface list
+ */
+ mutex_t *mutex;
+
+ /**
+ * Known interfaces, as iface_t
+ */
+ linked_list_t *ifaces;
+
+ /**
+ * Earliest time of the next roam event
+ */
+ timeval_t roam_next;
+
+ /**
+ * Roam event due to address change?
+ */
+ bool roam_address;
+};
+
+/**
+ * Interface entry
+ */
+typedef struct {
+ /** interface index */
+ DWORD ifindex;
+ /** interface name */
+ char *ifname;
+ /** interface description */
+ char *ifdesc;
+ /** type of interface */
+ DWORD iftype;
+ /** interface status */
+ IF_OPER_STATUS status;
+ /** list of known addresses, as host_t */
+ linked_list_t *addrs;
+} iface_t;
+
+/**
+ * Clean up an iface_t
+ */
+static void iface_destroy(iface_t *this)
+{
+ this->addrs->destroy_offset(this->addrs, offsetof(host_t, destroy));
+ free(this->ifname);
+ free(this->ifdesc);
+ free(this);
+}
+
+/**
+ * Enum names for Windows IF_OPER_STATUS
+ */
+ENUM(if_oper_names, IfOperStatusUp, IfOperStatusLowerLayerDown,
+ "Up",
+ "Down",
+ "Testing",
+ "Unknown",
+ "Dormant",
+ "NotPresent",
+ "LowerLayerDown",
+);
+
+/**
+ * Callback function that raises the delayed roam event
+ */
+static job_requeue_t roam_event(private_kernel_iph_net_t *this)
+{
+ bool address;
+
+ this->mutex->lock(this->mutex);
+ address = this->roam_address;
+ this->roam_address = FALSE;
+ this->mutex->unlock(this->mutex);
+
+ hydra->kernel_interface->roam(hydra->kernel_interface, address);
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Fire delayed roam event, caller should hold mutex
+ */
+static void fire_roam_event(private_kernel_iph_net_t *this, bool address)
+{
+ timeval_t now;
+
+ time_monotonic(&now);
+ this->roam_address |= address;
+ if (timercmp(&now, &this->roam_next, >))
+ {
+ timeval_add_ms(&now, ROAM_DELAY);
+ this->roam_next = now;
+ lib->scheduler->schedule_job_ms(lib->scheduler, (job_t*)
+ callback_job_create((callback_job_cb_t)roam_event,
+ this, NULL, NULL),
+ ROAM_DELAY);
+ }
+}
+
+/**
+ * Update addresses for an iface entry
+ */
+static void update_addrs(private_kernel_iph_net_t *this, iface_t *entry,
+ IP_ADAPTER_ADDRESSES *addr, bool log)
+{
+ IP_ADAPTER_UNICAST_ADDRESS *current;
+ enumerator_t *enumerator;
+ linked_list_t *list;
+ host_t *host, *old;
+ bool changes = FALSE;
+
+ list = entry->addrs;
+ entry->addrs = linked_list_create();
+
+ for (current = addr->FirstUnicastAddress; current; current = current->Next)
+ {
+ if (current->Address.lpSockaddr->sa_family == AF_INET6)
+ {
+ struct sockaddr_in6 *sin;
+
+ sin = (struct sockaddr_in6*)current->Address.lpSockaddr;
+ if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr))
+ {
+ continue;
+ }
+ }
+
+ host = host_create_from_sockaddr(current->Address.lpSockaddr);
+ if (host)
+ {
+ bool found = FALSE;
+
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &old))
+ {
+ if (host->ip_equals(host, old))
+ {
+ list->remove_at(list, enumerator);
+ old->destroy(old);
+ found = TRUE;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ entry->addrs->insert_last(entry->addrs, host);
+
+ if (!found && log)
+ {
+ DBG1(DBG_KNL, "%H appeared on interface %u '%s'",
+ host, entry->ifindex, entry->ifdesc);
+ changes = TRUE;
+ }
+ }
+ }
+
+ while (list->remove_first(list, (void**)&old) == SUCCESS)
+ {
+ if (log)
+ {
+ DBG1(DBG_KNL, "%H disappeared from interface %u '%s'",
+ old, entry->ifindex, entry->ifdesc);
+ changes = TRUE;
+ }
+ old->destroy(old);
+ }
+ list->destroy(list);
+
+ if (changes)
+ {
+ fire_roam_event(this, TRUE);
+ }
+}
+
+/**
+ * Add an interface entry
+ */
+static void add_interface(private_kernel_iph_net_t *this,
+ IP_ADAPTER_ADDRESSES *addr, bool log)
+{
+ enumerator_t *enumerator;
+ iface_t *entry;
+ bool exists = FALSE;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->ifaces->create_enumerator(this->ifaces);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->ifindex == addr->IfIndex)
+ {
+ exists = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+
+ if (!exists)
+ {
+ char desc[128] = "";
+
+ wcstombs(desc, addr->Description, sizeof(desc));
+
+ INIT(entry,
+ .ifindex = addr->IfIndex,
+ .ifname = strdup(addr->AdapterName),
+ .ifdesc = strdup(desc),
+ .iftype = addr->IfType,
+ .status = addr->OperStatus,
+ .addrs = linked_list_create(),
+ );
+
+ if (log)
+ {
+ DBG1(DBG_KNL, "interface %u '%s' appeared",
+ entry->ifindex, entry->ifdesc);
+ }
+
+ this->mutex->lock(this->mutex);
+ update_addrs(this, entry, addr, log);
+ this->ifaces->insert_last(this->ifaces, entry);
+ this->mutex->unlock(this->mutex);
+ }
+}
+
+/**
+ * Remove an interface entry that is gone
+ */
+static void remove_interface(private_kernel_iph_net_t *this, NET_IFINDEX index)
+{
+ enumerator_t *enumerator;
+ iface_t *entry;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->ifaces->create_enumerator(this->ifaces);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->ifindex == index)
+ {
+ this->ifaces->remove_at(this->ifaces, enumerator);
+ DBG1(DBG_KNL, "interface %u '%s' disappeared",
+ entry->ifindex, entry->ifdesc);
+ iface_destroy(entry);
+ fire_roam_event(this, TRUE);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Update an interface entry changed
+ */
+static void update_interface(private_kernel_iph_net_t *this,
+ IP_ADAPTER_ADDRESSES *addr)
+{
+ enumerator_t *enumerator;
+ iface_t *entry;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->ifaces->create_enumerator(this->ifaces);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->ifindex == addr->IfIndex)
+ {
+ if (entry->status != addr->OperStatus)
+ {
+ DBG1(DBG_KNL, "interface %u '%s' changed state from %N to %N",
+ entry->ifindex, entry->ifdesc, if_oper_names,
+ entry->status, if_oper_names, addr->OperStatus);
+ entry->status = addr->OperStatus;
+ fire_roam_event(this, TRUE);
+ }
+ update_addrs(this, entry, addr, TRUE);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * MinGW gets MIB_IPINTERFACE_ROW wrong, as it packs InterfaceLuid just after
+ * Family. Fix that with our own version of the struct header.
+ */
+typedef struct {
+ ADDRESS_FAMILY Family;
+ union {
+ ULONG64 Value;
+ struct {
+ ULONG64 Reserved :24;
+ ULONG64 NetLuidIndex :24;
+ ULONG64 IfType :16;
+ } Info;
+ } InterfaceLuid;
+ NET_IFINDEX InterfaceIndex;
+ /* more would go here if needed */
+} MIB_IPINTERFACE_ROW_FIXUP;
+
+/**
+ * NotifyIpInterfaceChange() callback
+ */
+static void WINAPI change_interface(void *user, PMIB_IPINTERFACE_ROW row_badal,
+ MIB_NOTIFICATION_TYPE type)
+{
+ private_kernel_iph_net_t *this = user;
+ MIB_IPINTERFACE_ROW_FIXUP* row = (MIB_IPINTERFACE_ROW_FIXUP*)row_badal;
+ IP_ADAPTER_ADDRESSES addrs[64], *current;
+ ULONG res, size = sizeof(addrs);
+
+ if (row && type == MibDeleteInstance)
+ {
+ remove_interface(this, row->InterfaceIndex);
+ }
+ else
+ {
+ res = GetAdaptersAddresses(AF_UNSPEC,
+ GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
+ GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME,
+ NULL, addrs, &size);
+ if (res == NO_ERROR)
+ {
+ current = addrs;
+ while (current)
+ {
+ /* row is NULL only on MibInitialNotification */
+ if (!row || row->InterfaceIndex == current->IfIndex)
+ {
+ switch (type)
+ {
+ case MibParameterNotification:
+ update_interface(this, current);
+ break;
+ case MibInitialNotification:
+ add_interface(this, current, FALSE);
+ break;
+ case MibAddInstance:
+ add_interface(this, current, TRUE);
+ break;
+ default:
+ break;
+ }
+ }
+ current = current->Next;
+ }
+ }
+ else
+ {
+ DBG1(DBG_KNL, "getting IPH adapter addresses failed: 0x%08lx", res);
+ }
+ }
+}
+
+/**
+ * Get an iface entry for a local address, does no locking
+ */
+static iface_t* address2entry(private_kernel_iph_net_t *this, host_t *ip)
+{
+ enumerator_t *ifaces, *addrs;
+ iface_t *entry, *found = NULL;
+ host_t *host;
+
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (!found && ifaces->enumerate(ifaces, &entry))
+ {
+ addrs = entry->addrs->create_enumerator(entry->addrs);
+ while (!found && addrs->enumerate(addrs, &host))
+ {
+ if (host->ip_equals(host, ip))
+ {
+ found = entry;
+ }
+ }
+ addrs->destroy(addrs);
+ }
+ ifaces->destroy(ifaces);
+
+ return found;
+}
+
+METHOD(kernel_net_t, get_interface_name, bool,
+ private_kernel_iph_net_t *this, host_t* ip, char **name)
+{
+ iface_t *entry;
+
+ this->mutex->lock(this->mutex);
+ entry = address2entry(this, ip);
+ if (entry && name)
+ {
+ *name = strdup(entry->ifname);
+ }
+ this->mutex->unlock(this->mutex);
+
+ return entry != NULL;
+}
+
+/**
+ * Address enumerator
+ */
+typedef struct {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** what kind of address should we enumerate? */
+ kernel_address_type_t which;
+ /** enumerator over interfaces */
+ enumerator_t *ifaces;
+ /** current enumerator over addresses, or NULL */
+ enumerator_t *addrs;
+ /** mutex to unlock on destruction */
+ mutex_t *mutex;
+} addr_enumerator_t;
+
+METHOD(enumerator_t, addr_enumerate, bool,
+ addr_enumerator_t *this, host_t **host)
+{
+ iface_t *entry;
+
+ while (TRUE)
+ {
+ while (!this->addrs)
+ {
+ if (!this->ifaces->enumerate(this->ifaces, &entry))
+ {
+ return FALSE;
+ }
+ if (entry->iftype == IF_TYPE_SOFTWARE_LOOPBACK &&
+ !(this->which & ADDR_TYPE_LOOPBACK))
+ {
+ continue;
+ }
+ if (entry->status != IfOperStatusUp &&
+ !(this->which & ADDR_TYPE_DOWN))
+ {
+ continue;
+ }
+ this->addrs = entry->addrs->create_enumerator(entry->addrs);
+ }
+ if (this->addrs->enumerate(this->addrs, host))
+ {
+ return TRUE;
+ }
+ this->addrs->destroy(this->addrs);
+ this->addrs = NULL;
+ }
+}
+
+METHOD(enumerator_t, addr_destroy, void,
+ addr_enumerator_t *this)
+{
+ DESTROY_IF(this->addrs);
+ this->ifaces->destroy(this->ifaces);
+ this->mutex->unlock(this->mutex);
+ free(this);
+}
+
+METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
+ private_kernel_iph_net_t *this, kernel_address_type_t which)
+{
+ addr_enumerator_t *enumerator;
+
+ if (!(which & ADDR_TYPE_REGULAR))
+ {
+ /* we currently have no virtual, but regular IPs only */
+ return enumerator_create_empty();
+ }
+
+ this->mutex->lock(this->mutex);
+
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)_addr_enumerate,
+ .destroy = _addr_destroy,
+ },
+ .which = which,
+ .ifaces = this->ifaces->create_enumerator(this->ifaces),
+ .mutex = this->mutex,
+ );
+ return &enumerator->public;
+}
+
+METHOD(kernel_net_t, get_source_addr, host_t*,
+ private_kernel_iph_net_t *this, host_t *dest, host_t *src)
+{
+ MIB_IPFORWARD_ROW2 route;
+ SOCKADDR_INET best, *sai_dst, *sai_src = NULL;
+ DWORD res, index = 0;
+
+ res = GetBestInterfaceEx(dest->get_sockaddr(dest), &index);
+ if (res != NO_ERROR)
+ {
+ DBG1(DBG_KNL, "getting interface to %H failed: 0x%08x", dest, res);
+ return NULL;
+ }
+
+ sai_dst = (SOCKADDR_INET*)dest->get_sockaddr(dest);
+ if (src)
+ {
+ sai_src = (SOCKADDR_INET*)src->get_sockaddr(src);
+ }
+ res = GetBestRoute2(0, index, sai_src, sai_dst, 0, &route, &best);
+ if (res != NO_ERROR)
+ {
+ DBG2(DBG_KNL, "getting src address to %H failed: 0x%08x", dest, res);
+ return NULL;
+ }
+ return host_create_from_sockaddr((struct sockaddr*)&best);
+}
+
+METHOD(kernel_net_t, get_nexthop, host_t*,
+ private_kernel_iph_net_t *this, host_t *dest, int prefix, host_t *src)
+{
+ MIB_IPFORWARD_ROW2 route;
+ SOCKADDR_INET best, *sai_dst, *sai_src = NULL;
+ DWORD res, index = 0;
+ host_t *nexthop;
+
+ res = GetBestInterfaceEx(dest->get_sockaddr(dest), &index);
+ if (res != NO_ERROR)
+ {
+ DBG1(DBG_KNL, "getting interface to %H failed: 0x%08x", dest, res);
+ return NULL;
+ }
+
+ sai_dst = (SOCKADDR_INET*)dest->get_sockaddr(dest);
+ if (src)
+ {
+ sai_src = (SOCKADDR_INET*)src->get_sockaddr(src);
+ }
+ res = GetBestRoute2(0, index, sai_src, sai_dst, 0, &route, &best);
+ if (res != NO_ERROR)
+ {
+ DBG2(DBG_KNL, "getting nexthop to %H failed: 0x%08x", dest, res);
+ return NULL;
+ }
+ nexthop = host_create_from_sockaddr((struct sockaddr*)&route.NextHop);
+ if (nexthop)
+ {
+ if (!nexthop->is_anyaddr(nexthop))
+ {
+ return nexthop;
+ }
+ nexthop->destroy(nexthop);
+ }
+ return NULL;
+}
+
+METHOD(kernel_net_t, add_ip, status_t,
+ private_kernel_iph_net_t *this, host_t *virtual_ip, int prefix,
+ char *iface_name)
+{
+ return NOT_SUPPORTED;
+}
+
+METHOD(kernel_net_t, del_ip, status_t,
+ private_kernel_iph_net_t *this, host_t *virtual_ip, int prefix,
+ bool wait)
+{
+ return NOT_SUPPORTED;
+}
+
+/**
+ * Add or remove a route
+ */
+static status_t manage_route(private_kernel_iph_net_t *this, bool add,
+ chunk_t dst, u_int8_t prefixlen, host_t *gtw, char *name)
+{
+ MIB_IPFORWARD_ROW2 row = {
+ .DestinationPrefix = {
+ .PrefixLength = prefixlen,
+ },
+ .SitePrefixLength = prefixlen,
+ .ValidLifetime = INFINITE,
+ .PreferredLifetime = INFINITE,
+ .Metric = 10,
+ .Protocol = MIB_IPPROTO_NETMGMT,
+ };
+ enumerator_t *enumerator;
+ iface_t *entry;
+ ULONG ret;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->ifaces->create_enumerator(this->ifaces);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (streq(name, entry->ifname))
+ {
+ row.InterfaceIndex = entry->ifindex;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+
+ if (!row.InterfaceIndex)
+ {
+ return NOT_FOUND;
+ }
+ switch (dst.len)
+ {
+ case 4:
+ row.DestinationPrefix.Prefix.si_family = AF_INET;
+ memcpy(&row.DestinationPrefix.Prefix.Ipv4.sin_addr,
+ dst.ptr, dst.len);
+ break;
+ case 16:
+ row.DestinationPrefix.Prefix.si_family = AF_INET6;
+ memcpy(&row.DestinationPrefix.Prefix.Ipv6.sin6_addr,
+ dst.ptr, dst.len);
+ break;
+ default:
+ return FAILED;
+ }
+ if (gtw)
+ {
+ memcpy(&row.NextHop, gtw->get_sockaddr(gtw),
+ *gtw->get_sockaddr_len(gtw));
+ }
+
+ if (add)
+ {
+ ret = CreateIpForwardEntry2(&row);
+ }
+ else
+ {
+ ret = DeleteIpForwardEntry2(&row);
+ }
+ if (ret != NO_ERROR)
+ {
+ DBG1(DBG_KNL, "%sing route failed: 0x%08lx", add ? "add" : "remov", ret);
+ return FAILED;
+ }
+
+ if (add)
+ {
+ ret = EnableRouter(NULL, &this->router);
+ if (ret != ERROR_IO_PENDING)
+ {
+ DBG1(DBG_KNL, "EnableRouter router failed: 0x%08lx", ret);
+ }
+ }
+ else
+ {
+ ret = UnenableRouter(&this->router, NULL);
+ if (ret != NO_ERROR)
+ {
+ DBG1(DBG_KNL, "UnenableRouter router failed: 0x%08lx", ret);
+ }
+ }
+ return SUCCESS;
+}
+
+METHOD(kernel_net_t, add_route, status_t,
+ private_kernel_iph_net_t *this, chunk_t dst, u_int8_t prefixlen,
+ host_t *gateway, host_t *src, char *name)
+{
+ return manage_route(this, TRUE, dst, prefixlen, gateway, name);
+}
+
+METHOD(kernel_net_t, del_route, status_t,
+ private_kernel_iph_net_t *this, chunk_t dst, u_int8_t prefixlen,
+ host_t *gateway, host_t *src, char *name)
+{
+ return manage_route(this, FALSE, dst, prefixlen, gateway, name);
+}
+
+METHOD(kernel_net_t, destroy, void,
+ private_kernel_iph_net_t *this)
+{
+ if (this->changes)
+ {
+ CancelMibChangeNotify2(this->changes);
+ }
+ CloseHandle(this->router.hEvent);
+ this->mutex->destroy(this->mutex);
+ this->ifaces->destroy_function(this->ifaces, (void*)iface_destroy);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+kernel_iph_net_t *kernel_iph_net_create()
+{
+ private_kernel_iph_net_t *this;
+ ULONG res;
+
+ INIT(this,
+ .public = {
+ .interface = {
+ .get_interface = _get_interface_name,
+ .create_address_enumerator = _create_address_enumerator,
+ .get_source_addr = _get_source_addr,
+ .get_nexthop = _get_nexthop,
+ .add_ip = _add_ip,
+ .del_ip = _del_ip,
+ .add_route = _add_route,
+ .del_route = _del_route,
+ .destroy = _destroy,
+ },
+ },
+ .router = {
+ .hEvent = CreateEvent(NULL, FALSE, FALSE, NULL),
+ },
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .ifaces = linked_list_create(),
+ );
+ /* PIPINTERFACE_CHANGE_CALLBACK is not using WINAPI in MinGW, which seems
+ * to be wrong. Force a cast to our WINAPI call */
+ res = NotifyIpInterfaceChange(AF_UNSPEC, (void*)change_interface,
+ this, TRUE, &this->changes);
+ if (res != NO_ERROR)
+ {
+ DBG1(DBG_KNL, "registering for IPH interface changes failed: 0x%08lx",
+ res);
+ destroy(this);
+ return NULL;
+ }
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/kernel_iph/kernel_iph_net.h b/src/libcharon/plugins/kernel_iph/kernel_iph_net.h
new file mode 100644
index 000000000..c8f35de18
--- /dev/null
+++ b/src/libcharon/plugins/kernel_iph/kernel_iph_net.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup kernel_iph_net_i kernel_iph_net
+ * @{ @ingroup kernel_iph
+ */
+
+#ifndef KERNEL_IPH_NET_H_
+#define KERNEL_IPH_NET_H_
+
+#include <kernel/kernel_net.h>
+
+typedef struct kernel_iph_net_t kernel_iph_net_t;
+
+/**
+ * Implementation of the kernel network interface using Windows IP Helper.
+ */
+struct kernel_iph_net_t {
+
+ /**
+ * Implements kernel_net_t interface
+ */
+ kernel_net_t interface;
+};
+
+/**
+ * Create IP Helper network backend instance.
+ *
+ * @return kernel_iph_net_t instance
+ */
+kernel_iph_net_t *kernel_iph_net_create();
+
+#endif /** KERNEL_IPH_NET_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_iph/kernel_iph_plugin.c b/src/libcharon/plugins/kernel_iph/kernel_iph_plugin.c
new file mode 100644
index 000000000..c5475e30b
--- /dev/null
+++ b/src/libcharon/plugins/kernel_iph/kernel_iph_plugin.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+
+#include "kernel_iph_plugin.h"
+#include "kernel_iph_net.h"
+
+#include <hydra.h>
+
+typedef struct private_kernel_iph_plugin_t private_kernel_iph_plugin_t;
+
+/**
+ * Private data of kernel iph plugin
+ */
+struct private_kernel_iph_plugin_t {
+
+ /**
+ * Implements plugin interface
+ */
+ kernel_iph_plugin_t public;
+};
+
+METHOD(plugin_t, get_name, char*,
+ private_kernel_iph_plugin_t *this)
+{
+ return "kernel-iph";
+}
+
+METHOD(plugin_t, get_features, int,
+ private_kernel_iph_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_CALLBACK(kernel_net_register, kernel_iph_net_create),
+ PLUGIN_PROVIDE(CUSTOM, "kernel-net"),
+ };
+ *features = f;
+ return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+ private_kernel_iph_plugin_t *this)
+{
+ free(this);
+}
+
+/*
+ * See header file
+ */
+plugin_t *kernel_iph_plugin_create()
+{
+ private_kernel_iph_plugin_t *this;
+
+ INIT(this,
+ .public = {
+ .plugin = {
+ .get_name = _get_name,
+ .get_features = _get_features,
+ .destroy = _destroy,
+ },
+ },
+ );
+
+ return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/kernel_iph/kernel_iph_plugin.h b/src/libcharon/plugins/kernel_iph/kernel_iph_plugin.h
new file mode 100644
index 000000000..616f90e77
--- /dev/null
+++ b/src/libcharon/plugins/kernel_iph/kernel_iph_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup kernel_iph kernel_iph
+ * @ingroup cplugins
+ *
+ * @defgroup kernel_iph_plugin kernel_iph_plugin
+ * @{ @ingroup kernel_iph
+ */
+
+#ifndef KERNEL_IPH_PLUGIN_H_
+#define KERNEL_IPH_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct kernel_iph_plugin_t kernel_iph_plugin_t;
+
+/**
+ * Windows IP Helper API based networking backend.
+ */
+struct kernel_iph_plugin_t {
+
+ /**
+ * Implements plugin interface.
+ */
+ plugin_t plugin;
+};
+
+#endif /** KERNEL_IPH_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_libipsec/Makefile.am b/src/libcharon/plugins/kernel_libipsec/Makefile.am
index a39d06753..eca2b2325 100644
--- a/src/libcharon/plugins/kernel_libipsec/Makefile.am
+++ b/src/libcharon/plugins/kernel_libipsec/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libipsec
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-kernel-libipsec.la
diff --git a/src/libcharon/plugins/kernel_libipsec/Makefile.in b/src/libcharon/plugins/kernel_libipsec/Makefile.in
index 3bc289d22..a4e5ba931 100644
--- a/src/libcharon/plugins/kernel_libipsec/Makefile.in
+++ b/src/libcharon/plugins/kernel_libipsec/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -268,6 +268,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -286,6 +287,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -313,6 +315,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -404,6 +407,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -421,7 +425,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libipsec
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-kernel-libipsec.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-kernel-libipsec.la
diff --git a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c
index b33580700..bd07a67a2 100644
--- a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c
+++ b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c
@@ -252,8 +252,9 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
private_kernel_libipsec_ipsec_t *this, host_t *src, host_t *dst,
u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
- u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
- u_int16_t cpi, bool initiator, bool encap, bool esn, bool inbound,
+ u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
+ u_int16_t ipcomp, u_int16_t cpi, u_int32_t replay_window,
+ bool initiator, bool encap, bool esn, bool inbound,
traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
{
return ipsec->sas->add_sa(ipsec->sas, src, dst, spi, protocol, reqid, mark,
@@ -313,7 +314,7 @@ static void add_exclude_route(private_kernel_libipsec_ipsec_t *this,
{
DBG2(DBG_KNL, "installing new exclude route for %H src %H", dst, src);
gtw = hydra->kernel_interface->get_nexthop(hydra->kernel_interface,
- dst, NULL);
+ dst, -1, NULL);
if (gtw)
{
char *if_name = NULL;
@@ -444,7 +445,7 @@ static bool install_route(private_kernel_libipsec_ipsec_t *this,
#ifndef __linux__
/* on Linux we cant't install a gateway */
route->gateway = hydra->kernel_interface->get_nexthop(
- hydra->kernel_interface, dst, src);
+ hydra->kernel_interface, dst, -1, src);
#endif
if (policy->route)
diff --git a/src/libcharon/plugins/kernel_wfp/Makefile.am b/src/libcharon/plugins/kernel_wfp/Makefile.am
new file mode 100644
index 000000000..85e5089a3
--- /dev/null
+++ b/src/libcharon/plugins/kernel_wfp/Makefile.am
@@ -0,0 +1,33 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-kernel-wfp.la
+else
+plugin_LTLIBRARIES = libstrongswan-kernel-wfp.la
+endif
+
+libstrongswan_kernel_wfp_la_SOURCES = \
+ kernel_wfp_plugin.h kernel_wfp_plugin.c \
+ kernel_wfp_compat.c kernel_wfp_compat.h \
+ kernel_wfp_ipsec.h kernel_wfp_ipsec.c
+
+libstrongswan_kernel_wfp_la_LDFLAGS = -module -avoid-version
+libstrongswan_kernel_wfp_la_LIBADD = -lfwpuclnt
+
+
+noinst_PROGRAMS = ipsecdump
+
+ipsecdump_SOURCES = \
+ ipsecdump.c
+ipsecdump_LDADD = \
+ libstrongswan-kernel-wfp.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+
+
+EXTRA_DIST = mingw-w64-4.8.1.diff
diff --git a/src/libcharon/plugins/kernel_wfp/Makefile.in b/src/libcharon/plugins/kernel_wfp/Makefile.in
new file mode 100644
index 000000000..ff987f8d4
--- /dev/null
+++ b/src/libcharon/plugins/kernel_wfp/Makefile.in
@@ -0,0 +1,801 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+noinst_PROGRAMS = ipsecdump$(EXEEXT)
+subdir = src/libcharon/plugins/kernel_wfp
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/split-package-version.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(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'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_kernel_wfp_la_DEPENDENCIES =
+am_libstrongswan_kernel_wfp_la_OBJECTS = kernel_wfp_plugin.lo \
+ kernel_wfp_compat.lo kernel_wfp_ipsec.lo
+libstrongswan_kernel_wfp_la_OBJECTS = \
+ $(am_libstrongswan_kernel_wfp_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+libstrongswan_kernel_wfp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_kernel_wfp_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_kernel_wfp_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_kernel_wfp_la_rpath =
+PROGRAMS = $(noinst_PROGRAMS)
+am_ipsecdump_OBJECTS = ipsecdump.$(OBJEXT)
+ipsecdump_OBJECTS = $(am_ipsecdump_OBJECTS)
+ipsecdump_DEPENDENCIES = libstrongswan-kernel-wfp.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+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) $(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_CC_1 =
+CCLD = $(CC)
+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_CCLD_1 =
+SOURCES = $(libstrongswan_kernel_wfp_la_SOURCES) $(ipsecdump_SOURCES)
+DIST_SOURCES = $(libstrongswan_kernel_wfp_la_SOURCES) \
+ $(ipsecdump_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+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@
+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@
+ECHO_N = @ECHO_N@
+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@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
+PTHREADLIB = @PTHREADLIB@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+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@
+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@
+aikgen_plugins = @aikgen_plugins@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+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@
+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@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+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@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-kernel-wfp.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-kernel-wfp.la
+libstrongswan_kernel_wfp_la_SOURCES = \
+ kernel_wfp_plugin.h kernel_wfp_plugin.c \
+ kernel_wfp_compat.c kernel_wfp_compat.h \
+ kernel_wfp_ipsec.h kernel_wfp_ipsec.c
+
+libstrongswan_kernel_wfp_la_LDFLAGS = -module -avoid-version
+libstrongswan_kernel_wfp_la_LIBADD = -lfwpuclnt
+ipsecdump_SOURCES = \
+ ipsecdump.c
+
+ipsecdump_LDADD = \
+ libstrongswan-kernel-wfp.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+
+EXTRA_DIST = mingw-w64-4.8.1.diff
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/kernel_wfp/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/kernel_wfp/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(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)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libstrongswan-kernel-wfp.la: $(libstrongswan_kernel_wfp_la_OBJECTS) $(libstrongswan_kernel_wfp_la_DEPENDENCIES) $(EXTRA_libstrongswan_kernel_wfp_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libstrongswan_kernel_wfp_la_LINK) $(am_libstrongswan_kernel_wfp_la_rpath) $(libstrongswan_kernel_wfp_la_OBJECTS) $(libstrongswan_kernel_wfp_la_LIBADD) $(LIBS)
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+ipsecdump$(EXEEXT): $(ipsecdump_OBJECTS) $(ipsecdump_DEPENDENCIES) $(EXTRA_ipsecdump_DEPENDENCIES)
+ @rm -f ipsecdump$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(ipsecdump_OBJECTS) $(ipsecdump_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipsecdump.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_wfp_compat.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_wfp_ipsec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_wfp_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-noinstPROGRAMS clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \
+ clean-pluginLTLIBRARIES cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginLTLIBRARIES \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/kernel_wfp/ipsecdump.c b/src/libcharon/plugins/kernel_wfp/ipsecdump.c
new file mode 100644
index 000000000..7ca7df5a1
--- /dev/null
+++ b/src/libcharon/plugins/kernel_wfp/ipsecdump.c
@@ -0,0 +1,666 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/* Windows 7, for some fwpmu.h functionality */
+#define _WIN32_WINNT 0x0601
+
+#include "kernel_wfp_compat.h"
+
+#include <library.h>
+
+ENUM(auth_type_names, IPSEC_AUTH_MD5, IPSEC_AUTH_AES_256,
+ "MD5",
+ "SHA1",
+ "SHA256",
+ "AES128",
+ "AES192",
+ "AES256",
+);
+
+ENUM(auth_config_names, 0, 5,
+ "HMAC96",
+ "HMAC96",
+ "HMAC128",
+ "GMAC",
+ "GMAC",
+ "GMAC",
+);
+
+ENUM(cipher_type_names, IPSEC_CIPHER_TYPE_DES, IPSEC_CIPHER_TYPE_AES_256,
+ "DES",
+ "3DES",
+ "AES128",
+ "AES192",
+ "AES256",
+);
+
+ENUM(cipher_config_names, 1, 8,
+ "CBC",
+ "CBC",
+ "CBC",
+ "CBC",
+ "CBC",
+ "GCM",
+ "GCM",
+ "GCM",
+);
+
+ENUM(match_type_names, FWP_MATCH_EQUAL, FWP_MATCH_NOT_EQUAL,
+ "equals",
+ "greater",
+ "less than",
+ "greater or equal than",
+ "less or equal than",
+ "in range",
+ "has all flags set",
+ "has any flags set",
+ "has none flags set",
+ "equals case insensitive",
+ "not equal",
+);
+
+ENUM(traffic_type_names, IPSEC_TRAFFIC_TYPE_TRANSPORT, IPSEC_TRAFFIC_TYPE_TUNNEL,
+ "Transport",
+ "Tunnel",
+);
+
+/**
+ * Print a GUID to a static buffer
+ */
+static char *guid2string(GUID *guid)
+{
+ static char buf[64];
+
+ snprintf(buf, sizeof(buf),
+ "%08x,%04x,%04x%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x",
+ guid->Data1, guid->Data2, guid->Data3,
+ guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
+ guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
+
+ return buf;
+}
+
+/**
+ * Convert filter condition key GUID to some known strings
+ */
+static char* cond2name(GUID *guid, bool *address)
+{
+ struct {
+ GUID guid;
+ char *name;
+ bool address;
+ } map[] = {
+ { FWPM_CONDITION_IP_LOCAL_ADDRESS, "local address", TRUE},
+ { FWPM_CONDITION_IP_REMOTE_ADDRESS, "remote address", TRUE},
+ { FWPM_CONDITION_IP_SOURCE_ADDRESS, "source address", TRUE},
+ { FWPM_CONDITION_IP_DESTINATION_ADDRESS, "destination address", TRUE},
+ { FWPM_CONDITION_IP_LOCAL_PORT, "local port", FALSE},
+ { FWPM_CONDITION_IP_REMOTE_PORT, "remote port", FALSE},
+ { FWPM_CONDITION_IP_PROTOCOL, "protocol", FALSE},
+ { FWPM_CONDITION_ICMP_CODE, "icmp code", FALSE},
+ { FWPM_CONDITION_ICMP_TYPE, "icmp type", FALSE},
+ };
+ int i;
+
+ for (i = 0; i < countof(map); i++)
+ {
+ if (memeq(&map[i].guid, guid, sizeof(GUID)))
+ {
+ *address = map[i].address;
+ return map[i].name;
+ }
+ }
+ *address = FALSE;
+ return guid2string(guid);
+}
+
+/**
+ * Print a host from raw data and IP version
+ */
+static void print_host(FWP_IP_VERSION version, void *data)
+{
+ host_t *host = NULL;
+ UINT32 ints[4];
+
+ switch (version)
+ {
+ case FWP_IP_VERSION_V4:
+ ints[0] = untoh32(data);
+ host = host_create_from_chunk(AF_INET, chunk_from_thing(ints[0]), 0);
+ break;
+ case FWP_IP_VERSION_V6:
+ ints[3] = untoh32(data);
+ ints[2] = untoh32(data + 4);
+ ints[1] = untoh32(data + 8);
+ ints[0] = untoh32(data + 12);
+ host = host_create_from_chunk(AF_INET6, chunk_from_thing(ints), 0);
+ break;
+ default:
+ break;
+ }
+ if (host)
+ {
+ printf("%H", host);
+ host->destroy(host);
+ }
+}
+
+/**
+ * Print IPSEC_SA_AUTH_INFORMATION0
+ */
+static void print_auth(IPSEC_SA_AUTH_INFORMATION0 *a)
+{
+ printf("%N-%N",
+ auth_type_names, a->authTransform.authTransformId.authType,
+ auth_config_names, a->authTransform.authTransformId.authConfig);
+}
+
+/**
+ * Print IPSEC_SA_CIPHER_INFORMATION0
+ */
+static void print_cipher(IPSEC_SA_CIPHER_INFORMATION0 *c)
+{
+ printf("%N-%N",
+ cipher_type_names, c->cipherTransform.cipherTransformId.cipherType,
+ cipher_config_names, c->cipherTransform.cipherTransformId.cipherConfig);
+}
+
+/**
+ * Print IPsec SA transform
+ */
+static void list_sa(HANDLE engine, IPSEC_SA0 *sa)
+{
+ printf(" SPI 0x%08x\n", sa->spi);
+ switch (sa->saTransformType)
+ {
+ case IPSEC_TRANSFORM_AH:
+ printf(" AH: ");
+ print_auth(sa->ahInformation);
+ break;
+ case IPSEC_TRANSFORM_ESP_AUTH:
+ printf(" ESP: ");
+ print_auth(sa->espAuthInformation);
+ break;
+ case IPSEC_TRANSFORM_ESP_CIPHER:
+ printf(" ESP: ");
+ print_cipher(sa->espCipherInformation);
+ break;
+ case IPSEC_TRANSFORM_ESP_AUTH_AND_CIPHER:
+ printf(" ESP: ");
+ print_auth(&sa->espAuthAndCipherInformation->saAuthInformation);
+ printf(", ");
+ print_cipher(&sa->espAuthAndCipherInformation->saCipherInformation);
+ break;
+ default:
+ printf(" (Transform %d)", sa->saTransformType);
+ break;
+ }
+ printf("\n");
+}
+
+/**
+ * List a filter condition value, optionally as IP address
+ */
+static void print_value(FWP_CONDITION_VALUE0 *value, bool address)
+{
+ chunk_t chunk;
+
+ switch (value->type)
+ {
+ case FWP_EMPTY:
+ printf("empty");
+ break;
+ case FWP_UINT8:
+ printf("%u", value->uint8);
+ break;
+ case FWP_UINT16:
+ printf("%u", value->uint16);
+ break;
+ case FWP_UINT32:
+ if (address)
+ {
+ print_host(FWP_IP_VERSION_V4, &value->uint32);
+ }
+ else
+ {
+ printf("%u", value->uint32);
+ }
+ break;
+ case FWP_UINT64:
+ printf("%llu", value->uint64);
+ break;
+ case FWP_INT8:
+ printf("%d", value->int8);
+ break;
+ case FWP_INT16:
+ printf("%d", value->int16);
+ break;
+ case FWP_INT32:
+ printf("%d", value->int32);
+ break;
+ case FWP_INT64:
+ printf("%lld", value->int64);
+ break;
+ case FWP_FLOAT:
+ printf("%f", value->float32);
+ break;
+ case FWP_DOUBLE:
+ printf("%lf", value->double64);
+ break;
+ case FWP_BYTE_ARRAY16_TYPE:
+ if (address)
+ {
+ print_host(FWP_IP_VERSION_V6, value->byteArray16);
+ }
+ else
+ {
+ chunk = chunk_create((u_char*)value->byteArray16, 16);
+ printf("%#B", &chunk);
+ }
+ break;
+ case FWP_BYTE_BLOB_TYPE:
+ chunk = chunk_create(value->byteBlob->data, value->byteBlob->size);
+ printf("%#B", &chunk);
+ break;
+ case FWP_V4_ADDR_MASK:
+ print_host(FWP_IP_VERSION_V4, &value->v4AddrMask->addr);
+ printf("/");
+ print_host(FWP_IP_VERSION_V4, &value->v4AddrMask->mask);
+ break;
+ case FWP_V6_ADDR_MASK:
+ print_host(FWP_IP_VERSION_V6, &value->v6AddrMask->addr);
+ printf("/%u", &value->v6AddrMask->prefixLength);
+ break;
+ case FWP_RANGE_TYPE:
+ print_value((FWP_CONDITION_VALUE0*)&value->rangeValue->valueLow,
+ address);
+ printf(" - ");
+ print_value((FWP_CONDITION_VALUE0*)&value->rangeValue->valueHigh,
+ address);
+ break;
+ default:
+ printf("(unsupported)");
+ break;
+ }
+}
+
+/**
+ * List a filter condition
+ */
+static void list_cond(HANDLE engine, FWPM_FILTER_CONDITION0 *cond)
+{
+ bool address;
+
+ printf(" '%s' %N '", cond2name(&cond->fieldKey, &address),
+ match_type_names, cond->matchType);
+ print_value(&cond->conditionValue, address);
+ printf("'\n");
+}
+
+/**
+ * Print IPsec SA details
+ */
+static void list_details(HANDLE engine, IPSEC_SA_DETAILS1 *details)
+{
+ int i;
+
+ printf(" %sbound SA: ",
+ details->saDirection == FWP_DIRECTION_INBOUND ? "In" : "Out");
+ print_host(details->traffic.ipVersion, &details->traffic.localV4Address);
+ printf(" %s ", details->saDirection == FWP_DIRECTION_INBOUND ? "<-" : "->");
+ print_host(details->traffic.ipVersion, &details->traffic.remoteV4Address);
+ printf("\n %N, flags: 0x%06x, lifetime: %us\n",
+ traffic_type_names, details->traffic.trafficType,
+ details->saBundle.flags, details->saBundle.lifetime.lifetimeSeconds);
+ if (details->udpEncapsulation)
+ {
+ printf(" UDP encap ports %u - %u\n",
+ details->udpEncapsulation->localUdpEncapPort,
+ details->udpEncapsulation->remoteUdpEncapPort);
+ }
+ for (i = 0; i < details->saBundle.numSAs; i++)
+ {
+ list_sa(engine, &details->saBundle.saList[i]);
+ }
+ printf(" Filter ID %llu\n", details->transportFilter->filterId);
+ for (i = 0; i < details->transportFilter->numFilterConditions; i++)
+ {
+ list_cond(engine, &details->transportFilter->filterCondition[i]);
+ }
+}
+
+/**
+ * List installed SA contexts
+ */
+static bool list_contexts(HANDLE engine)
+{
+ HANDLE handle;
+ UINT32 returned;
+ DWORD res;
+ IPSEC_SA_CONTEXT1 **entries;
+
+ res = IPsecSaContextCreateEnumHandle0(engine, NULL, &handle);
+ if (res != ERROR_SUCCESS)
+ {
+ fprintf(stderr, "IPsecSaContextCreateEnumHandle0(): 0x%08x\n", res);
+ return FALSE;
+ }
+
+ while (TRUE)
+ {
+ res = IPsecSaContextEnum1(engine, handle, 1, &entries, &returned);
+ if (res != ERROR_SUCCESS)
+ {
+ fprintf(stderr, "IPsecSaContextEnum1(): 0x%08x\n", res);
+ IPsecSaContextDestroyEnumHandle0(engine, handle);
+ return FALSE;
+ }
+ if (returned == 0)
+ {
+ break;
+ }
+
+ printf("SA context %llu:\n", entries[0]->saContextId);
+ list_details(engine, entries[0]->inboundSa);
+ list_details(engine, entries[0]->outboundSa);
+
+ FwpmFreeMemory0((void**)&entries);
+ }
+ IPsecSaContextDestroyEnumHandle0(engine, handle);
+ return TRUE;
+}
+
+const GUID FWPM_LAYER_IPSEC_KM_DEMUX_V4 = {
+ 0xf02b1526, 0xa459, 0x4a51, { 0xb9, 0xe3, 0x75, 0x9d, 0xe5, 0x2b, 0x9d, 0x2c }
+};
+const GUID FWPM_LAYER_IPSEC_KM_DEMUX_V6 = {
+ 0x2f755cf6, 0x2fd4, 0x4e88, { 0xb3, 0xe4, 0xa9, 0x1b, 0xca, 0x49, 0x52, 0x35 }
+};
+const GUID FWPM_LAYER_IPSEC_V4 = {
+ 0xeda65c74, 0x610d, 0x4bc5, { 0x94, 0x8f, 0x3c, 0x4f, 0x89, 0x55, 0x68, 0x67 }
+};
+const GUID FWPM_LAYER_IPSEC_V6 = {
+ 0x13c48442, 0x8d87, 0x4261, { 0x9a, 0x29, 0x59, 0xd2, 0xab, 0xc3, 0x48, 0xb4 }
+};
+const GUID FWPM_LAYER_IKEEXT_V4 = {
+ 0xb14b7bdb, 0xdbbd, 0x473e, { 0xbe, 0xd4, 0x8b, 0x47, 0x08, 0xd4, 0xf2, 0x70 }
+};
+const GUID FWPM_LAYER_IKEEXT_V6 = {
+ 0xb64786b3, 0xf687, 0x4eb9, { 0x89, 0xd2, 0x8e, 0xf3, 0x2a, 0xcd, 0xab, 0xe2 }
+};
+const GUID FWPM_LAYER_INBOUND_IPPACKET_V4 = {
+ 0xc86fd1bf, 0x21cd, 0x497e, { 0xa0, 0xbb, 0x17, 0x42, 0x5c, 0x88, 0x5c, 0x58 }
+};
+const GUID FWPM_LAYER_INBOUND_IPPACKET_V4_DISCARD = {
+ 0xb5a230d0, 0xa8c0, 0x44f2, { 0x91, 0x6e, 0x99, 0x1b, 0x53, 0xde, 0xd1, 0xf7 }
+};
+const GUID FWPM_LAYER_INBOUND_IPPACKET_V6 = {
+ 0xf52032cb, 0x991c, 0x46e7, { 0x97, 0x1d, 0x26, 0x01, 0x45, 0x9a, 0x91, 0xca }
+};
+const GUID FWPM_LAYER_INBOUND_IPPACKET_V6_DISCARD = {
+ 0xbb24c279, 0x93b4, 0x47a2, { 0x83, 0xad, 0xae, 0x16, 0x98, 0xb5, 0x08, 0x85 }
+};
+const GUID FWPM_LAYER_OUTBOUND_IPPACKET_V4 = {
+ 0x1e5c9fae, 0x8a84, 0x4135, { 0xa3, 0x31, 0x95, 0x0b, 0x54, 0x22, 0x9e, 0xcd }
+};
+const GUID FWPM_LAYER_OUTBOUND_IPPACKET_V4_DISCARD = {
+ 0x08e4bcb5, 0xb647, 0x48f3, { 0x95, 0x3c, 0xe5, 0xdd, 0xbd, 0x03, 0x93, 0x7e }
+};
+const GUID FWPM_LAYER_OUTBOUND_IPPACKET_V6 = {
+ 0xa3b3ab6b, 0x3564, 0x488c, { 0x91, 0x17, 0xf3, 0x4e, 0x82, 0x14, 0x27, 0x63 }
+};
+const GUID FWPM_LAYER_OUTBOUND_IPPACKET_V6_DISCARD = {
+ 0x9513d7c4, 0xa934, 0x49dc, { 0x91, 0xa7, 0x6c, 0xcb, 0x80, 0xcc, 0x02, 0xe3 }
+};
+const GUID FWPM_LAYER_IPFORWARD_V4_DISCARD = {
+ 0x9e9ea773, 0x2fae, 0x4210, { 0x8f, 0x17, 0x34, 0x12, 0x9e, 0xf3, 0x69, 0xeb }
+};
+const GUID FWPM_LAYER_IPFORWARD_V6_DISCARD = {
+ 0x31524a5d, 0x1dfe, 0x472f, { 0xbb, 0x93, 0x51, 0x8e, 0xe9, 0x45, 0xd8, 0xa2 }
+};
+const GUID FWPM_LAYER_INBOUND_TRANSPORT_V4_DISCARD = {
+ 0xac4a9833, 0xf69d, 0x4648, { 0xb2, 0x61, 0x6d, 0xc8, 0x48, 0x35, 0xef, 0x39 }
+};
+const GUID FWPM_LAYER_INBOUND_TRANSPORT_V6_DISCARD = {
+ 0x2a6ff955, 0x3b2b, 0x49d2, { 0x98, 0x48, 0xad, 0x9d, 0x72, 0xdc, 0xaa, 0xb7 }
+};
+const GUID FWPM_LAYER_OUTBOUND_TRANSPORT_V4_DISCARD = {
+ 0xc5f10551, 0xbdb0, 0x43d7, { 0xa3, 0x13, 0x50, 0xe2, 0x11, 0xf4, 0xd6, 0x8a }
+};
+const GUID FWPM_LAYER_OUTBOUND_TRANSPORT_V6_DISCARD = {
+ 0xf433df69, 0xccbd, 0x482e, { 0xb9, 0xb2, 0x57, 0x16, 0x56, 0x58, 0xc3, 0xb3 }
+};
+
+/**
+ * Convert filter layer GUID to name
+ */
+static char* layer2name(GUID *guid)
+{
+ struct {
+ GUID guid;
+ char *name;
+ } map[] = {
+ { FWPM_LAYER_IPSEC_KM_DEMUX_V4, "IPsec KM demux v4" },
+ { FWPM_LAYER_IPSEC_KM_DEMUX_V6, "IPsec KM demux v6" },
+ { FWPM_LAYER_IPSEC_V4, "IPsec v4" },
+ { FWPM_LAYER_IPSEC_V6, "IPsec v6" },
+ { FWPM_LAYER_IKEEXT_V4, "IKE ext v4" },
+ { FWPM_LAYER_IKEEXT_V6, "IKE ext v6" },
+ { FWPM_LAYER_INBOUND_IPPACKET_V4, "inbound v4" },
+ { FWPM_LAYER_INBOUND_IPPACKET_V4_DISCARD, "inbound v4 dsc" },
+ { FWPM_LAYER_INBOUND_IPPACKET_V6, "inbound v6" },
+ { FWPM_LAYER_INBOUND_IPPACKET_V6_DISCARD, "inbound v6 dsc" },
+ { FWPM_LAYER_OUTBOUND_IPPACKET_V4, "outbound v4" },
+ { FWPM_LAYER_OUTBOUND_IPPACKET_V4_DISCARD, "outbound v4 dsc" },
+ { FWPM_LAYER_OUTBOUND_IPPACKET_V6, "outbound v6" },
+ { FWPM_LAYER_OUTBOUND_IPPACKET_V6_DISCARD, "outbound v6 dsc" },
+ { FWPM_LAYER_IPFORWARD_V4, "forward v4" },
+ { FWPM_LAYER_IPFORWARD_V4_DISCARD, "forward v4 dsc" },
+ { FWPM_LAYER_IPFORWARD_V6, "forward v6" },
+ { FWPM_LAYER_IPFORWARD_V6_DISCARD, "forward v6 discard" },
+ { FWPM_LAYER_INBOUND_TRANSPORT_V4, "inbound transport v4" },
+ { FWPM_LAYER_INBOUND_TRANSPORT_V4_DISCARD, "inbound transport v4 dsc" },
+ { FWPM_LAYER_INBOUND_TRANSPORT_V6, "inbound transport v6" },
+ { FWPM_LAYER_INBOUND_TRANSPORT_V6_DISCARD, "inbound v6 transport dsc" },
+ { FWPM_LAYER_OUTBOUND_TRANSPORT_V4, "outbound transport v4" },
+ { FWPM_LAYER_OUTBOUND_TRANSPORT_V4_DISCARD, "outbound transport v4 dsc" },
+ { FWPM_LAYER_OUTBOUND_TRANSPORT_V6, "outbound transport v6" },
+ { FWPM_LAYER_OUTBOUND_TRANSPORT_V6_DISCARD, "outbound transport v6 dsc" },
+ };
+ int i;
+
+ for (i = 0; i < countof(map); i++)
+ {
+ if (memeq(&map[i].guid, guid, sizeof(GUID)))
+ {
+ return map[i].name;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Convert filter callout GUID to name
+ */
+static char* callout2name(GUID *guid)
+{
+ struct {
+ GUID guid;
+ char *name;
+ } map[] = {
+ { FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V4, "inbound transport v4" },
+ { FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V6, "inbound transport v6" },
+ { FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V4, "outbound transport v4" },
+ { FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V6, "outbound transport v6" },
+ { FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V4, "inbound tunnel v4" },
+ { FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V6, "inbound tunnel v6" },
+ { FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V4, "outbound tunnel v4" },
+ { FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V6, "outbound tunnel v6" },
+ { FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V4, "forward in tunnel v4" },
+ { FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V6, "forward in tunnel v6" },
+ { FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V4, "forward out tunnel v4" },
+ { FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V6, "forward out tunnel v6" },
+ };
+ int i;
+
+ for (i = 0; i < countof(map); i++)
+ {
+ if (memeq(&map[i].guid, guid, sizeof(GUID)))
+ {
+ return map[i].name;
+ }
+ }
+ return guid2string(guid);
+}
+
+/**
+ * Print display data with description
+ */
+static void print_display_data(FWPM_DISPLAY_DATA0 *data)
+{
+ char buf[128];
+
+ buf[0] = '\0';
+ if (data->name)
+ {
+ wcstombs(buf, data->name, sizeof(buf));
+ }
+ printf("%s", buf);
+ if (data->description)
+ {
+ buf[0] = '\0';
+ wcstombs(buf, data->description, sizeof(buf));
+ if (strlen(buf))
+ {
+ printf(" (%s)", buf);
+ }
+ }
+}
+
+/**
+ * List installed firewall filters
+ */
+static bool list_filters(HANDLE engine)
+{
+ HANDLE handle;
+ UINT32 returned;
+ DWORD res;
+ FWPM_FILTER0 **entries;
+ char *layer;
+ int i;
+
+ res = FwpmFilterCreateEnumHandle0(engine, NULL, &handle);
+ if (res != ERROR_SUCCESS)
+ {
+ fprintf(stderr, "FwpmFilterCreateEnumHandle0(): 0x%08x\n", res);
+ return FALSE;
+ }
+
+ while (TRUE)
+ {
+ res = FwpmFilterEnum0(engine, handle, 1, &entries, &returned);
+ if (res != ERROR_SUCCESS)
+ {
+ fprintf(stderr, "FwpmFilterEnum0(): 0x%08x\n", res);
+ FwpmFilterDestroyEnumHandle0(engine, handle);
+ return FALSE;
+ }
+ if (returned == 0)
+ {
+ break;
+ }
+
+ layer = layer2name(&entries[0]->layerKey);
+ if (layer)
+ {
+ printf("Filter ID %llu, '", entries[0]->filterId);
+ print_display_data(&entries[0]->displayData);
+ printf("'\n");
+ printf(" %s, ", layer);
+ if (entries[0]->effectiveWeight.type == FWP_UINT64)
+ {
+ printf("weight %016llx, ", *entries[0]->effectiveWeight.uint64);
+ }
+
+ switch (entries[0]->action.type)
+ {
+ case FWP_ACTION_BLOCK:
+ printf("block\n");
+ break;
+ case FWP_ACTION_PERMIT:
+ printf("permit\n");
+ break;
+ case FWP_ACTION_CALLOUT_TERMINATING:
+ printf("callout terminating: %s\n",
+ callout2name(&entries[0]->action.calloutKey));
+ break;
+ case FWP_ACTION_CALLOUT_INSPECTION:
+ printf("callout inspection: %s\n",
+ callout2name(&entries[0]->action.calloutKey));
+ break;
+ case FWP_ACTION_CALLOUT_UNKNOWN:
+ printf("callout unknown: %s\n",
+ callout2name(&entries[0]->action.calloutKey));
+ break;
+ default:
+ printf("(unknown action)\n");
+ break;
+ }
+ for (i = 0; i < entries[0]->numFilterConditions; i++)
+ {
+ list_cond(engine, &entries[0]->filterCondition[i]);
+ }
+ }
+ FwpmFreeMemory0((void**)&entries);
+ }
+ FwpmFilterDestroyEnumHandle0(engine, handle);
+ return TRUE;
+}
+
+/**
+ * ipsecdump main()
+ */
+int main(int argc, char *argv[])
+{
+ FWPM_SESSION0 session = {
+ .displayData = {
+ .name = L"ipsecdump",
+ .description = L"strongSwan SAD/SPD dumper",
+ },
+ };
+ HANDLE engine;
+ DWORD res;
+ int code;
+
+ library_init(NULL, "ipsecdump");
+ atexit(library_deinit);
+
+ res = FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, &session, &engine);
+ if (res != ERROR_SUCCESS)
+ {
+ fprintf(stderr, "FwpmEngineOpen(): 0x%08x\n", res);
+ return 2;
+ }
+ if (argc > 1 && streq(argv[1], "filters"))
+ {
+ code = list_filters(engine) ? 0 : 1;
+ }
+ else
+ {
+ code = list_contexts(engine) ? 0 : 1;
+ }
+ FwpmEngineClose0(engine);
+ return code;
+}
diff --git a/src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.c b/src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.c
new file mode 100644
index 000000000..41f85ba5c
--- /dev/null
+++ b/src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <library.h>
+
+const GUID FWPM_CONDITION_IP_REMOTE_ADDRESS = {
+ 0xb235ae9a, 0x1d64, 0x49b8, { 0xa4,0x4c,0x5f,0xf3,0xd9,0x09,0x50,0x45 }
+};
+const GUID FWPM_CONDITION_IP_LOCAL_ADDRESS = {
+ 0xd9ee00de, 0xc1ef, 0x4617, { 0xbf,0xe3,0xff,0xd8,0xf5,0xa0,0x89,0x57 }
+};
+const GUID FWPM_CONDITION_IP_SOURCE_ADDRESS = {
+ 0xae96897e, 0x2e94, 0x4bc9, { 0xb3,0x13,0xb2,0x7e,0xe8,0x0e,0x57,0x4d }
+};
+const GUID FWPM_CONDITION_IP_DESTINATION_ADDRESS = {
+ 0x2d79133b, 0xb390, 0x45c6, { 0x86,0x99,0xac,0xac,0xea,0xaf,0xed,0x33 }
+};
+const GUID FWPM_CONDITION_IP_LOCAL_PORT = {
+ 0x0c1ba1af, 0x5765, 0x453f, { 0xaf,0x22,0xa8,0xf7,0x91,0xac,0x77,0x5b }
+};
+const GUID FWPM_CONDITION_IP_REMOTE_PORT = {
+ 0xc35a604d, 0xd22b, 0x4e1a, { 0x91,0xb4,0x68,0xf6,0x74,0xee,0x67,0x4b }
+};
+const GUID FWPM_CONDITION_IP_PROTOCOL = {
+ 0x3971ef2b, 0x623e, 0x4f9a, { 0x8c,0xb1,0x6e,0x79,0xb8,0x06,0xb9,0xa7 }
+};
+const GUID FWPM_LAYER_INBOUND_TRANSPORT_V4 = {
+ 0x5926dfc8, 0xe3cf, 0x4426, { 0xa2,0x83,0xdc,0x39,0x3f,0x5d,0x0f,0x9d }
+};
+const GUID FWPM_LAYER_INBOUND_TRANSPORT_V6 = {
+ 0x634a869f, 0xfc23, 0x4b90, { 0xb0,0xc1,0xbf,0x62,0x0a,0x36,0xae,0x6f }
+};
+const GUID FWPM_LAYER_OUTBOUND_TRANSPORT_V4 = {
+ 0x09e61aea, 0xd214, 0x46e2, { 0x9b,0x21,0xb2,0x6b,0x0b,0x2f,0x28,0xc8 }
+};
+const GUID FWPM_LAYER_OUTBOUND_TRANSPORT_V6 = {
+ 0xe1735bde, 0x013f, 0x4655, { 0xb3,0x51,0xa4,0x9e,0x15,0x76,0x2d,0xf0 }
+};
+const GUID FWPM_LAYER_IPFORWARD_V4 = {
+ 0xa82acc24, 0x4ee1, 0x4ee1, { 0xb4,0x65,0xfd,0x1d,0x25,0xcb,0x10,0xa4}
+};
+const GUID FWPM_LAYER_IPFORWARD_V6 = {
+ 0x7b964818, 0x19c7, 0x493a, { 0xb7,0x1f,0x83,0x2c,0x36,0x84,0xd2,0x8c }
+};
+const GUID FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V4 = {
+ 0x5132900d, 0x5e84, 0x4b5f, { 0x80,0xe4,0x01,0x74,0x1e,0x81,0xff,0x10 }
+};
+const GUID FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V6 = {
+ 0x49d3ac92, 0x2a6c, 0x4dcf, { 0x95,0x5f,0x1c,0x3b,0xe0,0x09,0xdd,0x99 }
+};
+const GUID FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V4 = {
+ 0x4b46bf0a, 0x4523, 0x4e57, { 0xaa,0x38,0xa8,0x79,0x87,0xc9,0x10,0xd9 }
+};
+const GUID FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V6 = {
+ 0x38d87722, 0xad83, 0x4f11, { 0xa9,0x1f,0xdf,0x0f,0xb0,0x77,0x22,0x5b }
+};
+const GUID FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V4 = {
+ 0x191a8a46, 0x0bf8, 0x46cf, { 0xb0,0x45,0x4b,0x45,0xdf,0xa6,0xa3,0x24 }
+};
+const GUID FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V6 = {
+ 0x80c342e3, 0x1e53, 0x4d6f, { 0x9b,0x44,0x03,0xdf,0x5a,0xee,0xe1,0x54 }
+};
+const GUID FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V4 = {
+ 0x70a4196c, 0x835b, 0x4fb0, { 0x98,0xe8,0x07,0x5f,0x4d,0x97,0x7d,0x46 }
+};
+const GUID FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V6 = {
+ 0xf1835363, 0xa6a5, 0x4e62, { 0xb1,0x80,0x23,0xdb,0x78,0x9d,0x8d,0xa6 }
+};
+const GUID FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V4 = {
+ 0x28829633, 0xc4f0, 0x4e66, { 0x87,0x3f,0x84,0x4d,0xb2,0xa8,0x99,0xc7 }
+};
+const GUID FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V6 = {
+ 0xaf50bec2, 0xc686, 0x429a, { 0x88,0x4d,0xb7,0x44,0x43,0xe7,0xb0,0xb4 }
+};
+const GUID FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V4 = {
+ 0xfb532136, 0x15cb, 0x440b, { 0x93,0x7c,0x17,0x17,0xca,0x32,0x0c,0x40 }
+};
+const GUID FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V6 = {
+ 0xdae640cc, 0xe021, 0x4bee, { 0x9e,0xb6,0xa4,0x8b,0x27,0x5c,0x8c,0x1d }
+};
+
+/**
+ * Load a function symbol from a loaded dll
+ */
+static inline void *load_function(char *dll, char *name)
+{
+ HANDLE handle;
+ void *sym = NULL;
+
+ handle = GetModuleHandle(dll);
+ if (!handle)
+ {
+ return NULL;
+ }
+ sym = GetProcAddress(handle, name);
+ return sym;
+}
+
+/**
+ * Macro that defines a stub for a function that calls the same DLL function
+ *
+ * @param dll DLL to find function in
+ * @param ret return type of function
+ * @param name function name
+ * @param size size of all arguments on stack
+ * @param ... arguments of function
+ */
+#define STUB(dll, ret, name, size, ...) \
+ret WINAPI name(__VA_ARGS__) \
+{ \
+ static void (*fun)() = NULL; \
+ if (!fun) \
+ { \
+ fun = load_function(#dll, #name); \
+ } \
+ if (fun) \
+ { \
+ __builtin_return(__builtin_apply(fun, __builtin_apply_args(), size)); \
+ } \
+ return ERROR_NOT_SUPPORTED; \
+}
+
+STUB(fwpuclnt, DWORD, IPsecSaContextCreate1, 40,
+ HANDLE engineHandle, const void *outboundTraffic,
+ const void *virtualIfTunnelInfo, UINT64 *inboundFilterId, UINT64 *id)
+
+STUB(fwpuclnt, DWORD, IPsecSaContextSetSpi0, 32,
+ HANDLE engineHandle, UINT64 id, const void *getSpi, UINT32 inboundSpi)
+
+STUB(fwpuclnt, DWORD, IPsecSaContextGetById1, 24,
+ HANDLE engineHandle, UINT64 id, void **saContext)
+
+STUB(fwpuclnt, DWORD, IPsecSaContextUpdate0, 24,
+ HANDLE engineHandle, UINT32 flags, const void *newValues)
+
+STUB(fwpuclnt, DWORD, IPsecSaContextEnum1, 40,
+ HANDLE engineHandle, HANDLE enumHandle, UINT32 numEntriesRequested,
+ void ***entries, UINT32 *numEntriesReturned)
+
+STUB(fwpuclnt, DWORD, FwpmNetEventSubscribe0, 40,
+ HANDLE engineHandle, const void *subscription, void(*callback)(),
+ void *context, HANDLE *eventsHandle)
+
+STUB(fwpuclnt, DWORD, FwpmNetEventUnsubscribe0, 16,
+ HANDLE engineHandle, HANDLE eventsHandle)
diff --git a/src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.h b/src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.h
new file mode 100644
index 000000000..50a89a007
--- /dev/null
+++ b/src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup kernel_wfp_compat kernel_wfp_compat
+ * @{ @ingroup kernel_wfp
+ */
+
+#ifndef KERNEL_WFP_COMPAT_H_
+#define KERNEL_WFP_COMPAT_H_
+
+#include <winsock2.h>
+#include <windows.h>
+#include <ipsectypes.h>
+
+/* MinGW defines CIPHERs incorrectly starting at 0 */
+#define IPSEC_CIPHER_TYPE_DES 1
+#define IPSEC_CIPHER_TYPE_3DES 2
+#define IPSEC_CIPHER_TYPE_AES_128 3
+#define IPSEC_CIPHER_TYPE_AES_192 4
+#define IPSEC_CIPHER_TYPE_AES_256 5
+#define IPSEC_CIPHER_TYPE_MAX 6
+
+#include <fwpmtypes.h>
+#include <fwpmu.h>
+#undef interface
+
+/* MinGW defines TRANSFORMs incorrectly starting at 0 */
+#define IPSEC_TRANSFORM_AH 1
+#define IPSEC_TRANSFORM_ESP_AUTH 2
+#define IPSEC_TRANSFORM_ESP_CIPHER 3
+#define IPSEC_TRANSFORM_ESP_AUTH_AND_CIPHER 4
+#define IPSEC_TRANSFORM_ESP_AUTH_FW 5
+#define IPSEC_TRANSFORM_TYPE_MAX 6
+
+/* missing in MinGW */
+enum {
+ FWPM_TUNNEL_FLAG_POINT_TO_POINT = (1<<0),
+ FWPM_TUNNEL_FLAG_ENABLE_VIRTUAL_IF_TUNNELING = (1<<1),
+};
+
+/* missing in MinGW */
+enum {
+ IPSEC_SA_DETAILS_UPDATE_TRAFFIC = (1<<0),
+ IPSEC_SA_DETAILS_UPDATE_UDP_ENCAPSULATION = (1<<1),
+ IPSEC_SA_BUNDLE_UPDATE_FLAGS = (1<<2),
+ IPSEC_SA_BUNDLE_UPDATE_NAP_CONTEXT = (1<<3),
+ IPSEC_SA_BUNDLE_UPDATE_KEY_MODULE_STATE = (1<<4),
+ IPSEC_SA_BUNDLE_UPDATE_PEER_V4_PRIVATE_ADDRESS = (1<<5),
+ IPSEC_SA_BUNDLE_UPDATE_MM_SA_ID = (1<<6),
+};
+
+/* missing in MinGW */
+enum {
+ FWPM_NET_EVENT_FLAG_IP_PROTOCOL_SET = (1<<0),
+ FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET = (1<<1),
+ FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET = (1<<2),
+ FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET = (1<<3),
+ FWPM_NET_EVENT_FLAG_REMOTE_PORT_SET = (1<<4),
+ FWPM_NET_EVENT_FLAG_APP_ID_SET = (1<<5),
+ FWPM_NET_EVENT_FLAG_USER_ID_SET = (1<<6),
+ FWPM_NET_EVENT_FLAG_SCOPE_ID_SET = (1<<7),
+ FWPM_NET_EVENT_FLAG_IP_VERSION_SET = (1<<8),
+ FWPM_NET_EVENT_FLAG_REAUTH_REASON_SET = (1<<9),
+};
+
+/* missing in MinGW */
+enum {
+ FWPM_FILTER_FLAG_PERSISTENT = (1<<0),
+ FWPM_FILTER_FLAG_BOOTTIME = (1<<1),
+ FWPM_FILTER_FLAG_HAS_PROVIDER_CONTEXT = (1<<2),
+ FWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT = (1<<3),
+ FWPM_FILTER_FLAG_PERMIT_IF_CALLOUT_UNREGISTERED = (1<<4),
+ FWPM_FILTER_FLAG_DISABLED = (1<<5),
+};
+
+/* missing in MinGW */
+enum {
+ IPSEC_SA_BUNDLE_FLAG_ND_SECURE = (1<< 0),
+ IPSEC_SA_BUNDLE_FLAG_ND_BOUNDARY = (1<< 1),
+ IPSEC_SA_BUNDLE_FLAG_ND_PEER_NAT_BOUNDARY = (1<< 2),
+ IPSEC_SA_BUNDLE_FLAG_GUARANTEE_ENCRYPTION = (1<< 3),
+ IPSEC_SA_BUNDLE_FLAG_NLB = (1<< 4),
+ IPSEC_SA_BUNDLE_FLAG_NO_MACHINE_LUID_VERIFY = (1<< 5),
+ IPSEC_SA_BUNDLE_FLAG_NO_IMPERSONATION_LUID_VERIFY = (1<< 6),
+ IPSEC_SA_BUNDLE_FLAG_NO_EXPLICIT_CRED_MATCH = (1<< 7),
+ IPSEC_SA_BUNDLE_FLAG_ALLOW_NULL_TARGET_NAME_MATCH = (1<< 9),
+ IPSEC_SA_BUNDLE_FLAG_CLEAR_DF_ON_TUNNEL = (1<<10),
+ IPSEC_SA_BUNDLE_FLAG_ASSUME_UDP_CONTEXT_OUTBOUND = (1<<11),
+ IPSEC_SA_BUNDLE_FLAG_ND_PEER_BOUNDARY = (1<<12),
+ IPSEC_SA_BUNDLE_FLAG_SUPPRESS_DUPLICATE_DELETION = (1<<13),
+ IPSEC_SA_BUNDLE_FLAG_PEER_SUPPORTS_GUARANTEE_ENCRYPTION = (1<<14),
+ IPSEC_SA_BUNDLE_FLAG_FORCE_INBOUND_CONNECTIONS = (1<<15),
+ IPSEC_SA_BUNDLE_FLAG_FORCE_OUTBOUND_CONNECTIONS = (1<<16),
+ IPSEC_SA_BUNDLE_FLAG_FORWARD_PATH_INITIATOR = (1<<17),
+};
+
+/* missing in some MinGW versions */
+const GUID FWPM_CONDITION_IP_REMOTE_ADDRESS;
+const GUID FWPM_CONDITION_IP_LOCAL_ADDRESS;
+const GUID FWPM_CONDITION_IP_SOURCE_ADDRESS;
+const GUID FWPM_CONDITION_IP_DESTINATION_ADDRESS;
+const GUID FWPM_CONDITION_IP_LOCAL_PORT;
+const GUID FWPM_CONDITION_IP_REMOTE_PORT;
+const GUID FWPM_CONDITION_IP_PROTOCOL;
+#ifndef FWPM_CONDITION_ICMP_TYPE
+# define FWPM_CONDITION_ICMP_TYPE FWPM_CONDITION_IP_LOCAL_PORT
+#endif
+#ifndef FWPM_CONDITION_ICMP_CODE
+# define FWPM_CONDITION_ICMP_CODE FWPM_CONDITION_IP_REMOTE_PORT
+#endif
+const GUID FWPM_LAYER_INBOUND_TRANSPORT_V4;
+const GUID FWPM_LAYER_INBOUND_TRANSPORT_V6;
+const GUID FWPM_LAYER_OUTBOUND_TRANSPORT_V4;
+const GUID FWPM_LAYER_OUTBOUND_TRANSPORT_V6;
+const GUID FWPM_LAYER_IPFORWARD_V4;
+const GUID FWPM_LAYER_IPFORWARD_V6;
+const GUID FWPM_SUBLAYER_IPSEC_TUNNEL;
+const GUID FWPM_SUBLAYER_IPSEC_FORWARD_OUTBOUND_TUNNEL;
+const GUID FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V4;
+const GUID FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V6;
+const GUID FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V4;
+const GUID FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V6;
+const GUID FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V4;
+const GUID FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V6;
+const GUID FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V4;
+const GUID FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V6;
+const GUID FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V4;
+const GUID FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V6;
+const GUID FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V4;
+const GUID FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V6;
+
+/* integrity config, missing in some MinGW versions */
+#ifndef IPSEC_AUTH_CONFIG_HMAC_MD5_96
+enum {
+ IPSEC_AUTH_CONFIG_HMAC_MD5_96 = 0,
+ IPSEC_AUTH_CONFIG_HMAC_SHA_1_96,
+ IPSEC_AUTH_CONFIG_HMAC_SHA_256_128,
+ IPSEC_AUTH_CONFIG_GCM_AES_128,
+ IPSEC_AUTH_CONFIG_GCM_AES_192,
+ IPSEC_AUTH_CONFIG_GCM_AES_256,
+ IPSEC_AUTH_CONFIG_MAX
+};
+#define IPSEC_AUTH_TRANSFORM_ID_HMAC_MD5_96 { \
+ IPSEC_AUTH_MD5, IPSEC_AUTH_CONFIG_HMAC_MD5_96 }
+#define IPSEC_AUTH_TRANSFORM_ID_HMAC_SHA_1_96 { \
+ IPSEC_AUTH_SHA_1, IPSEC_AUTH_CONFIG_HMAC_SHA_1_96 }
+#define IPSEC_AUTH_TRANSFORM_ID_HMAC_SHA_256_128 { \
+ IPSEC_AUTH_SHA_256, IPSEC_AUTH_CONFIG_HMAC_SHA_256_128 }
+#define IPSEC_AUTH_TRANSFORM_ID_GCM_AES_128 { \
+ IPSEC_AUTH_AES_128, IPSEC_AUTH_CONFIG_GCM_AES_128 }
+#define IPSEC_AUTH_TRANSFORM_ID_GCM_AES_192 { \
+ IPSEC_AUTH_AES_192, IPSEC_AUTH_CONFIG_GCM_AES_192 }
+#define IPSEC_AUTH_TRANSFORM_ID_GCM_AES_256 { \
+ IPSEC_AUTH_AES_256, IPSEC_AUTH_CONFIG_GCM_AES_256 }
+#endif
+
+/* encryption config, missing in some MinGW versions */
+#ifndef IPSEC_CIPHER_CONFIG_CBC_DES
+enum {
+ IPSEC_CIPHER_CONFIG_CBC_DES = 1,
+ IPSEC_CIPHER_CONFIG_CBC_3DES,
+ IPSEC_CIPHER_CONFIG_CBC_AES_128,
+ IPSEC_CIPHER_CONFIG_CBC_AES_192,
+ IPSEC_CIPHER_CONFIG_CBC_AES_256,
+ IPSEC_CIPHER_CONFIG_GCM_AES_128,
+ IPSEC_CIPHER_CONFIG_GCM_AES_192,
+ IPSEC_CIPHER_CONFIG_GCM_AES_256,
+ IPSEC_CIPHER_CONFIG_MAX
+};
+#define IPSEC_CIPHER_TRANSFORM_ID_GCM_AES_128 { \
+ IPSEC_CIPHER_TYPE_AES_128, IPSEC_CIPHER_CONFIG_GCM_AES_128 }
+#define IPSEC_CIPHER_TRANSFORM_ID_GCM_AES_192 { \
+ IPSEC_CIPHER_TYPE_AES_192, IPSEC_CIPHER_CONFIG_GCM_AES_192 }
+#define IPSEC_CIPHER_TRANSFORM_ID_GCM_AES_256 { \
+ IPSEC_CIPHER_TYPE_AES_256, IPSEC_CIPHER_CONFIG_GCM_AES_256 }
+#define IPSEC_CIPHER_TRANSFORM_ID_CBC_DES { \
+ IPSEC_CIPHER_TYPE_DES, IPSEC_CIPHER_CONFIG_CBC_DES }
+#define IPSEC_CIPHER_TRANSFORM_ID_CBC_3DES { \
+ IPSEC_CIPHER_TYPE_3DES, IPSEC_CIPHER_CONFIG_CBC_3DES }
+#define IPSEC_CIPHER_TRANSFORM_ID_AES_128 { \
+ IPSEC_CIPHER_TYPE_AES_128, IPSEC_CIPHER_CONFIG_CBC_AES_128 }
+#define IPSEC_CIPHER_TRANSFORM_ID_AES_192 { \
+ IPSEC_CIPHER_TYPE_AES_192, IPSEC_CIPHER_CONFIG_CBC_AES_192 }
+#define IPSEC_CIPHER_TRANSFORM_ID_AES_256 { \
+ IPSEC_CIPHER_TYPE_AES_256, IPSEC_CIPHER_CONFIG_CBC_AES_256 }
+#endif
+
+DWORD WINAPI FwpmIPsecTunnelAdd0(HANDLE, UINT32,
+ const FWPM_PROVIDER_CONTEXT0*, const FWPM_PROVIDER_CONTEXT0*, UINT32,
+ const FWPM_FILTER_CONDITION0*, PSECURITY_DESCRIPTOR);
+
+#endif /** KERNEL_WFP_COMPAT_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c b/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c
new file mode 100644
index 000000000..c788bfb10
--- /dev/null
+++ b/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c
@@ -0,0 +1,2551 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/* Windows 7, for some fwpmu.h functionality */
+#define _WIN32_WINNT 0x0601
+
+#include "kernel_wfp_compat.h"
+#include "kernel_wfp_ipsec.h"
+
+#include <daemon.h>
+#include <hydra.h>
+#include <threading/mutex.h>
+#include <collections/array.h>
+#include <collections/hashtable.h>
+#include <processing/jobs/callback_job.h>
+
+
+typedef struct private_kernel_wfp_ipsec_t private_kernel_wfp_ipsec_t;
+
+struct private_kernel_wfp_ipsec_t {
+
+ /**
+ * Public interface
+ */
+ kernel_wfp_ipsec_t public;
+
+ /**
+ * Next SPI to allocate
+ */
+ refcount_t nextspi;
+
+ /**
+ * Mix value to distribute SPI allocation randomly
+ */
+ u_int32_t mixspi;
+
+ /**
+ * IKE bypass filters, as UINT64 filter LUID
+ */
+ array_t *bypass;
+
+ /**
+ * Temporary SAD/SPD entries referenced reqid, as uintptr_t => entry_t
+ */
+ hashtable_t *tsas;
+
+ /**
+ * SAD/SPD entries referenced by inbound SA, as sa_entry_t => entry_t
+ */
+ hashtable_t *isas;
+
+ /**
+ * SAD/SPD entries referenced by outbound SA, as sa_entry_t => entry_t
+ */
+ hashtable_t *osas;
+
+ /**
+ * Installed routes, as route_t => route_t
+ */
+ hashtable_t *routes;
+
+ /**
+ * Installed traps, as trap_t => trap_t
+ */
+ hashtable_t *traps;
+
+ /**
+ * Mutex for accessing entries
+ */
+ mutex_t *mutex;
+
+ /**
+ * WFP session handle
+ */
+ HANDLE handle;
+
+ /**
+ * Provider charon registers as
+ */
+ FWPM_PROVIDER0 provider;
+
+ /**
+ * Event handle
+ */
+ HANDLE event;
+};
+
+/**
+ * Security association entry
+ */
+typedef struct {
+ /** SPI for this SA */
+ u_int32_t spi;
+ /** protocol, IPPROTO_ESP/IPPROTO_AH */
+ u_int8_t protocol;
+ /** hard lifetime of SA */
+ u_int32_t lifetime;
+ /** destination host address for this SPI */
+ host_t *dst;
+ struct {
+ /** algorithm */
+ u_int16_t alg;
+ /** key */
+ chunk_t key;
+ } integ, encr;
+} sa_entry_t;
+
+/**
+ * Hash function for sas lookup table
+ */
+static u_int hash_sa(sa_entry_t *key)
+{
+ return chunk_hash_inc(chunk_from_thing(key->spi),
+ chunk_hash(key->dst->get_address(key->dst)));
+}
+
+/**
+ * equals function for sas lookup table
+ */
+static bool equals_sa(sa_entry_t *a, sa_entry_t *b)
+{
+ return a->spi == b->spi && a->dst->ip_equals(a->dst, b->dst);
+}
+
+/**
+ * Security policy entry
+ */
+typedef struct {
+ /** policy source addresses */
+ traffic_selector_t *src;
+ /** policy destinaiton addresses */
+ traffic_selector_t *dst;
+ /** WFP allocated LUID for inbound filter ID */
+ u_int64_t policy_in;
+ /** WFP allocated LUID for outbound filter ID */
+ u_int64_t policy_out;
+ /** WFP allocated LUID for forward inbound filter ID, tunnel mode only */
+ u_int64_t policy_fwd_in;
+ /** WFP allocated LUID for forward outbound filter ID, tunnel mode only */
+ u_int64_t policy_fwd_out;
+ /** have installed a route for it? */
+ bool route;
+} sp_entry_t;
+
+/**
+ * Destroy an SP entry
+ */
+static void sp_entry_destroy(sp_entry_t *sp)
+{
+ sp->src->destroy(sp->src);
+ sp->dst->destroy(sp->dst);
+ free(sp);
+}
+
+/**
+ * Collection of SA/SP database entries for a reqid
+ */
+typedef struct {
+ /** reqid of entry */
+ u_int32_t reqid;
+ /** outer address on local host */
+ host_t *local;
+ /** outer address on remote host */
+ host_t *remote;
+ /** inbound SA entry */
+ sa_entry_t isa;
+ /** outbound SA entry */
+ sa_entry_t osa;
+ /** associated (outbound) policies, as sp_entry_t* */
+ array_t *sps;
+ /** IPsec mode, tunnel|transport */
+ ipsec_mode_t mode;
+ /** UDP encapsulation */
+ bool encap;
+ /** provider context, for tunnel mode only */
+ u_int64_t provider;
+ /** WFP allocated LUID for SA context */
+ u_int64_t sa_id;
+} entry_t;
+
+/**
+ * Installed route
+ */
+typedef struct {
+ /** destination net of route */
+ host_t *dst;
+ /** prefix length of dst */
+ u_int8_t mask;
+ /** source address for route */
+ host_t *src;
+ /** gateway of route, NULL if directly attached */
+ host_t *gtw;
+ /** references for route */
+ u_int refs;
+} route_t;
+
+/**
+ * Destroy a route_t
+ */
+static void destroy_route(route_t *this)
+{
+ this->dst->destroy(this->dst);
+ this->src->destroy(this->src);
+ DESTROY_IF(this->gtw);
+ free(this);
+}
+
+/**
+ * Hashtable equals function for routes
+ */
+static bool equals_route(route_t *a, route_t *b)
+{
+ return a->mask == b->mask &&
+ a->dst->ip_equals(a->dst, b->dst) &&
+ a->src->ip_equals(a->src, b->src);
+}
+
+/**
+ * Hashtable hash function for routes
+ */
+static u_int hash_route(route_t *route)
+{
+ return chunk_hash_inc(route->src->get_address(route->src),
+ chunk_hash_inc(route->dst->get_address(route->dst), route->mask));
+}
+
+/** forward declaration */
+static bool manage_routes(private_kernel_wfp_ipsec_t *this, entry_t *entry,
+ bool add);
+
+/**
+ * Remove policies associated to an entry from kernel
+ */
+static void cleanup_policies(private_kernel_wfp_ipsec_t *this, entry_t *entry)
+{
+ enumerator_t *enumerator;
+ sp_entry_t *sp;
+
+ if (entry->mode == MODE_TUNNEL)
+ {
+ manage_routes(this, entry, FALSE);
+ }
+
+ enumerator = array_create_enumerator(entry->sps);
+ while (enumerator->enumerate(enumerator, &sp))
+ {
+ if (sp->policy_in)
+ {
+ FwpmFilterDeleteById0(this->handle, sp->policy_in);
+ sp->policy_in = 0;
+ }
+ if (sp->policy_out)
+ {
+ FwpmFilterDeleteById0(this->handle, sp->policy_out);
+ sp->policy_out = 0;
+ }
+ if (sp->policy_fwd_in)
+ {
+ FwpmFilterDeleteById0(this->handle, sp->policy_fwd_in);
+ sp->policy_fwd_in = 0;
+ }
+ if (sp->policy_fwd_out)
+ {
+ FwpmFilterDeleteById0(this->handle, sp->policy_fwd_out);
+ sp->policy_fwd_out = 0;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Destroy a SA/SP entry set
+ */
+static void entry_destroy(private_kernel_wfp_ipsec_t *this, entry_t *entry)
+{
+ if (entry->sa_id)
+ {
+ IPsecSaContextDeleteById0(this->handle, entry->sa_id);
+ }
+ if (entry->provider)
+ {
+ FwpmProviderContextDeleteById0(this->handle, entry->provider);
+ }
+ cleanup_policies(this, entry);
+ array_destroy_function(entry->sps, (void*)sp_entry_destroy, NULL);
+ entry->local->destroy(entry->local);
+ entry->remote->destroy(entry->remote);
+ chunk_clear(&entry->isa.integ.key);
+ chunk_clear(&entry->isa.encr.key);
+ chunk_clear(&entry->osa.integ.key);
+ chunk_clear(&entry->osa.encr.key);
+ free(entry);
+}
+
+/**
+ * Append/Realloc a filter condition to an existing condition set
+ */
+static FWPM_FILTER_CONDITION0 *append_condition(FWPM_FILTER_CONDITION0 *conds[],
+ int *count)
+{
+ FWPM_FILTER_CONDITION0 *cond;
+
+ (*count)++;
+ *conds = realloc(*conds, *count * sizeof(*cond));
+ cond = *conds + *count - 1;
+ memset(cond, 0, sizeof(*cond));
+
+ return cond;
+}
+
+/**
+ * Convert an IPv4 prefix to a host order subnet mask
+ */
+static u_int32_t prefix2mask(u_int8_t prefix)
+{
+ u_int8_t netmask[4] = {};
+ int i;
+
+ for (i = 0; i < sizeof(netmask); i++)
+ {
+ if (prefix < 8)
+ {
+ netmask[i] = 0xFF << (8 - prefix);
+ break;
+ }
+ netmask[i] = 0xFF;
+ prefix -= 8;
+ }
+ return untoh32(netmask);
+}
+
+/**
+ * Convert a 16-bit range to a WFP condition
+ */
+static void range2cond(FWPM_FILTER_CONDITION0 *cond,
+ u_int16_t from, u_int16_t to)
+{
+ if (from == to)
+ {
+ cond->matchType = FWP_MATCH_EQUAL;
+ cond->conditionValue.type = FWP_UINT16;
+ cond->conditionValue.uint16 = from;
+ }
+ else
+ {
+ cond->matchType = FWP_MATCH_RANGE;
+ cond->conditionValue.type = FWP_RANGE_TYPE;
+ cond->conditionValue.rangeValue = calloc(1, sizeof(FWP_RANGE0));
+ cond->conditionValue.rangeValue->valueLow.type = FWP_UINT16;
+ cond->conditionValue.rangeValue->valueLow.uint16 = from;
+ cond->conditionValue.rangeValue->valueHigh.type = FWP_UINT16;
+ cond->conditionValue.rangeValue->valueHigh.uint16 = to;
+ }
+}
+
+/**
+ * (Re-)allocate filter conditions for given local or remote traffic selector
+ */
+static bool ts2condition(traffic_selector_t *ts, const GUID *target,
+ FWPM_FILTER_CONDITION0 *conds[], int *count)
+{
+ FWPM_FILTER_CONDITION0 *cond;
+ FWP_BYTE_ARRAY16 *addr;
+ FWP_RANGE0 *range;
+ u_int16_t from_port, to_port;
+ void *from, *to;
+ u_int8_t proto;
+ host_t *net;
+ u_int8_t prefix;
+
+ from = ts->get_from_address(ts).ptr;
+ to = ts->get_to_address(ts).ptr;
+ from_port = ts->get_from_port(ts);
+ to_port = ts->get_to_port(ts);
+
+ cond = append_condition(conds, count);
+ cond->fieldKey = *target;
+ if (ts->is_host(ts, NULL))
+ {
+ cond->matchType = FWP_MATCH_EQUAL;
+ switch (ts->get_type(ts))
+ {
+ case TS_IPV4_ADDR_RANGE:
+ cond->conditionValue.type = FWP_UINT32;
+ cond->conditionValue.uint32 = untoh32(from);
+ break;
+ case TS_IPV6_ADDR_RANGE:
+ cond->conditionValue.type = FWP_BYTE_ARRAY16_TYPE;
+ cond->conditionValue.byteArray16 = addr = malloc(sizeof(*addr));
+ memcpy(addr, from, sizeof(*addr));
+ break;
+ default:
+ return FALSE;
+ }
+ }
+ else if (ts->to_subnet(ts, &net, &prefix))
+ {
+ FWP_V6_ADDR_AND_MASK *m6;
+ FWP_V4_ADDR_AND_MASK *m4;
+
+ cond->matchType = FWP_MATCH_EQUAL;
+ switch (net->get_family(net))
+ {
+ case AF_INET:
+ cond->conditionValue.type = FWP_V4_ADDR_MASK;
+ cond->conditionValue.v4AddrMask = m4 = calloc(1, sizeof(*m4));
+ m4->addr = untoh32(from);
+ m4->mask = prefix2mask(prefix);
+ break;
+ case AF_INET6:
+ cond->conditionValue.type = FWP_V6_ADDR_MASK;
+ cond->conditionValue.v6AddrMask = m6 = calloc(1, sizeof(*m6));
+ memcpy(m6->addr, from, sizeof(m6->addr));
+ m6->prefixLength = prefix;
+ break;
+ default:
+ net->destroy(net);
+ return FALSE;
+ }
+ net->destroy(net);
+ }
+ else
+ {
+ cond->matchType = FWP_MATCH_RANGE;
+ cond->conditionValue.type = FWP_RANGE_TYPE;
+ cond->conditionValue.rangeValue = range = calloc(1, sizeof(*range));
+ switch (ts->get_type(ts))
+ {
+ case TS_IPV4_ADDR_RANGE:
+ range->valueLow.type = FWP_UINT32;
+ range->valueLow.uint32 = untoh32(from);
+ range->valueHigh.type = FWP_UINT32;
+ range->valueHigh.uint32 = untoh32(to);
+ break;
+ case TS_IPV6_ADDR_RANGE:
+ range->valueLow.type = FWP_BYTE_ARRAY16_TYPE;
+ range->valueLow.byteArray16 = addr = malloc(sizeof(*addr));
+ memcpy(addr, from, sizeof(*addr));
+ range->valueHigh.type = FWP_BYTE_ARRAY16_TYPE;
+ range->valueHigh.byteArray16 = addr = malloc(sizeof(*addr));
+ memcpy(addr, to, sizeof(*addr));
+ break;
+ default:
+ return FALSE;
+ }
+ }
+
+ proto = ts->get_protocol(ts);
+ if (proto && target == &FWPM_CONDITION_IP_LOCAL_ADDRESS)
+ {
+ cond = append_condition(conds, count);
+ cond->fieldKey = FWPM_CONDITION_IP_PROTOCOL;
+ cond->matchType = FWP_MATCH_EQUAL;
+ cond->conditionValue.type = FWP_UINT8;
+ cond->conditionValue.uint8 = proto;
+ }
+
+ if (proto == IPPROTO_ICMP)
+ {
+ if (target == &FWPM_CONDITION_IP_LOCAL_ADDRESS)
+ {
+ u_int8_t from_type, to_type, from_code, to_code;
+
+ from_type = traffic_selector_icmp_type(from_port);
+ to_type = traffic_selector_icmp_type(to_port);
+ from_code = traffic_selector_icmp_code(from_port);
+ to_code = traffic_selector_icmp_code(to_port);
+
+ if (from_type != 0 || to_type != 0xFF)
+ {
+ cond = append_condition(conds, count);
+ cond->fieldKey = FWPM_CONDITION_ICMP_TYPE;
+ range2cond(cond, from_type, to_type);
+ }
+ if (from_code != 0 || to_code != 0xFF)
+ {
+ cond = append_condition(conds, count);
+ cond->fieldKey = FWPM_CONDITION_ICMP_CODE;
+ range2cond(cond, from_code, to_code);
+ }
+ }
+ }
+ else if (from_port != 0 || to_port != 0xFFFF)
+ {
+ if (target == &FWPM_CONDITION_IP_LOCAL_ADDRESS)
+ {
+ cond = append_condition(conds, count);
+ cond->fieldKey = FWPM_CONDITION_IP_LOCAL_PORT;
+ range2cond(cond, from_port, to_port);
+ }
+ if (target == &FWPM_CONDITION_IP_REMOTE_ADDRESS)
+ {
+ cond = append_condition(conds, count);
+ cond->fieldKey = FWPM_CONDITION_IP_REMOTE_PORT;
+ range2cond(cond, from_port, to_port);
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Free memory associated to a single condition
+ */
+static void free_condition(FWP_DATA_TYPE type, void *value)
+{
+ FWP_RANGE0 *range;
+
+ switch (type)
+ {
+ case FWP_BYTE_ARRAY16_TYPE:
+ case FWP_V4_ADDR_MASK:
+ case FWP_V6_ADDR_MASK:
+ free(value);
+ break;
+ case FWP_RANGE_TYPE:
+ range = value;
+ free_condition(range->valueLow.type, range->valueLow.sd);
+ free_condition(range->valueHigh.type, range->valueHigh.sd);
+ free(range);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Free memory used by a set of conditions
+ */
+static void free_conditions(FWPM_FILTER_CONDITION0 *conds, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ {
+ free_condition(conds[i].conditionValue.type, conds[i].conditionValue.sd);
+ }
+ free(conds);
+}
+
+/**
+ * Find the callout GUID for given parameters
+ */
+static bool find_callout(bool tunnel, bool v6, bool inbound, bool forward,
+ GUID *layer, GUID *sublayer, GUID *callout)
+{
+ struct {
+ bool tunnel;
+ bool v6;
+ bool inbound;
+ bool forward;
+ const GUID *layer;
+ const GUID *sublayer;
+ const GUID *callout;
+ } map[] = {
+ { 0, 0, 0, 0, &FWPM_LAYER_OUTBOUND_TRANSPORT_V4, NULL,
+ &FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V4 },
+ { 0, 0, 1, 0, &FWPM_LAYER_INBOUND_TRANSPORT_V4, NULL,
+ &FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V4 },
+ { 0, 1, 0, 0, &FWPM_LAYER_OUTBOUND_TRANSPORT_V6, NULL,
+ &FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V6 },
+ { 0, 1, 1, 0, &FWPM_LAYER_INBOUND_TRANSPORT_V6, NULL,
+ &FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V6 },
+ { 1, 0, 0, 0, &FWPM_LAYER_OUTBOUND_TRANSPORT_V4,
+ &FWPM_SUBLAYER_IPSEC_TUNNEL,
+ &FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V4 },
+ { 1, 0, 0, 1, &FWPM_LAYER_IPFORWARD_V4,
+ &FWPM_SUBLAYER_IPSEC_FORWARD_OUTBOUND_TUNNEL,
+ &FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V4 },
+ { 1, 0, 1, 0, &FWPM_LAYER_INBOUND_TRANSPORT_V4,
+ &FWPM_SUBLAYER_IPSEC_TUNNEL,
+ &FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V4 },
+ { 1, 0, 1, 1, &FWPM_LAYER_IPFORWARD_V4,
+ &FWPM_SUBLAYER_IPSEC_TUNNEL,
+ &FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V4 },
+ { 1, 1, 0, 0, &FWPM_LAYER_OUTBOUND_TRANSPORT_V6,
+ &FWPM_SUBLAYER_IPSEC_TUNNEL,
+ &FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V6 },
+ { 1, 1, 0, 1, &FWPM_LAYER_IPFORWARD_V6,
+ &FWPM_SUBLAYER_IPSEC_TUNNEL,
+ &FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V6 },
+ { 1, 1, 1, 0, &FWPM_LAYER_INBOUND_TRANSPORT_V6,
+ &FWPM_SUBLAYER_IPSEC_TUNNEL,
+ &FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V6 },
+ { 1, 1, 1, 1, &FWPM_LAYER_IPFORWARD_V6,
+ &FWPM_SUBLAYER_IPSEC_TUNNEL,
+ &FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V6 },
+ };
+ int i;
+
+ for (i = 0; i < countof(map); i++)
+ {
+ if (tunnel == map[i].tunnel &&
+ v6 == map[i].v6 &&
+ inbound == map[i].inbound &&
+ forward == map[i].forward)
+ {
+ *callout = *map[i].callout;
+ *layer = *map[i].layer;
+ if (map[i].sublayer)
+ {
+ *sublayer = *map[i].sublayer;
+ }
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * Install a single policy in to the kernel
+ */
+static bool install_sp(private_kernel_wfp_ipsec_t *this, sp_entry_t *sp,
+ GUID *context, bool inbound, bool fwd, UINT64 *filter_id)
+{
+ FWPM_FILTER_CONDITION0 *conds = NULL;
+ traffic_selector_t *local, *remote;
+ const GUID *ltarget, *rtarget;
+ int count = 0;
+ bool v6;
+ DWORD res;
+ FWPM_FILTER0 filter = {
+ .displayData = {
+ .name = L"charon IPsec policy",
+ },
+ .action = {
+ .type = FWP_ACTION_CALLOUT_TERMINATING,
+ },
+ };
+
+ if (context)
+ {
+ filter.flags |= FWPM_FILTER_FLAG_HAS_PROVIDER_CONTEXT;
+ filter.providerKey = (GUID*)&this->provider.providerKey;
+ filter.providerContextKey = *context;
+ }
+
+ v6 = sp->src->get_type(sp->src) == TS_IPV6_ADDR_RANGE;
+ if (!find_callout(context != NULL, v6, inbound, fwd,
+ &filter.layerKey, &filter.subLayerKey,
+ &filter.action.calloutKey))
+ {
+ return FALSE;
+ }
+
+ if (inbound && fwd)
+ {
+ local = sp->dst;
+ remote = sp->src;
+ }
+ else
+ {
+ local = sp->src;
+ remote = sp->dst;
+ }
+ if (fwd)
+ {
+ ltarget = &FWPM_CONDITION_IP_SOURCE_ADDRESS;
+ rtarget = &FWPM_CONDITION_IP_DESTINATION_ADDRESS;
+ }
+ else
+ {
+ ltarget = &FWPM_CONDITION_IP_LOCAL_ADDRESS;
+ rtarget = &FWPM_CONDITION_IP_REMOTE_ADDRESS;
+ }
+ if (!ts2condition(local, ltarget, &conds, &count) ||
+ !ts2condition(remote, rtarget, &conds, &count))
+ {
+ free_conditions(conds, count);
+ return FALSE;
+ }
+
+ filter.numFilterConditions = count;
+ filter.filterCondition = conds;
+
+ res = FwpmFilterAdd0(this->handle, &filter, NULL, filter_id);
+ free_conditions(conds, count);
+ if (res != ERROR_SUCCESS)
+ {
+ DBG1(DBG_KNL, "installing %s%sbound WFP filter failed: 0x%08x",
+ fwd ? "forward " : "", inbound ? "in" : "out", res);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Install a set of policies in to the kernel
+ */
+static bool install_sps(private_kernel_wfp_ipsec_t *this,
+ entry_t *entry, GUID *context)
+{
+ enumerator_t *enumerator;
+ sp_entry_t *sp;
+
+ enumerator = array_create_enumerator(entry->sps);
+ while (enumerator->enumerate(enumerator, &sp))
+ {
+ /* inbound policy */
+ if (!install_sp(this, sp, context, TRUE, FALSE, &sp->policy_in))
+ {
+ enumerator->destroy(enumerator);
+ return FALSE;
+ }
+ /* outbound policy */
+ if (!install_sp(this, sp, context, FALSE, FALSE, &sp->policy_out))
+ {
+ enumerator->destroy(enumerator);
+ return FALSE;
+ }
+ if (context)
+ {
+ if (!sp->src->is_host(sp->src, entry->local) ||
+ !sp->dst->is_host(sp->dst, entry->remote))
+ {
+ /* inbound forward policy, from decapsulation */
+ if (!install_sp(this, sp, context,
+ TRUE, TRUE, &sp->policy_fwd_in))
+ {
+ enumerator->destroy(enumerator);
+ return FALSE;
+ }
+ /* outbound forward policy, to encapsulate */
+ if (!install_sp(this, sp, context,
+ FALSE, TRUE, &sp->policy_fwd_out))
+ {
+ enumerator->destroy(enumerator);
+ return FALSE;
+ }
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return TRUE;
+}
+
+/**
+ * Convert a chunk_t to a WFP FWP_BYTE_BLOB
+ */
+static inline FWP_BYTE_BLOB chunk2blob(chunk_t chunk)
+{
+ return (FWP_BYTE_BLOB){
+ .size = chunk.len,
+ .data = chunk.ptr,
+ };
+}
+
+/**
+ * Convert an integrity_algorithm_t to a WFP IPSEC_AUTH_TRANFORM_ID0
+ */
+static bool alg2auth(integrity_algorithm_t alg,
+ IPSEC_SA_AUTH_INFORMATION0 *info)
+{
+ struct {
+ integrity_algorithm_t alg;
+ IPSEC_AUTH_TRANSFORM_ID0 transform;
+ } map[] = {
+ { AUTH_HMAC_MD5_96, IPSEC_AUTH_TRANSFORM_ID_HMAC_MD5_96 },
+ { AUTH_HMAC_SHA1_96, IPSEC_AUTH_TRANSFORM_ID_HMAC_SHA_1_96 },
+ { AUTH_HMAC_SHA2_256_128, IPSEC_AUTH_TRANSFORM_ID_HMAC_SHA_256_128},
+ { AUTH_AES_128_GMAC, IPSEC_AUTH_TRANSFORM_ID_GCM_AES_128 },
+ { AUTH_AES_192_GMAC, IPSEC_AUTH_TRANSFORM_ID_GCM_AES_192 },
+ { AUTH_AES_256_GMAC, IPSEC_AUTH_TRANSFORM_ID_GCM_AES_256 },
+ };
+ int i;
+
+ for (i = 0; i < countof(map); i++)
+ {
+ if (map[i].alg == alg)
+ {
+ info->authTransform.authTransformId = map[i].transform;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * Convert an encryption_algorithm_t to a WFP IPSEC_CIPHER_TRANFORM_ID0
+ */
+static bool alg2cipher(encryption_algorithm_t alg, int keylen,
+ IPSEC_SA_CIPHER_INFORMATION0 *info)
+{
+ struct {
+ encryption_algorithm_t alg;
+ int keylen;
+ IPSEC_CIPHER_TRANSFORM_ID0 transform;
+ } map[] = {
+ { ENCR_DES, 8, IPSEC_CIPHER_TRANSFORM_ID_CBC_DES },
+ { ENCR_3DES, 24, IPSEC_CIPHER_TRANSFORM_ID_CBC_3DES },
+ { ENCR_AES_CBC, 16, IPSEC_CIPHER_TRANSFORM_ID_AES_128 },
+ { ENCR_AES_CBC, 24, IPSEC_CIPHER_TRANSFORM_ID_AES_192 },
+ { ENCR_AES_CBC, 32, IPSEC_CIPHER_TRANSFORM_ID_AES_256 },
+ { ENCR_AES_GCM_ICV16, 20, IPSEC_CIPHER_TRANSFORM_ID_GCM_AES_128 },
+ { ENCR_AES_GCM_ICV16, 28, IPSEC_CIPHER_TRANSFORM_ID_GCM_AES_192 },
+ { ENCR_AES_GCM_ICV16, 36, IPSEC_CIPHER_TRANSFORM_ID_GCM_AES_256 },
+ };
+ int i;
+
+ for (i = 0; i < countof(map); i++)
+ {
+ if (map[i].alg == alg && map[i].keylen == keylen)
+ {
+ info->cipherTransform.cipherTransformId = map[i].transform;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * Get the integrity algorithm used for an AEAD transform
+ */
+static integrity_algorithm_t encr2integ(encryption_algorithm_t encr, int keylen)
+{
+ struct {
+ encryption_algorithm_t encr;
+ int keylen;
+ integrity_algorithm_t integ;
+ } map[] = {
+ { ENCR_NULL_AUTH_AES_GMAC, 20, AUTH_AES_128_GMAC },
+ { ENCR_NULL_AUTH_AES_GMAC, 28, AUTH_AES_192_GMAC },
+ { ENCR_NULL_AUTH_AES_GMAC, 36, AUTH_AES_256_GMAC },
+ { ENCR_AES_GCM_ICV16, 20, AUTH_AES_128_GMAC },
+ { ENCR_AES_GCM_ICV16, 28, AUTH_AES_192_GMAC },
+ { ENCR_AES_GCM_ICV16, 36, AUTH_AES_256_GMAC },
+ };
+ int i;
+
+ for (i = 0; i < countof(map); i++)
+ {
+ if (map[i].encr == encr && map[i].keylen == keylen)
+ {
+ return map[i].integ;
+ }
+ }
+ return AUTH_UNDEFINED;
+}
+
+/**
+ * Install a single SA
+ */
+static bool install_sa(private_kernel_wfp_ipsec_t *this, entry_t *entry,
+ bool inbound, sa_entry_t *sa, FWP_IP_VERSION version)
+{
+ IPSEC_SA_AUTH_AND_CIPHER_INFORMATION0 info = {};
+ IPSEC_SA0 ipsec = {
+ .spi = ntohl(sa->spi),
+ };
+ IPSEC_SA_BUNDLE0 bundle = {
+ .lifetime = {
+ .lifetimeSeconds = inbound ? entry->isa.lifetime
+ : entry->osa.lifetime,
+ },
+ .saList = &ipsec,
+ .numSAs = 1,
+ .ipVersion = version,
+ };
+ struct {
+ u_int16_t alg;
+ chunk_t key;
+ } integ = {}, encr = {};
+ DWORD res;
+
+ switch (sa->protocol)
+ {
+ case IPPROTO_AH:
+ ipsec.saTransformType = IPSEC_TRANSFORM_AH;
+ ipsec.ahInformation = &info.saAuthInformation;
+ integ.key = sa->integ.key;
+ integ.alg = sa->integ.alg;
+ break;
+ case IPPROTO_ESP:
+ if (sa->encr.alg == ENCR_NULL ||
+ sa->encr.alg == ENCR_NULL_AUTH_AES_GMAC)
+ {
+ ipsec.saTransformType = IPSEC_TRANSFORM_ESP_AUTH;
+ ipsec.espAuthInformation = &info.saAuthInformation;
+ }
+ else
+ {
+ ipsec.saTransformType = IPSEC_TRANSFORM_ESP_AUTH_AND_CIPHER;
+ ipsec.espAuthAndCipherInformation = &info;
+ encr.key = sa->encr.key;
+ encr.alg = sa->encr.alg;
+ }
+ if (encryption_algorithm_is_aead(sa->encr.alg))
+ {
+ integ.alg = encr2integ(sa->encr.alg, sa->encr.key.len);
+ integ.key = sa->encr.key;
+ }
+ else
+ {
+ integ.alg = sa->integ.alg;
+ integ.key = sa->integ.key;
+ }
+ break;
+ default:
+ return FALSE;
+ }
+
+ if (integ.alg)
+ {
+ info.saAuthInformation.authKey = chunk2blob(integ.key);
+ if (!alg2auth(integ.alg, &info.saAuthInformation))
+ {
+ DBG1(DBG_KNL, "integrity algorithm %N not supported by WFP",
+ integrity_algorithm_names, integ.alg);
+ return FALSE;
+ }
+ }
+ if (encr.alg)
+ {
+ info.saCipherInformation.cipherKey = chunk2blob(encr.key);
+ if (!alg2cipher(encr.alg, encr.key.len, &info.saCipherInformation))
+ {
+ DBG1(DBG_KNL, "encryption algorithm %N not supported by WFP",
+ encryption_algorithm_names, encr.alg);
+ return FALSE;
+ }
+ }
+
+ if (inbound)
+ {
+ res = IPsecSaContextAddInbound0(this->handle, entry->sa_id, &bundle);
+ }
+ else
+ {
+ bundle.flags |= IPSEC_SA_BUNDLE_FLAG_ASSUME_UDP_CONTEXT_OUTBOUND;
+ res = IPsecSaContextAddOutbound0(this->handle, entry->sa_id, &bundle);
+ }
+ if (res != ERROR_SUCCESS)
+ {
+ DBG1(DBG_KNL, "adding %sbound WFP SA failed: 0x%08x",
+ inbound ? "in" : "out", res);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Convert an IPv6 host address to WFP representation
+ */
+static void host2address6(host_t *host, void *out)
+{
+ u_int32_t *src, *dst = out;
+
+ src = (u_int32_t*)host->get_address(host).ptr;
+
+ dst[0] = untoh32(&src[3]);
+ dst[1] = untoh32(&src[2]);
+ dst[2] = untoh32(&src[1]);
+ dst[3] = untoh32(&src[0]);
+}
+
+/**
+ * Fill in traffic structure from entry addresses
+ */
+static bool hosts2traffic(private_kernel_wfp_ipsec_t *this,
+ host_t *l, host_t *r, IPSEC_TRAFFIC1 *traffic)
+{
+ if (l->get_family(l) != r->get_family(r))
+ {
+ return FALSE;
+ }
+ switch (l->get_family(l))
+ {
+ case AF_INET:
+ traffic->ipVersion = FWP_IP_VERSION_V4;
+ traffic->localV4Address = untoh32(l->get_address(l).ptr);
+ traffic->remoteV4Address = untoh32(r->get_address(r).ptr);
+ return TRUE;
+ case AF_INET6:
+ traffic->ipVersion = FWP_IP_VERSION_V6;
+ host2address6(l, &traffic->localV6Address);
+ host2address6(r, &traffic->remoteV6Address);
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+/**
+ * Install SAs to the kernel
+ */
+static bool install_sas(private_kernel_wfp_ipsec_t *this, entry_t *entry,
+ IPSEC_TRAFFIC_TYPE type)
+{
+ IPSEC_TRAFFIC1 traffic = {
+ .trafficType = type,
+ };
+ IPSEC_GETSPI1 spi = {
+ .inboundIpsecTraffic = {
+ .trafficType = type,
+ },
+ };
+ enumerator_t *enumerator;
+ sp_entry_t *sp;
+ DWORD res;
+
+ if (type == IPSEC_TRAFFIC_TYPE_TRANSPORT)
+ {
+ enumerator = array_create_enumerator(entry->sps);
+ if (enumerator->enumerate(enumerator, &sp))
+ {
+ traffic.ipsecFilterId = sp->policy_out;
+ spi.inboundIpsecTraffic.ipsecFilterId = sp->policy_in;
+ }
+ else
+ {
+ enumerator->destroy(enumerator);
+ return FALSE;
+ }
+ enumerator->destroy(enumerator);
+ }
+ else
+ {
+ traffic.tunnelPolicyId = entry->provider;
+ spi.inboundIpsecTraffic.tunnelPolicyId = entry->provider;
+ }
+
+ if (!hosts2traffic(this, entry->local, entry->remote, &traffic))
+ {
+ return FALSE;
+ }
+
+ res = IPsecSaContextCreate1(this->handle, &traffic, NULL, NULL,
+ &entry->sa_id);
+ if (res != ERROR_SUCCESS)
+ {
+ DBG1(DBG_KNL, "creating WFP SA context failed: 0x%08x", res);
+ return FALSE;
+ }
+
+ memcpy(spi.inboundIpsecTraffic.localV6Address, traffic.localV6Address,
+ sizeof(traffic.localV6Address));
+ memcpy(spi.inboundIpsecTraffic.remoteV6Address, traffic.remoteV6Address,
+ sizeof(traffic.remoteV6Address));
+ spi.ipVersion = traffic.ipVersion;
+
+ res = IPsecSaContextSetSpi0(this->handle, entry->sa_id, &spi,
+ ntohl(entry->isa.spi));
+ if (res != ERROR_SUCCESS)
+ {
+ DBG1(DBG_KNL, "setting WFP SA SPI failed: 0x%08x", res);
+ IPsecSaContextDeleteById0(this->handle, entry->sa_id);
+ entry->sa_id = 0;
+ return FALSE;
+ }
+
+ if (!install_sa(this, entry, TRUE, &entry->isa, spi.ipVersion) ||
+ !install_sa(this, entry, FALSE, &entry->osa, spi.ipVersion))
+ {
+ IPsecSaContextDeleteById0(this->handle, entry->sa_id);
+ entry->sa_id = 0;
+ return FALSE;
+ }
+
+ if (entry->encap)
+ {
+ IPSEC_V4_UDP_ENCAPSULATION0 encap = {
+ .localUdpEncapPort = entry->local->get_port(entry->local),
+ .remoteUdpEncapPort = entry->remote->get_port(entry->remote),
+ };
+ IPSEC_SA_CONTEXT1 *ctx;
+
+ res = IPsecSaContextGetById1(this->handle, entry->sa_id, &ctx);
+ if (res != ERROR_SUCCESS)
+ {
+ DBG1(DBG_KNL, "getting WFP SA for UDP encap failed: 0x%08x", res);
+ IPsecSaContextDeleteById0(this->handle, entry->sa_id);
+ entry->sa_id = 0;
+ return FALSE;
+ }
+ ctx->inboundSa->udpEncapsulation = &encap;
+ ctx->outboundSa->udpEncapsulation = &encap;
+
+ res = IPsecSaContextUpdate0(this->handle,
+ IPSEC_SA_DETAILS_UPDATE_UDP_ENCAPSULATION, ctx);
+ FwpmFreeMemory0((void**)&ctx);
+ if (res != ERROR_SUCCESS)
+ {
+ DBG1(DBG_KNL, "enable WFP UDP encap failed: 0x%08x", res);
+ IPsecSaContextDeleteById0(this->handle, entry->sa_id);
+ entry->sa_id = 0;
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * Install a transport mode SA/SP set to the kernel
+ */
+static bool install_transport(private_kernel_wfp_ipsec_t *this, entry_t *entry)
+{
+ if (install_sps(this, entry, NULL) &&
+ install_sas(this, entry, IPSEC_TRAFFIC_TYPE_TRANSPORT))
+ {
+ return TRUE;
+ }
+ cleanup_policies(this, entry);
+ return FALSE;
+}
+
+/**
+ * Generate a new GUID, random
+ */
+static bool generate_guid(private_kernel_wfp_ipsec_t *this, GUID *guid)
+{
+ bool ok;
+ rng_t *rng;
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
+ {
+ return FALSE;
+ }
+ ok = rng->get_bytes(rng, sizeof(GUID), (u_int8_t*)guid);
+ rng->destroy(rng);
+ return ok;
+}
+
+/**
+ * Register a dummy tunnel provider to associate tunnel filters to
+ */
+static bool add_tunnel_provider(private_kernel_wfp_ipsec_t *this,
+ entry_t *entry, GUID *guid, UINT64 *luid)
+{
+ DWORD res;
+
+ IPSEC_AUTH_TRANSFORM0 transform = {
+ /* Create any valid proposal. This is actually not used, as we
+ * don't create an SA from this information. */
+ .authTransformId = IPSEC_AUTH_TRANSFORM_ID_HMAC_SHA_1_96,
+ };
+ IPSEC_SA_TRANSFORM0 transforms = {
+ .ipsecTransformType = IPSEC_TRANSFORM_ESP_AUTH,
+ .espAuthTransform = &transform,
+ };
+ IPSEC_PROPOSAL0 proposal = {
+ .lifetime = {
+ /* We need a valid lifetime, even if we don't create any SA
+ * from these values. Pick some values accepted. */
+ .lifetimeSeconds = 0xFFFF,
+ .lifetimeKilobytes = 0xFFFFFFFF,
+ .lifetimePackets = 0xFFFFFFFF,
+ },
+ .numSaTransforms = 1,
+ .saTransforms = &transforms,
+ };
+ IPSEC_TUNNEL_POLICY0 policy = {
+ .numIpsecProposals = 1,
+ .ipsecProposals = &proposal,
+ .saIdleTimeout = {
+ /* not used, set to lifetime for maximum */
+ .idleTimeoutSeconds = proposal.lifetime.lifetimeSeconds,
+ .idleTimeoutSecondsFailOver = proposal.lifetime.lifetimeSeconds,
+ },
+ };
+ FWPM_PROVIDER_CONTEXT0 qm = {
+ .displayData = {
+ .name = L"charon tunnel provider",
+ },
+ .providerKey = (GUID*)&this->provider.providerKey,
+ .type = FWPM_IPSEC_IKE_QM_TUNNEL_CONTEXT,
+ .ikeQmTunnelPolicy = &policy,
+ };
+
+ switch (entry->local->get_family(entry->local))
+ {
+ case AF_INET:
+ policy.tunnelEndpoints.ipVersion = FWP_IP_VERSION_V4;
+ policy.tunnelEndpoints.localV4Address =
+ untoh32(entry->local->get_address(entry->local).ptr);
+ policy.tunnelEndpoints.remoteV4Address =
+ untoh32(entry->remote->get_address(entry->remote).ptr);
+ break;
+ case AF_INET6:
+ policy.tunnelEndpoints.ipVersion = FWP_IP_VERSION_V6;
+ host2address6(entry->local, &policy.tunnelEndpoints.localV6Address);
+ host2address6(entry->remote, &policy.tunnelEndpoints.remoteV6Address);
+ break;
+ default:
+ return FALSE;
+ }
+
+ if (!generate_guid(this, &qm.providerContextKey))
+ {
+ return FALSE;
+ }
+
+ res = FwpmProviderContextAdd0(this->handle, &qm, NULL, luid);
+ if (res != ERROR_SUCCESS)
+ {
+ DBG1(DBG_KNL, "adding provider context failed: 0x%08x", res);
+ return FALSE;
+ }
+ *guid = qm.providerContextKey;
+ return TRUE;
+}
+
+/**
+ * Install tunnel mode SPs to the kernel
+ */
+static bool install_tunnel_sps(private_kernel_wfp_ipsec_t *this, entry_t *entry)
+{
+ GUID guid;
+
+ if (!add_tunnel_provider(this, entry, &guid, &entry->provider))
+ {
+ return FALSE;
+ }
+ if (!install_sps(this, entry, &guid))
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Reduce refcount, or uninstall a route if all refs gone
+ */
+static bool uninstall_route(private_kernel_wfp_ipsec_t *this,
+ host_t *dst, u_int8_t mask, host_t *src, host_t *gtw)
+{
+ route_t *route, key = {
+ .dst = dst,
+ .mask = mask,
+ .src = src,
+ };
+ char *name;
+ bool res = FALSE;
+
+ this->mutex->lock(this->mutex);
+ route = this->routes->get(this->routes, &key);
+ if (route)
+ {
+ if (--route->refs == 0)
+ {
+ if (hydra->kernel_interface->get_interface(hydra->kernel_interface,
+ src, &name))
+ {
+ res = hydra->kernel_interface->del_route(hydra->kernel_interface,
+ dst->get_address(dst), mask, gtw, src, name) == SUCCESS;
+ free(name);
+ }
+ route = this->routes->remove(this->routes, route);
+ if (route)
+ {
+ destroy_route(route);
+ }
+ }
+ else
+ {
+ res = TRUE;
+ }
+ }
+ this->mutex->unlock(this->mutex);
+
+ return res;
+}
+
+/**
+ * Install a single route, or refcount if exists
+ */
+static bool install_route(private_kernel_wfp_ipsec_t *this,
+ host_t *dst, u_int8_t mask, host_t *src, host_t *gtw)
+{
+ route_t *route, key = {
+ .dst = dst,
+ .mask = mask,
+ .src = src,
+ };
+ char *name;
+ bool res = FALSE;
+
+ this->mutex->lock(this->mutex);
+ route = this->routes->get(this->routes, &key);
+ if (route)
+ {
+ route->refs++;
+ res = TRUE;
+ }
+ else
+ {
+ if (hydra->kernel_interface->get_interface(hydra->kernel_interface,
+ src, &name))
+ {
+ if (hydra->kernel_interface->add_route(hydra->kernel_interface,
+ dst->get_address(dst), mask, gtw, src, name) == SUCCESS)
+ {
+ INIT(route,
+ .dst = dst->clone(dst),
+ .mask = mask,
+ .src = src->clone(src),
+ .gtw = gtw ? gtw->clone(gtw) : NULL,
+ .refs = 1,
+ );
+ route = this->routes->put(this->routes, route, route);
+ if (route)
+ {
+ destroy_route(route);
+ }
+ res = TRUE;
+ }
+ free(name);
+ }
+ }
+ this->mutex->unlock(this->mutex);
+
+ return res;
+}
+
+/**
+ * (Un)-install a single route
+ */
+static bool manage_route(private_kernel_wfp_ipsec_t *this,
+ host_t *local, host_t *remote,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
+ bool add)
+{
+ host_t *src, *dst, *gtw;
+ u_int8_t mask;
+ bool done;
+
+ if (!dst_ts->to_subnet(dst_ts, &dst, &mask))
+ {
+ return FALSE;
+ }
+ if (hydra->kernel_interface->get_address_by_ts(hydra->kernel_interface,
+ src_ts, &src, NULL) != SUCCESS)
+ {
+ dst->destroy(dst);
+ return FALSE;
+ }
+ gtw = hydra->kernel_interface->get_nexthop(hydra->kernel_interface,
+ remote, -1, local);
+ if (add)
+ {
+ done = install_route(this, dst, mask, src, gtw);
+ }
+ else
+ {
+ done = uninstall_route(this, dst, mask, src, gtw);
+ }
+ dst->destroy(dst);
+ src->destroy(src);
+ DESTROY_IF(gtw);
+
+ if (!done)
+ {
+ DBG1(DBG_KNL, "%sinstalling route for policy %R === %R failed",
+ add ? "" : "un", src_ts, dst_ts);
+ }
+ return done;
+}
+
+/**
+ * (Un)-install routes for IPsec policies
+ */
+static bool manage_routes(private_kernel_wfp_ipsec_t *this, entry_t *entry,
+ bool add)
+{
+ enumerator_t *enumerator;
+ sp_entry_t *sp;
+
+ enumerator = array_create_enumerator(entry->sps);
+ while (enumerator->enumerate(enumerator, &sp))
+ {
+ if (add && sp->route)
+ {
+ continue;
+ }
+ if (!add && !sp->route)
+ {
+ continue;
+ }
+ if (manage_route(this, entry->local, entry->remote,
+ sp->src, sp->dst, add))
+ {
+ sp->route = add;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return TRUE;
+}
+
+/**
+ * Install a tunnel mode SA/SP set to the kernel
+ */
+static bool install_tunnel(private_kernel_wfp_ipsec_t *this, entry_t *entry)
+{
+ if (install_tunnel_sps(this, entry) &&
+ manage_routes(this, entry, TRUE) &&
+ install_sas(this, entry, IPSEC_TRAFFIC_TYPE_TUNNEL))
+ {
+ return TRUE;
+ }
+ cleanup_policies(this, entry);
+ return FALSE;
+}
+
+/**
+ * Install a SA/SP set to the kernel
+ */
+static bool install(private_kernel_wfp_ipsec_t *this, entry_t *entry)
+{
+ switch (entry->mode)
+ {
+ case MODE_TRANSPORT:
+ return install_transport(this, entry);
+ case MODE_TUNNEL:
+ return install_tunnel(this, entry);
+ case MODE_BEET:
+ default:
+ return FALSE;
+ }
+}
+
+/**
+ * Installed trap entry
+ */
+typedef struct {
+ /** reqid this trap is installed for */
+ u_int32_t reqid;
+ /** is this a forward policy trap for tunnel mode? */
+ bool fwd;
+ /** do we have installed a route for this trap policy? */
+ bool route;
+ /** local address of associated route */
+ host_t *local;
+ /** remote address of associated route */
+ host_t *remote;
+ /** src traffic selector */
+ traffic_selector_t *src;
+ /** dst traffic selector */
+ traffic_selector_t *dst;
+ /** LUID of installed tunnel policy filter */
+ UINT64 filter_id;
+} trap_t;
+
+/**
+ * Destroy a trap entry
+ */
+static void destroy_trap(trap_t *this)
+{
+ this->local->destroy(this->local);
+ this->remote->destroy(this->remote);
+ this->src->destroy(this->src);
+ this->dst->destroy(this->dst);
+ free(this);
+}
+
+/**
+ * Hashtable equals function for traps
+ */
+static bool equals_trap(trap_t *a, trap_t *b)
+{
+ return a->filter_id == b->filter_id;
+}
+
+/**
+ * Hashtable hash function for traps
+ */
+static u_int hash_trap(trap_t *trap)
+{
+ return chunk_hash(chunk_from_thing(trap->filter_id));
+}
+
+/**
+ * Send an acquire for an installed trap filter
+ */
+static void acquire(private_kernel_wfp_ipsec_t *this, UINT64 filter_id,
+ traffic_selector_t *src, traffic_selector_t *dst)
+{
+ u_int32_t reqid = 0;
+ trap_t *trap, key = {
+ .filter_id = filter_id,
+ };
+
+ this->mutex->lock(this->mutex);
+ trap = this->traps->get(this->traps, &key);
+ if (trap)
+ {
+ reqid = trap->reqid;
+ }
+ this->mutex->unlock(this->mutex);
+
+ if (reqid)
+ {
+ src = src ? src->clone(src) : NULL;
+ dst = dst ? dst->clone(dst) : NULL;
+ hydra->kernel_interface->acquire(hydra->kernel_interface, reqid,
+ src, dst);
+ }
+}
+
+/**
+ * Create a single host traffic selector from an FWP address definition
+ */
+static traffic_selector_t *addr2ts(FWP_IP_VERSION version, void *data,
+ u_int8_t protocol, u_int16_t from_port, u_int16_t to_port)
+{
+ ts_type_t type;
+ UINT32 ints[4];
+ chunk_t addr;
+
+ switch (version)
+ {
+ case FWP_IP_VERSION_V4:
+ ints[0] = untoh32(data);
+ addr = chunk_from_thing(ints[0]);
+ type = TS_IPV4_ADDR_RANGE;
+ break;
+ case FWP_IP_VERSION_V6:
+ ints[3] = untoh32(data);
+ ints[2] = untoh32(data + 4);
+ ints[1] = untoh32(data + 8);
+ ints[0] = untoh32(data + 12);
+ addr = chunk_from_thing(ints);
+ type = TS_IPV6_ADDR_RANGE;
+ break;
+ default:
+ return NULL;
+ }
+ return traffic_selector_create_from_bytes(protocol, type, addr, from_port,
+ addr, to_port);
+}
+
+/**
+ * FwpmNetEventSubscribe0() callback
+ */
+static void WINAPI event_callback(void *user, const FWPM_NET_EVENT1 *event)
+{
+ private_kernel_wfp_ipsec_t *this = user;
+ traffic_selector_t *local = NULL, *remote = NULL;
+ u_int8_t protocol = 0;
+ u_int16_t from_local = 0, to_local = 65535;
+ u_int16_t from_remote = 0, to_remote = 65535;
+
+ if ((event->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) &&
+ (event->header.flags & FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET))
+ {
+ if (event->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET)
+ {
+ from_local = to_local = event->header.localPort;
+ }
+ if (event->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET)
+ {
+ from_remote = to_remote = event->header.remotePort;
+ }
+ if (event->header.flags & FWPM_NET_EVENT_FLAG_IP_PROTOCOL_SET)
+ {
+ protocol = event->header.ipProtocol;
+ }
+
+ local = addr2ts(event->header.ipVersion,
+ (void*)&event->header.localAddrV6,
+ protocol, from_local, to_local);
+ remote = addr2ts(event->header.ipVersion,
+ (void*)&event->header.remoteAddrV6,
+ protocol, from_remote, to_remote);
+ }
+
+ switch (event->type)
+ {
+ case FWPM_NET_EVENT_TYPE_CLASSIFY_DROP:
+ acquire(this, event->classifyDrop->filterId, local, remote);
+ break;
+ case FWPM_NET_EVENT_TYPE_IKEEXT_MM_FAILURE:
+ case FWPM_NET_EVENT_TYPE_IKEEXT_QM_FAILURE:
+ case FWPM_NET_EVENT_TYPE_IKEEXT_EM_FAILURE:
+ case FWPM_NET_EVENT_TYPE_IPSEC_KERNEL_DROP:
+ DBG1(DBG_KNL, "IPsec kernel drop: %R === %R, error 0x%08x, "
+ "SPI 0x%08x, %s filterId %llu", local, remote,
+ event->ipsecDrop->failureStatus, event->ipsecDrop->spi,
+ event->ipsecDrop->direction ? "in" : "out",
+ event->ipsecDrop->filterId);
+ break;
+ case FWPM_NET_EVENT_TYPE_IPSEC_DOSP_DROP:
+ default:
+ break;
+ }
+
+ DESTROY_IF(local);
+ DESTROY_IF(remote);
+}
+
+/**
+ * Register for net events
+ */
+static bool register_events(private_kernel_wfp_ipsec_t *this)
+{
+ FWPM_NET_EVENT_SUBSCRIPTION0 subscription = {};
+ DWORD res;
+
+ res = FwpmNetEventSubscribe0(this->handle, &subscription,
+ event_callback, this, &this->event);
+ if (res != ERROR_SUCCESS)
+ {
+ DBG1(DBG_KNL, "registering for WFP events failed: 0x%08x", res);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Install a trap policy to kernel
+ */
+static bool install_trap(private_kernel_wfp_ipsec_t *this, trap_t *trap)
+{
+ FWPM_FILTER_CONDITION0 *conds = NULL;
+ int count = 0;
+ DWORD res;
+ const GUID *starget, *dtarget;
+ UINT64 weight = 0x000000000000ff00;
+ FWPM_FILTER0 filter = {
+ .displayData = {
+ .name = L"charon IPsec trap",
+ },
+ .action = {
+ .type = FWP_ACTION_BLOCK,
+ },
+ .weight = {
+ .type = FWP_UINT64,
+ .uint64 = &weight,
+ },
+ };
+
+ if (trap->fwd)
+ {
+ if (trap->src->get_type(trap->src) == TS_IPV4_ADDR_RANGE)
+ {
+ filter.layerKey = FWPM_LAYER_IPFORWARD_V4;
+ }
+ else
+ {
+ filter.layerKey = FWPM_LAYER_IPFORWARD_V6;
+ }
+ starget = &FWPM_CONDITION_IP_SOURCE_ADDRESS;
+ dtarget = &FWPM_CONDITION_IP_DESTINATION_ADDRESS;
+ }
+ else
+ {
+ if (trap->src->get_type(trap->src) == TS_IPV4_ADDR_RANGE)
+ {
+ filter.layerKey = FWPM_LAYER_OUTBOUND_TRANSPORT_V4;
+ }
+ else
+ {
+ filter.layerKey = FWPM_LAYER_OUTBOUND_TRANSPORT_V6;
+ }
+ starget = &FWPM_CONDITION_IP_LOCAL_ADDRESS;
+ dtarget = &FWPM_CONDITION_IP_REMOTE_ADDRESS;
+ }
+
+ if (!ts2condition(trap->src, starget, &conds, &count) ||
+ !ts2condition(trap->dst, dtarget, &conds, &count))
+ {
+ free_conditions(conds, count);
+ return FALSE;
+ }
+
+ filter.numFilterConditions = count;
+ filter.filterCondition = conds;
+
+ res = FwpmFilterAdd0(this->handle, &filter, NULL, &trap->filter_id);
+ free_conditions(conds, count);
+ if (res != ERROR_SUCCESS)
+ {
+ DBG1(DBG_KNL, "installing WFP trap filter failed: 0x%08x", res);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Uninstall a trap policy from kernel
+ */
+static bool uninstall_trap(private_kernel_wfp_ipsec_t *this, trap_t *trap)
+{
+ DWORD res;
+
+ res = FwpmFilterDeleteById0(this->handle, trap->filter_id);
+ if (res != ERROR_SUCCESS)
+ {
+ DBG1(DBG_KNL, "uninstalling WFP trap filter failed: 0x%08x", res);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Create and install a new trap entry
+ */
+static bool add_trap(private_kernel_wfp_ipsec_t *this,
+ u_int32_t reqid, bool fwd, host_t *local, host_t *remote,
+ traffic_selector_t *src, traffic_selector_t *dst)
+{
+ trap_t *trap;
+
+ INIT(trap,
+ .reqid = reqid,
+ .fwd = fwd,
+ .src = src->clone(src),
+ .dst = dst->clone(dst),
+ .local = local->clone(local),
+ .remote = remote->clone(remote),
+ );
+
+ if (!install_trap(this, trap))
+ {
+ destroy_trap(trap);
+ return FALSE;
+ }
+
+ trap->route = manage_route(this, local, remote, src, dst, TRUE);
+
+ this->mutex->lock(this->mutex);
+ this->traps->put(this->traps, trap, trap);
+ this->mutex->unlock(this->mutex);
+ return TRUE;
+}
+
+/**
+ * Uninstall and remove a new trap entry
+ */
+static bool remove_trap(private_kernel_wfp_ipsec_t *this,
+ u_int32_t reqid, bool fwd,
+ traffic_selector_t *src, traffic_selector_t *dst)
+{
+ enumerator_t *enumerator;
+ trap_t *trap, *found = NULL;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->traps->create_enumerator(this->traps);
+ while (enumerator->enumerate(enumerator, NULL, &trap))
+ {
+ if (reqid == trap->reqid &&
+ fwd == trap->fwd &&
+ src->equals(src, trap->src) &&
+ dst->equals(dst, trap->dst))
+ {
+ this->traps->remove_at(this->traps, enumerator);
+ found = trap;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+
+ if (found)
+ {
+ if (trap->route)
+ {
+ trap->route = !manage_route(this, trap->local, trap->remote,
+ src, dst, FALSE);
+ }
+ uninstall_trap(this, found);
+ destroy_trap(found);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+METHOD(kernel_ipsec_t, get_features, kernel_feature_t,
+ private_kernel_wfp_ipsec_t *this)
+{
+ return KERNEL_ESP_V3_TFC | KERNEL_NO_POLICY_UPDATES;
+}
+
+/**
+ * Initialize seeds for SPI generation
+ */
+static bool init_spi(private_kernel_wfp_ipsec_t *this)
+{
+ bool ok = TRUE;
+ rng_t *rng;
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
+ if (!rng)
+ {
+ return FALSE;
+ }
+ ok = rng->get_bytes(rng, sizeof(this->nextspi), (u_int8_t*)&this->nextspi);
+ if (ok)
+ {
+ ok = rng->get_bytes(rng, sizeof(this->mixspi), (u_int8_t*)&this->mixspi);
+ }
+ rng->destroy(rng);
+ return ok;
+}
+
+/**
+ * Map an integer x with a one-to-one function using quadratic residues.
+ */
+static u_int permute(u_int x, u_int p)
+{
+ u_int qr;
+
+ x = x % p;
+ qr = ((u_int64_t)x * x) % p;
+ if (x <= p / 2)
+ {
+ return qr;
+ }
+ return p - qr;
+}
+
+METHOD(kernel_ipsec_t, get_spi, status_t,
+ private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
+ u_int8_t protocol, u_int32_t reqid, u_int32_t *spi)
+{
+ /* To avoid sequencial SPIs, we use a one-to-one permuation function on
+ * an incrementing counter, that is a full period PRNG for the range we
+ * allocate SPIs in. We add some randomness using a fixed XOR and start
+ * the counter at random position. This is not cryptographically safe,
+ * but that is actually not required.
+ * The selected prime should be smaller than the range we allocate SPIs
+ * in, and it must satisfy p % 4 == 3 to map x > p/2 using p - qr. */
+ static const u_int p = 268435399, offset = 0xc0000000;
+
+ *spi = htonl(offset + permute(ref_get(&this->nextspi) ^ this->mixspi, p));
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, get_cpi, status_t,
+ private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
+ u_int32_t reqid, u_int16_t *cpi)
+{
+ return NOT_SUPPORTED;
+}
+
+/**
+ * Data for an expire callback job
+ */
+typedef struct {
+ /* backref to kernel backend */
+ private_kernel_wfp_ipsec_t *this;
+ /* SPI of expiring SA */
+ u_int32_t spi;
+ /* destination address of expiring SA */
+ host_t *dst;
+ /* is this a hard expire, or a rekey request? */
+ bool hard;
+} expire_data_t;
+
+/**
+ * Clean up expire data
+ */
+static void expire_data_destroy(expire_data_t *data)
+{
+ data->dst->destroy(data->dst);
+ free(data);
+}
+
+/**
+ * Callback job for SA expiration
+ */
+static job_requeue_t expire_job(expire_data_t *data)
+{
+ private_kernel_wfp_ipsec_t *this = data->this;
+ u_int32_t reqid = 0;
+ u_int8_t protocol;
+ entry_t *entry;
+ sa_entry_t key = {
+ .spi = data->spi,
+ .dst = data->dst,
+ };
+
+ if (data->hard)
+ {
+ this->mutex->lock(this->mutex);
+ entry = this->isas->remove(this->isas, &key);
+ this->mutex->unlock(this->mutex);
+ if (entry)
+ {
+ protocol = entry->isa.protocol;
+ reqid = entry->reqid;
+ if (entry->osa.dst)
+ {
+ key.dst = entry->osa.dst;
+ key.spi = entry->osa.spi;
+ this->osas->remove(this->osas, &key);
+ }
+ entry_destroy(this, entry);
+ }
+ }
+ else
+ {
+ this->mutex->lock(this->mutex);
+ entry = this->isas->get(this->isas, &key);
+ if (entry)
+ {
+ protocol = entry->isa.protocol;
+ reqid = entry->reqid;
+ }
+ this->mutex->unlock(this->mutex);
+ }
+
+ if (reqid)
+ {
+ hydra->kernel_interface->expire(hydra->kernel_interface,
+ reqid, protocol, data->spi, data->hard);
+ }
+
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Schedule an expire event for an SA
+ */
+static void schedule_expire(private_kernel_wfp_ipsec_t *this, u_int32_t spi,
+ host_t *dst, u_int32_t lifetime, bool hard)
+{
+ expire_data_t *data;
+
+ INIT(data,
+ .this = this,
+ .spi = spi,
+ .dst = dst->clone(dst),
+ .hard = hard,
+ );
+
+ lib->scheduler->schedule_job(lib->scheduler, (job_t*)
+ callback_job_create((void*)expire_job, data,
+ (void*)expire_data_destroy, NULL),
+ lifetime);
+}
+
+METHOD(kernel_ipsec_t, add_sa, status_t,
+ private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
+ u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
+ u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
+ u_int16_t ipcomp, u_int16_t cpi, u_int32_t replay_window,
+ bool initiator, bool encap, bool esn, bool inbound,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
+{
+ host_t *local, *remote;
+ entry_t *entry;
+
+ if (inbound)
+ {
+ /* comes first, create new entry */
+ local = dst->clone(dst);
+ remote = src->clone(src);
+
+ INIT(entry,
+ .reqid = reqid,
+ .isa = {
+ .spi = spi,
+ .dst = local,
+ .protocol = protocol,
+ .lifetime = lifetime->time.life,
+ .encr = {
+ .alg = enc_alg,
+ .key = chunk_clone(enc_key),
+ },
+ .integ = {
+ .alg = int_alg,
+ .key = chunk_clone(int_key),
+ },
+ },
+ .sps = array_create(0, 0),
+ .local = local,
+ .remote = remote,
+ .mode = mode,
+ .encap = encap,
+ );
+
+ if (lifetime->time.life)
+ {
+ schedule_expire(this, spi, local, lifetime->time.life, TRUE);
+ }
+ if (lifetime->time.rekey && lifetime->time.rekey != lifetime->time.life)
+ {
+ schedule_expire(this, spi, local, lifetime->time.rekey, FALSE);
+ }
+
+ this->mutex->lock(this->mutex);
+ this->tsas->put(this->tsas, (void*)(uintptr_t)reqid, entry);
+ this->isas->put(this->isas, &entry->isa, entry);
+ this->mutex->unlock(this->mutex);
+ }
+ else
+ {
+ /* comes after inbound, update entry */
+ this->mutex->lock(this->mutex);
+ entry = this->tsas->remove(this->tsas, (void*)(uintptr_t)reqid);
+ this->mutex->unlock(this->mutex);
+
+ if (!entry)
+ {
+ DBG1(DBG_KNL, "adding outbound SA failed, no inbound SA found "
+ "for reqid %u ", reqid);
+ return NOT_FOUND;
+ }
+ /* TODO: should we check for local/remote, mode etc.? */
+
+ entry->osa = (sa_entry_t){
+ .spi = spi,
+ .dst = entry->remote,
+ .protocol = protocol,
+ .lifetime = lifetime->time.life,
+ .encr = {
+ .alg = enc_alg,
+ .key = chunk_clone(enc_key),
+ },
+ .integ = {
+ .alg = int_alg,
+ .key = chunk_clone(int_key),
+ },
+ };
+
+ this->mutex->lock(this->mutex);
+ this->osas->put(this->osas, &entry->osa, entry);
+ this->mutex->unlock(this->mutex);
+ }
+
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, update_sa, status_t,
+ private_kernel_wfp_ipsec_t *this, u_int32_t spi, u_int8_t protocol,
+ u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
+ bool encap, bool new_encap, mark_t mark)
+{
+ entry_t *entry;
+ sa_entry_t key = {
+ .dst = dst,
+ .spi = spi,
+ };
+ UINT64 sa_id = 0;
+ IPSEC_SA_CONTEXT1 *ctx;
+ IPSEC_V4_UDP_ENCAPSULATION0 ports;
+ UINT32 flags = IPSEC_SA_DETAILS_UPDATE_TRAFFIC;
+ DWORD res;
+
+ this->mutex->lock(this->mutex);
+ entry = this->osas->get(this->osas, &key);
+ this->mutex->unlock(this->mutex);
+
+ if (entry)
+ {
+ /* outbound entry, nothing to do */
+ return SUCCESS;
+ }
+
+ this->mutex->lock(this->mutex);
+ entry = this->isas->get(this->isas, &key);
+ if (entry)
+ {
+ /* inbound entry, do update */
+ sa_id = entry->sa_id;
+ ports.localUdpEncapPort = entry->local->get_port(entry->local);
+ ports.remoteUdpEncapPort = entry->remote->get_port(entry->remote);
+ }
+ this->mutex->unlock(this->mutex);
+
+ if (!sa_id)
+ {
+ return NOT_FOUND;
+ }
+
+ res = IPsecSaContextGetById1(this->handle, sa_id, &ctx);
+ if (res != ERROR_SUCCESS)
+ {
+ DBG1(DBG_KNL, "getting WFP SA context for updated failed: 0x%08x", res);
+ return FAILED;
+ }
+ if (!hosts2traffic(this, new_dst, new_src, &ctx->inboundSa->traffic) ||
+ !hosts2traffic(this, new_dst, new_src, &ctx->outboundSa->traffic))
+ {
+ FwpmFreeMemory0((void**)&ctx);
+ return FAILED;
+ }
+
+ if (new_encap != encap)
+ {
+ if (new_encap)
+ {
+ ctx->inboundSa->udpEncapsulation = &ports;
+ ctx->outboundSa->udpEncapsulation = &ports;
+ }
+ else
+ {
+ ctx->inboundSa->udpEncapsulation = NULL;
+ ctx->outboundSa->udpEncapsulation = NULL;
+ }
+ flags |= IPSEC_SA_DETAILS_UPDATE_UDP_ENCAPSULATION;
+ }
+
+ res = IPsecSaContextUpdate0(this->handle, flags, ctx);
+ FwpmFreeMemory0((void**)&ctx);
+ if (res != ERROR_SUCCESS)
+ {
+ DBG1(DBG_KNL, "updating WFP SA context failed: 0x%08x", res);
+ return FAILED;
+ }
+
+ this->mutex->lock(this->mutex);
+ entry = this->isas->remove(this->isas, &key);
+ if (entry)
+ {
+ key.spi = entry->osa.spi;
+ key.dst = entry->osa.dst;
+ this->osas->remove(this->osas, &key);
+
+ entry->local->destroy(entry->local);
+ entry->remote->destroy(entry->remote);
+ entry->local = new_dst->clone(new_dst);
+ entry->remote = new_src->clone(new_src);
+ entry->isa.dst = entry->local;
+ entry->osa.dst = entry->remote;
+
+ this->isas->put(this->isas, &entry->isa, entry);
+ this->osas->put(this->osas, &entry->osa, entry);
+
+ manage_routes(this, entry, FALSE);
+ manage_routes(this, entry, TRUE);
+ }
+ this->mutex->unlock(this->mutex);
+
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, query_sa, status_t,
+ private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, u_int8_t protocol, mark_t mark, u_int64_t *bytes,
+ u_int64_t *packets, time_t *time)
+{
+ /* It does not seem that WFP provides any means of getting per-SA traffic
+ * statistics. IPsecGetStatistics0/1() provides global stats, and
+ * IPsecSaContextEnum0/1() and IPsecSaEnum0/1() return the configured
+ * values only. */
+ return NOT_SUPPORTED;
+}
+
+METHOD(kernel_ipsec_t, del_sa, status_t,
+ private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, u_int8_t protocol, u_int16_t cpi, mark_t mark)
+{
+ entry_t *entry;
+ sa_entry_t key = {
+ .dst = dst,
+ .spi = spi,
+ };
+
+ this->mutex->lock(this->mutex);
+ entry = this->isas->remove(this->isas, &key);
+ this->mutex->unlock(this->mutex);
+
+ if (entry)
+ {
+ /* keep entry until removal of outbound */
+ return SUCCESS;
+ }
+
+ this->mutex->lock(this->mutex);
+ entry = this->osas->remove(this->osas, &key);
+ this->mutex->unlock(this->mutex);
+
+ if (entry)
+ {
+ entry_destroy(this, entry);
+ return SUCCESS;
+ }
+
+ return NOT_FOUND;
+}
+
+METHOD(kernel_ipsec_t, flush_sas, status_t,
+ private_kernel_wfp_ipsec_t *this)
+{
+ return NOT_SUPPORTED;
+}
+
+METHOD(kernel_ipsec_t, add_policy, status_t,
+ private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
+ policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa, mark_t mark,
+ policy_priority_t priority)
+{
+ status_t status = SUCCESS;
+ entry_t *entry;
+ sp_entry_t *sp;
+ sa_entry_t key = {
+ .spi = sa->esp.use ? sa->esp.spi : sa->ah.spi,
+ .dst = dst,
+ };
+
+ if (sa->esp.use && sa->ah.use)
+ {
+ return NOT_SUPPORTED;
+ }
+
+ switch (type)
+ {
+ case POLICY_IPSEC:
+ break;
+ case POLICY_PASS:
+ case POLICY_DROP:
+ return NOT_SUPPORTED;
+ }
+
+ switch (direction)
+ {
+ case POLICY_OUT:
+ break;
+ case POLICY_IN:
+ case POLICY_FWD:
+ /* not required */
+ return SUCCESS;
+ default:
+ return NOT_SUPPORTED;
+ }
+
+ switch (priority)
+ {
+ case POLICY_PRIORITY_DEFAULT:
+ break;
+ case POLICY_PRIORITY_ROUTED:
+ if (!add_trap(this, sa->reqid, FALSE, src, dst, src_ts, dst_ts))
+ {
+ return FAILED;
+ }
+ if (sa->mode == MODE_TUNNEL)
+ {
+ if (!add_trap(this, sa->reqid, TRUE, src, dst, src_ts, dst_ts))
+ {
+ return FAILED;
+ }
+ }
+ return SUCCESS;
+ case POLICY_PRIORITY_FALLBACK:
+ default:
+ return NOT_SUPPORTED;
+ }
+
+ this->mutex->lock(this->mutex);
+ entry = this->osas->get(this->osas, &key);
+ if (entry)
+ {
+ if (sa->mode == MODE_TUNNEL || array_count(entry->sps) == 0)
+ {
+ INIT(sp,
+ .src = src_ts->clone(src_ts),
+ .dst = dst_ts->clone(dst_ts),
+ );
+ array_insert(entry->sps, -1, sp);
+ if (array_count(entry->sps) == sa->policy_count)
+ {
+ if (!install(this, entry))
+ {
+ status = FAILED;
+ }
+ }
+ }
+ else
+ {
+ /* TODO: reinstall with a filter using multiple TS?
+ * Filters are ANDed for a match, but we could install a filter
+ * with the inverse TS set using NOT-matches... */
+ DBG1(DBG_KNL, "multiple transport mode traffic selectors not "
+ "supported by WFP");
+ status = NOT_SUPPORTED;
+ }
+ }
+ else
+ {
+ DBG1(DBG_KNL, "adding SP failed, no SA found for SPI 0x%08x", key.spi);
+ status = FAILED;
+ }
+ this->mutex->unlock(this->mutex);
+
+ return status;
+}
+
+METHOD(kernel_ipsec_t, query_policy, status_t,
+ private_kernel_wfp_ipsec_t *this, traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+ time_t *use_time)
+{
+ /* see query_sa() for some notes */
+ return NOT_SUPPORTED;
+}
+
+METHOD(kernel_ipsec_t, del_policy, status_t,
+ private_kernel_wfp_ipsec_t *this, traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t reqid,
+ mark_t mark, policy_priority_t priority)
+{
+ if (direction == POLICY_OUT && priority == POLICY_PRIORITY_ROUTED)
+ {
+ if (remove_trap(this, reqid, FALSE, src_ts, dst_ts))
+ {
+ remove_trap(this, reqid, TRUE, src_ts, dst_ts);
+ return SUCCESS;
+ }
+ return NOT_FOUND;
+ }
+ /* not required, as we delete the whole SA/SP set during del_sa() */
+ return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, flush_policies, status_t,
+ private_kernel_wfp_ipsec_t *this)
+{
+ return NOT_SUPPORTED;
+}
+
+/**
+ * Add a bypass policy for a specific UDP port
+ */
+static bool add_bypass(private_kernel_wfp_ipsec_t *this,
+ int family, u_int16_t port, bool inbound, UINT64 *luid)
+{
+ FWPM_FILTER_CONDITION0 *cond, *conds = NULL;
+ int count = 0;
+ DWORD res;
+ UINT64 weight = 0xff00000000000000;
+ FWPM_FILTER0 filter = {
+ .displayData = {
+ .name = L"charon IKE bypass",
+ },
+ .action = {
+ .type = FWP_ACTION_PERMIT,
+ },
+ .weight = {
+ .type = FWP_UINT64,
+ .uint64 = &weight,
+ },
+ };
+
+ switch (family)
+ {
+ case AF_INET:
+ filter.layerKey = inbound ? FWPM_LAYER_INBOUND_TRANSPORT_V4
+ : FWPM_LAYER_OUTBOUND_TRANSPORT_V4;
+ break;
+ case AF_INET6:
+ filter.layerKey = inbound ? FWPM_LAYER_INBOUND_TRANSPORT_V6
+ : FWPM_LAYER_OUTBOUND_TRANSPORT_V6;
+ break;
+ default:
+ return FALSE;
+ }
+
+ cond = append_condition(&conds, &count);
+ cond->fieldKey = FWPM_CONDITION_IP_PROTOCOL;
+ cond->matchType = FWP_MATCH_EQUAL;
+ cond->conditionValue.type = FWP_UINT8;
+ cond->conditionValue.uint8 = IPPROTO_UDP;
+
+ cond = append_condition(&conds, &count);
+ cond->fieldKey = FWPM_CONDITION_IP_LOCAL_PORT;
+ cond->matchType = FWP_MATCH_EQUAL;
+ cond->conditionValue.type = FWP_UINT16;
+ cond->conditionValue.uint16 = port;
+
+ filter.numFilterConditions = count;
+ filter.filterCondition = conds;
+
+ res = FwpmFilterAdd0(this->handle, &filter, NULL, luid);
+ free_conditions(conds, count);
+ if (res != ERROR_SUCCESS)
+ {
+ DBG1(DBG_KNL, "installing WFP bypass filter failed: 0x%08x", res);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+METHOD(kernel_ipsec_t, bypass_socket, bool,
+ private_kernel_wfp_ipsec_t *this, int fd, int family)
+{
+ union {
+ struct sockaddr sa;
+ SOCKADDR_IN in;
+ SOCKADDR_IN6 in6;
+ } saddr;
+ int addrlen = sizeof(saddr);
+ UINT64 filter_out, filter_in = 0;
+ u_int16_t port;
+
+ if (getsockname(fd, &saddr.sa, &addrlen) == SOCKET_ERROR)
+ {
+ return FALSE;
+ }
+ switch (family)
+ {
+ case AF_INET:
+ port = ntohs(saddr.in.sin_port);
+ break;
+ case AF_INET6:
+ port = ntohs(saddr.in6.sin6_port);
+ break;
+ default:
+ return FALSE;
+ }
+
+ if (!add_bypass(this, family, port, TRUE, &filter_in) ||
+ !add_bypass(this, family, port, FALSE, &filter_out))
+ {
+ if (filter_in)
+ {
+ FwpmFilterDeleteById0(this->handle, filter_in);
+ }
+ return FALSE;
+ }
+
+ this->mutex->lock(this->mutex);
+ array_insert(this->bypass, ARRAY_TAIL, &filter_in);
+ array_insert(this->bypass, ARRAY_TAIL, &filter_out);
+ this->mutex->unlock(this->mutex);
+
+ return TRUE;
+}
+
+METHOD(kernel_ipsec_t, enable_udp_decap, bool,
+ private_kernel_wfp_ipsec_t *this, int fd, int family, u_int16_t port)
+{
+ return FALSE;
+}
+
+METHOD(kernel_ipsec_t, destroy, void,
+ private_kernel_wfp_ipsec_t *this)
+{
+ UINT64 filter;
+
+ while (array_remove(this->bypass, ARRAY_TAIL, &filter))
+ {
+ FwpmFilterDeleteById0(this->handle, filter);
+ }
+ if (this->handle)
+ {
+ if (this->event)
+ {
+ FwpmNetEventUnsubscribe0(this->handle, this->event);
+ }
+ FwpmProviderDeleteByKey0(this->handle, &this->provider.providerKey);
+ FwpmEngineClose0(this->handle);
+ }
+ array_destroy(this->bypass);
+ this->tsas->destroy(this->tsas);
+ this->isas->destroy(this->isas);
+ this->osas->destroy(this->osas);
+ this->routes->destroy(this->routes);
+ this->traps->destroy(this->traps);
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+kernel_wfp_ipsec_t *kernel_wfp_ipsec_create()
+{
+ private_kernel_wfp_ipsec_t *this;
+ DWORD res;
+ FWPM_SESSION0 session = {
+ .displayData = {
+ .name = L"charon",
+ .description = L"strongSwan IKE kernel-wfp backend",
+ },
+ };
+
+ INIT(this,
+ .public = {
+ .interface = {
+ .get_features = _get_features,
+ .get_spi = _get_spi,
+ .get_cpi = _get_cpi,
+ .add_sa = _add_sa,
+ .update_sa = _update_sa,
+ .query_sa = _query_sa,
+ .del_sa = _del_sa,
+ .flush_sas = _flush_sas,
+ .add_policy = _add_policy,
+ .query_policy = _query_policy,
+ .del_policy = _del_policy,
+ .flush_policies = _flush_policies,
+ .bypass_socket = _bypass_socket,
+ .enable_udp_decap = _enable_udp_decap,
+ .destroy = _destroy,
+ },
+ },
+ .provider = {
+ .displayData = {
+ .name = L"charon",
+ .description = L"strongSwan IKE kernel-wfp backend",
+ },
+ .providerKey = { 0x59cdae2e, 0xf6bb, 0x4c09,
+ { 0xa9,0x59,0x9d,0x91,0xac,0xaf,0xf9,0x19 }},
+ },
+ .mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
+ .bypass = array_create(sizeof(UINT64), 2),
+ .tsas = hashtable_create(hashtable_hash_ptr, hashtable_equals_ptr, 4),
+ .isas = hashtable_create((void*)hash_sa, (void*)equals_sa, 4),
+ .osas = hashtable_create((void*)hash_sa, (void*)equals_sa, 4),
+ .routes = hashtable_create((void*)hash_route, (void*)equals_route, 4),
+ .traps = hashtable_create((void*)hash_trap, (void*)equals_trap, 4),
+ );
+
+ if (!init_spi(this))
+ {
+ destroy(this);
+ return NULL;
+ }
+
+ res = FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, &session,
+ &this->handle);
+ if (res != ERROR_SUCCESS)
+ {
+ DBG1(DBG_KNL, "opening WFP engine failed: 0x%08x", res);
+ destroy(this);
+ return NULL;
+ }
+
+ res = FwpmProviderAdd0(this->handle, &this->provider, NULL);
+ if (res != ERROR_SUCCESS && res != FWP_E_ALREADY_EXISTS)
+ {
+ DBG1(DBG_KNL, "registering WFP provider failed: 0x%08x", res);
+ destroy(this);
+ return NULL;
+ }
+
+ if (!register_events(this))
+ {
+ destroy(this);
+ return NULL;
+ }
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.h b/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.h
new file mode 100644
index 000000000..d61c230e4
--- /dev/null
+++ b/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup kernel_wfp_ipsec kernel_wfp_ipsec
+ * @{ @ingroup kernel_wfp
+ */
+
+#ifndef KERNEL_WFP_IPSEC_H_
+#define KERNEL_WFP_IPSEC_H_
+
+#include <library.h>
+#include <kernel/kernel_ipsec.h>
+
+typedef struct kernel_wfp_ipsec_t kernel_wfp_ipsec_t;
+
+/**
+ * Windows Filter Platform based IPsec kernel backend.
+ */
+struct kernel_wfp_ipsec_t {
+
+ /**
+ * Implements kernel_ipsec_t interface
+ */
+ kernel_ipsec_t interface;
+};
+
+/**
+ * Create WFP kernel interface instance.
+ *
+ * @return kernel_wfp_ipsec_t instance
+ */
+kernel_wfp_ipsec_t *kernel_wfp_ipsec_create();
+
+#endif /** KERNEL_WFP_IPSEC_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_wfp/kernel_wfp_plugin.c b/src/libcharon/plugins/kernel_wfp/kernel_wfp_plugin.c
new file mode 100644
index 000000000..e465b0a76
--- /dev/null
+++ b/src/libcharon/plugins/kernel_wfp/kernel_wfp_plugin.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "kernel_wfp_plugin.h"
+#include "kernel_wfp_ipsec.h"
+
+#include <daemon.h>
+
+typedef struct private_kernel_wfp_plugin_t private_kernel_wfp_plugin_t;
+
+/**
+ * Private data of kernel-wfp plugin
+ */
+struct private_kernel_wfp_plugin_t {
+
+ /**
+ * Implements plugin interface
+ */
+ kernel_wfp_plugin_t public;
+};
+
+METHOD(plugin_t, get_name, char*,
+ private_kernel_wfp_plugin_t *this)
+{
+ return "kernel-wfp";
+}
+
+METHOD(plugin_t, get_features, int,
+ private_kernel_wfp_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_CALLBACK(kernel_ipsec_register, kernel_wfp_ipsec_create),
+ PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"),
+ PLUGIN_DEPENDS(RNG, RNG_WEAK),
+ PLUGIN_DEPENDS(RNG, RNG_STRONG),
+ };
+ *features = f;
+ return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+ private_kernel_wfp_plugin_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *kernel_wfp_plugin_create()
+{
+ private_kernel_wfp_plugin_t *this;
+
+ INIT(this,
+ .public = {
+ .plugin = {
+ .get_name = _get_name,
+ .get_features = _get_features,
+ .destroy = _destroy,
+ },
+ },
+ );
+
+ return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/kernel_wfp/kernel_wfp_plugin.h b/src/libcharon/plugins/kernel_wfp/kernel_wfp_plugin.h
new file mode 100644
index 000000000..a538e34a1
--- /dev/null
+++ b/src/libcharon/plugins/kernel_wfp/kernel_wfp_plugin.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup kernel_wfp kernel_wfp
+ * @ingroup cplugins
+ *
+ * @defgroup kernel_wfp_plugin kernel_wfp_plugin
+ * @{ @ingroup kernel_wfp
+ */
+
+#ifndef KERNEL_WFP_PLUGIN_H_
+#define KERNEL_WFP_PLUGIN_H_
+
+#include <library.h>
+#include <plugins/plugin.h>
+
+typedef struct kernel_wfp_plugin_t kernel_wfp_plugin_t;
+
+/**
+ * Windows Filter Platform based IPsec backend plugin.
+ */
+struct kernel_wfp_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** KERNEL_WFP_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_wfp/mingw-w64-4.8.1.diff b/src/libcharon/plugins/kernel_wfp/mingw-w64-4.8.1.diff
new file mode 100644
index 000000000..c72b94c07
--- /dev/null
+++ b/src/libcharon/plugins/kernel_wfp/mingw-w64-4.8.1.diff
@@ -0,0 +1,26 @@
+diff -Naur /mingw-orig/x86_64-w64-mingw32/include/fwptypes.h /mingw/x86_64-w64-mingw32/include/fwptypes.h
+--- /mingw-orig/x86_64-w64-mingw32/include/fwptypes.h 2013-08-30 07:15:40 +0200
++++ /mingw/x86_64-w64-mingw32/include/fwptypes.h 2014-01-02 16:32:26 +0100
+@@ -333,11 +333,6 @@
+ } __C89_NAMELESSUNIONNAME;
+ } FWP_CONDITION_VALUE0;
+
+-typedef struct FWPM_DISPLAY_DATA0_ {
+- wchar_t *name;
+- wchar_t *description;
+-} FWPM_DISPLAY_DATA0;
+-
+ #endif /* WINAPI_PARTITION_DESKTOP. */
+ /* Begin additional prototypes for all interfaces */
+
+diff -Naur /mingw-orig/x86_64-w64-mingw32/include/iketypes.h /mingw/x86_64-w64-mingw32/include/iketypes.h
+--- /mingw-orig/x86_64-w64-mingw32/include/iketypes.h 2013-08-30 07:15:40 +0200
++++ /mingw/x86_64-w64-mingw32/include/iketypes.h 2014-01-02 16:31:12 +0100
+@@ -212,7 +212,6 @@
+ FWP_BYTE_BLOB presharedKey;
+ UINT32 flags;
+ } IKEEXT_PRESHARED_KEY_AUTHENTICATION1;
+-#endif
+
+ typedef struct IKEEXT_CERTIFICATE_AUTHENTICATION0_ {
+ IKEEXT_CERT_CONFIG_TYPE inboundConfigType;
diff --git a/src/libcharon/plugins/led/Makefile.am b/src/libcharon/plugins/led/Makefile.am
index fbe779dd6..18d6af399 100644
--- a/src/libcharon/plugins/led/Makefile.am
+++ b/src/libcharon/plugins/led/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-led.la
diff --git a/src/libcharon/plugins/led/Makefile.in b/src/libcharon/plugins/led/Makefile.in
index f7179cfe8..78ec6660e 100644
--- a/src/libcharon/plugins/led/Makefile.in
+++ b/src/libcharon/plugins/led/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -263,6 +263,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -281,6 +282,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -308,6 +310,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -399,6 +402,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -415,7 +419,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-led.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-led.la
diff --git a/src/libcharon/plugins/load_tester/Makefile.am b/src/libcharon/plugins/load_tester/Makefile.am
index e7c08783f..31e1b5c6f 100644
--- a/src/libcharon/plugins/load_tester/Makefile.am
+++ b/src/libcharon/plugins/load_tester/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
-DIPSEC_PIDDIR=\"${piddir}\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-load-tester.la
diff --git a/src/libcharon/plugins/load_tester/Makefile.in b/src/libcharon/plugins/load_tester/Makefile.in
index 561d69a23..df75c0f4b 100644
--- a/src/libcharon/plugins/load_tester/Makefile.in
+++ b/src/libcharon/plugins/load_tester/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -276,6 +276,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -294,6 +295,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -321,6 +323,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -412,6 +415,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -429,7 +433,7 @@ AM_CPPFLAGS = \
-DIPSEC_PIDDIR=\"${piddir}\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-load-tester.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-load-tester.la
diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c
index e133190b4..bc7c0ffbc 100644
--- a/src/libcharon/plugins/load_tester/load_tester_config.c
+++ b/src/libcharon/plugins/load_tester/load_tester_config.c
@@ -150,7 +150,7 @@ struct private_load_tester_config_t {
/**
* incremental numbering of generated configs
*/
- u_int num;
+ refcount_t num;
/**
* Dynamic source port, if used
@@ -802,7 +802,7 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
{
if (streq(name, "load-test"))
{
- return generate_config(this, this->num++);
+ return generate_config(this, (u_int)ref_get(&this->num));
}
return NULL;
}
diff --git a/src/libcharon/plugins/load_tester/load_tester_creds.c b/src/libcharon/plugins/load_tester/load_tester_creds.c
index f17d41f46..d62c7295d 100644
--- a/src/libcharon/plugins/load_tester/load_tester_creds.c
+++ b/src/libcharon/plugins/load_tester/load_tester_creds.c
@@ -68,6 +68,11 @@ struct private_load_tester_creds_t {
* Password for EAP
*/
shared_key_t *pwd;
+
+ /**
+ * List of certificate distribution points to include in generated certs
+ */
+ linked_list_t *cdps;
};
/**
@@ -377,6 +382,7 @@ METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
BUILD_NOT_BEFORE_TIME, now - 60 * 60 * 24,
BUILD_NOT_AFTER_TIME, now + 60 * 60 * 24,
BUILD_SERIAL, chunk_from_thing(serial),
+ BUILD_CRL_DISTRIBUTION_POINTS, this->cdps,
BUILD_END);
peer_key->destroy(peer_key);
sans->destroy(sans);
@@ -436,13 +442,14 @@ METHOD(load_tester_creds_t, destroy, void,
DESTROY_IF(this->ca);
this->psk->destroy(this->psk);
this->pwd->destroy(this->pwd);
+ this->cdps->destroy_function(this->cdps, free);
free(this);
}
load_tester_creds_t *load_tester_creds_create()
{
private_load_tester_creds_t *this;
- char *pwd, *psk, *digest;
+ char *pwd, *psk, *digest, *crl;
psk = lib->settings->get_str(lib->settings,
"%s.plugins.load-tester.preshared_key", default_psk, lib->ns);
@@ -450,6 +457,8 @@ load_tester_creds_t *load_tester_creds_create()
"%s.plugins.load-tester.eap_password", default_pwd, lib->ns);
digest = lib->settings->get_str(lib->settings,
"%s.plugins.load-tester.digest", "sha1", lib->ns);
+ crl = lib->settings->get_str(lib->settings,
+ "%s.plugins.load-tester.crl", NULL, lib->ns);
INIT(this,
.public = {
@@ -465,7 +474,7 @@ load_tester_creds_t *load_tester_creds_create()
.private = load_issuer_key(),
.ca = load_issuer_cert(),
.cas = linked_list_create(),
- .digest = enum_from_name(hash_algorithm_short_names, digest),
+ .cdps = linked_list_create(),
.psk = shared_key_create(SHARED_IKE,
chunk_clone(chunk_create(psk, strlen(psk)))),
.pwd = shared_key_create(SHARED_EAP,
@@ -477,14 +486,23 @@ load_tester_creds_t *load_tester_creds_create()
this->cas->insert_last(this->cas, this->ca->get_ref(this->ca));
}
- if (this->digest == -1)
+ if (!enum_from_name(hash_algorithm_short_names, digest, &this->digest))
{
DBG1(DBG_CFG, "invalid load-tester digest: '%s', using sha1", digest);
this->digest = HASH_SHA1;
}
+ if (crl)
+ {
+ x509_cdp_t *cdp;
+
+ INIT(cdp,
+ .uri = crl,
+ );
+ this->cdps->insert_last(this->cdps, cdp);
+ }
+
load_ca_certs(this);
return &this->public;
}
-
diff --git a/src/libcharon/plugins/load_tester/load_tester_ipsec.c b/src/libcharon/plugins/load_tester/load_tester_ipsec.c
index 02b1d4216..3f256ddd0 100644
--- a/src/libcharon/plugins/load_tester/load_tester_ipsec.c
+++ b/src/libcharon/plugins/load_tester/load_tester_ipsec.c
@@ -31,14 +31,14 @@ struct private_load_tester_ipsec_t {
/**
* faked SPI counter
*/
- u_int32_t spi;
+ refcount_t spi;
};
METHOD(kernel_ipsec_t, get_spi, status_t,
private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
u_int8_t protocol, u_int32_t reqid, u_int32_t *spi)
{
- *spi = ++this->spi;
+ *spi = (uint32_t)ref_get(&this->spi);
return SUCCESS;
}
@@ -53,8 +53,9 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
- u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
- u_int16_t cpi, bool initiator, bool encap, bool esn, bool inbound,
+ u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
+ u_int16_t ipcomp, u_int16_t cpi, u_int32_t replay_window,
+ bool initiator, bool encap, bool esn, bool inbound,
traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
{
return SUCCESS;
diff --git a/src/libcharon/plugins/lookip/Makefile.am b/src/libcharon/plugins/lookip/Makefile.am
index 6d71c8c13..223654ea9 100644
--- a/src/libcharon/plugins/lookip/Makefile.am
+++ b/src/libcharon/plugins/lookip/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
-DIPSEC_PIDDIR=\"${piddir}\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-lookip.la
diff --git a/src/libcharon/plugins/lookip/Makefile.in b/src/libcharon/plugins/lookip/Makefile.in
index 57aaeeaeb..deb517ed8 100644
--- a/src/libcharon/plugins/lookip/Makefile.in
+++ b/src/libcharon/plugins/lookip/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -272,6 +272,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -290,6 +291,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -317,6 +319,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -408,6 +411,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -425,7 +429,7 @@ AM_CPPFLAGS = \
-DIPSEC_PIDDIR=\"${piddir}\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-lookip.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-lookip.la
diff --git a/src/libcharon/plugins/maemo/Makefile.am b/src/libcharon/plugins/maemo/Makefile.am
index c3c55ba41..fe5c963fd 100644
--- a/src/libcharon/plugins/maemo/Makefile.am
+++ b/src/libcharon/plugins/maemo/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
AM_CFLAGS = \
${maemo_CFLAGS} \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-maemo.la
diff --git a/src/libcharon/plugins/maemo/Makefile.in b/src/libcharon/plugins/maemo/Makefile.in
index e1d4ee301..aa3ade079 100644
--- a/src/libcharon/plugins/maemo/Makefile.in
+++ b/src/libcharon/plugins/maemo/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -268,6 +268,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -286,6 +287,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -313,6 +315,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -404,6 +407,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -421,7 +425,7 @@ AM_CPPFLAGS = \
AM_CFLAGS = \
${maemo_CFLAGS} \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-maemo.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-maemo.la
diff --git a/src/libcharon/plugins/maemo/maemo_service.c b/src/libcharon/plugins/maemo/maemo_service.c
index f0f3105c4..2e96f8fb4 100644
--- a/src/libcharon/plugins/maemo/maemo_service.c
+++ b/src/libcharon/plugins/maemo/maemo_service.c
@@ -327,6 +327,7 @@ static gboolean initiate_connection(private_maemo_service_t *this,
charon->socket->get_port(charon->socket, FALSE),
hostname, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+ ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
peer_cfg = peer_cfg_create(this->current, ike_cfg,
CERT_SEND_IF_ASKED,
@@ -351,6 +352,7 @@ static gboolean initiate_connection(private_maemo_service_t *this,
TRUE, MODE_TUNNEL, ACTION_NONE, ACTION_NONE,
ACTION_NONE, FALSE, 0, 0, NULL, NULL, 0);
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
+ child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
ts = traffic_selector_create_dynamic(0, 0, 65535);
child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE, "0.0.0.0",
diff --git a/src/libcharon/plugins/medcli/Makefile.am b/src/libcharon/plugins/medcli/Makefile.am
index f645be27e..cfa825980 100644
--- a/src/libcharon/plugins/medcli/Makefile.am
+++ b/src/libcharon/plugins/medcli/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-medcli.la
diff --git a/src/libcharon/plugins/medcli/Makefile.in b/src/libcharon/plugins/medcli/Makefile.in
index b6a04dfe7..919b936c0 100644
--- a/src/libcharon/plugins/medcli/Makefile.in
+++ b/src/libcharon/plugins/medcli/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-medcli.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-medcli.la
diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c
index d048b003b..1fb57b928 100644
--- a/src/libcharon/plugins/medcli/medcli_config.c
+++ b/src/libcharon/plugins/medcli/medcli_config.c
@@ -106,6 +106,7 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
charon->socket->get_port(charon->socket, FALSE),
address, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+ ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
med_cfg = peer_cfg_create(
"mediation", ike_cfg,
CERT_NEVER_SEND, UNIQUE_REPLACE,
@@ -168,6 +169,7 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
0, 0, NULL, NULL, 0);
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
+ child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net));
child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net));
peer_cfg->add_child_cfg(peer_cfg, child_cfg);
@@ -242,6 +244,7 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
0, 0, NULL, NULL, 0);
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
+ child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net));
child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net));
this->current->add_child_cfg(this->current, child_cfg);
@@ -382,6 +385,7 @@ medcli_config_t *medcli_config_create(database_t *db)
FRAGMENTATION_NO, 0),
);
this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE));
+ this->ike->add_proposal(this->ike, proposal_create_default_aead(PROTO_IKE));
schedule_autoinit(this);
diff --git a/src/libcharon/plugins/medsrv/Makefile.am b/src/libcharon/plugins/medsrv/Makefile.am
index ec305da21..f21220260 100644
--- a/src/libcharon/plugins/medsrv/Makefile.am
+++ b/src/libcharon/plugins/medsrv/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-medsrv.la
diff --git a/src/libcharon/plugins/medsrv/Makefile.in b/src/libcharon/plugins/medsrv/Makefile.in
index 82d985e57..ce81fb1a8 100644
--- a/src/libcharon/plugins/medsrv/Makefile.in
+++ b/src/libcharon/plugins/medsrv/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-medsrv.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-medsrv.la
diff --git a/src/libcharon/plugins/medsrv/medsrv_config.c b/src/libcharon/plugins/medsrv/medsrv_config.c
index ac6076ae8..02d805e06 100644
--- a/src/libcharon/plugins/medsrv/medsrv_config.c
+++ b/src/libcharon/plugins/medsrv/medsrv_config.c
@@ -145,6 +145,7 @@ medsrv_config_t *medsrv_config_create(database_t *db)
FRAGMENTATION_NO, 0),
);
this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE));
+ this->ike->add_proposal(this->ike, proposal_create_default_aead(PROTO_IKE));
return &this->public;
}
diff --git a/src/libcharon/plugins/osx_attr/Makefile.am b/src/libcharon/plugins/osx_attr/Makefile.am
index f1ff22e60..aa1d46290 100644
--- a/src/libcharon/plugins/osx_attr/Makefile.am
+++ b/src/libcharon/plugins/osx_attr/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-osx-attr.la
diff --git a/src/libcharon/plugins/osx_attr/Makefile.in b/src/libcharon/plugins/osx_attr/Makefile.in
index ce8d67c53..870b42790 100644
--- a/src/libcharon/plugins/osx_attr/Makefile.in
+++ b/src/libcharon/plugins/osx_attr/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-osx-attr.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-osx-attr.la
diff --git a/src/libcharon/plugins/radattr/Makefile.am b/src/libcharon/plugins/radattr/Makefile.am
index a0b0584d6..15d5a0a1f 100644
--- a/src/libcharon/plugins/radattr/Makefile.am
+++ b/src/libcharon/plugins/radattr/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libradius
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-radattr.la
diff --git a/src/libcharon/plugins/radattr/Makefile.in b/src/libcharon/plugins/radattr/Makefile.in
index 3dbebd807..35ebf9975 100644
--- a/src/libcharon/plugins/radattr/Makefile.in
+++ b/src/libcharon/plugins/radattr/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -267,6 +267,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -285,6 +286,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -312,6 +314,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -403,6 +406,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -420,7 +424,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libradius
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-radattr.la
@MONOLITHIC_FALSE@libstrongswan_radattr_la_LIBADD = $(top_builddir)/src/libradius/libradius.la
diff --git a/src/libcharon/plugins/radattr/radattr_listener.c b/src/libcharon/plugins/radattr/radattr_listener.c
index aca83aafc..1d30460ad 100644
--- a/src/libcharon/plugins/radattr/radattr_listener.c
+++ b/src/libcharon/plugins/radattr/radattr_listener.c
@@ -68,7 +68,7 @@ static void print_radius_attributes(private_radattr_listener_t *this,
enumerator = message->create_payload_enumerator(message);
while (enumerator->enumerate(enumerator, &payload))
{
- if (payload->get_type(payload) == NOTIFY)
+ if (payload->get_type(payload) == PLV2_NOTIFY)
{
notify = (notify_payload_t*)payload;
if (notify->get_notify_type(notify) == RADIUS_ATTRIBUTE)
@@ -144,7 +144,7 @@ METHOD(listener_t, message, bool,
{
if (plain && ike_sa->supports_extension(ike_sa, EXT_STRONGSWAN) &&
message->get_exchange_type(message) == IKE_AUTH &&
- message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
+ message->get_payload(message, PLV2_EAP))
{
if (incoming)
{
diff --git a/src/libcharon/plugins/smp/Makefile.am b/src/libcharon/plugins/smp/Makefile.am
index 67b4b2a6d..3aa533e56 100644
--- a/src/libcharon/plugins/smp/Makefile.am
+++ b/src/libcharon/plugins/smp/Makefile.am
@@ -6,7 +6,7 @@ AM_CPPFLAGS = \
AM_CFLAGS = \
${xml_CFLAGS} \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-smp.la
diff --git a/src/libcharon/plugins/smp/Makefile.in b/src/libcharon/plugins/smp/Makefile.in
index e0134e7a2..35e7f2a87 100644
--- a/src/libcharon/plugins/smp/Makefile.in
+++ b/src/libcharon/plugins/smp/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -264,6 +264,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -282,6 +283,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -309,6 +311,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -400,6 +403,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
AM_CFLAGS = \
${xml_CFLAGS} \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-smp.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-smp.la
diff --git a/src/libcharon/plugins/socket_default/Makefile.am b/src/libcharon/plugins/socket_default/Makefile.am
index d734b313f..e524ffd18 100644
--- a/src/libcharon/plugins/socket_default/Makefile.am
+++ b/src/libcharon/plugins/socket_default/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-socket-default.la
diff --git a/src/libcharon/plugins/socket_default/Makefile.in b/src/libcharon/plugins/socket_default/Makefile.in
index 894c1f9dc..bee1259e6 100644
--- a/src/libcharon/plugins/socket_default/Makefile.in
+++ b/src/libcharon/plugins/socket_default/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -419,7 +423,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-socket-default.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-socket-default.la
diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.am b/src/libcharon/plugins/socket_dynamic/Makefile.am
index 04973e5ba..a1e21b98b 100644
--- a/src/libcharon/plugins/socket_dynamic/Makefile.am
+++ b/src/libcharon/plugins/socket_dynamic/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-socket-dynamic.la
diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.in b/src/libcharon/plugins/socket_dynamic/Makefile.in
index a0e2d2d93..073806d64 100644
--- a/src/libcharon/plugins/socket_dynamic/Makefile.in
+++ b/src/libcharon/plugins/socket_dynamic/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -419,7 +423,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-socket-dynamic.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-socket-dynamic.la
diff --git a/src/libcharon/plugins/socket_win/Makefile.am b/src/libcharon/plugins/socket_win/Makefile.am
new file mode 100644
index 000000000..f01178fcc
--- /dev/null
+++ b/src/libcharon/plugins/socket_win/Makefile.am
@@ -0,0 +1,21 @@
+AM_CPPFLAGS = \
+ -I${linux_headers} \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-socket-win.la
+else
+plugin_LTLIBRARIES = libstrongswan-socket-win.la
+endif
+
+libstrongswan_socket_win_la_SOURCES = \
+ socket_win_socket.h socket_win_socket.c \
+ socket_win_plugin.h socket_win_plugin.c
+
+libstrongswan_socket_win_la_LDFLAGS = -module -avoid-version
+libstrongswan_socket_win_la_LIBADD = -lws2_32
diff --git a/src/libcharon/plugins/socket_win/Makefile.in b/src/libcharon/plugins/socket_win/Makefile.in
new file mode 100644
index 000000000..ff38e8158
--- /dev/null
+++ b/src/libcharon/plugins/socket_win/Makefile.in
@@ -0,0 +1,769 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libcharon/plugins/socket_win
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/split-package-version.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(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'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_socket_win_la_DEPENDENCIES =
+am_libstrongswan_socket_win_la_OBJECTS = socket_win_socket.lo \
+ socket_win_plugin.lo
+libstrongswan_socket_win_la_OBJECTS = \
+ $(am_libstrongswan_socket_win_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+libstrongswan_socket_win_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_socket_win_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_socket_win_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_socket_win_la_rpath =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+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) $(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_CC_1 =
+CCLD = $(CC)
+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_CCLD_1 =
+SOURCES = $(libstrongswan_socket_win_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_socket_win_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+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@
+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@
+ECHO_N = @ECHO_N@
+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@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
+PTHREADLIB = @PTHREADLIB@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+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@
+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@
+aikgen_plugins = @aikgen_plugins@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+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@
+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@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+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@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+ -I${linux_headers} \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-socket-win.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-socket-win.la
+libstrongswan_socket_win_la_SOURCES = \
+ socket_win_socket.h socket_win_socket.c \
+ socket_win_plugin.h socket_win_plugin.c
+
+libstrongswan_socket_win_la_LDFLAGS = -module -avoid-version
+libstrongswan_socket_win_la_LIBADD = -lws2_32
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/socket_win/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/socket_win/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(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)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libstrongswan-socket-win.la: $(libstrongswan_socket_win_la_OBJECTS) $(libstrongswan_socket_win_la_DEPENDENCIES) $(EXTRA_libstrongswan_socket_win_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libstrongswan_socket_win_la_LINK) $(am_libstrongswan_socket_win_la_rpath) $(libstrongswan_socket_win_la_OBJECTS) $(libstrongswan_socket_win_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_win_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_win_socket.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-pluginLTLIBRARIES install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/socket_win/socket_win_plugin.c b/src/libcharon/plugins/socket_win/socket_win_plugin.c
new file mode 100644
index 000000000..a0ef0858a
--- /dev/null
+++ b/src/libcharon/plugins/socket_win/socket_win_plugin.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "socket_win_plugin.h"
+#include "socket_win_socket.h"
+
+#include <daemon.h>
+
+typedef struct private_socket_win_plugin_t private_socket_win_plugin_t;
+
+/**
+ * Private data of socket plugin
+ */
+struct private_socket_win_plugin_t {
+
+ /**
+ * Implements plugin interface
+ */
+ socket_win_plugin_t public;
+};
+
+METHOD(plugin_t, get_name, char*,
+ private_socket_win_plugin_t *this)
+{
+ return "socket-win";
+}
+
+METHOD(plugin_t, destroy, void,
+ private_socket_win_plugin_t *this)
+{
+ free(this);
+}
+
+METHOD(plugin_t, get_features, int,
+ private_socket_win_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_CALLBACK(socket_register, socket_win_socket_create),
+ PLUGIN_PROVIDE(CUSTOM, "socket"),
+ PLUGIN_DEPENDS(CUSTOM, "kernel-ipsec"),
+ };
+ *features = f;
+ return countof(f);
+}
+
+/**
+ * Create instance of socket-win plugin
+ */
+plugin_t *socket_win_plugin_create()
+{
+ private_socket_win_plugin_t *this;
+
+ INIT(this,
+ .public = {
+ .plugin = {
+ .get_name = _get_name,
+ .get_features = _get_features,
+ .destroy = _destroy,
+ },
+ },
+ );
+
+ return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/socket_win/socket_win_plugin.h b/src/libcharon/plugins/socket_win/socket_win_plugin.h
new file mode 100644
index 000000000..c4873ce61
--- /dev/null
+++ b/src/libcharon/plugins/socket_win/socket_win_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup socket_win socket_win
+ * @ingroup cplugins
+ *
+ * @defgroup socket_win_plugin socket_win_plugin
+ * @{ @ingroup socket_win
+ */
+
+#ifndef SOCKET_WIN_PLUGIN_H_
+#define SOCKET_WIN_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct socket_win_plugin_t socket_win_plugin_t;
+
+/**
+ * Winsock2 based socket implementation plugin.
+ */
+struct socket_win_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** SOCKET_WIN_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/socket_win/socket_win_socket.c b/src/libcharon/plugins/socket_win/socket_win_socket.c
new file mode 100644
index 000000000..5ebe04aac
--- /dev/null
+++ b/src/libcharon/plugins/socket_win/socket_win_socket.c
@@ -0,0 +1,501 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/* for WSAID_WSASENDMSG, Windows 7 */
+#define _WIN32_WINNT 0x0601
+
+#include "socket_win_socket.h"
+
+#include <library.h>
+#include <hydra.h>
+#include <threading/thread.h>
+#include <daemon.h>
+
+#include <mswsock.h>
+
+/* Maximum size of a packet */
+#define MAX_PACKET 10000
+
+/* number of sockets in use */
+#define SOCKET_COUNT 2
+
+/* missing on MinGW */
+#ifndef IPV6_V6ONLY
+# define IPV6_V6ONLY 27
+#endif
+
+/* GUIDS to lookup WSASend/RecvMsg */
+static GUID WSARecvMsgGUID = WSAID_WSARECVMSG;
+static GUID WSASendMsgGUID = WSAID_WSASENDMSG;
+
+typedef struct private_socket_win_socket_t private_socket_win_socket_t;
+
+/**
+ * Private data of an socket_t object
+ */
+struct private_socket_win_socket_t {
+
+ /**
+ * public functions
+ */
+ socket_win_socket_t public;
+
+ /**
+ * Port for each socket
+ */
+ u_int16_t ports[SOCKET_COUNT];
+
+ /**
+ * IPv4/IPv6 dual-use sockets
+ */
+ SOCKET socks[SOCKET_COUNT];
+
+ /**
+ * Events to wait for socket data
+ */
+ HANDLE events[SOCKET_COUNT];
+
+ /**
+ * Maximum packet size to receive
+ */
+ int max_packet;
+
+ /**
+ * WSASendMsg function
+ */
+ int WINAPI (*WSASendMsg)(SOCKET, LPWSAMSG, DWORD, LPDWORD,
+ LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
+
+ /**
+ * WSARecvMsg function
+ */
+ int WINAPI (*WSARecvMsg)(SOCKET, LPWSAMSG, LPDWORD,
+ LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
+};
+
+METHOD(socket_t, receiver, status_t,
+ private_socket_win_socket_t *this, packet_t **out)
+{
+ char buf[this->max_packet], cbuf[128];
+ bool old;
+ DWORD i, len, err;
+ WSAMSG msg;
+ WSABUF data;
+ WSACMSGHDR *cmsg;
+ SOCKADDR_IN6 addr;
+ host_t *src = NULL, *dst = NULL;
+ packet_t *pkt;
+
+ data.buf = buf;
+ data.len = sizeof(buf);
+
+ memset(&msg, 0, sizeof(msg));
+ msg.name = (struct sockaddr*)&addr;
+ msg.namelen = sizeof(addr);
+ msg.lpBuffers = &data;
+ msg.dwBufferCount = 1;
+ msg.Control.buf = cbuf;
+ msg.Control.len = sizeof(cbuf);
+
+ /* wait for socket events */
+ old = thread_cancelability(TRUE);
+ i = WSAWaitForMultipleEvents(SOCKET_COUNT, this->events,
+ FALSE, INFINITE, TRUE);
+ thread_cancelability(old);
+ if (i < WSA_WAIT_EVENT_0 || i >= WSA_WAIT_EVENT_0 + SOCKET_COUNT)
+ {
+ DBG1(DBG_NET, "waiting on sockets failed: %d", WSAGetLastError());
+ return FAILED;
+ }
+ i -= WSA_WAIT_EVENT_0;
+
+ /* WSAEvents must be reset manually */
+ WSAResetEvent(this->events[i]);
+
+ if (this->WSARecvMsg(this->socks[i], &msg, &len,
+ NULL, NULL) == SOCKET_ERROR)
+ {
+ err = WSAGetLastError();
+ /* ignore WSAECONNRESET; this is returned for any ICMP port unreachable,
+ * for a packet we sent, but is most likely not related to the packet
+ * we try to receive. */
+ if (err != WSAECONNRESET)
+ {
+ DBG1(DBG_NET, "reading from socket failed: %d", WSAGetLastError());
+ }
+ return FAILED;
+ }
+
+ DBG3(DBG_NET, "received packet %b", buf, (int)len);
+
+ for (cmsg = WSA_CMSG_FIRSTHDR(&msg); dst == NULL && cmsg != NULL;
+ cmsg = WSA_CMSG_NXTHDR(&msg, cmsg))
+ {
+ if (cmsg->cmsg_level == IPPROTO_IP &&
+ cmsg->cmsg_type == IP_PKTINFO)
+ {
+ struct in_pktinfo *pktinfo;
+ struct sockaddr_in sin = {
+ .sin_family = AF_INET,
+ };
+
+ pktinfo = (struct in_pktinfo*)WSA_CMSG_DATA(cmsg);
+ sin.sin_addr = pktinfo->ipi_addr;
+ sin.sin_port = htons(this->ports[i]);
+ dst = host_create_from_sockaddr((struct sockaddr*)&sin);
+ }
+ if (cmsg->cmsg_level == IPPROTO_IPV6 &&
+ cmsg->cmsg_type == IPV6_PKTINFO)
+ {
+ struct in6_pktinfo *pktinfo;
+ struct sockaddr_in6 sin = {
+ .sin6_family = AF_INET6,
+ };
+
+ pktinfo = (struct in6_pktinfo*)WSA_CMSG_DATA(cmsg);
+ sin.sin6_addr = pktinfo->ipi6_addr;
+ sin.sin6_port = htons(this->ports[i]);
+ dst = host_create_from_sockaddr((struct sockaddr*)&sin);
+ }
+ }
+
+ if (!dst)
+ {
+ DBG1(DBG_NET, "receiving IP destination address failed");
+ return FAILED;
+ }
+
+ switch (dst->get_family(dst))
+ {
+ case AF_INET6:
+ src = host_create_from_sockaddr((struct sockaddr*)&addr);
+ break;
+ case AF_INET:
+ /* extract v4 address from mapped v6 */
+ src = host_create_from_chunk(AF_INET,
+ chunk_create(addr.sin6_addr.u.Byte + 12, 4),
+ ntohs(addr.sin6_port));
+ break;
+ }
+ if (!src)
+ {
+ DBG1(DBG_NET, "receiving IP source address failed");
+ dst->destroy(dst);
+ return FAILED;
+ }
+
+ pkt = packet_create();
+ pkt->set_source(pkt, src);
+ pkt->set_destination(pkt, dst);
+ DBG2(DBG_NET, "received packet: from %#H to %#H", src, dst);
+ pkt->set_data(pkt, chunk_clone(chunk_create(buf, len)));
+
+ *out = pkt;
+ return SUCCESS;
+}
+
+METHOD(socket_t, sender, status_t,
+ private_socket_win_socket_t *this, packet_t *packet)
+{
+ u_int16_t port;
+ int i = -1, j;
+ host_t *src, *dst;
+ WSAMSG msg;
+ DWORD len;
+ WSABUF data;
+ WSACMSGHDR *cmsg;
+ SOCKADDR_IN6 addr = {
+ .sin6_family = AF_INET6,
+ .sin6_addr = {
+ .u = {
+ .Byte = {
+ /* v6-mapped-v4 by default */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,
+ },
+ },
+ },
+ };
+ char buf[WSA_CMSG_SPACE(max(sizeof(struct in6_pktinfo),
+ sizeof(struct in_pktinfo)))];
+
+ src = packet->get_source(packet);
+ dst = packet->get_destination(packet);
+ data.len = packet->get_data(packet).len;
+ data.buf = packet->get_data(packet).ptr;
+
+ DBG2(DBG_NET, "sending packet: from %#H to %#H", src, dst);
+
+ DBG3(DBG_NET, "sending packet %b", data.buf, (int)data.len);
+
+ port = src->get_port(src);
+ for (j = 0; j < SOCKET_COUNT; j++)
+ {
+ if (!port || this->ports[j] == port)
+ {
+ i = j;
+ break;
+ }
+ }
+ if (i == -1)
+ {
+ DBG1(DBG_NET, "no socket found to send packet from port %u", port);
+ return FAILED;
+ }
+
+ /* copy destination IPv6, or last 32 bits of mapped IPv4 address */
+ len = dst->get_address(dst).len;
+ if (len > sizeof(addr.sin6_addr))
+ {
+ return FAILED;
+ }
+ memcpy(addr.sin6_addr.u.Byte + sizeof(addr.sin6_addr) - len,
+ dst->get_address(dst).ptr, len);
+ addr.sin6_port = htons(dst->get_port(dst));
+
+ memset(&msg, 0, sizeof(msg));
+ msg.name = (struct sockaddr*)&addr;
+ msg.namelen = sizeof(addr);
+ msg.lpBuffers = &data;
+ msg.dwBufferCount = 1;
+
+ if (!src->is_anyaddr(src))
+ {
+ memset(buf, 0, sizeof(buf));
+ msg.Control.buf = buf;
+
+ switch (src->get_family(src))
+ {
+ case AF_INET:
+ {
+ struct in_pktinfo *pktinfo;
+ SOCKADDR_IN *sin;
+
+ msg.Control.len = WSA_CMSG_SPACE(sizeof(*pktinfo));
+ cmsg = WSA_CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = IPPROTO_IP;
+ cmsg->cmsg_type = IP_PKTINFO;
+ cmsg->cmsg_len = WSA_CMSG_LEN(sizeof(*pktinfo));
+ pktinfo = (struct in_pktinfo*)WSA_CMSG_DATA(cmsg);
+ sin = (SOCKADDR_IN*)src->get_sockaddr(src);
+ pktinfo->ipi_addr = sin->sin_addr;
+ break;
+ }
+ case AF_INET6:
+ {
+ struct in6_pktinfo *pktinfo;
+ SOCKADDR_IN6 *sin;
+
+ msg.Control.len = WSA_CMSG_SPACE(sizeof(*pktinfo));
+ cmsg = WSA_CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = IPPROTO_IPV6;
+ cmsg->cmsg_type = IPV6_PKTINFO;
+ cmsg->cmsg_len = WSA_CMSG_LEN(sizeof(*pktinfo));
+ pktinfo = (struct in6_pktinfo*)WSA_CMSG_DATA(cmsg);
+ sin = (SOCKADDR_IN6*)src->get_sockaddr(src);
+ pktinfo->ipi6_addr = sin->sin6_addr;
+ break;
+ }
+ }
+ }
+
+ if (this->WSASendMsg(this->socks[i], &msg, 0, &len,
+ NULL, NULL) == SOCKET_ERROR)
+ {
+ DBG1(DBG_NET, "sending packet failed: %d", WSAGetLastError());
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+METHOD(socket_t, get_port, u_int16_t,
+ private_socket_win_socket_t *this, bool nat)
+{
+ return this->ports[nat != 0];
+}
+
+METHOD(socket_t, supported_families, socket_family_t,
+ private_socket_win_socket_t *this)
+{
+ return SOCKET_FAMILY_IPV4 | SOCKET_FAMILY_IPV6;
+}
+
+/**
+ * Open an IPv4/IPv6 dual-use socket to send and receive packets
+ */
+static SOCKET open_socket(private_socket_win_socket_t *this, int i)
+{
+ SOCKADDR_IN6 addr = {
+ .sin6_family = AF_INET6,
+ .sin6_port = htons(this->ports[i]),
+ };
+ int addrlen = sizeof(addr);
+ BOOL on = TRUE, off = FALSE;
+ DWORD dwon = TRUE;
+ SOCKET s;
+
+ s = WSASocket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0);
+ if (s == INVALID_SOCKET)
+ {
+ DBG1(DBG_NET, "creating socket failed: %d", WSAGetLastError());
+ return INVALID_SOCKET;
+ }
+ /* enable IPv4 on IPv6 socket */
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
+ (const char*)&off, sizeof(off)) == SOCKET_ERROR)
+ {
+ DBG1(DBG_NET, "using dual-mode socket failed: %d", WSAGetLastError());
+ closesocket(s);
+ return INVALID_SOCKET;
+ }
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+ (const char*)&on, sizeof(on)) == SOCKET_ERROR)
+ {
+ DBG1(DBG_NET, "enabling SO_REUSEADDR failed: %d", WSAGetLastError());
+ closesocket(s);
+ return INVALID_SOCKET;
+ }
+ if (bind(s, (const struct sockaddr*)&addr, addrlen) == SOCKET_ERROR)
+ {
+ DBG1(DBG_NET, "unable to bind socket: %d", WSAGetLastError());
+ closesocket(s);
+ return INVALID_SOCKET;
+ }
+ /* retrieve randomly allocated port if needed */
+ if (this->ports[i] == 0)
+ {
+ if (getsockname(s, (struct sockaddr*)&addr,
+ &addrlen) == SOCKET_ERROR)
+ {
+ DBG1(DBG_NET, "unable to determine port: %d", WSAGetLastError());
+ closesocket(s);
+ return INVALID_SOCKET;
+ }
+ this->ports[i] = ntohs(addr.sin6_port);
+ }
+ /* PKTINFO is required for both protocol families */
+ if (setsockopt(s, IPPROTO_IP, IP_PKTINFO,
+ (char*)&dwon, sizeof(dwon)) == SOCKET_ERROR)
+ {
+ DBG1(DBG_NET, "unable to set IP_PKTINFO: %d", WSAGetLastError());
+ closesocket(s);
+ return INVALID_SOCKET;
+ }
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO,
+ (char*)&dwon, sizeof(dwon)) == SOCKET_ERROR)
+ {
+ DBG1(DBG_NET, "unable to set IP6_PKTINFO: %d", WSAGetLastError());
+ closesocket(s);
+ return INVALID_SOCKET;
+ }
+ if (!hydra->kernel_interface->bypass_socket(hydra->kernel_interface,
+ s, AF_INET))
+ {
+ DBG1(DBG_NET, "installing IPv4 IKE bypass policy failed");
+ }
+ if (!hydra->kernel_interface->bypass_socket(hydra->kernel_interface,
+ s, AF_INET6))
+ {
+ DBG1(DBG_NET, "installing IPv6 IKE bypass policy failed");
+ }
+ return s;
+}
+
+METHOD(socket_t, destroy, void,
+ private_socket_win_socket_t *this)
+{
+ int i;
+
+ for (i = 0; i < SOCKET_COUNT; i++)
+ {
+ if (this->socks[i] != INVALID_SOCKET)
+ {
+ closesocket(this->socks[i]);
+ }
+ if (this->events[i] != WSA_INVALID_EVENT)
+ {
+ WSACloseEvent(this->events[i]);
+ }
+ }
+ free(this);
+}
+
+/*
+ * See header for description
+ */
+socket_win_socket_t *socket_win_socket_create()
+{
+ private_socket_win_socket_t *this;
+ DWORD len;
+ int i;
+
+ INIT(this,
+ .public = {
+ .socket = {
+ .send = _sender,
+ .receive = _receiver,
+ .get_port = _get_port,
+ .supported_families = _supported_families,
+ .destroy = _destroy,
+ },
+ },
+ .ports = {
+ lib->settings->get_int(lib->settings,
+ "%s.port", CHARON_UDP_PORT, lib->ns),
+ lib->settings->get_int(lib->settings,
+ "%s.port_nat_t", CHARON_NATT_PORT, lib->ns),
+ },
+ .max_packet = lib->settings->get_int(lib->settings,
+ "%s.max_packet", MAX_PACKET, lib->ns),
+ );
+
+ for (i = 0; i < SOCKET_COUNT; i++)
+ {
+ this->socks[i] = open_socket(this, i);
+ this->events[i] = WSACreateEvent();
+ }
+
+ for (i = 0; i < SOCKET_COUNT; i++)
+ {
+ if (this->events[i] == WSA_INVALID_EVENT ||
+ this->socks[i] == INVALID_SOCKET)
+ {
+ DBG1(DBG_NET, "creating socket failed: %d", WSAGetLastError());
+ destroy(this);
+ return NULL;
+ }
+ if (WSAEventSelect(this->socks[i], this->events[i],
+ FD_READ) == SOCKET_ERROR)
+ {
+ DBG1(DBG_NET, "WSAEventSelect() failed: %d", WSAGetLastError());
+ destroy(this);
+ return NULL;
+ }
+ }
+
+ if (WSAIoctl(this->socks[0], SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &WSASendMsgGUID, sizeof(WSASendMsgGUID), &this->WSASendMsg,
+ sizeof(this->WSASendMsg), &len, NULL, NULL) != 0 ||
+ WSAIoctl(this->socks[0], SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &WSARecvMsgGUID, sizeof(WSARecvMsgGUID), &this->WSARecvMsg,
+ sizeof(this->WSARecvMsg), &len, NULL, NULL) != 0)
+ {
+ DBG1(DBG_NET, "send/recvmsg() lookup failed: %d", WSAGetLastError());
+ destroy(this);
+ return NULL;
+ }
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/socket_win/socket_win_socket.h b/src/libcharon/plugins/socket_win/socket_win_socket.h
new file mode 100644
index 000000000..21699c330
--- /dev/null
+++ b/src/libcharon/plugins/socket_win/socket_win_socket.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup socket_win_socket socket_win_socket
+ * @{ @ingroup socket_win
+ */
+
+#ifndef SOCKET_WIN_SOCKET_H_
+#define SOCKET_WIN_SOCKET_H_
+
+typedef struct socket_win_socket_t socket_win_socket_t;
+
+#include <network/socket.h>
+
+/**
+ * Winsock2 based socket implementation.
+ */
+struct socket_win_socket_t {
+
+ /**
+ * Implements the socket_t interface.
+ */
+ socket_t socket;
+};
+
+/**
+ * Create a socket_win_socket instance.
+ */
+socket_win_socket_t *socket_win_socket_create();
+
+#endif /** SOCKET_WIN_SOCKET_H_ @}*/
diff --git a/src/libcharon/plugins/sql/Makefile.am b/src/libcharon/plugins/sql/Makefile.am
index fd5693123..c947db892 100644
--- a/src/libcharon/plugins/sql/Makefile.am
+++ b/src/libcharon/plugins/sql/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-sql.la
diff --git a/src/libcharon/plugins/sql/Makefile.in b/src/libcharon/plugins/sql/Makefile.in
index 02967d0dd..208b900e1 100644
--- a/src/libcharon/plugins/sql/Makefile.in
+++ b/src/libcharon/plugins/sql/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -264,6 +264,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -282,6 +283,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -309,6 +311,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -400,6 +403,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -416,7 +420,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-sql.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-sql.la
diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c
index a8d34f2d4..c47c7c0f8 100644
--- a/src/libcharon/plugins/sql/sql_config.c
+++ b/src/libcharon/plugins/sql/sql_config.c
@@ -153,6 +153,7 @@ static void add_esp_proposals(private_sql_config_t *this,
if (use_default)
{
child->add_proposal(child, proposal_create_default(PROTO_ESP));
+ child->add_proposal(child, proposal_create_default_aead(PROTO_ESP));
}
}
@@ -242,6 +243,7 @@ static void add_ike_proposals(private_sql_config_t *this,
if (use_default)
{
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+ ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
}
}
diff --git a/src/libcharon/plugins/stroke/Makefile.am b/src/libcharon/plugins/stroke/Makefile.am
index 9509b1bd3..b90688791 100644
--- a/src/libcharon/plugins/stroke/Makefile.am
+++ b/src/libcharon/plugins/stroke/Makefile.am
@@ -7,7 +7,7 @@ AM_CPPFLAGS = \
-DIPSEC_PIDDIR=\"${piddir}\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-stroke.la
diff --git a/src/libcharon/plugins/stroke/Makefile.in b/src/libcharon/plugins/stroke/Makefile.in
index 253203de7..59a59834a 100644
--- a/src/libcharon/plugins/stroke/Makefile.in
+++ b/src/libcharon/plugins/stroke/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -268,6 +268,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -286,6 +287,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -313,6 +315,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -404,6 +407,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -423,7 +427,7 @@ AM_CPPFLAGS = \
-DIPSEC_PIDDIR=\"${piddir}\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-stroke.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-stroke.la
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index e5e6d9246..62967b006 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -174,10 +174,12 @@ static void add_proposals(private_stroke_config_t *this, char *string,
if (ike_cfg)
{
ike_cfg->add_proposal(ike_cfg, proposal_create_default(proto));
+ ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(proto));
}
else
{
child_cfg->add_proposal(child_cfg, proposal_create_default(proto));
+ child_cfg->add_proposal(child_cfg, proposal_create_default_aead(proto));
}
}
@@ -1149,6 +1151,10 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
map_action(msg->add_conn.close_action), msg->add_conn.ipcomp,
msg->add_conn.inactivity, msg->add_conn.reqid,
&mark_in, &mark_out, msg->add_conn.tfc);
+ if (msg->add_conn.replay_window != -1)
+ {
+ child_cfg->set_replay_window(child_cfg, msg->add_conn.replay_window);
+ }
child_cfg->set_mipv6_options(child_cfg, msg->add_conn.proxy_mode,
msg->add_conn.install_policy);
add_ts(this, &msg->add_conn.me, child_cfg, TRUE);
diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c
index 169ff2bf6..54dd56e91 100644
--- a/src/libcharon/plugins/stroke/stroke_socket.c
+++ b/src/libcharon/plugins/stroke/stroke_socket.c
@@ -107,6 +107,19 @@ struct private_stroke_socket_t {
};
/**
+ * Helper macro to log configuration options, but only if they are defined.
+ */
+#define DBG_OPT(...) VA_ARGS_DISPATCH(DBG_OPT, __VA_ARGS__)(__VA_ARGS__)
+#define DBG_OPT2(fmt, val) ({ \
+ typeof(val) _val = val; \
+ if (_val) { DBG2(DBG_CFG, fmt, _val); } \
+})
+#define DBG_OPT3(fmt, label, val) ({ \
+ typeof(val) _val = val; \
+ if (_val) { DBG2(DBG_CFG, fmt, label, _val); } \
+})
+
+/**
* Helper function which corrects the string pointers
* in a stroke_msg_t. Strings in a stroke_msg sent over "wire"
* contains RELATIVE addresses (relative to the beginning of the
@@ -157,22 +170,22 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
pop_string(msg, &end->cert_policy);
pop_string(msg, &end->updown);
- DBG2(DBG_CFG, " %s=%s", label, end->address);
- DBG2(DBG_CFG, " %ssubnet=%s", label, end->subnets);
- DBG2(DBG_CFG, " %ssourceip=%s", label, end->sourceip);
- DBG2(DBG_CFG, " %sdns=%s", label, end->dns);
- DBG2(DBG_CFG, " %sauth=%s", label, end->auth);
- DBG2(DBG_CFG, " %sauth2=%s", label, end->auth2);
- DBG2(DBG_CFG, " %sid=%s", label, end->id);
- DBG2(DBG_CFG, " %sid2=%s", label, end->id2);
- DBG2(DBG_CFG, " %srsakey=%s", label, end->rsakey);
- DBG2(DBG_CFG, " %scert=%s", label, end->cert);
- DBG2(DBG_CFG, " %scert2=%s", label, end->cert2);
- DBG2(DBG_CFG, " %sca=%s", label, end->ca);
- DBG2(DBG_CFG, " %sca2=%s", label, end->ca2);
- DBG2(DBG_CFG, " %sgroups=%s", label, end->groups);
- DBG2(DBG_CFG, " %sgroups2=%s", label, end->groups2);
- DBG2(DBG_CFG, " %supdown=%s", label, end->updown);
+ DBG_OPT(" %s=%s", label, end->address);
+ DBG_OPT(" %ssubnet=%s", label, end->subnets);
+ DBG_OPT(" %ssourceip=%s", label, end->sourceip);
+ DBG_OPT(" %sdns=%s", label, end->dns);
+ DBG_OPT(" %sauth=%s", label, end->auth);
+ DBG_OPT(" %sauth2=%s", label, end->auth2);
+ DBG_OPT(" %sid=%s", label, end->id);
+ DBG_OPT(" %sid2=%s", label, end->id2);
+ DBG_OPT(" %srsakey=%s", label, end->rsakey);
+ DBG_OPT(" %scert=%s", label, end->cert);
+ DBG_OPT(" %scert2=%s", label, end->cert2);
+ DBG_OPT(" %sca=%s", label, end->ca);
+ DBG_OPT(" %sca2=%s", label, end->ca2);
+ DBG_OPT(" %sgroups=%s", label, end->groups);
+ DBG_OPT(" %sgroups2=%s", label, end->groups2);
+ DBG_OPT(" %supdown=%s", label, end->updown);
}
/**
@@ -194,20 +207,20 @@ static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
pop_string(msg, &msg->add_conn.algorithms.ah);
pop_string(msg, &msg->add_conn.ikeme.mediated_by);
pop_string(msg, &msg->add_conn.ikeme.peerid);
- DBG2(DBG_CFG, " eap_identity=%s", msg->add_conn.eap_identity);
- DBG2(DBG_CFG, " aaa_identity=%s", msg->add_conn.aaa_identity);
- DBG2(DBG_CFG, " xauth_identity=%s", msg->add_conn.xauth_identity);
- DBG2(DBG_CFG, " ike=%s", msg->add_conn.algorithms.ike);
- DBG2(DBG_CFG, " esp=%s", msg->add_conn.algorithms.esp);
- DBG2(DBG_CFG, " ah=%s", msg->add_conn.algorithms.ah);
- DBG2(DBG_CFG, " dpddelay=%d", msg->add_conn.dpd.delay);
- DBG2(DBG_CFG, " dpdtimeout=%d", msg->add_conn.dpd.timeout);
- DBG2(DBG_CFG, " dpdaction=%d", msg->add_conn.dpd.action);
- DBG2(DBG_CFG, " closeaction=%d", msg->add_conn.close_action);
- DBG2(DBG_CFG, " mediation=%s", msg->add_conn.ikeme.mediation ? "yes" : "no");
- DBG2(DBG_CFG, " mediated_by=%s", msg->add_conn.ikeme.mediated_by);
- DBG2(DBG_CFG, " me_peerid=%s", msg->add_conn.ikeme.peerid);
- DBG2(DBG_CFG, " keyexchange=ikev%u", msg->add_conn.version);
+ DBG_OPT(" eap_identity=%s", msg->add_conn.eap_identity);
+ DBG_OPT(" aaa_identity=%s", msg->add_conn.aaa_identity);
+ DBG_OPT(" xauth_identity=%s", msg->add_conn.xauth_identity);
+ DBG_OPT(" ike=%s", msg->add_conn.algorithms.ike);
+ DBG_OPT(" esp=%s", msg->add_conn.algorithms.esp);
+ DBG_OPT(" ah=%s", msg->add_conn.algorithms.ah);
+ DBG_OPT(" dpddelay=%d", msg->add_conn.dpd.delay);
+ DBG_OPT(" dpdtimeout=%d", msg->add_conn.dpd.timeout);
+ DBG_OPT(" dpdaction=%d", msg->add_conn.dpd.action);
+ DBG_OPT(" closeaction=%d", msg->add_conn.close_action);
+ DBG_OPT(" mediation=%s", msg->add_conn.ikeme.mediation ? "yes" : "no");
+ DBG_OPT(" mediated_by=%s", msg->add_conn.ikeme.mediated_by);
+ DBG_OPT(" me_peerid=%s", msg->add_conn.ikeme.peerid);
+ DBG_OPT(" keyexchange=ikev%u", msg->add_conn.version);
this->config->add(this->config, msg);
this->attribute->add_dns(this->attribute, msg);
@@ -311,13 +324,13 @@ static void stroke_add_ca(private_stroke_socket_t *this,
pop_string(msg, &msg->add_ca.ocspuri);
pop_string(msg, &msg->add_ca.ocspuri2);
pop_string(msg, &msg->add_ca.certuribase);
- DBG2(DBG_CFG, "ca %s", msg->add_ca.name);
- DBG2(DBG_CFG, " cacert=%s", msg->add_ca.cacert);
- DBG2(DBG_CFG, " crluri=%s", msg->add_ca.crluri);
- DBG2(DBG_CFG, " crluri2=%s", msg->add_ca.crluri2);
- DBG2(DBG_CFG, " ocspuri=%s", msg->add_ca.ocspuri);
- DBG2(DBG_CFG, " ocspuri2=%s", msg->add_ca.ocspuri2);
- DBG2(DBG_CFG, " certuribase=%s", msg->add_ca.certuribase);
+ DBG2(DBG_CFG, "ca %s", msg->add_ca.name);
+ DBG_OPT(" cacert=%s", msg->add_ca.cacert);
+ DBG_OPT(" crluri=%s", msg->add_ca.crluri);
+ DBG_OPT(" crluri2=%s", msg->add_ca.crluri2);
+ DBG_OPT(" ocspuri=%s", msg->add_ca.ocspuri);
+ DBG_OPT(" ocspuri2=%s", msg->add_ca.ocspuri2);
+ DBG_OPT(" certuribase=%s", msg->add_ca.certuribase);
this->ca->add(this->ca, msg);
}
@@ -584,8 +597,7 @@ static void stroke_loglevel(private_stroke_socket_t *this,
}
else
{
- group = enum_from_name(debug_names, msg->loglevel.type);
- if ((int)group < 0)
+ if (!enum_from_name(debug_names, msg->loglevel.type, &group))
{
fprintf(out, "unknown type '%s'!\n", msg->loglevel.type);
return;
diff --git a/src/libcharon/plugins/systime_fix/Makefile.in b/src/libcharon/plugins/systime_fix/Makefile.in
index 76b2c5703..769ad52bc 100644
--- a/src/libcharon/plugins/systime_fix/Makefile.in
+++ b/src/libcharon/plugins/systime_fix/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
diff --git a/src/libcharon/plugins/tnc_ifmap/Makefile.am b/src/libcharon/plugins/tnc_ifmap/Makefile.am
index dfbb1b632..90fbf4651 100644
--- a/src/libcharon/plugins/tnc_ifmap/Makefile.am
+++ b/src/libcharon/plugins/tnc_ifmap/Makefile.am
@@ -6,7 +6,7 @@ AM_CPPFLAGS = \
AM_CFLAGS = \
${xml_CFLAGS} \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-tnc-ifmap.la
diff --git a/src/libcharon/plugins/tnc_ifmap/Makefile.in b/src/libcharon/plugins/tnc_ifmap/Makefile.in
index 194113088..51d46a673 100644
--- a/src/libcharon/plugins/tnc_ifmap/Makefile.in
+++ b/src/libcharon/plugins/tnc_ifmap/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -269,6 +269,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -287,6 +288,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -314,6 +316,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -405,6 +408,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -423,7 +427,7 @@ AM_CPPFLAGS = \
AM_CFLAGS = \
${xml_CFLAGS} \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnc-ifmap.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnc-ifmap.la
diff --git a/src/libcharon/plugins/tnc_pdp/Makefile.am b/src/libcharon/plugins/tnc_pdp/Makefile.am
index 48de82571..3478c5b30 100644
--- a/src/libcharon/plugins/tnc_pdp/Makefile.am
+++ b/src/libcharon/plugins/tnc_pdp/Makefile.am
@@ -9,7 +9,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libpttls
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-tnc-pdp.la
diff --git a/src/libcharon/plugins/tnc_pdp/Makefile.in b/src/libcharon/plugins/tnc_pdp/Makefile.in
index 875aa99d1..531c00c0c 100644
--- a/src/libcharon/plugins/tnc_pdp/Makefile.in
+++ b/src/libcharon/plugins/tnc_pdp/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -270,6 +270,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -288,6 +289,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -315,6 +317,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -406,6 +409,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -427,7 +431,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libpttls
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnc-pdp.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnc-pdp.la
diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp.c b/src/libcharon/plugins/tnc_pdp/tnc_pdp.c
index 89237f564..109c216d5 100644
--- a/src/libcharon/plugins/tnc_pdp/tnc_pdp.c
+++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp.c
@@ -18,6 +18,7 @@
#include <errno.h>
#include <unistd.h>
+#include <time.h>
#include <radius_message.h>
#include <radius_mppe.h>
@@ -37,7 +38,7 @@
#include <sa/eap/eap_method.h>
typedef struct private_tnc_pdp_t private_tnc_pdp_t;
-
+typedef struct client_entry_t client_entry_t;
/**
* Default RADIUS port, when not configured
*/
@@ -48,6 +49,8 @@ typedef struct private_tnc_pdp_t private_tnc_pdp_t;
*/
#define MAX_PACKET 4096
+#define RADIUS_RETRANSMIT_TIMEOUT 30 /* seconds */
+
/**
* private data of tnc_pdp_t
*/
@@ -99,6 +102,11 @@ struct private_tnc_pdp_t {
chunk_t secret;
/**
+ * RADIUS clients
+ */
+ linked_list_t *clients;
+
+ /**
* MD5 hasher
*/
hasher_t *hasher;
@@ -121,6 +129,33 @@ struct private_tnc_pdp_t {
};
/**
+ * Client entry helping to detect RADIUS packet retransmissions
+ */
+struct client_entry_t {
+
+ /**
+ * IP host address and port of client
+ */
+ host_t *host;
+
+ /**
+ * Time of last RADIUS Access-Request received from client
+ */
+ time_t last_time;
+
+ /**
+ * Identifier of last RADIUS Access-Request received from client
+ */
+ uint8_t last_id;
+};
+
+static void free_client_entry(client_entry_t *this)
+{
+ this->host->destroy(this->host);
+ free(this);
+}
+
+/**
* Open IPv4 or IPv6 UDP socket
*/
static int open_udp_socket(int family, u_int16_t port)
@@ -663,16 +698,24 @@ static bool radius_receive(private_tnc_pdp_t *this, int fd, watcher_event_t even
{
radius_message_t *request;
char buffer[MAX_PACKET];
+ client_entry_t *client;
+ bool retransmission = FALSE, found = FALSE, stale;
+ enumerator_t *enumerator;
int bytes_read = 0;
host_t *source;
+ uint8_t id;
+ time_t now;
+
union {
struct sockaddr_in in4;
struct sockaddr_in6 in6;
} src;
+
struct iovec iov = {
.iov_base = buffer,
.iov_len = MAX_PACKET,
};
+
struct msghdr msg = {
.msg_name = &src,
.msg_namelen = sizeof(src),
@@ -704,7 +747,46 @@ static bool radius_receive(private_tnc_pdp_t *this, int fd, watcher_event_t even
if (request->verify(request, NULL, this->secret, this->hasher,
this->signer))
{
- process_eap(this, request, source);
+ id = request->get_identifier(request);
+ now = time(NULL);
+
+ enumerator = this->clients->create_enumerator(this->clients);
+ while (enumerator->enumerate(enumerator, &client))
+ {
+ stale = client->last_time < now - RADIUS_RETRANSMIT_TIMEOUT;
+
+ if (source->equals(source, client->host))
+ {
+ retransmission = !stale && client->last_id == id;
+ client->last_id = id;
+ client->last_time = now;
+ found = TRUE;
+ }
+ else if (stale)
+ {
+ this->clients->remove_at(this->clients, enumerator);
+ free_client_entry(client);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!found)
+ {
+ client = malloc_thing(client_entry_t);
+ client->host = source->clone(source);
+ client->last_id = id;
+ client->last_time = now;
+ this->clients->insert_last(this->clients, client);
+ }
+ if (retransmission)
+ {
+ DBG1(DBG_CFG, "ignoring RADIUS Access-Request 0x%02x, "
+ "already processing", id);
+ }
+ else
+ {
+ process_eap(this, request, source);
+ }
}
request->destroy(request);
}
@@ -739,6 +821,10 @@ METHOD(tnc_pdp_t, destroy, void,
lib->watcher->remove(lib->watcher, this->radius_ipv6);
close(this->radius_ipv6);
}
+ if (this->clients)
+ {
+ this->clients->destroy_function(this->clients, (void*)free_client_entry);
+ }
DESTROY_IF(this->server);
DESTROY_IF(this->signer);
DESTROY_IF(this->hasher);
@@ -843,6 +929,7 @@ tnc_pdp_t *tnc_pdp_create(void)
this->radius_ipv4 = open_udp_socket(AF_INET, radius_port);
this->radius_ipv6 = open_udp_socket(AF_INET6, radius_port);
this->secret = chunk_from_str(secret);
+ this->clients = linked_list_create();
this->type = eap_type_from_string(eap_type_str);
this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
this->signer = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_MD5_128);
diff --git a/src/libcharon/plugins/uci/Makefile.am b/src/libcharon/plugins/uci/Makefile.am
index 1fcd9ed25..134ced0e3 100644
--- a/src/libcharon/plugins/uci/Makefile.am
+++ b/src/libcharon/plugins/uci/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-uci.la
diff --git a/src/libcharon/plugins/uci/Makefile.in b/src/libcharon/plugins/uci/Makefile.in
index 8c38ceade..948db7e3c 100644
--- a/src/libcharon/plugins/uci/Makefile.in
+++ b/src/libcharon/plugins/uci/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -264,6 +264,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -282,6 +283,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -309,6 +311,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -400,6 +403,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -416,7 +420,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-uci.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-uci.la
diff --git a/src/libcharon/plugins/unit_tester/Makefile.am b/src/libcharon/plugins/unit_tester/Makefile.am
index 21cf08c61..b7f8fc319 100644
--- a/src/libcharon/plugins/unit_tester/Makefile.am
+++ b/src/libcharon/plugins/unit_tester/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-unit-tester.la
diff --git a/src/libcharon/plugins/unit_tester/Makefile.in b/src/libcharon/plugins/unit_tester/Makefile.in
index 165590dee..6e4dbff2b 100644
--- a/src/libcharon/plugins/unit_tester/Makefile.in
+++ b/src/libcharon/plugins/unit_tester/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -269,6 +269,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -287,6 +288,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -314,6 +316,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -405,6 +408,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -421,7 +425,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-unit-tester.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-unit-tester.la
diff --git a/src/libcharon/plugins/unity/Makefile.am b/src/libcharon/plugins/unity/Makefile.am
index b50dc9a03..38923e068 100644
--- a/src/libcharon/plugins/unity/Makefile.am
+++ b/src/libcharon/plugins/unity/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-unity.la
diff --git a/src/libcharon/plugins/unity/Makefile.in b/src/libcharon/plugins/unity/Makefile.in
index efb7e958d..4d411f68e 100644
--- a/src/libcharon/plugins/unity/Makefile.in
+++ b/src/libcharon/plugins/unity/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -265,6 +265,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -283,6 +284,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -310,6 +312,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -401,6 +404,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -417,7 +421,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-unity.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-unity.la
diff --git a/src/libcharon/plugins/updown/Makefile.am b/src/libcharon/plugins/updown/Makefile.am
index a35909408..f03f4744c 100644
--- a/src/libcharon/plugins/updown/Makefile.am
+++ b/src/libcharon/plugins/updown/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-updown.la
diff --git a/src/libcharon/plugins/updown/Makefile.in b/src/libcharon/plugins/updown/Makefile.in
index 36cf78eca..b377110ec 100644
--- a/src/libcharon/plugins/updown/Makefile.in
+++ b/src/libcharon/plugins/updown/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-updown.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-updown.la
diff --git a/src/libcharon/plugins/updown/updown_listener.c b/src/libcharon/plugins/updown/updown_listener.c
index 2c3f93298..200f298a1 100644
--- a/src/libcharon/plugins/updown/updown_listener.c
+++ b/src/libcharon/plugins/updown/updown_listener.c
@@ -344,12 +344,12 @@ METHOD(listener_t, child_updown, bool,
"PLUTO_UNIQUEID='%u' "
"PLUTO_ME='%H' "
"PLUTO_MY_ID='%Y' "
- "PLUTO_MY_CLIENT='%H/%u' "
+ "PLUTO_MY_CLIENT='%+H/%u' "
"PLUTO_MY_PORT='%u' "
"PLUTO_MY_PROTOCOL='%u' "
"PLUTO_PEER='%H' "
"PLUTO_PEER_ID='%Y' "
- "PLUTO_PEER_CLIENT='%H/%u' "
+ "PLUTO_PEER_CLIENT='%+H/%u' "
"PLUTO_PEER_PORT='%u' "
"PLUTO_PEER_PROTOCOL='%u' "
"%s"
diff --git a/src/libcharon/plugins/vici/Makefile.am b/src/libcharon/plugins/vici/Makefile.am
new file mode 100644
index 000000000..7e459c58d
--- /dev/null
+++ b/src/libcharon/plugins/vici/Makefile.am
@@ -0,0 +1,69 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon \
+ -DIPSEC_PIDDIR=\"${piddir}\"
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-vici.la
+else
+plugin_LTLIBRARIES = libstrongswan-vici.la
+endif
+
+libstrongswan_vici_la_SOURCES = \
+ vici_socket.h vici_socket.c \
+ vici_message.h vici_message.c \
+ vici_builder.h vici_builder.c \
+ vici_dispatcher.h vici_dispatcher.c \
+ vici_query.h vici_query.c \
+ vici_control.h vici_control.c \
+ vici_config.h vici_config.c \
+ vici_cred.h vici_cred.c \
+ vici_attribute.h vici_attribute.c \
+ vici_logger.h vici_logger.c \
+ vici_plugin.h vici_plugin.c
+
+libstrongswan_vici_la_LDFLAGS = -module -avoid-version
+
+
+EXTRA_DIST = README.md
+
+
+ipseclib_LTLIBRARIES = libvici.la
+
+libvici_la_SOURCES = \
+ vici_message.c vici_message.h \
+ vici_builder.c vici_builder.h \
+ libvici.c libvici.h
+
+libvici_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
+
+
+TESTS = vici_tests
+
+check_PROGRAMS = $(TESTS)
+
+vici_tests_SOURCES = \
+ suites/test_socket.c \
+ suites/test_message.c \
+ suites/test_request.c \
+ suites/test_event.c \
+ vici_socket.c \
+ vici_message.c \
+ vici_builder.c \
+ vici_dispatcher.c \
+ libvici.c \
+ vici_tests.h vici_tests.c
+
+vici_tests_CFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libstrongswan/tests \
+ @COVERAGE_CFLAGS@
+
+vici_tests_LDFLAGS = @COVERAGE_LDFLAGS@
+vici_tests_LDADD = \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(top_builddir)/src/libstrongswan/tests/libtest.la
diff --git a/src/libcharon/plugins/vici/Makefile.in b/src/libcharon/plugins/vici/Makefile.in
new file mode 100644
index 000000000..e0a6a1b5d
--- /dev/null
+++ b/src/libcharon/plugins/vici/Makefile.in
@@ -0,0 +1,1183 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+TESTS = vici_tests$(EXEEXT)
+check_PROGRAMS = $(am__EXEEXT_1)
+subdir = src/libcharon/plugins/vici
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/split-package-version.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(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'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(ipseclibdir)" "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(ipseclib_LTLIBRARIES) $(noinst_LTLIBRARIES) \
+ $(plugin_LTLIBRARIES)
+libstrongswan_vici_la_LIBADD =
+am_libstrongswan_vici_la_OBJECTS = vici_socket.lo vici_message.lo \
+ vici_builder.lo vici_dispatcher.lo vici_query.lo \
+ vici_control.lo vici_config.lo vici_cred.lo vici_attribute.lo \
+ vici_logger.lo vici_plugin.lo
+libstrongswan_vici_la_OBJECTS = $(am_libstrongswan_vici_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+libstrongswan_vici_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_vici_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_vici_la_rpath = -rpath $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_vici_la_rpath =
+libvici_la_DEPENDENCIES = \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+am_libvici_la_OBJECTS = vici_message.lo vici_builder.lo libvici.lo
+libvici_la_OBJECTS = $(am_libvici_la_OBJECTS)
+am__EXEEXT_1 = vici_tests$(EXEEXT)
+am__dirstamp = $(am__leading_dot)dirstamp
+am_vici_tests_OBJECTS = suites/vici_tests-test_socket.$(OBJEXT) \
+ suites/vici_tests-test_message.$(OBJEXT) \
+ suites/vici_tests-test_request.$(OBJEXT) \
+ suites/vici_tests-test_event.$(OBJEXT) \
+ vici_tests-vici_socket.$(OBJEXT) \
+ vici_tests-vici_message.$(OBJEXT) \
+ vici_tests-vici_builder.$(OBJEXT) \
+ vici_tests-vici_dispatcher.$(OBJEXT) \
+ vici_tests-libvici.$(OBJEXT) vici_tests-vici_tests.$(OBJEXT)
+vici_tests_OBJECTS = $(am_vici_tests_OBJECTS)
+vici_tests_DEPENDENCIES = \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(top_builddir)/src/libstrongswan/tests/libtest.la
+vici_tests_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(vici_tests_CFLAGS) \
+ $(CFLAGS) $(vici_tests_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+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) $(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_CC_1 =
+CCLD = $(CC)
+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_CCLD_1 =
+SOURCES = $(libstrongswan_vici_la_SOURCES) $(libvici_la_SOURCES) \
+ $(vici_tests_SOURCES)
+DIST_SOURCES = $(libstrongswan_vici_la_SOURCES) $(libvici_la_SOURCES) \
+ $(vici_tests_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red=''; \
+ grn=''; \
+ lgn=''; \
+ blu=''; \
+ mgn=''; \
+ brg=''; \
+ std=''; \
+ fi; \
+}
+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@
+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@
+ECHO_N = @ECHO_N@
+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@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
+PTHREADLIB = @PTHREADLIB@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+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@
+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@
+aikgen_plugins = @aikgen_plugins@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+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@
+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@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+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@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon \
+ -DIPSEC_PIDDIR=\"${piddir}\"
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-vici.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-vici.la
+libstrongswan_vici_la_SOURCES = \
+ vici_socket.h vici_socket.c \
+ vici_message.h vici_message.c \
+ vici_builder.h vici_builder.c \
+ vici_dispatcher.h vici_dispatcher.c \
+ vici_query.h vici_query.c \
+ vici_control.h vici_control.c \
+ vici_config.h vici_config.c \
+ vici_cred.h vici_cred.c \
+ vici_attribute.h vici_attribute.c \
+ vici_logger.h vici_logger.c \
+ vici_plugin.h vici_plugin.c
+
+libstrongswan_vici_la_LDFLAGS = -module -avoid-version
+EXTRA_DIST = README.md
+ipseclib_LTLIBRARIES = libvici.la
+libvici_la_SOURCES = \
+ vici_message.c vici_message.h \
+ vici_builder.c vici_builder.h \
+ libvici.c libvici.h
+
+libvici_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
+vici_tests_SOURCES = \
+ suites/test_socket.c \
+ suites/test_message.c \
+ suites/test_request.c \
+ suites/test_event.c \
+ vici_socket.c \
+ vici_message.c \
+ vici_builder.c \
+ vici_dispatcher.c \
+ libvici.c \
+ vici_tests.h vici_tests.c
+
+vici_tests_CFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libstrongswan/tests \
+ @COVERAGE_CFLAGS@
+
+vici_tests_LDFLAGS = @COVERAGE_LDFLAGS@
+vici_tests_LDADD = \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(top_builddir)/src/libstrongswan/tests/libtest.la
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/vici/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/vici/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+install-ipseclibLTLIBRARIES: $(ipseclib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(ipseclib_LTLIBRARIES)'; test -n "$(ipseclibdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(ipseclibdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(ipseclibdir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(ipseclibdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(ipseclibdir)"; \
+ }
+
+uninstall-ipseclibLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(ipseclib_LTLIBRARIES)'; test -n "$(ipseclibdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(ipseclibdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(ipseclibdir)/$$f"; \
+ done
+
+clean-ipseclibLTLIBRARIES:
+ -test -z "$(ipseclib_LTLIBRARIES)" || rm -f $(ipseclib_LTLIBRARIES)
+ @list='$(ipseclib_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(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)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libstrongswan-vici.la: $(libstrongswan_vici_la_OBJECTS) $(libstrongswan_vici_la_DEPENDENCIES) $(EXTRA_libstrongswan_vici_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libstrongswan_vici_la_LINK) $(am_libstrongswan_vici_la_rpath) $(libstrongswan_vici_la_OBJECTS) $(libstrongswan_vici_la_LIBADD) $(LIBS)
+
+libvici.la: $(libvici_la_OBJECTS) $(libvici_la_DEPENDENCIES) $(EXTRA_libvici_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) -rpath $(ipseclibdir) $(libvici_la_OBJECTS) $(libvici_la_LIBADD) $(LIBS)
+
+clean-checkPROGRAMS:
+ @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+suites/$(am__dirstamp):
+ @$(MKDIR_P) suites
+ @: > suites/$(am__dirstamp)
+suites/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) suites/$(DEPDIR)
+ @: > suites/$(DEPDIR)/$(am__dirstamp)
+suites/vici_tests-test_socket.$(OBJEXT): suites/$(am__dirstamp) \
+ suites/$(DEPDIR)/$(am__dirstamp)
+suites/vici_tests-test_message.$(OBJEXT): suites/$(am__dirstamp) \
+ suites/$(DEPDIR)/$(am__dirstamp)
+suites/vici_tests-test_request.$(OBJEXT): suites/$(am__dirstamp) \
+ suites/$(DEPDIR)/$(am__dirstamp)
+suites/vici_tests-test_event.$(OBJEXT): suites/$(am__dirstamp) \
+ suites/$(DEPDIR)/$(am__dirstamp)
+
+vici_tests$(EXEEXT): $(vici_tests_OBJECTS) $(vici_tests_DEPENDENCIES) $(EXTRA_vici_tests_DEPENDENCIES)
+ @rm -f vici_tests$(EXEEXT)
+ $(AM_V_CCLD)$(vici_tests_LINK) $(vici_tests_OBJECTS) $(vici_tests_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+ -rm -f suites/*.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvici.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_attribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_builder.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_control.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_cred.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_dispatcher.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_logger.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_message.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_query.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_socket.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_tests-libvici.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_tests-vici_builder.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_tests-vici_dispatcher.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_tests-vici_message.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_tests-vici_socket.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_tests-vici_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/vici_tests-test_event.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/vici_tests-test_message.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/vici_tests-test_request.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/vici_tests-test_socket.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+suites/vici_tests-test_socket.o: suites/test_socket.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT suites/vici_tests-test_socket.o -MD -MP -MF suites/$(DEPDIR)/vici_tests-test_socket.Tpo -c -o suites/vici_tests-test_socket.o `test -f 'suites/test_socket.c' || echo '$(srcdir)/'`suites/test_socket.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/vici_tests-test_socket.Tpo suites/$(DEPDIR)/vici_tests-test_socket.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_socket.c' object='suites/vici_tests-test_socket.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -c -o suites/vici_tests-test_socket.o `test -f 'suites/test_socket.c' || echo '$(srcdir)/'`suites/test_socket.c
+
+suites/vici_tests-test_socket.obj: suites/test_socket.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT suites/vici_tests-test_socket.obj -MD -MP -MF suites/$(DEPDIR)/vici_tests-test_socket.Tpo -c -o suites/vici_tests-test_socket.obj `if test -f 'suites/test_socket.c'; then $(CYGPATH_W) 'suites/test_socket.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_socket.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/vici_tests-test_socket.Tpo suites/$(DEPDIR)/vici_tests-test_socket.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_socket.c' object='suites/vici_tests-test_socket.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -c -o suites/vici_tests-test_socket.obj `if test -f 'suites/test_socket.c'; then $(CYGPATH_W) 'suites/test_socket.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_socket.c'; fi`
+
+suites/vici_tests-test_message.o: suites/test_message.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT suites/vici_tests-test_message.o -MD -MP -MF suites/$(DEPDIR)/vici_tests-test_message.Tpo -c -o suites/vici_tests-test_message.o `test -f 'suites/test_message.c' || echo '$(srcdir)/'`suites/test_message.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/vici_tests-test_message.Tpo suites/$(DEPDIR)/vici_tests-test_message.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_message.c' object='suites/vici_tests-test_message.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -c -o suites/vici_tests-test_message.o `test -f 'suites/test_message.c' || echo '$(srcdir)/'`suites/test_message.c
+
+suites/vici_tests-test_message.obj: suites/test_message.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT suites/vici_tests-test_message.obj -MD -MP -MF suites/$(DEPDIR)/vici_tests-test_message.Tpo -c -o suites/vici_tests-test_message.obj `if test -f 'suites/test_message.c'; then $(CYGPATH_W) 'suites/test_message.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_message.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/vici_tests-test_message.Tpo suites/$(DEPDIR)/vici_tests-test_message.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_message.c' object='suites/vici_tests-test_message.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -c -o suites/vici_tests-test_message.obj `if test -f 'suites/test_message.c'; then $(CYGPATH_W) 'suites/test_message.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_message.c'; fi`
+
+suites/vici_tests-test_request.o: suites/test_request.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT suites/vici_tests-test_request.o -MD -MP -MF suites/$(DEPDIR)/vici_tests-test_request.Tpo -c -o suites/vici_tests-test_request.o `test -f 'suites/test_request.c' || echo '$(srcdir)/'`suites/test_request.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/vici_tests-test_request.Tpo suites/$(DEPDIR)/vici_tests-test_request.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_request.c' object='suites/vici_tests-test_request.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -c -o suites/vici_tests-test_request.o `test -f 'suites/test_request.c' || echo '$(srcdir)/'`suites/test_request.c
+
+suites/vici_tests-test_request.obj: suites/test_request.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT suites/vici_tests-test_request.obj -MD -MP -MF suites/$(DEPDIR)/vici_tests-test_request.Tpo -c -o suites/vici_tests-test_request.obj `if test -f 'suites/test_request.c'; then $(CYGPATH_W) 'suites/test_request.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_request.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/vici_tests-test_request.Tpo suites/$(DEPDIR)/vici_tests-test_request.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_request.c' object='suites/vici_tests-test_request.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -c -o suites/vici_tests-test_request.obj `if test -f 'suites/test_request.c'; then $(CYGPATH_W) 'suites/test_request.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_request.c'; fi`
+
+suites/vici_tests-test_event.o: suites/test_event.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT suites/vici_tests-test_event.o -MD -MP -MF suites/$(DEPDIR)/vici_tests-test_event.Tpo -c -o suites/vici_tests-test_event.o `test -f 'suites/test_event.c' || echo '$(srcdir)/'`suites/test_event.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/vici_tests-test_event.Tpo suites/$(DEPDIR)/vici_tests-test_event.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_event.c' object='suites/vici_tests-test_event.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -c -o suites/vici_tests-test_event.o `test -f 'suites/test_event.c' || echo '$(srcdir)/'`suites/test_event.c
+
+suites/vici_tests-test_event.obj: suites/test_event.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT suites/vici_tests-test_event.obj -MD -MP -MF suites/$(DEPDIR)/vici_tests-test_event.Tpo -c -o suites/vici_tests-test_event.obj `if test -f 'suites/test_event.c'; then $(CYGPATH_W) 'suites/test_event.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_event.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/vici_tests-test_event.Tpo suites/$(DEPDIR)/vici_tests-test_event.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_event.c' object='suites/vici_tests-test_event.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -c -o suites/vici_tests-test_event.obj `if test -f 'suites/test_event.c'; then $(CYGPATH_W) 'suites/test_event.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_event.c'; fi`
+
+vici_tests-vici_socket.o: vici_socket.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-vici_socket.o -MD -MP -MF $(DEPDIR)/vici_tests-vici_socket.Tpo -c -o vici_tests-vici_socket.o `test -f 'vici_socket.c' || echo '$(srcdir)/'`vici_socket.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-vici_socket.Tpo $(DEPDIR)/vici_tests-vici_socket.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vici_socket.c' object='vici_tests-vici_socket.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-vici_socket.o `test -f 'vici_socket.c' || echo '$(srcdir)/'`vici_socket.c
+
+vici_tests-vici_socket.obj: vici_socket.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-vici_socket.obj -MD -MP -MF $(DEPDIR)/vici_tests-vici_socket.Tpo -c -o vici_tests-vici_socket.obj `if test -f 'vici_socket.c'; then $(CYGPATH_W) 'vici_socket.c'; else $(CYGPATH_W) '$(srcdir)/vici_socket.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-vici_socket.Tpo $(DEPDIR)/vici_tests-vici_socket.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vici_socket.c' object='vici_tests-vici_socket.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-vici_socket.obj `if test -f 'vici_socket.c'; then $(CYGPATH_W) 'vici_socket.c'; else $(CYGPATH_W) '$(srcdir)/vici_socket.c'; fi`
+
+vici_tests-vici_message.o: vici_message.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-vici_message.o -MD -MP -MF $(DEPDIR)/vici_tests-vici_message.Tpo -c -o vici_tests-vici_message.o `test -f 'vici_message.c' || echo '$(srcdir)/'`vici_message.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-vici_message.Tpo $(DEPDIR)/vici_tests-vici_message.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vici_message.c' object='vici_tests-vici_message.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-vici_message.o `test -f 'vici_message.c' || echo '$(srcdir)/'`vici_message.c
+
+vici_tests-vici_message.obj: vici_message.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-vici_message.obj -MD -MP -MF $(DEPDIR)/vici_tests-vici_message.Tpo -c -o vici_tests-vici_message.obj `if test -f 'vici_message.c'; then $(CYGPATH_W) 'vici_message.c'; else $(CYGPATH_W) '$(srcdir)/vici_message.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-vici_message.Tpo $(DEPDIR)/vici_tests-vici_message.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vici_message.c' object='vici_tests-vici_message.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-vici_message.obj `if test -f 'vici_message.c'; then $(CYGPATH_W) 'vici_message.c'; else $(CYGPATH_W) '$(srcdir)/vici_message.c'; fi`
+
+vici_tests-vici_builder.o: vici_builder.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-vici_builder.o -MD -MP -MF $(DEPDIR)/vici_tests-vici_builder.Tpo -c -o vici_tests-vici_builder.o `test -f 'vici_builder.c' || echo '$(srcdir)/'`vici_builder.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-vici_builder.Tpo $(DEPDIR)/vici_tests-vici_builder.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vici_builder.c' object='vici_tests-vici_builder.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-vici_builder.o `test -f 'vici_builder.c' || echo '$(srcdir)/'`vici_builder.c
+
+vici_tests-vici_builder.obj: vici_builder.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-vici_builder.obj -MD -MP -MF $(DEPDIR)/vici_tests-vici_builder.Tpo -c -o vici_tests-vici_builder.obj `if test -f 'vici_builder.c'; then $(CYGPATH_W) 'vici_builder.c'; else $(CYGPATH_W) '$(srcdir)/vici_builder.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-vici_builder.Tpo $(DEPDIR)/vici_tests-vici_builder.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vici_builder.c' object='vici_tests-vici_builder.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-vici_builder.obj `if test -f 'vici_builder.c'; then $(CYGPATH_W) 'vici_builder.c'; else $(CYGPATH_W) '$(srcdir)/vici_builder.c'; fi`
+
+vici_tests-vici_dispatcher.o: vici_dispatcher.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-vici_dispatcher.o -MD -MP -MF $(DEPDIR)/vici_tests-vici_dispatcher.Tpo -c -o vici_tests-vici_dispatcher.o `test -f 'vici_dispatcher.c' || echo '$(srcdir)/'`vici_dispatcher.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-vici_dispatcher.Tpo $(DEPDIR)/vici_tests-vici_dispatcher.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vici_dispatcher.c' object='vici_tests-vici_dispatcher.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-vici_dispatcher.o `test -f 'vici_dispatcher.c' || echo '$(srcdir)/'`vici_dispatcher.c
+
+vici_tests-vici_dispatcher.obj: vici_dispatcher.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-vici_dispatcher.obj -MD -MP -MF $(DEPDIR)/vici_tests-vici_dispatcher.Tpo -c -o vici_tests-vici_dispatcher.obj `if test -f 'vici_dispatcher.c'; then $(CYGPATH_W) 'vici_dispatcher.c'; else $(CYGPATH_W) '$(srcdir)/vici_dispatcher.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-vici_dispatcher.Tpo $(DEPDIR)/vici_tests-vici_dispatcher.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vici_dispatcher.c' object='vici_tests-vici_dispatcher.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-vici_dispatcher.obj `if test -f 'vici_dispatcher.c'; then $(CYGPATH_W) 'vici_dispatcher.c'; else $(CYGPATH_W) '$(srcdir)/vici_dispatcher.c'; fi`
+
+vici_tests-libvici.o: libvici.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-libvici.o -MD -MP -MF $(DEPDIR)/vici_tests-libvici.Tpo -c -o vici_tests-libvici.o `test -f 'libvici.c' || echo '$(srcdir)/'`libvici.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-libvici.Tpo $(DEPDIR)/vici_tests-libvici.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libvici.c' object='vici_tests-libvici.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-libvici.o `test -f 'libvici.c' || echo '$(srcdir)/'`libvici.c
+
+vici_tests-libvici.obj: libvici.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-libvici.obj -MD -MP -MF $(DEPDIR)/vici_tests-libvici.Tpo -c -o vici_tests-libvici.obj `if test -f 'libvici.c'; then $(CYGPATH_W) 'libvici.c'; else $(CYGPATH_W) '$(srcdir)/libvici.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-libvici.Tpo $(DEPDIR)/vici_tests-libvici.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libvici.c' object='vici_tests-libvici.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-libvici.obj `if test -f 'libvici.c'; then $(CYGPATH_W) 'libvici.c'; else $(CYGPATH_W) '$(srcdir)/libvici.c'; fi`
+
+vici_tests-vici_tests.o: vici_tests.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-vici_tests.o -MD -MP -MF $(DEPDIR)/vici_tests-vici_tests.Tpo -c -o vici_tests-vici_tests.o `test -f 'vici_tests.c' || echo '$(srcdir)/'`vici_tests.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-vici_tests.Tpo $(DEPDIR)/vici_tests-vici_tests.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vici_tests.c' object='vici_tests-vici_tests.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-vici_tests.o `test -f 'vici_tests.c' || echo '$(srcdir)/'`vici_tests.c
+
+vici_tests-vici_tests.obj: vici_tests.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-vici_tests.obj -MD -MP -MF $(DEPDIR)/vici_tests-vici_tests.Tpo -c -o vici_tests-vici_tests.obj `if test -f 'vici_tests.c'; then $(CYGPATH_W) 'vici_tests.c'; else $(CYGPATH_W) '$(srcdir)/vici_tests.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-vici_tests.Tpo $(DEPDIR)/vici_tests-vici_tests.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vici_tests.c' object='vici_tests-vici_tests.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-vici_tests.obj `if test -f 'vici_tests.c'; then $(CYGPATH_W) 'vici_tests.c'; else $(CYGPATH_W) '$(srcdir)/vici_tests.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ $(am__tty_colors); \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=XPASS; \
+ ;; \
+ *) \
+ col=$$grn; res=PASS; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xfail=`expr $$xfail + 1`; \
+ col=$$lgn; res=XFAIL; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=FAIL; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ col=$$blu; res=SKIP; \
+ fi; \
+ echo "$${col}$$res$${std}: $$tst"; \
+ done; \
+ if test "$$all" -eq 1; then \
+ tests="test"; \
+ All=""; \
+ else \
+ tests="tests"; \
+ All="All "; \
+ fi; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="$$All$$all $$tests passed"; \
+ else \
+ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all $$tests failed"; \
+ else \
+ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ if test "$$skip" -eq 1; then \
+ skipped="($$skip test was not run)"; \
+ else \
+ skipped="($$skip tests were not run)"; \
+ fi; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ if test "$$failed" -eq 0; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ fi; \
+ echo "$${col}$$dashes$${std}"; \
+ echo "$${col}$$banner$${std}"; \
+ test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
+ test -z "$$report" || echo "$${col}$$report$${std}"; \
+ echo "$${col}$$dashes$${std}"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(ipseclibdir)" "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f suites/$(DEPDIR)/$(am__dirstamp)
+ -rm -f suites/$(am__dirstamp)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-checkPROGRAMS clean-generic clean-ipseclibLTLIBRARIES \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR) suites/$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-ipseclibLTLIBRARIES install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR) suites/$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-ipseclibLTLIBRARIES \
+ uninstall-pluginLTLIBRARIES
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \
+ clean-checkPROGRAMS clean-generic clean-ipseclibLTLIBRARIES \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-ipseclibLTLIBRARIES \
+ install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \
+ uninstall-ipseclibLTLIBRARIES uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/vici/README.md b/src/libcharon/plugins/vici/README.md
new file mode 100644
index 000000000..aeabbbd4d
--- /dev/null
+++ b/src/libcharon/plugins/vici/README.md
@@ -0,0 +1,176 @@
+# The Versatile IKE Control Interface (VICI) protocol #
+
+The vici plugin implements the server side of an IPC protocol to configure,
+monitor and control the IKE daemon charon. It uses request/response and event
+messages to communicate over a reliable stream based transport.
+
+## Transport protocol ##
+
+To provide the service, the plugin opens a listening socket using a reliable,
+stream based transport. charon relies on the different stream service
+abstractions provided by libstrongswan, such as TCP and UNIX sockets.
+
+A client connects to this service to access functionality. It may send an
+arbitrary number of packets over the connection before closing it.
+
+To exchange data, the transport protocol is segmented into byte sequences.
+Each byte sequence is prefixed by a 32-bit length header in network order,
+followed by the data. The maximum segment length is currently limited to 512KB
+of data, and the length field contains the length of the data only, not
+including the length field itself.
+
+The order of byte sequences must be strict, byte sequences must arrive in the
+same order as sent.
+
+## Packet layer ##
+
+Within the byte sequences defined by the transport layer, both the client
+and the server can exchange packets. The type of packet defines its structure
+and purpose. The packet type is a 8-bit identifier, and is the first byte
+in a transport layer byte sequence. The length of the packet is given by the
+transport layer.
+
+While a packet type may define the format of the wrapped data freely, currently
+all types either contain a name, a message or both. The following packet types
+are currently defined:
+
+* _CMD_REQUEST = 0_: A named request message
+* _CMD_RESPONSE = 1_: An unnamed response message for a request
+* _CMD_UNKNOWN = 2_: An unnamed response if requested command is unknown
+* _EVENT_REGISTER = 3_: A named event registration request
+* _EVENT_UNREGISTER = 4_: A named event deregistration request
+* _EVENT_CONFIRM = 5_: An unnamed response for successful event (de-)registration
+* _EVENT_UNKNOWN = 6_: A unnamed response if event (de-)registration failed
+* _EVENT = 7_: A named event message
+
+For packets having a named type, after the packet type an 8-bit length header
+of the name follows, indicating the string length in bytes of the name tag, not
+including the length field itself. The name is an ASCII string that is not
+null-terminated.
+
+The rest of the packet forms the exchanged message, the length is determined
+by the transport byte sequence length, subtracting the packet type and
+the optional name tag in some messages.
+
+### Commands ###
+
+Commands are currently always requested by the client. The server replies with
+a response, or with a CMD_UNKNOWN failure message to let the client know
+that it does not have a handler for such a command. There is no sequence number
+to associate responses to requests, so only one command can be active at
+a time on a single connection.
+
+### Events ###
+
+To receive event messages, the client explicitly registers for events by name,
+and also unregisters if it does not want to receive events of the named kind
+anymore. The server confirms event registration using EVENT_CONFIRM, or
+indicates that there is no such event source with EVENT_UNKNOWN.
+
+Events may get raised at any time while registered, even during an active
+request command. This mechanism is used to feed continuous data during a request,
+for example.
+
+## Message format ##
+
+The defined packet types optionally wrap a message with additional data.
+Messages are currently used in CMD_REQUEST/CMD_RESPONSE, and in EVENT packets.
+A message uses a hierarchial tree of sections. Each section (or the implicit
+root section) contains an arbitrary set of key/value pairs, lists and
+sub-sections. The length of a message is not part of the message itself, but
+the wrapping layer, usually calculated from the transport byte sequence length.
+
+The message encoding consists of a sequence of elements. Each element starts
+with the element type, optionally followed by an element name and/or an element
+value. Currently the following message element types are defined:
+
+* _SECTION_START = 0_: Begin a new section having a name
+* _SECTION_END = 1_: End a previously started section
+* _KEY_VALUE = 2_: Define a value for a named key in the current section
+* _LIST_START = 3_: Begin a named list for list items
+* _LIST_ITEM = 4_: Define an unnamed item value in the current list
+* _LIST_END = 5_: End a previously started list
+
+Types are encoded as 8-bit values. Types having a name (SECTION_START,
+KEY_VALUE and LIST_START) have an ASCII string following the type, which itself
+uses an 8-bit length header. The string must not be null-terminated, the string
+length does not include the length field itself.
+
+Types having a value (KEY_VALUE and LIST_ITEM) have a raw blob sequence,
+prefixed with a 16-bit network order length. The blob follows the type or the
+name tag if available, the length defined by the length field does not include
+the length field itself.
+
+The interpretation of any value is not defined by the message format; it can
+take arbitrary blobs. The application may specify types for specific keys, such
+as strings or integer representations.
+
+### Sections ###
+
+Sections may be opened in the implicit root section, or any previously section.
+They can be nested to arbitrary levels. A SECTION_END marker always closes
+the last opened section; SECTION_START and SECTION_END items must be balanced
+in a valid message.
+
+### Key/Values ###
+
+Key/Value pair elements may appear in the implicit root section or any explicit
+sub-section at any level. Key names must be unique in the current section, use
+lists to define multiple values for a key. Key/values may not appear in lists,
+use a sub-section instead.
+
+### Lists ###
+
+Lists may appear at the same locations as Key/Values, and may not be nested.
+Only a single list may be opened at the same time, and all lists must be closed
+in valid messages. After opening a list, only list items may appear before the
+list closing element. Empty lists are allowed, list items may appear within
+lists only.
+
+### Encoding example ###
+
+Consider the following structure using pseudo-markup for this example:
+
+ key1 = value1
+ section1 = {
+ sub-section = {
+ key2 = value2
+ }
+ list1 = [ item1, item2 ]
+ }
+
+The example above reprensents a valid tree structure, that gets encoded as
+the following C array:
+
+ char msg[] = {
+ /* key1 = value1 */
+ 2, 4,'k','e','y','1', 0,6,'v','a','l','u','e','1',
+ /* section1 */
+ 0, 8,'s','e','c','t','i','o','n','1',
+ /* sub-section */
+ 0, 11,'s','u','b','-','s','e','c','t','i','o','n',
+ /* key2 = value2 */
+ 2, 4,'k','e','y','2', 0,6,'v','a','l','u','e','2',
+ /* sub-section end */
+ 1,
+ /* list1 */
+ 3, 5, 'l','i','s','t','1',
+ /* item1 */
+ 4, 0,5,'i','t','e','m','1',
+ /* item2 */
+ 4, 0,5,'i','t','e','m','2',
+ /* list1 end */
+ 5,
+ /* section1 end */
+ 1,
+ };
+
+# libvici C client library #
+
+libvici is the reference implementation of a C client library implementing
+the vici protocol. It builds upon libstrongswan, but provides a stable API
+to implement client applications in the C programming language. libvici uses
+the libstrongswan thread pool to deliver event messages asynchronously.
+
+More information about the libvici API is available in the libvici.h header
+file.
diff --git a/src/libcharon/plugins/vici/libvici.c b/src/libcharon/plugins/vici/libvici.c
new file mode 100644
index 000000000..a2cbb3082
--- /dev/null
+++ b/src/libcharon/plugins/vici/libvici.c
@@ -0,0 +1,764 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "libvici.h"
+#include "vici_builder.h"
+#include "vici_dispatcher.h"
+#include "vici_socket.h"
+
+#include <library.h>
+#include <threading/mutex.h>
+#include <threading/condvar.h>
+#include <collections/hashtable.h>
+
+#include <errno.h>
+
+/**
+ * Event registration
+ */
+typedef struct {
+ /** name of event */
+ char *name;
+ /** callback function */
+ vici_event_cb_t cb;
+ /** user data for callback */
+ void *user;
+} event_t;
+
+/**
+ * Wait state signaled by asynchronous on_read callback
+ */
+typedef enum {
+ WAIT_IDLE = 0,
+ WAIT_SUCCESS,
+ WAIT_FAILURE,
+ WAIT_READ_ERROR,
+} wait_state_t;
+
+/**
+ * Private vici connection contex.
+ */
+struct vici_conn_t {
+ /** connection stream */
+ stream_t *stream;
+ /** event registrations, as char* => event_t */
+ hashtable_t *events;
+ /** connection lock */
+ mutex_t *mutex;
+ /** condvar to signal incoming response */
+ condvar_t *cond;
+ /** queued response message */
+ chunk_t queue;
+ /** asynchronous read error */
+ int error;
+ /** wait state */
+ wait_state_t wait;
+};
+
+/**
+ * Private vici request message.
+ */
+struct vici_req_t {
+ /** connection context */
+ vici_conn_t *conn;
+ /** name of request message */
+ char *name;
+ /** message builder */
+ vici_builder_t *b;
+};
+
+/**
+ * Private vici response/event message.
+ */
+struct vici_res_t {
+ /** response message */
+ vici_message_t *message;
+ /** allocated strings */
+ linked_list_t *strings;
+ /** item enumerator */
+ enumerator_t *enumerator;
+ /** currently enumerating type */
+ vici_type_t type;
+ /** currently enumerating name */
+ char *name;
+ /** currently enumerating value */
+ chunk_t value;
+ /** section nesting level of callback parser */
+ int level;
+};
+
+/**
+ * Signal wait result for waiting user thread
+ */
+static bool wait_result(vici_conn_t *conn, wait_state_t wait)
+{
+ conn->mutex->lock(conn->mutex);
+ conn->wait = wait;
+ conn->mutex->unlock(conn->mutex);
+ conn->cond->signal(conn->cond);
+ return FALSE;
+}
+
+/**
+ * Signal wait error result for waiting user thread
+ */
+static bool read_error(vici_conn_t *conn, int err)
+{
+ conn->error = err;
+ return wait_result(conn, WAIT_READ_ERROR);
+}
+
+/**
+ * Handle a command response message
+ */
+static bool handle_response(vici_conn_t *conn, u_int32_t len)
+{
+ chunk_t buf;
+
+ buf = chunk_alloc(len);
+ if (!conn->stream->read_all(conn->stream, buf.ptr, buf.len))
+ {
+ free(buf.ptr);
+ return read_error(conn, errno);
+ }
+ conn->queue = buf;
+ return wait_result(conn, WAIT_SUCCESS);
+}
+
+/**
+ * Dispatch received event message
+ */
+static bool handle_event(vici_conn_t *conn, u_int32_t len)
+{
+ vici_message_t *message;
+ event_t *event;
+ u_int8_t namelen;
+ char name[257], *buf;
+
+ if (len < sizeof(namelen))
+ {
+ return read_error(conn, EBADMSG);
+ }
+ if (!conn->stream->read_all(conn->stream, &namelen, sizeof(namelen)))
+ {
+ return read_error(conn, errno);
+ }
+ if (namelen > len - sizeof(namelen))
+ {
+ return read_error(conn, EBADMSG);
+ }
+ if (!conn->stream->read_all(conn->stream, name, namelen))
+ {
+ return read_error(conn, errno);
+ }
+ name[namelen] = '\0';
+ len -= sizeof(namelen) + namelen;
+ buf = malloc(len);
+ if (!conn->stream->read_all(conn->stream, buf, len))
+ {
+ free(buf);
+ return read_error(conn, errno);
+ }
+ message = vici_message_create_from_data(chunk_create(buf, len), TRUE);
+
+ conn->mutex->lock(conn->mutex);
+ event = conn->events->get(conn->events, name);
+ if (event)
+ {
+ vici_res_t res = {
+ .message = message,
+ .enumerator = message->create_enumerator(message),
+ .strings = linked_list_create(),
+ };
+
+ event->cb(event->user, name, &res);
+
+ res.enumerator->destroy(res.enumerator);
+ res.strings->destroy_function(res.strings, free);
+ }
+ conn->mutex->unlock(conn->mutex);
+
+ message->destroy(message);
+
+ return TRUE;
+}
+
+CALLBACK(on_read, bool,
+ vici_conn_t *conn, stream_t *stream)
+{
+ u_int32_t len;
+ u_int8_t op;
+ ssize_t hlen;
+
+ hlen = stream->read(stream, &len, sizeof(len), FALSE);
+ if (hlen <= 0)
+ {
+ if (errno == EWOULDBLOCK)
+ {
+ return TRUE;
+ }
+ return read_error(conn, errno);
+ }
+ if (hlen < sizeof(len))
+ {
+ if (!stream->read_all(stream, ((void*)&len) + hlen, sizeof(len) - hlen))
+ {
+ return read_error(conn, errno);
+ }
+ }
+
+ len = ntohl(len);
+ if (len > VICI_MESSAGE_SIZE_MAX)
+ {
+ return read_error(conn, EBADMSG);
+ }
+ if (len-- < sizeof(op))
+ {
+ return read_error(conn, EBADMSG);
+ }
+ if (!stream->read_all(stream, &op, sizeof(op)))
+ {
+ return read_error(conn, errno);
+ }
+ switch (op)
+ {
+ case VICI_EVENT:
+ return handle_event(conn, len);
+ case VICI_CMD_RESPONSE:
+ return handle_response(conn, len);
+ case VICI_EVENT_CONFIRM:
+ return wait_result(conn, WAIT_SUCCESS);
+ case VICI_CMD_UNKNOWN:
+ case VICI_EVENT_UNKNOWN:
+ return wait_result(conn, WAIT_FAILURE);
+ case VICI_CMD_REQUEST:
+ case VICI_EVENT_REGISTER:
+ case VICI_EVENT_UNREGISTER:
+ default:
+ return read_error(conn, EBADMSG);
+ }
+}
+
+vici_conn_t* vici_connect(char *uri)
+{
+ vici_conn_t *conn;
+ stream_t *stream;
+
+ stream = lib->streams->connect(lib->streams, uri ?: VICI_DEFAULT_URI);
+ if (!stream)
+ {
+ return NULL;
+ }
+
+ INIT(conn,
+ .stream = stream,
+ .events = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .cond = condvar_create(CONDVAR_TYPE_DEFAULT),
+ );
+
+ stream->on_read(stream, on_read, conn);
+
+ return conn;
+}
+
+void vici_disconnect(vici_conn_t *conn)
+{
+ enumerator_t *enumerator;
+ event_t *event;
+
+ conn->stream->destroy(conn->stream);
+ enumerator = conn->events->create_enumerator(conn->events);
+ while (enumerator->enumerate(enumerator, NULL, &event))
+ {
+ free(event->name);
+ free(event);
+ }
+ enumerator->destroy(enumerator);
+ conn->events->destroy(conn->events);
+ conn->mutex->destroy(conn->mutex);
+ conn->cond->destroy(conn->cond);
+ free(conn);
+}
+
+vici_req_t* vici_begin(char *name)
+{
+ vici_req_t *req;
+
+ INIT(req,
+ .name = strdup(name),
+ .b = vici_builder_create(),
+ );
+
+ return req;
+}
+
+void vici_begin_section(vici_req_t *req, char *name)
+{
+ req->b->add(req->b, VICI_SECTION_START, name);
+}
+
+void vici_end_section(vici_req_t *req)
+{
+ req->b->add(req->b, VICI_SECTION_END);
+}
+
+void vici_add_key_value(vici_req_t *req, char *key, void *buf, int len)
+{
+ req->b->add(req->b, VICI_KEY_VALUE, key, chunk_create(buf, len));
+}
+
+void vici_add_key_valuef(vici_req_t *req, char *key, char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ req->b->vadd_kv(req->b, key, fmt, args);
+ va_end(args);
+}
+
+void vici_begin_list(vici_req_t *req, char *name)
+{
+ req->b->add(req->b, VICI_LIST_START, name);
+}
+
+void vici_add_list_item(vici_req_t *req, void *buf, int len)
+{
+ req->b->add(req->b, VICI_LIST_ITEM, chunk_create(buf, len));
+}
+
+void vici_add_list_itemf(vici_req_t *req, char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ req->b->vadd_li(req->b, fmt, args);
+ va_end(args);
+}
+
+void vici_end_list(vici_req_t *req)
+{
+ req->b->add(req->b, VICI_LIST_END);
+}
+
+vici_res_t* vici_submit(vici_req_t *req, vici_conn_t *conn)
+{
+ vici_message_t *message;
+ vici_res_t *res;
+ chunk_t data;
+ u_int32_t len;
+ u_int8_t namelen, op;
+
+ message = req->b->finalize(req->b);
+ if (!message)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ op = VICI_CMD_REQUEST;
+ namelen = strlen(req->name);
+ data = message->get_encoding(message);
+ len = htonl(sizeof(op) + sizeof(namelen) + namelen + data.len);
+
+ if (!conn->stream->write_all(conn->stream, &len, sizeof(len)) ||
+ !conn->stream->write_all(conn->stream, &op, sizeof(op)) ||
+ !conn->stream->write_all(conn->stream, &namelen, sizeof(namelen)) ||
+ !conn->stream->write_all(conn->stream, req->name, namelen) ||
+ !conn->stream->write_all(conn->stream, data.ptr, data.len))
+ {
+ free(req->name);
+ free(req);
+ message->destroy(message);
+ return NULL;
+ }
+ free(req->name);
+ free(req);
+ message->destroy(message);
+
+ message = NULL;
+ conn->mutex->lock(conn->mutex);
+ while (conn->wait == WAIT_IDLE)
+ {
+ conn->cond->wait(conn->cond, conn->mutex);
+ }
+ switch (conn->wait)
+ {
+ case WAIT_SUCCESS:
+ message = vici_message_create_from_data(conn->queue, TRUE);
+ conn->queue = chunk_empty;
+ break;
+ case WAIT_READ_ERROR:
+ errno = conn->error;
+ break;
+ case WAIT_FAILURE:
+ default:
+ errno = ENOENT;
+ break;
+ }
+ conn->wait = WAIT_IDLE;
+ conn->mutex->unlock(conn->mutex);
+
+ conn->stream->on_read(conn->stream, on_read, conn);
+
+ if (message)
+ {
+ INIT(res,
+ .message = message,
+ .enumerator = message->create_enumerator(message),
+ .strings = linked_list_create(),
+ );
+ return res;
+ }
+ return NULL;
+}
+
+void vici_free_req(vici_req_t *req)
+{
+ vici_message_t *message;
+
+ free(req->name);
+ message = req->b->finalize(req->b);
+ if (message)
+ {
+ message->destroy(message);
+ }
+ free(req);
+}
+
+int vici_dump(vici_res_t *res, char *label, bool pretty, FILE *out)
+{
+ if (res->message->dump(res->message, label, pretty, out))
+ {
+ return 0;
+ }
+ errno = EBADMSG;
+ return 1;
+}
+
+vici_parse_t vici_parse(vici_res_t *res)
+{
+ if (!res->enumerator->enumerate(res->enumerator,
+ &res->type, &res->name, &res->value))
+ {
+ return VICI_PARSE_ERROR;
+ }
+ switch (res->type)
+ {
+ case VICI_END:
+ return VICI_PARSE_END;
+ case VICI_SECTION_START:
+ return VICI_PARSE_BEGIN_SECTION;
+ case VICI_SECTION_END:
+ return VICI_PARSE_END_SECTION;
+ case VICI_LIST_START:
+ return VICI_PARSE_BEGIN_LIST;
+ case VICI_LIST_ITEM:
+ return VICI_PARSE_LIST_ITEM;
+ case VICI_LIST_END:
+ return VICI_PARSE_END_LIST;
+ case VICI_KEY_VALUE:
+ return VICI_PARSE_KEY_VALUE;
+ default:
+ return VICI_PARSE_ERROR;
+ }
+}
+
+char* vici_parse_name(vici_res_t *res)
+{
+ char *name;
+
+ switch (res->type)
+ {
+ case VICI_SECTION_START:
+ case VICI_LIST_START:
+ case VICI_KEY_VALUE:
+ name = strdup(res->name);
+ res->strings->insert_last(res->strings, name);
+ return name;
+ default:
+ errno = EINVAL;
+ return NULL;
+ }
+}
+
+int vici_parse_name_eq(vici_res_t *res, char *name)
+{
+ switch (res->type)
+ {
+ case VICI_SECTION_START:
+ case VICI_LIST_START:
+ case VICI_KEY_VALUE:
+ return streq(name, res->name) ? 1 : 0;
+ default:
+ return 0;
+ }
+}
+
+void* vici_parse_value(vici_res_t *res, int *len)
+{
+ switch (res->type)
+ {
+ case VICI_LIST_ITEM:
+ case VICI_KEY_VALUE:
+ *len = res->value.len;
+ return res->value.ptr;
+ default:
+ *len = 0;
+ errno = EINVAL;
+ return NULL;
+ }
+}
+
+char* vici_parse_value_str(vici_res_t *res)
+{
+ char *val;
+
+ switch (res->type)
+ {
+ case VICI_LIST_ITEM:
+ case VICI_KEY_VALUE:
+ if (!chunk_printable(res->value, NULL, 0))
+ {
+ errno = EBADMSG;
+ return NULL;
+ }
+ val = strndup(res->value.ptr, res->value.len);
+ res->strings->insert_last(res->strings, val);
+ return val;
+ default:
+ errno = EINVAL;
+ return NULL;
+ }
+}
+
+int vici_parse_cb(vici_res_t *res, vici_parse_section_cb_t section,
+ vici_parse_value_cb_t kv, vici_parse_value_cb_t li,
+ void *user)
+{
+ char *name, *list = NULL;
+ void *value;
+ int base, len, ret;
+
+ base = res->level;
+
+ while (TRUE)
+ {
+ switch (vici_parse(res))
+ {
+ case VICI_PARSE_KEY_VALUE:
+ if (res->level == base)
+ {
+ if (kv)
+ {
+ name = vici_parse_name(res);
+ value = vici_parse_value(res, &len);
+ if (name && value)
+ {
+ ret = kv(user, res, name, value, len);
+ if (ret)
+ {
+ return ret;
+ }
+ }
+ }
+ }
+ break;
+ case VICI_PARSE_BEGIN_SECTION:
+ if (res->level++ == base)
+ {
+ if (section)
+ {
+ name = vici_parse_name(res);
+ if (name)
+ {
+ ret = section(user, res, name);
+ if (ret)
+ {
+ return ret;
+ }
+ }
+ }
+ }
+ break;
+ case VICI_PARSE_END_SECTION:
+ if (res->level-- == base)
+ {
+ return 0;
+ }
+ break;
+ case VICI_PARSE_END:
+ res->level = 0;
+ return 0;
+ case VICI_PARSE_BEGIN_LIST:
+ if (res->level == base)
+ {
+ list = vici_parse_name(res);
+ }
+ break;
+ case VICI_PARSE_LIST_ITEM:
+ if (list && li)
+ {
+ value = vici_parse_value(res, &len);
+ if (value)
+ {
+ ret = li(user, res, list, value, len);
+ if (ret)
+ {
+ return ret;
+ }
+ }
+ }
+ break;
+ case VICI_PARSE_END_LIST:
+ if (res->level == base)
+ {
+ list = NULL;
+ }
+ break;
+ case VICI_PARSE_ERROR:
+ res->level = 0;
+ errno = EBADMSG;
+ return 1;
+ }
+ }
+}
+
+void* vici_find(vici_res_t *res, int *len, char *fmt, ...)
+{
+ va_list args;
+ chunk_t value;
+
+ va_start(args, fmt);
+ value = res->message->vget_value(res->message, chunk_empty, fmt, args);
+ va_end(args);
+
+ *len = value.len;
+ return value.ptr;
+}
+
+char* vici_find_str(vici_res_t *res, char *def, char *fmt, ...)
+{
+ va_list args;
+ char *str;
+
+ va_start(args, fmt);
+ str = res->message->vget_str(res->message, def, fmt, args);
+ va_end(args);
+
+ return str;
+}
+
+int vici_find_int(vici_res_t *res, int def, char *fmt, ...)
+{
+ va_list args;
+ int val;
+
+ va_start(args, fmt);
+ val = res->message->vget_int(res->message, def, fmt, args);
+ va_end(args);
+
+ return val;
+}
+
+void vici_free_res(vici_res_t *res)
+{
+ res->strings->destroy_function(res->strings, free);
+ res->message->destroy(res->message);
+ res->enumerator->destroy(res->enumerator);
+ free(res);
+}
+
+int vici_register(vici_conn_t *conn, char *name, vici_event_cb_t cb, void *user)
+{
+ event_t *event;
+ u_int32_t len;
+ u_int8_t namelen, op;
+ int ret = 1;
+
+ op = cb ? VICI_EVENT_REGISTER : VICI_EVENT_UNREGISTER;
+ namelen = strlen(name);
+ len = htonl(sizeof(op) + sizeof(namelen) + namelen);
+ if (!conn->stream->write_all(conn->stream, &len, sizeof(len)) ||
+ !conn->stream->write_all(conn->stream, &op, sizeof(op)) ||
+ !conn->stream->write_all(conn->stream, &namelen, sizeof(namelen)) ||
+ !conn->stream->write_all(conn->stream, name, namelen))
+ {
+ return 1;
+ }
+
+ conn->mutex->lock(conn->mutex);
+ while (conn->wait == WAIT_IDLE)
+ {
+ conn->cond->wait(conn->cond, conn->mutex);
+ }
+ switch (conn->wait)
+ {
+ case WAIT_SUCCESS:
+ ret = 0;
+ break;
+ case WAIT_READ_ERROR:
+ errno = conn->error;
+ break;
+ case WAIT_FAILURE:
+ default:
+ errno = ENOENT;
+ break;
+ }
+ conn->wait = WAIT_IDLE;
+ conn->mutex->unlock(conn->mutex);
+
+ conn->stream->on_read(conn->stream, on_read, conn);
+
+ if (ret == 0)
+ {
+ conn->mutex->lock(conn->mutex);
+ if (cb)
+ {
+ INIT(event,
+ .name = strdup(name),
+ .cb = cb,
+ .user = user,
+ );
+ event = conn->events->put(conn->events, event->name, event);
+ }
+ else
+ {
+ event = conn->events->remove(conn->events, name);
+ }
+ conn->mutex->unlock(conn->mutex);
+
+ if (event)
+ {
+ free(event->name);
+ free(event);
+ }
+ }
+ return ret;
+}
+
+void vici_init()
+{
+ library_init(NULL, "vici");
+ if (lib->processor->get_total_threads(lib->processor) < 4)
+ {
+ lib->processor->set_threads(lib->processor, 4);
+ }
+}
+
+void vici_deinit()
+{
+ library_deinit();
+}
diff --git a/src/libcharon/plugins/vici/libvici.h b/src/libcharon/plugins/vici/libvici.h
new file mode 100644
index 000000000..58595d8cc
--- /dev/null
+++ b/src/libcharon/plugins/vici/libvici.h
@@ -0,0 +1,459 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup libvici libvici
+ * @{ @ingroup vici
+ *
+ * libvici is a low-level client library for the "Versatile IKE Control
+ * Interface" protocol. While it uses libstrongswan and its thread-pool for
+ * asynchronous message delivery, this interface does not directly depend on
+ * libstrongswan interfaces and should be stable.
+ *
+ * This interface provides the following basic functions:
+ *
+ * - vici_init()/vici_deinit(): Library initialization functions
+ * - vici_connect(): Connect to a vici service
+ * - vici_disconnect(): Disconnect from a vici service
+ *
+ * Library initialization implicitly initializes libstrongswan and a small
+ * thread pool.
+ *
+ * Connecting requires an uri, which is currently either a UNIX socket path
+ * prefixed with unix://, or a hostname:port touple prefixed with tcp://.
+ * Passing NULL takes the system default socket path.
+ *
+ * After the connection has been established, request messages can be sent.
+ * Only a single thread may operate on a single connection instance
+ * simultaneously. To construct request messages, use the following functions:
+ *
+ * - vici_add_key_value() / vici_add_key_valuef(): Add key/value pairs
+ * - vici_begin(): Start constructing a new request message
+ * - vici_begin_section(): Open a new section to add contents to
+ * - vici_end_section(): Close a previously opened session
+ * - vici_begin_list(): Open a new list to add list items to
+ * - vici_end_list(): Close a previously opened list
+ * - vici_add_list_item() / vici_add_list_itemf(): Add list item
+ *
+ * Once the request message is complete, it can be sent or cancelled with:
+ *
+ * - vici_submit()
+ * - vici_free_req()
+ *
+ * If submitting a message is successful, a response message is returned. It
+ * can be processed using the following functions:
+ *
+ * - vici_parse(): Parse content type
+ * - vici_parse_name(): Parse name if content type provides one
+ * - vici_parse_name_eq(): Parse name and check if matches string
+ * - vici_parse_value() / vici_parse_value_str(): Parse value for content type
+ * - vici_dump(): Dump a full response to a FILE stream
+ * - vici_free_res(): Free response after use
+ *
+ * Usually vici_parse() is called in a loop, and depending on the returned
+ * type the name and value can be inspected.
+ *
+ * To register or unregister for asynchronous event messages vici_register() is
+ * used. The registered callback gets invoked by an asynchronous thread. To
+ * parse the event message, the vici_parse*() functions can be used.
+ */
+
+#ifndef LIBVICI_H_
+#define LIBVICI_H_
+
+#include <stdio.h>
+
+#include <utils/utils.h>
+
+/**
+ * Opaque vici connection contex.
+ */
+typedef struct vici_conn_t vici_conn_t;
+
+/**
+ * Opaque vici request message.
+ */
+typedef struct vici_req_t vici_req_t;
+
+/**
+ * Opaque vici response/event message.
+ */
+typedef struct vici_res_t vici_res_t;
+
+/**
+ * Vici parse result, as returned by vici_parse().
+ */
+typedef enum {
+ /** encountered a section start, has a name */
+ VICI_PARSE_BEGIN_SECTION,
+ /** encountered a section end */
+ VICI_PARSE_END_SECTION,
+ /** encountered a list start, has a name */
+ VICI_PARSE_BEGIN_LIST,
+ /** encountered a list element, has a value */
+ VICI_PARSE_LIST_ITEM,
+ /** encountered a list end */
+ VICI_PARSE_END_LIST,
+ /** encountered a key/value pair, has a name and a value */
+ VICI_PARSE_KEY_VALUE,
+ /** encountered valid end of message */
+ VICI_PARSE_END,
+ /** parse error */
+ VICI_PARSE_ERROR,
+} vici_parse_t;
+
+/**
+ * Callback function invoked for received event messages.
+ *
+ * It is not allowed to call vici_submit() from this callback.
+ *
+ * @param user user data, as passed to vici_connect
+ * @param name name of received event
+ * @param msg associated event message, destroyed by libvici
+ */
+typedef void (*vici_event_cb_t)(void *user, char *name, vici_res_t *msg);
+
+/**
+ * Callback function for key/value and list items, invoked by vici_parse_cb().
+ *
+ * @param user user data, as passed to vici_parse_cb()
+ * @param res message currently parsing
+ * @param name name of key or list
+ * @param value value buffer
+ * @param len length of value buffer
+ * @return 0 if parsed successfully
+ */
+typedef int (*vici_parse_value_cb_t)(void *user, vici_res_t *res, char *name,
+ void *value, int len);
+
+/**
+ * Callback function for sections, invoked by vici_parse_cb().
+ *
+ * @param user user data, as passed to vici_parse_cb()
+ * @param res message currently parsing
+ * @param name name of the section
+ * @return 0 if parsed successfully
+ */
+typedef int (*vici_parse_section_cb_t)(void *user, vici_res_t *res, char *name);
+
+/**
+ * Open a new vici connection.
+ *
+ * On error, NULL is returned and errno is set appropriately.
+ *
+ * @param uri URI to connect to, NULL to use system default
+ * @return opaque vici connection context, NULL on error
+ */
+vici_conn_t* vici_connect(char *uri);
+
+/**
+ * Close a vici connection.
+ *
+ * @param conn connection context
+ */
+void vici_disconnect(vici_conn_t *conn);
+
+/**
+ * Begin a new vici message request.
+ *
+ * This function always succeeds.
+ *
+ * @param name name of request command
+ * @return request message, to add contents
+ */
+vici_req_t* vici_begin(char *name);
+
+/**
+ * Begin a new section in a vici request message.
+ *
+ * @param req request message to create a new section in
+ * @param name name of section to create
+ */
+void vici_begin_section(vici_req_t *req, char *name);
+
+/**
+ * End a previously opened section.
+ *
+ * @param req request message to close an open section in
+ */
+void vici_end_section(vici_req_t *req);
+
+/**
+ * Add a key/value pair, using an as-is blob as value.
+ *
+ * @param req request message to add key/value pair to
+ * @param key key name of key/value pair
+ * @param buf pointer to blob to add as value
+ * @param len length of value blob to add
+ */
+void vici_add_key_value(vici_req_t *req, char *key, void *buf, int len);
+
+/**
+ * Add a key/value pair, setting value from a printf() format string.
+ *
+ * @param req request message to add key/value pair to
+ * @param key key name of key/value pair
+ * @param fmt format string for value
+ * @param ... arguments to format string
+ */
+void vici_add_key_valuef(vici_req_t *req, char *key, char *fmt, ...);
+
+/**
+ * Begin a list in a request message.
+ *
+ * After starting a list, only list items can be added until the list gets
+ * closed by vici_end_list().
+ *
+ * @param req request message to begin list in
+ * @param name name of list to begin
+ */
+void vici_begin_list(vici_req_t *req, char *name);
+
+/**
+ * Add a list item to a currently open list, using an as-is blob.
+ *
+ * @param req request message to add list item to
+ * @param buf pointer to blob to add as value
+ * @param len length of value blob to add
+ */
+void vici_add_list_item(vici_req_t *req, void *buf, int len);
+
+/**
+ * Add a list item to a currently open list, using a printf() format string.
+ *
+ * @param req request message to add list item to
+ * @param fmt format string to create value from
+ * @param ... arguments to format string
+ */
+void vici_add_list_itemf(vici_req_t *req, char *fmt, ...);
+
+/**
+ * End a previously opened list in a request message.
+ *
+ * @param req request message to end list in
+ */
+void vici_end_list(vici_req_t *req);
+
+/**
+ * Submit a request message, and wait for response.
+ *
+ * The request messages gets cleaned up by this call and gets invalid.
+ * On error, NULL is returned an errno is set to:
+ * - EINVAL if the request is invalid/incomplete
+ * - ENOENT if the command is unknown
+ * - EBADMSG if the response is invalid
+ * - Any other IO related errno
+ *
+ * @param req request message to send
+ * @param conn connection context to send message over
+ * @return response message, NULL on error
+ */
+vici_res_t* vici_submit(vici_req_t *req, vici_conn_t *conn);
+
+/**
+ * Cancel a request message started.
+ *
+ * If a request created by vici_begin() does not get submitted using
+ * vici_submit(), it has to get freed using this call.
+ *
+ * @param req request message to clean up
+ */
+void vici_free_req(vici_req_t *req);
+
+/**
+ * Dump a message text representation to a FILE stream.
+ *
+ * On error, errno is set to:
+ * - EBADMSG if the message is invalid
+ *
+ * @param res response message to dump
+ * @param label a label to print for this message
+ * @param pretty use pretty print with indentation
+ * @param out FILE to dump to
+ * @return 0 if dumped complete message, 1 on error
+ */
+int vici_dump(vici_res_t *res, char *label, bool pretty, FILE *out);
+
+/**
+ * Parse next element from a vici response message.
+ *
+ * @param res response message to parse
+ * @return parse result
+ */
+vici_parse_t vici_parse(vici_res_t *res);
+
+/**
+ * Parse name tag / key of a previously parsed element.
+ *
+ * This call is valid only after vici_parse() returned VICI_PARSE_KEY_VALUE,
+ * VICI_PARSE_BEGIN_SECTION or VICI_PARSE_BEGIN_LIST.
+ *
+ * The string is valid until vici_free_res() is called.
+ *
+ * On error, errno is set to:
+ *- EINVAL if not in valid parser state
+ *
+ * @param res response message to parse
+ * @return name tag / key, NULL on error
+ */
+char* vici_parse_name(vici_res_t *res);
+
+/**
+ * Compare name tag / key of a previusly parsed element.
+ *
+ * This call is valid only after vici_parse() returned VICI_PARSE_KEY_VALUE,
+ * VICI_PARSE_BEGIN_SECTION or VICI_PARSE_BEGIN_LIST.
+ *
+ * @param res response message to parse
+ * @param name string to compare
+ * @return 1 if name equals, 0 if not
+ */
+int vici_parse_name_eq(vici_res_t *res, char *name);
+
+/**
+ * Parse value of a previously parsed element, as a blob.
+ *
+ * This call is valid only after vici_parse() returned VICI_PARSE_KEY_VALUE or
+ * VICI_PARSE_LIST_ITEM.
+ *
+ * The string is valid until vici_free_res() is called.
+ *
+ * On error, errno is set to:
+ * - EINVAL if not in valid parser state
+ *
+ * @param res response message to parse
+ * @param len pointer receiving value length
+ * @return pointer to value, NULL on error
+ */
+void* vici_parse_value(vici_res_t *res, int *len);
+
+/**
+ * Parse value of a previously parsed element, as a string.
+ *
+ * This call is valid only after vici_parse() returned VICI_PARSE_KEY_VALUE or
+ * VICI_PARSE_LIST_ITEM.
+ *
+ * This call is successful only if the value contains no non-printable
+ * characters. The string is valid until vici_free_res() is called.
+ *
+ * On error, errno is set to:
+ * - EBADMSG if value is not a printable string
+ * - EINVAL if not in valid parser state
+ *
+ * @param res response message to parse
+ * @return value as string, NULL on error
+ */
+char* vici_parse_value_str(vici_res_t *res);
+
+/**
+ * Parse a complete message with callbacks.
+ *
+ * Any of the callbacks may be NULL to skip this kind of item. Callbacks are
+ * invoked for the current section level only. To descent into sections, call
+ * vici_parse_cb() from within a section callback.
+ *
+ * On error, errno is set to:
+ * - EBADMSG if message encoding invalid
+ * - Any other errno set by the invoked callbacks
+ *
+ * @param res message to parse
+ * @param section callback invoked for each section
+ * @param kv callback invoked for key/value pairs
+ * @param li callback invoked for list items
+ * @param user user data to pass to callbacks
+ * @return 0 if parsing successful
+ */
+int vici_parse_cb(vici_res_t *res, vici_parse_section_cb_t section,
+ vici_parse_value_cb_t kv, vici_parse_value_cb_t li,
+ void *user);
+
+/*
+ * Find a blob value in a message for a given key.
+ *
+ * Sections can be selected by prefixing them separated by dots.
+ *
+ * @param res response message to parse
+ * @param len length of returned object
+ * @param fmt printf format string of key and sections
+ * @param ... arguments to format string
+ * @return blob value, having *len bytes, NULL if not found
+ */
+void *vici_find(vici_res_t *res, int *len, char *fmt, ...);
+
+/**
+ * Find a string value in a message for a given key.
+ *
+ * Sections can be selected by prefixing them separated by dots.
+ *
+ * @param res response message to parse
+ * @param def default value, if key not found
+ * @param fmt printf format string of key and sections
+ * @param ... arguments to format string
+ * @return string, def if not found
+ */
+char* vici_find_str(vici_res_t *res, char *def, char *fmt, ...);
+
+/**
+ * Find an integer value in a message for a given key.
+ *
+ * Sections can be selected by prefixing them separated by dots.
+ *
+ * @param res response message to parse
+ * @param def default value, if key not found
+ * @param fmt printf format string of key and sections
+ * @param ... arguments to format string
+ * @return integer value, def if not found
+ */
+int vici_find_int(vici_res_t *res, int def, char *fmt, ...);
+
+/**
+ * Clean up a received response message.
+ *
+ * Event messages get cleaned up by the library, it is not allowed to call
+ * vici_free_res() from within a vici_event_cb_t.
+ *
+ * @param res response message to free
+ */
+void vici_free_res(vici_res_t *res);
+
+/**
+ * (Un-)Register for events of a given kind.
+ *
+ * Events callbacks get invoked by a different thread from the libstrongswan
+ * thread pool.
+ * On failure, errno is set to:
+ * - ENOENT if the event name is unknown
+ * - EBADMSG if the response is invalid
+ * - Any other IO related errno
+ *
+ * @param conn connection context
+ * @param name name of event messages to register to
+ * @param cb callback function to register, NULL to unregister
+ * @param user user data passed to callback invocations
+ * @return 0 if registered successfully
+ */
+int vici_register(vici_conn_t *conn, char *name, vici_event_cb_t cb, void *user);
+
+/**
+ * Initialize libvici before first time use.
+ */
+void vici_init();
+
+/**
+ * Deinitialize libvici after use.
+ */
+void vici_deinit();
+
+#endif /** LIBVICI_H_ @}*/
diff --git a/src/libcharon/plugins/vici/suites/test_event.c b/src/libcharon/plugins/vici/suites/test_event.c
new file mode 100644
index 000000000..b923ad393
--- /dev/null
+++ b/src/libcharon/plugins/vici/suites/test_event.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <test_suite.h>
+
+#include "../vici_dispatcher.h"
+#include "../libvici.h"
+
+#include <unistd.h>
+
+#ifdef WIN32
+# define URI "tcp://127.0.0.1:6543"
+#else /* !WIN32 */
+# define URI "unix:///tmp/strongswan-vici-event-test"
+#endif /* !WIN32 */
+
+static void event_cb(void *user, char *name, vici_res_t *ev)
+{
+ int *count = (int*)user;
+
+ ck_assert_str_eq(name, "test");
+ ck_assert(vici_parse(ev) == VICI_PARSE_KEY_VALUE);
+ ck_assert_str_eq(vici_parse_name(ev), "key1");
+ ck_assert_str_eq(vici_parse_value_str(ev), "value1");
+ ck_assert(vici_parse(ev) == VICI_PARSE_END);
+
+ (*count)++;
+}
+
+START_TEST(test_event)
+{
+ vici_dispatcher_t *dispatcher;
+ vici_conn_t *conn;
+ int count = 0;
+
+ lib->processor->set_threads(lib->processor, 8);
+
+ dispatcher = vici_dispatcher_create(URI);
+ ck_assert(dispatcher);
+
+ dispatcher->manage_event(dispatcher, "test", TRUE);
+
+ vici_init();
+ conn = vici_connect(URI);
+ ck_assert(conn);
+
+ ck_assert(vici_register(conn, "test", event_cb, &count) == 0);
+ ck_assert(vici_register(conn, "nonexistent", event_cb, &count) != 0);
+
+ dispatcher->raise_event(dispatcher, "test", 0, vici_message_create_from_args(
+ VICI_KEY_VALUE, "key1", chunk_from_str("value1"),
+ VICI_END));
+
+ while (count == 0)
+ {
+ usleep(1000);
+ }
+
+ vici_disconnect(conn);
+
+ dispatcher->manage_event(dispatcher, "test", FALSE);
+
+ lib->processor->cancel(lib->processor);
+ dispatcher->destroy(dispatcher);
+
+ vici_deinit();
+}
+END_TEST
+
+#define EVENT_COUNT 500
+
+CALLBACK(raise_cb, vici_message_t*,
+ vici_dispatcher_t *dispatcher, char *name, u_int id, vici_message_t *req)
+{
+ u_int i;
+
+ for (i = 0; i < EVENT_COUNT; i++)
+ {
+ dispatcher->raise_event(dispatcher, "event", id,
+ vici_message_create_from_args(
+ VICI_KEY_VALUE, "counter", chunk_from_thing(i),
+ VICI_END));
+ }
+ return vici_message_create_from_args(VICI_END);
+}
+
+CALLBACK(raise_event_cb, void,
+ int *count, char *name, vici_res_t *ev)
+{
+ u_int *value, len;
+
+ ck_assert_str_eq(name, "event");
+ ck_assert(vici_parse(ev) == VICI_PARSE_KEY_VALUE);
+ ck_assert_str_eq(vici_parse_name(ev), "counter");
+ value = vici_parse_value(ev, &len);
+ ck_assert_int_eq(len, sizeof(*value));
+ ck_assert(vici_parse(ev) == VICI_PARSE_END);
+
+ ck_assert_int_eq(*count, *value);
+ (*count)++;
+}
+
+START_TEST(test_raise_events)
+{
+ vici_dispatcher_t *dispatcher;
+ vici_res_t *res;
+ vici_conn_t *conn;
+ int count = 0;
+
+ lib->processor->set_threads(lib->processor, 8);
+
+ dispatcher = vici_dispatcher_create(URI);
+ ck_assert(dispatcher);
+
+ dispatcher->manage_event(dispatcher, "event", TRUE);
+ dispatcher->manage_command(dispatcher, "raise", raise_cb, dispatcher);
+
+ vici_init();
+ conn = vici_connect(URI);
+ ck_assert(conn);
+
+ ck_assert(vici_register(conn, "event", raise_event_cb, &count) == 0);
+
+ res = vici_submit(vici_begin("raise"), conn);
+
+ ck_assert_int_eq(count, EVENT_COUNT);
+ ck_assert(res);
+ vici_free_res(res);
+
+ vici_disconnect(conn);
+
+ dispatcher->manage_event(dispatcher, "event", FALSE);
+ dispatcher->manage_command(dispatcher, "raise", NULL, NULL);
+
+ lib->processor->cancel(lib->processor);
+ dispatcher->destroy(dispatcher);
+
+ vici_deinit();
+}
+END_TEST
+
+START_TEST(test_stress)
+{
+ vici_dispatcher_t *dispatcher;
+ vici_conn_t *conn;
+ int count = 0, i, total = 50;
+
+ lib->processor->set_threads(lib->processor, 8);
+
+ dispatcher = vici_dispatcher_create(URI);
+ ck_assert(dispatcher);
+
+ dispatcher->manage_event(dispatcher, "test", TRUE);
+ dispatcher->manage_event(dispatcher, "dummy", TRUE);
+
+ vici_init();
+ conn = vici_connect(URI);
+ ck_assert(conn);
+
+ vici_register(conn, "test", event_cb, &count);
+
+ for (i = 0; i < total; i++)
+ {
+ /* do some event re/deregistration in between */
+ ck_assert(vici_register(conn, "dummy", event_cb, NULL) == 0);
+
+ dispatcher->raise_event(dispatcher, "test", 0,
+ vici_message_create_from_args(
+ VICI_KEY_VALUE, "key1", chunk_from_str("value1"),
+ VICI_END));
+
+ ck_assert(vici_register(conn, "dummy", NULL, NULL) == 0);
+ }
+
+ while (count < total)
+ {
+ usleep(1000);
+ }
+
+ vici_disconnect(conn);
+
+ dispatcher->manage_event(dispatcher, "test", FALSE);
+ dispatcher->manage_event(dispatcher, "dummy", FALSE);
+
+ lib->processor->cancel(lib->processor);
+ dispatcher->destroy(dispatcher);
+
+ vici_deinit();
+}
+END_TEST
+
+Suite *event_suite_create()
+{
+ Suite *s;
+ TCase *tc;
+
+ s = suite_create("vici events");
+
+ tc = tcase_create("single");
+ tcase_add_test(tc, test_event);
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("raise events");
+ tcase_add_test(tc, test_raise_events);
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("stress");
+ tcase_add_test(tc, test_stress);
+ suite_add_tcase(s, tc);
+
+ return s;
+}
diff --git a/src/libcharon/plugins/vici/suites/test_message.c b/src/libcharon/plugins/vici/suites/test_message.c
new file mode 100644
index 000000000..293117348
--- /dev/null
+++ b/src/libcharon/plugins/vici/suites/test_message.c
@@ -0,0 +1,407 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <test_suite.h>
+
+#include "../vici_message.h"
+#include "../vici_builder.h"
+
+#include <unistd.h>
+
+static char blob[] = {
+ 0xd3,0xe5,0xee,0x37,0x7b,0x96,0x2f,0x3e,0x5f,0x3e,0x91,0xea,0x38,0x44,0xba,0x6c,
+ 0x75,0xc8,0x42,0x32,0xaf,0x7a,0x66,0x43,0x33,0x92,0xd2,0xef,0x7d,0x91,0x7b,0x59,
+ 0x9f,0x9f,0xd1,0x44,0xb6,0x1e,0x8c,0xd1,0xc5,0xa0,0xd9,0xe4,0xf2,0x31,0xfd,0x7b,
+ 0x5b,0x56,0xa7,0xfe,0x63,0x0d,0xcb,0x31,0x74,0xd8,0xd6,0x4a,0x42,0x3a,0x88,0xf3,
+ 0x79,0xf9,0x41,0xa6,0xc0,0x64,0x53,0x31,0x42,0xe2,0xd4,0x4a,0x22,0x5f,0x3f,0x99,
+ 0xe0,0x1a,0xcb,0x93,0x26,0xd0,0xec,0xac,0x90,0x97,0x0a,0x5f,0x69,0x86,0xf1,0xda,
+ 0xfc,0xa7,0xac,0xd0,0xd8,0x81,0xcf,0x7d,0x47,0x22,0xbe,0xbf,0x00,0x9b,0x6b,0x86,
+ 0x92,0x89,0xbe,0x7f,0x74,0x13,0x53,0xf1,0x4c,0x2b,0xc9,0xe1,0x39,0xd6,0xfc,0x50,
+ 0x3f,0x00,0xfb,0x76,0x42,0xa6,0xa4,0x70,0xfc,0x93,0x17,0x4a,0x35,0xce,0x5e,0x78,
+ 0x41,0x88,0x24,0x50,0x78,0xf2,0x38,0x08,0xff,0x40,0xef,0x61,0xbb,0xbf,0x16,0xff,
+ 0x0b,0xf6,0x33,0x21,0xcb,0x48,0xbd,0x7d,0xd1,0x73,0xfa,0x6d,0xd6,0xab,0xde,0x69,
+ 0x63,0x17,0xdb,0x52,0xe2,0x75,0x4b,0xb7,0x1e,0xf0,0x8a,0x55,0x4f,0x70,0x8d,0x18,
+ 0xe5,0x38,0x6a,0x9f,0xb8,0x06,0xb5,0x91,0x90,0x2b,0xc5,0x67,0xa9,0x12,0xe5,0xf3,
+ 0x48,0x2f,0x80,0x03,0xa1,0xa0,0xfc,0x43,0xe9,0x0f,0x83,0x2b,0xbc,0x7c,0xa8,0x3b,
+ 0x6c,0xc1,0xc8,0x72,0x5f,0x87,0x63,0x77,0x93,0x9b,0xe2,0xd7,0x4e,0xe6,0x65,0xa1,
+ 0x69,0x00,0xda,0xf8,0xb4,0x61,0xee,0xb7,0x20,0xe7,0x2a,0x35,0x23,0xf0,0x37,0x4b,
+ 0x67,0xcf,0x8d,0x85,0x72,0x22,0x6d,0x7a,0xb2,0x96,0xff,0x49,0xf4,0x94,0x3e,0x7e,
+ 0x87,0x26,0x5d,0x34,0x05,0x26,0x60,0x9b,0x89,0xfe,0xf9,0x91,0xd3,0x03,0xe7,0x8a,
+ 0x03,0xf6,0x4e,0xbf,0x68,0x13,0xc6,0xf2,0x7b,0x9c,0xe6,0x36,0x1b,0xe2,0x22,0x44,
+ 0xb1,0x19,0x34,0x5f,0xe8,0x44,0x48,0x3a,0x19,0xe4,0xbd,0xb0,0x4e,0xb5,0x2c,0x40,
+ 0x55,0x39,0xe6,0x4c,0xd5,0x68,0x34,0x72,0x6b,0x6d,0x88,0xce,0x7e,0x77,0x95,0x17,
+ 0x2e,0x68,0x3f,0x0e,0x9d,0x70,0x9a,0x22,0xfa,0x19,0xcc,0x15,0x9d,0xba,0xaa,0xec,
+ 0xb1,0x67,0x19,0x51,0xce,0x60,0x9a,0x38,0xf8,0xa7,0x4e,0xe3,0x25,0x47,0x1e,0x1d,
+ 0x30,0x76,0x91,0x8f,0x4d,0x13,0x59,0x06,0x2f,0x01,0x10,0x95,0xdb,0x08,0x7c,0x46,
+ 0xed,0x47,0xa1,0x19,0x4c,0x46,0xd1,0x3a,0x3f,0x88,0x7a,0x63,0xae,0x29,0x13,0x42,
+ 0xe9,0x17,0xe8,0xa9,0x95,0xfc,0xd1,0xea,0xfa,0x59,0x90,0xfe,0xb7,0xbb,0x7f,0x61,
+ 0x1b,0xcb,0x3d,0x12,0x99,0x96,0x3e,0x23,0x23,0xec,0x3a,0x4d,0x86,0x86,0x74,0xef,
+ 0x38,0xa6,0xdc,0x3a,0x83,0x85,0xf8,0xb8,0xad,0x5b,0x33,0x94,0x4d,0x0e,0x68,0xbc,
+ 0xf2,0xc7,0x6f,0x84,0x18,0x1e,0x5a,0x66,0x1f,0x6c,0x98,0x33,0xda,0xde,0x9e,0xda,
+ 0x82,0xd0,0x56,0x44,0x47,0x08,0x0c,0x07,0x81,0x9d,0x8b,0x64,0x16,0x73,0x9d,0x80,
+ 0x54,0x9c,0x4c,0x42,0xde,0x27,0x4e,0x97,0xb2,0xcf,0x48,0xaf,0x7e,0x85,0xc1,0xcd,
+ 0x6a,0x4d,0x04,0x40,0x89,0xa3,0x9d,0x4e,0x89,0x56,0x60,0x31,0x1f,0x3f,0x49,0x16,
+};
+
+typedef struct {
+ vici_type_t type;
+ char *name;
+ chunk_t data;
+} endecode_test_t;
+
+static endecode_test_t endecode_test_simple[] = {
+ { VICI_SECTION_START, "section1", {} },
+ { VICI_KEY_VALUE, "key1", { "value1", 6 } },
+ { VICI_KEY_VALUE, "key2", { "value2", 6 } },
+ { VICI_SECTION_END, NULL, {} },
+ { VICI_END, NULL, {} },
+};
+
+static endecode_test_t endecode_test_nested[] = {
+ { VICI_SECTION_START, "section1", {} },
+ { VICI_SECTION_START, "section2", {} },
+ { VICI_SECTION_START, "section3", {} },
+ { VICI_KEY_VALUE, "key1", { "value1", 6 } },
+ { VICI_SECTION_START, "section4", {} },
+ { VICI_KEY_VALUE, "key2", { "value2", 6 } },
+ { VICI_SECTION_END, NULL, {} },
+ { VICI_SECTION_END, NULL, {} },
+ { VICI_SECTION_END, NULL, {} },
+ { VICI_KEY_VALUE, "key3", { "value3", 6 } },
+ { VICI_SECTION_END, NULL, {} },
+ { VICI_END, NULL, {} },
+};
+
+static endecode_test_t endecode_test_list[] = {
+ { VICI_SECTION_START, "section1", {} },
+ { VICI_LIST_START, "list1", {} },
+ { VICI_LIST_ITEM, NULL, { "item1", 5 } },
+ { VICI_LIST_ITEM, NULL, { "item2", 5 } },
+ { VICI_LIST_END, NULL, {} },
+ { VICI_KEY_VALUE, "key1", { "value1", 6 } },
+ { VICI_SECTION_END, NULL, {} },
+ { VICI_END, NULL, {} },
+};
+
+static endecode_test_t endecode_test_blobs[] = {
+ { VICI_KEY_VALUE, "key1", { blob, countof(blob) } },
+ { VICI_SECTION_START, "section1", {} },
+ { VICI_LIST_START, "list1", {} },
+ { VICI_LIST_ITEM, NULL, { blob, countof(blob) } },
+ { VICI_LIST_ITEM, NULL, { blob, countof(blob) } },
+ { VICI_LIST_END, NULL, {} },
+ { VICI_KEY_VALUE, "key2", { blob, countof(blob) } },
+ { VICI_SECTION_END, NULL, {} },
+ { VICI_END, NULL, {} },
+};
+
+static endecode_test_t *endecode_tests[] = {
+ endecode_test_simple,
+ endecode_test_nested,
+ endecode_test_list,
+ endecode_test_blobs,
+};
+
+typedef struct {
+ enumerator_t public;
+ endecode_test_t *next;
+} endecode_enum_t;
+
+static bool endecode_enumerate(endecode_enum_t *this, vici_type_t *type,
+ char **name, chunk_t *data)
+{
+ if (this->next)
+ {
+ *type = this->next->type;
+ *name = this->next->name;
+ *data = this->next->data;
+ if (this->next->type == VICI_END)
+ {
+ this->next = NULL;
+ }
+ else
+ {
+ this->next++;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static enumerator_t *endecode_create_enumerator(endecode_test_t *test)
+{
+ endecode_enum_t *enumerator;
+
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)endecode_enumerate,
+ .destroy = (void*)free,
+ },
+ .next = test,
+ );
+
+ return &enumerator->public;
+}
+
+static void compare_vici(enumerator_t *parse, enumerator_t *tmpl)
+{
+ vici_type_t type, ttype;
+ char *name, *tname;
+ chunk_t data, tdata;;
+
+ while (TRUE)
+ {
+ ck_assert(parse->enumerate(parse, &type, &name, &data));
+ ck_assert(tmpl->enumerate(tmpl, &ttype, &tname, &tdata));
+ ck_assert_int_eq(type, ttype);
+ switch (type)
+ {
+ case VICI_END:
+ return;
+ case VICI_SECTION_START:
+ case VICI_LIST_START:
+ ck_assert(streq(name, tname));
+ break;
+ case VICI_LIST_ITEM:
+ ck_assert(chunk_equals(data, tdata));
+ break;
+ case VICI_KEY_VALUE:
+ ck_assert(streq(name, tname));
+ ck_assert(chunk_equals(data, tdata));
+ break;
+ case VICI_SECTION_END:
+ case VICI_LIST_END:
+ break;
+ default:
+ ck_assert(FALSE);
+ break;
+ }
+ }
+}
+
+START_TEST(test_endecode)
+{
+ enumerator_t *parse, *tmpl;
+ vici_message_t *m;
+ chunk_t data;
+
+ tmpl = endecode_create_enumerator(endecode_tests[_i]);
+ m = vici_message_create_from_enumerator(tmpl);
+ ck_assert(m);
+ data = chunk_clone(m->get_encoding(m));
+ tmpl = endecode_create_enumerator(endecode_tests[_i]);
+ parse = m->create_enumerator(m);
+ ck_assert(parse);
+ compare_vici(parse, tmpl);
+ tmpl->destroy(tmpl);
+ parse->destroy(parse);
+ m->destroy(m);
+
+ m = vici_message_create_from_data(data, TRUE);
+ ck_assert(m);
+ tmpl = endecode_create_enumerator(endecode_tests[_i]);
+ parse = m->create_enumerator(m);
+ ck_assert(parse);
+ compare_vici(parse, tmpl);
+ tmpl->destroy(tmpl);
+ parse->destroy(parse);
+ m->destroy(m);
+}
+END_TEST
+
+START_TEST(test_vararg)
+{
+ enumerator_t *parse, *tmpl;
+ vici_message_t *m;
+
+ m = vici_message_create_from_args(
+ VICI_SECTION_START, "section1",
+ VICI_LIST_START, "list1",
+ VICI_LIST_ITEM, chunk_from_str("item1"),
+ VICI_LIST_ITEM, chunk_from_str("item2"),
+ VICI_LIST_END,
+ VICI_KEY_VALUE, "key1", chunk_from_str("value1"),
+ VICI_SECTION_END,
+ VICI_END);
+ ck_assert(m);
+ tmpl = endecode_create_enumerator(endecode_test_list);
+ parse = m->create_enumerator(m);
+ ck_assert(parse);
+
+ compare_vici(parse, tmpl);
+
+ m->destroy(m);
+ tmpl->destroy(tmpl);
+ parse->destroy(parse);
+}
+END_TEST
+
+START_TEST(test_builder)
+{
+ enumerator_t *parse, *tmpl;
+ vici_message_t *m;
+ vici_builder_t *b;
+
+ b = vici_builder_create();
+ b->add(b, VICI_SECTION_START, "section1");
+ b->add(b, VICI_LIST_START, "list1");
+ b->add(b, VICI_LIST_ITEM, chunk_from_str("item1"));
+ b->add(b, VICI_LIST_ITEM, chunk_from_str("item2"));
+ b->add(b, VICI_LIST_END);
+ b->add(b, VICI_KEY_VALUE, "key1", chunk_from_str("value1"));
+ b->add(b, VICI_SECTION_END);
+ m = b->finalize(b);
+ ck_assert(m);
+ tmpl = endecode_create_enumerator(endecode_test_list);
+ parse = m->create_enumerator(m);
+ ck_assert(parse);
+
+ compare_vici(parse, tmpl);
+
+ m->destroy(m);
+ tmpl->destroy(tmpl);
+ parse->destroy(parse);
+}
+END_TEST
+
+START_TEST(test_builder_fmt)
+{
+ enumerator_t *parse, *tmpl;
+ vici_message_t *m;
+ vici_builder_t *b;
+
+ b = vici_builder_create();
+ b->begin_section(b, "section1");
+ b->begin_list(b, "list1");
+ b->add_li(b, "item%u", 1);
+ b->add_li(b, "%s%u", "item", 2);
+ b->end_list(b);
+ b->add_kv(b, "key1", "value%u", 1);
+ b->end_section(b);
+ m = b->finalize(b);
+ ck_assert(m);
+ tmpl = endecode_create_enumerator(endecode_test_list);
+ parse = m->create_enumerator(m);
+ ck_assert(parse);
+
+ compare_vici(parse, tmpl);
+
+ m->destroy(m);
+ tmpl->destroy(tmpl);
+ parse->destroy(parse);
+}
+END_TEST
+
+static vici_message_t* build_getter_msg()
+{
+ return vici_message_create_from_args(
+ VICI_KEY_VALUE, "key1", chunk_from_str("1"),
+ VICI_SECTION_START, "section1",
+ VICI_KEY_VALUE, "key2", chunk_from_str("0x12"),
+ VICI_SECTION_START, "section2",
+ VICI_KEY_VALUE, "key3", chunk_from_str("-1"),
+ VICI_SECTION_END,
+ VICI_KEY_VALUE, "key4", chunk_from_str("asdf"),
+ VICI_SECTION_END,
+ VICI_KEY_VALUE, "key5", chunk_from_str(""),
+ VICI_END);
+}
+
+START_TEST(test_get_str)
+{
+ vici_message_t *m;
+
+ m = build_getter_msg();
+
+ ck_assert_str_eq(m->get_str(m, "def", "key1"), "1");
+ ck_assert_str_eq(m->get_str(m, "def", "section1.key2"), "0x12");
+ ck_assert_str_eq(m->get_str(m, "def", "section%d.section2.key3", 1), "-1");
+ ck_assert_str_eq(m->get_str(m, "def", "section1.key4"), "asdf");
+ ck_assert_str_eq(m->get_str(m, "def", "key5"), "");
+ ck_assert_str_eq(m->get_str(m, "no", "nonexistent"), "no");
+ ck_assert_str_eq(m->get_str(m, "no", "n.o.n.e.x.i.s.t.e.n.t"), "no");
+
+ m->destroy(m);
+}
+END_TEST
+
+START_TEST(test_get_int)
+{
+ vici_message_t *m;
+
+ m = build_getter_msg();
+
+ ck_assert_int_eq(m->get_int(m, 2, "key1"), 1);
+ ck_assert_int_eq(m->get_int(m, 2, "section1.key2"), 0x12);
+ ck_assert_int_eq(m->get_int(m, 2, "section1.section2.key3"), -1);
+ ck_assert_int_eq(m->get_int(m, 2, "section1.key4"), 2);
+ ck_assert_int_eq(m->get_int(m, 2, "key5"), 0);
+ ck_assert_int_eq(m->get_int(m, 2, "nonexistent"), 2);
+ ck_assert_int_eq(m->get_int(m, 2, "n.o.n.e.x.i.s.t.e.n.t"), 2);
+
+ m->destroy(m);
+}
+END_TEST
+
+START_TEST(test_get_value)
+{
+ vici_message_t *m;
+ chunk_t d = chunk_from_chars('d','e','f');
+
+ m = build_getter_msg();
+
+ ck_assert_chunk_eq(m->get_value(m, d, "key1"), chunk_from_str("1"));
+ ck_assert_chunk_eq(m->get_value(m, d, "section1.key2"), chunk_from_str("0x12"));
+ ck_assert_chunk_eq(m->get_value(m, d, "section1.section2.key3"), chunk_from_str("-1"));
+ ck_assert_chunk_eq(m->get_value(m, d, "section1.key4"), chunk_from_str("asdf"));
+ ck_assert_chunk_eq(m->get_value(m, d, "key5"), chunk_empty);
+ ck_assert_chunk_eq(m->get_value(m, d, "nonexistent"), d);
+ ck_assert_chunk_eq(m->get_value(m, d, "n.o.n.e.x.i.s.t.e.n.t"), d);
+
+ m->destroy(m);
+}
+END_TEST
+
+Suite *message_suite_create()
+{
+ Suite *s;
+ TCase *tc;
+
+ s = suite_create("vici message");
+
+ tc = tcase_create("enumerator en/decode");
+ tcase_add_loop_test(tc, test_endecode, 0, countof(endecode_tests));
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("vararg encode");
+ tcase_add_test(tc, test_vararg);
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("builder encode");
+ tcase_add_test(tc, test_builder);
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("builder format encode");
+ tcase_add_test(tc, test_builder_fmt);
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("convenience getters");
+ tcase_add_test(tc, test_get_str);
+ tcase_add_test(tc, test_get_int);
+ tcase_add_test(tc, test_get_value);
+ suite_add_tcase(s, tc);
+
+ return s;
+}
diff --git a/src/libcharon/plugins/vici/suites/test_request.c b/src/libcharon/plugins/vici/suites/test_request.c
new file mode 100644
index 000000000..8eeb37bc9
--- /dev/null
+++ b/src/libcharon/plugins/vici/suites/test_request.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <test_suite.h>
+
+#include "../vici_dispatcher.h"
+#include "../libvici.h"
+
+#include <unistd.h>
+
+#ifdef WIN32
+# define URI "tcp://127.0.0.1:6543"
+#else /* !WIN32 */
+# define URI "unix:///tmp/strongswan-vici-request-test"
+#endif /* !WIN32 */
+
+static void encode_section(vici_req_t *req)
+{
+ vici_begin_section(req, "section1");
+ vici_add_key_valuef(req, "key1", "value%u", 1);
+ vici_add_key_value(req, "key2", "value2", strlen("value2"));
+ vici_end_section(req);
+}
+
+static void decode_section(vici_res_t *res)
+{
+ char *str;
+ int len;
+
+ ck_assert(vici_parse(res) == VICI_PARSE_BEGIN_SECTION);
+ ck_assert_str_eq(vici_parse_name(res), "section1");
+ ck_assert(vici_parse(res) == VICI_PARSE_KEY_VALUE);
+ ck_assert_str_eq(vici_parse_name(res), "key1");
+ ck_assert_str_eq(vici_parse_value_str(res), "value1");
+ ck_assert(vici_parse(res) == VICI_PARSE_KEY_VALUE);
+ ck_assert_str_eq(vici_parse_name(res), "key2");
+ str = vici_parse_value(res, &len);
+ ck_assert(chunk_equals(chunk_from_str("value2"), chunk_create(str, len)));
+ ck_assert(vici_parse(res) == VICI_PARSE_END_SECTION);
+ ck_assert(vici_parse(res) == VICI_PARSE_END);
+}
+
+static void encode_list(vici_req_t *req)
+{
+ vici_begin_list(req, "list1");
+ vici_add_list_item(req, "item1", strlen("item1"));
+ vici_add_list_itemf(req, "item%u", 2);
+ vici_end_list(req);
+}
+
+static void decode_list(vici_res_t *res)
+{
+ char *str;
+ int len;
+
+ ck_assert(vici_parse(res) == VICI_PARSE_BEGIN_LIST);
+ ck_assert_str_eq(vici_parse_name(res), "list1");
+ ck_assert(vici_parse(res) == VICI_PARSE_LIST_ITEM);
+ ck_assert_str_eq(vici_parse_value_str(res), "item1");
+ ck_assert(vici_parse(res) == VICI_PARSE_LIST_ITEM);
+ str = vici_parse_value(res, &len);
+ ck_assert(chunk_equals(chunk_from_str("item2"), chunk_create(str, len)));
+ ck_assert(vici_parse(res) == VICI_PARSE_END_LIST);
+ ck_assert(vici_parse(res) == VICI_PARSE_END);
+}
+
+static struct {
+ void (*encode)(vici_req_t* req);
+ void (*decode)(vici_res_t* res);
+} echo_tests[] = {
+ { encode_section, decode_section },
+ { encode_list, decode_list },
+};
+
+static vici_message_t* echo_cb(void *user, char *name,
+ u_int id, vici_message_t *request)
+{
+ ck_assert_str_eq(name, "echo");
+ ck_assert_int_eq((uintptr_t)user, 1);
+
+ return vici_message_create_from_enumerator(request->create_enumerator(request));
+}
+
+START_TEST(test_echo)
+{
+ vici_dispatcher_t *dispatcher;
+ vici_conn_t *conn;
+ vici_req_t *req;
+ vici_res_t *res;
+
+ lib->processor->set_threads(lib->processor, 8);
+
+ dispatcher = vici_dispatcher_create(URI);
+ ck_assert(dispatcher);
+
+ dispatcher->manage_command(dispatcher, "echo", echo_cb, (void*)(uintptr_t)1);
+
+ vici_init();
+ conn = vici_connect(URI);
+ ck_assert(conn);
+
+ req = vici_begin("echo");
+ echo_tests[_i].encode(req);
+ res = vici_submit(req, conn);
+ ck_assert(res);
+ echo_tests[_i].decode(res);
+ vici_free_res(res);
+
+ vici_disconnect(conn);
+
+ dispatcher->manage_command(dispatcher, "echo", NULL, NULL);
+
+ lib->processor->cancel(lib->processor);
+ dispatcher->destroy(dispatcher);
+
+ vici_deinit();
+}
+END_TEST
+
+START_TEST(test_missing)
+{
+ vici_dispatcher_t *dispatcher;
+ vici_conn_t *conn;
+ vici_req_t *req;
+ vici_res_t *res;
+
+ lib->processor->set_threads(lib->processor, 8);
+
+ dispatcher = vici_dispatcher_create(URI);
+ ck_assert(dispatcher);
+
+ vici_init();
+ conn = vici_connect(URI);
+ ck_assert(conn);
+
+ req = vici_begin("nonexistent");
+ encode_section(req);
+ res = vici_submit(req, conn);
+ ck_assert(res == NULL);
+
+ vici_disconnect(conn);
+
+ dispatcher->manage_command(dispatcher, "echo", NULL, NULL);
+
+ lib->processor->cancel(lib->processor);
+ dispatcher->destroy(dispatcher);
+
+ vici_deinit();
+}
+END_TEST
+
+static void event_cb(void *user, char *name, vici_res_t *ev)
+{
+ int *events = (int*)user;
+
+ (*events)++;
+}
+
+START_TEST(test_stress)
+{
+ vici_dispatcher_t *dispatcher;
+ vici_conn_t *conn;
+ vici_req_t *req;
+ vici_res_t *res;
+ int i, total = 50, events = 0;
+
+ lib->processor->set_threads(lib->processor, 8);
+
+ dispatcher = vici_dispatcher_create(URI);
+ ck_assert(dispatcher);
+
+ dispatcher->manage_command(dispatcher, "echo", echo_cb, (void*)(uintptr_t)1);
+ dispatcher->manage_event(dispatcher, "dummy", TRUE);
+
+ vici_init();
+ conn = vici_connect(URI);
+ ck_assert(conn);
+
+ for (i = 0; i < total; i++)
+ {
+ /* do some event management in between */
+ ck_assert(vici_register(conn, "dummy", event_cb, &events) == 0);
+ dispatcher->raise_event(dispatcher, "dummy", 0,
+ vici_message_create_from_args(
+ VICI_KEY_VALUE, "key1", chunk_from_str("value1"),
+ VICI_END));
+
+ req = vici_begin("echo");
+ encode_section(req);
+ res = vici_submit(req, conn);
+ ck_assert(res);
+ decode_section(res);
+ vici_free_res(res);
+
+ ck_assert(vici_register(conn, "dummy", NULL, NULL) == 0);
+ }
+
+ while (events < total)
+ {
+ usleep(1000);
+ }
+
+ vici_disconnect(conn);
+
+ dispatcher->manage_command(dispatcher, "echo", NULL, NULL);
+ dispatcher->manage_event(dispatcher, "dummy", FALSE);
+
+ lib->processor->cancel(lib->processor);
+ dispatcher->destroy(dispatcher);
+
+ vici_deinit();
+}
+END_TEST
+
+Suite *request_suite_create()
+{
+ Suite *s;
+ TCase *tc;
+
+ s = suite_create("vici request");
+
+ tc = tcase_create("echo");
+ tcase_add_loop_test(tc, test_echo, 0, countof(echo_tests));
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("missing");
+ tcase_add_test(tc, test_missing);
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("stress");
+ tcase_add_test(tc, test_stress);
+ suite_add_tcase(s, tc);
+
+ return s;
+}
diff --git a/src/libcharon/plugins/vici/suites/test_socket.c b/src/libcharon/plugins/vici/suites/test_socket.c
new file mode 100644
index 000000000..8d545c6c1
--- /dev/null
+++ b/src/libcharon/plugins/vici/suites/test_socket.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <test_suite.h>
+
+#include "../vici_socket.h"
+
+#include <unistd.h>
+
+typedef struct {
+ vici_socket_t *s;
+ int disconnect;
+ int bytes;
+ u_int id;
+} test_data_t;
+
+static void echo_inbound(void *user, u_int id, chunk_t buf)
+{
+ test_data_t *data = user;
+
+ ck_assert_int_eq(data->id, id);
+ /* count number of bytes, including the header */
+ data->bytes += buf.len + sizeof(u_int32_t);
+ /* echo back data chunk */
+ data->s->send(data->s, id, chunk_clone(buf));
+}
+
+static void echo_connect(void *user, u_int id)
+{
+ test_data_t *data = user;
+
+ data->id = id;
+}
+
+static void echo_disconnect(void *user, u_int id)
+{
+ test_data_t *data = user;
+
+ ck_assert(id == data->id);
+ data->disconnect++;
+}
+
+static struct {
+ char *uri;
+ u_int chunksize;
+} echo_tests[] = {
+ { "tcp://127.0.0.1:6543", ~0 },
+ { "tcp://127.0.0.1:6543", 1 },
+ { "tcp://127.0.0.1:6543", 2 },
+ { "tcp://127.0.0.1:6543", 3 },
+ { "tcp://127.0.0.1:6543", 7 },
+#ifndef WIN32
+ { "unix:///tmp/strongswan-tests-vici-socket", ~0 },
+ { "unix:///tmp/strongswan-tests-vici-socket", 1 },
+ { "unix:///tmp/strongswan-tests-vici-socket", 2 },
+ { "unix:///tmp/strongswan-tests-vici-socket", 3 },
+ { "unix:///tmp/strongswan-tests-vici-socket", 7 },
+#endif /* !WIN32 */
+};
+
+START_TEST(test_echo)
+{
+ stream_t *c;
+ test_data_t data = {};
+ chunk_t x, m = chunk_from_chars(
+ 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x01, 0x01,
+ 0x00,0x00,0x00,0x05, 0x11,0x12,0x13,0x14,0x15,
+ 0x00,0x00,0x00,0x0A, 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x02A,
+ );
+ char buf[m.len];
+ u_int32_t len;
+
+ lib->processor->set_threads(lib->processor, 4);
+
+ /* create socket, connect with stream */
+ data.s = vici_socket_create(echo_tests[_i].uri, echo_inbound, echo_connect,
+ echo_disconnect, &data);
+ ck_assert(data.s != NULL);
+ c = lib->streams->connect(lib->streams, echo_tests[_i].uri);
+ ck_assert(c != NULL);
+
+ /* write arbitrary chunks of messages blob depending on test */
+ x = m;
+ while (x.len)
+ {
+ len = min(x.len, echo_tests[_i].chunksize);
+ ck_assert(c->write_all(c, x.ptr, len));
+ x = chunk_skip(x, len);
+ }
+
+ /* verify echo */
+ ck_assert(c->read_all(c, buf, sizeof(buf)));
+ ck_assert(chunk_equals(m, chunk_from_thing(buf)));
+
+ /* wait for completion */
+ c->destroy(c);
+ while (data.disconnect != 1)
+ {
+ usleep(1000);
+ }
+ /* check that we got correct number of bytes/invocations */
+ ck_assert_int_eq(data.bytes, m.len);
+
+ data.s->destroy(data.s);
+}
+END_TEST
+
+Suite *socket_suite_create()
+{
+ Suite *s;
+ TCase *tc;
+
+ s = suite_create("vici socket");
+
+ tc = tcase_create("echo");
+ tcase_add_loop_test(tc, test_echo, 0, countof(echo_tests));
+ suite_add_tcase(s, tc);
+
+ return s;
+}
diff --git a/src/libcharon/plugins/vici/vici_attribute.c b/src/libcharon/plugins/vici/vici_attribute.c
new file mode 100644
index 000000000..2178116c9
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_attribute.c
@@ -0,0 +1,713 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "vici_attribute.h"
+#include "vici_builder.h"
+
+#include <daemon.h>
+#include <collections/hashtable.h>
+#include <collections/array.h>
+#include <threading/rwlock.h>
+#include <attributes/mem_pool.h>
+
+typedef struct private_vici_attribute_t private_vici_attribute_t;
+
+/**
+ * private data of vici_attribute
+ */
+struct private_vici_attribute_t {
+
+ /**
+ * public functions
+ */
+ vici_attribute_t public;
+
+ /**
+ * vici connection dispatcher
+ */
+ vici_dispatcher_t *dispatcher;
+
+ /**
+ * Configured pools, as char* => pool_t
+ */
+ hashtable_t *pools;
+
+ /**
+ * rwlock to lock access to pools
+ */
+ rwlock_t *lock;
+};
+
+/**
+ * Single configuration attribute with type
+ */
+typedef struct {
+ /** type of attribute */
+ configuration_attribute_type_t type;
+ /** attribute value */
+ chunk_t value;
+} attribute_t;
+
+/**
+ * Clean up an attribute
+ */
+static void attribute_destroy(attribute_t *attr)
+{
+ free(attr->value.ptr);
+ free(attr);
+}
+
+/**
+ * Pool instances with associated attributes
+ */
+typedef struct {
+ /** in-memory virtual IP pool */
+ mem_pool_t *vips;
+ /** configuration attributes, as attribute_t */
+ array_t *attrs;
+} pool_t;
+
+/**
+ * Clean up a pool instance
+ */
+static void pool_destroy(pool_t *pool)
+{
+ DESTROY_IF(pool->vips);
+ array_destroy_function(pool->attrs, (void*)attribute_destroy, NULL);
+ free(pool);
+}
+
+/**
+ * Find an existing or not yet existing lease
+ */
+static host_t *find_addr(private_vici_attribute_t *this, linked_list_t *pools,
+ identification_t *id, host_t *requested, mem_pool_op_t op)
+{
+ enumerator_t *enumerator;
+ host_t *addr = NULL;
+ pool_t *pool;
+ char *name;
+
+ enumerator = pools->create_enumerator(pools);
+ while (enumerator->enumerate(enumerator, &name))
+ {
+ pool = this->pools->get(this->pools, name);
+ if (pool)
+ {
+ addr = pool->vips->acquire_address(pool->vips, id, requested, op);
+ if (addr)
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return addr;
+}
+
+METHOD(attribute_provider_t, acquire_address, host_t*,
+ private_vici_attribute_t *this, linked_list_t *pools, identification_t *id,
+ host_t *requested)
+{
+ host_t *addr;
+
+ this->lock->read_lock(this->lock);
+
+ addr = find_addr(this, pools, id, requested, MEM_POOL_EXISTING);
+ if (!addr)
+ {
+ addr = find_addr(this, pools, id, requested, MEM_POOL_NEW);
+ if (!addr)
+ {
+ addr = find_addr(this, pools, id, requested, MEM_POOL_REASSIGN);
+ }
+ }
+
+ this->lock->unlock(this->lock);
+
+ return addr;
+}
+
+METHOD(attribute_provider_t, release_address, bool,
+ private_vici_attribute_t *this, linked_list_t *pools, host_t *address,
+ identification_t *id)
+{
+ enumerator_t *enumerator;
+ bool found = FALSE;
+ pool_t *pool;
+ char *name;
+
+ this->lock->read_lock(this->lock);
+
+ enumerator = pools->create_enumerator(pools);
+ while (enumerator->enumerate(enumerator, &name))
+ {
+ pool = this->pools->get(this->pools, name);
+ if (pool)
+ {
+ found = pool->vips->release_address(pool->vips, address, id);
+ if (found)
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ this->lock->unlock(this->lock);
+
+ return found;
+}
+
+/**
+ * Filter mapping attribute_t to enumerated type/value arguments
+ */
+static bool attr_filter(void *data, attribute_t **attr,
+ configuration_attribute_type_t *type,
+ void *in, chunk_t *value)
+{
+ *type = (*attr)->type;
+ *value = (*attr)->value;
+ return TRUE;
+}
+
+/**
+ * Create nested inner enumerator over pool attributes
+ */
+CALLBACK(create_nested, enumerator_t*,
+ pool_t *pool, void *this)
+{
+ return enumerator_create_filter(array_create_enumerator(pool->attrs),
+ (void*)attr_filter, NULL, NULL);
+}
+
+/**
+ * Data associated to nested enumerator cleanup
+ */
+typedef struct {
+ private_vici_attribute_t *this;
+ linked_list_t *list;
+} nested_data_t;
+
+/**
+ * Clean up nested enumerator data
+ */
+CALLBACK(nested_cleanup, void,
+ nested_data_t *data)
+{
+ data->this->lock->unlock(data->this->lock);
+ data->list->destroy(data->list);
+ free(data);
+}
+
+/**
+ * Check if any of vips is from pool
+ */
+static bool have_vips_from_pool(mem_pool_t *pool, linked_list_t *vips)
+{
+ enumerator_t *enumerator;
+ host_t *host;
+ chunk_t start, end, current;
+ u_int32_t size;
+ bool found = FALSE;
+
+ host = pool->get_base(pool);
+ start = host->get_address(host);
+
+ if (start.len >= sizeof(size))
+ {
+ end = chunk_clone(start);
+
+ /* mem_pool is currenty limited to 2^31 addresses, so 32-bit
+ * calculations should be sufficient. */
+ size = untoh32(start.ptr + start.len - sizeof(size));
+ htoun32(end.ptr + end.len - sizeof(size), size + pool->get_size(pool));
+
+ enumerator = vips->create_enumerator(vips);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ current = host->get_address(host);
+ if (chunk_compare(current, start) >= 0 &&
+ chunk_compare(current, end) < 0)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ free(end.ptr);
+ }
+ return found;
+}
+
+METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
+ private_vici_attribute_t *this, linked_list_t *pools,
+ identification_t *id, linked_list_t *vips)
+{
+ enumerator_t *enumerator;
+ nested_data_t *data;
+ pool_t *pool;
+ char *name;
+
+ INIT(data,
+ .this = this,
+ .list = linked_list_create(),
+ );
+
+ this->lock->read_lock(this->lock);
+
+ enumerator = pools->create_enumerator(pools);
+ while (enumerator->enumerate(enumerator, &name))
+ {
+ pool = this->pools->get(this->pools, name);
+ if (pool && have_vips_from_pool(pool->vips, vips))
+ {
+ data->list->insert_last(data->list, pool);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return enumerator_create_nested(data->list->create_enumerator(data->list),
+ create_nested, data, nested_cleanup);
+}
+
+/**
+ * Merge a pool configuration with existing ones
+ */
+static bool merge_pool(private_vici_attribute_t *this, pool_t *new)
+{
+ mem_pool_t *tmp;
+ host_t *base;
+ pool_t *old;
+ const char *name;
+ u_int size;
+
+ name = new->vips->get_name(new->vips);
+ base = new->vips->get_base(new->vips);
+ size = new->vips->get_size(new->vips);
+
+ old = this->pools->remove(this->pools, name);
+ if (!old)
+ {
+ this->pools->put(this->pools, name, new);
+ DBG1(DBG_CFG, "added vici pool %s: %H, %u entries", name, base, size);
+ return TRUE;
+ }
+
+ if (base->ip_equals(base, old->vips->get_base(old->vips)) &&
+ size == old->vips->get_size(old->vips))
+ {
+ /* no changes in pool, so keep existing, but use new attributes */
+ DBG1(DBG_CFG, "updated vici pool %s: %H, %u entries", name, base, size);
+ tmp = new->vips;
+ new->vips = old->vips;
+ old->vips = tmp;
+ this->pools->put(this->pools, new->vips->get_name(new->vips), new);
+ pool_destroy(old);
+ return TRUE;
+ }
+ if (old->vips->get_online(old->vips) == 0)
+ {
+ /* can replace old pool, no online leases */
+ DBG1(DBG_CFG, "replaced vici pool %s: %H, %u entries", name, base, size);
+ this->pools->put(this->pools, name, new);
+ pool_destroy(old);
+ return TRUE;
+ }
+ /* have online leases, unable to replace, TODO: migrate leases? */
+ DBG1(DBG_CFG, "vici pool %s has %u online leases, unable to replace",
+ name, old->vips->get_online(old->vips));
+ this->pools->put(this->pools, old->vips->get_name(old->vips), old);
+ return FALSE;
+}
+
+/**
+ * Create a (error) reply message
+ */
+static vici_message_t* create_reply(char *fmt, ...)
+{
+ vici_builder_t *builder;
+ va_list args;
+
+ builder = vici_builder_create();
+ builder->add_kv(builder, "success", fmt ? "no" : "yes");
+ if (fmt)
+ {
+ va_start(args, fmt);
+ builder->vadd_kv(builder, "errmsg", fmt, args);
+ va_end(args);
+ }
+ return builder->finalize(builder);
+}
+
+/**
+ * Parse callback data, passed to each callback
+ */
+typedef struct {
+ private_vici_attribute_t *this;
+ vici_message_t *reply;
+} request_data_t;
+
+/**
+ * Data associated to a pool load
+ */
+typedef struct {
+ request_data_t *request;
+ char *name;
+ pool_t *pool;
+} load_data_t;
+
+CALLBACK(pool_li, bool,
+ load_data_t *data, vici_message_t *message, char *name, chunk_t value)
+{
+ struct {
+ char *name;
+ configuration_attribute_type_t v4;
+ configuration_attribute_type_t v6;
+ } keys[] = {
+ {"address", INTERNAL_IP4_ADDRESS, INTERNAL_IP6_ADDRESS },
+ {"dns", INTERNAL_IP4_DNS, INTERNAL_IP6_DNS },
+ {"nbns", INTERNAL_IP4_NBNS, INTERNAL_IP6_NBNS },
+ {"dhcp", INTERNAL_IP4_DHCP, INTERNAL_IP6_DHCP },
+ {"netmask", INTERNAL_IP4_NETMASK, INTERNAL_IP6_NETMASK },
+ {"server", INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER },
+ {"subnet", INTERNAL_IP4_SUBNET, INTERNAL_IP6_SUBNET },
+ {"split_include", UNITY_SPLIT_INCLUDE, UNITY_SPLIT_INCLUDE },
+ {"split_exclude", UNITY_LOCAL_LAN, UNITY_LOCAL_LAN },
+ };
+ char buf[256];
+ int i, index = -1, mask = -1, type = 0;
+ chunk_t encoding;
+ attribute_t *attr;
+ host_t *host = NULL;
+
+ for (i = 0; i < countof(keys); i++)
+ {
+ if (streq(name, keys[i].name))
+ {
+ index = i;
+ break;
+ }
+ }
+ if (index == -1)
+ {
+ type = atoi(name);
+ if (!type)
+ {
+ data->request->reply = create_reply("invalid attribute: %s", name);
+ return FALSE;
+ }
+ }
+
+ if (vici_stringify(value, buf, sizeof(buf)))
+ {
+ if (strchr(buf, '/'))
+ {
+ host = host_create_from_subnet(buf, &mask);
+ }
+ else
+ {
+ host = host_create_from_string(buf, 0);
+ }
+ }
+ if (host)
+ {
+ if (index != -1)
+ {
+ switch (host->get_family(host))
+ {
+ case AF_INET:
+ type = keys[index].v4;
+ break;
+ case AF_INET6:
+ default:
+ type = keys[index].v6;
+ break;
+ }
+ }
+ if (mask == -1)
+ {
+ encoding = chunk_clone(host->get_address(host));
+ }
+ else
+ {
+ if (host->get_family(host) == AF_INET)
+ { /* IPv4 attributes contain a subnet mask */
+ u_int32_t netmask = 0;
+
+ if (mask)
+ { /* shifting u_int32_t by 32 or more is undefined */
+ mask = 32 - mask;
+ netmask = htonl((0xFFFFFFFF >> mask) << mask);
+ }
+ encoding = chunk_cat("cc", host->get_address(host),
+ chunk_from_thing(netmask));
+ }
+ else
+ { /* IPv6 addresses the prefix only */
+ encoding = chunk_cat("cc", host->get_address(host),
+ chunk_from_chars(mask));
+ }
+ }
+ host->destroy(host);
+ }
+ else
+ {
+ if (index != -1)
+ {
+ data->request->reply = create_reply("invalid attribute value "
+ "for %s", name);
+ return FALSE;
+ }
+ /* use raw binary data for numbered attributes */
+ encoding = chunk_clone(value);
+ }
+ INIT(attr,
+ .type = type,
+ .value = encoding,
+ );
+ array_insert_create(&data->pool->attrs, ARRAY_TAIL, attr);
+ return TRUE;
+}
+
+CALLBACK(pool_kv, bool,
+ load_data_t *data, vici_message_t *message, char *name, chunk_t value)
+{
+ if (streq(name, "addrs"))
+ {
+ char buf[128];
+ host_t *base;
+ int bits;
+
+ if (data->pool->vips)
+ {
+ data->request->reply = create_reply("multiple addrs defined");
+ return FALSE;
+ }
+ if (!vici_stringify(value, buf, sizeof(buf)))
+ {
+ data->request->reply = create_reply("invalid addrs value");
+ return FALSE;
+ }
+ base = host_create_from_subnet(buf, &bits);
+ if (!base)
+ {
+ data->request->reply = create_reply("invalid addrs value: %s", buf);
+ return FALSE;
+ }
+ data->pool->vips = mem_pool_create(data->name, base, bits);
+ base->destroy(base);
+ return TRUE;
+ }
+ data->request->reply = create_reply("invalid attribute: %s", name);
+ return FALSE;
+}
+
+CALLBACK(pool_sn, bool,
+ request_data_t *request, vici_message_t *message,
+ vici_parse_context_t *ctx, char *name)
+{
+ load_data_t data = {
+ .request = request,
+ .name = name,
+ };
+ bool merged;
+
+ INIT(data.pool);
+
+ if (!message->parse(message, ctx, NULL, pool_kv, pool_li, &data))
+ {
+ pool_destroy(data.pool);
+ return FALSE;
+ }
+
+ if (!data.pool->vips)
+ {
+ request->reply = create_reply("missing addrs for pool '%s'", name);
+ pool_destroy(data.pool);
+ return FALSE;
+ }
+
+ request->this->lock->write_lock(request->this->lock);
+ merged = merge_pool(request->this, data.pool);
+ request->this->lock->unlock(request->this->lock);
+
+ if (!merged)
+ {
+ request->reply = create_reply("vici pool %s has online leases, "
+ "unable to replace", name);
+ pool_destroy(data.pool);
+ }
+ return merged;
+}
+
+CALLBACK(load_pool, vici_message_t*,
+ private_vici_attribute_t *this, char *name, u_int id,
+ vici_message_t *message)
+{
+ request_data_t request = {
+ .this = this,
+ };
+
+ if (!message->parse(message, NULL, pool_sn, NULL, NULL, &request))
+ {
+ if (request.reply)
+ {
+ return request.reply;
+ }
+ return create_reply("parsing request failed");
+ }
+ return create_reply(NULL);
+}
+
+CALLBACK(unload_pool, vici_message_t*,
+ private_vici_attribute_t *this, char *name, u_int id,
+ vici_message_t *message)
+{
+ vici_message_t *reply;
+ u_int online;
+ pool_t *pool;
+
+ name = message->get_str(message, NULL, "name");
+ if (!name)
+ {
+ return create_reply("missing pool name to unload");
+ }
+
+ this->lock->write_lock(this->lock);
+
+ pool = this->pools->remove(this->pools, name);
+ if (pool)
+ {
+ online = pool->vips->get_online(pool->vips);
+ if (online)
+ {
+ DBG1(DBG_CFG, "vici pool %s has %u online leases, unable to unload",
+ name, online);
+ reply = create_reply("%s has online leases, unable to unload", name);
+ this->pools->put(this->pools, pool->vips->get_name(pool->vips), pool);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "unloaded vici pool %s", name);
+ reply = create_reply(NULL);
+ pool_destroy(pool);
+ }
+ }
+ else
+ {
+ reply = create_reply("%s not found", name);
+ }
+
+ this->lock->unlock(this->lock);
+
+ return reply;
+}
+
+CALLBACK(get_pools, vici_message_t*,
+ private_vici_attribute_t *this, char *name, u_int id,
+ vici_message_t *message)
+{
+ vici_builder_t *builder;
+ enumerator_t *enumerator;
+ mem_pool_t *vips;
+ pool_t *pool;
+
+ builder = vici_builder_create();
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->pools->create_enumerator(this->pools);
+ while (enumerator->enumerate(enumerator, &name, &pool))
+ {
+ vips = pool->vips;
+
+ builder->begin_section(builder, name);
+
+ builder->add_kv(builder, "base", "%H", vips->get_base(vips));
+ builder->add_kv(builder, "size", "%u", vips->get_size(vips));
+ builder->add_kv(builder, "online", "%u", vips->get_online(vips));
+ builder->add_kv(builder, "offline", "%u", vips->get_offline(vips));
+
+ builder->end_section(builder);
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ return builder->finalize(builder);
+}
+
+static void manage_command(private_vici_attribute_t *this,
+ char *name, vici_command_cb_t cb, bool reg)
+{
+ this->dispatcher->manage_command(this->dispatcher, name,
+ reg ? cb : NULL, this);
+}
+
+/**
+ * (Un-)register dispatcher functions
+ */
+static void manage_commands(private_vici_attribute_t *this, bool reg)
+{
+ manage_command(this, "load-pool", load_pool, reg);
+ manage_command(this, "unload-pool", unload_pool, reg);
+ manage_command(this, "get-pools", get_pools, reg);
+}
+
+METHOD(vici_attribute_t, destroy, void,
+ private_vici_attribute_t *this)
+{
+ enumerator_t *enumerator;
+ pool_t *pool;
+
+ manage_commands(this, FALSE);
+
+ enumerator = this->pools->create_enumerator(this->pools);
+ while (enumerator->enumerate(enumerator, NULL, &pool))
+ {
+ pool_destroy(pool);
+ }
+ enumerator->destroy(enumerator);
+ this->pools->destroy(this->pools);
+ this->lock->destroy(this->lock);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+vici_attribute_t *vici_attribute_create(vici_dispatcher_t *dispatcher)
+{
+ private_vici_attribute_t *this;
+
+ INIT(this,
+ .public = {
+ .provider = {
+ .acquire_address = _acquire_address,
+ .release_address = _release_address,
+ .create_attribute_enumerator = _create_attribute_enumerator,
+ },
+ .destroy = _destroy,
+ },
+ .dispatcher = dispatcher,
+ .pools = hashtable_create(hashtable_hash_str, hashtable_equals_str, 4),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ manage_commands(this, TRUE);
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/vici/vici_attribute.h b/src/libcharon/plugins/vici/vici_attribute.h
new file mode 100644
index 000000000..652a96d39
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_attribute.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup vici_attribute vici_attribute
+ * @{ @ingroup vici
+ */
+
+#ifndef VICI_ATTRIBUTE_H_
+#define VICI_ATTRIBUTE_H_
+
+#include "vici_dispatcher.h"
+
+#include <attributes/attribute_provider.h>
+
+typedef struct vici_attribute_t vici_attribute_t;
+
+/**
+ * IKE configuration attribute backend for vici.
+ */
+struct vici_attribute_t {
+
+ /**
+ * Implements attribute provider interface
+ */
+ attribute_provider_t provider;
+
+ /**
+ * Destroy a vici_attribute_t.
+ */
+ void (*destroy)(vici_attribute_t *this);
+};
+
+/**
+ * Create a vici_attribute instance.
+ *
+ * @param dispatcher vici dispatcher context
+ * @return vici attribute handler
+ */
+vici_attribute_t *vici_attribute_create(vici_dispatcher_t *dispatcher);
+
+#endif /** VICI_ATTRIBUTE_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_builder.c b/src/libcharon/plugins/vici/vici_builder.c
new file mode 100644
index 000000000..561632049
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_builder.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "vici_builder.h"
+
+#include <bio/bio_writer.h>
+
+typedef struct private_vici_builder_t private_vici_builder_t;
+
+/**
+ * Private data of an vici_builder_t object.
+ */
+struct private_vici_builder_t {
+
+ /**
+ * Public vici_builder_t interface.
+ */
+ vici_builder_t public;
+
+ /**
+ * Writer for elements
+ */
+ bio_writer_t *writer;
+
+ /**
+ * Errors encountered
+ */
+ u_int error;
+
+ /**
+ * Section nesting level
+ */
+ u_int section;
+
+ /**
+ * In list element?
+ */
+ bool list;
+};
+
+METHOD(vici_builder_t, add, void,
+ private_vici_builder_t *this, vici_type_t type, ...)
+{
+ va_list args;
+ char *name = NULL;
+ chunk_t value = chunk_empty;
+
+ va_start(args, type);
+ switch (type)
+ {
+ case VICI_SECTION_END:
+ case VICI_LIST_END:
+ case VICI_END:
+ break;
+ case VICI_LIST_START:
+ case VICI_SECTION_START:
+ name = va_arg(args, char*);
+ break;
+ case VICI_KEY_VALUE:
+ name = va_arg(args, char*);
+ value = va_arg(args, chunk_t);
+ break;
+ case VICI_LIST_ITEM:
+ value = va_arg(args, chunk_t);
+ break;
+ default:
+ va_end(args);
+ this->error++;
+ return;
+ }
+ va_end(args);
+
+ if (value.len > 0xffff)
+ {
+ this->error++;
+ return;
+ }
+ if (!vici_verify_type(type, this->section, this->list))
+ {
+ this->error++;
+ return;
+ }
+ if (type != VICI_END)
+ {
+ this->writer->write_uint8(this->writer, type);
+ }
+ switch (type)
+ {
+ case VICI_SECTION_START:
+ this->writer->write_data8(this->writer, chunk_from_str(name));
+ this->section++;
+ break;
+ case VICI_SECTION_END:
+ this->section--;
+ break;
+ case VICI_KEY_VALUE:
+ this->writer->write_data8(this->writer, chunk_from_str(name));
+ this->writer->write_data16(this->writer, value);
+ break;
+ case VICI_LIST_START:
+ this->writer->write_data8(this->writer, chunk_from_str(name));
+ this->list = TRUE;
+ break;
+ case VICI_LIST_ITEM:
+ this->writer->write_data16(this->writer, value);
+ break;
+ case VICI_LIST_END:
+ this->list = FALSE;
+ break;
+ default:
+ this->error++;
+ break;
+ }
+}
+
+METHOD(vici_builder_t, vadd_kv, void,
+ private_vici_builder_t *this, char *key, char *fmt, va_list args)
+{
+ char buf[2048];
+ ssize_t len;
+
+ len = vsnprintf(buf, sizeof(buf), fmt, args);
+ if (len < 0 || len >= sizeof(buf))
+ {
+ DBG1(DBG_ENC, "vici builder format buffer exceeds limit");
+ this->error++;
+ }
+ else
+ {
+ add(this, VICI_KEY_VALUE, key, chunk_create(buf, len));
+ }
+}
+
+METHOD(vici_builder_t, add_kv, void,
+ private_vici_builder_t *this, char *key, char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vadd_kv(this, key, fmt, args);
+ va_end(args);
+}
+
+
+METHOD(vici_builder_t, vadd_li, void,
+ private_vici_builder_t *this, char *fmt, va_list args)
+{
+ char buf[2048];
+ ssize_t len;
+
+ len = vsnprintf(buf, sizeof(buf), fmt, args);
+ if (len < 0 || len >= sizeof(buf))
+ {
+ DBG1(DBG_ENC, "vici builder format buffer exceeds limit");
+ this->error++;
+ }
+ else
+ {
+ add(this, VICI_LIST_ITEM, chunk_create(buf, len));
+ }
+}
+
+METHOD(vici_builder_t, add_li, void,
+ private_vici_builder_t *this, char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vadd_li(this, fmt, args);
+ va_end(args);
+}
+
+METHOD(vici_builder_t, begin_section, void,
+ private_vici_builder_t *this, char *name)
+{
+ add(this, VICI_SECTION_START, name);
+}
+
+METHOD(vici_builder_t, end_section, void,
+ private_vici_builder_t *this)
+{
+ add(this, VICI_SECTION_END);
+}
+
+METHOD(vici_builder_t, begin_list, void,
+ private_vici_builder_t *this, char *name)
+{
+ add(this, VICI_LIST_START, name);
+}
+
+METHOD(vici_builder_t, end_list, void,
+ private_vici_builder_t *this)
+{
+ add(this, VICI_LIST_END);
+}
+
+METHOD(vici_builder_t, finalize, vici_message_t*,
+ private_vici_builder_t *this)
+{
+ vici_message_t *product;
+
+ if (this->error || this->section || this->list)
+ {
+ DBG1(DBG_ENC, "vici builder error: %u errors (section: %u, list %u)",
+ this->error, this->section, this->list);
+ this->writer->destroy(this->writer);
+ free(this);
+ return NULL;
+ }
+ product = vici_message_create_from_data(
+ this->writer->extract_buf(this->writer), TRUE);
+ this->writer->destroy(this->writer);
+ free(this);
+ return product;
+}
+
+/**
+ * See header
+ */
+vici_builder_t *vici_builder_create()
+{
+ private_vici_builder_t *this;
+
+ INIT(this,
+ .public = {
+ .add = _add,
+ .add_kv = _add_kv,
+ .vadd_kv = _vadd_kv,
+ .add_li = _add_li,
+ .vadd_li = _vadd_li,
+ .begin_section = _begin_section,
+ .end_section = _end_section,
+ .begin_list = _begin_list,
+ .end_list = _end_list,
+ .finalize = _finalize,
+ },
+ .writer = bio_writer_create(0),
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/vici/vici_builder.h b/src/libcharon/plugins/vici/vici_builder.h
new file mode 100644
index 000000000..5a5cc8a03
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_builder.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup vici_builder vici_builder
+ * @{ @ingroup vici
+ */
+
+#ifndef VICI_BUILDER_H_
+#define VICI_BUILDER_H_
+
+#include "vici_message.h"
+
+typedef struct vici_builder_t vici_builder_t;
+
+/**
+ * Build helper for vici message
+ */
+struct vici_builder_t {
+
+ /**
+ * Append a generic message element to message.
+ *
+ * The additional arguments are type specific, it may be nothing, a string,
+ * a chunk value or both.
+ *
+ * @param type element type to add
+ * @param ... additional type specific arguments
+ */
+ void (*add)(vici_builder_t *this, vici_type_t type, ...);
+
+ /**
+ * Append a key/value element using a format string.
+ *
+ * Instead of passing the type specific value as a chunk, this method
+ * takes a printf() style format string followed by its arguments. The
+ * key name for a key/value type is still a fixed string.
+ *
+ * @param key key name of the key/value to add
+ * @param fmt value format string
+ * @param ... arguments to value format string
+ */
+ void (*add_kv)(vici_builder_t *this, char *key, char *fmt, ...);
+
+ /**
+ * Append a message element using a format string and va_list.
+ *
+ * Instead of passing the type specific value as a chunk, this method
+ * takes a printf() style format string followed by its arguments. The
+ * key name for a key/value type is still a fixed string.
+ *
+ * @param key key name of the key/value to add
+ * @param fmt value format string
+ * @param args arguments to value format string
+ */
+ void (*vadd_kv)(vici_builder_t *this, char *key, char *fmt, va_list args);
+
+ /**
+ * Append a list item element using a format string.
+ *
+ * Instead of passing the type specific value as a chunk, this method
+ * takes a printf() style format string followed by its arguments.
+ *
+ * @param fmt value format string
+ * @param ... arguments to value format string
+ */
+ void (*add_li)(vici_builder_t *this, char *fmt, ...);
+
+ /**
+ * Append a list item element using a format string and va_list.
+ *
+ * Instead of passing the type specific value as a chunk, this method
+ * takes a printf() style format string followed by its arguments.
+ *
+ * @param fmt value format string
+ * @param args arguments to value format string
+ */
+ void (*vadd_li)(vici_builder_t *this, char *fmt, va_list args);
+
+ /**
+ * Begin a new section.
+ *
+ * @param name name of section to begin
+ */
+ void (*begin_section)(vici_builder_t *this, char *name);
+
+ /**
+ * End the currently open section.
+ */
+ void (*end_section)(vici_builder_t *this);
+
+ /**
+ * Begin a new list.
+ *
+ * @param name name of list to begin
+ */
+ void (*begin_list)(vici_builder_t *this, char *name);
+
+ /**
+ * End the currently open list.
+ */
+ void (*end_list)(vici_builder_t *this);
+
+ /**
+ * Finalize a vici message with all added elements, destroy builder.
+ *
+ * @return vici message, NULL on error
+ */
+ vici_message_t* (*finalize)(vici_builder_t *this);
+};
+
+/**
+ * Create a vici_builder instance.
+ */
+vici_builder_t *vici_builder_create();
+
+#endif /** VICI_BUILDER_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c
new file mode 100644
index 000000000..113d48084
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_config.c
@@ -0,0 +1,2006 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#define _GNU_SOURCE
+
+#include "vici_config.h"
+#include "vici_builder.h"
+
+#include <daemon.h>
+#include <threading/rwlock.h>
+#include <collections/array.h>
+#include <collections/linked_list.h>
+
+#include <stdio.h>
+
+/**
+ * Magic value for an undefined lifetime
+ */
+#define LFT_UNDEFINED (~(u_int64_t)0)
+
+/**
+ * Default IKE rekey time
+ */
+#define LFT_DEFAULT_IKE_REKEY (4 * 60 * 60)
+
+/**
+ * Default CHILD rekey time
+ */
+#define LFT_DEFAULT_CHILD_REKEY (1 * 60 * 60)
+
+/**
+ * Undefined replay window
+ */
+#define REPLAY_UNDEFINED (~(u_int32_t)0)
+
+typedef struct private_vici_config_t private_vici_config_t;
+
+/**
+ * Private data of an vici_config_t object.
+ */
+struct private_vici_config_t {
+
+ /**
+ * Public vici_config_t interface.
+ */
+ vici_config_t public;
+
+ /**
+ * Dispatcher
+ */
+ vici_dispatcher_t *dispatcher;
+
+ /**
+ * List of loaded connections, as peer_cfg_t
+ */
+ linked_list_t *conns;
+
+ /**
+ * Lock for conns list
+ */
+ rwlock_t *lock;
+};
+
+METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
+ private_vici_config_t *this, identification_t *me, identification_t *other)
+{
+ this->lock->read_lock(this->lock);
+ return enumerator_create_cleaner(this->conns->create_enumerator(this->conns),
+ (void*)this->lock->unlock, this->lock);
+}
+
+/**
+ * Enumerator filter function for ike configs
+ */
+static bool ike_filter(void *data, peer_cfg_t **in, ike_cfg_t **out)
+{
+ *out = (*in)->get_ike_cfg(*in);
+ return TRUE;
+}
+
+METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
+ private_vici_config_t *this, host_t *me, host_t *other)
+{
+ this->lock->read_lock(this->lock);
+ return enumerator_create_filter(this->conns->create_enumerator(this->conns),
+ (void*)ike_filter, this->lock,
+ (void*)this->lock->unlock);
+}
+
+METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
+ private_vici_config_t *this, char *name)
+{
+ peer_cfg_t *current, *found = NULL;
+ enumerator_t *enumerator;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->conns->create_enumerator(this->conns);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (streq(current->get_name(current), name))
+ {
+ found = current;
+ found->get_ref(found);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ return found;
+}
+
+/**
+ * Create a (error) reply message
+ */
+static vici_message_t* create_reply(char *fmt, ...)
+{
+ vici_builder_t *builder;
+ va_list args;
+
+ builder = vici_builder_create();
+ builder->add_kv(builder, "success", fmt ? "no" : "yes");
+ if (fmt)
+ {
+ va_start(args, fmt);
+ builder->vadd_kv(builder, "errmsg", fmt, args);
+ va_end(args);
+ }
+ return builder->finalize(builder);
+}
+
+/**
+ * A rule to parse a key/value or list item
+ */
+typedef struct {
+ /** name of the key/value or list */
+ char *name;
+ /** function to parse value */
+ bool (*parse)(void *out, chunk_t value);
+ /** result, passed to parse() */
+ void *out;
+} parse_rule_t;
+
+/**
+ * Parse key/values using a rule-set
+ */
+static bool parse_rules(parse_rule_t *rules, int count, char *name,
+ chunk_t value, vici_message_t **reply)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ {
+ if (streq(name, rules[i].name))
+ {
+ if (rules[i].parse(rules[i].out, value))
+ {
+ return TRUE;
+ }
+ *reply = create_reply("invalid value for: %s, config discarded",
+ name);
+ return FALSE;
+ }
+ }
+ *reply = create_reply("unknown option: %s, config discarded", name);
+ return FALSE;
+}
+
+/**
+ * Parse callback data, passed to each callback
+ */
+typedef struct {
+ private_vici_config_t *this;
+ vici_message_t *reply;
+} request_data_t;
+
+/**
+ * Data associated to a peer config
+ */
+typedef struct {
+ request_data_t *request;
+ u_int32_t version;
+ bool aggressive;
+ bool encap;
+ bool mobike;
+ bool send_certreq;
+ bool pull;
+ cert_policy_t send_cert;
+ u_int64_t dpd_delay;
+ u_int64_t dpd_timeout;
+ fragmentation_t fragmentation;
+ unique_policy_t unique;
+ u_int32_t keyingtries;
+ u_int32_t local_port;
+ u_int32_t remote_port;
+ char *local_addrs;
+ char *remote_addrs;
+ linked_list_t *local;
+ linked_list_t *remote;
+ linked_list_t *proposals;
+ linked_list_t *children;
+ linked_list_t *vips;
+ char *pools;
+ u_int64_t reauth_time;
+ u_int64_t rekey_time;
+ u_int64_t over_time;
+ u_int64_t rand_time;
+} peer_data_t;
+
+/**
+ * Log relevant auth config data
+ */
+static void log_auth(auth_cfg_t *auth)
+{
+ enumerator_t *enumerator;
+ auth_rule_t rule;
+ union {
+ uintptr_t u;
+ identification_t *id;
+ char *str;
+ } v;
+
+ enumerator = auth->create_enumerator(auth);
+ while (enumerator->enumerate(enumerator, &rule, &v))
+ {
+ switch (rule)
+ {
+ case AUTH_RULE_AUTH_CLASS:
+ DBG2(DBG_CFG, " class = %N", auth_class_names, v.u);
+ break;
+ case AUTH_RULE_EAP_TYPE:
+ DBG2(DBG_CFG, " eap-type = %N", eap_type_names, v.u);
+ break;
+ case AUTH_RULE_EAP_VENDOR:
+ DBG2(DBG_CFG, " eap-vendor = %u", v.u);
+ break;
+ case AUTH_RULE_XAUTH_BACKEND:
+ DBG2(DBG_CFG, " xauth = %s", v.str);
+ break;
+ case AUTH_RULE_CRL_VALIDATION:
+ DBG2(DBG_CFG, " revocation = %N", cert_validation_names, v.u);
+ break;
+ case AUTH_RULE_IDENTITY:
+ DBG2(DBG_CFG, " id = %Y", v.id);
+ break;
+ case AUTH_RULE_AAA_IDENTITY:
+ DBG2(DBG_CFG, " aaa_id = %Y", v.id);
+ break;
+ case AUTH_RULE_EAP_IDENTITY:
+ DBG2(DBG_CFG, " eap_id = %Y", v.id);
+ break;
+ case AUTH_RULE_XAUTH_IDENTITY:
+ DBG2(DBG_CFG, " xauth_id = %Y", v.id);
+ break;
+ case AUTH_RULE_GROUP:
+ DBG2(DBG_CFG, " group = %Y", v.id);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Log parsed peer data
+ */
+static void log_peer_data(peer_data_t *data)
+{
+ enumerator_t *enumerator;
+ auth_cfg_t *auth;
+ host_t *host;
+
+ DBG2(DBG_CFG, " version = %u", data->version);
+ DBG2(DBG_CFG, " local_addrs = %s", data->local_addrs);
+ DBG2(DBG_CFG, " remote_addrs = %s", data->remote_addrs);
+ DBG2(DBG_CFG, " local_port = %u", data->local_port);
+ DBG2(DBG_CFG, " remote_port = %u", data->remote_port);
+ DBG2(DBG_CFG, " send_certreq = %u", data->send_certreq);
+ DBG2(DBG_CFG, " send_cert = %N", cert_policy_names, data->send_cert);
+ DBG2(DBG_CFG, " mobike = %u", data->mobike);
+ DBG2(DBG_CFG, " aggressive = %u", data->aggressive);
+ DBG2(DBG_CFG, " encap = %u", data->encap);
+ DBG2(DBG_CFG, " dpd_delay = %llu", data->dpd_delay);
+ DBG2(DBG_CFG, " dpd_timeout = %llu", data->dpd_timeout);
+ DBG2(DBG_CFG, " fragmentation = %u", data->fragmentation);
+ DBG2(DBG_CFG, " unique = %N", unique_policy_names, data->unique);
+ DBG2(DBG_CFG, " keyingtries = %u", data->keyingtries);
+ DBG2(DBG_CFG, " reauth_time = %llu", data->reauth_time);
+ DBG2(DBG_CFG, " rekey_time = %llu", data->rekey_time);
+ DBG2(DBG_CFG, " over_time = %llu", data->over_time);
+ DBG2(DBG_CFG, " rand_time = %llu", data->rand_time);
+ DBG2(DBG_CFG, " proposals = %#P", data->proposals);
+
+ if (data->vips->get_count(data->vips))
+ {
+ DBG2(DBG_CFG, " vips:");
+ }
+ enumerator = data->vips->create_enumerator(data->vips);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ DBG2(DBG_CFG, " %H", host);
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = data->local->create_enumerator(data->local);
+ while (enumerator->enumerate(enumerator, &auth))
+ {
+ DBG2(DBG_CFG, " local:");
+ log_auth(auth);
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = data->remote->create_enumerator(data->remote);
+ while (enumerator->enumerate(enumerator, &auth))
+ {
+ DBG2(DBG_CFG, " remote:");
+ log_auth(auth);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Clean up peer config data
+ */
+static void free_peer_data(peer_data_t *data)
+{
+ data->local->destroy_offset(data->local,
+ offsetof(auth_cfg_t, destroy));
+ data->remote->destroy_offset(data->remote,
+ offsetof(auth_cfg_t, destroy));
+ data->children->destroy_offset(data->children,
+ offsetof(child_cfg_t, destroy));
+ data->proposals->destroy_offset(data->proposals,
+ offsetof(proposal_t, destroy));
+ data->vips->destroy_offset(data->vips, offsetof(host_t, destroy));
+ free(data->pools);
+ free(data->local_addrs);
+ free(data->remote_addrs);
+}
+
+/**
+ * CHILD config data
+ */
+typedef struct {
+ request_data_t *request;
+ lifetime_cfg_t lft;
+ char* updown;
+ bool hostaccess;
+ bool ipcomp;
+ bool route;
+ ipsec_mode_t mode;
+ u_int32_t replay_window;
+ action_t dpd_action;
+ action_t start_action;
+ action_t close_action;
+ u_int32_t reqid;
+ u_int32_t tfc;
+ mark_t mark_in;
+ mark_t mark_out;
+ u_int64_t inactivity;
+ linked_list_t *proposals;
+ linked_list_t *local_ts;
+ linked_list_t *remote_ts;
+} child_data_t;
+
+/**
+ * Log parsed CHILD config data
+ */
+static void log_child_data(child_data_t *data, char *name)
+{
+ DBG2(DBG_CFG, " child %s:", name);
+ DBG2(DBG_CFG, " rekey_time = %llu", data->lft.time.rekey);
+ DBG2(DBG_CFG, " life_time = %llu", data->lft.time.life);
+ DBG2(DBG_CFG, " rand_time = %llu", data->lft.time.jitter);
+ DBG2(DBG_CFG, " rekey_bytes = %llu", data->lft.bytes.rekey);
+ DBG2(DBG_CFG, " life_bytes = %llu", data->lft.bytes.life);
+ DBG2(DBG_CFG, " rand_bytes = %llu", data->lft.bytes.jitter);
+ DBG2(DBG_CFG, " rekey_packets = %llu", data->lft.packets.rekey);
+ DBG2(DBG_CFG, " life_packets = %llu", data->lft.packets.life);
+ DBG2(DBG_CFG, " rand_packets = %llu", data->lft.packets.jitter);
+ DBG2(DBG_CFG, " updown = %s", data->updown);
+ DBG2(DBG_CFG, " hostaccess = %u", data->hostaccess);
+ DBG2(DBG_CFG, " ipcomp = %u", data->ipcomp);
+ DBG2(DBG_CFG, " mode = %N", ipsec_mode_names, data->mode);
+ if (data->replay_window != REPLAY_UNDEFINED)
+ {
+ DBG2(DBG_CFG, " replay_window = %u", data->replay_window);
+ }
+ DBG2(DBG_CFG, " dpd_action = %N", action_names, data->dpd_action);
+ DBG2(DBG_CFG, " start_action = %N", action_names, data->start_action);
+ DBG2(DBG_CFG, " close_action = %N", action_names, data->close_action);
+ DBG2(DBG_CFG, " reqid = %u", data->reqid);
+ DBG2(DBG_CFG, " tfc = %d", data->tfc);
+ DBG2(DBG_CFG, " mark_in = %u/%u",
+ data->mark_in.value, data->mark_in.mask);
+ DBG2(DBG_CFG, " mark_out = %u/%u",
+ data->mark_out.value, data->mark_out.mask);
+ DBG2(DBG_CFG, " inactivity = %llu", data->inactivity);
+ DBG2(DBG_CFG, " proposals = %#P", data->proposals);
+ DBG2(DBG_CFG, " local_ts = %#R", data->local_ts);
+ DBG2(DBG_CFG, " remote_ts = %#R", data->remote_ts);
+}
+
+/**
+ * Clean up CHILD config data
+ */
+static void free_child_data(child_data_t *data)
+{
+ data->proposals->destroy_offset(data->proposals,
+ offsetof(proposal_t, destroy));
+ data->local_ts->destroy_offset(data->local_ts,
+ offsetof(traffic_selector_t, destroy));
+ data->remote_ts->destroy_offset(data->remote_ts,
+ offsetof(traffic_selector_t, destroy));
+ free(data->updown);
+}
+
+/**
+ * Auth config data
+ */
+typedef struct {
+ request_data_t *request;
+ auth_cfg_t *cfg;
+} auth_data_t;
+
+/**
+ * Common proposal parsing
+ */
+static bool parse_proposal(linked_list_t *list, protocol_id_t proto, chunk_t v)
+{
+ char buf[128];
+ proposal_t *proposal;
+
+ if (!vici_stringify(v, buf, sizeof(buf)))
+ {
+ return FALSE;
+ }
+ if (strcaseeq("default", buf))
+ {
+ proposal = proposal_create_default(proto);
+ if (proposal)
+ {
+ list->insert_last(list, proposal);
+ }
+ proposal = proposal_create_default_aead(proto);
+ if (proposal)
+ {
+ list->insert_last(list, proposal);
+ }
+ return TRUE;
+ }
+ proposal = proposal_create_from_string(proto, buf);
+ if (proposal)
+ {
+ list->insert_last(list, proposal);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse IKE proposal
+ */
+CALLBACK(parse_ike_proposal, bool,
+ linked_list_t *out, chunk_t v)
+{
+ return parse_proposal(out, PROTO_IKE, v);
+}
+
+/**
+ * Parse ESP proposal
+ */
+CALLBACK(parse_esp_proposal, bool,
+ linked_list_t *out, chunk_t v)
+{
+ return parse_proposal(out, PROTO_ESP, v);
+}
+
+/**
+ * Parse AH proposal
+ */
+CALLBACK(parse_ah_proposal, bool,
+ linked_list_t *out, chunk_t v)
+{
+ return parse_proposal(out, PROTO_AH, v);
+}
+
+/**
+ * Parse a traffic selector
+ */
+CALLBACK(parse_ts, bool,
+ linked_list_t *out, chunk_t v)
+{
+ char buf[128], *protoport, *sep, *port = "", *end;
+ traffic_selector_t *ts;
+ struct protoent *protoent;
+ struct servent *svc;
+ long int p;
+ u_int16_t from = 0, to = 0xffff;
+ u_int8_t proto = 0;
+
+ if (!vici_stringify(v, buf, sizeof(buf)))
+ {
+ return FALSE;
+ }
+
+ protoport = strchr(buf, '[');
+ if (protoport)
+ {
+ *(protoport++) = '\0';
+
+ sep = strrchr(protoport, ']');
+ if (!sep)
+ {
+ return FALSE;
+ }
+ *sep = '\0';
+
+ sep = strchr(protoport, '/');
+ if (sep)
+ { /* protocol/port */
+ *sep = '\0';
+ port = sep + 1;
+ }
+
+ if (streq(protoport, "any"))
+ {
+ proto = 0;
+ }
+ else
+ {
+ protoent = getprotobyname(protoport);
+ if (protoent)
+ {
+ proto = protoent->p_proto;
+ }
+ else
+ {
+ p = strtol(protoport, &end, 0);
+ if ((*protoport && *end) || p < 0 || p > 0xff)
+ {
+ return FALSE;
+ }
+ proto = (u_int8_t)p;
+ }
+ }
+ if (streq(port, "opaque"))
+ {
+ from = 0xffff;
+ to = 0;
+ }
+ else if (*port && !streq(port, "any"))
+ {
+ svc = getservbyname(port, NULL);
+ if (svc)
+ {
+ from = to = ntohs(svc->s_port);
+ }
+ else
+ {
+ p = strtol(port, &end, 0);
+ if (p < 0 || p > 0xffff)
+ {
+ return FALSE;
+ }
+ from = p;
+ if (*end == '-')
+ {
+ port = end + 1;
+ p = strtol(port, &end, 0);
+ if (p < 0 || p > 0xffff)
+ {
+ return FALSE;
+ }
+ }
+ to = p;
+ if (*end)
+ {
+ return FALSE;
+ }
+ }
+ }
+ }
+ if (streq(buf, "dynamic"))
+ {
+ ts = traffic_selector_create_dynamic(proto, from, to);
+ }
+ else
+ {
+ ts = traffic_selector_create_from_cidr(buf, proto, from, to);
+ }
+ if (!ts)
+ {
+ return FALSE;
+ }
+ out->insert_last(out, ts);
+ return TRUE;
+}
+
+/**
+ * Parse a string
+ */
+CALLBACK(parse_string, bool,
+ char **out, chunk_t v)
+{
+ if (!chunk_printable(v, NULL, ' '))
+ {
+ return FALSE;
+ }
+ free(*out);
+ *out = NULL;
+ if (asprintf(out, "%.*s", (int)v.len, v.ptr) == -1)
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Map a string to an integer
+ */
+typedef struct {
+ char *str;
+ int d;
+} enum_map_t;
+
+/**
+ * Parse a string to an integer mapping
+ */
+static bool parse_map(enum_map_t *map, int count, int *out, chunk_t v)
+{
+ char buf[128];
+ int i;
+
+ if (!vici_stringify(v, buf, sizeof(buf)))
+ {
+ return FALSE;
+ }
+ for (i = 0; i < count; i++)
+ {
+ if (strcaseeq(map[i].str, buf))
+ {
+ *out = map[i].d;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * Parse a boolean
+ */
+CALLBACK(parse_bool, bool,
+ bool *out, chunk_t v)
+{
+ enum_map_t map[] = {
+ { "yes", TRUE },
+ { "true", TRUE },
+ { "enabled", TRUE },
+ { "1", TRUE },
+ { "no", FALSE },
+ { "false", FALSE },
+ { "disabled", FALSE },
+ { "0", FALSE },
+ };
+ int d;
+
+ if (parse_map(map, countof(map), &d, v))
+ {
+ *out = d;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse a ipsec_mode_t
+ */
+CALLBACK(parse_mode, bool,
+ ipsec_mode_t *out, chunk_t v)
+{
+ enum_map_t map[] = {
+ { "tunnel", MODE_TUNNEL },
+ { "transport", MODE_TRANSPORT },
+ { "beet", MODE_BEET },
+ { "drop", MODE_DROP },
+ { "pass", MODE_PASS },
+ };
+ int d;
+
+ if (parse_map(map, countof(map), &d, v))
+ {
+ *out = d;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse an action_t
+ */
+CALLBACK(parse_action, bool,
+ action_t *out, chunk_t v)
+{
+ enum_map_t map[] = {
+ { "start", ACTION_RESTART },
+ { "restart", ACTION_RESTART },
+ { "route", ACTION_ROUTE },
+ { "trap", ACTION_ROUTE },
+ { "none", ACTION_NONE },
+ { "clear", ACTION_NONE },
+ };
+ int d;
+
+ if (parse_map(map, countof(map), &d, v))
+ {
+ *out = d;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse a u_int32_t
+ */
+CALLBACK(parse_uint32, bool,
+ u_int32_t *out, chunk_t v)
+{
+ char buf[16], *end;
+ u_long l;
+
+ if (!vici_stringify(v, buf, sizeof(buf)))
+ {
+ return FALSE;
+ }
+ l = strtoul(buf, &end, 0);
+ if (*end == 0)
+ {
+ *out = l;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse a u_int64_t
+ */
+CALLBACK(parse_uint64, bool,
+ u_int64_t *out, chunk_t v)
+{
+ char buf[16], *end;
+ unsigned long long l;
+
+ if (!vici_stringify(v, buf, sizeof(buf)))
+ {
+ return FALSE;
+ }
+ l = strtoull(buf, &end, 0);
+ if (*end == 0)
+ {
+ *out = l;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse a relative time
+ */
+CALLBACK(parse_time, bool,
+ u_int64_t *out, chunk_t v)
+{
+ char buf[16], *end;
+ u_long l;
+
+ if (!vici_stringify(v, buf, sizeof(buf)))
+ {
+ return FALSE;
+ }
+
+ l = strtoul(buf, &end, 0);
+ while (*end == ' ')
+ {
+ end++;
+ }
+ switch (*end)
+ {
+ case 'd':
+ case 'D':
+ l *= 24;
+ /* fall */
+ case 'h':
+ case 'H':
+ l *= 60;
+ /* fall */
+ case 'm':
+ case 'M':
+ l *= 60;
+ /* fall */
+ case 's':
+ case 'S':
+ end++;
+ break;
+ case '\0':
+ break;
+ default:
+ return FALSE;
+ }
+ if (*end)
+ {
+ return FALSE;
+ }
+ *out = l;
+ return TRUE;
+}
+
+/**
+ * Parse byte volume
+ */
+CALLBACK(parse_bytes, bool,
+ u_int64_t *out, chunk_t v)
+{
+ char buf[16], *end;
+ unsigned long long l;
+
+ if (!vici_stringify(v, buf, sizeof(buf)))
+ {
+ return FALSE;
+ }
+
+ l = strtoull(buf, &end, 0);
+ while (*end == ' ')
+ {
+ end++;
+ }
+ switch (*end)
+ {
+ case 'g':
+ case 'G':
+ l *= 1024;
+ /* fall */
+ case 'm':
+ case 'M':
+ l *= 1024;
+ /* fall */
+ case 'k':
+ case 'K':
+ l *= 1024;
+ end++;
+ break;
+ case '\0':
+ break;
+ default:
+ return FALSE;
+ }
+ if (*end)
+ {
+ return FALSE;
+ }
+ *out = l;
+ return TRUE;
+}
+
+/**
+ * Parse a mark_t
+ */
+CALLBACK(parse_mark, bool,
+ mark_t *out, chunk_t v)
+{
+ char buf[32];
+
+ if (!vici_stringify(v, buf, sizeof(buf)))
+ {
+ return FALSE;
+ }
+ return mark_from_string(buf, out);
+}
+
+/**
+ * Parse TFC padding option
+ */
+CALLBACK(parse_tfc, bool,
+ u_int32_t *out, chunk_t v)
+{
+ if (chunk_equals(v, chunk_from_str("mtu")))
+ {
+ *out = -1;
+ return TRUE;
+ }
+ return parse_uint32(out, v);
+}
+
+/**
+ * Parse authentication config
+ */
+CALLBACK(parse_auth, bool,
+ auth_cfg_t *cfg, chunk_t v)
+{
+ char buf[64], *pos;
+ eap_vendor_type_t *type;
+
+ if (!vici_stringify(v, buf, sizeof(buf)))
+ {
+ return FALSE;
+ }
+ if (strcaseeq(buf, "pubkey"))
+ {
+ cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+ return TRUE;
+ }
+ if (strcaseeq(buf, "psk"))
+ {
+ cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
+ return TRUE;
+ }
+ if (strcasepfx(buf, "xauth"))
+ {
+ pos = strchr(buf, '-');
+ if (pos)
+ {
+ cfg->add(cfg, AUTH_RULE_XAUTH_BACKEND, strdup(++pos));
+ }
+ cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_XAUTH);
+ return TRUE;
+ }
+ if (strcasepfx(buf, "eap"))
+ {
+ cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
+
+ type = eap_vendor_type_from_string(buf);
+ if (type)
+ {
+ cfg->add(cfg, AUTH_RULE_EAP_TYPE, type->type);
+ if (type->vendor)
+ {
+ cfg->add(cfg, AUTH_RULE_EAP_VENDOR, type->vendor);
+ }
+ free(type);
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse identity; add as auth rule to config
+ */
+static bool parse_id(auth_cfg_t *cfg, auth_rule_t rule, chunk_t v)
+{
+ char buf[256];
+
+ if (!vici_stringify(v, buf, sizeof(buf)))
+ {
+ return FALSE;
+ }
+ cfg->add(cfg, rule, identification_create_from_string(buf));
+ return TRUE;
+}
+
+/**
+ * Parse IKE identity
+ */
+CALLBACK(parse_ike_id, bool,
+ auth_cfg_t *cfg, chunk_t v)
+{
+ return parse_id(cfg, AUTH_RULE_IDENTITY, v);
+}
+
+/**
+ * Parse AAA identity
+ */
+CALLBACK(parse_aaa_id, bool,
+ auth_cfg_t *cfg, chunk_t v)
+{
+ return parse_id(cfg, AUTH_RULE_AAA_IDENTITY, v);
+}
+
+/**
+ * Parse EAP identity
+ */
+CALLBACK(parse_eap_id, bool,
+ auth_cfg_t *cfg, chunk_t v)
+{
+ return parse_id(cfg, AUTH_RULE_EAP_IDENTITY, v);
+}
+
+/**
+ * Parse XAuth identity
+ */
+CALLBACK(parse_xauth_id, bool,
+ auth_cfg_t *cfg, chunk_t v)
+{
+ return parse_id(cfg, AUTH_RULE_XAUTH_IDENTITY, v);
+}
+
+/**
+ * Parse group membership
+ */
+CALLBACK(parse_group, bool,
+ auth_cfg_t *cfg, chunk_t v)
+{
+ return parse_id(cfg, AUTH_RULE_GROUP, v);
+}
+
+/**
+ * Parse a certificate; add as auth rule to config
+ */
+static bool parse_cert(auth_cfg_t *cfg, auth_rule_t rule, chunk_t v)
+{
+ certificate_t *cert;
+
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_PEM, v, BUILD_END);
+ if (cert)
+ {
+ cfg->add(cfg, rule, cert);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse subject certificates
+ */
+CALLBACK(parse_certs, bool,
+ auth_cfg_t *cfg, chunk_t v)
+{
+ return parse_cert(cfg, AUTH_RULE_SUBJECT_CERT, v);
+}
+
+/**
+ * Parse CA certificates
+ */
+CALLBACK(parse_cacerts, bool,
+ auth_cfg_t *cfg, chunk_t v)
+{
+ return parse_cert(cfg, AUTH_RULE_CA_CERT, v);
+}
+
+/**
+ * Parse revocation status
+ */
+CALLBACK(parse_revocation, bool,
+ auth_cfg_t *cfg, chunk_t v)
+{
+ enum_map_t map[] = {
+ { "strict", VALIDATION_GOOD },
+ { "ifuri", VALIDATION_SKIPPED },
+ { "relaxed", VALIDATION_FAILED },
+ };
+ int d;
+
+ if (parse_map(map, countof(map), &d, v))
+ {
+ if (d != VALIDATION_FAILED)
+ {
+ cfg->add(cfg, AUTH_RULE_CRL_VALIDATION, d);
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse list items to comma separated strings
+ */
+CALLBACK(parse_stringlist, bool,
+ char **out, chunk_t v)
+{
+ char *current;
+
+ if (!chunk_printable(v, NULL, ' '))
+ {
+ return FALSE;
+ }
+ current = *out;
+ if (current)
+ {
+ if (asprintf(out, "%s, %.*s", current, (int)v.len, v.ptr) == -1)
+ {
+ return FALSE;
+ }
+ free(current);
+ }
+ else
+ {
+ if (asprintf(out, "%.*s", (int)v.len, v.ptr) == -1)
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Parse an fragmentation_t
+ */
+CALLBACK(parse_frag, bool,
+ fragmentation_t *out, chunk_t v)
+{
+ enum_map_t map[] = {
+ { "yes", FRAGMENTATION_YES },
+ { "no", FRAGMENTATION_NO },
+ { "force", FRAGMENTATION_FORCE },
+ };
+ int d;
+
+ if (parse_map(map, countof(map), &d, v))
+ {
+ *out = d;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse a cert_policy_t
+ */
+CALLBACK(parse_send_cert, bool,
+ cert_policy_t *out, chunk_t v)
+{
+ enum_map_t map[] = {
+ { "ifasked", CERT_SEND_IF_ASKED },
+ { "always", CERT_ALWAYS_SEND },
+ { "never", CERT_NEVER_SEND },
+ };
+ int d;
+
+ if (parse_map(map, countof(map), &d, v))
+ {
+ *out = d;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse a unique_policy_t
+ */
+CALLBACK(parse_unique, bool,
+ unique_policy_t *out, chunk_t v)
+{
+ enum_map_t map[] = {
+ { "never", UNIQUE_NEVER },
+ { "no", UNIQUE_NO },
+ { "replace", UNIQUE_REPLACE },
+ { "keep", UNIQUE_KEEP },
+ };
+ int d;
+
+ if (parse_map(map, countof(map), &d, v))
+ {
+ *out = d;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse host_t into a list
+ */
+CALLBACK(parse_hosts, bool,
+ linked_list_t *list, chunk_t v)
+{
+ char buf[64];
+ host_t *host;
+
+ if (!vici_stringify(v, buf, sizeof(buf)))
+ {
+ return FALSE;
+ }
+ host = host_create_from_string(buf, 0);
+ if (!host)
+ {
+ return FALSE;
+ }
+ list->insert_last(list, host);
+ return TRUE;
+}
+
+CALLBACK(child_li, bool,
+ child_data_t *child, vici_message_t *message, char *name, chunk_t value)
+{
+ parse_rule_t rules[] = {
+ { "ah_proposals", parse_ah_proposal, child->proposals },
+ { "esp_proposals", parse_esp_proposal, child->proposals },
+ { "local_ts", parse_ts, child->local_ts },
+ { "remote_ts", parse_ts, child->remote_ts },
+ };
+
+ return parse_rules(rules, countof(rules), name, value,
+ &child->request->reply);
+}
+
+CALLBACK(child_kv, bool,
+ child_data_t *child, vici_message_t *message, char *name, chunk_t value)
+{
+ parse_rule_t rules[] = {
+ { "updown", parse_string, &child->updown },
+ { "hostaccess", parse_bool, &child->hostaccess },
+ { "mode", parse_mode, &child->mode },
+ { "replay_window", parse_uint32, &child->replay_window },
+ { "rekey_time", parse_time, &child->lft.time.rekey },
+ { "life_time", parse_time, &child->lft.time.life },
+ { "rand_time", parse_time, &child->lft.time.jitter },
+ { "rekey_bytes", parse_bytes, &child->lft.bytes.rekey },
+ { "life_bytes", parse_bytes, &child->lft.bytes.life },
+ { "rand_bytes", parse_bytes, &child->lft.bytes.jitter },
+ { "rekey_packets", parse_uint64, &child->lft.packets.rekey },
+ { "life_packets", parse_uint64, &child->lft.packets.life },
+ { "rand_packets", parse_uint64, &child->lft.packets.jitter },
+ { "dpd_action", parse_action, &child->dpd_action },
+ { "start_action", parse_action, &child->start_action },
+ { "close_action", parse_action, &child->close_action },
+ { "ipcomp", parse_bool, &child->ipcomp },
+ { "inactivity", parse_time, &child->inactivity },
+ { "reqid", parse_uint32, &child->reqid },
+ { "mark_in", parse_mark, &child->mark_in },
+ { "mark_out", parse_mark, &child->mark_out },
+ { "tfc_padding", parse_tfc, &child->tfc },
+ };
+
+ return parse_rules(rules, countof(rules), name, value,
+ &child->request->reply);
+}
+
+CALLBACK(auth_li, bool,
+ auth_data_t *auth, vici_message_t *message, char *name, chunk_t value)
+{
+ parse_rule_t rules[] = {
+ { "groups", parse_group, auth->cfg },
+ { "certs", parse_certs, auth->cfg },
+ { "cacerts", parse_cacerts, auth->cfg },
+ };
+
+ return parse_rules(rules, countof(rules), name, value,
+ &auth->request->reply);
+}
+
+CALLBACK(auth_kv, bool,
+ auth_data_t *auth, vici_message_t *message, char *name, chunk_t value)
+{
+ parse_rule_t rules[] = {
+ { "auth", parse_auth, auth->cfg },
+ { "id", parse_ike_id, auth->cfg },
+ { "aaa_id", parse_aaa_id, auth->cfg },
+ { "eap_id", parse_eap_id, auth->cfg },
+ { "xauth_id", parse_xauth_id, auth->cfg },
+ { "revocation", parse_revocation, auth->cfg },
+ };
+
+ return parse_rules(rules, countof(rules), name, value,
+ &auth->request->reply);
+}
+
+CALLBACK(peer_li, bool,
+ peer_data_t *peer, vici_message_t *message, char *name, chunk_t value)
+{
+ parse_rule_t rules[] = {
+ { "local_addrs", parse_stringlist, &peer->local_addrs },
+ { "remote_addrs", parse_stringlist, &peer->remote_addrs },
+ { "proposals", parse_ike_proposal, peer->proposals },
+ { "vips", parse_hosts, peer->vips },
+ { "pools", parse_stringlist, &peer->pools },
+ };
+
+ return parse_rules(rules, countof(rules), name, value,
+ &peer->request->reply);
+}
+
+CALLBACK(peer_kv, bool,
+ peer_data_t *peer, vici_message_t *message, char *name, chunk_t value)
+{
+ parse_rule_t rules[] = {
+ { "version", parse_uint32, &peer->version },
+ { "aggressive", parse_bool, &peer->aggressive },
+ { "pull", parse_bool, &peer->pull },
+ { "encap", parse_bool, &peer->encap },
+ { "mobike", parse_bool, &peer->mobike },
+ { "dpd_delay", parse_time, &peer->dpd_delay },
+ { "dpd_timeout", parse_time, &peer->dpd_timeout },
+ { "fragmentation", parse_frag, &peer->fragmentation },
+ { "send_certreq", parse_bool, &peer->send_certreq },
+ { "send_cert", parse_send_cert, &peer->send_cert },
+ { "keyingtries", parse_uint32, &peer->keyingtries },
+ { "unique", parse_unique, &peer->unique },
+ { "local_port", parse_uint32, &peer->local_port },
+ { "remote_port", parse_uint32, &peer->remote_port },
+ { "reauth_time", parse_time, &peer->reauth_time },
+ { "rekey_time", parse_time, &peer->rekey_time },
+ { "over_time", parse_time, &peer->over_time },
+ { "rand_time", parse_time, &peer->rand_time },
+ };
+
+ return parse_rules(rules, countof(rules), name, value,
+ &peer->request->reply);
+}
+
+CALLBACK(children_sn, bool,
+ peer_data_t *peer, vici_message_t *message, vici_parse_context_t *ctx,
+ char *name)
+{
+ child_data_t child = {
+ .request = peer->request,
+ .proposals = linked_list_create(),
+ .local_ts = linked_list_create(),
+ .remote_ts = linked_list_create(),
+ .mode = MODE_TUNNEL,
+ .replay_window = REPLAY_UNDEFINED,
+ .dpd_action = ACTION_NONE,
+ .start_action = ACTION_NONE,
+ .close_action = ACTION_NONE,
+ .lft = {
+ .time = {
+ .rekey = LFT_DEFAULT_CHILD_REKEY,
+ .life = LFT_UNDEFINED,
+ .jitter = LFT_UNDEFINED,
+ },
+ .bytes = {
+ .life = LFT_UNDEFINED,
+ .jitter = LFT_UNDEFINED,
+ },
+ .packets = {
+ .life = LFT_UNDEFINED,
+ .jitter = LFT_UNDEFINED,
+ },
+ }
+ };
+ child_cfg_t *cfg;
+ proposal_t *proposal;
+ traffic_selector_t *ts;
+
+ if (!message->parse(message, ctx, NULL, child_kv, child_li, &child))
+ {
+ free_child_data(&child);
+ return FALSE;
+ }
+
+ if (child.local_ts->get_count(child.local_ts) == 0)
+ {
+ child.local_ts->insert_last(child.local_ts,
+ traffic_selector_create_dynamic(0, 0, 65535));
+ }
+ if (child.remote_ts->get_count(child.remote_ts) == 0)
+ {
+ child.remote_ts->insert_last(child.remote_ts,
+ traffic_selector_create_dynamic(0, 0, 65535));
+ }
+ if (child.proposals->get_count(child.proposals) == 0)
+ {
+ proposal = proposal_create_default(PROTO_ESP);
+ if (proposal)
+ {
+ child.proposals->insert_last(child.proposals, proposal);
+ }
+ proposal = proposal_create_default_aead(PROTO_ESP);
+ if (proposal)
+ {
+ child.proposals->insert_last(child.proposals, proposal);
+ }
+ }
+
+ /* if no hard lifetime specified, add one at soft lifetime + 10% */
+ if (child.lft.time.life == LFT_UNDEFINED)
+ {
+ child.lft.time.life = child.lft.time.rekey * 110 / 100;
+ }
+ if (child.lft.bytes.life == LFT_UNDEFINED)
+ {
+ child.lft.bytes.life = child.lft.bytes.rekey * 110 / 100;
+ }
+ if (child.lft.packets.life == LFT_UNDEFINED)
+ {
+ child.lft.packets.life = child.lft.packets.rekey * 110 / 100;
+ }
+ /* if no rand time defined, use difference of hard and soft */
+ if (child.lft.time.jitter == LFT_UNDEFINED)
+ {
+ child.lft.time.jitter = child.lft.time.life -
+ min(child.lft.time.life, child.lft.time.rekey);
+ }
+ if (child.lft.bytes.jitter == LFT_UNDEFINED)
+ {
+ child.lft.bytes.jitter = child.lft.bytes.life -
+ min(child.lft.bytes.life, child.lft.bytes.rekey);
+ }
+ if (child.lft.packets.jitter == LFT_UNDEFINED)
+ {
+ child.lft.packets.jitter = child.lft.packets.life -
+ min(child.lft.packets.life, child.lft.packets.rekey);
+ }
+
+ log_child_data(&child, name);
+
+ cfg = child_cfg_create(name, &child.lft, child.updown,
+ child.hostaccess, child.mode, child.start_action,
+ child.dpd_action, child.close_action, child.ipcomp,
+ child.inactivity, child.reqid, &child.mark_in,
+ &child.mark_out, child.tfc);
+
+ if (child.replay_window != REPLAY_UNDEFINED)
+ {
+ cfg->set_replay_window(cfg, child.replay_window);
+ }
+ while (child.local_ts->remove_first(child.local_ts,
+ (void**)&ts) == SUCCESS)
+ {
+ cfg->add_traffic_selector(cfg, TRUE, ts);
+ }
+ while (child.remote_ts->remove_first(child.remote_ts,
+ (void**)&ts) == SUCCESS)
+ {
+ cfg->add_traffic_selector(cfg, FALSE, ts);
+ }
+ while (child.proposals->remove_first(child.proposals,
+ (void**)&proposal) == SUCCESS)
+ {
+ cfg->add_proposal(cfg, proposal);
+ }
+
+ peer->children->insert_last(peer->children, cfg);
+
+ free_child_data(&child);
+
+ return TRUE;
+}
+
+CALLBACK(peer_sn, bool,
+ peer_data_t *peer, vici_message_t *message, vici_parse_context_t *ctx,
+ char *name)
+{
+ if (strcaseeq(name, "children"))
+ {
+ return message->parse(message, ctx, children_sn, NULL, NULL, peer);
+ }
+ if (strcasepfx(name, "local") ||
+ strcasepfx(name, "remote"))
+ {
+ auth_data_t auth = {
+ .request = peer->request,
+ .cfg = auth_cfg_create(),
+ };
+
+ if (!message->parse(message, ctx, NULL, auth_kv, auth_li, &auth))
+ {
+ auth.cfg->destroy(auth.cfg);
+ return FALSE;
+ }
+
+ if (strcasepfx(name, "local"))
+ {
+ peer->local->insert_last(peer->local, auth.cfg);
+ }
+ else
+ {
+ peer->remote->insert_last(peer->remote, auth.cfg);
+ }
+ return TRUE;
+ }
+ peer->request->reply = create_reply("invalid section: %s", name);
+ return FALSE;
+}
+
+/**
+ * Find reqid of an existing CHILD_SA
+ */
+static u_int32_t find_reqid(child_cfg_t *cfg)
+{
+ enumerator_t *enumerator, *children;
+ child_sa_t *child_sa;
+ ike_sa_t *ike_sa;
+ u_int32_t reqid;
+
+ reqid = charon->traps->find_reqid(charon->traps, cfg);
+ if (reqid)
+ { /* already trapped */
+ return reqid;
+ }
+
+ enumerator = charon->controller->create_ike_sa_enumerator(
+ charon->controller, TRUE);
+ while (!reqid && enumerator->enumerate(enumerator, &ike_sa))
+ {
+ children = ike_sa->create_child_sa_enumerator(ike_sa);
+ while (children->enumerate(children, &child_sa))
+ {
+ if (streq(cfg->get_name(cfg), child_sa->get_name(child_sa)))
+ {
+ reqid = child_sa->get_reqid(child_sa);
+ break;
+ }
+ }
+ children->destroy(children);
+ }
+ enumerator->destroy(enumerator);
+ return reqid;
+}
+
+/**
+ * Perform start actions associated to a child config
+ */
+static void run_start_action(private_vici_config_t *this, peer_cfg_t *peer_cfg,
+ child_cfg_t *child_cfg)
+{
+ switch (child_cfg->get_start_action(child_cfg))
+ {
+ case ACTION_RESTART:
+ DBG1(DBG_CFG, "initiating '%s'", child_cfg->get_name(child_cfg));
+ charon->controller->initiate(charon->controller,
+ peer_cfg->get_ref(peer_cfg), child_cfg->get_ref(child_cfg),
+ NULL, NULL, 0);
+ break;
+ case ACTION_ROUTE:
+ DBG1(DBG_CFG, "installing '%s'", child_cfg->get_name(child_cfg));
+ switch (child_cfg->get_mode(child_cfg))
+ {
+ case MODE_PASS:
+ case MODE_DROP:
+ charon->shunts->install(charon->shunts, child_cfg);
+ break;
+ default:
+ charon->traps->install(charon->traps, peer_cfg, child_cfg,
+ find_reqid(child_cfg));
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Undo start actions associated to a child config
+ */
+static void clear_start_action(private_vici_config_t *this,
+ child_cfg_t *child_cfg)
+{
+ enumerator_t *enumerator, *children;
+ child_sa_t *child_sa;
+ ike_sa_t *ike_sa;
+ u_int32_t reqid = 0, *del;
+ array_t *reqids = NULL;
+ char *name;
+
+ name = child_cfg->get_name(child_cfg);
+ switch (child_cfg->get_start_action(child_cfg))
+ {
+ case ACTION_RESTART:
+ enumerator = charon->controller->create_ike_sa_enumerator(
+ charon->controller, TRUE);
+ while (enumerator->enumerate(enumerator, &ike_sa))
+ {
+ children = ike_sa->create_child_sa_enumerator(ike_sa);
+ while (children->enumerate(children, &child_sa))
+ {
+ if (streq(name, child_sa->get_name(child_sa)))
+ {
+ reqid = child_sa->get_reqid(child_sa);
+ array_insert_create(&reqids, ARRAY_TAIL, &reqid);
+ }
+ }
+ children->destroy(children);
+ }
+ enumerator->destroy(enumerator);
+
+ if (array_count(reqids))
+ {
+ while (array_remove(reqids, ARRAY_HEAD, &del))
+ {
+ DBG1(DBG_CFG, "closing '%s' #%u", name, *del);
+ charon->controller->terminate_child(charon->controller,
+ *del, NULL, NULL, 0);
+ }
+ array_destroy(reqids);
+ }
+ break;
+ case ACTION_ROUTE:
+ DBG1(DBG_CFG, "uninstalling '%s'", name);
+ switch (child_cfg->get_mode(child_cfg))
+ {
+ case MODE_PASS:
+ case MODE_DROP:
+ charon->shunts->uninstall(charon->shunts, name);
+ break;
+ default:
+ enumerator = charon->traps->create_enumerator(charon->traps);
+ while (enumerator->enumerate(enumerator, NULL, &child_sa))
+ {
+ if (streq(name, child_sa->get_name(child_sa)))
+ {
+ reqid = child_sa->get_reqid(child_sa);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (reqid)
+ {
+ charon->traps->uninstall(charon->traps, reqid);
+ }
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Run start actions associated to all child configs of a peer config
+ */
+static void run_start_actions(private_vici_config_t *this, peer_cfg_t *peer_cfg)
+{
+ enumerator_t *enumerator;
+ child_cfg_t *child_cfg;
+
+ enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
+ while (enumerator->enumerate(enumerator, &child_cfg))
+ {
+ run_start_action(this, peer_cfg, child_cfg);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Undo start actions associated to all child configs of a peer config
+ */
+static void clear_start_actions(private_vici_config_t *this,
+ peer_cfg_t *peer_cfg)
+{
+ enumerator_t *enumerator;
+ child_cfg_t *child_cfg;
+
+ enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
+ while (enumerator->enumerate(enumerator, &child_cfg))
+ {
+ clear_start_action(this, child_cfg);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Replace children of a peer config by a new config
+ */
+static void replace_children(private_vici_config_t *this,
+ peer_cfg_t *from, peer_cfg_t *to)
+{
+ enumerator_t *enumerator;
+ child_cfg_t *child;
+
+ enumerator = to->create_child_cfg_enumerator(to);
+ while (enumerator->enumerate(enumerator, &child))
+ {
+ to->remove_child_cfg(to, enumerator);
+ clear_start_action(this, child);
+ child->destroy(child);
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = from->create_child_cfg_enumerator(from);
+ while (enumerator->enumerate(enumerator, &child))
+ {
+ from->remove_child_cfg(from, enumerator);
+ to->add_child_cfg(to, child);
+ run_start_action(this, to, child);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Merge/replace a peer config with existing configs
+ */
+static void merge_config(private_vici_config_t *this, peer_cfg_t *peer_cfg)
+{
+ enumerator_t *enumerator;
+ peer_cfg_t *current;
+ ike_cfg_t *ike_cfg;
+ bool merged = FALSE;
+
+ this->lock->write_lock(this->lock);
+
+ enumerator = this->conns->create_enumerator(this->conns);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (streq(peer_cfg->get_name(peer_cfg), current->get_name(current)))
+ {
+ ike_cfg = current->get_ike_cfg(current);
+ if (peer_cfg->equals(peer_cfg, current) &&
+ ike_cfg->equals(ike_cfg, peer_cfg->get_ike_cfg(peer_cfg)))
+ {
+ DBG1(DBG_CFG, "updated vici connection: %s",
+ peer_cfg->get_name(peer_cfg));
+ replace_children(this, peer_cfg, current);
+ peer_cfg->destroy(peer_cfg);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "replaced vici connection: %s",
+ peer_cfg->get_name(peer_cfg));
+ this->conns->remove_at(this->conns, enumerator);
+ clear_start_actions(this, current);
+ current->destroy(current);
+ this->conns->insert_last(this->conns, peer_cfg);
+ run_start_actions(this, peer_cfg);
+ }
+ merged = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!merged)
+ {
+ DBG1(DBG_CFG, "added vici connection: %s", peer_cfg->get_name(peer_cfg));
+ this->conns->insert_last(this->conns, peer_cfg);
+ run_start_actions(this, peer_cfg);
+ }
+
+ this->lock->unlock(this->lock);
+}
+
+CALLBACK(config_sn, bool,
+ request_data_t *request, vici_message_t *message,
+ vici_parse_context_t *ctx, char *name)
+{
+ peer_data_t peer = {
+ .request = request,
+ .local = linked_list_create(),
+ .remote = linked_list_create(),
+ .vips = linked_list_create(),
+ .children = linked_list_create(),
+ .proposals = linked_list_create(),
+ .mobike = TRUE,
+ .send_certreq = TRUE,
+ .pull = TRUE,
+ .send_cert = CERT_SEND_IF_ASKED,
+ .version = IKE_ANY,
+ .remote_port = IKEV2_UDP_PORT,
+ .fragmentation = FRAGMENTATION_NO,
+ .unique = UNIQUE_NO,
+ .keyingtries = 1,
+ .rekey_time = LFT_DEFAULT_IKE_REKEY,
+ .over_time = LFT_UNDEFINED,
+ .rand_time = LFT_UNDEFINED,
+ };
+ enumerator_t *enumerator;
+ peer_cfg_t *peer_cfg;
+ ike_cfg_t *ike_cfg;
+ child_cfg_t *child_cfg;
+ auth_cfg_t *auth_cfg;
+ proposal_t *proposal;
+ host_t *host;
+ char *str;
+
+ DBG2(DBG_CFG, " conn %s:", name);
+
+ if (!message->parse(message, ctx, peer_sn, peer_kv, peer_li, &peer))
+ {
+ free_peer_data(&peer);
+ return FALSE;
+ }
+
+ if (peer.local->get_count(peer.local) == 0)
+ {
+ free_peer_data(&peer);
+ peer.request->reply = create_reply("missing local auth config");
+ return FALSE;
+ }
+ if (peer.remote->get_count(peer.remote) == 0)
+ {
+ auth_cfg = auth_cfg_create();
+ peer.remote->insert_last(peer.remote, auth_cfg);
+ }
+ if (peer.proposals->get_count(peer.proposals) == 0)
+ {
+ proposal = proposal_create_default(PROTO_IKE);
+ if (proposal)
+ {
+ peer.proposals->insert_last(peer.proposals, proposal);
+ }
+ proposal = proposal_create_default_aead(PROTO_IKE);
+ if (proposal)
+ {
+ peer.proposals->insert_last(peer.proposals, proposal);
+ }
+ }
+ if (!peer.local_addrs)
+ {
+ peer.local_addrs = strdup("%any");
+ }
+ if (!peer.remote_addrs)
+ {
+ peer.remote_addrs = strdup("%any");
+ }
+ if (!peer.local_port)
+ {
+ peer.local_port = charon->socket->get_port(charon->socket, FALSE);
+ }
+
+ if (peer.over_time == LFT_UNDEFINED)
+ {
+ /* default over_time to 10% of rekey/reauth time if not given */
+ peer.over_time = max(peer.rekey_time, peer.reauth_time) / 10;
+ }
+ if (peer.rand_time == LFT_UNDEFINED)
+ {
+ /* default rand_time to over_time if not given */
+ peer.rand_time = min(peer.over_time,
+ max(peer.rekey_time, peer.reauth_time) / 2);
+ }
+
+ log_peer_data(&peer);
+
+ ike_cfg = ike_cfg_create(peer.version, peer.send_certreq, peer.encap,
+ peer.local_addrs, peer.local_port,
+ peer.remote_addrs, peer.remote_port,
+ peer.fragmentation, 0);
+ peer_cfg = peer_cfg_create(name, ike_cfg, peer.send_cert, peer.unique,
+ peer.keyingtries, peer.rekey_time, peer.reauth_time,
+ peer.rand_time, peer.over_time, peer.mobike,
+ peer.aggressive, peer.pull,
+ peer.dpd_delay, peer.dpd_timeout,
+ FALSE, NULL, NULL);
+
+ while (peer.local->remove_first(peer.local,
+ (void**)&auth_cfg) == SUCCESS)
+ {
+ peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE);
+ }
+ while (peer.remote->remove_first(peer.remote,
+ (void**)&auth_cfg) == SUCCESS)
+ {
+ peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
+ }
+ while (peer.children->remove_first(peer.children,
+ (void**)&child_cfg) == SUCCESS)
+ {
+ peer_cfg->add_child_cfg(peer_cfg, child_cfg);
+ }
+ while (peer.proposals->remove_first(peer.proposals,
+ (void**)&proposal) == SUCCESS)
+ {
+ ike_cfg->add_proposal(ike_cfg, proposal);
+ }
+ while (peer.vips->remove_first(peer.vips, (void**)&host) == SUCCESS)
+ {
+ peer_cfg->add_virtual_ip(peer_cfg, host);
+ }
+ if (peer.pools)
+ {
+ enumerator = enumerator_create_token(peer.pools, ",", " ");
+ while (enumerator->enumerate(enumerator, &str))
+ {
+ peer_cfg->add_pool(peer_cfg, str);
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ free_peer_data(&peer);
+
+ merge_config(request->this, peer_cfg);
+
+ return TRUE;
+}
+
+CALLBACK(load_conn, vici_message_t*,
+ private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
+{
+ request_data_t request = {
+ .this = this,
+ };
+
+ if (!message->parse(message, NULL, config_sn, NULL, NULL, &request))
+ {
+ if (request.reply)
+ {
+ return request.reply;
+ }
+ return create_reply("parsing request failed");
+ }
+ return create_reply(NULL);
+}
+
+CALLBACK(unload_conn, vici_message_t*,
+ private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
+{
+ enumerator_t *enumerator;
+ peer_cfg_t *cfg;
+ bool found = FALSE;
+ char *conn;
+
+ conn = message->get_str(message, NULL, "name");
+ if (!conn)
+ {
+ return create_reply("missing connection name to unload");
+ }
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->conns->create_enumerator(this->conns);
+ while (enumerator->enumerate(enumerator, &cfg))
+ {
+ if (streq(cfg->get_name(cfg), conn))
+ {
+ this->conns->remove_at(this->conns, enumerator);
+ cfg->destroy(cfg);
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ if (!found)
+ {
+ return create_reply("connection '%s' not found for unloading", conn);
+ }
+ return create_reply(NULL);
+}
+
+CALLBACK(get_conns, vici_message_t*,
+ private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
+{
+ vici_builder_t *builder;
+ enumerator_t *enumerator;
+ peer_cfg_t *cfg;
+
+ builder = vici_builder_create();
+ builder->begin_list(builder, "conns");
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->conns->create_enumerator(this->conns);
+ while (enumerator->enumerate(enumerator, &cfg))
+ {
+ builder->add_li(builder, "%s", cfg->get_name(cfg));
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ builder->end_list(builder);
+
+ return builder->finalize(builder);
+}
+
+static void manage_command(private_vici_config_t *this,
+ char *name, vici_command_cb_t cb, bool reg)
+{
+ this->dispatcher->manage_command(this->dispatcher, name,
+ reg ? cb : NULL, this);
+}
+
+/**
+ * (Un-)register dispatcher functions
+ */
+static void manage_commands(private_vici_config_t *this, bool reg)
+{
+ manage_command(this, "load-conn", load_conn, reg);
+ manage_command(this, "unload-conn", unload_conn, reg);
+ manage_command(this, "get-conns", get_conns, reg);
+}
+
+METHOD(vici_config_t, destroy, void,
+ private_vici_config_t *this)
+{
+ manage_commands(this, FALSE);
+ this->conns->destroy_offset(this->conns, offsetof(peer_cfg_t, destroy));
+ this->lock->destroy(this->lock);
+ free(this);
+}
+
+/**
+ * See header
+ */
+vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher)
+{
+ private_vici_config_t *this;
+
+ INIT(this,
+ .public = {
+ .backend = {
+ .create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
+ .create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
+ .get_peer_cfg_by_name = _get_peer_cfg_by_name,
+ },
+ .destroy = _destroy,
+ },
+ .dispatcher = dispatcher,
+ .conns = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ manage_commands(this, TRUE);
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/vici/vici_config.h b/src/libcharon/plugins/vici/vici_config.h
new file mode 100644
index 000000000..820d5f300
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_config.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup vici_config vici_config
+ * @{ @ingroup vici
+ */
+
+#ifndef VICI_CONFIG_H_
+#define VICI_CONFIG_H_
+
+#include "vici_dispatcher.h"
+
+#include <config/backend.h>
+
+typedef struct vici_config_t vici_config_t;
+
+/**
+ * In-memory configuration backend, managed by VICI.
+ */
+struct vici_config_t {
+
+ /**
+ * Implements a configuraiton backend.
+ */
+ backend_t backend;
+
+ /**
+ * Destroy a vici_config_t.
+ */
+ void (*destroy)(vici_config_t *this);
+};
+/**
+ * Create a vici_config instance.
+ *
+ * @param dispatcher dispatcher to receive requests from
+ * @return config backend
+ */
+vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher);
+
+#endif /** VICI_CONFIG_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_control.c b/src/libcharon/plugins/vici/vici_control.c
new file mode 100644
index 000000000..3cd008162
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_control.c
@@ -0,0 +1,496 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "vici_control.h"
+#include "vici_builder.h"
+
+#include <inttypes.h>
+
+#include <daemon.h>
+#include <collections/array.h>
+
+typedef struct private_vici_control_t private_vici_control_t;
+
+/**
+ * Private data of an vici_control_t object.
+ */
+struct private_vici_control_t {
+
+ /**
+ * Public vici_control_t interface.
+ */
+ vici_control_t public;
+
+ /**
+ * Dispatcher
+ */
+ vici_dispatcher_t *dispatcher;
+};
+
+/**
+ * Log callback helper data
+ */
+typedef struct {
+ /** dispatcher to send log messages over */
+ vici_dispatcher_t *dispatcher;
+ /** connection ID to send messages to */
+ u_int id;
+ /** loglevel */
+ level_t level;
+ /** prevent recursive log */
+ u_int recursive;
+} log_info_t;
+
+/**
+ * Log using vici event messages
+ */
+static bool log_vici(log_info_t *info, debug_t group, level_t level,
+ ike_sa_t *ike_sa, char *text)
+{
+ if (level <= info->level)
+ {
+ if (info->recursive++ == 0)
+ {
+ vici_message_t *message;
+ vici_builder_t *builder;
+
+ builder = vici_builder_create();
+ builder->add_kv(builder, "group", "%N", debug_names, group);
+ builder->add_kv(builder, "level", "%d", level);
+ if (ike_sa)
+ {
+ builder->add_kv(builder, "ikesa-name", "%s",
+ ike_sa->get_name(ike_sa));
+ builder->add_kv(builder, "ikesa-uniqueid", "%u",
+ ike_sa->get_unique_id(ike_sa));
+ }
+ builder->add_kv(builder, "msg", "%s", text);
+
+ message = builder->finalize(builder);
+ if (message)
+ {
+ info->dispatcher->raise_event(info->dispatcher, "control-log",
+ info->id, message);
+ }
+ }
+ info->recursive--;
+ }
+ return TRUE;
+}
+
+/**
+ * Send a (error) reply message
+ */
+static vici_message_t* send_reply(private_vici_control_t *this, char *fmt, ...)
+{
+ vici_builder_t *builder;
+ va_list args;
+
+ builder = vici_builder_create();
+ builder->add_kv(builder, "success", fmt ? "no" : "yes");
+ if (fmt)
+ {
+ va_start(args, fmt);
+ builder->vadd_kv(builder, "errmsg", fmt, args);
+ va_end(args);
+ }
+ return builder->finalize(builder);
+}
+
+/**
+ * Get the child_cfg having name from peer_cfg
+ */
+static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name)
+{
+ child_cfg_t *current, *found = NULL;
+ enumerator_t *enumerator;
+
+ enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (streq(current->get_name(current), name))
+ {
+ found = current;
+ found->get_ref(found);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+/**
+ * Find a peer/child config from a child config name
+ */
+static child_cfg_t* find_child_cfg(char *name, peer_cfg_t **out)
+{
+ enumerator_t *enumerator;
+ peer_cfg_t *peer_cfg;
+ child_cfg_t *child_cfg;
+
+ enumerator = charon->backends->create_peer_cfg_enumerator(
+ charon->backends, NULL, NULL, NULL, NULL, IKE_ANY);
+ while (enumerator->enumerate(enumerator, &peer_cfg))
+ {
+ child_cfg = get_child_from_peer(peer_cfg, name);
+ if (child_cfg)
+ {
+ *out = peer_cfg->get_ref(peer_cfg);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return child_cfg;
+}
+
+CALLBACK(initiate, vici_message_t*,
+ private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
+{
+ child_cfg_t *child_cfg = NULL;
+ peer_cfg_t *peer_cfg;
+ char *child;
+ u_int timeout;
+ log_info_t log = {
+ .dispatcher = this->dispatcher,
+ .id = id,
+ };
+
+ child = request->get_str(request, NULL, "child");
+ timeout = request->get_int(request, 0, "timeout");
+ log.level = request->get_int(request, 1, "loglevel");
+
+ if (!child)
+ {
+ return send_reply(this, "missing configuration name");
+ }
+
+ DBG1(DBG_CFG, "vici initiate '%s'", child);
+
+ child_cfg = find_child_cfg(child, &peer_cfg);
+ if (!child_cfg)
+ {
+ return send_reply(this, "CHILD_SA config '%s' not found", child);
+ }
+ switch (charon->controller->initiate(charon->controller,
+ peer_cfg, child_cfg, (controller_cb_t)log_vici, &log, timeout))
+ {
+ case SUCCESS:
+ return send_reply(this, NULL);
+ case OUT_OF_RES:
+ return send_reply(this, "CHILD_SA '%s' not established after %dms",
+ child, timeout);
+ case FAILED:
+ default:
+ return send_reply(this, "establishing CHILD_SA '%s' failed", child);
+ }
+}
+
+CALLBACK(terminate, vici_message_t*,
+ private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
+{
+ enumerator_t *enumerator, *isas, *csas;
+ char *child, *ike, *errmsg = NULL;
+ u_int timeout, child_id, ike_id, current, *del, done = 0;
+ ike_sa_t *ike_sa;
+ child_sa_t *child_sa;
+ array_t *ids;
+ vici_builder_t *builder;
+ log_info_t log = {
+ .dispatcher = this->dispatcher,
+ .id = id,
+ };
+
+ child = request->get_str(request, NULL, "child");
+ ike = request->get_str(request, NULL, "ike");
+ child_id = request->get_int(request, 0, "child-id");
+ ike_id = request->get_int(request, 0, "ike-id");
+ timeout = request->get_int(request, 0, "timeout");
+ log.level = request->get_int(request, 1, "loglevel");
+
+ if (!child && !ike && !ike_id && !child_id)
+ {
+ return send_reply(this, "missing terminate selector");
+ }
+
+ if (ike_id)
+ {
+ DBG1(DBG_CFG, "vici terminate IKE_SA #%d", ike_id);
+ }
+ if (child_id)
+ {
+ DBG1(DBG_CFG, "vici terminate CHILD_SA #%d", child_id);
+ }
+ if (ike)
+ {
+ DBG1(DBG_CFG, "vici terminate IKE_SA '%s'", ike);
+ }
+ if (child)
+ {
+ DBG1(DBG_CFG, "vici terminate CHILD_SA '%s'", child);
+ }
+
+ ids = array_create(sizeof(u_int), 0);
+
+ isas = charon->controller->create_ike_sa_enumerator(charon->controller, TRUE);
+ while (isas->enumerate(isas, &ike_sa))
+ {
+ if (child || child_id)
+ {
+ if (ike && !streq(ike, ike_sa->get_name(ike_sa)))
+ {
+ continue;
+ }
+ if (ike_id && ike_id != ike_sa->get_unique_id(ike_sa))
+ {
+ continue;
+ }
+ csas = ike_sa->create_child_sa_enumerator(ike_sa);
+ while (csas->enumerate(csas, &child_sa))
+ {
+ if (child && !streq(child, child_sa->get_name(child_sa)))
+ {
+ continue;
+ }
+ if (child_id && child_sa->get_reqid(child_sa) != child_id)
+ {
+ continue;
+ }
+ current = child_sa->get_reqid(child_sa);
+ array_insert(ids, ARRAY_TAIL, &current);
+ }
+ csas->destroy(csas);
+ }
+ else if (ike && streq(ike, ike_sa->get_name(ike_sa)))
+ {
+ current = ike_sa->get_unique_id(ike_sa);
+ array_insert(ids, ARRAY_TAIL, &current);
+ }
+ else if (ike_id && ike_id == ike_sa->get_unique_id(ike_sa))
+ {
+ array_insert(ids, ARRAY_TAIL, &ike_id);
+ }
+ }
+ isas->destroy(isas);
+
+ enumerator = array_create_enumerator(ids);
+ while (enumerator->enumerate(enumerator, &del))
+ {
+ if (child || child_id)
+ {
+ if (charon->controller->terminate_child(charon->controller, *del,
+ (controller_cb_t)log_vici, &log, timeout) == SUCCESS)
+ {
+ done++;
+ }
+ }
+ else
+ {
+ if (charon->controller->terminate_ike(charon->controller, *del,
+ (controller_cb_t)log_vici, &log, timeout) == SUCCESS)
+ {
+ done++;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ builder = vici_builder_create();
+ if (array_count(ids) == 0)
+ {
+ errmsg = "no matching SAs to terminate found";
+ }
+ else if (done < array_count(ids))
+ {
+ if (array_count(ids) == 1)
+ {
+ errmsg = "terminating SA failed";
+ }
+ else
+ {
+ errmsg = "not all matching SAs could be terminated";
+ }
+ }
+ builder->add_kv(builder, "success", errmsg ? "no" : "yes");
+ builder->add_kv(builder, "matches", "%u", array_count(ids));
+ builder->add_kv(builder, "terminated", "%u", done);
+ if (errmsg)
+ {
+ builder->add_kv(builder, "errmsg", "%s", errmsg);
+ }
+ array_destroy(ids);
+ return builder->finalize(builder);
+}
+
+/**
+ * Find reqid of an existing CHILD_SA
+ */
+static u_int32_t find_reqid(child_cfg_t *cfg)
+{
+ enumerator_t *enumerator, *children;
+ child_sa_t *child_sa;
+ ike_sa_t *ike_sa;
+ u_int32_t reqid;
+
+ reqid = charon->traps->find_reqid(charon->traps, cfg);
+ if (reqid)
+ { /* already trapped */
+ return reqid;
+ }
+
+ enumerator = charon->controller->create_ike_sa_enumerator(
+ charon->controller, TRUE);
+ while (!reqid && enumerator->enumerate(enumerator, &ike_sa))
+ {
+ children = ike_sa->create_child_sa_enumerator(ike_sa);
+ while (children->enumerate(children, &child_sa))
+ {
+ if (streq(cfg->get_name(cfg), child_sa->get_name(child_sa)))
+ {
+ reqid = child_sa->get_reqid(child_sa);
+ break;
+ }
+ }
+ children->destroy(children);
+ }
+ enumerator->destroy(enumerator);
+ return reqid;
+}
+
+CALLBACK(install, vici_message_t*,
+ private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
+{
+ child_cfg_t *child_cfg = NULL;
+ peer_cfg_t *peer_cfg;
+ char *child;
+ bool ok;
+
+ child = request->get_str(request, NULL, "child");
+ if (!child)
+ {
+ return send_reply(this, "missing configuration name");
+ }
+
+ DBG1(DBG_CFG, "vici install '%s'", child);
+
+ child_cfg = find_child_cfg(child, &peer_cfg);
+ if (!child_cfg)
+ {
+ return send_reply(this, "configuration name not found");
+ }
+ switch (child_cfg->get_mode(child_cfg))
+ {
+ case MODE_PASS:
+ case MODE_DROP:
+ ok = charon->shunts->install(charon->shunts, child_cfg);
+ break;
+ default:
+ ok = charon->traps->install(charon->traps, peer_cfg, child_cfg,
+ find_reqid(child_cfg));
+ break;
+ }
+ peer_cfg->destroy(peer_cfg);
+ child_cfg->destroy(child_cfg);
+
+ return send_reply(this, ok ? NULL : "installing policy '%s' failed", child);
+}
+
+CALLBACK(uninstall, vici_message_t*,
+ private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
+{
+ child_sa_t *child_sa;
+ enumerator_t *enumerator;
+ u_int32_t reqid = 0;
+ char *child;
+
+ child = request->get_str(request, NULL, "child");
+ if (!child)
+ {
+ return send_reply(this, "missing configuration name");
+ }
+
+ DBG1(DBG_CFG, "vici uninstall '%s'", child);
+
+ if (charon->shunts->uninstall(charon->shunts, child))
+ {
+ return send_reply(this, NULL);
+ }
+
+ enumerator = charon->traps->create_enumerator(charon->traps);
+ while (enumerator->enumerate(enumerator, NULL, &child_sa))
+ {
+ if (streq(child, child_sa->get_name(child_sa)))
+ {
+ reqid = child_sa->get_reqid(child_sa);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (reqid)
+ {
+ if (charon->traps->uninstall(charon->traps, reqid))
+ {
+ return send_reply(this, NULL);
+ }
+ return send_reply(this, "uninstalling policy '%s' failed", child);
+ }
+ return send_reply(this, "policy '%s' not found", child);
+}
+
+static void manage_command(private_vici_control_t *this,
+ char *name, vici_command_cb_t cb, bool reg)
+{
+ this->dispatcher->manage_command(this->dispatcher, name,
+ reg ? cb : NULL, this);
+}
+
+/**
+ * (Un-)register dispatcher functions
+ */
+static void manage_commands(private_vici_control_t *this, bool reg)
+{
+ manage_command(this, "initiate", initiate, reg);
+ manage_command(this, "terminate", terminate, reg);
+ manage_command(this, "install", install, reg);
+ manage_command(this, "uninstall", uninstall, reg);
+ this->dispatcher->manage_event(this->dispatcher, "control-log", reg);
+}
+
+METHOD(vici_control_t, destroy, void,
+ private_vici_control_t *this)
+{
+ manage_commands(this, FALSE);
+ free(this);
+}
+
+/**
+ * See header
+ */
+vici_control_t *vici_control_create(vici_dispatcher_t *dispatcher)
+{
+ private_vici_control_t *this;
+
+ INIT(this,
+ .public = {
+ .destroy = _destroy,
+ },
+ .dispatcher = dispatcher,
+ );
+
+ manage_commands(this, TRUE);
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/vici/vici_control.h b/src/libcharon/plugins/vici/vici_control.h
new file mode 100644
index 000000000..71a13a074
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_control.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup vici_control vici_control
+ * @{ @ingroup vici
+ */
+
+#include "vici_dispatcher.h"
+
+#ifndef VICI_CONTROL_H_
+#define VICI_CONTROL_H_
+
+typedef struct vici_control_t vici_control_t;
+
+/**
+ * Control helper, provides initiate/terminate and other commands.
+ */
+struct vici_control_t {
+
+ /**
+ * Destroy a vici_control_t.
+ */
+ void (*destroy)(vici_control_t *this);
+};
+
+/**
+ * Create a vici_control instance.
+ *
+ * @param dispatcher dispatcher to receive requests from
+ * @return query handler
+ */
+vici_control_t *vici_control_create(vici_dispatcher_t *dispatcher);
+
+#endif /** VICI_CONTROL_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_cred.c b/src/libcharon/plugins/vici/vici_cred.c
new file mode 100644
index 000000000..cc6434b62
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_cred.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "vici_cred.h"
+#include "vici_builder.h"
+
+#include <credentials/sets/mem_cred.h>
+#include <credentials/certificates/ac.h>
+#include <credentials/certificates/crl.h>
+#include <credentials/certificates/x509.h>
+
+typedef struct private_vici_cred_t private_vici_cred_t;
+
+/**
+ * Private data of an vici_cred_t object.
+ */
+struct private_vici_cred_t {
+
+ /**
+ * Public vici_cred_t interface.
+ */
+ vici_cred_t public;
+
+ /**
+ * Dispatcher
+ */
+ vici_dispatcher_t *dispatcher;
+
+ /**
+ * credentials
+ */
+ mem_cred_t *creds;
+};
+
+/**
+ * Create a (error) reply message
+ */
+static vici_message_t* create_reply(char *fmt, ...)
+{
+ vici_builder_t *builder;
+ va_list args;
+
+ builder = vici_builder_create();
+ builder->add_kv(builder, "success", fmt ? "no" : "yes");
+ if (fmt)
+ {
+ va_start(args, fmt);
+ builder->vadd_kv(builder, "errmsg", fmt, args);
+ va_end(args);
+ }
+ return builder->finalize(builder);
+}
+
+CALLBACK(load_cert, vici_message_t*,
+ private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
+{
+ certificate_type_t type;
+ x509_flag_t required_flags = 0, additional_flags = 0;
+ certificate_t *cert;
+ x509_t *x509;
+ chunk_t data;
+ char *str;
+
+ str = message->get_str(message, NULL, "type");
+ if (!str)
+ {
+ return create_reply("certificate type missing");
+ }
+ if (strcaseeq(str, "x509"))
+ {
+ type = CERT_X509;
+ }
+ else if (strcaseeq(str, "x509ca"))
+ {
+ type = CERT_X509;
+ required_flags = X509_CA;
+ }
+ else if (strcaseeq(str, "x509aa"))
+ {
+ type = CERT_X509;
+ additional_flags = X509_AA;
+ }
+ else if (strcaseeq(str, "x509crl"))
+ {
+ type = CERT_X509_CRL;
+ }
+ else if (strcaseeq(str, "x509ac"))
+ {
+ type = CERT_X509_AC;
+ }
+ else
+ {
+ return create_reply("invalid certificate type: %s", str);
+ }
+ data = message->get_value(message, chunk_empty, "data");
+ if (!data.len)
+ {
+ return create_reply("certificate data missing");
+ }
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, type,
+ BUILD_BLOB_PEM, data,
+ BUILD_X509_FLAG, additional_flags,
+ BUILD_END);
+ if (!cert)
+ {
+ return create_reply("parsing %N certificate failed",
+ certificate_type_names, type);
+ }
+ if (cert->get_type(cert) == CERT_X509)
+ {
+ x509 = (x509_t*)cert;
+
+ if ((required_flags & x509->get_flags(x509)) != required_flags)
+ {
+ cert->destroy(cert);
+ return create_reply("certificate misses required flag, rejected");
+ }
+ }
+
+ DBG1(DBG_CFG, "loaded certificate '%Y'", cert->get_subject(cert));
+
+ this->creds->add_cert(this->creds, TRUE, cert);
+
+ return create_reply(NULL);
+}
+
+CALLBACK(load_key, vici_message_t*,
+ private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
+{
+ key_type_t type;
+ private_key_t *key;
+ chunk_t data;
+ char *str;
+
+ str = message->get_str(message, NULL, "type");
+ if (!str)
+ {
+ return create_reply("key type missing");
+ }
+ if (strcaseeq(str, "any"))
+ {
+ type = KEY_ANY;
+ }
+ else if (strcaseeq(str, "rsa"))
+ {
+ type = KEY_RSA;
+ }
+ else if (strcaseeq(str, "ecdsa"))
+ {
+ type = KEY_ECDSA;
+ }
+ else
+ {
+ return create_reply("invalid key type: %s", str);
+ }
+ data = message->get_value(message, chunk_empty, "data");
+ if (!data.len)
+ {
+ return create_reply("key data missing");
+ }
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
+ BUILD_BLOB_PEM, data, BUILD_END);
+ if (!key)
+ {
+ return create_reply("parsing %N private key failed",
+ key_type_names, type);
+ }
+
+ DBG1(DBG_CFG, "loaded %N private key", key_type_names, type);
+
+ this->creds->add_key(this->creds, key);
+
+ return create_reply(NULL);
+}
+
+CALLBACK(shared_owners, bool,
+ linked_list_t *owners, vici_message_t *message, char *name, chunk_t value)
+{
+ if (streq(name, "owners"))
+ {
+ char buf[256];
+
+ if (!vici_stringify(value, buf, sizeof(buf)))
+ {
+ return FALSE;
+ }
+ owners->insert_last(owners, identification_create_from_string(buf));
+ }
+ return TRUE;
+}
+
+CALLBACK(load_shared, vici_message_t*,
+ private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
+{
+ shared_key_type_t type;
+ linked_list_t *owners;
+ chunk_t data;
+ char *str, buf[512] = "";
+ enumerator_t *enumerator;
+ identification_t *owner;
+ int len;
+
+ str = message->get_str(message, NULL, "type");
+ if (!str)
+ {
+ return create_reply("shared key type missing");
+ }
+ if (strcaseeq(str, "ike"))
+ {
+ type = SHARED_IKE;
+ }
+ else if (strcaseeq(str, "eap") || streq(str, "xauth"))
+ {
+ type = SHARED_EAP;
+ }
+ else
+ {
+ return create_reply("invalid shared key type: %s", str);
+ }
+ data = message->get_value(message, chunk_empty, "data");
+ if (!data.len)
+ {
+ return create_reply("shared key data missing");
+ }
+
+ owners = linked_list_create();
+ if (!message->parse(message, NULL, NULL, NULL, shared_owners, owners))
+ {
+ owners->destroy_offset(owners, offsetof(identification_t, destroy));
+ return create_reply("parsing shared key owners failed");
+ }
+ if (owners->get_count(owners) == 0)
+ {
+ owners->insert_last(owners, identification_create_from_string("%any"));
+ }
+
+ enumerator = owners->create_enumerator(owners);
+ while (enumerator->enumerate(enumerator, &owner))
+ {
+ len = strlen(buf);
+ if (len < sizeof(buf))
+ {
+ snprintf(buf + len, sizeof(buf) - len, "%s'%Y'",
+ len ? ", " : "", owner);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ DBG1(DBG_CFG, "loaded %N shared key for: %s",
+ shared_key_type_names, type, buf);
+
+ this->creds->add_shared_list(this->creds,
+ shared_key_create(type, chunk_clone(data)), owners);
+
+ return create_reply(NULL);
+}
+
+CALLBACK(clear_creds, vici_message_t*,
+ private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
+{
+ vici_builder_t *builder;
+
+ this->creds->clear(this->creds);
+ lib->credmgr->flush_cache(lib->credmgr, CERT_ANY);
+
+ builder = vici_builder_create();
+ return builder->finalize(builder);
+}
+
+static void manage_command(private_vici_cred_t *this,
+ char *name, vici_command_cb_t cb, bool reg)
+{
+ this->dispatcher->manage_command(this->dispatcher, name,
+ reg ? cb : NULL, this);
+}
+
+/**
+ * (Un-)register dispatcher functions
+ */
+static void manage_commands(private_vici_cred_t *this, bool reg)
+{
+ manage_command(this, "clear-creds", clear_creds, reg);
+ manage_command(this, "load-cert", load_cert, reg);
+ manage_command(this, "load-key", load_key, reg);
+ manage_command(this, "load-shared", load_shared, reg);
+}
+
+METHOD(vici_cred_t, destroy, void,
+ private_vici_cred_t *this)
+{
+ manage_commands(this, FALSE);
+
+ lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
+ this->creds->destroy(this->creds);
+ free(this);
+}
+
+/**
+ * See header
+ */
+vici_cred_t *vici_cred_create(vici_dispatcher_t *dispatcher)
+{
+ private_vici_cred_t *this;
+
+ INIT(this,
+ .public = {
+ .destroy = _destroy,
+ },
+ .dispatcher = dispatcher,
+ .creds = mem_cred_create(),
+ );
+
+ lib->credmgr->add_set(lib->credmgr, &this->creds->set);
+
+ manage_commands(this, TRUE);
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/vici/vici_cred.h b/src/libcharon/plugins/vici/vici_cred.h
new file mode 100644
index 000000000..e109a27da
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_cred.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup vici_cred vici_cred
+ * @{ @ingroup vici
+ */
+
+#ifndef VICI_CRED_H_
+#define VICI_CRED_H_
+
+#include "vici_dispatcher.h"
+
+typedef struct vici_cred_t vici_cred_t;
+
+/**
+ * In-memory credential backend, managed by VICI.
+ */
+struct vici_cred_t {
+
+ /**
+ * Destroy a vici_cred_t.
+ */
+ void (*destroy)(vici_cred_t *this);
+};
+
+/**
+ * Create a vici_cred instance.
+ *
+ * @param dispatcher dispatcher to receive requests from
+ * @return credential backend
+ */
+vici_cred_t *vici_cred_create(vici_dispatcher_t *dispatcher);
+
+#endif /** VICI_CRED_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_dispatcher.c b/src/libcharon/plugins/vici/vici_dispatcher.c
new file mode 100644
index 000000000..6db36fbe0
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_dispatcher.c
@@ -0,0 +1,524 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "vici_dispatcher.h"
+#include "vici_socket.h"
+
+#include <bio/bio_reader.h>
+#include <bio/bio_writer.h>
+#include <threading/mutex.h>
+#include <threading/condvar.h>
+#include <threading/thread.h>
+#include <collections/array.h>
+#include <collections/hashtable.h>
+
+typedef struct private_vici_dispatcher_t private_vici_dispatcher_t;
+
+/**
+ * Private data of an vici_dispatcher_t object.
+ */
+struct private_vici_dispatcher_t {
+
+ /**
+ * Public vici_dispatcher_t interface.
+ */
+ vici_dispatcher_t public;
+
+ /**
+ * Socket to send/receive messages
+ */
+ vici_socket_t *socket;
+
+ /**
+ * List of registered commands (char* => command_t*)
+ */
+ hashtable_t *cmds;
+
+ /**
+ * List of known events, and registered clients (char* => event_t*)
+ */
+ hashtable_t *events;
+
+ /**
+ * Mutex to lock hashtables
+ */
+ mutex_t *mutex;
+
+ /**
+ * Condvar to signal command termination
+ */
+ condvar_t *cond;
+};
+
+/**
+ * Registered command
+ */
+typedef struct {
+ /** command name */
+ char *name;
+ /** callback for command */
+ vici_command_cb_t cb;
+ /** user data to pass to callback */
+ void *user;
+ /** command currently in use? */
+ u_int uses;
+} command_t;
+
+/**
+ * Registered event
+ */
+typedef struct {
+ /** event name */
+ char *name;
+ /** registered clients, as u_int */
+ array_t *clients;
+ /** event currently in use? */
+ u_int uses;
+} event_t;
+
+/**
+ * Send a operation code, optionally with name and message
+ */
+static void send_op(private_vici_dispatcher_t *this, u_int id,
+ vici_operation_t op, char *name, vici_message_t *message)
+{
+ bio_writer_t *writer;
+ u_int len;
+
+ len = sizeof(u_int8_t);
+ if (name)
+ {
+ len += sizeof(u_int8_t) + strlen(name);
+ }
+ if (message)
+ {
+ len += message->get_encoding(message).len;
+ }
+ writer = bio_writer_create(len);
+ writer->write_uint8(writer, op);
+ if (name)
+ {
+ writer->write_data8(writer, chunk_from_str(name));
+ }
+ if (message)
+ {
+ writer->write_data(writer, message->get_encoding(message));
+ }
+ this->socket->send(this->socket, id, writer->extract_buf(writer));
+ writer->destroy(writer);
+}
+
+/**
+ * Register client for event
+ */
+static void register_event(private_vici_dispatcher_t *this, char *name,
+ u_int id)
+{
+ event_t *event;
+
+ this->mutex->lock(this->mutex);
+ while (TRUE)
+ {
+ event = this->events->get(this->events, name);
+ if (!event)
+ {
+ break;
+ }
+ if (!event->uses)
+ {
+ array_insert(event->clients, ARRAY_TAIL, &id);
+ break;
+ }
+ this->cond->wait(this->cond, this->mutex);
+ }
+ this->mutex->unlock(this->mutex);
+
+ if (event)
+ {
+ DBG2(DBG_CFG, "vici client %u registered for: %s", id, name);
+ send_op(this, id, VICI_EVENT_CONFIRM, NULL, NULL);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "vici client %u invalid registration: %s", id, name);
+ send_op(this, id, VICI_EVENT_UNKNOWN, NULL, NULL);
+ }
+}
+
+/**
+ * Unregister client for event
+ */
+static void unregister_event(private_vici_dispatcher_t *this, char *name,
+ u_int id)
+{
+ enumerator_t *enumerator;
+ event_t *event;
+ u_int *current;
+ bool found = FALSE;
+
+ this->mutex->lock(this->mutex);
+ while (TRUE)
+ {
+ event = this->events->get(this->events, name);
+ if (!event)
+ {
+ break;
+ }
+ if (!event->uses)
+ {
+ enumerator = array_create_enumerator(event->clients);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (*current == id)
+ {
+ array_remove_at(event->clients, enumerator);
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ break;
+ }
+ this->cond->wait(this->cond, this->mutex);
+ }
+ this->mutex->unlock(this->mutex);
+
+ DBG2(DBG_CFG, "vici client %u unregistered for: %s", id, name);
+
+ if (found)
+ {
+ send_op(this, id, VICI_EVENT_CONFIRM, NULL, NULL);
+ }
+ else
+ {
+ send_op(this, id, VICI_EVENT_UNKNOWN, NULL, NULL);
+ }
+}
+
+/**
+ * Data to release on thread cancellation
+ */
+typedef struct {
+ private_vici_dispatcher_t *this;
+ command_t *cmd;
+ vici_message_t *request;
+} release_data_t;
+
+/**
+ * Release command after execution/cancellation
+ */
+CALLBACK(release_command, void,
+ release_data_t *release)
+{
+ release->request->destroy(release->request);
+
+ release->this->mutex->lock(release->this->mutex);
+ if (--release->cmd->uses == 0)
+ {
+ release->this->cond->broadcast(release->this->cond);
+ }
+ release->this->mutex->unlock(release->this->mutex);
+
+ free(release);
+}
+
+/**
+ * Process a request message
+ */
+void process_request(private_vici_dispatcher_t *this, char *name, u_int id,
+ chunk_t data)
+{
+ vici_message_t *response = NULL;
+ release_data_t *release;
+ command_t *cmd;
+
+ this->mutex->lock(this->mutex);
+ cmd = this->cmds->get(this->cmds, name);
+ if (cmd)
+ {
+ cmd->uses++;
+ }
+ this->mutex->unlock(this->mutex);
+
+ if (cmd)
+ {
+ INIT(release,
+ .this = this,
+ .cmd = cmd,
+ );
+
+ DBG2(DBG_CFG, "vici client %u requests: %s", id, name);
+
+ thread_cleanup_push(release_command, release);
+
+ release->request = vici_message_create_from_data(data, FALSE);
+ response = release->cmd->cb(cmd->user, cmd->name, id, release->request);
+
+ thread_cleanup_pop(TRUE);
+
+ if (response)
+ {
+ send_op(this, id, VICI_CMD_RESPONSE, NULL, response);
+ response->destroy(response);
+ }
+ }
+ else
+ {
+ DBG1(DBG_CFG, "vici client %u invalid request: %s", id, name);
+ send_op(this, id, VICI_CMD_UNKNOWN, NULL, NULL);
+ }
+}
+
+CALLBACK(inbound, void,
+ private_vici_dispatcher_t *this, u_int id, chunk_t data)
+{
+ bio_reader_t *reader;
+ chunk_t chunk;
+ u_int8_t type;
+ char name[257];
+
+ reader = bio_reader_create(data);
+ if (reader->read_uint8(reader, &type))
+ {
+ switch (type)
+ {
+ case VICI_EVENT_REGISTER:
+ if (reader->read_data8(reader, &chunk) &&
+ vici_stringify(chunk, name, sizeof(name)))
+ {
+ register_event(this, name, id);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "invalid vici register message");
+ }
+ break;
+ case VICI_EVENT_UNREGISTER:
+ if (reader->read_data8(reader, &chunk) &&
+ vici_stringify(chunk, name, sizeof(name)))
+ {
+ unregister_event(this, name, id);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "invalid vici unregister message");
+ }
+ break;
+ case VICI_CMD_REQUEST:
+ if (reader->read_data8(reader, &chunk) &&
+ vici_stringify(chunk, name, sizeof(name)))
+ {
+ thread_cleanup_push((void*)reader->destroy, reader);
+ process_request(this, name, id, reader->peek(reader));
+ thread_cleanup_pop(FALSE);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "invalid vici request message");
+ }
+ break;
+ case VICI_CMD_RESPONSE:
+ case VICI_EVENT_CONFIRM:
+ case VICI_EVENT_UNKNOWN:
+ case VICI_EVENT:
+ default:
+ DBG1(DBG_CFG, "unsupported vici operation: %u", type);
+ break;
+ }
+ }
+ else
+ {
+ DBG1(DBG_CFG, "invalid vici message");
+ }
+ reader->destroy(reader);
+}
+
+CALLBACK(connect_, void,
+ private_vici_dispatcher_t *this, u_int id)
+{
+ DBG2(DBG_CFG, "vici client %u connected", id);
+}
+
+CALLBACK(disconnect, void,
+ private_vici_dispatcher_t *this, u_int id)
+{
+ enumerator_t *events, *ids;
+ event_t *event;
+ u_int *current;
+
+ /* deregister client from all events */
+ this->mutex->lock(this->mutex);
+ events = this->events->create_enumerator(this->events);
+ while (events->enumerate(events, NULL, &event))
+ {
+ while (event->uses)
+ {
+ this->cond->wait(this->cond, this->mutex);
+ }
+ ids = array_create_enumerator(event->clients);
+ while (ids->enumerate(ids, &current))
+ {
+ if (id == *current)
+ {
+ array_remove_at(event->clients, ids);
+ }
+ }
+ ids->destroy(ids);
+ }
+ events->destroy(events);
+ this->mutex->unlock(this->mutex);
+
+ DBG2(DBG_CFG, "vici client %u disconnected", id);
+}
+
+METHOD(vici_dispatcher_t, manage_command, void,
+ private_vici_dispatcher_t *this, char *name,
+ vici_command_cb_t cb, void *user)
+{
+ command_t *cmd;
+
+ this->mutex->lock(this->mutex);
+ if (cb)
+ {
+ INIT(cmd,
+ .name = strdup(name),
+ .cb = cb,
+ .user = user,
+ );
+ cmd = this->cmds->put(this->cmds, cmd->name, cmd);
+ }
+ else
+ {
+ cmd = this->cmds->remove(this->cmds, name);
+ }
+ if (cmd)
+ {
+ while (cmd->uses)
+ {
+ this->cond->wait(this->cond, this->mutex);
+ }
+ free(cmd->name);
+ free(cmd);
+ }
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(vici_dispatcher_t, manage_event, void,
+ private_vici_dispatcher_t *this, char *name, bool reg)
+{
+ event_t *event;
+
+ this->mutex->lock(this->mutex);
+ if (reg)
+ {
+ INIT(event,
+ .name = strdup(name),
+ .clients = array_create(sizeof(u_int), 0),
+ );
+ event = this->events->put(this->events, event->name, event);
+ }
+ else
+ {
+ event = this->events->remove(this->events, name);
+ }
+ if (event)
+ {
+ while (event->uses)
+ {
+ this->cond->wait(this->cond, this->mutex);
+ }
+ array_destroy(event->clients);
+ free(event->name);
+ free(event);
+ }
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(vici_dispatcher_t, raise_event, void,
+ private_vici_dispatcher_t *this, char *name, u_int id,
+ vici_message_t *message)
+{
+ enumerator_t *enumerator;
+ event_t *event;
+ u_int *current;
+
+ this->mutex->lock(this->mutex);
+ event = this->events->get(this->events, name);
+ if (event)
+ {
+ event->uses++;
+ this->mutex->unlock(this->mutex);
+
+ enumerator = array_create_enumerator(event->clients);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (id == 0 || id == *current)
+ {
+ send_op(this, *current, VICI_EVENT, name, message);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ this->mutex->lock(this->mutex);
+ if (--event->uses == 0)
+ {
+ this->cond->broadcast(this->cond);
+ }
+ }
+ this->mutex->unlock(this->mutex);
+
+ message->destroy(message);
+}
+
+METHOD(vici_dispatcher_t, destroy, void,
+ private_vici_dispatcher_t *this)
+{
+ DESTROY_IF(this->socket);
+ this->mutex->destroy(this->mutex);
+ this->cond->destroy(this->cond);
+ this->cmds->destroy(this->cmds);
+ this->events->destroy(this->events);
+ free(this);
+}
+
+/**
+ * See header
+ */
+vici_dispatcher_t *vici_dispatcher_create(char *uri)
+{
+ private_vici_dispatcher_t *this;
+
+ INIT(this,
+ .public = {
+ .manage_command = _manage_command,
+ .manage_event = _manage_event,
+ .raise_event = _raise_event,
+ .destroy = _destroy,
+ },
+ .cmds = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1),
+ .events = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .cond = condvar_create(CONDVAR_TYPE_DEFAULT),
+ );
+
+ this->socket = vici_socket_create(uri, inbound, connect_, disconnect, this);
+ if (!this->socket)
+ {
+ destroy(this);
+ return NULL;
+ }
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/vici/vici_dispatcher.h b/src/libcharon/plugins/vici/vici_dispatcher.h
new file mode 100644
index 000000000..2297a80bd
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_dispatcher.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup vici_dispatcher vici_dispatcher
+ * @{ @ingroup vici
+ */
+
+#ifndef VICI_DISPATCHER_H_
+#define VICI_DISPATCHER_H_
+
+#include "vici_message.h"
+
+typedef struct vici_dispatcher_t vici_dispatcher_t;
+typedef enum vici_operation_t vici_operation_t;
+
+/**
+ * Default socket URI of vici service
+ */
+#ifdef WIN32
+# define VICI_DEFAULT_URI "tcp://127.0.0.1:4502"
+#else
+# define VICI_DEFAULT_URI "unix://" IPSEC_PIDDIR "/charon.vici"
+#endif
+
+/**
+ * Kind of vici operation
+ */
+enum vici_operation_t {
+ /** a named request message */
+ VICI_CMD_REQUEST,
+ /** an unnamed response message to a request */
+ VICI_CMD_RESPONSE,
+ /** unnamed response if requested command is unknown */
+ VICI_CMD_UNKNOWN,
+ /** a named event registration request */
+ VICI_EVENT_REGISTER,
+ /** a named event unregistration request */
+ VICI_EVENT_UNREGISTER,
+ /** unnamed response for successful event (un-)registration */
+ VICI_EVENT_CONFIRM,
+ /** unnamed response if event (un-)registration failed */
+ VICI_EVENT_UNKNOWN,
+ /** a named event message */
+ VICI_EVENT,
+};
+
+/**
+ * Vici command callback function
+ *
+ * @param user user data, as supplied during registration
+ * @param name name of the command it has been registered under
+ * @param id client connection identifier
+ * @param request request message data
+ * @return response message
+ */
+typedef vici_message_t* (*vici_command_cb_t)(void *user, char *name, u_int id,
+ vici_message_t *request);
+
+/**
+ * Vici command dispatcher.
+ */
+struct vici_dispatcher_t {
+
+ /**
+ * Register/Unregister a callback invoked for a specific command request.
+ *
+ * @param name name of the command
+ * @param cb callback function to register, NULL to unregister
+ * @param user user data to pass to callback
+ */
+ void (*manage_command)(vici_dispatcher_t *this, char *name,
+ vici_command_cb_t cb, void *user);
+
+ /**
+ * Register/Unregister an event type to send.
+ *
+ * The dispatcher internally manages event subscriptions. Clients registered
+ * for an event will receive such messages when the event is raised.
+ *
+ * @param name event name to manager
+ * @param reg TRUE to register, FALSE to unregister
+ */
+ void (*manage_event)(vici_dispatcher_t *this, char *name, bool reg);
+
+ /**
+ * Raise an event to a specific or all clients registered to that event.
+ *
+ * @param name event name to raise
+ * @param id client connection ID, 0 for all
+ * @param message event message to send, gets destroyed
+ */
+ void (*raise_event)(vici_dispatcher_t *this, char *name, u_int id,
+ vici_message_t *message);
+
+ /**
+ * Destroy a vici_dispatcher_t.
+ */
+ void (*destroy)(vici_dispatcher_t *this);
+};
+
+/**
+ * Create a vici_dispatcher instance.
+ *
+ * @param uri uri for listening stream service
+ * @return dispatcher instance
+ */
+vici_dispatcher_t *vici_dispatcher_create(char *uri);
+
+#endif /** VICI_DISPATCHER_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_logger.c b/src/libcharon/plugins/vici/vici_logger.c
new file mode 100644
index 000000000..cffd65bad
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_logger.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "vici_logger.h"
+#include "vici_builder.h"
+
+#include <daemon.h>
+#include <threading/mutex.h>
+
+typedef struct private_vici_logger_t private_vici_logger_t;
+
+/**
+ * Private data of an vici_logger_t object.
+ */
+struct private_vici_logger_t {
+
+ /**
+ * Public vici_logger_t interface.
+ */
+ vici_logger_t public;
+
+ /**
+ * Dispatcher
+ */
+ vici_dispatcher_t *dispatcher;
+
+ /**
+ * Recursiveness avoidance counter
+ */
+ int recursive;
+
+ /**
+ * Mutex to synchronize logging
+ */
+ mutex_t *mutex;
+};
+
+METHOD(logger_t, log_, void,
+ private_vici_logger_t *this, debug_t group, level_t level, int thread,
+ ike_sa_t* ike_sa, const char *msg)
+{
+ this->mutex->lock(this->mutex);
+
+ /* avoid recursive invocations by the vici subsystem */
+ if (this->recursive++ == 0)
+ {
+ vici_message_t *message;
+ vici_builder_t *builder;
+
+ builder = vici_builder_create();
+ builder->add_kv(builder, "group", "%N", debug_names, group);
+ builder->add_kv(builder, "level", "%d", level);
+ builder->add_kv(builder, "thread", "%d", thread);
+ if (ike_sa)
+ {
+ builder->add_kv(builder, "ikesa-name", "%s",
+ ike_sa->get_name(ike_sa));
+ builder->add_kv(builder, "ikesa-uniqueid", "%u",
+ ike_sa->get_unique_id(ike_sa));
+ }
+ builder->add_kv(builder, "msg", "%s", msg);
+
+ message = builder->finalize(builder);
+ if (message)
+ {
+ this->dispatcher->raise_event(this->dispatcher, "log", 0, message);
+ }
+ }
+ this->recursive--;
+
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(logger_t, get_level, level_t,
+ private_vici_logger_t *this, debug_t group)
+{
+ return LEVEL_CTRL;
+}
+
+/**
+ * (Un-)register dispatcher functions/events
+ */
+static void manage_commands(private_vici_logger_t *this, bool reg)
+{
+ this->dispatcher->manage_event(this->dispatcher, "log", reg);
+}
+
+METHOD(vici_logger_t, destroy, void,
+ private_vici_logger_t *this)
+{
+ manage_commands(this, FALSE);
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/**
+ * See header
+ */
+vici_logger_t *vici_logger_create(vici_dispatcher_t *dispatcher)
+{
+ private_vici_logger_t *this;
+
+ INIT(this,
+ .public = {
+ .logger = {
+ .log = _log_,
+ .get_level = _get_level,
+ },
+ .destroy = _destroy,
+ },
+ .dispatcher = dispatcher,
+ .mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
+ );
+
+ manage_commands(this, TRUE);
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/vici/vici_logger.h b/src/libcharon/plugins/vici/vici_logger.h
new file mode 100644
index 000000000..7be1d60d4
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_logger.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup vici_logger vici_logger
+ * @{ @ingroup vici
+ */
+
+#ifndef VICI_LOGGER_H_
+#define VICI_LOGGER_H_
+
+#include "vici_dispatcher.h"
+
+#include <bus/listeners/logger.h>
+
+typedef struct vici_logger_t vici_logger_t;
+
+/**
+ * Generic debugging logger over vici.
+ */
+struct vici_logger_t {
+
+ /**
+ * Implements logger interface.
+ */
+ logger_t logger;
+
+ /**
+ * Destroy a vici_logger_t.
+ */
+ void (*destroy)(vici_logger_t *this);
+};
+
+/**
+ * Create a vici_logger instance.
+ *
+ * @param dispatcher dispatcher to receive requests from
+ * @return loggerential backend
+ */
+vici_logger_t *vici_logger_create(vici_dispatcher_t *dispatcher);
+
+#endif /** VICI_LOGGER_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_message.c b/src/libcharon/plugins/vici/vici_message.c
new file mode 100644
index 000000000..dcc175f67
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_message.c
@@ -0,0 +1,727 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "vici_message.h"
+#include "vici_builder.h"
+
+#include <bio/bio_reader.h>
+#include <bio/bio_writer.h>
+
+#include <errno.h>
+
+typedef struct private_vici_message_t private_vici_message_t;
+
+/**
+ * Private data of an vici_message_t object.
+ */
+struct private_vici_message_t {
+
+ /**
+ * Public vici_message_t interface.
+ */
+ vici_message_t public;
+
+ /**
+ * Message encoding
+ */
+ chunk_t encoding;
+
+ /**
+ * Free encoding during destruction?
+ */
+ bool cleanup;
+
+ /**
+ * Allocated strings we maintain for get_str()
+ */
+ linked_list_t *strings;
+};
+
+ENUM(vici_type_names, VICI_START, VICI_END,
+ "start",
+ "section-start",
+ "section-end",
+ "key-value",
+ "list-start",
+ "list-item",
+ "list-end",
+ "end"
+);
+
+/**
+ * See header.
+ */
+bool vici_stringify(chunk_t chunk, char *buf, size_t size)
+{
+ if (!chunk_printable(chunk, NULL, 0))
+ {
+ return FALSE;
+ }
+ snprintf(buf, size, "%.*s", (int)chunk.len, chunk.ptr);
+ return TRUE;
+}
+
+/**
+ * See header.
+ */
+bool vici_verify_type(vici_type_t type, u_int section, bool list)
+{
+ if (list)
+ {
+ if (type != VICI_LIST_END && type != VICI_LIST_ITEM)
+ {
+ DBG1(DBG_ENC, "'%N' within list", vici_type_names, type);
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (type == VICI_LIST_ITEM || type == VICI_LIST_END)
+ {
+ DBG1(DBG_ENC, "'%N' outside list", vici_type_names, type);
+ return FALSE;
+ }
+ }
+ if (type == VICI_SECTION_END && section == 0)
+ {
+ DBG1(DBG_ENC, "'%N' outside of section", vici_type_names, type);
+ return FALSE;
+ }
+ if (type == VICI_END)
+ {
+ if (section)
+ {
+ DBG1(DBG_ENC, "'%N' within section", vici_type_names, type);
+ return FALSE;
+ }
+ if (list)
+ {
+ DBG1(DBG_ENC, "'%N' within list", vici_type_names, type);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Enumerator parsing message
+ */
+typedef struct {
+ /* implements enumerator */
+ enumerator_t public;
+ /** reader to parse from */
+ bio_reader_t *reader;
+ /** section nesting level */
+ int section;
+ /** currently parsing list? */
+ bool list;
+ /** string currently enumerating */
+ char name[257];
+} parse_enumerator_t;
+
+METHOD(enumerator_t, parse_enumerate, bool,
+ parse_enumerator_t *this, vici_type_t *out, char **name, chunk_t *value)
+{
+ u_int8_t type;
+ chunk_t data;
+
+ if (!this->reader->remaining(this->reader) ||
+ !this->reader->read_uint8(this->reader, &type))
+ {
+ *out = VICI_END;
+ return TRUE;
+ }
+ if (!vici_verify_type(type, this->section, this->list))
+ {
+ return FALSE;
+ }
+
+ switch (type)
+ {
+ case VICI_SECTION_START:
+ if (!this->reader->read_data8(this->reader, &data) ||
+ !vici_stringify(data, this->name, sizeof(this->name)))
+ {
+ DBG1(DBG_ENC, "invalid '%N' encoding", vici_type_names, type);
+ return FALSE;
+ }
+ *name = this->name;
+ this->section++;
+ break;
+ case VICI_SECTION_END:
+ this->section--;
+ break;
+ case VICI_KEY_VALUE:
+ if (!this->reader->read_data8(this->reader, &data) ||
+ !vici_stringify(data, this->name, sizeof(this->name)) ||
+ !this->reader->read_data16(this->reader, value))
+ {
+ DBG1(DBG_ENC, "invalid '%N' encoding", vici_type_names, type);
+ return FALSE;
+ }
+ *name = this->name;
+ break;
+ case VICI_LIST_START:
+ if (!this->reader->read_data8(this->reader, &data) ||
+ !vici_stringify(data, this->name, sizeof(this->name)))
+ {
+ DBG1(DBG_ENC, "invalid '%N' encoding", vici_type_names, type);
+ return FALSE;
+ }
+ *name = this->name;
+ this->list = TRUE;
+ break;
+ case VICI_LIST_ITEM:
+ this->reader->read_data16(this->reader, value);
+ break;
+ case VICI_LIST_END:
+ this->list = FALSE;
+ break;
+ case VICI_END:
+ return TRUE;
+ default:
+ DBG1(DBG_ENC, "unknown encoding type: %u", type);
+ return FALSE;
+ }
+
+ *out = type;
+
+ return TRUE;
+}
+
+METHOD(enumerator_t, parse_destroy, void,
+ parse_enumerator_t *this)
+{
+ this->reader->destroy(this->reader);
+ free(this);
+}
+
+METHOD(vici_message_t, create_enumerator, enumerator_t*,
+ private_vici_message_t *this)
+{
+ parse_enumerator_t *enumerator;
+
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)_parse_enumerate,
+ .destroy = _parse_destroy,
+ },
+ .reader = bio_reader_create(this->encoding),
+ );
+
+ return &enumerator->public;
+}
+
+/**
+ * Find a value for given vararg key
+ */
+static bool find_value(private_vici_message_t *this, chunk_t *value,
+ char *fmt, va_list args)
+{
+ enumerator_t *enumerator;
+ char buf[128], *name, *key, *dot, *next;
+ int section = 0, keysection = 0;
+ bool found = FALSE;
+ chunk_t current;
+ vici_type_t type;
+
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ next = buf;
+
+ enumerator = create_enumerator(this);
+
+ /* descent into section */
+ while (TRUE)
+ {
+ dot = strchr(next, '.');
+ if (!dot)
+ {
+ key = next;
+ break;
+ }
+ *dot = '\0';
+ key = next;
+ next = dot + 1;
+ keysection++;
+
+ while (enumerator->enumerate(enumerator, &type, &name, &current))
+ {
+ switch (type)
+ {
+ case VICI_SECTION_START:
+ section++;
+ if (section == keysection && streq(name, key))
+ {
+ break;
+ }
+ continue;
+ case VICI_SECTION_END:
+ section--;
+ continue;
+ case VICI_END:
+ break;
+ default:
+ continue;
+ }
+ break;
+ }
+ }
+
+ /* find key/value in current section */
+ while (enumerator->enumerate(enumerator, &type, &name, &current))
+ {
+ switch (type)
+ {
+ case VICI_KEY_VALUE:
+ if (section == keysection && streq(key, name))
+ {
+ *value = current;
+ found = TRUE;
+ break;
+ }
+ continue;
+ case VICI_SECTION_START:
+ section++;
+ continue;
+ case VICI_SECTION_END:
+ section--;
+ continue;
+ case VICI_END:
+ break;
+ default:
+ continue;
+ }
+ break;
+ }
+
+ enumerator->destroy(enumerator);
+
+ return found;
+}
+
+METHOD(vici_message_t, vget_str, char*,
+ private_vici_message_t *this, char *def, char *fmt, va_list args)
+{
+ chunk_t value;
+ bool found;
+ char *str;
+
+ found = find_value(this, &value, fmt, args);
+ if (found)
+ {
+ if (chunk_printable(value, NULL, 0))
+ {
+ str = strndup(value.ptr, value.len);
+ /* keep a reference to string, so caller doesn't have to care */
+ this->strings->insert_last(this->strings, str);
+ return str;
+ }
+ }
+ return def;
+}
+
+METHOD(vici_message_t, get_str, char*,
+ private_vici_message_t *this, char *def, char *fmt, ...)
+{
+ va_list args;
+ char *str;
+
+ va_start(args, fmt);
+ str = vget_str(this, def, fmt, args);
+ va_end(args);
+ return str;
+}
+
+METHOD(vici_message_t, vget_int, int,
+ private_vici_message_t *this, int def, char *fmt, va_list args)
+{
+ chunk_t value;
+ bool found;
+ char buf[32], *pos;
+ int ret;
+
+ found = find_value(this, &value, fmt, args);
+ if (found)
+ {
+ if (chunk_printable(value, NULL, 0))
+ {
+ snprintf(buf, sizeof(buf), "%.*s", (int)value.len, value.ptr);
+ errno = 0;
+ ret = strtol(buf, &pos, 0);
+ if (errno == 0 && pos == buf + strlen(buf))
+ {
+ return ret;
+ }
+ }
+ }
+ return def;
+}
+
+METHOD(vici_message_t, get_int, int,
+ private_vici_message_t *this, int def, char *fmt, ...)
+{
+ va_list args;
+ int val;
+
+ va_start(args, fmt);
+ val = vget_int(this, def, fmt, args);
+ va_end(args);
+ return val;
+}
+
+METHOD(vici_message_t, vget_value, chunk_t,
+ private_vici_message_t *this, chunk_t def, char *fmt, va_list args)
+{
+ chunk_t value;
+ bool found;
+
+ found = find_value(this, &value, fmt, args);
+ if (found)
+ {
+ return value;
+ }
+ return def;
+}
+
+METHOD(vici_message_t, get_value, chunk_t,
+ private_vici_message_t *this, chunk_t def, char *fmt, ...)
+{
+ va_list args;
+ chunk_t value;
+
+ va_start(args, fmt);
+ value = vget_value(this, def, fmt, args);
+ va_end(args);
+ return value;
+}
+
+METHOD(vici_message_t, get_encoding, chunk_t,
+ private_vici_message_t *this)
+{
+ return this->encoding;
+}
+
+/**
+ * Private parse context data
+ */
+struct vici_parse_context_t {
+ /** current section nesting level */
+ int level;
+ /** parse enumerator */
+ enumerator_t *e;
+};
+
+METHOD(vici_message_t, parse, bool,
+ private_vici_message_t *this, vici_parse_context_t *ctx,
+ vici_section_cb_t section, vici_value_cb_t kv, vici_value_cb_t li,
+ void *user)
+{
+ vici_parse_context_t root = {};
+ char *name, *list = NULL;
+ vici_type_t type;
+ chunk_t value;
+ int base;
+ bool ok = TRUE;
+
+ if (!ctx)
+ {
+ ctx = &root;
+ root.e = create_enumerator(this);
+ }
+
+ base = ctx->level;
+
+ while (ok)
+ {
+ ok = ctx->e->enumerate(ctx->e, &type, &name, &value);
+ if (ok)
+ {
+ switch (type)
+ {
+ case VICI_START:
+ /* should never occur */
+ continue;
+ case VICI_KEY_VALUE:
+ if (ctx->level == base && kv)
+ {
+ name = strdup(name);
+ this->strings->insert_last(this->strings, name);
+ ok = kv(user, &this->public, name, value);
+ }
+ continue;
+ case VICI_LIST_START:
+ if (ctx->level == base)
+ {
+ list = strdup(name);
+ this->strings->insert_last(this->strings, list);
+ }
+ continue;
+ case VICI_LIST_ITEM:
+ if (list && li)
+ {
+ name = strdup(name);
+ this->strings->insert_last(this->strings, name);
+ ok = li(user, &this->public, list, value);
+ }
+ continue;
+ case VICI_LIST_END:
+ if (ctx->level == base)
+ {
+ list = NULL;
+ }
+ continue;
+ case VICI_SECTION_START:
+ if (ctx->level++ == base && section)
+ {
+ name = strdup(name);
+ this->strings->insert_last(this->strings, name);
+ ok = section(user, &this->public, ctx, name);
+ }
+ continue;
+ case VICI_SECTION_END:
+ if (ctx->level-- == base)
+ {
+ break;
+ }
+ continue;
+ case VICI_END:
+ break;
+ }
+ }
+ break;
+ }
+
+ if (ctx == &root)
+ {
+ root.e->destroy(root.e);
+ }
+ return ok;
+}
+
+METHOD(vici_message_t, dump, bool,
+ private_vici_message_t *this, char *label, bool pretty, FILE *out)
+{
+ enumerator_t *enumerator;
+ int ident = 0, delta;
+ vici_type_t type, last_type = VICI_START;
+ char *name, *term, *sep, *separ, *assign;
+ chunk_t value;
+
+ /* pretty print uses indentation on multiple lines */
+ if (pretty)
+ {
+ delta = 2;
+ term = "\n";
+ separ = "";
+ assign = " = ";
+ }
+ else
+ {
+ delta = 0;
+ term = "";
+ separ = " ";
+ assign = "=";
+ }
+
+ fprintf(out, "%s {%s", label, term);
+ ident += delta;
+
+ enumerator = create_enumerator(this);
+ while (enumerator->enumerate(enumerator, &type, &name, &value))
+ {
+ switch (type)
+ {
+ case VICI_START:
+ /* should never occur */
+ break;
+ case VICI_SECTION_START:
+ sep = (last_type != VICI_SECTION_START &&
+ last_type != VICI_START) ? separ : "";
+ fprintf(out, "%*s%s%s {%s", ident, "", sep, name, term);
+ ident += delta;
+ break;
+ case VICI_SECTION_END:
+ ident -= delta;
+ fprintf(out, "%*s}%s", ident, "", term);
+ break;
+ case VICI_KEY_VALUE:
+ sep = (last_type != VICI_SECTION_START &&
+ last_type != VICI_START) ? separ : "";
+ if (chunk_printable(value, NULL, ' '))
+ {
+ fprintf(out, "%*s%s%s%s%.*s%s", ident, "", sep, name,
+ assign, (int)value.len, value.ptr, term);
+ }
+ else
+ {
+ fprintf(out, "%*s%s%s%s0x%+#B%s", ident, "", sep, name,
+ assign, &value, term);
+ }
+ break;
+ case VICI_LIST_START:
+ sep = (last_type != VICI_SECTION_START &&
+ last_type != VICI_START) ? separ : "";
+ fprintf(out, "%*s%s%s%s[%s", ident, "", sep, name, assign, term);
+ ident += delta;
+ break;
+ case VICI_LIST_END:
+ ident -= delta;
+ fprintf(out, "%*s]%s", ident, "", term);
+ break;
+ case VICI_LIST_ITEM:
+ sep = (last_type != VICI_LIST_START) ? separ : "";
+ if (chunk_printable(value, NULL, ' '))
+ {
+ fprintf(out, "%*s%s%.*s%s", ident, "", sep,
+ (int)value.len, value.ptr, term);
+ }
+ else
+ {
+ fprintf(out, "%*s%s0x%+#B%s", ident, "", sep,
+ &value, term);
+ }
+ break;
+ case VICI_END:
+ fprintf(out, "}\n");
+ enumerator->destroy(enumerator);
+ return TRUE;
+ }
+ last_type = type;
+ }
+ enumerator->destroy(enumerator);
+ return FALSE;
+}
+
+METHOD(vici_message_t, destroy, void,
+ private_vici_message_t *this)
+{
+ if (this->cleanup)
+ {
+ chunk_clear(&this->encoding);
+ }
+ this->strings->destroy_function(this->strings, free);
+ free(this);
+}
+
+/**
+ * See header
+ */
+vici_message_t *vici_message_create_from_data(chunk_t data, bool cleanup)
+{
+ private_vici_message_t *this;
+
+ INIT(this,
+ .public = {
+ .create_enumerator = _create_enumerator,
+ .get_str = _get_str,
+ .vget_str = _vget_str,
+ .get_int = _get_int,
+ .vget_int = _vget_int,
+ .get_value = _get_value,
+ .vget_value = _vget_value,
+ .get_encoding = _get_encoding,
+ .parse = _parse,
+ .dump = _dump,
+ .destroy = _destroy,
+ },
+ .strings = linked_list_create(),
+ .encoding = data,
+ .cleanup = cleanup,
+ );
+
+ return &this->public;
+}
+
+/**
+ * See header
+ */
+vici_message_t *vici_message_create_from_enumerator(enumerator_t *enumerator)
+{
+ vici_builder_t *builder;
+ vici_type_t type;
+ char *name;
+ chunk_t value;
+
+ builder = vici_builder_create();
+ while (enumerator->enumerate(enumerator, &type, &name, &value))
+ {
+ switch (type)
+ {
+ case VICI_SECTION_START:
+ case VICI_LIST_START:
+ builder->add(builder, type, name);
+ continue;
+ case VICI_KEY_VALUE:
+ builder->add(builder, type, name, value);
+ continue;
+ case VICI_LIST_ITEM:
+ builder->add(builder, type, value);
+ continue;
+ case VICI_SECTION_END:
+ case VICI_LIST_END:
+ default:
+ builder->add(builder, type);
+ continue;
+ case VICI_END:
+ break;
+ }
+ break;
+ }
+ enumerator->destroy(enumerator);
+
+ return builder->finalize(builder);
+}
+
+/**
+ * See header
+ */
+vici_message_t *vici_message_create_from_args(vici_type_t type, ...)
+{
+ vici_builder_t *builder;
+ va_list args;
+ char *name;
+ chunk_t value;
+
+ builder = vici_builder_create();
+ va_start(args, type);
+ while (type != VICI_END)
+ {
+ switch (type)
+ {
+ case VICI_LIST_START:
+ case VICI_SECTION_START:
+ name = va_arg(args, char*);
+ builder->add(builder, type, name);
+ break;
+ case VICI_KEY_VALUE:
+ name = va_arg(args, char*);
+ value = va_arg(args, chunk_t);
+ builder->add(builder, type, name, value);
+ break;
+ case VICI_LIST_ITEM:
+ value = va_arg(args, chunk_t);
+ builder->add(builder, type, value);
+ break;
+ case VICI_SECTION_END:
+ case VICI_LIST_END:
+ default:
+ builder->add(builder, type);
+ break;
+ }
+ type = va_arg(args, vici_type_t);
+ }
+ va_end(args);
+ return builder->finalize(builder);
+}
diff --git a/src/libcharon/plugins/vici/vici_message.h b/src/libcharon/plugins/vici/vici_message.h
new file mode 100644
index 000000000..1a89cf829
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_message.h
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup vici_message vici_message
+ * @{ @ingroup vici_dispatcher
+ */
+
+#ifndef VICI_MESSAGE_H_
+#define VICI_MESSAGE_H_
+
+#include <library.h>
+
+typedef struct vici_message_t vici_message_t;
+typedef struct vici_parse_context_t vici_parse_context_t;
+typedef enum vici_type_t vici_type_t;
+
+/**
+ * Vici message encoding types
+ */
+enum vici_type_t {
+ /** never used in an argument list, needed by dump as initial value */
+ VICI_START = 0,
+
+ /** begin of new section, argument is section name as char* */
+ VICI_SECTION_START = 1,
+ /** end of current section, no arguments */
+ VICI_SECTION_END = 2,
+ /** key/value, arguments are key as char*, value as chunk_t */
+ VICI_KEY_VALUE = 3,
+ /** list start, argument is list name as char* */
+ VICI_LIST_START = 4,
+ /** list item, argument is item value as chunk_t */
+ VICI_LIST_ITEM = 5,
+ /** end of list, no arguments */
+ VICI_LIST_END = 6,
+
+ /** end of argument list, no arguments (never encoded) */
+ VICI_END = 7
+};
+
+/**
+ * Callback function for key/value and list items, invoked by parse().
+ *
+ * @param user user data, as passed to parse()
+ * @param message message currently parsing
+ * @param name name of key or list
+ * @param value parsed value
+ * @return TRUE if parsed successfully
+ */
+typedef bool (*vici_value_cb_t)(void *user, vici_message_t *message,
+ char *name, chunk_t value);
+
+/**
+ * Callback function for sections, invoked by parse().
+ *
+ * @param user user data, as passed to parse()
+ * @param message message currently parsing
+ * @param ctx parse context, to pass to recursive parse() invocations.
+ * @param name name of the section
+ * @return TRUE if parsed successfully
+ */
+typedef bool (*vici_section_cb_t)(void *user, vici_message_t *message,
+ vici_parse_context_t *ctx, char *name);
+
+/**
+ * Names for vici encoding types
+ */
+extern enum_name_t *vici_type_names;
+
+/**
+ * Vici message representation, encoding/decoding routines.
+ */
+struct vici_message_t {
+
+ /**
+ * Create an enumerator over message contents.
+ *
+ * The enumerator takes a fixed list of arguments, but depending on the
+ * type may set not all of them. It returns VICI_END as last argument
+ * to indicate the message end, and returns FALSE if parsing the message
+ * failed.
+ *
+ * @return enumerator over (vici_type_t, char*, chunk_t)
+ */
+ enumerator_t* (*create_enumerator)(vici_message_t *this);
+
+ /**
+ * Get the value of a key/value pair as a string.
+ *
+ * @param def default value if not found
+ * @param fmt printf style format string for key, with sections
+ * @param ... arguments to fmt string
+ * @return string
+ */
+ char* (*get_str)(vici_message_t *this, char *def, char *fmt, ...);
+
+ /**
+ * Get the value of a key/value pair as a string, va_list variant.
+ *
+ * @param def default value if not found
+ * @param fmt printf style format string for key, with sections
+ * @param args arguments to fmt string
+ * @return string
+ */
+ char* (*vget_str)(vici_message_t *this, char *def, char *fmt, va_list args);
+
+ /**
+ * Get the value of a key/value pair as integer.
+ *
+ * @param def default value if not found
+ * @param fmt printf style format string for key, with sections
+ * @param ... arguments to fmt string
+ * @return value
+ */
+ int (*get_int)(vici_message_t *this, int def, char *fmt, ...);
+
+ /**
+ * Get the value of a key/value pair as integer, va_list variant
+ *
+ * @param def default value if not found
+ * @param fmt printf style format string for key, with sections
+ * @param args arguments to fmt string
+ * @return value
+ */
+ int (*vget_int)(vici_message_t *this, int def, char *fmt, va_list args);
+
+ /**
+ * Get the raw value of a key/value pair.
+ *
+ * @param def default value if not found
+ * @param fmt printf style format string for key, with sections
+ * @param ... arguments to fmt string
+ * @return value
+ */
+ chunk_t (*get_value)(vici_message_t *this, chunk_t def, char *fmt, ...);
+
+ /**
+ * Get the raw value of a key/value pair, va_list variant.
+ *
+ * @param def default value if not found
+ * @param fmt printf style format string for key, with sections
+ * @param args arguments to fmt string
+ * @return value
+ */
+ chunk_t (*vget_value)(vici_message_t *this, chunk_t def,
+ char *fmt, va_list args);
+
+ /**
+ * Get encoded message.
+ *
+ * @return message data, points to internal data
+ */
+ chunk_t (*get_encoding)(vici_message_t *this);
+
+ /**
+ * Parse a message using callback functions.
+ *
+ * Any of the callbacks may be NULL to skip this kind of item. Callbacks are
+ * invoked for the current section level only. To descent into sections,
+ * call parse() from within a section callback using the provided parse
+ * context.
+ *
+ * @param ctx parse context, NULL for root level
+ * @param section callback invoked for each section
+ * @param kv callback invoked for key/value pairs
+ * @param li callback invoked for list items
+ * @param user user data to pass to callbacks
+ * @return TRUE if parsed successfully
+ */
+ bool (*parse)(vici_message_t *this, vici_parse_context_t *ctx,
+ vici_section_cb_t section, vici_value_cb_t kv,
+ vici_value_cb_t li, void *user);
+
+ /**
+ * Dump a message text representation to a FILE stream.
+ *
+ * @param label label to print for message
+ * @param pretty use pretty print with indentation
+ * @param out FILE stream to dump to
+ * @return TRUE if message valid
+ */
+ bool (*dump)(vici_message_t *this, char *label, bool pretty, FILE *out);
+
+ /**
+ * Destroy a vici_message_t.
+ */
+ void (*destroy)(vici_message_t *this);
+};
+
+/**
+ * Create a vici_message from encoded data.
+ *
+ * @param data message encoding
+ * @param cleanup TRUE to free data during
+ * @return message representation
+ */
+vici_message_t *vici_message_create_from_data(chunk_t data, bool cleanup);
+
+/**
+ * Create a vici_message from an enumerator.
+ *
+ * The enumerator uses the same signature as the enumerator returned
+ * by create_enumerator(), and gets destroyed by this function. It should
+ * return VICI_END to close the message, return FALSE to indicate a failure.
+ *
+ * @param enumerator enumerator over (vici_type_t, char*, chunk_t)
+ * @return message representation, NULL on error
+ */
+vici_message_t *vici_message_create_from_enumerator(enumerator_t *enumerator);
+
+/**
+ * Create vici message from a variable argument list.
+ *
+ * @param type first type beginning message
+ * @param ... vici_type_t and args, terminated by VICI_END
+ * @return message representation, NULL on error
+ */
+vici_message_t *vici_message_create_from_args(vici_type_t type, ...);
+
+/**
+ * Check if a chunk has a printable string, and print it to buf.
+ *
+ * @param chunk chunk containing potential string
+ * @param buf buffer to write string to
+ * @param size size of buf
+ * @return TRUE if printable and string written to buf
+ */
+bool vici_stringify(chunk_t chunk, char *buf, size_t size);
+
+/**
+ * Verify the occurrence of a given type for given section/list nesting
+ */
+bool vici_verify_type(vici_type_t type, u_int section, bool list);
+
+#endif /** VICI_MESSAGE_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_plugin.c b/src/libcharon/plugins/vici/vici_plugin.c
new file mode 100644
index 000000000..8881feca9
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_plugin.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "vici_plugin.h"
+#include "vici_dispatcher.h"
+#include "vici_query.h"
+#include "vici_control.h"
+#include "vici_cred.h"
+#include "vici_config.h"
+#include "vici_attribute.h"
+#include "vici_logger.h"
+
+#include <library.h>
+#include <hydra.h>
+#include <daemon.h>
+
+typedef struct private_vici_plugin_t private_vici_plugin_t;
+
+/**
+ * Private members of vici_plugin_t
+ */
+struct private_vici_plugin_t {
+
+ /**
+ * public functions
+ */
+ vici_plugin_t public;
+
+ /**
+ * Dispatcher, creating socket
+ */
+ vici_dispatcher_t *dispatcher;
+
+ /**
+ * Query commands
+ */
+ vici_query_t *query;
+
+ /**
+ * Control commands
+ */
+ vici_control_t *control;
+
+ /**
+ * Credential backend
+ */
+ vici_cred_t *cred;
+
+ /**
+ * Configuration backend
+ */
+ vici_config_t *config;
+
+ /**
+ * IKE attribute backend
+ */
+ vici_attribute_t *attrs;
+
+ /**
+ * Generic debug logger
+ */
+ vici_logger_t *logger;
+};
+
+METHOD(plugin_t, get_name, char*,
+ private_vici_plugin_t *this)
+{
+ return "vici";
+}
+
+/**
+ * Register vici plugin features
+ */
+static bool register_vici(private_vici_plugin_t *this,
+ plugin_feature_t *feature, bool reg, void *data)
+{
+ if (reg)
+ {
+ char *uri;
+
+ uri = lib->settings->get_str(lib->settings, "%s.plugins.vici.socket",
+ VICI_DEFAULT_URI, lib->ns);
+ this->dispatcher = vici_dispatcher_create(uri);
+ if (this->dispatcher)
+ {
+ this->query = vici_query_create(this->dispatcher);
+ this->control = vici_control_create(this->dispatcher);
+ this->cred = vici_cred_create(this->dispatcher);
+ this->config = vici_config_create(this->dispatcher);
+ this->attrs = vici_attribute_create(this->dispatcher);
+ this->logger = vici_logger_create(this->dispatcher);
+
+ charon->backends->add_backend(charon->backends,
+ &this->config->backend);
+ hydra->attributes->add_provider(hydra->attributes,
+ &this->attrs->provider);
+ charon->bus->add_logger(charon->bus, &this->logger->logger);
+ return TRUE;
+ }
+ return FALSE;
+ }
+ else
+ {
+ charon->bus->remove_logger(charon->bus, &this->logger->logger);
+ hydra->attributes->remove_provider(hydra->attributes,
+ &this->attrs->provider);
+ charon->backends->remove_backend(charon->backends,
+ &this->config->backend);
+
+ this->logger->destroy(this->logger);
+ this->attrs->destroy(this->attrs);
+ this->config->destroy(this->config);
+ this->cred->destroy(this->cred);
+ this->control->destroy(this->control);
+ this->query->destroy(this->query);
+ this->dispatcher->destroy(this->dispatcher);
+ }
+ return TRUE;
+}
+
+METHOD(plugin_t, get_features, int,
+ private_vici_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_CALLBACK((plugin_feature_callback_t)register_vici, NULL),
+ PLUGIN_PROVIDE(CUSTOM, "vici"),
+ };
+ *features = f;
+ return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+ private_vici_plugin_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *vici_plugin_create()
+{
+ private_vici_plugin_t *this;
+
+ INIT(this,
+ .public = {
+ .plugin = {
+ .get_name = _get_name,
+ .reload = (void*)return_false,
+ .get_features = _get_features,
+ .destroy = _destroy,
+ },
+ },
+ );
+
+ return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/vici/vici_plugin.h b/src/libcharon/plugins/vici/vici_plugin.h
new file mode 100644
index 000000000..b4c380200
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup vici vici
+ * @ingroup cplugins
+ *
+ * @defgroup vici_plugin vici_plugin
+ * @{ @ingroup vici
+ */
+
+#ifndef VICI_PLUGIN_H_
+#define VICI_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct vici_plugin_t vici_plugin_t;
+
+/**
+ * vici plugin, the "Versatile IKE Control Interface" interface.
+ */
+struct vici_plugin_t {
+
+ /**
+ * Implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** VICI_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_query.c b/src/libcharon/plugins/vici/vici_query.c
new file mode 100644
index 000000000..54833abde
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_query.c
@@ -0,0 +1,1039 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "vici_query.h"
+#include "vici_builder.h"
+
+#include <inttypes.h>
+#include <time.h>
+#ifndef WIN32
+#include <sys/utsname.h>
+#endif
+#ifdef HAVE_MALLINFO
+#include <malloc.h>
+#endif
+
+#include <daemon.h>
+
+typedef struct private_vici_query_t private_vici_query_t;
+
+/**
+ * Private data of an vici_query_t object.
+ */
+struct private_vici_query_t {
+
+ /**
+ * Public vici_query_t interface.
+ */
+ vici_query_t public;
+
+ /**
+ * Dispatcher
+ */
+ vici_dispatcher_t *dispatcher;
+
+ /**
+ * Daemon startup timestamp
+ */
+ time_t uptime;
+};
+
+/**
+ * List details of a CHILD_SA
+ */
+static void list_child(private_vici_query_t *this, vici_builder_t *b,
+ child_sa_t *child, time_t now)
+{
+ time_t t;
+ u_int64_t bytes, packets;
+ u_int16_t alg, ks;
+ proposal_t *proposal;
+ enumerator_t *enumerator;
+ traffic_selector_t *ts;
+
+ b->add_kv(b, "reqid", "%u", child->get_reqid(child));
+ b->add_kv(b, "state", "%N", child_sa_state_names, child->get_state(child));
+ b->add_kv(b, "mode", "%N", ipsec_mode_names, child->get_mode(child));
+ if (child->get_state(child) == CHILD_INSTALLED ||
+ child->get_state(child) == CHILD_REKEYING)
+ {
+ b->add_kv(b, "protocol", "%N", protocol_id_names,
+ child->get_protocol(child));
+ if (child->has_encap(child))
+ {
+ b->add_kv(b, "encap", "yes");
+ }
+ b->add_kv(b, "spi-in", "%.8x", ntohl(child->get_spi(child, TRUE)));
+ b->add_kv(b, "spi-out", "%.8x", ntohl(child->get_spi(child, FALSE)));
+
+ if (child->get_ipcomp(child) != IPCOMP_NONE)
+ {
+ b->add_kv(b, "cpi-in", "%.4x", ntohs(child->get_cpi(child, TRUE)));
+ b->add_kv(b, "cpi-out", "%.4x", ntohs(child->get_cpi(child, FALSE)));
+ }
+ proposal = child->get_proposal(child);
+ if (proposal)
+ {
+ if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
+ &alg, &ks) && alg != ENCR_UNDEFINED)
+ {
+ b->add_kv(b, "encr-alg", "%N", encryption_algorithm_names, alg);
+ if (ks)
+ {
+ b->add_kv(b, "encr-keysize", "%u", ks);
+ }
+ }
+ if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
+ &alg, &ks) && alg != ENCR_UNDEFINED)
+ {
+ b->add_kv(b, "integ-alg", "%N", integrity_algorithm_names, alg);
+ if (ks)
+ {
+ b->add_kv(b, "integ-keysize", "%u", ks);
+ }
+ }
+ if (proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION,
+ &alg, NULL))
+ {
+ b->add_kv(b, "prf-alg", "%N", pseudo_random_function_names, alg);
+ }
+ if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
+ &alg, NULL))
+ {
+ b->add_kv(b, "dh-group", "%N", diffie_hellman_group_names, alg);
+ }
+ if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
+ &alg, NULL) && alg == EXT_SEQ_NUMBERS)
+ {
+ b->add_kv(b, "esn", "1");
+ }
+ }
+
+ child->get_usestats(child, TRUE, &t, &bytes, &packets);
+ b->add_kv(b, "bytes-in", "%" PRIu64, bytes);
+ b->add_kv(b, "packets-in", "%" PRIu64, packets);
+ if (t)
+ {
+ b->add_kv(b, "use-in", "%"PRIu64, (u_int64_t)(now - t));
+ }
+
+ child->get_usestats(child, FALSE, &t, &bytes, &packets);
+ b->add_kv(b, "bytes-out", "%"PRIu64, bytes);
+ b->add_kv(b, "packets-out", "%"PRIu64, packets);
+ if (t)
+ {
+ b->add_kv(b, "use-out", "%"PRIu64, (u_int64_t)(now - t));
+ }
+
+ t = child->get_lifetime(child, FALSE);
+ if (t)
+ {
+ b->add_kv(b, "rekey-time", "%"PRId64, (int64_t)(t - now));
+ }
+ t = child->get_lifetime(child, TRUE);
+ if (t)
+ {
+ b->add_kv(b, "life-time", "%"PRId64, (int64_t)(t - now));
+ }
+ t = child->get_installtime(child);
+ b->add_kv(b, "install-time", "%"PRId64, (int64_t)(now - t));
+ }
+
+ b->begin_list(b, "local-ts");
+ enumerator = child->create_ts_enumerator(child, TRUE);
+ while (enumerator->enumerate(enumerator, &ts))
+ {
+ b->add_li(b, "%R", ts);
+ }
+ enumerator->destroy(enumerator);
+ b->end_list(b /* local-ts */);
+
+ b->begin_list(b, "remote-ts");
+ enumerator = child->create_ts_enumerator(child, FALSE);
+ while (enumerator->enumerate(enumerator, &ts))
+ {
+ b->add_li(b, "%R", ts);
+ }
+ enumerator->destroy(enumerator);
+ b->end_list(b /* remote-ts */);
+}
+
+/**
+ * List tasks in a specific queue
+ */
+static void list_task_queue(private_vici_query_t *this, vici_builder_t *b,
+ ike_sa_t *ike_sa, task_queue_t q, char *name)
+{
+ enumerator_t *enumerator;
+ bool has = FALSE;
+ task_t *task;
+
+ enumerator = ike_sa->create_task_enumerator(ike_sa, q);
+ while (enumerator->enumerate(enumerator, &task))
+ {
+ if (!has)
+ {
+ b->begin_list(b, name);
+ has = TRUE;
+ }
+ b->add_li(b, "%N", task_type_names, task->get_type(task));
+ }
+ enumerator->destroy(enumerator);
+ if (has)
+ {
+ b->end_list(b);
+ }
+}
+
+/**
+ * List details of an IKE_SA
+ */
+static void list_ike(private_vici_query_t *this, vici_builder_t *b,
+ ike_sa_t *ike_sa, time_t now)
+{
+ time_t t;
+ ike_sa_id_t *id;
+ identification_t *eap;
+ proposal_t *proposal;
+ u_int16_t alg, ks;
+
+ b->add_kv(b, "uniqueid", "%u", ike_sa->get_unique_id(ike_sa));
+ b->add_kv(b, "version", "%u", ike_sa->get_version(ike_sa));
+ b->add_kv(b, "state", "%N", ike_sa_state_names, ike_sa->get_state(ike_sa));
+
+ b->add_kv(b, "local-host", "%H", ike_sa->get_my_host(ike_sa));
+ b->add_kv(b, "local-id", "%Y", ike_sa->get_my_id(ike_sa));
+
+ b->add_kv(b, "remote-host", "%H", ike_sa->get_other_host(ike_sa));
+ b->add_kv(b, "remote-id", "%Y", ike_sa->get_other_id(ike_sa));
+
+ eap = ike_sa->get_other_eap_id(ike_sa);
+
+ if (!eap->equals(eap, ike_sa->get_other_id(ike_sa)))
+ {
+ if (ike_sa->get_version(ike_sa) == IKEV1)
+ {
+ b->add_kv(b, "remote-xauth-id", "%Y", eap);
+ }
+ else
+ {
+ b->add_kv(b, "remote-eap-id", "%Y", eap);
+ }
+ }
+
+ id = ike_sa->get_id(ike_sa);
+ if (id->is_initiator(id))
+ {
+ b->add_kv(b, "initiator", "yes");
+ }
+ b->add_kv(b, "initiator-spi", "%.16"PRIx64, id->get_initiator_spi(id));
+ b->add_kv(b, "responder-spi", "%.16"PRIx64, id->get_responder_spi(id));
+
+ proposal = ike_sa->get_proposal(ike_sa);
+ if (proposal)
+ {
+ if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &ks))
+ {
+ b->add_kv(b, "encr-alg", "%N", encryption_algorithm_names, alg);
+ if (ks)
+ {
+ b->add_kv(b, "encr-keysize", "%u", ks);
+ }
+ }
+ if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, &ks))
+ {
+ b->add_kv(b, "integ-alg", "%N", integrity_algorithm_names, alg);
+ if (ks)
+ {
+ b->add_kv(b, "integ-keysize", "%u", ks);
+ }
+ }
+ if (proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
+ {
+ b->add_kv(b, "prf-alg", "%N", pseudo_random_function_names, alg);
+ }
+ if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &alg, NULL))
+ {
+ b->add_kv(b, "dh-group", "%N", diffie_hellman_group_names, alg);
+ }
+ }
+
+ if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
+ {
+ t = ike_sa->get_statistic(ike_sa, STAT_ESTABLISHED);
+ b->add_kv(b, "established", "%"PRId64, (int64_t)(now - t));
+ t = ike_sa->get_statistic(ike_sa, STAT_REKEY);
+ if (t)
+ {
+ b->add_kv(b, "rekey-time", "%"PRId64, (int64_t)(t - now));
+ }
+ t = ike_sa->get_statistic(ike_sa, STAT_REAUTH);
+ if (t)
+ {
+ b->add_kv(b, "reauth-time", "%"PRId64, (int64_t)(t - now));
+ }
+ }
+
+ list_task_queue(this, b, ike_sa, TASK_QUEUE_QUEUED, "tasks-queued");
+ list_task_queue(this, b, ike_sa, TASK_QUEUE_ACTIVE, "tasks-active");
+ list_task_queue(this, b, ike_sa, TASK_QUEUE_PASSIVE, "tasks-passive");
+}
+
+CALLBACK(list_sas, vici_message_t*,
+ private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
+{
+ vici_builder_t *b;
+ enumerator_t *isas, *csas;
+ ike_sa_t *ike_sa;
+ child_sa_t *child_sa;
+ time_t now;
+ char *ike;
+ u_int ike_id;
+ bool bl;
+
+ bl = request->get_str(request, NULL, "noblock") == NULL;
+ ike = request->get_str(request, NULL, "ike");
+ ike_id = request->get_int(request, 0, "ike-id");
+
+ isas = charon->controller->create_ike_sa_enumerator(charon->controller, bl);
+ while (isas->enumerate(isas, &ike_sa))
+ {
+ if (ike && !streq(ike, ike_sa->get_name(ike_sa)))
+ {
+ continue;
+ }
+ if (ike_id && ike_id != ike_sa->get_unique_id(ike_sa))
+ {
+ continue;
+ }
+
+ now = time_monotonic(NULL);
+
+ b = vici_builder_create();
+ b->begin_section(b, ike_sa->get_name(ike_sa));
+
+ list_ike(this, b, ike_sa, now);
+
+ b->begin_section(b, "child-sas");
+ csas = ike_sa->create_child_sa_enumerator(ike_sa);
+ while (csas->enumerate(csas, &child_sa))
+ {
+ b->begin_section(b, child_sa->get_name(child_sa));
+ list_child(this, b, child_sa, now);
+ b->end_section(b);
+ }
+ csas->destroy(csas);
+ b->end_section(b /* child-sas */ );
+
+ b->end_section(b);
+
+ this->dispatcher->raise_event(this->dispatcher, "list-sa", id,
+ b->finalize(b));
+ }
+ isas->destroy(isas);
+
+ b = vici_builder_create();
+ return b->finalize(b);
+}
+
+/**
+ * Raise a list-policy event for given CHILD_SA
+ */
+static void raise_policy(private_vici_query_t *this, u_int id, child_sa_t *child)
+{
+ enumerator_t *enumerator;
+ traffic_selector_t *ts;
+ vici_builder_t *b;
+
+ b = vici_builder_create();
+ b->begin_section(b, child->get_name(child));
+
+ b->add_kv(b, "mode", "%N", ipsec_mode_names, child->get_mode(child));
+
+ b->begin_list(b, "local-ts");
+ enumerator = child->create_ts_enumerator(child, TRUE);
+ while (enumerator->enumerate(enumerator, &ts))
+ {
+ b->add_li(b, "%R", ts);
+ }
+ enumerator->destroy(enumerator);
+ b->end_list(b /* local-ts */);
+
+ b->begin_list(b, "remote-ts");
+ enumerator = child->create_ts_enumerator(child, FALSE);
+ while (enumerator->enumerate(enumerator, &ts))
+ {
+ b->add_li(b, "%R", ts);
+ }
+ enumerator->destroy(enumerator);
+ b->end_list(b /* remote-ts */);
+
+ b->end_section(b);
+
+ this->dispatcher->raise_event(this->dispatcher, "list-policy", id,
+ b->finalize(b));
+}
+
+/**
+ * Raise a list-policy event for given CHILD_SA config
+ */
+static void raise_policy_cfg(private_vici_query_t *this, u_int id,
+ child_cfg_t *cfg)
+{
+ enumerator_t *enumerator;
+ linked_list_t *list;
+ traffic_selector_t *ts;
+ vici_builder_t *b;
+
+ b = vici_builder_create();
+ b->begin_section(b, cfg->get_name(cfg));
+
+ b->add_kv(b, "mode", "%N", ipsec_mode_names, cfg->get_mode(cfg));
+
+ b->begin_list(b, "local-ts");
+ list = cfg->get_traffic_selectors(cfg, TRUE, NULL, NULL);
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &ts))
+ {
+ b->add_li(b, "%R", ts);
+ }
+ enumerator->destroy(enumerator);
+ list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
+ b->end_list(b /* local-ts */);
+
+ b->begin_list(b, "remote-ts");
+ list = cfg->get_traffic_selectors(cfg, FALSE, NULL, NULL);
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &ts))
+ {
+ b->add_li(b, "%R", ts);
+ }
+ enumerator->destroy(enumerator);
+ list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
+ b->end_list(b /* remote-ts */);
+
+ b->end_section(b);
+
+ this->dispatcher->raise_event(this->dispatcher, "list-policy", id,
+ b->finalize(b));
+}
+
+CALLBACK(list_policies, vici_message_t*,
+ private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
+{
+ enumerator_t *enumerator;
+ vici_builder_t *b;
+ child_sa_t *child_sa;
+ child_cfg_t *child_cfg;
+ bool drop, pass, trap;
+ char *child;
+
+ drop = request->get_str(request, NULL, "drop") != NULL;
+ pass = request->get_str(request, NULL, "pass") != NULL;
+ trap = request->get_str(request, NULL, "trap") != NULL;
+ child = request->get_str(request, NULL, "child");
+
+ if (trap)
+ {
+ enumerator = charon->traps->create_enumerator(charon->traps);
+ while (enumerator->enumerate(enumerator, NULL, &child_sa))
+ {
+ if (child && !streq(child, child_sa->get_name(child_sa)))
+ {
+ continue;
+ }
+ raise_policy(this, id, child_sa);
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ if (drop || pass)
+ {
+ enumerator = charon->shunts->create_enumerator(charon->shunts);
+ while (enumerator->enumerate(enumerator, &child_cfg))
+ {
+ if (child && !streq(child, child_cfg->get_name(child_cfg)))
+ {
+ continue;
+ }
+ switch (child_cfg->get_mode(child_cfg))
+ {
+ case MODE_DROP:
+ if (drop)
+ {
+ raise_policy_cfg(this, id, child_cfg);
+ }
+ break;
+ case MODE_PASS:
+ if (pass)
+ {
+ raise_policy_cfg(this, id, child_cfg);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ b = vici_builder_create();
+ return b->finalize(b);
+}
+
+/**
+ * Build sections for auth configs, local or remote
+ */
+static void build_auth_cfgs(peer_cfg_t *peer_cfg, bool local, vici_builder_t *b)
+{
+ enumerator_t *enumerator, *rules;
+ auth_rule_t rule;
+ auth_cfg_t *auth;
+ union {
+ uintptr_t u;
+ identification_t *id;
+ certificate_t *cert;
+ char *str;
+ } v;
+
+ enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
+ while (enumerator->enumerate(enumerator, &auth))
+ {
+ b->begin_section(b, local ? "local" : "remote");
+
+ rules = auth->create_enumerator(auth);
+ while (rules->enumerate(rules, &rule, &v))
+ {
+ switch (rule)
+ {
+ case AUTH_RULE_AUTH_CLASS:
+ b->add_kv(b, "class", "%N", auth_class_names, v.u);
+ break;
+ case AUTH_RULE_EAP_TYPE:
+ b->add_kv(b, "eap-type", "%N", eap_type_names, v.u);
+ break;
+ case AUTH_RULE_EAP_VENDOR:
+ b->add_kv(b, "eap-vendor", "%u", v.u);
+ break;
+ case AUTH_RULE_XAUTH_BACKEND:
+ b->add_kv(b, "xauth", "%s", v.str);
+ break;
+ case AUTH_RULE_CRL_VALIDATION:
+ b->add_kv(b, "revocation", "%N", cert_validation_names, v.u);
+ break;
+ case AUTH_RULE_IDENTITY:
+ b->add_kv(b, "id", "%Y", v.id);
+ break;
+ case AUTH_RULE_AAA_IDENTITY:
+ b->add_kv(b, "aaa_id", "%Y", v.id);
+ break;
+ case AUTH_RULE_EAP_IDENTITY:
+ b->add_kv(b, "eap_id", "%Y", v.id);
+ break;
+ case AUTH_RULE_XAUTH_IDENTITY:
+ b->add_kv(b, "xauth_id", "%Y", v.id);
+ break;
+ default:
+ break;
+ }
+ }
+ rules->destroy(rules);
+
+ b->begin_list(b, "groups");
+ rules = auth->create_enumerator(auth);
+ while (rules->enumerate(rules, &rule, &v))
+ {
+ if (rule == AUTH_RULE_GROUP)
+ {
+ b->add_li(b, "%Y", v.id);
+ }
+ }
+ rules->destroy(rules);
+ b->end_list(b);
+
+ b->begin_list(b, "certs");
+ rules = auth->create_enumerator(auth);
+ while (rules->enumerate(rules, &rule, &v))
+ {
+ if (rule == AUTH_RULE_SUBJECT_CERT)
+ {
+ b->add_li(b, "%Y", v.cert->get_subject(v.cert));
+ }
+ }
+ rules->destroy(rules);
+ b->end_list(b);
+
+ b->begin_list(b, "cacerts");
+ rules = auth->create_enumerator(auth);
+ while (rules->enumerate(rules, &rule, &v))
+ {
+ if (rule == AUTH_RULE_CA_CERT)
+ {
+ b->add_li(b, "%Y", v.cert->get_subject(v.cert));
+ }
+ }
+ rules->destroy(rules);
+ b->end_list(b);
+
+ b->end_section(b);
+ }
+ enumerator->destroy(enumerator);
+}
+
+CALLBACK(list_conns, vici_message_t*,
+ private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
+{
+ enumerator_t *enumerator, *tokens, *selectors, *children;
+ peer_cfg_t *peer_cfg;
+ ike_cfg_t *ike_cfg;
+ child_cfg_t *child_cfg;
+ char *ike, *str;
+ linked_list_t *list;
+ traffic_selector_t *ts;
+ vici_builder_t *b;
+
+ ike = request->get_str(request, NULL, "ike");
+
+ enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
+ NULL, NULL, NULL, NULL, IKE_ANY);
+ while (enumerator->enumerate(enumerator, &peer_cfg))
+ {
+ if (ike && !streq(ike, peer_cfg->get_name(peer_cfg)))
+ {
+ continue;
+ }
+
+ b = vici_builder_create();
+ b->begin_section(b, peer_cfg->get_name(peer_cfg));
+
+ ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
+
+ b->begin_list(b, "local_addrs");
+ str = ike_cfg->get_my_addr(ike_cfg);
+ tokens = enumerator_create_token(str, ",", " ");
+ while (tokens->enumerate(tokens, &str))
+ {
+ b->add_li(b, "%s", str);
+ }
+ tokens->destroy(tokens);
+ b->end_list(b);
+
+ b->begin_list(b, "remote_addrs");
+ str = ike_cfg->get_other_addr(ike_cfg);
+ tokens = enumerator_create_token(str, ",", " ");
+ while (tokens->enumerate(tokens, &str))
+ {
+ b->add_li(b, "%s", str);
+ }
+ tokens->destroy(tokens);
+ b->end_list(b);
+
+ b->add_kv(b, "version", "%N", ike_version_names,
+ peer_cfg->get_ike_version(peer_cfg));
+
+ build_auth_cfgs(peer_cfg, TRUE, b);
+ build_auth_cfgs(peer_cfg, FALSE, b);
+
+ b->begin_section(b, "children");
+
+ children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
+ while (children->enumerate(children, &child_cfg))
+ {
+ b->begin_section(b, child_cfg->get_name(child_cfg));
+
+ b->add_kv(b, "mode", "%N", ipsec_mode_names,
+ child_cfg->get_mode(child_cfg));
+
+ b->begin_list(b, "local-ts");
+ list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
+ selectors = list->create_enumerator(list);
+ while (selectors->enumerate(selectors, &ts))
+ {
+ b->add_li(b, "%R", ts);
+ }
+ selectors->destroy(selectors);
+ list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
+ b->end_list(b /* local-ts */);
+
+ b->begin_list(b, "remote-ts");
+ list = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
+ selectors = list->create_enumerator(list);
+ while (selectors->enumerate(selectors, &ts))
+ {
+ b->add_li(b, "%R", ts);
+ }
+ selectors->destroy(selectors);
+ list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
+ b->end_list(b /* remote-ts */);
+
+ b->end_section(b);
+ }
+ children->destroy(children);
+
+ b->end_section(b); /* children */
+
+ b->end_section(b); /* name */
+
+ this->dispatcher->raise_event(this->dispatcher, "list-conn", id,
+ b->finalize(b));
+ }
+ enumerator->destroy(enumerator);
+
+ b = vici_builder_create();
+ return b->finalize(b);
+}
+
+/**
+ * Do we have a private key for given certificate
+ */
+static bool has_privkey(private_vici_query_t *this, certificate_t *cert)
+{
+ private_key_t *private;
+ public_key_t *public;
+ identification_t *keyid;
+ chunk_t chunk;
+ bool found = FALSE;
+
+ public = cert->get_public_key(cert);
+ if (public)
+ {
+ if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &chunk))
+ {
+ keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
+ private = lib->credmgr->get_private(lib->credmgr,
+ public->get_type(public), keyid, NULL);
+ if (private)
+ {
+ found = TRUE;
+ private->destroy(private);
+ }
+ keyid->destroy(keyid);
+ }
+ public->destroy(public);
+ }
+ return found;
+}
+
+CALLBACK(list_certs, vici_message_t*,
+ private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
+{
+ enumerator_t *enumerator, *added;
+ linked_list_t *list;
+ certificate_t *cert, *current;
+ chunk_t encoding;
+ identification_t *subject = NULL;
+ int type;
+ vici_builder_t *b;
+ bool found;
+ char *str;
+
+ str = request->get_str(request, "ANY", "type");
+ if (!enum_from_name(certificate_type_names, str, &type))
+ {
+ b = vici_builder_create();
+ return b->finalize(b);
+ }
+ str = request->get_str(request, NULL, "subject");
+ if (str)
+ {
+ subject = identification_create_from_string(str);
+ }
+
+ list = linked_list_create();
+ enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
+ type, KEY_ANY, subject, FALSE);
+ while (enumerator->enumerate(enumerator, &cert))
+ {
+ found = FALSE;
+ added = list->create_enumerator(list);
+ while (added->enumerate(added, &current))
+ {
+ if (current->equals(current, cert))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ added->destroy(added);
+
+ if (!found && cert->get_encoding(cert, CERT_ASN1_DER, &encoding))
+ {
+ b = vici_builder_create();
+ b->add_kv(b, "type", "%N",
+ certificate_type_names, cert->get_type(cert));
+ if (has_privkey(this, cert))
+ {
+ b->add_kv(b, "has_privkey", "yes");
+ }
+ b->add(b, VICI_KEY_VALUE, "data", encoding);
+ free(encoding.ptr);
+
+ this->dispatcher->raise_event(this->dispatcher, "list-cert", id,
+ b->finalize(b));
+ list->insert_last(list, cert->get_ref(cert));
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ list->destroy_offset(list, offsetof(certificate_t, destroy));
+ DESTROY_IF(subject);
+
+ b = vici_builder_create();
+ return b->finalize(b);
+}
+
+CALLBACK(version, vici_message_t*,
+ private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
+{
+ vici_builder_t *b;
+
+ b = vici_builder_create();
+
+ b->add_kv(b, "daemon", "%s", lib->ns);
+ b->add_kv(b, "version", "%s", VERSION);
+
+#ifdef WIN32
+ {
+ OSVERSIONINFOEX osvie;
+
+ memset(&osvie, 0, sizeof(osvie));
+ osvie.dwOSVersionInfoSize = sizeof(osvie);
+
+ if (GetVersionEx((LPOSVERSIONINFO)&osvie))
+ {
+ b->add_kv(b, "sysname", "Windows %s",
+ osvie.wProductType == VER_NT_WORKSTATION ? "Client" : "Server");
+ b->add_kv(b, "release", "%d.%d.%d (SP %d.%d)",
+ osvie.dwMajorVersion, osvie.dwMinorVersion, osvie.dwBuildNumber,
+ osvie.wServicePackMajor, osvie.wServicePackMinor);
+ b->add_kv(b, "machine", "%s",
+#ifdef WIN64
+ "x86_64");
+#else
+ "x86");
+#endif /* !WIN64 */
+ }
+ }
+#else /* !WIN32 */
+ {
+ struct utsname utsname;
+
+ if (uname(&utsname) == 0)
+ {
+ b->add_kv(b, "sysname", "%s", utsname.sysname);
+ b->add_kv(b, "release", "%s", utsname.release);
+ b->add_kv(b, "machine", "%s", utsname.machine);
+ }
+ }
+#endif /* !WIN32 */
+ return b->finalize(b);
+}
+
+/**
+ * Callback function for memusage summary
+ */
+CALLBACK(sum_usage, void,
+ vici_builder_t *b, int count, size_t bytes, int whitelisted)
+{
+ b->begin_section(b, "mem");
+ b->add_kv(b, "total", "%zu", bytes);
+ b->add_kv(b, "allocs", "%d", count);
+ b->end_section(b);
+}
+
+CALLBACK(stats, vici_message_t*,
+ private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
+{
+ vici_builder_t *b;
+ enumerator_t *enumerator;
+ plugin_t *plugin;
+ time_t since, now;
+ int i;
+
+ b = vici_builder_create();
+
+ now = time_monotonic(NULL);
+ since = time(NULL) - (now - this->uptime);
+
+ b->begin_section(b, "uptime");
+ b->add_kv(b, "running", "%V", &now, &this->uptime);
+ b->add_kv(b, "since", "%T", &since, FALSE);
+ b->end_section(b);
+
+ b->begin_section(b, "workers");
+ b->add_kv(b, "total", "%d",
+ lib->processor->get_total_threads(lib->processor));
+ b->add_kv(b, "idle", "%d",
+ lib->processor->get_idle_threads(lib->processor));
+ b->begin_section(b, "active");
+ for (i = 0; i < JOB_PRIO_MAX; i++)
+ {
+ b->add_kv(b, enum_to_name(job_priority_names, i), "%d",
+ lib->processor->get_working_threads(lib->processor, i));
+ }
+ b->end_section(b);
+ b->end_section(b);
+
+ b->begin_section(b, "queues");
+ for (i = 0; i < JOB_PRIO_MAX; i++)
+ {
+ b->add_kv(b, enum_to_name(job_priority_names, i), "%d",
+ lib->processor->get_job_load(lib->processor, i));
+ }
+ b->end_section(b);
+
+ b->add_kv(b, "scheduled", "%d",
+ lib->scheduler->get_job_load(lib->scheduler));
+
+ b->begin_section(b, "ikesas");
+ b->add_kv(b, "total", "%u",
+ charon->ike_sa_manager->get_count(charon->ike_sa_manager));
+ b->add_kv(b, "half-open", "%u",
+ charon->ike_sa_manager->get_half_open_count(charon->ike_sa_manager,
+ NULL));
+ b->end_section(b);
+
+ b->begin_list(b, "plugins");
+ enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
+ while (enumerator->enumerate(enumerator, &plugin, NULL))
+ {
+ b->add_li(b, "%s", plugin->get_name(plugin));
+ }
+ enumerator->destroy(enumerator);
+ b->end_list(b);
+
+ if (lib->leak_detective)
+ {
+ lib->leak_detective->usage(lib->leak_detective, NULL, sum_usage, b);
+ }
+#ifdef WIN32
+ else
+ {
+ DWORD lasterr = ERROR_INVALID_HANDLE;
+ HANDLE heaps[32];
+ int i, count;
+ char buf[16];
+ size_t total = 0;
+ int allocs = 0;
+
+ b->begin_section(b, "mem");
+ count = GetProcessHeaps(countof(heaps), heaps);
+ for (i = 0; i < count; i++)
+ {
+ PROCESS_HEAP_ENTRY entry = {};
+ size_t heap_total = 0;
+ int heap_allocs = 0;
+
+ if (HeapLock(heaps[i]))
+ {
+ while (HeapWalk(heaps[i], &entry))
+ {
+ if (entry.wFlags & PROCESS_HEAP_ENTRY_BUSY)
+ {
+ heap_total += entry.cbData;
+ heap_allocs++;
+ }
+ }
+ lasterr = GetLastError();
+ HeapUnlock(heaps[i]);
+ }
+ if (lasterr != ERROR_NO_MORE_ITEMS)
+ {
+ break;
+ }
+ snprintf(buf, sizeof(buf), "heap-%d", i);
+ b->begin_section(b, buf);
+ b->add_kv(b, "total", "%zu", heap_total);
+ b->add_kv(b, "allocs", "%d", heap_allocs);
+ b->end_section(b);
+
+ total += heap_total;
+ allocs += heap_allocs;
+ }
+ if (lasterr == ERROR_NO_MORE_ITEMS)
+ {
+ b->add_kv(b, "total", "%zu", total);
+ b->add_kv(b, "allocs", "%d", allocs);
+ }
+ b->end_section(b);
+ }
+#endif
+
+#ifdef HAVE_MALLINFO
+ {
+ struct mallinfo mi = mallinfo();
+
+ b->begin_section(b, "mallinfo");
+ b->add_kv(b, "sbrk", "%d", mi.arena);
+ b->add_kv(b, "mmap", "%d", mi.hblkhd);
+ b->add_kv(b, "used", "%d", mi.uordblks);
+ b->add_kv(b, "free", "%d", mi.fordblks);
+ b->end_section(b);
+ }
+#endif /* HAVE_MALLINFO */
+
+ return b->finalize(b);
+}
+
+static void manage_command(private_vici_query_t *this,
+ char *name, vici_command_cb_t cb, bool reg)
+{
+ this->dispatcher->manage_command(this->dispatcher, name,
+ reg ? cb : NULL, this);
+}
+
+/**
+ * (Un-)register dispatcher functions
+ */
+static void manage_commands(private_vici_query_t *this, bool reg)
+{
+ this->dispatcher->manage_event(this->dispatcher, "list-sa", reg);
+ this->dispatcher->manage_event(this->dispatcher, "list-policy", reg);
+ this->dispatcher->manage_event(this->dispatcher, "list-conn", reg);
+ this->dispatcher->manage_event(this->dispatcher, "list-cert", reg);
+ manage_command(this, "list-sas", list_sas, reg);
+ manage_command(this, "list-policies", list_policies, reg);
+ manage_command(this, "list-conns", list_conns, reg);
+ manage_command(this, "list-certs", list_certs, reg);
+ manage_command(this, "version", version, reg);
+ manage_command(this, "stats", stats, reg);
+}
+
+METHOD(vici_query_t, destroy, void,
+ private_vici_query_t *this)
+{
+ manage_commands(this, FALSE);
+ free(this);
+}
+
+/**
+ * See header
+ */
+vici_query_t *vici_query_create(vici_dispatcher_t *dispatcher)
+{
+ private_vici_query_t *this;
+
+ INIT(this,
+ .public = {
+ .destroy = _destroy,
+ },
+ .dispatcher = dispatcher,
+ .uptime = time_monotonic(NULL),
+ );
+
+ manage_commands(this, TRUE);
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/vici/vici_query.h b/src/libcharon/plugins/vici/vici_query.h
new file mode 100644
index 000000000..da72b1411
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_query.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup vici_query vici_query
+ * @{ @ingroup vici
+ */
+
+#include "vici_dispatcher.h"
+
+#ifndef VICI_QUERY_H_
+#define VICI_QUERY_H_
+
+typedef struct vici_query_t vici_query_t;
+
+/**
+ * Query helper, provides various commands to query/list daemon info.
+ */
+struct vici_query_t {
+
+ /**
+ * Destroy a vici_query_t.
+ */
+ void (*destroy)(vici_query_t *this);
+};
+
+/**
+ * Create a vici_query instance.
+ *
+ * @param dispatcher dispatcher to receive requests from
+ * @return query handler
+ */
+vici_query_t *vici_query_create(vici_dispatcher_t *dispatcher);
+
+#endif /** VICI_QUERY_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_socket.c b/src/libcharon/plugins/vici/vici_socket.c
new file mode 100644
index 000000000..916772871
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_socket.c
@@ -0,0 +1,679 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "vici_socket.h"
+
+#include <threading/mutex.h>
+#include <threading/condvar.h>
+#include <threading/thread.h>
+#include <collections/array.h>
+#include <collections/linked_list.h>
+#include <processing/jobs/callback_job.h>
+
+#include <errno.h>
+#include <string.h>
+
+typedef struct private_vici_socket_t private_vici_socket_t;
+
+/**
+ * Private members of vici_socket_t
+ */
+struct private_vici_socket_t {
+
+ /**
+ * public functions
+ */
+ vici_socket_t public;
+
+ /**
+ * Inbound message callback
+ */
+ vici_inbound_cb_t inbound;
+
+ /**
+ * Client connect callback
+ */
+ vici_connect_cb_t connect;
+
+ /**
+ * Client disconnect callback
+ */
+ vici_disconnect_cb_t disconnect;
+
+ /**
+ * Next client connection identifier
+ */
+ u_int nextid;
+
+ /**
+ * User data for callbacks
+ */
+ void *user;
+
+ /**
+ * Service accepting vici connections
+ */
+ stream_service_t *service;
+
+ /**
+ * Client connections, as entry_t
+ */
+ linked_list_t *connections;
+
+ /**
+ * mutex for client connections
+ */
+ mutex_t *mutex;
+};
+
+/**
+ * Data to securely reference an entry
+ */
+typedef struct {
+ /* reference to socket instance */
+ private_vici_socket_t *this;
+ /** connection identifier of entry */
+ u_int id;
+} entry_selector_t;
+
+/**
+ * Partially processed message
+ */
+typedef struct {
+ /** bytes of length header sent/received */
+ u_char hdrlen;
+ /** bytes of length header */
+ char hdr[sizeof(u_int32_t)];
+ /** send/receive buffer on heap */
+ chunk_t buf;
+ /** bytes sent/received in buffer */
+ u_int32_t done;
+} msg_buf_t;
+
+/**
+ * Client connection entry
+ */
+typedef struct {
+ /** reference to socket */
+ private_vici_socket_t *this;
+ /** associated stream */
+ stream_t *stream;
+ /** queued messages to send, as msg_buf_t pointers */
+ array_t *out;
+ /** input message buffer */
+ msg_buf_t in;
+ /** queued input messages to process, as chunk_t */
+ array_t *queue;
+ /** do we have job processing input queue? */
+ bool has_processor;
+ /** client connection identifier */
+ u_int id;
+ /** any users reading over this connection? */
+ int readers;
+ /** any users writing over this connection? */
+ int writers;
+ /** condvar to wait for usage */
+ condvar_t *cond;
+} entry_t;
+
+/**
+ * Destroy an connection entry
+ */
+CALLBACK(destroy_entry, void,
+ entry_t *entry)
+{
+ msg_buf_t *out;
+ chunk_t chunk;
+
+ entry->stream->destroy(entry->stream);
+ entry->this->disconnect(entry->this->user, entry->id);
+ entry->cond->destroy(entry->cond);
+
+ while (array_remove(entry->out, ARRAY_TAIL, &out))
+ {
+ chunk_clear(&out->buf);
+ free(out);
+ }
+ array_destroy(entry->out);
+ while (array_remove(entry->queue, ARRAY_TAIL, &chunk))
+ {
+ chunk_clear(&chunk);
+ }
+ array_destroy(entry->queue);
+ chunk_clear(&entry->in.buf);
+ free(entry);
+}
+
+/**
+ * Find entry by stream (if given) or id, claim use
+ */
+static entry_t* find_entry(private_vici_socket_t *this, stream_t *stream,
+ u_int id, bool reader, bool writer)
+{
+ enumerator_t *enumerator;
+ entry_t *entry, *found = NULL;
+ bool candidate = TRUE;
+
+ this->mutex->lock(this->mutex);
+ while (candidate && !found)
+ {
+ candidate = FALSE;
+ enumerator = this->connections->create_enumerator(this->connections);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (stream)
+ {
+ if (entry->stream != stream)
+ {
+ continue;
+ }
+ }
+ else
+ {
+ if (entry->id != id)
+ {
+ continue;
+ }
+ }
+ candidate = TRUE;
+
+ if ((reader && entry->readers) ||
+ (writer && entry->writers))
+ {
+ entry->cond->wait(entry->cond, this->mutex);
+ break;
+ }
+ if (reader)
+ {
+ entry->readers++;
+ }
+ if (writer)
+ {
+ entry->writers++;
+ }
+ found = entry;
+ break;
+ }
+ enumerator->destroy(enumerator);
+ }
+ this->mutex->unlock(this->mutex);
+
+ return found;
+}
+
+/**
+ * Remove entry by id, claim use
+ */
+static entry_t* remove_entry(private_vici_socket_t *this, u_int id)
+{
+ enumerator_t *enumerator;
+ entry_t *entry, *found = NULL;
+ bool candidate = TRUE;
+
+ this->mutex->lock(this->mutex);
+ while (candidate && !found)
+ {
+ candidate = FALSE;
+ enumerator = this->connections->create_enumerator(this->connections);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->id == id)
+ {
+ candidate = TRUE;
+ if (entry->readers || entry->writers)
+ {
+ entry->cond->wait(entry->cond, this->mutex);
+ break;
+ }
+ this->connections->remove_at(this->connections, enumerator);
+ found = entry;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ this->mutex->unlock(this->mutex);
+
+ return found;
+}
+
+/**
+ * Release a claimed entry
+ */
+static void put_entry(private_vici_socket_t *this, entry_t *entry,
+ bool reader, bool writer)
+{
+ this->mutex->lock(this->mutex);
+ if (reader)
+ {
+ entry->readers--;
+ }
+ if (writer)
+ {
+ entry->writers--;
+ }
+ entry->cond->signal(entry->cond);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Asynchronous callback to disconnect client
+ */
+CALLBACK(disconnect_async, job_requeue_t,
+ entry_selector_t *sel)
+{
+ entry_t *entry;
+
+ entry = remove_entry(sel->this, sel->id);
+ if (entry)
+ {
+ destroy_entry(entry);
+ }
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Disconnect a connected client
+ */
+static void disconnect(private_vici_socket_t *this, u_int id)
+{
+ entry_selector_t *sel;
+
+ INIT(sel,
+ .this = this,
+ .id = id,
+ );
+
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create(disconnect_async, sel, free, NULL));
+}
+
+/**
+ * Write queued output data
+ */
+static bool do_write(private_vici_socket_t *this, entry_t *entry,
+ stream_t *stream)
+{
+ msg_buf_t *out;
+ ssize_t len;
+
+ while (array_get(entry->out, ARRAY_HEAD, &out))
+ {
+ /* write header */
+ while (out->hdrlen < sizeof(out->hdr))
+ {
+ len = stream->write(stream, out->hdr + out->hdrlen,
+ sizeof(out->hdr) - out->hdrlen, FALSE);
+ if (len == 0)
+ {
+ return FALSE;
+ }
+ if (len < 0)
+ {
+ if (errno == EWOULDBLOCK)
+ {
+ return TRUE;
+ }
+ DBG1(DBG_CFG, "vici header write error: %s", strerror(errno));
+ return FALSE;
+ }
+ out->hdrlen += len;
+ }
+
+ /* write buffer buffer */
+ while (out->buf.len > out->done)
+ {
+ len = stream->write(stream, out->buf.ptr + out->done,
+ out->buf.len - out->done, FALSE);
+ if (len == 0)
+ {
+ DBG1(DBG_CFG, "premature vici disconnect");
+ return FALSE;
+ }
+ if (len < 0)
+ {
+ if (errno == EWOULDBLOCK)
+ {
+ return TRUE;
+ }
+ DBG1(DBG_CFG, "vici write error: %s", strerror(errno));
+ return FALSE;
+ }
+ out->done += len;
+ }
+
+ if (array_remove(entry->out, ARRAY_HEAD, &out))
+ {
+ chunk_clear(&out->buf);
+ free(out);
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Send pending messages
+ */
+CALLBACK(on_write, bool,
+ private_vici_socket_t *this, stream_t *stream)
+{
+ entry_t *entry;
+ bool ret = FALSE;
+
+ entry = find_entry(this, stream, 0, FALSE, TRUE);
+ if (entry)
+ {
+ ret = do_write(this, entry, stream);
+ if (ret)
+ {
+ /* unregister if we have no more messages to send */
+ ret = array_count(entry->out) != 0;
+ }
+ else
+ {
+ disconnect(entry->this, entry->id);
+ }
+ put_entry(this, entry, FALSE, TRUE);
+ }
+
+ return ret;
+}
+
+/**
+ * Read in available header with data, non-blocking cumulating to buffer
+ */
+static bool do_read(private_vici_socket_t *this, entry_t *entry,
+ stream_t *stream)
+{
+ u_int32_t msglen;
+ ssize_t len;
+
+ /* assemble the length header first */
+ while (entry->in.hdrlen < sizeof(entry->in.hdr))
+ {
+ len = stream->read(stream, entry->in.hdr + entry->in.hdrlen,
+ sizeof(entry->in.hdr) - entry->in.hdrlen, FALSE);
+ if (len == 0)
+ {
+ return FALSE;
+ }
+ if (len < 0)
+ {
+ if (errno == EWOULDBLOCK)
+ {
+ return TRUE;
+ }
+ DBG1(DBG_CFG, "vici header read error: %s", strerror(errno));
+ return FALSE;
+ }
+ entry->in.hdrlen += len;
+ if (entry->in.hdrlen == sizeof(entry->in.hdr))
+ {
+ msglen = untoh32(entry->in.hdr);
+ if (msglen > VICI_MESSAGE_SIZE_MAX)
+ {
+ DBG1(DBG_CFG, "vici message length %u exceeds %u bytes limit, "
+ "ignored", msglen, VICI_MESSAGE_SIZE_MAX);
+ return FALSE;
+ }
+ /* header complete, continue with data */
+ entry->in.buf = chunk_alloc(msglen);
+ }
+ }
+
+ /* assemble buffer */
+ while (entry->in.buf.len > entry->in.done)
+ {
+ len = stream->read(stream, entry->in.buf.ptr + entry->in.done,
+ entry->in.buf.len - entry->in.done, FALSE);
+ if (len == 0)
+ {
+ DBG1(DBG_CFG, "premature vici disconnect");
+ return FALSE;
+ }
+ if (len < 0)
+ {
+ if (errno == EWOULDBLOCK)
+ {
+ return TRUE;
+ }
+ DBG1(DBG_CFG, "vici read error: %s", strerror(errno));
+ return FALSE;
+ }
+ entry->in.done += len;
+ }
+
+ return TRUE;
+}
+
+/**
+ * Callback processing incoming requestes in strict order
+ */
+CALLBACK(process_queue, job_requeue_t,
+ entry_selector_t *sel)
+{
+ entry_t *entry;
+ chunk_t chunk;
+ bool found;
+ u_int id;
+
+ while (TRUE)
+ {
+ entry = find_entry(sel->this, NULL, sel->id, TRUE, FALSE);
+ if (!entry)
+ {
+ break;
+ }
+
+ found = array_remove(entry->queue, ARRAY_HEAD, &chunk);
+ if (!found)
+ {
+ entry->has_processor = FALSE;
+ }
+ id = entry->id;
+ put_entry(sel->this, entry, TRUE, FALSE);
+ if (!found)
+ {
+ break;
+ }
+
+ thread_cleanup_push(free, chunk.ptr);
+ sel->this->inbound(sel->this->user, id, chunk);
+ thread_cleanup_pop(TRUE);
+ }
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Process incoming messages
+ */
+CALLBACK(on_read, bool,
+ private_vici_socket_t *this, stream_t *stream)
+{
+ entry_selector_t *sel;
+ entry_t *entry;
+ bool ret = FALSE;
+
+ entry = find_entry(this, stream, 0, TRUE, FALSE);
+ if (entry)
+ {
+ ret = do_read(this, entry, stream);
+ if (!ret)
+ {
+ disconnect(this, entry->id);
+ }
+ else if (entry->in.hdrlen == sizeof(entry->in.hdr) &&
+ entry->in.buf.len == entry->in.done)
+ {
+ array_insert(entry->queue, ARRAY_TAIL, &entry->in.buf);
+ entry->in.buf = chunk_empty;
+ entry->in.hdrlen = entry->in.done = 0;
+
+ if (!entry->has_processor)
+ {
+ INIT(sel,
+ .this = this,
+ .id = entry->id,
+ );
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create(process_queue,
+ sel, free, NULL));
+ entry->has_processor = TRUE;
+ }
+ }
+ put_entry(this, entry, TRUE, FALSE);
+ }
+
+ return ret;
+}
+
+/**
+ * Process connection request
+ */
+CALLBACK(on_accept, bool,
+ private_vici_socket_t *this, stream_t *stream)
+{
+ entry_t *entry;
+ u_int id;
+
+ id = ref_get(&this->nextid);
+
+ INIT(entry,
+ .this = this,
+ .stream = stream,
+ .id = id,
+ .out = array_create(0, 0),
+ .queue = array_create(sizeof(chunk_t), 0),
+ .cond = condvar_create(CONDVAR_TYPE_DEFAULT),
+ .readers = 1,
+ );
+
+ this->mutex->lock(this->mutex);
+ this->connections->insert_last(this->connections, entry);
+ this->mutex->unlock(this->mutex);
+
+ stream->on_read(stream, on_read, this);
+
+ put_entry(this, entry, TRUE, FALSE);
+
+ this->connect(this->user, id);
+
+ return TRUE;
+}
+
+/**
+ * Async callback to enable writer
+ */
+CALLBACK(enable_writer, job_requeue_t,
+ entry_selector_t *sel)
+{
+ entry_t *entry;
+
+ entry = find_entry(sel->this, NULL, sel->id, FALSE, TRUE);
+ if (entry)
+ {
+ entry->stream->on_write(entry->stream, on_write, sel->this);
+ put_entry(sel->this, entry, FALSE, TRUE);
+ }
+ return JOB_REQUEUE_NONE;
+}
+
+METHOD(vici_socket_t, send_, void,
+ private_vici_socket_t *this, u_int id, chunk_t msg)
+{
+ if (msg.len <= VICI_MESSAGE_SIZE_MAX)
+ {
+ entry_selector_t *sel;
+ msg_buf_t *out;
+ entry_t *entry;
+
+ entry = find_entry(this, NULL, id, FALSE, TRUE);
+ if (entry)
+ {
+ INIT(out,
+ .buf = msg,
+ );
+ htoun32(out->hdr, msg.len);
+
+ array_insert(entry->out, ARRAY_TAIL, out);
+ if (array_count(entry->out) == 1)
+ { /* asynchronously re-enable on_write callback when we get data */
+ INIT(sel,
+ .this = this,
+ .id = entry->id,
+ );
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create(enable_writer,
+ sel, free, NULL));
+ }
+ put_entry(this, entry, FALSE, TRUE);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "vici connection %u unknown", id);
+ chunk_clear(&msg);
+ }
+ }
+ else
+ {
+ DBG1(DBG_CFG, "vici message size %zu exceeds maximum size of %u, "
+ "discarded", msg.len, VICI_MESSAGE_SIZE_MAX);
+ chunk_clear(&msg);
+ }
+}
+
+METHOD(vici_socket_t, destroy, void,
+ private_vici_socket_t *this)
+{
+ DESTROY_IF(this->service);
+ this->connections->destroy_function(this->connections, destroy_entry);
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+vici_socket_t *vici_socket_create(char *uri, vici_inbound_cb_t inbound,
+ vici_connect_cb_t connect,
+ vici_disconnect_cb_t disconnect, void *user)
+{
+ private_vici_socket_t *this;
+
+ INIT(this,
+ .public = {
+ .send = _send_,
+ .destroy = _destroy,
+ },
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .connections = linked_list_create(),
+ .inbound = inbound,
+ .connect = connect,
+ .disconnect = disconnect,
+ .user = user,
+ );
+
+ this->service = lib->streams->create_service(lib->streams, uri, 3);
+ if (!this->service)
+ {
+ DBG1(DBG_CFG, "creating vici socket failed");
+ destroy(this);
+ return NULL;
+ }
+ this->service->on_accept(this->service, on_accept, this,
+ JOB_PRIO_CRITICAL, 0);
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/vici/vici_socket.h b/src/libcharon/plugins/vici/vici_socket.h
new file mode 100644
index 000000000..872783665
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_socket.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup vici_socket vici_socket
+ * @{ @ingroup vici
+ */
+
+#ifndef VICI_SOCKET_H_
+#define VICI_SOCKET_H_
+
+#include <library.h>
+
+/**
+ * Maximum size of a single message exchanged.
+ */
+#define VICI_MESSAGE_SIZE_MAX (512 * 1024)
+
+typedef struct vici_socket_t vici_socket_t;
+
+/**
+ * Callback function for dispatching inbound client messages.
+ *
+ * @param user user data, as passed during registration
+ * @param id unique client connection identifier
+ * @param data incoming message data
+ */
+typedef void (*vici_inbound_cb_t)(void *user, u_int id, chunk_t data);
+
+/**
+ * Callback function invoked when new clients connect
+ *
+ * @param user user data, as passed during registration
+ * @param id unique client connection identifier
+ * @return client connection context
+ */
+typedef void (*vici_connect_cb_t)(void *user, u_int id);
+
+/**
+ * Callback function invoked when connected clients disconnect
+ *
+ * @param user user data, as passed during registration
+ * @param id unique client connection identifier
+ */
+typedef void (*vici_disconnect_cb_t)(void *user, u_int id);
+
+/**
+ * Vici socket, low level socket input/output handling.
+ *
+ * On the socket, we pass raw chunks having a 2 byte network order length
+ * prefix. The length field does not count the length header itself, and
+ * is not included in the data passed over this interface.
+ */
+struct vici_socket_t {
+
+ /**
+ * Send a message to a client identified by connection identifier.
+ *
+ * @param id unique client connection identifier
+ * @param data data to send to client, gets owned
+ */
+ void (*send)(vici_socket_t *this, u_int id, chunk_t data);
+
+ /**
+ * Destroy socket.
+ */
+ void (*destroy)(vici_socket_t *this);
+};
+
+/**
+ * Create a vici_socket instance.
+ *
+ * @param uri socket URI to listen on
+ * @param inbound inbound message callback
+ * @param connect connect callback
+ * @param disconnect disconnect callback
+ * @param user user data to pass to callbacks
+ */
+vici_socket_t *vici_socket_create(char *uri, vici_inbound_cb_t inbound,
+ vici_connect_cb_t connect,
+ vici_disconnect_cb_t disconnect, void *user);
+
+#endif /** VICI_SOCKET_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_tests.c b/src/libcharon/plugins/vici/vici_tests.c
new file mode 100644
index 000000000..434aa5e18
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_tests.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <test_runner.h>
+
+#include <daemon.h>
+#include <hydra.h>
+
+/* declare test suite constructors */
+#define TEST_SUITE(x) test_suite_t* x();
+#include "vici_tests.h"
+#undef TEST_SUITE
+
+static test_configuration_t tests[] = {
+#define TEST_SUITE(x) \
+ { .suite = x, },
+#include "vici_tests.h"
+ { .suite = NULL, }
+};
+
+static bool test_runner_init(bool init)
+{
+ if (!init)
+ {
+ lib->processor->set_threads(lib->processor, 0);
+ lib->processor->cancel(lib->processor);
+ }
+ return TRUE;
+}
+
+int main(int argc, char *argv[])
+{
+ return test_runner_run("vici", tests, test_runner_init);
+}
diff --git a/src/libcharon/plugins/vici/vici_tests.h b/src/libcharon/plugins/vici/vici_tests.h
new file mode 100644
index 000000000..3e8f170e4
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_tests.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+TEST_SUITE(socket_suite_create)
+TEST_SUITE(message_suite_create)
+TEST_SUITE(request_suite_create)
+TEST_SUITE(event_suite_create)
diff --git a/src/libcharon/plugins/whitelist/Makefile.am b/src/libcharon/plugins/whitelist/Makefile.am
index e02b4a041..1fd01c888 100644
--- a/src/libcharon/plugins/whitelist/Makefile.am
+++ b/src/libcharon/plugins/whitelist/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
-DIPSEC_PIDDIR=\"${piddir}\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-whitelist.la
diff --git a/src/libcharon/plugins/whitelist/Makefile.in b/src/libcharon/plugins/whitelist/Makefile.in
index e3588ad7d..8a714a9ea 100644
--- a/src/libcharon/plugins/whitelist/Makefile.in
+++ b/src/libcharon/plugins/whitelist/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -273,6 +273,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -291,6 +292,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -318,6 +320,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -409,6 +412,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -426,7 +430,7 @@ AM_CPPFLAGS = \
-DIPSEC_PIDDIR=\"${piddir}\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-whitelist.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-whitelist.la
diff --git a/src/libcharon/plugins/xauth_eap/Makefile.am b/src/libcharon/plugins/xauth_eap/Makefile.am
index 21f8d0297..ea75c1581 100644
--- a/src/libcharon/plugins/xauth_eap/Makefile.am
+++ b/src/libcharon/plugins/xauth_eap/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-xauth-eap.la
diff --git a/src/libcharon/plugins/xauth_eap/Makefile.in b/src/libcharon/plugins/xauth_eap/Makefile.in
index b78a91764..26bb6fb1a 100644
--- a/src/libcharon/plugins/xauth_eap/Makefile.in
+++ b/src/libcharon/plugins/xauth_eap/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-xauth-eap.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-xauth-eap.la
diff --git a/src/libcharon/plugins/xauth_eap/xauth_eap.c b/src/libcharon/plugins/xauth_eap/xauth_eap.c
index f597bb7ae..f21d02697 100644
--- a/src/libcharon/plugins/xauth_eap/xauth_eap.c
+++ b/src/libcharon/plugins/xauth_eap/xauth_eap.c
@@ -163,11 +163,11 @@ METHOD(xauth_method_t, initiate, status_t,
{
cp_payload_t *cp;
- cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
+ cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REQUEST);
cp->add_attribute(cp, configuration_attribute_create_chunk(
- CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, chunk_empty));
+ PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME, chunk_empty));
cp->add_attribute(cp, configuration_attribute_create_chunk(
- CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, chunk_empty));
+ PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_PASSWORD, chunk_empty));
*out = cp;
return NEED_MORE;
}
diff --git a/src/libcharon/plugins/xauth_generic/Makefile.am b/src/libcharon/plugins/xauth_generic/Makefile.am
index d48e52ddd..1ecd9fd14 100644
--- a/src/libcharon/plugins/xauth_generic/Makefile.am
+++ b/src/libcharon/plugins/xauth_generic/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-xauth-generic.la
diff --git a/src/libcharon/plugins/xauth_generic/Makefile.in b/src/libcharon/plugins/xauth_generic/Makefile.in
index e4d96a954..f06fdb593 100644
--- a/src/libcharon/plugins/xauth_generic/Makefile.in
+++ b/src/libcharon/plugins/xauth_generic/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-xauth-generic.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-xauth-generic.la
diff --git a/src/libcharon/plugins/xauth_generic/xauth_generic.c b/src/libcharon/plugins/xauth_generic/xauth_generic.c
index 5df8aadee..c37da0cb0 100644
--- a/src/libcharon/plugins/xauth_generic/xauth_generic.c
+++ b/src/libcharon/plugins/xauth_generic/xauth_generic.c
@@ -69,7 +69,7 @@ METHOD(xauth_method_t, process_peer, status_t,
}
enumerator->destroy(enumerator);
- cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
+ cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REPLY);
enumerator = in->create_attribute_enumerator(in);
while (enumerator->enumerate(enumerator, &attr))
@@ -80,7 +80,7 @@ METHOD(xauth_method_t, process_peer, status_t,
{
case XAUTH_USER_NAME:
cp->add_attribute(cp, configuration_attribute_create_chunk(
- CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME,
+ PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME,
this->peer->get_encoding(this->peer)));
break;
case XAUTH_NEXT_PIN:
@@ -99,7 +99,7 @@ METHOD(xauth_method_t, process_peer, status_t,
return FAILED;
}
cp->add_attribute(cp, configuration_attribute_create_chunk(
- CONFIGURATION_ATTRIBUTE_V1, attr->get_type(attr),
+ PLV1_CONFIGURATION_ATTRIBUTE, attr->get_type(attr),
shared->get_key(shared)));
shared->destroy(shared);
break;
@@ -118,11 +118,11 @@ METHOD(xauth_method_t, initiate_server, status_t,
{
cp_payload_t *cp;
- cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
+ cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REQUEST);
cp->add_attribute(cp, configuration_attribute_create_chunk(
- CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, chunk_empty));
+ PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME, chunk_empty));
cp->add_attribute(cp, configuration_attribute_create_chunk(
- CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, chunk_empty));
+ PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_PASSWORD, chunk_empty));
*out = cp;
return NEED_MORE;
}
diff --git a/src/libcharon/plugins/xauth_noauth/Makefile.am b/src/libcharon/plugins/xauth_noauth/Makefile.am
index f1581ba67..3902471fe 100644
--- a/src/libcharon/plugins/xauth_noauth/Makefile.am
+++ b/src/libcharon/plugins/xauth_noauth/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-xauth-noauth.la
diff --git a/src/libcharon/plugins/xauth_noauth/Makefile.in b/src/libcharon/plugins/xauth_noauth/Makefile.in
index 5fe4c064f..72f3dc668 100644
--- a/src/libcharon/plugins/xauth_noauth/Makefile.in
+++ b/src/libcharon/plugins/xauth_noauth/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-xauth-noauth.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-xauth-noauth.la
diff --git a/src/libcharon/plugins/xauth_pam/Makefile.am b/src/libcharon/plugins/xauth_pam/Makefile.am
index 1875f81d3..abf83ca75 100644
--- a/src/libcharon/plugins/xauth_pam/Makefile.am
+++ b/src/libcharon/plugins/xauth_pam/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-xauth-pam.la
diff --git a/src/libcharon/plugins/xauth_pam/Makefile.in b/src/libcharon/plugins/xauth_pam/Makefile.in
index 2a6aec0c3..9af015e29 100644
--- a/src/libcharon/plugins/xauth_pam/Makefile.in
+++ b/src/libcharon/plugins/xauth_pam/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libcharon
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-xauth-pam.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-xauth-pam.la
diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam.c b/src/libcharon/plugins/xauth_pam/xauth_pam.c
index 71c79ecc0..3414d2ec8 100644
--- a/src/libcharon/plugins/xauth_pam/xauth_pam.c
+++ b/src/libcharon/plugins/xauth_pam/xauth_pam.c
@@ -43,11 +43,11 @@ METHOD(xauth_method_t, initiate, status_t,
{
cp_payload_t *cp;
- cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
+ cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REQUEST);
cp->add_attribute(cp, configuration_attribute_create_chunk(
- CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, chunk_empty));
+ PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME, chunk_empty));
cp->add_attribute(cp, configuration_attribute_create_chunk(
- CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, chunk_empty));
+ PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_PASSWORD, chunk_empty));
*out = cp;
return NEED_MORE;
}
@@ -153,7 +153,12 @@ METHOD(xauth_method_t, process, status_t,
attr2string(user, sizeof(user), chunk);
break;
case XAUTH_USER_PASSWORD:
- attr2string(pass, sizeof(pass), attr->get_chunk(attr));
+ chunk = attr->get_chunk(attr);
+ if (chunk.len && chunk.ptr[chunk.len - 1] == 0)
+ { /* fix null-terminated passwords (Android etc.) */
+ chunk.len -= 1;
+ }
+ attr2string(pass, sizeof(pass), chunk);
break;
default:
break;
diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam_listener.h b/src/libcharon/plugins/xauth_pam/xauth_pam_listener.h
index 5b15410f4..fd1122395 100644
--- a/src/libcharon/plugins/xauth_pam/xauth_pam_listener.h
+++ b/src/libcharon/plugins/xauth_pam/xauth_pam_listener.h
@@ -26,7 +26,7 @@
* @{ @ingroup xauth_pam
*/
-#ifndef XAUTH_PAM_LISENER_H_
+#ifndef XAUTH_PAM_LISTENER_H_
#define XAUTH_PAM_LISTENER_H_
typedef struct xauth_pam_listener_t xauth_pam_listener_t;