summaryrefslogtreecommitdiff
path: root/src/libcharon
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@corsac.net>2017-05-30 20:59:31 +0200
committerYves-Alexis Perez <corsac@corsac.net>2017-05-30 20:59:31 +0200
commitbba25e2ff6c4a193acb54560ea4417537bd2954e (patch)
tree9e074fe343f9ab6f5ce1e9c5142d9a6cf180fcda /src/libcharon
parent05ddd767992d68bb38c7f16ece142e8c2e9ae016 (diff)
downloadvyos-strongswan-bba25e2ff6c4a193acb54560ea4417537bd2954e.tar.gz
vyos-strongswan-bba25e2ff6c4a193acb54560ea4417537bd2954e.zip
New upstream version 5.5.3
Diffstat (limited to 'src/libcharon')
-rw-r--r--src/libcharon/Makefile.am9
-rw-r--r--src/libcharon/Makefile.in22
-rw-r--r--src/libcharon/attributes/attribute_manager.c25
-rw-r--r--src/libcharon/attributes/mem_pool.c12
-rw-r--r--src/libcharon/bus/bus.c43
-rw-r--r--src/libcharon/config/backend_manager.c30
-rw-r--r--src/libcharon/config/child_cfg.c100
-rw-r--r--src/libcharon/config/child_cfg.h82
-rw-r--r--src/libcharon/config/ike_cfg.c2
-rw-r--r--src/libcharon/config/ike_cfg.h8
-rw-r--r--src/libcharon/config/peer_cfg.c22
-rw-r--r--src/libcharon/config/proposal.c40
-rw-r--r--src/libcharon/daemon.c24
-rw-r--r--src/libcharon/encoding/message.c2
-rw-r--r--src/libcharon/encoding/payloads/certreq_payload.c9
-rw-r--r--src/libcharon/encoding/payloads/delete_payload.c9
-rw-r--r--src/libcharon/encoding/payloads/eap_payload.c9
-rw-r--r--src/libcharon/kernel/kernel_interface.c9
-rw-r--r--src/libcharon/kernel/kernel_ipsec.h2
-rw-r--r--src/libcharon/network/receiver.c6
-rw-r--r--src/libcharon/plugins/addrblock/Makefile.in2
-rw-r--r--src/libcharon/plugins/addrblock/addrblock_validator.c4
-rw-r--r--src/libcharon/plugins/android_dns/Makefile.in2
-rw-r--r--src/libcharon/plugins/android_dns/android_dns_handler.c12
-rw-r--r--src/libcharon/plugins/android_log/Makefile.am1
-rw-r--r--src/libcharon/plugins/android_log/Makefile.in5
-rw-r--r--src/libcharon/plugins/attr/Makefile.in2
-rw-r--r--src/libcharon/plugins/attr/attr_provider.c26
-rw-r--r--src/libcharon/plugins/attr_sql/Makefile.in2
-rw-r--r--src/libcharon/plugins/attr_sql/attr_sql_provider.c20
-rw-r--r--src/libcharon/plugins/bypass_lan/Makefile.in2
-rw-r--r--src/libcharon/plugins/bypass_lan/bypass_lan_listener.c7
-rw-r--r--src/libcharon/plugins/certexpire/Makefile.in2
-rw-r--r--src/libcharon/plugins/connmark/Makefile.in2
-rw-r--r--src/libcharon/plugins/coupling/Makefile.in2
-rw-r--r--src/libcharon/plugins/dhcp/Makefile.in2
-rw-r--r--src/libcharon/plugins/dhcp/dhcp_provider.c3
-rw-r--r--src/libcharon/plugins/dhcp/dhcp_socket.c3
-rw-r--r--src/libcharon/plugins/dhcp/dhcp_transaction.c26
-rw-r--r--src/libcharon/plugins/dnscert/Makefile.in2
-rw-r--r--src/libcharon/plugins/dnscert/dnscert_cred.c8
-rw-r--r--src/libcharon/plugins/duplicheck/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_aka/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_dynamic/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_dynamic/eap_dynamic.c12
-rw-r--r--src/libcharon/plugins/eap_gtc/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_identity/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_md5/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_mschapv2/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_peap/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_radius/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_provider.c11
-rw-r--r--src/libcharon/plugins/eap_sim/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_sim_file/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.c34
-rw-r--r--src/libcharon/plugins/eap_sim_pcsc/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_simaka_reauth/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_simaka_sql/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.c11
-rw-r--r--src/libcharon/plugins/eap_tls/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_tnc/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_ttls/Makefile.in2
-rw-r--r--src/libcharon/plugins/error_notify/Makefile.in2
-rw-r--r--src/libcharon/plugins/ext_auth/Makefile.in2
-rw-r--r--src/libcharon/plugins/farp/Makefile.in2
-rw-r--r--src/libcharon/plugins/forecast/Makefile.in2
-rw-r--r--src/libcharon/plugins/forecast/forecast_listener.c30
-rw-r--r--src/libcharon/plugins/ha/Makefile.in2
-rw-r--r--src/libcharon/plugins/ha/ha_dispatcher.c16
-rw-r--r--src/libcharon/plugins/ha/ha_message.c11
-rw-r--r--src/libcharon/plugins/ha/ha_tunnel.c9
-rw-r--r--src/libcharon/plugins/ipseckey/Makefile.in2
-rw-r--r--src/libcharon/plugins/ipseckey/ipseckey_cred.c8
-rw-r--r--src/libcharon/plugins/kernel_iph/Makefile.in2
-rw-r--r--src/libcharon/plugins/kernel_iph/kernel_iph_net.c8
-rw-r--r--src/libcharon/plugins/kernel_libipsec/Makefile.in2
-rw-r--r--src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c35
-rw-r--r--src/libcharon/plugins/kernel_netlink/Makefile.in2
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c136
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c169
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.c23
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c3
-rw-r--r--src/libcharon/plugins/kernel_pfkey/Makefile.in2
-rw-r--r--src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c119
-rw-r--r--src/libcharon/plugins/kernel_pfroute/Makefile.in2
-rw-r--r--src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c123
-rw-r--r--src/libcharon/plugins/kernel_wfp/Makefile.in2
-rw-r--r--src/libcharon/plugins/led/Makefile.in2
-rw-r--r--src/libcharon/plugins/load_tester/Makefile.in2
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_creds.c34
-rw-r--r--src/libcharon/plugins/lookip/Makefile.in2
-rw-r--r--src/libcharon/plugins/medcli/Makefile.in2
-rw-r--r--src/libcharon/plugins/medcli/medcli_config.c8
-rw-r--r--src/libcharon/plugins/medcli/medcli_creds.c16
-rw-r--r--src/libcharon/plugins/medcli/medcli_creds.h2
-rw-r--r--src/libcharon/plugins/medcli/medcli_listener.h2
-rw-r--r--src/libcharon/plugins/medsrv/Makefile.in2
-rw-r--r--src/libcharon/plugins/medsrv/medsrv_creds.c9
-rw-r--r--src/libcharon/plugins/medsrv/medsrv_creds.h2
-rw-r--r--src/libcharon/plugins/osx_attr/Makefile.in2
-rw-r--r--src/libcharon/plugins/osx_attr/osx_attr_handler.c12
-rw-r--r--src/libcharon/plugins/p_cscf/Makefile.in2
-rw-r--r--src/libcharon/plugins/p_cscf/p_cscf_handler.c23
-rw-r--r--src/libcharon/plugins/radattr/Makefile.in2
-rw-r--r--src/libcharon/plugins/resolve/Makefile.in2
-rw-r--r--src/libcharon/plugins/resolve/resolve_handler.c12
-rw-r--r--src/libcharon/plugins/smp/Makefile.in2
-rw-r--r--src/libcharon/plugins/socket_default/Makefile.in2
-rw-r--r--src/libcharon/plugins/socket_default/socket_default_socket.c55
-rw-r--r--src/libcharon/plugins/socket_dynamic/Makefile.in2
-rw-r--r--src/libcharon/plugins/socket_win/Makefile.in2
-rw-r--r--src/libcharon/plugins/sql/Makefile.in2
-rw-r--r--src/libcharon/plugins/sql/sql_config.c79
-rw-r--r--src/libcharon/plugins/sql/sql_cred.c35
-rw-r--r--src/libcharon/plugins/stroke/Makefile.in2
-rw-r--r--src/libcharon/plugins/stroke/stroke_attribute.c76
-rw-r--r--src/libcharon/plugins/stroke/stroke_ca.c49
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.c30
-rw-r--r--src/libcharon/plugins/stroke/stroke_handler.c56
-rw-r--r--src/libcharon/plugins/stroke/stroke_list.c5
-rw-r--r--src/libcharon/plugins/stroke/stroke_socket.c1
-rw-r--r--src/libcharon/plugins/systime_fix/Makefile.in2
-rw-r--r--src/libcharon/plugins/tnc_ifmap/Makefile.in2
-rw-r--r--src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap_msg.c9
-rw-r--r--src/libcharon/plugins/tnc_pdp/Makefile.in2
-rw-r--r--src/libcharon/plugins/uci/Makefile.in2
-rw-r--r--src/libcharon/plugins/uci/uci_config.c16
-rw-r--r--src/libcharon/plugins/uci/uci_creds.c10
-rw-r--r--src/libcharon/plugins/uci/uci_parser.c17
-rw-r--r--src/libcharon/plugins/unity/Makefile.in2
-rw-r--r--src/libcharon/plugins/unity/unity_handler.c39
-rw-r--r--src/libcharon/plugins/unity/unity_provider.c10
-rw-r--r--src/libcharon/plugins/updown/Makefile.in2
-rw-r--r--src/libcharon/plugins/updown/updown_listener.c2
-rw-r--r--src/libcharon/plugins/vici/Makefile.in2
-rw-r--r--src/libcharon/plugins/vici/README.md3
-rw-r--r--src/libcharon/plugins/vici/perl/Makefile.in2
-rw-r--r--src/libcharon/plugins/vici/python/Makefile.in2
-rw-r--r--src/libcharon/plugins/vici/python/vici/protocol.py2
-rw-r--r--src/libcharon/plugins/vici/ruby/Makefile.in4
-rw-r--r--src/libcharon/plugins/vici/suites/test_message.c12
-rw-r--r--src/libcharon/plugins/vici/vici_attribute.c26
-rw-r--r--src/libcharon/plugins/vici/vici_config.c113
-rw-r--r--src/libcharon/plugins/vici/vici_cred.c14
-rw-r--r--src/libcharon/plugins/vici/vici_message.c10
-rw-r--r--src/libcharon/plugins/vici/vici_query.c2
-rw-r--r--src/libcharon/plugins/whitelist/Makefile.in2
-rw-r--r--src/libcharon/plugins/whitelist/whitelist_listener.c21
-rw-r--r--src/libcharon/plugins/xauth_eap/Makefile.in2
-rw-r--r--src/libcharon/plugins/xauth_generic/Makefile.in2
-rw-r--r--src/libcharon/plugins/xauth_noauth/Makefile.in2
-rw-r--r--src/libcharon/plugins/xauth_pam/Makefile.in2
-rw-r--r--src/libcharon/processing/jobs/delete_child_sa_job.c69
-rw-r--r--src/libcharon/processing/jobs/delete_child_sa_job.h13
-rw-r--r--src/libcharon/sa/child_sa.c560
-rw-r--r--src/libcharon/sa/child_sa.h120
-rw-r--r--src/libcharon/sa/eap/eap_manager.c53
-rw-r--r--src/libcharon/sa/ike_sa.c57
-rw-r--r--src/libcharon/sa/ike_sa_manager.c121
-rw-r--r--src/libcharon/sa/ikev1/task_manager_v1.c31
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_mode.c37
-rw-r--r--src/libcharon/sa/ikev2/connect_manager.c164
-rw-r--r--src/libcharon/sa/ikev2/task_manager_v2.c47
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_create.c96
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_delete.c229
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_rekey.c16
-rw-r--r--src/libcharon/sa/shunt_manager.c22
-rw-r--r--src/libcharon/sa/task_manager.c32
-rw-r--r--src/libcharon/sa/task_manager.h16
-rw-r--r--src/libcharon/sa/trap_manager.c72
-rw-r--r--src/libcharon/tests/Makefile.in2
-rw-r--r--src/libcharon/tests/suites/test_child_rekey.c617
-rw-r--r--src/libcharon/tests/utils/exchange_test_asserts.c57
-rw-r--r--src/libcharon/tests/utils/exchange_test_asserts.h61
-rw-r--r--src/libcharon/tests/utils/mock_ipsec.c179
-rw-r--r--src/libcharon/tests/utils/mock_ipsec.h11
-rw-r--r--src/libcharon/tests/utils/sa_asserts.h32
179 files changed, 3522 insertions, 1486 deletions
diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am
index 8461d6230..3fcaedc3b 100644
--- a/src/libcharon/Makefile.am
+++ b/src/libcharon/Makefile.am
@@ -184,6 +184,15 @@ if USE_ME
sa/ikev2/tasks/ike_me.c sa/ikev2/tasks/ike_me.h
endif
+if STATIC_PLUGIN_CONSTRUCTORS
+BUILT_SOURCES = $(srcdir)/plugin_constructors.c
+CLEANFILES = $(srcdir)/plugin_constructors.c
+
+$(srcdir)/plugin_constructors.c: $(top_srcdir)/src/libstrongswan/plugins/plugin_constructors.py
+ $(AM_V_GEN) \
+ $(PYTHON) $(top_srcdir)/src/libstrongswan/plugins/plugin_constructors.py ${c_plugins} > $@
+endif
+
# build optional plugins
########################
diff --git a/src/libcharon/Makefile.in b/src/libcharon/Makefile.in
index 8f6dc89a3..ef9ffd39b 100644
--- a/src/libcharon/Makefile.in
+++ b/src/libcharon/Makefile.in
@@ -934,6 +934,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -956,6 +957,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
@@ -1167,6 +1169,8 @@ libcharon_la_LIBADD = \
$(am__append_141) $(am__append_143) $(am__append_145) \
$(am__append_147)
EXTRA_DIST = Android.mk
+@STATIC_PLUGIN_CONSTRUCTORS_TRUE@BUILT_SOURCES = $(srcdir)/plugin_constructors.c
+@STATIC_PLUGIN_CONSTRUCTORS_TRUE@CLEANFILES = $(srcdir)/plugin_constructors.c
@MONOLITHIC_FALSE@SUBDIRS = . $(am__append_6) $(am__append_8) \
@MONOLITHIC_FALSE@ $(am__append_10) $(am__append_12) \
@MONOLITHIC_FALSE@ $(am__append_14) $(am__append_16) \
@@ -1240,7 +1244,8 @@ EXTRA_DIST = Android.mk
@MONOLITHIC_TRUE@ $(am__append_138) $(am__append_140) \
@MONOLITHIC_TRUE@ $(am__append_142) $(am__append_144) \
@MONOLITHIC_TRUE@ $(am__append_146) . tests
-all: all-recursive
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-recursive
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
@@ -2095,14 +2100,16 @@ distdir: $(DISTFILES)
fi; \
done
check-am: all-am
-check: check-recursive
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-recursive
all-am: Makefile $(LTLIBRARIES)
installdirs: installdirs-recursive
installdirs-am:
for dir in "$(DESTDIR)$(ipseclibdir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
-install: install-recursive
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive
@@ -2124,6 +2131,7 @@ install-strip:
mostlyclean-generic:
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
@@ -2170,6 +2178,7 @@ distclean-generic:
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
clean: clean-recursive
clean-am: clean-generic clean-ipseclibLTLIBRARIES clean-libtool \
@@ -2241,7 +2250,8 @@ ps-am:
uninstall-am: uninstall-ipseclibLTLIBRARIES
-.MAKE: $(am__recursive_targets) install-am install-strip
+.MAKE: $(am__recursive_targets) all check install install-am \
+ install-strip
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
check-am clean clean-generic clean-ipseclibLTLIBRARIES \
@@ -2264,6 +2274,10 @@ uninstall-am: uninstall-ipseclibLTLIBRARIES
daemon.lo : $(top_builddir)/config.status
+@STATIC_PLUGIN_CONSTRUCTORS_TRUE@$(srcdir)/plugin_constructors.c: $(top_srcdir)/src/libstrongswan/plugins/plugin_constructors.py
+@STATIC_PLUGIN_CONSTRUCTORS_TRUE@ $(AM_V_GEN) \
+@STATIC_PLUGIN_CONSTRUCTORS_TRUE@ $(PYTHON) $(top_srcdir)/src/libstrongswan/plugins/plugin_constructors.py ${c_plugins} > $@
+
@MONOLITHIC_TRUE@@USE_SIMAKA_TRUE@ # otherwise this library is linked to both the eap_aka and the eap_sim plugin
@MONOLITHIC_TRUE@@USE_TLS_TRUE@ # otherwise this library is linked to eap_tls
diff --git a/src/libcharon/attributes/attribute_manager.c b/src/libcharon/attributes/attribute_manager.c
index 2ab7ed118..3a4a21a02 100644
--- a/src/libcharon/attributes/attribute_manager.c
+++ b/src/libcharon/attributes/attribute_manager.c
@@ -237,14 +237,14 @@ typedef struct {
linked_list_t *vips;
} initiator_enumerator_t;
-/**
- * Enumerator implementation for initiator attributes
- */
-static bool initiator_enumerate(initiator_enumerator_t *this,
- attribute_handler_t **handler,
- configuration_attribute_type_t *type,
- chunk_t *value)
+METHOD(enumerator_t, initiator_enumerate, bool,
+ initiator_enumerator_t *this, va_list args)
{
+ configuration_attribute_type_t *type;
+ attribute_handler_t **handler;
+ chunk_t *value;
+
+ VA_ARGS_VGET(args, handler, type, value);
/* enumerate inner attributes using outer handler enumerator */
while (!this->inner || !this->inner->enumerate(this->inner, type, value))
{
@@ -261,10 +261,8 @@ static bool initiator_enumerate(initiator_enumerator_t *this,
return TRUE;
}
-/**
- * Cleanup function of initiator attribute enumerator
- */
-static void initiator_destroy(initiator_enumerator_t *this)
+METHOD(enumerator_t, initiator_destroy, void,
+ initiator_enumerator_t *this)
{
this->this->lock->unlock(this->this->lock);
this->outer->destroy(this->outer);
@@ -281,8 +279,9 @@ METHOD(attribute_manager_t, create_initiator_enumerator, enumerator_t*,
INIT(enumerator,
.public = {
- .enumerate = (void*)initiator_enumerate,
- .destroy = (void*)initiator_destroy,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _initiator_enumerate,
+ .destroy = _initiator_destroy,
},
.this = this,
.ike_sa = ike_sa,
diff --git a/src/libcharon/attributes/mem_pool.c b/src/libcharon/attributes/mem_pool.c
index a2b7c2803..e1a9a6dce 100644
--- a/src/libcharon/attributes/mem_pool.c
+++ b/src/libcharon/attributes/mem_pool.c
@@ -512,10 +512,15 @@ typedef struct {
} lease_enumerator_t;
METHOD(enumerator_t, lease_enumerate, bool,
- lease_enumerator_t *this, identification_t **id, host_t **addr, bool *online)
+ lease_enumerator_t *this, va_list args)
{
- u_int *offset;
+ identification_t **id;
unique_lease_t *lease;
+ host_t **addr;
+ u_int *offset;
+ bool *online;
+
+ VA_ARGS_VGET(args, id, addr, online);
DESTROY_IF(this->addr);
this->addr = NULL;
@@ -570,7 +575,8 @@ METHOD(mem_pool_t, create_lease_enumerator, enumerator_t*,
this->mutex->lock(this->mutex);
INIT(enumerator,
.public = {
- .enumerate = (void*)_lease_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _lease_enumerate,
.destroy = _lease_enumerator_destroy,
},
.pool = this,
diff --git a/src/libcharon/bus/bus.c b/src/libcharon/bus/bus.c
index f4bba872f..77a910197 100644
--- a/src/libcharon/bus/bus.c
+++ b/src/libcharon/bus/bus.c
@@ -207,20 +207,20 @@ static inline void register_logger(private_bus_t *this, debug_t group,
}
}
-/**
- * Find the log level of the first registered logger that implements log or
- * vlog (or both).
- */
-static bool find_max_levels(log_entry_t *entry, debug_t *group, level_t *level,
- level_t *vlevel)
+CALLBACK(find_max_levels, bool,
+ log_entry_t *entry, va_list args)
{
+ level_t *level, *vlevel;
+ debug_t group;
+
+ VA_ARGS_VGET(args, group, level, vlevel);
if (entry->logger->log && *level == LEVEL_SILENT)
{
- *level = entry->levels[*group];
+ *level = entry->levels[group];
}
if (entry->logger->vlog && *vlevel == LEVEL_SILENT)
{
- *vlevel = entry->levels[*group];
+ *vlevel = entry->levels[group];
}
return *level > LEVEL_SILENT && *vlevel > LEVEL_SILENT;
}
@@ -258,8 +258,8 @@ static inline void unregister_logger(private_bus_t *this, logger_t *logger)
loggers = this->loggers[group];
loggers->remove(loggers, found, NULL);
- loggers->find_first(loggers, (linked_list_match_t)find_max_levels,
- NULL, &group, &level, &vlevel);
+ loggers->find_first(loggers, find_max_levels, NULL, group,
+ &level, &vlevel);
set_level(&this->max_level[group], level);
set_level(&this->max_vlevel[group], vlevel);
}
@@ -330,11 +330,12 @@ typedef struct {
va_list args;
} log_data_t;
-/**
- * logger->log() invocation as a invoke_function callback
- */
-static void log_cb(log_entry_t *entry, log_data_t *data)
+CALLBACK(log_cb, void,
+ log_entry_t *entry, va_list args)
{
+ log_data_t *data;
+
+ VA_ARGS_VGET(args, data);
if (entry->logger->log && entry->levels[data->group] >= data->level)
{
entry->logger->log(entry->logger, data->group, data->level,
@@ -342,11 +343,12 @@ static void log_cb(log_entry_t *entry, log_data_t *data)
}
}
-/**
- * logger->vlog() invocation as a invoke_function callback
- */
-static void vlog_cb(log_entry_t *entry, log_data_t *data)
+CALLBACK(vlog_cb, void,
+ log_entry_t *entry, va_list args)
{
+ log_data_t *data;
+
+ VA_ARGS_VGET(args, data);
if (entry->logger->vlog && entry->levels[data->group] >= data->level)
{
va_list copy;
@@ -405,8 +407,7 @@ METHOD(bus_t, vlog, void,
}
if (len > 0)
{
- loggers->invoke_function(loggers, (linked_list_invoke_t)log_cb,
- &data);
+ loggers->invoke_function(loggers, log_cb, &data);
}
if (data.message != buf)
{
@@ -422,7 +423,7 @@ METHOD(bus_t, vlog, void,
data.message = format;
va_copy(data.args, args);
- loggers->invoke_function(loggers, (linked_list_invoke_t)vlog_cb, &data);
+ loggers->invoke_function(loggers, vlog_cb, &data);
va_end(data.args);
}
diff --git a/src/libcharon/config/backend_manager.c b/src/libcharon/config/backend_manager.c
index 79f1d9fee..4f154df9b 100644
--- a/src/libcharon/config/backend_manager.c
+++ b/src/libcharon/config/backend_manager.c
@@ -265,20 +265,24 @@ static void peer_enum_destroy(peer_data_t *data)
free(data);
}
-/**
- * convert enumerator value from match_entry to config
- */
-static bool peer_enum_filter(linked_list_t *configs,
- match_entry_t **in, peer_cfg_t **out)
+CALLBACK(peer_enum_filter, bool,
+ linked_list_t *configs, enumerator_t *orig, va_list args)
{
- *out = (*in)->cfg;
- return TRUE;
+ match_entry_t *entry;
+ peer_cfg_t **out;
+
+ VA_ARGS_VGET(args, out);
+
+ if (orig->enumerate(orig, &entry))
+ {
+ *out = entry->cfg;
+ return TRUE;
+ }
+ return FALSE;
}
-/**
- * Clean up temporary config list
- */
-static void peer_enum_filter_destroy(linked_list_t *configs)
+CALLBACK(peer_enum_filter_destroy, void,
+ linked_list_t *configs)
{
match_entry_t *entry;
@@ -379,8 +383,8 @@ METHOD(backend_manager_t, create_peer_cfg_enumerator, enumerator_t*,
helper->destroy(helper);
return enumerator_create_filter(configs->create_enumerator(configs),
- (void*)peer_enum_filter, configs,
- (void*)peer_enum_filter_destroy);
+ peer_enum_filter, configs,
+ peer_enum_filter_destroy);
}
METHOD(backend_manager_t, get_peer_cfg_by_name, peer_cfg_t*,
diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c
index 3c6dd5198..ec2a12431 100644
--- a/src/libcharon/config/child_cfg.c
+++ b/src/libcharon/config/child_cfg.c
@@ -1,6 +1,6 @@
/*
+ * Copyright (C) 2008-2017 Tobias Brunner
* Copyright (C) 2016 Andreas Steffen
- * Copyright (C) 2008-2016 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
@@ -54,6 +54,11 @@ struct private_child_cfg_t {
char *name;
/**
+ * Options
+ */
+ child_cfg_option_t options;
+
+ /**
* list for all proposals
*/
linked_list_t *proposals;
@@ -74,11 +79,6 @@ struct private_child_cfg_t {
char *updown;
/**
- * allow host access
- */
- bool hostaccess;
-
- /**
* Mode to propose for a initiated CHILD: tunnel/transport
*/
ipsec_mode_t mode;
@@ -104,11 +104,6 @@ struct private_child_cfg_t {
lifetime_cfg_t lifetime;
/**
- * enable IPComp
- */
- bool use_ipcomp;
-
- /**
* Inactivity timeout
*/
uint32_t inactivity;
@@ -144,21 +139,6 @@ struct private_child_cfg_t {
char *interface;
/**
- * set up IPsec transport SA in MIPv6 proxy mode
- */
- bool proxy_mode;
-
- /**
- * enable installation and removal of kernel IPsec policies
- */
- bool install_policy;
-
- /**
- * Install outbound FWD policies
- */
- bool fwd_out_policy;
-
- /**
* anti-replay window size
*/
uint32_t replay_window;
@@ -170,6 +150,12 @@ METHOD(child_cfg_t, get_name, char*,
return this->name;
}
+METHOD(child_cfg_t, has_option, bool,
+ private_child_cfg_t *this, child_cfg_option_t option)
+{
+ return this->options & option;
+}
+
METHOD(child_cfg_t, add_proposal, void,
private_child_cfg_t *this, proposal_t *proposal)
{
@@ -179,8 +165,12 @@ METHOD(child_cfg_t, add_proposal, void,
}
}
-static bool match_proposal(proposal_t *item, proposal_t *proposal)
+CALLBACK(match_proposal, bool,
+ proposal_t *item, va_list args)
{
+ proposal_t *proposal;
+
+ VA_ARGS_VGET(args, proposal);
return item->equals(item, proposal);
}
@@ -199,8 +189,7 @@ METHOD(child_cfg_t, get_proposals, linked_list_t*,
{
current->strip_dh(current, MODP_NONE);
}
- if (proposals->find_first(proposals, (linked_list_match_t)match_proposal,
- NULL, current) == SUCCESS)
+ if (proposals->find_first(proposals, match_proposal, NULL, current))
{
current->destroy(current);
continue;
@@ -311,8 +300,9 @@ METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*,
{
if (hosts && hosts->get_count(hosts))
{ /* set hosts if TS is dynamic or as initiator in transport mode */
- bool dynamic = ts1->is_dynamic(ts1);
- if (dynamic || (this->mode == MODE_TRANSPORT && !this->proxy_mode &&
+ bool dynamic = ts1->is_dynamic(ts1),
+ proxy_mode = has_option(this, OPT_PROXY_MODE);
+ if (dynamic || (this->mode == MODE_TRANSPORT && !proxy_mode &&
!supplied))
{
e2 = hosts->create_enumerator(hosts);
@@ -428,12 +418,6 @@ METHOD(child_cfg_t, get_updown, char*,
return this->updown;
}
-METHOD(child_cfg_t, get_hostaccess, bool,
- private_child_cfg_t *this)
-{
- return this->hostaccess;
-}
-
/**
* Applies jitter to the rekey value. Returns the new rekey value.
* Note: The distribution of random values is not perfect, but it
@@ -508,12 +492,6 @@ METHOD(child_cfg_t, get_dh_group, diffie_hellman_group_t,
return dh_group;
}
-METHOD(child_cfg_t, use_ipcomp, bool,
- private_child_cfg_t *this)
-{
- return this->use_ipcomp;
-}
-
METHOD(child_cfg_t, get_inactivity, uint32_t,
private_child_cfg_t *this)
{
@@ -562,24 +540,6 @@ METHOD(child_cfg_t, set_replay_window, void,
this->replay_window = replay_window;
}
-METHOD(child_cfg_t, use_proxy_mode, bool,
- private_child_cfg_t *this)
-{
- return this->proxy_mode;
-}
-
-METHOD(child_cfg_t, install_policy, bool,
- private_child_cfg_t *this)
-{
- return this->install_policy;
-}
-
-METHOD(child_cfg_t, install_fwd_out_policy, bool,
- private_child_cfg_t *this)
-{
- return this->fwd_out_policy;
-}
-
#define LT_PART_EQUALS(a, b) ({ a.life == b.life && a.rekey == b.rekey && a.jitter == b.jitter; })
#define LIFETIME_EQUALS(a, b) ({ LT_PART_EQUALS(a.time, b.time) && LT_PART_EQUALS(a.bytes, b.bytes) && LT_PART_EQUALS(a.packets, b.packets); })
@@ -611,13 +571,12 @@ METHOD(child_cfg_t, equals, bool,
{
return FALSE;
}
- return this->hostaccess == other->hostaccess &&
+ return this->options == other->options &&
this->mode == other->mode &&
this->start_action == other->start_action &&
this->dpd_action == other->dpd_action &&
this->close_action == other->close_action &&
LIFETIME_EQUALS(this->lifetime, other->lifetime) &&
- this->use_ipcomp == other->use_ipcomp &&
this->inactivity == other->inactivity &&
this->reqid == other->reqid &&
this->mark_in.value == other->mark_in.value &&
@@ -627,9 +586,6 @@ METHOD(child_cfg_t, equals, bool,
this->tfc == other->tfc &&
this->manual_prio == other->manual_prio &&
this->replay_window == other->replay_window &&
- this->proxy_mode == other->proxy_mode &&
- this->install_policy == other->install_policy &&
- this->fwd_out_policy == other->fwd_out_policy &&
streq(this->updown, other->updown) &&
streq(this->interface, other->interface);
}
@@ -672,14 +628,12 @@ child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data)
.get_proposals = _get_proposals,
.select_proposal = _select_proposal,
.get_updown = _get_updown,
- .get_hostaccess = _get_hostaccess,
.get_mode = _get_mode,
.get_start_action = _get_start_action,
.get_dpd_action = _get_dpd_action,
.get_close_action = _get_close_action,
.get_lifetime = _get_lifetime,
.get_dh_group = _get_dh_group,
- .use_ipcomp = _use_ipcomp,
.get_inactivity = _get_inactivity,
.get_reqid = _get_reqid,
.get_mark = _get_mark,
@@ -688,19 +642,16 @@ child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data)
.get_interface = _get_interface,
.get_replay_window = _get_replay_window,
.set_replay_window = _set_replay_window,
- .use_proxy_mode = _use_proxy_mode,
- .install_policy = _install_policy,
- .install_fwd_out_policy = _install_fwd_out_policy,
+ .has_option = _has_option,
.equals = _equals,
.get_ref = _get_ref,
.destroy = _destroy,
},
.name = strdup(name),
+ .options = data->options,
.updown = strdupnull(data->updown),
- .hostaccess = data->hostaccess,
.reqid = data->reqid,
.mode = data->mode,
- .proxy_mode = data->proxy_mode,
.start_action = data->start_action,
.dpd_action = data->dpd_action,
.close_action = data->close_action,
@@ -708,12 +659,9 @@ child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data)
.mark_out = data->mark_out,
.lifetime = data->lifetime,
.inactivity = data->inactivity,
- .use_ipcomp = data->ipcomp,
.tfc = data->tfc,
.manual_prio = data->priority,
.interface = strdupnull(data->interface),
- .install_policy = !data->suppress_policies,
- .fwd_out_policy = data->fwd_out_policies,
.refcount = 1,
.proposals = linked_list_create(),
.my_ts = linked_list_create(),
diff --git a/src/libcharon/config/child_cfg.h b/src/libcharon/config/child_cfg.h
index b85bfd9bc..a102c459c 100644
--- a/src/libcharon/config/child_cfg.h
+++ b/src/libcharon/config/child_cfg.h
@@ -1,6 +1,6 @@
/*
+ * Copyright (C) 2008-2017 Tobias Brunner
* Copyright (C) 2016 Andreas Steffen
- * Copyright (C) 2008-2016 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
@@ -25,6 +25,7 @@
#define CHILD_CFG_H_
typedef enum action_t action_t;
+typedef enum child_cfg_option_t child_cfg_option_t;
typedef struct child_cfg_t child_cfg_t;
typedef struct child_cfg_create_t child_cfg_create_t;
@@ -147,13 +148,6 @@ struct child_cfg_t {
char* (*get_updown)(child_cfg_t *this);
/**
- * Should we allow access to the local host (gateway)?
- *
- * @return value of hostaccess flag
- */
- bool (*get_hostaccess) (child_cfg_t *this);
-
- /**
* Get the lifetime configuration of a CHILD_SA.
*
* The rekey limits automatically contain a jitter to avoid simultaneous
@@ -203,14 +197,6 @@ struct child_cfg_t {
diffie_hellman_group_t (*get_dh_group)(child_cfg_t *this);
/**
- * Check whether IPComp should be used, if the other peer supports it.
- *
- * @return TRUE, if IPComp should be used
- * FALSE, otherwise
- */
- bool (*use_ipcomp)(child_cfg_t *this);
-
- /**
* Get the inactivity timeout value.
*
* @return inactivity timeout in s
@@ -263,33 +249,17 @@ struct child_cfg_t {
/**
* Set anti-replay window size
*
- * @param window anti-replay window size
+ * @param window anti-replay window size
*/
void (*set_replay_window)(child_cfg_t *this, uint32_t window);
/**
- * Check whether IPsec transport SA should be set up in proxy mode.
- *
- * @return TRUE, if proxy mode should be used
- * FALSE, otherwise
- */
- bool (*use_proxy_mode)(child_cfg_t *this);
-
- /**
- * Check whether IPsec policies should be installed in the kernel.
- *
- * @return TRUE, if IPsec kernel policies should be installed
- * FALSE, otherwise
- */
- bool (*install_policy)(child_cfg_t *this);
-
- /**
- * Check whether outbound FWD IPsec policies should be installed.
+ * Check if an option flag is set.
*
- * @return TRUE, if outbound FWD policies should be installed
- * FALSE, otherwise
+ * @param option option flag to check
+ * @return TRUE if option flag set, FALSE otherwise
*/
- bool (*install_fwd_out_policy)(child_cfg_t *this);
+ bool (*has_option)(child_cfg_t *this, child_cfg_option_t option);
/**
* Check if two child_cfg objects are equal.
@@ -315,11 +285,39 @@ struct child_cfg_t {
void (*destroy) (child_cfg_t *this);
};
+/**
+ * Option flags that may be set on a child_cfg_t object
+ */
+enum child_cfg_option_t {
+
+ /** Use IPsec transport proxy mode */
+ OPT_PROXY_MODE = (1<<0),
+
+ /** Use IPComp, if peer supports it */
+ OPT_IPCOMP = (1<<1),
+
+ /** Allow access to the local host */
+ OPT_HOSTACCESS = (1<<2),
+
+ /** Don't install any IPsec policies */
+ OPT_NO_POLICIES = (1<<3),
+
+ /** Install outbound FWD IPsec policies to bypass drop policies */
+ OPT_FWD_OUT_POLICIES = (1<<4),
+
+ /** Enable hardware offload, if supported by the IPsec backend */
+ OPT_HW_OFFLOAD = (1<<5),
+
+ /** Force 96-bit truncation for SHA-256 */
+ OPT_SHA256_96 = (1<<6),
+};
/**
* Data passed to the constructor of a child_cfg_t object.
*/
struct child_cfg_create_t {
+ /** Options set for CHILD_SA */
+ child_cfg_option_t options;
/** Specific reqid to use for CHILD_SA, 0 for auto assignment */
uint32_t reqid;
/** Optional inbound mark */
@@ -328,10 +326,6 @@ struct child_cfg_create_t {
mark_t mark_out;
/** Mode to propose for CHILD_SA */
ipsec_mode_t mode;
- /** Use IPsec transport proxy mode */
- bool proxy_mode;
- /** Use IPComp, if peer supports it */
- bool ipcomp;
/** TFC padding size, 0 to disable, -1 to pad to PMTU */
uint32_t tfc;
/** Optional manually-set IPsec policy priority */
@@ -350,12 +344,6 @@ struct child_cfg_create_t {
action_t close_action;
/** updown script to execute on up/down event (cloned) */
char *updown;
- /** TRUE to allow access to the local host */
- bool hostaccess;
- /** Don't install IPsec policies */
- bool suppress_policies;
- /** Install outbound FWD IPsec policies to bypass drop policies */
- bool fwd_out_policies;
};
/**
diff --git a/src/libcharon/config/ike_cfg.c b/src/libcharon/config/ike_cfg.c
index 480dd3720..93300781d 100644
--- a/src/libcharon/config/ike_cfg.c
+++ b/src/libcharon/config/ike_cfg.c
@@ -224,12 +224,12 @@ static u_int match(linked_list_t *hosts, linked_list_t *ranges, host_t *cand)
if (ts->to_subnet(ts, &host, &mask))
{
quality = max(quality, mask + 1);
- host->destroy(host);
}
else
{
quality = max(quality, 1);
}
+ host->destroy(host);
}
}
enumerator->destroy(enumerator);
diff --git a/src/libcharon/config/ike_cfg.h b/src/libcharon/config/ike_cfg.h
index 4d37264f6..034996f60 100644
--- a/src/libcharon/config/ike_cfg.h
+++ b/src/libcharon/config/ike_cfg.h
@@ -47,14 +47,16 @@ enum ike_version_t {
};
/**
- * Proprietary IKEv1 fragmentation
+ * Proprietary IKEv1 fragmentation and IKEv2 fragmentation
*/
enum fragmentation_t {
/** disable fragmentation */
FRAGMENTATION_NO,
- /** enable fragmentation if supported by peer */
+ /** announce support, but don't send any fragments */
+ FRAGMENTATION_ACCEPT,
+ /** enable fragmentation, if supported by peer */
FRAGMENTATION_YES,
- /** force use of fragmentation (even for the first message) */
+ /** force use of fragmentation (even for the first message for IKEv1) */
FRAGMENTATION_FORCE,
};
diff --git a/src/libcharon/config/peer_cfg.c b/src/libcharon/config/peer_cfg.c
index 5d7ab076e..fcdd6fdeb 100644
--- a/src/libcharon/config/peer_cfg.c
+++ b/src/libcharon/config/peer_cfg.c
@@ -209,9 +209,12 @@ typedef struct {
} child_cfgs_replace_enumerator_t;
METHOD(enumerator_t, child_cfgs_replace_enumerate, bool,
- child_cfgs_replace_enumerator_t *this, child_cfg_t **chd, bool *added)
+ child_cfgs_replace_enumerator_t *this, va_list args)
{
- child_cfg_t *child_cfg;
+ child_cfg_t *child_cfg, **chd;
+ bool *added;
+
+ VA_ARGS_VGET(args, chd, added);
if (!this->wrapped)
{
@@ -303,8 +306,9 @@ METHOD(peer_cfg_t, replace_child_cfgs, enumerator_t*,
INIT(enumerator,
.public = {
- .enumerate = (void*)_child_cfgs_replace_enumerate,
- .destroy = (void*)_child_cfgs_replace_enumerator_destroy,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _child_cfgs_replace_enumerate,
+ .destroy = _child_cfgs_replace_enumerator_destroy,
},
.removed = removed,
.added = added,
@@ -336,8 +340,11 @@ METHOD(enumerator_t, child_cfg_enumerator_destroy, void,
}
METHOD(enumerator_t, child_cfg_enumerate, bool,
- child_cfg_enumerator_t *this, child_cfg_t **chd)
+ child_cfg_enumerator_t *this, va_list args)
{
+ child_cfg_t **chd;
+
+ VA_ARGS_VGET(args, chd);
return this->wrapped->enumerate(this->wrapped, chd);
}
@@ -348,8 +355,9 @@ METHOD(peer_cfg_t, create_child_cfg_enumerator, enumerator_t*,
INIT(enumerator,
.public = {
- .enumerate = (void*)_child_cfg_enumerate,
- .destroy = (void*)_child_cfg_enumerator_destroy,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _child_cfg_enumerate,
+ .destroy = _child_cfg_enumerator_destroy,
},
.mutex = this->mutex,
.wrapped = this->child_cfgs->create_enumerator(this->child_cfgs),
diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c
index a2dc113a5..6c71f78d3 100644
--- a/src/libcharon/config/proposal.c
+++ b/src/libcharon/config/proposal.c
@@ -94,27 +94,31 @@ METHOD(proposal_t, add_algorithm, void,
array_insert(this->transforms, ARRAY_TAIL, &entry);
}
-/**
- * filter function for peer configs
- */
-static bool alg_filter(uintptr_t type, entry_t **in, uint16_t *alg,
- void **unused, uint16_t *key_size)
+CALLBACK(alg_filter, bool,
+ uintptr_t type, enumerator_t *orig, va_list args)
{
- entry_t *entry = *in;
+ entry_t *entry;
+ uint16_t *alg, *key_size;
- if (entry->type != type)
- {
- return FALSE;
- }
- if (alg)
- {
- *alg = entry->alg;
- }
- if (key_size)
+ VA_ARGS_VGET(args, alg, key_size);
+
+ while (orig->enumerate(orig, &entry))
{
- *key_size = entry->key_size;
+ if (entry->type != type)
+ {
+ continue;
+ }
+ if (alg)
+ {
+ *alg = entry->alg;
+ }
+ if (key_size)
+ {
+ *key_size = entry->key_size;
+ }
+ return TRUE;
}
- return TRUE;
+ return FALSE;
}
METHOD(proposal_t, create_enumerator, enumerator_t*,
@@ -122,7 +126,7 @@ METHOD(proposal_t, create_enumerator, enumerator_t*,
{
return enumerator_create_filter(
array_create_enumerator(this->transforms),
- (void*)alg_filter, (void*)(uintptr_t)type, NULL);
+ alg_filter, (void*)(uintptr_t)type, NULL);
}
METHOD(proposal_t, get_algorithm, bool,
diff --git a/src/libcharon/daemon.c b/src/libcharon/daemon.c
index eadc10a6a..7c9f83d12 100644
--- a/src/libcharon/daemon.c
+++ b/src/libcharon/daemon.c
@@ -118,6 +118,13 @@ struct private_daemon_t {
};
/**
+ * Register plugins if built statically
+ */
+#ifdef STATIC_PLUGIN_CONSTRUCTORS
+#include "plugin_constructors.c"
+#endif
+
+/**
* One and only instance of the daemon.
*/
daemon_t *charon;
@@ -275,13 +282,14 @@ static void logger_entry_unregister_destroy(logger_entry_t *this)
logger_entry_destroy(this);
}
-/**
- * Match a logger entry by target and whether it is a file or syslog logger
- */
-static bool logger_entry_match(logger_entry_t *this, char *target,
- logger_type_t *type)
+CALLBACK(logger_entry_match, bool,
+ logger_entry_t *this, va_list args)
{
- return this->type == *type && streq(this->target, target);
+ logger_type_t type;
+ char *target;
+
+ VA_ARGS_VGET(args, target, type);
+ return this->type == type && streq(this->target, target);
}
/**
@@ -343,8 +351,8 @@ static logger_entry_t *get_logger_entry(char *target, logger_type_t type,
{
logger_entry_t *entry;
- if (existing->find_first(existing, (void*)logger_entry_match,
- (void**)&entry, target, &type) != SUCCESS)
+ if (!existing->find_first(existing, logger_entry_match, (void**)&entry,
+ target, type))
{
INIT(entry,
.target = strdup(target),
diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c
index 50dab9e38..6d850aac0 100644
--- a/src/libcharon/encoding/message.c
+++ b/src/libcharon/encoding/message.c
@@ -554,10 +554,10 @@ static payload_order_t aggressive_i_order[] = {
{PLV1_CERTREQ, 0},
{PLV1_NOTIFY, 0},
{PLV1_VENDOR_ID, 0},
+ {PLV1_HASH, 0},
{PLV1_NAT_D, 0},
{PLV1_NAT_D_DRAFT_00_03, 0},
{PLV1_SIGNATURE, 0},
- {PLV1_HASH, 0},
{PLV1_FRAGMENT, 0},
};
diff --git a/src/libcharon/encoding/payloads/certreq_payload.c b/src/libcharon/encoding/payloads/certreq_payload.c
index 09bfa2458..643fbc42f 100644
--- a/src/libcharon/encoding/payloads/certreq_payload.c
+++ b/src/libcharon/encoding/payloads/certreq_payload.c
@@ -190,8 +190,12 @@ struct keyid_enumerator_t {
};
METHOD(enumerator_t, keyid_enumerate, bool,
- keyid_enumerator_t *this, chunk_t *chunk)
+ keyid_enumerator_t *this, va_list args)
{
+ chunk_t *chunk;
+
+ VA_ARGS_VGET(args, chunk);
+
if (this->pos == NULL)
{
this->pos = this->full.ptr;
@@ -224,7 +228,8 @@ METHOD(certreq_payload_t, create_keyid_enumerator, enumerator_t*,
}
INIT(enumerator,
.public = {
- .enumerate = (void*)_keyid_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _keyid_enumerate,
.destroy = (void*)free,
},
.full = this->data,
diff --git a/src/libcharon/encoding/payloads/delete_payload.c b/src/libcharon/encoding/payloads/delete_payload.c
index 584e6f22b..3634cd36c 100644
--- a/src/libcharon/encoding/payloads/delete_payload.c
+++ b/src/libcharon/encoding/payloads/delete_payload.c
@@ -306,8 +306,12 @@ typedef struct {
} spi_enumerator_t;
METHOD(enumerator_t, spis_enumerate, bool,
- spi_enumerator_t *this, uint32_t *spi)
+ spi_enumerator_t *this, va_list args)
{
+ uint32_t *spi;
+
+ VA_ARGS_VGET(args, spi);
+
if (this->spis.len >= sizeof(*spi))
{
memcpy(spi, this->spis.ptr, sizeof(*spi));
@@ -328,7 +332,8 @@ METHOD(delete_payload_t, create_spi_enumerator, enumerator_t*,
}
INIT(e,
.public = {
- .enumerate = (void*)_spis_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _spis_enumerate,
.destroy = (void*)free,
},
.spis = this->spis,
diff --git a/src/libcharon/encoding/payloads/eap_payload.c b/src/libcharon/encoding/payloads/eap_payload.c
index 8c3fc5933..923135da9 100644
--- a/src/libcharon/encoding/payloads/eap_payload.c
+++ b/src/libcharon/encoding/payloads/eap_payload.c
@@ -270,8 +270,12 @@ typedef struct {
} type_enumerator_t;
METHOD(enumerator_t, enumerate_types, bool,
- type_enumerator_t *this, eap_type_t *type, uint32_t *vendor)
+ type_enumerator_t *this, va_list args)
{
+ eap_type_t *type;
+ uint32_t *vendor;
+
+ VA_ARGS_VGET(args, type, vendor);
this->offset = extract_type(this->payload, this->offset, type, vendor);
return this->offset;
}
@@ -289,7 +293,8 @@ METHOD(eap_payload_t, get_types, enumerator_t*,
{
INIT(enumerator,
.public = {
- .enumerate = (void*)_enumerate_types,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _enumerate_types,
.destroy = (void*)free,
},
.payload = this,
diff --git a/src/libcharon/kernel/kernel_interface.c b/src/libcharon/kernel/kernel_interface.c
index ea5af9eb8..3d736b25b 100644
--- a/src/libcharon/kernel/kernel_interface.c
+++ b/src/libcharon/kernel/kernel_interface.c
@@ -632,21 +632,18 @@ METHOD(kernel_interface_t, enable_udp_decap, bool,
METHOD(kernel_interface_t, is_interface_usable, bool,
private_kernel_interface_t *this, const char *iface)
{
- status_t expected;
-
if (!this->ifaces_filter)
{
return TRUE;
}
- expected = this->ifaces_exclude ? NOT_FOUND : SUCCESS;
- return this->ifaces_filter->find_first(this->ifaces_filter, (void*)streq,
- NULL, iface) == expected;
+ return this->ifaces_filter->find_first(this->ifaces_filter,
+ linked_list_match_str, NULL, iface) != this->ifaces_exclude;
}
METHOD(kernel_interface_t, all_interfaces_usable, bool,
private_kernel_interface_t *this)
{
- return this->ifaces_filter == NULL;
+ return !this->ifaces_filter;
}
METHOD(kernel_interface_t, get_address_by_ts, status_t,
diff --git a/src/libcharon/kernel/kernel_ipsec.h b/src/libcharon/kernel/kernel_ipsec.h
index 0ad566068..6fafeb760 100644
--- a/src/libcharon/kernel/kernel_ipsec.h
+++ b/src/libcharon/kernel/kernel_ipsec.h
@@ -91,6 +91,8 @@ struct kernel_ipsec_add_sa_t {
uint16_t cpi;
/** TRUE to enable UDP encapsulation for NAT traversal */
bool encap;
+ /** TRUE to enable hardware offloading if available */
+ bool hw_offload;
/** TRUE to use Extended Sequence Numbers */
bool esn;
/** TRUE if initiator of the exchange creating the SA */
diff --git a/src/libcharon/network/receiver.c b/src/libcharon/network/receiver.c
index 1bf93ad40..8fb48281f 100644
--- a/src/libcharon/network/receiver.c
+++ b/src/libcharon/network/receiver.c
@@ -321,18 +321,16 @@ static bool cookie_required(private_receiver_t *this,
*/
static bool drop_ike_sa_init(private_receiver_t *this, message_t *message)
{
- u_int half_open, half_open_r;
+ u_int half_open;
uint32_t now;
now = time_monotonic(NULL);
half_open = charon->ike_sa_manager->get_half_open_count(
- charon->ike_sa_manager, NULL, FALSE);
- half_open_r = charon->ike_sa_manager->get_half_open_count(
charon->ike_sa_manager, NULL, TRUE);
/* check for cookies in IKEv2 */
if (message->get_major_version(message) == IKEV2_MAJOR_VERSION &&
- cookie_required(this, half_open_r, now) && !check_cookie(this, message))
+ cookie_required(this, half_open, now) && !check_cookie(this, message))
{
chunk_t cookie;
diff --git a/src/libcharon/plugins/addrblock/Makefile.in b/src/libcharon/plugins/addrblock/Makefile.in
index f5dfc14d7..60fd19bdc 100644
--- a/src/libcharon/plugins/addrblock/Makefile.in
+++ b/src/libcharon/plugins/addrblock/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/addrblock/addrblock_validator.c b/src/libcharon/plugins/addrblock/addrblock_validator.c
index d16a1170c..78e377c2a 100644
--- a/src/libcharon/plugins/addrblock/addrblock_validator.c
+++ b/src/libcharon/plugins/addrblock/addrblock_validator.c
@@ -56,12 +56,12 @@ static bool check_addrblock(private_addrblock_validator_t *this,
}
if (!subject_const)
{
- DBG1(DBG_CFG, "subject certficate lacks ipAddrBlocks extension");
+ DBG1(DBG_CFG, "subject certificate lacks ipAddrBlocks extension");
return !this->strict;
}
if (!issuer_const)
{
- DBG1(DBG_CFG, "issuer certficate lacks ipAddrBlocks extension");
+ DBG1(DBG_CFG, "issuer certificate lacks ipAddrBlocks extension");
return FALSE;
}
subject_enumerator = subject->create_ipAddrBlock_enumerator(subject);
diff --git a/src/libcharon/plugins/android_dns/Makefile.in b/src/libcharon/plugins/android_dns/Makefile.in
index d79c753f0..0533d81eb 100644
--- a/src/libcharon/plugins/android_dns/Makefile.in
+++ b/src/libcharon/plugins/android_dns/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/android_dns/android_dns_handler.c b/src/libcharon/plugins/android_dns/android_dns_handler.c
index 160a145d3..68bbaecb2 100644
--- a/src/libcharon/plugins/android_dns/android_dns_handler.c
+++ b/src/libcharon/plugins/android_dns/android_dns_handler.c
@@ -182,12 +182,15 @@ METHOD(attribute_handler_t, release, void,
}
METHOD(enumerator_t, enumerate_dns, bool,
- enumerator_t *this, configuration_attribute_type_t *type, chunk_t *data)
+ enumerator_t *this, va_list args)
{
+ configuration_attribute_type_t *type;
+ chunk_t *data;
+
+ VA_ARGS_VGET(args, type, data);
*type = INTERNAL_IP4_DNS;
*data = chunk_empty;
- /* stop enumeration */
- this->enumerate = (void*)return_false;
+ this->venumerate = return_false;
return TRUE;
}
@@ -198,7 +201,8 @@ METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *,
enumerator_t *enumerator;
INIT(enumerator,
- .enumerate = (void*)_enumerate_dns,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _enumerate_dns,
.destroy = (void*)free,
);
return enumerator;
diff --git a/src/libcharon/plugins/android_log/Makefile.am b/src/libcharon/plugins/android_log/Makefile.am
index 9f82f6e60..4f062ee65 100644
--- a/src/libcharon/plugins/android_log/Makefile.am
+++ b/src/libcharon/plugins/android_log/Makefile.am
@@ -16,3 +16,4 @@ libstrongswan_android_log_la_SOURCES = \
android_log_logger.c android_log_logger.h
libstrongswan_android_log_la_LDFLAGS = -module -avoid-version
+libstrongswan_android_log_la_LIBADD = -llog
diff --git a/src/libcharon/plugins/android_log/Makefile.in b/src/libcharon/plugins/android_log/Makefile.in
index 65cdcff94..bc402ef69 100644
--- a/src/libcharon/plugins/android_log/Makefile.in
+++ b/src/libcharon/plugins/android_log/Makefile.in
@@ -136,7 +136,7 @@ am__uninstall_files_from_dir = { \
}
am__installdirs = "$(DESTDIR)$(plugindir)"
LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
-libstrongswan_android_log_la_LIBADD =
+libstrongswan_android_log_la_DEPENDENCIES =
am_libstrongswan_android_log_la_OBJECTS = android_log_plugin.lo \
android_log_logger.lo
libstrongswan_android_log_la_OBJECTS = \
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
@@ -458,6 +460,7 @@ libstrongswan_android_log_la_SOURCES = \
android_log_logger.c android_log_logger.h
libstrongswan_android_log_la_LDFLAGS = -module -avoid-version
+libstrongswan_android_log_la_LIBADD = -llog
all: all-am
.SUFFIXES:
diff --git a/src/libcharon/plugins/attr/Makefile.in b/src/libcharon/plugins/attr/Makefile.in
index 217a42ae6..9fe4d946f 100644
--- a/src/libcharon/plugins/attr/Makefile.in
+++ b/src/libcharon/plugins/attr/Makefile.in
@@ -355,6 +355,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -377,6 +378,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/attr/attr_provider.c b/src/libcharon/plugins/attr/attr_provider.c
index f4c143641..3310f79fd 100644
--- a/src/libcharon/plugins/attr/attr_provider.c
+++ b/src/libcharon/plugins/attr/attr_provider.c
@@ -75,17 +75,23 @@ typedef struct {
ike_version_t ike;
} enumerator_data_t;
-/**
- * convert enumerator value from attribute_entry
- */
-static bool attr_enum_filter(enumerator_data_t *data, attribute_entry_t **in,
- configuration_attribute_type_t *type, void* none, chunk_t *value)
+CALLBACK(attr_enum_filter, bool,
+ enumerator_data_t *data, enumerator_t *orig, va_list args)
{
- if ((*in)->ike == IKE_ANY || (*in)->ike == data->ike)
+ configuration_attribute_type_t *type;
+ attribute_entry_t *entry;
+ chunk_t *value;
+
+ VA_ARGS_VGET(args, type, value);
+
+ while (orig->enumerate(orig, &entry))
{
- *type = (*in)->type;
- *value = (*in)->value;
- return TRUE;
+ if (entry->ike == IKE_ANY || entry->ike == data->ike)
+ {
+ *type = entry->type;
+ *value = entry->value;
+ return TRUE;
+ }
}
return FALSE;
}
@@ -112,7 +118,7 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
this->lock->read_lock(this->lock);
return enumerator_create_filter(
this->attributes->create_enumerator(this->attributes),
- (void*)attr_enum_filter, data, attr_enum_destroy);
+ attr_enum_filter, data, attr_enum_destroy);
}
return enumerator_create_empty();
}
diff --git a/src/libcharon/plugins/attr_sql/Makefile.in b/src/libcharon/plugins/attr_sql/Makefile.in
index 668e23f07..b3ddf69b5 100644
--- a/src/libcharon/plugins/attr_sql/Makefile.in
+++ b/src/libcharon/plugins/attr_sql/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/attr_sql/attr_sql_provider.c b/src/libcharon/plugins/attr_sql/attr_sql_provider.c
index c2410705d..33d9f99fc 100644
--- a/src/libcharon/plugins/attr_sql/attr_sql_provider.c
+++ b/src/libcharon/plugins/attr_sql/attr_sql_provider.c
@@ -200,7 +200,6 @@ static host_t* get_lease(private_attr_sql_provider_t *this, char *name,
"SELECT id, address FROM addresses "
"WHERE pool = ? AND identity = 0 LIMIT 1",
DB_UINT, pool, DB_UINT, DB_BLOB);
-
}
if (!e || !e->enumerate(e, &id, &address))
@@ -447,7 +446,6 @@ METHOD(attr_sql_provider_t, destroy, void,
attr_sql_provider_t *attr_sql_provider_create(database_t *db)
{
private_attr_sql_provider_t *this;
- time_t now = time(NULL);
INIT(this,
.public = {
@@ -460,19 +458,25 @@ attr_sql_provider_t *attr_sql_provider_create(database_t *db)
},
.db = db,
.history = lib->settings->get_bool(lib->settings,
- "%s.plugins.attr-sql.lease_history", TRUE, lib->ns),
+ "%s.plugins.attr-sql.lease_history", TRUE, lib->ns),
);
- /* close any "online" leases in the case we crashed */
- if (this->history)
+ if (lib->settings->get_bool(lib->settings,
+ "%s.plugins.attr-sql.crash_recovery", TRUE, lib->ns))
{
- this->db->execute(this->db, NULL,
+ time_t now = time(NULL);
+
+ /* close any "online" leases in the case we crashed */
+ if (this->history)
+ {
+ this->db->execute(this->db, NULL,
"INSERT INTO leases (address, identity, acquired, released)"
" SELECT id, identity, acquired, ? FROM addresses "
" WHERE released = 0", DB_UINT, now);
- }
- this->db->execute(this->db, NULL,
+ }
+ this->db->execute(this->db, NULL,
"UPDATE addresses SET released = ? WHERE released = 0",
DB_UINT, now);
+ }
return &this->public;
}
diff --git a/src/libcharon/plugins/bypass_lan/Makefile.in b/src/libcharon/plugins/bypass_lan/Makefile.in
index 9f1dc71c9..6c079481b 100644
--- a/src/libcharon/plugins/bypass_lan/Makefile.in
+++ b/src/libcharon/plugins/bypass_lan/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/bypass_lan/bypass_lan_listener.c b/src/libcharon/plugins/bypass_lan/bypass_lan_listener.c
index e690028f2..644cff029 100644
--- a/src/libcharon/plugins/bypass_lan/bypass_lan_listener.c
+++ b/src/libcharon/plugins/bypass_lan/bypass_lan_listener.c
@@ -110,15 +110,12 @@ static bool policy_equals(bypass_policy_t *a, bypass_policy_t *b)
*/
static bool consider_interface(private_bypass_lan_listener_t *this, char *iface)
{
- status_t expected;
-
if (!iface || !this->ifaces_filter)
{
return TRUE;
}
- expected = this->ifaces_exclude ? NOT_FOUND : SUCCESS;
- return this->ifaces_filter->find_first(this->ifaces_filter, (void*)streq,
- NULL, iface) == expected;
+ return this->ifaces_filter->find_first(this->ifaces_filter,
+ linked_list_match_str, NULL, iface) != this->ifaces_exclude;
}
/**
diff --git a/src/libcharon/plugins/certexpire/Makefile.in b/src/libcharon/plugins/certexpire/Makefile.in
index ffde2d7aa..acbd7a858 100644
--- a/src/libcharon/plugins/certexpire/Makefile.in
+++ b/src/libcharon/plugins/certexpire/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/connmark/Makefile.in b/src/libcharon/plugins/connmark/Makefile.in
index 140f1b6ad..55bc25a9f 100644
--- a/src/libcharon/plugins/connmark/Makefile.in
+++ b/src/libcharon/plugins/connmark/Makefile.in
@@ -359,6 +359,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -381,6 +382,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/coupling/Makefile.in b/src/libcharon/plugins/coupling/Makefile.in
index 3910e4ea4..6d6fe25bb 100644
--- a/src/libcharon/plugins/coupling/Makefile.in
+++ b/src/libcharon/plugins/coupling/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/dhcp/Makefile.in b/src/libcharon/plugins/dhcp/Makefile.in
index 6033c6e12..d3f4ec8bc 100644
--- a/src/libcharon/plugins/dhcp/Makefile.in
+++ b/src/libcharon/plugins/dhcp/Makefile.in
@@ -356,6 +356,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -378,6 +379,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/dhcp/dhcp_provider.c b/src/libcharon/plugins/dhcp/dhcp_provider.c
index f0681b1da..50ffbab9d 100644
--- a/src/libcharon/plugins/dhcp/dhcp_provider.c
+++ b/src/libcharon/plugins/dhcp/dhcp_provider.c
@@ -151,8 +151,7 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
identification_t *id;
host_t *vip;
- if (pools->find_first(pools, (linked_list_match_t)streq,
- NULL, "dhcp") != SUCCESS)
+ if (!pools->find_first(pools, linked_list_match_str, NULL, "dhcp"))
{
return NULL;
}
diff --git a/src/libcharon/plugins/dhcp/dhcp_socket.c b/src/libcharon/plugins/dhcp/dhcp_socket.c
index 807c68274..42f8f1ef9 100644
--- a/src/libcharon/plugins/dhcp/dhcp_socket.c
+++ b/src/libcharon/plugins/dhcp/dhcp_socket.c
@@ -382,8 +382,7 @@ METHOD(dhcp_socket_t, enroll, dhcp_transaction_t*,
while (try <= DHCP_TRIES && discover(this, transaction))
{
if (!this->condvar->timed_wait(this->condvar, this->mutex, 1000 * try) &&
- this->request->find_first(this->request, NULL,
- (void**)&transaction) == SUCCESS)
+ this->request->find_first(this->request, NULL, (void**)&transaction))
{
break;
}
diff --git a/src/libcharon/plugins/dhcp/dhcp_transaction.c b/src/libcharon/plugins/dhcp/dhcp_transaction.c
index 3ee88a698..87711799c 100644
--- a/src/libcharon/plugins/dhcp/dhcp_transaction.c
+++ b/src/libcharon/plugins/dhcp/dhcp_transaction.c
@@ -114,16 +114,22 @@ METHOD(dhcp_transaction_t, add_attribute, void,
this->attributes->insert_last(this->attributes, entry);
}
-/**
- * Filter function to map entries to type/data
- */
-static bool attribute_filter(void *null, attribute_entry_t **entry,
- configuration_attribute_type_t *type,
- void **dummy, chunk_t *data)
+CALLBACK(attribute_filter, bool,
+ void *null, enumerator_t *orig, va_list args)
{
- *type = (*entry)->type;
- *data = (*entry)->data;
- return TRUE;
+ configuration_attribute_type_t *type;
+ attribute_entry_t *entry;
+ chunk_t *data;
+
+ VA_ARGS_VGET(args, type, data);
+
+ if (orig->enumerate(orig, &entry))
+ {
+ *type = entry->type;
+ *data = entry->data;
+ return TRUE;
+ }
+ return FALSE;
}
METHOD(dhcp_transaction_t, create_attribute_enumerator, enumerator_t*,
@@ -131,7 +137,7 @@ METHOD(dhcp_transaction_t, create_attribute_enumerator, enumerator_t*,
{
return enumerator_create_filter(
this->attributes->create_enumerator(this->attributes),
- (void*)attribute_filter, NULL, NULL);
+ attribute_filter, NULL, NULL);
}
/**
diff --git a/src/libcharon/plugins/dnscert/Makefile.in b/src/libcharon/plugins/dnscert/Makefile.in
index cd66af8c8..3687f0cb7 100644
--- a/src/libcharon/plugins/dnscert/Makefile.in
+++ b/src/libcharon/plugins/dnscert/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/dnscert/dnscert_cred.c b/src/libcharon/plugins/dnscert/dnscert_cred.c
index d32794c99..533bd5be4 100644
--- a/src/libcharon/plugins/dnscert/dnscert_cred.c
+++ b/src/libcharon/plugins/dnscert/dnscert_cred.c
@@ -75,12 +75,15 @@ typedef struct {
} cert_enumerator_t;
METHOD(enumerator_t, cert_enumerator_enumerate, bool,
- cert_enumerator_t *this, certificate_t **cert)
+ cert_enumerator_t *this, va_list args)
{
+ certificate_t **cert;
dnscert_t *cur_crt;
rr_t *cur_rr;
chunk_t certificate;
+ VA_ARGS_VGET(args, cert);
+
/* Get the next supported CERT using the inner enumerator. */
while (this->inner->enumerate(this->inner, &cur_rr))
{
@@ -175,7 +178,8 @@ METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
INIT(e,
.public = {
- .enumerate = (void*)_cert_enumerator_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _cert_enumerator_enumerate,
.destroy = _cert_enumerator_destroy,
},
.inner = response->get_rr_set(response)->create_rr_enumerator(
diff --git a/src/libcharon/plugins/duplicheck/Makefile.in b/src/libcharon/plugins/duplicheck/Makefile.in
index e4b60e6ad..69959d30f 100644
--- a/src/libcharon/plugins/duplicheck/Makefile.in
+++ b/src/libcharon/plugins/duplicheck/Makefile.in
@@ -365,6 +365,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -387,6 +388,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/eap_aka/Makefile.in b/src/libcharon/plugins/eap_aka/Makefile.in
index 20c0ddb8f..5fff12890 100644
--- a/src/libcharon/plugins/eap_aka/Makefile.in
+++ b/src/libcharon/plugins/eap_aka/Makefile.in
@@ -359,6 +359,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -381,6 +382,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
index f4fb8ec42..478225562 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
+++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
@@ -360,6 +360,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -382,6 +383,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/eap_dynamic/Makefile.in b/src/libcharon/plugins/eap_dynamic/Makefile.in
index 2dbc05f02..2591dee55 100644
--- a/src/libcharon/plugins/eap_dynamic/Makefile.in
+++ b/src/libcharon/plugins/eap_dynamic/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/eap_dynamic/eap_dynamic.c b/src/libcharon/plugins/eap_dynamic/eap_dynamic.c
index 83ccd3a8a..204fb317d 100644
--- a/src/libcharon/plugins/eap_dynamic/eap_dynamic.c
+++ b/src/libcharon/plugins/eap_dynamic/eap_dynamic.c
@@ -69,6 +69,15 @@ static bool entry_matches(eap_vendor_type_t *item, eap_vendor_type_t *other)
return item->type == other->type && item->vendor == other->vendor;
}
+CALLBACK(entry_matches_cb, bool,
+ eap_vendor_type_t *item, va_list args)
+{
+ eap_vendor_type_t *other;
+
+ VA_ARGS_VGET(args, other);
+ return entry_matches(item, other);
+}
+
/**
* Load the given EAP method
*/
@@ -121,8 +130,7 @@ static void select_method(private_eap_dynamic_t *this)
{
if (inner)
{
- if (inner->find_first(inner, (void*)entry_matches,
- NULL, entry) != SUCCESS)
+ if (!inner->find_first(inner, entry_matches_cb, NULL, entry))
{
if (entry->vendor)
{
diff --git a/src/libcharon/plugins/eap_gtc/Makefile.in b/src/libcharon/plugins/eap_gtc/Makefile.in
index 01d509ebd..08d8ef8f6 100644
--- a/src/libcharon/plugins/eap_gtc/Makefile.in
+++ b/src/libcharon/plugins/eap_gtc/Makefile.in
@@ -357,6 +357,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -379,6 +380,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/eap_identity/Makefile.in b/src/libcharon/plugins/eap_identity/Makefile.in
index cc1f21eed..4859833ba 100644
--- a/src/libcharon/plugins/eap_identity/Makefile.in
+++ b/src/libcharon/plugins/eap_identity/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/eap_md5/Makefile.in b/src/libcharon/plugins/eap_md5/Makefile.in
index 939bbf942..796d42f14 100644
--- a/src/libcharon/plugins/eap_md5/Makefile.in
+++ b/src/libcharon/plugins/eap_md5/Makefile.in
@@ -357,6 +357,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -379,6 +380,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.in b/src/libcharon/plugins/eap_mschapv2/Makefile.in
index 1e1936c45..00a9f73da 100644
--- a/src/libcharon/plugins/eap_mschapv2/Makefile.in
+++ b/src/libcharon/plugins/eap_mschapv2/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/eap_peap/Makefile.in b/src/libcharon/plugins/eap_peap/Makefile.in
index b83a80f73..df3c2eae2 100644
--- a/src/libcharon/plugins/eap_peap/Makefile.in
+++ b/src/libcharon/plugins/eap_peap/Makefile.in
@@ -359,6 +359,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -381,6 +382,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/eap_radius/Makefile.in b/src/libcharon/plugins/eap_radius/Makefile.in
index 29a2f3898..d8ebeb8b5 100644
--- a/src/libcharon/plugins/eap_radius/Makefile.in
+++ b/src/libcharon/plugins/eap_radius/Makefile.in
@@ -360,6 +360,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -382,6 +383,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_provider.c b/src/libcharon/plugins/eap_radius/eap_radius_provider.c
index 9a87ad38d..58bbc2edd 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_provider.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_provider.c
@@ -404,11 +404,13 @@ typedef struct {
attr_t *current;
} attribute_enumerator_t;
-
METHOD(enumerator_t, attribute_enumerate, bool,
- attribute_enumerator_t *this, configuration_attribute_type_t *type,
- chunk_t *data)
+ attribute_enumerator_t *this, va_list args)
{
+ configuration_attribute_type_t *type;
+ chunk_t *data;
+
+ VA_ARGS_VGET(args, type, data);
if (this->current)
{
destroy_attr(this->current);
@@ -446,7 +448,8 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
INIT(enumerator,
.public = {
- .enumerate = (void*)_attribute_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _attribute_enumerate,
.destroy = _attribute_destroy,
},
.list = linked_list_create(),
diff --git a/src/libcharon/plugins/eap_sim/Makefile.in b/src/libcharon/plugins/eap_sim/Makefile.in
index b4abce9b3..6c2584ae4 100644
--- a/src/libcharon/plugins/eap_sim/Makefile.in
+++ b/src/libcharon/plugins/eap_sim/Makefile.in
@@ -359,6 +359,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -381,6 +382,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.in b/src/libcharon/plugins/eap_sim_file/Makefile.in
index 914c8c0be..b2473725a 100644
--- a/src/libcharon/plugins/eap_sim_file/Makefile.in
+++ b/src/libcharon/plugins/eap_sim_file/Makefile.in
@@ -360,6 +360,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -382,6 +383,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.c b/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.c
index ec1686910..03a60cfb1 100644
--- a/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.c
+++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.c
@@ -79,10 +79,8 @@ typedef struct {
private_eap_sim_file_triplets_t *this;
} triplet_enumerator_t;
-/**
- * destroy a triplet enumerator
- */
-static void enumerator_destroy(triplet_enumerator_t *e)
+METHOD(enumerator_t, enumerator_destroy, void,
+ triplet_enumerator_t *e)
{
if (e->current)
{
@@ -97,13 +95,14 @@ static void enumerator_destroy(triplet_enumerator_t *e)
free(e);
}
-/**
- * enumerate through triplets
- */
-static bool enumerator_enumerate(triplet_enumerator_t *e, identification_t **imsi,
- char **rand, char **sres, char **kc)
+METHOD(enumerator_t, enumerator_enumerate, bool,
+ triplet_enumerator_t *e, va_list args)
{
+ identification_t **imsi;
triplet_t *triplet;
+ char **rand, **sres, **kc;
+
+ VA_ARGS_VGET(args, imsi, rand, sres, kc);
if (e->inner->enumerate(e->inner, &triplet))
{
@@ -121,15 +120,18 @@ static bool enumerator_enumerate(triplet_enumerator_t *e, identification_t **ims
METHOD(eap_sim_file_triplets_t, create_enumerator, enumerator_t*,
private_eap_sim_file_triplets_t *this)
{
- triplet_enumerator_t *enumerator = malloc_thing(triplet_enumerator_t);
+ triplet_enumerator_t *enumerator;
this->mutex->lock(this->mutex);
- enumerator->public.enumerate = (void*)enumerator_enumerate;
- enumerator->public.destroy = (void*)enumerator_destroy;
- enumerator->inner = this->triplets->create_enumerator(this->triplets);
- enumerator->current = NULL;
- enumerator->this = this;
-
+ INIT(enumerator,
+ .public = {
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _enumerator_enumerate,
+ .destroy = _enumerator_destroy,
+ },
+ .inner = this->triplets->create_enumerator(this->triplets),
+ .this = this,
+ );
return &enumerator->public;
}
diff --git a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
index 48ef92136..88c31a95e 100644
--- a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
+++ b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
@@ -361,6 +361,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -383,6 +384,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
index 5f12e2e2e..62c8ca11e 100644
--- a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
@@ -361,6 +361,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -383,6 +384,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
index 45e2b7498..ef20102bb 100644
--- a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
@@ -360,6 +360,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -382,6 +383,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.in b/src/libcharon/plugins/eap_simaka_sql/Makefile.in
index 8c134cff9..c9af52fa9 100644
--- a/src/libcharon/plugins/eap_simaka_sql/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.in
@@ -359,6 +359,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -381,6 +382,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.c b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.c
index 90627b52e..0f59c5b78 100644
--- a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.c
+++ b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.c
@@ -2,6 +2,9 @@
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
*
+ * Copyright (C) 2017 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
* Free Software Foundation; either version 2 of the License, or (at your
@@ -54,7 +57,7 @@ METHOD(simaka_card_t, get_triplet, bool,
snprintf(buf, sizeof(buf), "%Y", id);
query = this->db->query(this->db,
"select sres, kc from triplets where rand = ? and id = ? "
- "order by use limit 1",
+ "order by used limit 1",
DB_BLOB, chunk_create(rand, SIM_RAND_LEN), DB_TEXT, buf,
DB_BLOB, DB_BLOB);
if (query)
@@ -82,7 +85,7 @@ METHOD(simaka_card_t, get_triplet, bool,
else
{
this->db->execute(this->db, NULL,
- "update triplets set use = ? where id = ? and rand = ?",
+ "update triplets set used = ? where id = ? and rand = ?",
DB_UINT, time(NULL), DB_TEXT, buf,
DB_BLOB, chunk_create(rand, SIM_RAND_LEN));
}
@@ -102,7 +105,7 @@ METHOD(simaka_card_t, get_quintuplet, status_t,
snprintf(buf, sizeof(buf), "%Y", id);
query = this->db->query(this->db, "select ck, ik, res from quintuplets "
- "where rand = ? and autn = ? and id = ? order by use limit 1",
+ "where rand = ? and autn = ? and id = ? order by used limit 1",
DB_BLOB, chunk_create(rand, AKA_RAND_LEN),
DB_BLOB, chunk_create(autn, AKA_AUTN_LEN), DB_TEXT, buf,
DB_BLOB, DB_BLOB, DB_BLOB);
@@ -134,7 +137,7 @@ METHOD(simaka_card_t, get_quintuplet, status_t,
else
{
this->db->execute(this->db, NULL,
- "update quintuplets set use = ? where id = ? and rand = ?",
+ "update quintuplets set used = ? where id = ? and rand = ?",
DB_UINT, time(NULL), DB_TEXT, buf,
DB_BLOB, chunk_create(rand, AKA_RAND_LEN));
}
diff --git a/src/libcharon/plugins/eap_tls/Makefile.in b/src/libcharon/plugins/eap_tls/Makefile.in
index a9a2dede9..dfe6d8b03 100644
--- a/src/libcharon/plugins/eap_tls/Makefile.in
+++ b/src/libcharon/plugins/eap_tls/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/eap_tnc/Makefile.in b/src/libcharon/plugins/eap_tnc/Makefile.in
index cda1728c0..902d79d76 100644
--- a/src/libcharon/plugins/eap_tnc/Makefile.in
+++ b/src/libcharon/plugins/eap_tnc/Makefile.in
@@ -359,6 +359,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -381,6 +382,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/eap_ttls/Makefile.in b/src/libcharon/plugins/eap_ttls/Makefile.in
index a72b00576..53fb187fd 100644
--- a/src/libcharon/plugins/eap_ttls/Makefile.in
+++ b/src/libcharon/plugins/eap_ttls/Makefile.in
@@ -360,6 +360,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -382,6 +383,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/error_notify/Makefile.in b/src/libcharon/plugins/error_notify/Makefile.in
index 33862f01a..1514f4011 100644
--- a/src/libcharon/plugins/error_notify/Makefile.in
+++ b/src/libcharon/plugins/error_notify/Makefile.in
@@ -366,6 +366,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -388,6 +389,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/ext_auth/Makefile.in b/src/libcharon/plugins/ext_auth/Makefile.in
index de83d83d5..c3a18191f 100644
--- a/src/libcharon/plugins/ext_auth/Makefile.in
+++ b/src/libcharon/plugins/ext_auth/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/farp/Makefile.in b/src/libcharon/plugins/farp/Makefile.in
index daee657e7..3de99da38 100644
--- a/src/libcharon/plugins/farp/Makefile.in
+++ b/src/libcharon/plugins/farp/Makefile.in
@@ -356,6 +356,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -378,6 +379,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/forecast/Makefile.in b/src/libcharon/plugins/forecast/Makefile.in
index 5254bca04..5263ccd43 100644
--- a/src/libcharon/plugins/forecast/Makefile.in
+++ b/src/libcharon/plugins/forecast/Makefile.in
@@ -359,6 +359,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -381,6 +382,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/forecast/forecast_listener.c b/src/libcharon/plugins/forecast/forecast_listener.c
index 2024c2682..4585731de 100644
--- a/src/libcharon/plugins/forecast/forecast_listener.c
+++ b/src/libcharon/plugins/forecast/forecast_listener.c
@@ -613,17 +613,23 @@ METHOD(listener_t, ike_update, bool,
return TRUE;
}
-/**
- * Filter to map entries to ts/mark
- */
-static bool ts_filter(entry_t *entry, traffic_selector_t **ts,
- traffic_selector_t **out, void *dummy, uint32_t *mark,
- void *dummy2, bool *reinject)
+CALLBACK(ts_filter, bool,
+ entry_t *entry, enumerator_t *orig, va_list args)
{
- *out = *ts;
- *mark = entry->mark;
- *reinject = entry->reinject;
- return TRUE;
+ traffic_selector_t *ts, **out;
+ uint32_t *mark;
+ bool *reinject;
+
+ VA_ARGS_VGET(args, out, mark, reinject);
+
+ if (orig->enumerate(orig, &ts))
+ {
+ *out = ts;
+ *mark = entry->mark;
+ *reinject = entry->reinject;
+ return TRUE;
+ }
+ return FALSE;
}
/**
@@ -632,7 +638,7 @@ static bool ts_filter(entry_t *entry, traffic_selector_t **ts,
static enumerator_t* create_inner_local(entry_t *entry, rwlock_t *lock)
{
return enumerator_create_filter(array_create_enumerator(entry->lts),
- (void*)ts_filter, entry, NULL);
+ ts_filter, entry, NULL);
}
/**
@@ -641,7 +647,7 @@ static enumerator_t* create_inner_local(entry_t *entry, rwlock_t *lock)
static enumerator_t* create_inner_remote(entry_t *entry, rwlock_t *lock)
{
return enumerator_create_filter(array_create_enumerator(entry->rts),
- (void*)ts_filter, entry, NULL);
+ ts_filter, entry, NULL);
}
METHOD(forecast_listener_t, create_enumerator, enumerator_t*,
diff --git a/src/libcharon/plugins/ha/Makefile.in b/src/libcharon/plugins/ha/Makefile.in
index dd2a7a94c..d82bdd28e 100644
--- a/src/libcharon/plugins/ha/Makefile.in
+++ b/src/libcharon/plugins/ha/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c
index ee66b8442..7d22257c6 100644
--- a/src/libcharon/plugins/ha/ha_dispatcher.c
+++ b/src/libcharon/plugins/ha/ha_dispatcher.c
@@ -818,14 +818,14 @@ static void process_child_add(private_ha_dispatcher_t *this,
}
enumerator->destroy(enumerator);
+ child_sa->set_policies(child_sa, local_ts, remote_ts);
+
if (initiator)
{
if (child_sa->install(child_sa, encr_r, integ_r, inbound_spi,
- inbound_cpi, initiator, TRUE, TRUE,
- local_ts, remote_ts) != SUCCESS ||
+ inbound_cpi, initiator, TRUE, TRUE) != SUCCESS ||
child_sa->install(child_sa, encr_i, integ_i, outbound_spi,
- outbound_cpi, initiator, FALSE, TRUE,
- local_ts, remote_ts) != SUCCESS)
+ outbound_cpi, initiator, FALSE, TRUE) != SUCCESS)
{
failed = TRUE;
}
@@ -833,11 +833,9 @@ static void process_child_add(private_ha_dispatcher_t *this,
else
{
if (child_sa->install(child_sa, encr_i, integ_i, inbound_spi,
- inbound_cpi, initiator, TRUE, TRUE,
- local_ts, remote_ts) != SUCCESS ||
+ inbound_cpi, initiator, TRUE, TRUE) != SUCCESS ||
child_sa->install(child_sa, encr_r, integ_r, outbound_spi,
- outbound_cpi, initiator, FALSE, TRUE,
- local_ts, remote_ts) != SUCCESS)
+ outbound_cpi, initiator, FALSE, TRUE) != SUCCESS)
{
failed = TRUE;
}
@@ -868,7 +866,7 @@ static void process_child_add(private_ha_dispatcher_t *this,
child_sa->get_unique_id(child_sa), local_ts, remote_ts,
seg_i, this->segments->is_active(this->segments, seg_i) ? "*" : "",
seg_o, this->segments->is_active(this->segments, seg_o) ? "*" : "");
- child_sa->add_policies(child_sa, local_ts, remote_ts);
+ child_sa->install_policies(child_sa);
local_ts->destroy_offset(local_ts, offsetof(traffic_selector_t, destroy));
remote_ts->destroy_offset(remote_ts, offsetof(traffic_selector_t, destroy));
diff --git a/src/libcharon/plugins/ha/ha_message.c b/src/libcharon/plugins/ha/ha_message.c
index 42dfaf0e2..5f73b7156 100644
--- a/src/libcharon/plugins/ha/ha_message.c
+++ b/src/libcharon/plugins/ha/ha_message.c
@@ -331,10 +331,12 @@ typedef struct {
} attribute_enumerator_t;
METHOD(enumerator_t, attribute_enumerate, bool,
- attribute_enumerator_t *this, ha_message_attribute_t *attr_out,
- ha_message_value_t *value)
+ attribute_enumerator_t *this, va_list args)
{
- ha_message_attribute_t attr;
+ ha_message_attribute_t attr, *attr_out;
+ ha_message_value_t *value;
+
+ VA_ARGS_VGET(args, attr_out, value);
if (this->cleanup)
{
@@ -602,7 +604,8 @@ METHOD(ha_message_t, create_attribute_enumerator, enumerator_t*,
INIT(e,
.public = {
- .enumerate = (void*)_attribute_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _attribute_enumerate,
.destroy = _enum_destroy,
},
.buf = chunk_skip(this->buf, 2),
diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c
index a0e514614..1a6108ed9 100644
--- a/src/libcharon/plugins/ha/ha_tunnel.c
+++ b/src/libcharon/plugins/ha/ha_tunnel.c
@@ -111,8 +111,12 @@ typedef struct {
} shared_enum_t;
METHOD(enumerator_t, shared_enumerate, bool,
- shared_enum_t *this, shared_key_t **key, id_match_t *me, id_match_t *other)
+ shared_enum_t *this, va_list args)
{
+ shared_key_t **key;
+ id_match_t *me, *other;
+
+ VA_ARGS_VGET(args, key, me, other);
if (this->key)
{
if (me)
@@ -151,7 +155,8 @@ METHOD(ha_creds_t, create_shared_enumerator, enumerator_t*,
INIT(enumerator,
.public = {
- .enumerate = (void*)_shared_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _shared_enumerate,
.destroy = (void*)free,
},
.key = this->key,
diff --git a/src/libcharon/plugins/ipseckey/Makefile.in b/src/libcharon/plugins/ipseckey/Makefile.in
index 025a1a25e..02243e47c 100644
--- a/src/libcharon/plugins/ipseckey/Makefile.in
+++ b/src/libcharon/plugins/ipseckey/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/ipseckey/ipseckey_cred.c b/src/libcharon/plugins/ipseckey/ipseckey_cred.c
index ff50d8a17..b3ac2b328 100644
--- a/src/libcharon/plugins/ipseckey/ipseckey_cred.c
+++ b/src/libcharon/plugins/ipseckey/ipseckey_cred.c
@@ -62,13 +62,16 @@ typedef struct {
} cert_enumerator_t;
METHOD(enumerator_t, cert_enumerator_enumerate, bool,
- cert_enumerator_t *this, certificate_t **cert)
+ cert_enumerator_t *this, va_list args)
{
+ certificate_t **cert;
ipseckey_t *cur_ipseckey;
public_key_t *public;
rr_t *cur_rr;
chunk_t key;
+ VA_ARGS_VGET(args, cert);
+
/* Get the next supported IPSECKEY using the inner enumerator. */
while (this->inner->enumerate(this->inner, &cur_rr))
{
@@ -211,7 +214,8 @@ METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
INIT(e,
.public = {
- .enumerate = (void*)_cert_enumerator_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _cert_enumerator_enumerate,
.destroy = _cert_enumerator_destroy,
},
.inner = rrset->create_rr_enumerator(rrset),
diff --git a/src/libcharon/plugins/kernel_iph/Makefile.in b/src/libcharon/plugins/kernel_iph/Makefile.in
index fb8e42ee6..d9c172c1d 100644
--- a/src/libcharon/plugins/kernel_iph/Makefile.in
+++ b/src/libcharon/plugins/kernel_iph/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/kernel_iph/kernel_iph_net.c b/src/libcharon/plugins/kernel_iph/kernel_iph_net.c
index efeb98045..18a87b707 100644
--- a/src/libcharon/plugins/kernel_iph/kernel_iph_net.c
+++ b/src/libcharon/plugins/kernel_iph/kernel_iph_net.c
@@ -466,9 +466,12 @@ typedef struct {
} addr_enumerator_t;
METHOD(enumerator_t, addr_enumerate, bool,
- addr_enumerator_t *this, host_t **host)
+ addr_enumerator_t *this, va_list args)
{
iface_t *entry;
+ host_t **host;
+
+ VA_ARGS_VGET(args, host);
while (TRUE)
{
@@ -523,7 +526,8 @@ METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
INIT(enumerator,
.public = {
- .enumerate = (void*)_addr_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _addr_enumerate,
.destroy = _addr_destroy,
},
.which = which,
diff --git a/src/libcharon/plugins/kernel_libipsec/Makefile.in b/src/libcharon/plugins/kernel_libipsec/Makefile.in
index 4d5e46033..9f1a490cf 100644
--- a/src/libcharon/plugins/kernel_libipsec/Makefile.in
+++ b/src/libcharon/plugins/kernel_libipsec/Makefile.in
@@ -360,6 +360,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -382,6 +383,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c
index 77e37e249..d4832e233 100644
--- a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c
+++ b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c
@@ -84,12 +84,12 @@ static void exclude_route_destroy(exclude_route_t *this)
free(this);
}
-/**
- * Find an exclude route entry by destination address
- */
-static bool exclude_route_match(exclude_route_t *current,
- host_t *dst)
+CALLBACK(exclude_route_match, bool,
+ exclude_route_t *current, va_list args)
{
+ host_t *dst;
+
+ VA_ARGS_VGET(args, dst);
return dst->ip_equals(dst, current->dst);
}
@@ -204,12 +204,12 @@ static void policy_entry_destroy(policy_entry_t *this)
free(this);
}
-/**
- * Compare two policy_entry_t objects
- */
-static inline bool policy_entry_equals(policy_entry_t *a,
- policy_entry_t *b)
+CALLBACK(policy_entry_equals, bool,
+ policy_entry_t *a, va_list args)
{
+ policy_entry_t *b;
+
+ VA_ARGS_VGET(args, b);
return a->direction == b->direction &&
a->src.proto == b->src.proto &&
a->dst.proto == b->dst.proto &&
@@ -297,9 +297,8 @@ static void add_exclude_route(private_kernel_libipsec_ipsec_t *this,
exclude_route_t *exclude;
host_t *gtw;
- if (this->excludes->find_first(this->excludes,
- (linked_list_match_t)exclude_route_match,
- (void**)&exclude, dst) == SUCCESS)
+ if (this->excludes->find_first(this->excludes, exclude_route_match,
+ (void**)&exclude, dst))
{
route->exclude = exclude;
exclude->refs++;
@@ -524,9 +523,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
policy = create_policy_entry(id->src_ts, id->dst_ts, id->dir);
this->mutex->lock(this->mutex);
- if (this->policies->find_first(this->policies,
- (linked_list_match_t)policy_entry_equals,
- (void**)&found, policy) == SUCCESS)
+ if (this->policies->find_first(this->policies, policy_entry_equals,
+ (void**)&found, policy))
{
policy_entry_destroy(policy);
policy = found;
@@ -567,9 +565,8 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
policy = create_policy_entry(id->src_ts, id->dst_ts, id->dir);
this->mutex->lock(this->mutex);
- if (this->policies->find_first(this->policies,
- (linked_list_match_t)policy_entry_equals,
- (void**)&found, policy) != SUCCESS)
+ if (!this->policies->find_first(this->policies, policy_entry_equals,
+ (void**)&found, policy))
{
policy_entry_destroy(policy);
this->mutex->unlock(this->mutex);
diff --git a/src/libcharon/plugins/kernel_netlink/Makefile.in b/src/libcharon/plugins/kernel_netlink/Makefile.in
index 26a7090b3..7f25c5202 100644
--- a/src/libcharon/plugins/kernel_netlink/Makefile.in
+++ b/src/libcharon/plugins/kernel_netlink/Makefile.in
@@ -397,6 +397,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -419,6 +420,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
index becf6b5dc..c411b829d 100644
--- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -78,9 +78,6 @@
/** Base priority for installed policies */
#define PRIO_BASE 200000
-/** Default lifetime of an acquire XFRM state (in seconds) */
-#define DEFAULT_ACQUIRE_LIFETIME 165
-
/**
* Map the limit for bytes and packets to XFRM_INF by default
*/
@@ -545,10 +542,10 @@ static policy_sa_t *policy_sa_create(private_kernel_netlink_ipsec_t *this,
/**
* Destroy a policy_sa(_in)_t object
*/
-static void policy_sa_destroy(policy_sa_t *policy, policy_dir_t *dir,
+static void policy_sa_destroy(policy_sa_t *policy, policy_dir_t dir,
private_kernel_netlink_ipsec_t *this)
{
- if (*dir == POLICY_OUT)
+ if (dir == POLICY_OUT)
{
policy_sa_out_t *out = (policy_sa_out_t*)policy;
out->src_ts->destroy(out->src_ts);
@@ -558,6 +555,16 @@ static void policy_sa_destroy(policy_sa_t *policy, policy_dir_t *dir,
free(policy);
}
+CALLBACK(policy_sa_destroy_cb, void,
+ policy_sa_t *policy, va_list args)
+{
+ private_kernel_netlink_ipsec_t *this;
+ policy_dir_t dir;
+
+ VA_ARGS_VGET(args, dir, this);
+ policy_sa_destroy(policy, dir, this);
+}
+
typedef struct policy_entry_t policy_entry_t;
/**
@@ -602,9 +609,8 @@ static void policy_entry_destroy(private_kernel_netlink_ipsec_t *this,
}
if (policy->used_by)
{
- policy->used_by->invoke_function(policy->used_by,
- (linked_list_invoke_t)policy_sa_destroy,
- &policy->direction, this);
+ policy->used_by->invoke_function(policy->used_by, policy_sa_destroy_cb,
+ policy->direction, this);
policy->used_by->destroy(policy->used_by);
}
free(policy);
@@ -1639,12 +1645,46 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
data->replay_window);
sa->replay_window = data->replay_window;
}
+ if (data->hw_offload)
+ {
+ host_t *local = data->inbound ? id->dst : id->src;
+ char *ifname;
+
+ if (charon->kernel->get_interface(charon->kernel, local, &ifname))
+ {
+ struct xfrm_user_offload *offload;
+
+ offload = netlink_reserve(hdr, sizeof(request),
+ XFRMA_OFFLOAD_DEV, sizeof(*offload));
+ if (!offload)
+ {
+ free(ifname);
+ goto failed;
+ }
+ offload->ifindex = if_nametoindex(ifname);
+ if (local->get_family(local) == AF_INET6)
+ {
+ offload->flags |= XFRM_OFFLOAD_IPV6;
+ }
+ offload->flags |= data->inbound ? XFRM_OFFLOAD_INBOUND : 0;
+ free(ifname);
+ }
+ }
}
- if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
+ status = this->socket_xfrm->send_ack(this->socket_xfrm, hdr);
+ if (status == NOT_FOUND && data->update)
{
- DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x%s", ntohl(id->spi),
- markstr);
+ DBG1(DBG_KNL, "allocated SPI not found anymore, try to add SAD entry");
+ hdr->nlmsg_type = XFRM_MSG_NEWSA;
+ status = this->socket_xfrm->send_ack(this->socket_xfrm, hdr);
+ }
+
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x%s (%N)", ntohl(id->spi),
+ markstr, status_names, status);
+ status = FAILED;
goto failed;
}
@@ -1919,13 +1959,13 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
kernel_ipsec_update_sa_t *data)
{
netlink_buf_t request;
- struct nlmsghdr *hdr, *out = NULL;
+ struct nlmsghdr *hdr, *out_hdr = NULL, *out = NULL;
struct xfrm_usersa_id *sa_id;
- struct xfrm_usersa_info *out_sa = NULL, *sa;
+ struct xfrm_usersa_info *sa;
size_t len;
struct rtattr *rta;
size_t rtasize;
- struct xfrm_encap_tmpl* tmpl = NULL;
+ struct xfrm_encap_tmpl* encap = NULL;
struct xfrm_replay_state *replay = NULL;
struct xfrm_replay_state_esn *replay_esn = NULL;
struct xfrm_lifetime_cur *lifetime = NULL;
@@ -1983,7 +2023,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
{
case XFRM_MSG_NEWSA:
{
- out_sa = NLMSG_DATA(hdr);
+ out_hdr = hdr;
break;
}
case NLMSG_ERROR:
@@ -2002,7 +2042,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
break;
}
}
- if (out_sa == NULL)
+ if (!out_hdr)
{
DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x%s",
ntohl(id->spi), markstr);
@@ -2029,7 +2069,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
hdr->nlmsg_type = XFRM_MSG_NEWSA;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
sa = NLMSG_DATA(hdr);
- memcpy(sa, NLMSG_DATA(out), sizeof(struct xfrm_usersa_info));
+ memcpy(sa, NLMSG_DATA(out_hdr), sizeof(struct xfrm_usersa_info));
sa->family = data->new_dst->get_family(data->new_dst);
if (!id->src->ip_equals(id->src, data->new_src))
@@ -2041,8 +2081,8 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
host2xfrm(data->new_dst, &sa->id.daddr);
}
- rta = XFRM_RTA(out, struct xfrm_usersa_info);
- rtasize = XFRM_PAYLOAD(out, struct xfrm_usersa_info);
+ rta = XFRM_RTA(out_hdr, struct xfrm_usersa_info);
+ rtasize = XFRM_PAYLOAD(out_hdr, struct xfrm_usersa_info);
while (RTA_OK(rta, rtasize))
{
/* copy all attributes, but not XFRMA_ENCAP if we are disabling it */
@@ -2050,9 +2090,34 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
{
if (rta->rta_type == XFRMA_ENCAP)
{ /* update encap tmpl */
- tmpl = RTA_DATA(rta);
- tmpl->encap_sport = ntohs(data->new_src->get_port(data->new_src));
- tmpl->encap_dport = ntohs(data->new_dst->get_port(data->new_dst));
+ encap = RTA_DATA(rta);
+ encap->encap_sport = ntohs(data->new_src->get_port(data->new_src));
+ encap->encap_dport = ntohs(data->new_dst->get_port(data->new_dst));
+ }
+ if (rta->rta_type == XFRMA_OFFLOAD_DEV)
+ { /* update offload device */
+ struct xfrm_user_offload *offload;
+ host_t *local;
+ char *ifname;
+
+ offload = RTA_DATA(rta);
+ local = offload->flags & XFRM_OFFLOAD_INBOUND ? data->new_dst
+ : data->new_src;
+
+ if (charon->kernel->get_interface(charon->kernel, local,
+ &ifname))
+ {
+ offload->ifindex = if_nametoindex(ifname);
+ if (local->get_family(local) == AF_INET6)
+ {
+ offload->flags |= XFRM_OFFLOAD_IPV6;
+ }
+ else
+ {
+ offload->flags &= ~XFRM_OFFLOAD_IPV6;
+ }
+ free(ifname);
+ }
}
netlink_add_attribute(hdr, rta->rta_type,
chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)),
@@ -2061,17 +2126,18 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
rta = RTA_NEXT(rta, rtasize);
}
- if (tmpl == NULL && data->new_encap)
+ if (encap == NULL && data->new_encap)
{ /* add tmpl if we are enabling it */
- tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_ENCAP, sizeof(*tmpl));
- if (!tmpl)
+ encap = netlink_reserve(hdr, sizeof(request), XFRMA_ENCAP,
+ sizeof(*encap));
+ if (!encap)
{
goto failed;
}
- tmpl->encap_type = UDP_ENCAP_ESPINUDP;
- tmpl->encap_sport = ntohs(data->new_src->get_port(data->new_src));
- tmpl->encap_dport = ntohs(data->new_dst->get_port(data->new_dst));
- memset(&tmpl->encap_oa, 0, sizeof (xfrm_address_t));
+ encap->encap_type = UDP_ENCAP_ESPINUDP;
+ encap->encap_sport = ntohs(data->new_src->get_port(data->new_src));
+ encap->encap_dport = ntohs(data->new_dst->get_port(data->new_dst));
+ memset(&encap->encap_oa, 0, sizeof (xfrm_address_t));
}
if (replay_esn)
@@ -2711,7 +2777,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
ipsec_sa_equals(mapping->sa, &assigned_sa))
{
current->used_by->remove_at(current->used_by, enumerator);
- policy_sa_destroy(mapping, &id->dir, this);
+ policy_sa_destroy(mapping, id->dir, this);
break;
}
if (is_installed)
@@ -3171,7 +3237,6 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
{
private_kernel_netlink_ipsec_t *this;
bool register_for_events = TRUE;
- FILE *f;
INIT(this,
.public = {
@@ -3216,15 +3281,6 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
register_for_events = FALSE;
}
- f = fopen("/proc/sys/net/core/xfrm_acq_expires", "w");
- if (f)
- {
- fprintf(f, "%u", lib->settings->get_int(lib->settings,
- "%s.plugins.kernel-netlink.xfrm_acq_expires",
- DEFAULT_ACQUIRE_LIFETIME, lib->ns));
- fclose(f);
- }
-
this->socket_xfrm = netlink_socket_create(NETLINK_XFRM, xfrm_msg_names,
lib->settings->get_bool(lib->settings,
"%s.plugins.kernel-netlink.parallel_xfrm", FALSE, lib->ns));
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
index 2dc76d941..0dd3e30cb 100644
--- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
@@ -163,19 +163,21 @@ static void iface_entry_destroy(iface_entry_t *this)
free(this);
}
-/**
- * find an interface entry by index
- */
-static bool iface_entry_by_index(iface_entry_t *this, int *ifindex)
+CALLBACK(iface_entry_by_index, bool,
+ iface_entry_t *this, va_list args)
{
- return this->ifindex == *ifindex;
+ int ifindex;
+
+ VA_ARGS_VGET(args, ifindex);
+ return this->ifindex == ifindex;
}
-/**
- * find an interface entry by name
- */
-static bool iface_entry_by_name(iface_entry_t *this, char *ifname)
+CALLBACK(iface_entry_by_name, bool,
+ iface_entry_t *this, va_list args)
{
+ char *ifname;
+
+ VA_ARGS_VGET(args, ifname);
return streq(this->ifname, ifname);
}
@@ -1112,8 +1114,8 @@ static bool is_interface_up_and_usable(private_kernel_netlink_net_t *this,
{
iface_entry_t *iface;
- if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_index,
- (void**)&iface, &index) == SUCCESS)
+ if (this->ifaces->find_first(this->ifaces, iface_entry_by_index,
+ (void**)&iface, index))
{
return iface_entry_up_and_usable(iface);
}
@@ -1125,9 +1127,13 @@ static bool is_interface_up_and_usable(private_kernel_netlink_net_t *this,
*
* this->lock must be locked when calling this function
*/
-static void addr_entry_unregister(addr_entry_t *addr, iface_entry_t *iface,
- private_kernel_netlink_net_t *this)
+CALLBACK(addr_entry_unregister, void,
+ addr_entry_t *addr, va_list args)
{
+ private_kernel_netlink_net_t *this;
+ iface_entry_t *iface;
+
+ VA_ARGS_VGET(args, iface, this);
if (addr->refcount)
{
addr_map_entry_remove(this->vips, addr, iface);
@@ -1171,9 +1177,8 @@ static void process_link(private_kernel_netlink_net_t *this,
{
case RTM_NEWLINK:
{
- if (this->ifaces->find_first(this->ifaces,
- (void*)iface_entry_by_index, (void**)&entry,
- &msg->ifi_index) != SUCCESS)
+ if (!this->ifaces->find_first(this->ifaces, iface_entry_by_index,
+ (void**)&entry, msg->ifi_index))
{
INIT(entry,
.ifindex = msg->ifi_index,
@@ -1217,7 +1222,7 @@ static void process_link(private_kernel_netlink_net_t *this,
* another interface? */
this->ifaces->remove_at(this->ifaces, enumerator);
current->addrs->invoke_function(current->addrs,
- (void*)addr_entry_unregister, current, this);
+ addr_entry_unregister, current, this);
iface_entry_destroy(current);
break;
}
@@ -1288,8 +1293,8 @@ static void process_addr(private_kernel_netlink_net_t *this,
}
this->lock->write_lock(this->lock);
- if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_index,
- (void**)&iface, &msg->ifa_index) == SUCCESS)
+ if (this->ifaces->find_first(this->ifaces, iface_entry_by_index,
+ (void**)&iface, msg->ifa_index))
{
addr_map_entry_t *entry, lookup = {
.ip = host,
@@ -1518,35 +1523,39 @@ typedef struct {
kernel_address_type_t which;
} address_enumerator_t;
-/**
- * cleanup function for address enumerator
- */
-static void address_enumerator_destroy(address_enumerator_t *data)
+CALLBACK(address_enumerator_destroy, void,
+ address_enumerator_t *data)
{
data->this->lock->unlock(data->this->lock);
free(data);
}
-/**
- * filter for addresses
- */
-static bool filter_addresses(address_enumerator_t *data,
- addr_entry_t** in, host_t** out)
+CALLBACK(filter_addresses, bool,
+ address_enumerator_t *data, enumerator_t *orig, va_list args)
{
- if (!(data->which & ADDR_TYPE_VIRTUAL) && (*in)->refcount)
- { /* skip virtual interfaces added by us */
- return FALSE;
- }
- if (!(data->which & ADDR_TYPE_REGULAR) && !(*in)->refcount)
- { /* address is regular, but not requested */
- return FALSE;
- }
- if ((*in)->scope >= RT_SCOPE_LINK)
- { /* skip addresses with a unusable scope */
- return FALSE;
+ addr_entry_t *addr;
+ host_t **out;
+
+ VA_ARGS_VGET(args, out);
+
+ while (orig->enumerate(orig, &addr))
+ {
+ if (!(data->which & ADDR_TYPE_VIRTUAL) && addr->refcount)
+ { /* skip virtual interfaces added by us */
+ continue;
+ }
+ if (!(data->which & ADDR_TYPE_REGULAR) && !addr->refcount)
+ { /* address is regular, but not requested */
+ continue;
+ }
+ if (addr->scope >= RT_SCOPE_LINK)
+ { /* skip addresses with a unusable scope */
+ continue;
+ }
+ *out = addr->ip;
+ return TRUE;
}
- *out = (*in)->ip;
- return TRUE;
+ return FALSE;
}
/**
@@ -1556,30 +1565,35 @@ static enumerator_t *create_iface_enumerator(iface_entry_t *iface,
address_enumerator_t *data)
{
return enumerator_create_filter(
- iface->addrs->create_enumerator(iface->addrs),
- (void*)filter_addresses, data, NULL);
+ iface->addrs->create_enumerator(iface->addrs),
+ filter_addresses, data, NULL);
}
-/**
- * filter for interfaces
- */
-static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in,
- iface_entry_t** out)
+CALLBACK(filter_interfaces, bool,
+ address_enumerator_t *data, enumerator_t *orig, va_list args)
{
- if (!(data->which & ADDR_TYPE_IGNORED) && !(*in)->usable)
- { /* skip interfaces excluded by config */
- return FALSE;
- }
- if (!(data->which & ADDR_TYPE_LOOPBACK) && ((*in)->flags & IFF_LOOPBACK))
- { /* ignore loopback devices */
- return FALSE;
- }
- if (!(data->which & ADDR_TYPE_DOWN) && !((*in)->flags & IFF_UP))
- { /* skip interfaces not up */
- return FALSE;
+ iface_entry_t *iface, **out;
+
+ VA_ARGS_VGET(args, out);
+
+ while (orig->enumerate(orig, &iface))
+ {
+ if (!(data->which & ADDR_TYPE_IGNORED) && !iface->usable)
+ { /* skip interfaces excluded by config */
+ continue;
+ }
+ if (!(data->which & ADDR_TYPE_LOOPBACK) && (iface->flags & IFF_LOOPBACK))
+ { /* ignore loopback devices */
+ continue;
+ }
+ if (!(data->which & ADDR_TYPE_DOWN) && !(iface->flags & IFF_UP))
+ { /* skip interfaces not up */
+ continue;
+ }
+ *out = iface;
+ return TRUE;
}
- *out = *in;
- return TRUE;
+ return FALSE;
}
METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
@@ -1596,9 +1610,9 @@ METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
return enumerator_create_nested(
enumerator_create_filter(
this->ifaces->create_enumerator(this->ifaces),
- (void*)filter_interfaces, data, NULL),
+ filter_interfaces, data, NULL),
(void*)create_iface_enumerator, data,
- (void*)address_enumerator_destroy);
+ address_enumerator_destroy);
}
METHOD(kernel_net_t, get_interface_name, bool,
@@ -1661,8 +1675,8 @@ static int get_interface_index(private_kernel_netlink_net_t *this, char* name)
DBG2(DBG_KNL, "getting iface index for %s", name);
this->lock->read_lock(this->lock);
- if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_name,
- (void**)&iface, name) == SUCCESS)
+ if (this->ifaces->find_first(this->ifaces, iface_entry_by_name,
+ (void**)&iface, name))
{
ifindex = iface->ifindex;
}
@@ -1687,8 +1701,8 @@ static char *get_interface_name_by_index(private_kernel_netlink_net_t *this,
DBG2(DBG_KNL, "getting iface name for index %d", index);
this->lock->read_lock(this->lock);
- if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_index,
- (void**)&iface, &index) == SUCCESS)
+ if (this->ifaces->find_first(this->ifaces, iface_entry_by_index,
+ (void**)&iface, index))
{
name = strdup(iface->ifname);
}
@@ -1928,7 +1942,7 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
table = (uintptr_t)route->table;
if (this->rt_exclude->find_first(this->rt_exclude, NULL,
- (void**)&table) == SUCCESS)
+ (void**)&table))
{ /* route is from an excluded routing table */
continue;
}
@@ -2165,8 +2179,14 @@ METHOD(enumerator_t, destroy_subnet_enumerator, void,
}
METHOD(enumerator_t, enumerate_subnets, bool,
- subnet_enumerator_t *this, host_t **net, uint8_t *mask, char **ifname)
+ subnet_enumerator_t *this, va_list args)
{
+ host_t **net;
+ uint8_t *mask;
+ char **ifname;
+
+ VA_ARGS_VGET(args, net, mask, ifname);
+
if (!this->current)
{
this->current = this->msg;
@@ -2270,7 +2290,8 @@ METHOD(kernel_net_t, create_local_subnet_enumerator, enumerator_t*,
INIT(enumerator,
.public = {
- .enumerate = (void*)_enumerate_subnets,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _enumerate_subnets,
.destroy = _destroy_subnet_enumerator,
},
.private = this,
@@ -2380,11 +2401,11 @@ METHOD(kernel_net_t, add_ip, status_t,
}
/* try to find the target interface, either by config or via src ip */
if (!this->install_virtual_ip_on ||
- this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_name,
- (void**)&iface, this->install_virtual_ip_on) != SUCCESS)
+ !this->ifaces->find_first(this->ifaces, iface_entry_by_name,
+ (void**)&iface, this->install_virtual_ip_on))
{
- if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_name,
- (void**)&iface, iface_name) != SUCCESS)
+ if (!this->ifaces->find_first(this->ifaces, iface_entry_by_name,
+ (void**)&iface, iface_name))
{ /* if we don't find the requested interface we just use the first */
this->ifaces->get_first(this->ifaces, (void**)&iface);
}
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.c
index 8bafc3c55..58350028f 100644
--- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.c
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.c
@@ -19,6 +19,8 @@
#include "kernel_netlink_ipsec.h"
#include "kernel_netlink_net.h"
+#include <sa/task_manager.h>
+
typedef struct private_kernel_netlink_plugin_t private_kernel_netlink_plugin_t;
/**
@@ -50,6 +52,24 @@ METHOD(plugin_t, get_features, int,
return countof(f);
}
+METHOD(plugin_t, reload, bool,
+ private_kernel_netlink_plugin_t *this)
+{
+ u_int timeout;
+ FILE *f;
+
+ f = fopen("/proc/sys/net/core/xfrm_acq_expires", "w");
+ if (f)
+ {
+ timeout = lib->settings->get_int(lib->settings,
+ "%s.plugins.kernel-netlink.xfrm_acq_expires",
+ task_manager_total_retransmit_timeout(), lib->ns);
+ fprintf(f, "%u", timeout);
+ fclose(f);
+ }
+ return TRUE;
+}
+
METHOD(plugin_t, destroy, void,
private_kernel_netlink_plugin_t *this)
{
@@ -76,10 +96,13 @@ plugin_t *kernel_netlink_plugin_create()
.plugin = {
.get_name = _get_name,
.get_features = _get_features,
+ .reload = _reload,
.destroy = _destroy,
},
},
);
+ reload(this);
+
return &this->public.plugin;
}
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c
index da54031a1..cf85cb0a6 100644
--- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c
@@ -333,7 +333,8 @@ static status_t send_once(private_netlink_socket_t *this, struct nlmsghdr *in,
while (!entry->complete)
{
if (this->parallel &&
- lib->watcher->get_state(lib->watcher) != WATCHER_STOPPED)
+ lib->watcher->get_state(lib->watcher) != WATCHER_STOPPED &&
+ lib->processor->get_total_threads(lib->processor))
{
if (this->timeout)
{
diff --git a/src/libcharon/plugins/kernel_pfkey/Makefile.in b/src/libcharon/plugins/kernel_pfkey/Makefile.in
index b138a9603..b27408a3f 100644
--- a/src/libcharon/plugins/kernel_pfkey/Makefile.in
+++ b/src/libcharon/plugins/kernel_pfkey/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
index 17878147b..fd1adb2ae 100644
--- a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
+++ b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
@@ -464,10 +464,10 @@ static policy_sa_t *policy_sa_create(private_kernel_pfkey_ipsec_t *this,
/**
* Destroy a policy_sa(_in)_t object
*/
-static void policy_sa_destroy(policy_sa_t *policy, policy_dir_t *dir,
+static void policy_sa_destroy(policy_sa_t *policy, policy_dir_t dir,
private_kernel_pfkey_ipsec_t *this)
{
- if (*dir == POLICY_OUT)
+ if (dir == POLICY_OUT)
{
policy_sa_out_t *out = (policy_sa_out_t*)policy;
out->src_ts->destroy(out->src_ts);
@@ -477,6 +477,16 @@ static void policy_sa_destroy(policy_sa_t *policy, policy_dir_t *dir,
free(policy);
}
+CALLBACK(policy_sa_destroy_cb, void,
+ policy_sa_t *policy, va_list args)
+{
+ private_kernel_pfkey_ipsec_t *this;
+ policy_dir_t dir;
+
+ VA_ARGS_VGET(args, dir, this);
+ policy_sa_destroy(policy, dir, this);
+}
+
typedef struct policy_entry_t policy_entry_t;
/**
@@ -557,9 +567,8 @@ static void policy_entry_destroy(policy_entry_t *policy,
}
if (policy->used_by)
{
- policy->used_by->invoke_function(policy->used_by,
- (linked_list_invoke_t)policy_sa_destroy,
- &policy->direction, this);
+ policy->used_by->invoke_function(policy->used_by, policy_sa_destroy_cb,
+ policy->direction, this);
policy->used_by->destroy(policy->used_by);
}
DESTROY_IF(policy->src.net);
@@ -567,12 +576,21 @@ static void policy_entry_destroy(policy_entry_t *policy,
free(policy);
}
-/**
- * compares two policy_entry_t
- */
-static inline bool policy_entry_equals(policy_entry_t *current,
- policy_entry_t *policy)
+CALLBACK(policy_entry_destroy_cb, void,
+ policy_entry_t *policy, va_list args)
{
+ private_kernel_pfkey_ipsec_t *this;
+
+ VA_ARGS_VGET(args, this);
+ policy_entry_destroy(policy, this);
+}
+
+CALLBACK(policy_entry_equals, bool,
+ policy_entry_t *current, va_list args)
+{
+ policy_entry_t *policy;
+
+ VA_ARGS_VGET(args, policy);
return current->direction == policy->direction &&
current->src.proto == policy->src.proto &&
current->dst.proto == policy->dst.proto &&
@@ -582,13 +600,13 @@ static inline bool policy_entry_equals(policy_entry_t *current,
current->dst.net->equals(current->dst.net, policy->dst.net);
}
-/**
- * compare the given kernel index with that of a policy
- */
-static inline bool policy_entry_match_byindex(policy_entry_t *current,
- uint32_t *index)
+CALLBACK(policy_entry_match_byindex, bool,
+ policy_entry_t *current, va_list args)
{
- return current->index == *index;
+ uint32_t index;
+
+ VA_ARGS_VGET(args, index);
+ return current->index == index;
}
/**
@@ -999,24 +1017,6 @@ static void add_addr_ext(struct sadb_msg *msg, host_t *host, uint16_t type,
PFKEY_EXT_ADD(msg, addr);
}
-/**
- * adds an empty address extension to the given sadb_msg
- */
-static void add_anyaddr_ext(struct sadb_msg *msg, int family, uint8_t type)
-{
- socklen_t len = (family == AF_INET) ? sizeof(struct sockaddr_in) :
- sizeof(struct sockaddr_in6);
- struct sadb_address *addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
- addr->sadb_address_exttype = type;
- sockaddr_t *saddr = (sockaddr_t*)(addr + 1);
- saddr->sa_family = family;
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
- saddr->sa_len = len;
-#endif
- addr->sadb_address_len = PFKEY_LEN(sizeof(*addr) + len);
- PFKEY_EXT_ADD(msg, addr);
-}
-
#ifdef HAVE_NATT
/**
* add udp encap extensions to a sadb_msg
@@ -1279,9 +1279,8 @@ static void process_acquire(private_kernel_pfkey_ipsec_t *this,
index = response.x_policy->sadb_x_policy_id;
this->mutex->lock(this->mutex);
- if (this->policies->find_first(this->policies,
- (linked_list_match_t)policy_entry_match_byindex,
- (void**)&policy, &index) == SUCCESS &&
+ if (this->policies->find_first(this->policies, policy_entry_match_byindex,
+ (void**)&policy, index) &&
policy->used_by->get_first(policy->used_by, (void**)&sa) == SUCCESS)
{
reqid = sa->sa->cfg.reqid;
@@ -1854,6 +1853,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
pfkey_msg_t response;
size_t len;
+#ifndef SADB_X_EXT_NEW_ADDRESS_SRC
/* we can't update the SA if any of the ip addresses have changed.
* that's because we can't use SADB_UPDATE and by deleting and readding the
* SA the sequence numbers would get lost */
@@ -1864,6 +1864,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
"changes are not supported", ntohl(id->spi));
return NOT_SUPPORTED;
}
+#endif /*SADB_X_EXT_NEW_ADDRESS_SRC*/
/* if IPComp is used, we first update the IPComp SA */
if (data->cpi)
@@ -1900,9 +1901,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
sa->sadb_sa_state = SADB_SASTATE_MATURE;
PFKEY_EXT_ADD(msg, sa);
- /* the kernel wants a SADB_EXT_ADDRESS_SRC to be present even though
- * it is not used for anything. */
- add_anyaddr_ext(msg, id->dst->get_family(id->dst), SADB_EXT_ADDRESS_SRC);
+ add_addr_ext(msg, id->src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
add_addr_ext(msg, id->dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
if (pfkey_send(this, msg, &out, &len) != SUCCESS)
@@ -1944,7 +1943,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
sa_2 = (struct sadb_sa_2*)PFKEY_EXT_ADD_NEXT(msg);
sa_2->sa.sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa_2));
memcpy(&sa_2->sa, response.sa, sizeof(struct sadb_sa));
- if (data->encap)
+ if (data->new_encap)
{
sa_2->sadb_sa_natt_port = data->new_dst->get_port(data->new_dst);
sa_2->sa.sadb_sa_flags |= SADB_X_EXT_NATT;
@@ -1978,6 +1977,19 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
}
#endif /*HAVE_NATT*/
+#ifdef SADB_X_EXT_NEW_ADDRESS_SRC
+ if (!id->src->ip_equals(id->src, data->new_src))
+ {
+ add_addr_ext(msg, data->new_src, SADB_X_EXT_NEW_ADDRESS_SRC, 0, 0,
+ FALSE);
+ }
+ if (!id->dst->ip_equals(id->dst, data->new_dst))
+ {
+ add_addr_ext(msg, data->new_dst, SADB_X_EXT_NEW_ADDRESS_DST, 0, 0,
+ FALSE);
+ }
+#endif /*SADB_X_EXT_NEW_ADDRESS_SRC*/
+
free(out);
if (pfkey_send(this, msg, &out, &len) != SUCCESS)
@@ -2559,8 +2571,7 @@ static status_t add_policy_internal(private_kernel_pfkey_ipsec_t *this,
/* we try to find the policy again and update the kernel index */
this->mutex->lock(this->mutex);
- if (this->policies->find_first(this->policies, NULL,
- (void**)&policy) != SUCCESS)
+ if (!this->policies->find_first(this->policies, NULL, (void**)&policy))
{
DBG2(DBG_KNL, "unable to update index, the policy is already gone, "
"ignoring");
@@ -2611,9 +2622,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
/* find a matching policy */
this->mutex->lock(this->mutex);
- if (this->policies->find_first(this->policies,
- (linked_list_match_t)policy_entry_equals,
- (void**)&found, policy) == SUCCESS)
+ if (this->policies->find_first(this->policies, policy_entry_equals,
+ (void**)&found, policy))
{ /* use existing policy */
DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing "
"refcount", id->src_ts, id->dst_ts, policy_dir_names, id->dir);
@@ -2706,9 +2716,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
/* find a matching policy */
this->mutex->lock(this->mutex);
- if (this->policies->find_first(this->policies,
- (linked_list_match_t)policy_entry_equals,
- (void**)&found, policy) != SUCCESS)
+ if (!this->policies->find_first(this->policies, policy_entry_equals,
+ (void**)&found, policy))
{
DBG1(DBG_KNL, "querying policy %R === %R %N failed, not found",
id->src_ts, id->dst_ts, policy_dir_names, id->dir);
@@ -2819,9 +2828,8 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
/* find a matching policy */
this->mutex->lock(this->mutex);
- if (this->policies->find_first(this->policies,
- (linked_list_match_t)policy_entry_equals,
- (void**)&found, policy) != SUCCESS)
+ if (!this->policies->find_first(this->policies, policy_entry_equals,
+ (void**)&found, policy))
{
DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found",
id->src_ts, id->dst_ts, policy_dir_names, id->dir);
@@ -2865,7 +2873,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
if (policy->used_by->get_count(policy->used_by) > 0)
{ /* policy is used by more SAs, keep in kernel */
DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed");
- policy_sa_destroy(mapping, &id->dir, this);
+ policy_sa_destroy(mapping, id->dir, this);
if (!is_installed)
{ /* no need to update as the policy was not installed for this SA */
@@ -2920,7 +2928,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
}
this->policies->remove(this->policies, found, NULL);
- policy_sa_destroy(mapping, &id->dir, this);
+ policy_sa_destroy(mapping, id->dir, this);
policy_entry_destroy(policy, this);
this->mutex->unlock(this->mutex);
@@ -3093,8 +3101,7 @@ METHOD(kernel_ipsec_t, destroy, void,
lib->watcher->remove(lib->watcher, this->socket_events);
close(this->socket_events);
}
- this->policies->invoke_function(this->policies,
- (linked_list_invoke_t)policy_entry_destroy,
+ this->policies->invoke_function(this->policies, policy_entry_destroy_cb,
this);
this->policies->destroy(this->policies);
this->excludes->destroy(this->excludes);
diff --git a/src/libcharon/plugins/kernel_pfroute/Makefile.in b/src/libcharon/plugins/kernel_pfroute/Makefile.in
index 1e4b3e207..e7005bbff 100644
--- a/src/libcharon/plugins/kernel_pfroute/Makefile.in
+++ b/src/libcharon/plugins/kernel_pfroute/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c
index efcf1c2a7..6d06ee179 100644
--- a/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c
+++ b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c
@@ -601,9 +601,12 @@ typedef struct {
} rt_enumerator_t;
METHOD(enumerator_t, rt_enumerate, bool,
- rt_enumerator_t *this, int *xtype, struct sockaddr **addr)
+ rt_enumerator_t *this, va_list args)
{
- int i, type;
+ struct sockaddr **addr;
+ int i, type, *xtype;
+
+ VA_ARGS_VGET(args, xtype, addr);
if (this->remaining < sizeof(this->addr->sa_len) ||
this->remaining < this->addr->sa_len)
@@ -637,7 +640,8 @@ static enumerator_t *create_rt_enumerator(int types, int remaining,
INIT(this,
.public = {
- .enumerate = (void*)_rt_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _rt_enumerate,
.destroy = (void*)free,
},
.types = types,
@@ -1050,41 +1054,45 @@ typedef struct {
kernel_address_type_t which;
} address_enumerator_t;
-/**
- * cleanup function for address enumerator
- */
-static void address_enumerator_destroy(address_enumerator_t *data)
+CALLBACK(address_enumerator_destroy, void,
+ address_enumerator_t *data)
{
data->this->lock->unlock(data->this->lock);
free(data);
}
-/**
- * filter for addresses
- */
-static bool filter_addresses(address_enumerator_t *data,
- addr_entry_t** in, host_t** out)
+CALLBACK(filter_addresses, bool,
+ address_enumerator_t *data, enumerator_t *orig, va_list args)
{
- host_t *ip;
- if (!(data->which & ADDR_TYPE_VIRTUAL) && (*in)->virtual)
- { /* skip virtual interfaces added by us */
- return FALSE;
- }
- if (!(data->which & ADDR_TYPE_REGULAR) && !(*in)->virtual)
- { /* address is regular, but not requested */
- return FALSE;
- }
- ip = (*in)->ip;
- if (ip->get_family(ip) == AF_INET6)
+ addr_entry_t *addr;
+ host_t *ip, **out;
+ struct sockaddr_in6 *sin6;
+
+ VA_ARGS_VGET(args, out);
+
+ while (orig->enumerate(orig, &addr))
{
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ip->get_sockaddr(ip);
- if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
- { /* skip addresses with a unusable scope */
- return FALSE;
+ if (!(data->which & ADDR_TYPE_VIRTUAL) && addr->virtual)
+ { /* skip virtual interfaces added by us */
+ continue;
}
+ if (!(data->which & ADDR_TYPE_REGULAR) && !addr->virtual)
+ { /* address is regular, but not requested */
+ continue;
+ }
+ ip = addr->ip;
+ if (ip->get_family(ip) == AF_INET6)
+ {
+ sin6 = (struct sockaddr_in6 *)ip->get_sockaddr(ip);
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
+ { /* skip addresses with a unusable scope */
+ continue;
+ }
+ }
+ *out = ip;
+ return TRUE;
}
- *out = ip;
- return TRUE;
+ return FALSE;
}
/**
@@ -1094,29 +1102,34 @@ static enumerator_t *create_iface_enumerator(iface_entry_t *iface,
address_enumerator_t *data)
{
return enumerator_create_filter(iface->addrs->create_enumerator(iface->addrs),
- (void*)filter_addresses, data, NULL);
+ filter_addresses, data, NULL);
}
-/**
- * filter for interfaces
- */
-static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in,
- iface_entry_t** out)
+CALLBACK(filter_interfaces, bool,
+ address_enumerator_t *data, enumerator_t *orig, va_list args)
{
- if (!(data->which & ADDR_TYPE_IGNORED) && !(*in)->usable)
- { /* skip interfaces excluded by config */
- return FALSE;
- }
- if (!(data->which & ADDR_TYPE_LOOPBACK) && ((*in)->flags & IFF_LOOPBACK))
- { /* ignore loopback devices */
- return FALSE;
- }
- if (!(data->which & ADDR_TYPE_DOWN) && !((*in)->flags & IFF_UP))
- { /* skip interfaces not up */
- return FALSE;
+ iface_entry_t *iface, **out;
+
+ VA_ARGS_VGET(args, out);
+
+ while (orig->enumerate(orig, &iface))
+ {
+ if (!(data->which & ADDR_TYPE_IGNORED) && !iface->usable)
+ { /* skip interfaces excluded by config */
+ continue;
+ }
+ if (!(data->which & ADDR_TYPE_LOOPBACK) && (iface->flags & IFF_LOOPBACK))
+ { /* ignore loopback devices */
+ continue;
+ }
+ if (!(data->which & ADDR_TYPE_DOWN) && !(iface->flags & IFF_UP))
+ { /* skip interfaces not up */
+ continue;
+ }
+ *out = iface;
+ return TRUE;
}
- *out = *in;
- return TRUE;
+ return FALSE;
}
METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
@@ -1133,9 +1146,9 @@ METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
return enumerator_create_nested(
enumerator_create_filter(
this->ifaces->create_enumerator(this->ifaces),
- (void*)filter_interfaces, data, NULL),
+ filter_interfaces, data, NULL),
(void*)create_iface_enumerator, data,
- (void*)address_enumerator_destroy);
+ address_enumerator_destroy);
}
METHOD(kernel_net_t, get_features, kernel_feature_t,
@@ -1789,13 +1802,18 @@ METHOD(enumerator_t, destroy_subnet_enumerator, void,
}
METHOD(enumerator_t, enumerate_subnets, bool,
- subnet_enumerator_t *this, host_t **net, uint8_t *mask, char **ifname)
+ subnet_enumerator_t *this, va_list args)
{
enumerator_t *enumerator;
+ host_t **net;
struct rt_msghdr *rtm;
struct sockaddr *addr;
+ uint8_t *mask;
+ char **ifname;
int type;
+ VA_ARGS_VGET(args, net, mask, ifname);
+
if (!this->current)
{
this->current = this->buf;
@@ -1888,7 +1906,8 @@ METHOD(kernel_net_t, create_local_subnet_enumerator, enumerator_t*,
INIT(enumerator,
.public = {
- .enumerate = (void*)_enumerate_subnets,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _enumerate_subnets,
.destroy = _destroy_subnet_enumerator,
},
.buf = buf,
diff --git a/src/libcharon/plugins/kernel_wfp/Makefile.in b/src/libcharon/plugins/kernel_wfp/Makefile.in
index a3368d56f..ffdae84c0 100644
--- a/src/libcharon/plugins/kernel_wfp/Makefile.in
+++ b/src/libcharon/plugins/kernel_wfp/Makefile.in
@@ -366,6 +366,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -388,6 +389,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/led/Makefile.in b/src/libcharon/plugins/led/Makefile.in
index f16304dbc..7f820292d 100644
--- a/src/libcharon/plugins/led/Makefile.in
+++ b/src/libcharon/plugins/led/Makefile.in
@@ -355,6 +355,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -377,6 +378,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/load_tester/Makefile.in b/src/libcharon/plugins/load_tester/Makefile.in
index c6e17fb83..c55e3578c 100644
--- a/src/libcharon/plugins/load_tester/Makefile.in
+++ b/src/libcharon/plugins/load_tester/Makefile.in
@@ -368,6 +368,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -390,6 +391,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/load_tester/load_tester_creds.c b/src/libcharon/plugins/load_tester/load_tester_creds.c
index 2f482962a..2cedd130e 100644
--- a/src/libcharon/plugins/load_tester/load_tester_creds.c
+++ b/src/libcharon/plugins/load_tester/load_tester_creds.c
@@ -395,22 +395,28 @@ METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
return NULL;
}
-/**
- * Filter function for shared keys, returning ID matches
- */
-static bool shared_filter(void *null, shared_key_t **in, shared_key_t **out,
- void **un1, id_match_t *me, void **un2, id_match_t *other)
+CALLBACK(shared_filter, bool,
+ void *null, enumerator_t *orig, va_list args)
{
- *out = *in;
- if (me)
- {
- *me = ID_MATCH_ANY;
- }
- if (other)
+ shared_key_t *key, **out;
+ id_match_t *me, *other;
+
+ VA_ARGS_VGET(args, out, me, other);
+
+ if (orig->enumerate(orig, &key))
{
- *other = ID_MATCH_ANY;
+ *out = key;
+ if (me)
+ {
+ *me = ID_MATCH_ANY;
+ }
+ if (other)
+ {
+ *other = ID_MATCH_ANY;
+ }
+ return TRUE;
}
- return TRUE;
+ return FALSE;
}
METHOD(credential_set_t, create_shared_enumerator, enumerator_t*,
@@ -431,7 +437,7 @@ METHOD(credential_set_t, create_shared_enumerator, enumerator_t*,
return NULL;
}
return enumerator_create_filter(enumerator_create_single(shared, NULL),
- (void*)shared_filter, NULL, NULL);
+ shared_filter, NULL, NULL);
}
METHOD(load_tester_creds_t, destroy, void,
diff --git a/src/libcharon/plugins/lookip/Makefile.in b/src/libcharon/plugins/lookip/Makefile.in
index 919060469..ba86d3788 100644
--- a/src/libcharon/plugins/lookip/Makefile.in
+++ b/src/libcharon/plugins/lookip/Makefile.in
@@ -364,6 +364,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -386,6 +387,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/medcli/Makefile.in b/src/libcharon/plugins/medcli/Makefile.in
index 4db68a3fc..e2d63be1c 100644
--- a/src/libcharon/plugins/medcli/Makefile.in
+++ b/src/libcharon/plugins/medcli/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c
index 78159c845..f34990176 100644
--- a/src/libcharon/plugins/medcli/medcli_config.c
+++ b/src/libcharon/plugins/medcli/medcli_config.c
@@ -223,10 +223,11 @@ typedef struct {
} peer_enumerator_t;
METHOD(enumerator_t, peer_enumerator_enumerate, bool,
- peer_enumerator_t *this, peer_cfg_t **cfg)
+ peer_enumerator_t *this, va_list args)
{
char *name, *local_net, *remote_net;
chunk_t me, other;
+ peer_cfg_t **cfg;
child_cfg_t *child_cfg;
auth_cfg_t *auth;
peer_cfg_create_t peer = {
@@ -249,6 +250,8 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
.mode = MODE_TUNNEL,
};
+ VA_ARGS_VGET(args, cfg);
+
DESTROY_IF(this->current);
if (!this->inner->enumerate(this->inner, &name, &me, &other,
&local_net, &remote_net))
@@ -295,7 +298,8 @@ METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
INIT(e,
.public = {
- .enumerate = (void*)_peer_enumerator_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _peer_enumerator_enumerate,
.destroy = _peer_enumerator_destroy,
},
.ike = this->ike,
diff --git a/src/libcharon/plugins/medcli/medcli_creds.c b/src/libcharon/plugins/medcli/medcli_creds.c
index 677229b9f..528fc004d 100644
--- a/src/libcharon/plugins/medcli/medcli_creds.c
+++ b/src/libcharon/plugins/medcli/medcli_creds.c
@@ -50,10 +50,13 @@ typedef struct {
} private_enumerator_t;
METHOD(enumerator_t, private_enumerator_enumerate, bool,
- private_enumerator_t *this, private_key_t **key)
+ private_enumerator_t *this, va_list args)
{
+ private_key_t **key;
chunk_t chunk;
+ VA_ARGS_VGET(args, key);
+
DESTROY_IF(this->current);
while (this->inner->enumerate(this->inner, &chunk))
{
@@ -92,7 +95,8 @@ METHOD(credential_set_t, create_private_enumerator, enumerator_t*,
INIT(e,
.public = {
- .enumerate = (void*)_private_enumerator_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _private_enumerator_enumerate,
.destroy = _private_enumerator_destroy,
},
);
@@ -123,11 +127,14 @@ typedef struct {
} cert_enumerator_t;
METHOD(enumerator_t, cert_enumerator_enumerate, bool,
- cert_enumerator_t *this, certificate_t **cert)
+ cert_enumerator_t *this, va_list args)
{
+ certificate_t **cert;
public_key_t *public;
chunk_t chunk;
+ VA_ARGS_VGET(args, cert);
+
DESTROY_IF(this->current);
while (this->inner->enumerate(this->inner, &chunk))
{
@@ -180,7 +187,8 @@ METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
INIT(e,
.public = {
- .enumerate = (void*)_cert_enumerator_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _cert_enumerator_enumerate,
.destroy = _cert_enumerator_destroy,
},
.type = key,
diff --git a/src/libcharon/plugins/medcli/medcli_creds.h b/src/libcharon/plugins/medcli/medcli_creds.h
index 4b5402653..ec17955a2 100644
--- a/src/libcharon/plugins/medcli/medcli_creds.h
+++ b/src/libcharon/plugins/medcli/medcli_creds.h
@@ -37,7 +37,7 @@ struct medcli_creds_t {
credential_set_t set;
/**
- * Destroy the credentials databse.
+ * Destroy the credentials database.
*/
void (*destroy)(medcli_creds_t *this);
};
diff --git a/src/libcharon/plugins/medcli/medcli_listener.h b/src/libcharon/plugins/medcli/medcli_listener.h
index 4768beccd..860dcdc60 100644
--- a/src/libcharon/plugins/medcli/medcli_listener.h
+++ b/src/libcharon/plugins/medcli/medcli_listener.h
@@ -37,7 +37,7 @@ struct medcli_listener_t {
listener_t listener;
/**
- * Destroy the credentials databse.
+ * Destroy the credentials database.
*/
void (*destroy)(medcli_listener_t *this);
};
diff --git a/src/libcharon/plugins/medsrv/Makefile.in b/src/libcharon/plugins/medsrv/Makefile.in
index ceb06deb1..10b48daa3 100644
--- a/src/libcharon/plugins/medsrv/Makefile.in
+++ b/src/libcharon/plugins/medsrv/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/medsrv/medsrv_creds.c b/src/libcharon/plugins/medsrv/medsrv_creds.c
index 0d99c4f77..16d4bd7f3 100644
--- a/src/libcharon/plugins/medsrv/medsrv_creds.c
+++ b/src/libcharon/plugins/medsrv/medsrv_creds.c
@@ -52,12 +52,14 @@ typedef struct {
} cert_enumerator_t;
METHOD(enumerator_t, cert_enumerator_enumerate, bool,
- cert_enumerator_t *this, certificate_t **cert)
+ cert_enumerator_t *this, va_list args)
{
- certificate_t *trusted;
+ certificate_t *trusted, **cert;
public_key_t *public;
chunk_t chunk;
+ VA_ARGS_VGET(args, cert);
+
DESTROY_IF(this->current);
while (this->inner->enumerate(this->inner, &chunk))
{
@@ -110,7 +112,8 @@ METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
INIT(e,
.public = {
- .enumerate = (void*)_cert_enumerator_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _cert_enumerator_enumerate,
.destroy = _cert_enumerator_destroy,
},
.type = key,
diff --git a/src/libcharon/plugins/medsrv/medsrv_creds.h b/src/libcharon/plugins/medsrv/medsrv_creds.h
index 2079601af..08ecaa3f2 100644
--- a/src/libcharon/plugins/medsrv/medsrv_creds.h
+++ b/src/libcharon/plugins/medsrv/medsrv_creds.h
@@ -37,7 +37,7 @@ struct medsrv_creds_t {
credential_set_t set;
/**
- * Destroy the credentials databse.
+ * Destroy the credentials database.
*/
void (*destroy)(medsrv_creds_t *this);
};
diff --git a/src/libcharon/plugins/osx_attr/Makefile.in b/src/libcharon/plugins/osx_attr/Makefile.in
index ab9ece561..8e0b10eb0 100644
--- a/src/libcharon/plugins/osx_attr/Makefile.in
+++ b/src/libcharon/plugins/osx_attr/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/osx_attr/osx_attr_handler.c b/src/libcharon/plugins/osx_attr/osx_attr_handler.c
index 6baf76d35..e7a627b93 100644
--- a/src/libcharon/plugins/osx_attr/osx_attr_handler.c
+++ b/src/libcharon/plugins/osx_attr/osx_attr_handler.c
@@ -218,12 +218,15 @@ METHOD(attribute_handler_t, release, void,
}
METHOD(enumerator_t, enumerate_dns, bool,
- enumerator_t *this, configuration_attribute_type_t *type, chunk_t *data)
+ enumerator_t *this, va_list args)
{
+ configuration_attribute_type_t *type;
+ chunk_t *data;
+
+ VA_ARGS_VGET(args, type, data);
*type = INTERNAL_IP4_DNS;
*data = chunk_empty;
- /* stop enumeration */
- this->enumerate = (void*)return_false;
+ this->venumerate = (void*)return_false;
return TRUE;
}
@@ -234,7 +237,8 @@ METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *,
enumerator_t *enumerator;
INIT(enumerator,
- .enumerate = (void*)_enumerate_dns,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _enumerate_dns,
.destroy = (void*)free,
);
return enumerator;
diff --git a/src/libcharon/plugins/p_cscf/Makefile.in b/src/libcharon/plugins/p_cscf/Makefile.in
index 7b3cb2fa4..954a43dc8 100644
--- a/src/libcharon/plugins/p_cscf/Makefile.in
+++ b/src/libcharon/plugins/p_cscf/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/p_cscf/p_cscf_handler.c b/src/libcharon/plugins/p_cscf/p_cscf_handler.c
index 76633845e..cdf266054 100644
--- a/src/libcharon/plugins/p_cscf/p_cscf_handler.c
+++ b/src/libcharon/plugins/p_cscf/p_cscf_handler.c
@@ -83,9 +83,12 @@ typedef struct {
} attr_enumerator_t;
METHOD(enumerator_t, enumerate_attrs, bool,
- attr_enumerator_t *this, configuration_attribute_type_t *type,
- chunk_t *data)
+ attr_enumerator_t *this, va_list args)
{
+ configuration_attribute_type_t *type;
+ chunk_t *data;
+
+ VA_ARGS_VGET(args, type, data);
if (this->request_ipv4)
{
*type = P_CSCF_IP4_ADDRESS;
@@ -103,12 +106,13 @@ METHOD(enumerator_t, enumerate_attrs, bool,
return FALSE;
}
-/**
- * Check if the given host has a matching address family
- */
-static bool is_family(host_t *host, int *family)
+CALLBACK(is_family, bool,
+ host_t *host, va_list args)
{
- return host->get_family(host) == *family;
+ int family;
+
+ VA_ARGS_VGET(args, family);
+ return host->get_family(host) == family;
}
/**
@@ -116,7 +120,7 @@ static bool is_family(host_t *host, int *family)
*/
static bool has_host_family(linked_list_t *list, int family)
{
- return list->find_first(list, (void*)is_family, NULL, &family) == SUCCESS;
+ return list->find_first(list, is_family, NULL, family);
}
METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *,
@@ -132,7 +136,8 @@ METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *,
INIT(enumerator,
.public = {
- .enumerate = (void*)_enumerate_attrs,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _enumerate_attrs,
.destroy = (void*)free,
},
);
diff --git a/src/libcharon/plugins/radattr/Makefile.in b/src/libcharon/plugins/radattr/Makefile.in
index 1fe3033dc..add1f547f 100644
--- a/src/libcharon/plugins/radattr/Makefile.in
+++ b/src/libcharon/plugins/radattr/Makefile.in
@@ -359,6 +359,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -381,6 +382,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/resolve/Makefile.in b/src/libcharon/plugins/resolve/Makefile.in
index f8b62edf2..5e166f28f 100644
--- a/src/libcharon/plugins/resolve/Makefile.in
+++ b/src/libcharon/plugins/resolve/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/resolve/resolve_handler.c b/src/libcharon/plugins/resolve/resolve_handler.c
index 9077b51d4..05b865464 100644
--- a/src/libcharon/plugins/resolve/resolve_handler.c
+++ b/src/libcharon/plugins/resolve/resolve_handler.c
@@ -391,10 +391,13 @@ typedef struct {
bool v6;
} attribute_enumerator_t;
-static bool attribute_enumerate(attribute_enumerator_t *this,
- configuration_attribute_type_t *type,
- chunk_t *data)
+METHOD(enumerator_t, attribute_enumerate, bool,
+ attribute_enumerator_t *this, va_list args)
{
+ configuration_attribute_type_t *type;
+ chunk_t *data;
+
+ VA_ARGS_VGET(args, type, data);
if (this->v4)
{
*type = INTERNAL_IP4_DNS;
@@ -443,7 +446,8 @@ METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
INIT(enumerator,
.public = {
- .enumerate = (void*)attribute_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _attribute_enumerate,
.destroy = (void*)free,
},
.v4 = has_host_family(vips, AF_INET),
diff --git a/src/libcharon/plugins/smp/Makefile.in b/src/libcharon/plugins/smp/Makefile.in
index bf0791c42..9aac31894 100644
--- a/src/libcharon/plugins/smp/Makefile.in
+++ b/src/libcharon/plugins/smp/Makefile.in
@@ -356,6 +356,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -378,6 +379,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/socket_default/Makefile.in b/src/libcharon/plugins/socket_default/Makefile.in
index f66ae1679..b87afa4a6 100644
--- a/src/libcharon/plugins/socket_default/Makefile.in
+++ b/src/libcharon/plugins/socket_default/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c
index ba22b0c2b..109b3fe9b 100644
--- a/src/libcharon/plugins/socket_default/socket_default_socket.c
+++ b/src/libcharon/plugins/socket_default/socket_default_socket.c
@@ -142,6 +142,11 @@ struct private_socket_default_socket_t {
bool set_source;
/**
+ * TRUE to force sending source interface on outbound packetrs
+ */
+ bool set_sourceif;
+
+ /**
* A counter to implement round-robin selection of read sockets
*/
u_int rr_counter;
@@ -362,12 +367,33 @@ static ssize_t send_msg_generic(int skt, struct msghdr *msg)
return sendmsg(skt, msg, 0);
}
+#if defined(IP_PKTINFO) || defined(HAVE_IN6_PKTINFO)
+
+/**
+ * Find the interface index a source address is installed on
+ */
+static int find_srcif(host_t *src)
+{
+ char *ifname;
+ int idx = 0;
+
+ if (charon->kernel->get_interface(charon->kernel, src, &ifname))
+ {
+ idx = if_nametoindex(ifname);
+ free(ifname);
+ }
+ return idx;
+}
+
+#endif /* IP_PKTINFO || HAVE_IN6_PKTINFO */
+
/**
* Send a message with the IPv4 source address set, if possible.
*/
#ifdef IP_PKTINFO
-static ssize_t send_msg_v4(int skt, struct msghdr *msg, host_t *src)
+static ssize_t send_msg_v4(private_socket_default_socket_t *this, int skt,
+ struct msghdr *msg, host_t *src)
{
char buf[CMSG_SPACE(sizeof(struct in_pktinfo))] = {};
struct cmsghdr *cmsg;
@@ -383,6 +409,10 @@ static ssize_t send_msg_v4(int skt, struct msghdr *msg, host_t *src)
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
+ if (this->set_sourceif)
+ {
+ pktinfo->ipi_ifindex = find_srcif(src);
+ }
addr = &pktinfo->ipi_spec_dst;
sin = (struct sockaddr_in*)src->get_sockaddr(src);
@@ -392,7 +422,8 @@ static ssize_t send_msg_v4(int skt, struct msghdr *msg, host_t *src)
#elif defined(IP_SENDSRCADDR)
-static ssize_t send_msg_v4(int skt, struct msghdr *msg, host_t *src)
+static ssize_t send_msg_v4(private_socket_default_socket_t *this, int skt,
+ struct msghdr *msg, host_t *src)
{
char buf[CMSG_SPACE(sizeof(struct in_addr))] = {};
struct cmsghdr *cmsg;
@@ -415,7 +446,8 @@ static ssize_t send_msg_v4(int skt, struct msghdr *msg, host_t *src)
#else /* IP_PKTINFO || IP_RECVDSTADDR */
-static ssize_t send_msg_v4(int skt, struct msghdr *msg, host_t *src)
+static ssize_t send_msg_v4(private_socket_default_socket_t *this,
+ int skt, struct msghdr *msg, host_t *src)
{
return send_msg_generic(skt, msg);
}
@@ -427,7 +459,8 @@ static ssize_t send_msg_v4(int skt, struct msghdr *msg, host_t *src)
*/
#ifdef HAVE_IN6_PKTINFO
-static ssize_t send_msg_v6(int skt, struct msghdr *msg, host_t *src)
+static ssize_t send_msg_v6(private_socket_default_socket_t *this, int skt,
+ struct msghdr *msg, host_t *src)
{
char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))] = {};
struct cmsghdr *cmsg;
@@ -441,6 +474,10 @@ static ssize_t send_msg_v6(int skt, struct msghdr *msg, host_t *src)
cmsg->cmsg_type = IPV6_PKTINFO;
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
+ if (this->set_sourceif)
+ {
+ pktinfo->ipi6_ifindex = find_srcif(src);
+ }
sin = (struct sockaddr_in6*)src->get_sockaddr(src);
memcpy(&pktinfo->ipi6_addr, &sin->sin6_addr, sizeof(struct in6_addr));
return send_msg_generic(skt, msg);
@@ -448,7 +485,8 @@ static ssize_t send_msg_v6(int skt, struct msghdr *msg, host_t *src)
#else /* HAVE_IN6_PKTINFO */
-static ssize_t send_msg_v6(int skt, struct msghdr *msg, host_t *src)
+static ssize_t send_msg_v6(private_socket_default_socket_t *this,
+ int skt, struct msghdr *msg, host_t *src)
{
return send_msg_generic(skt, msg);
}
@@ -564,11 +602,11 @@ METHOD(socket_t, sender, status_t,
{
if (family == AF_INET)
{
- bytes_sent = send_msg_v4(skt, &msg, src);
+ bytes_sent = send_msg_v4(this, skt, &msg, src);
}
else
{
- bytes_sent = send_msg_v6(skt, &msg, src);
+ bytes_sent = send_msg_v6(this, skt, &msg, src);
}
}
else
@@ -831,6 +869,9 @@ socket_default_socket_t *socket_default_socket_create()
.set_source = lib->settings->get_bool(lib->settings,
"%s.plugins.socket-default.set_source", TRUE,
lib->ns),
+ .set_sourceif = lib->settings->get_bool(lib->settings,
+ "%s.plugins.socket-default.set_sourceif", FALSE,
+ lib->ns),
);
if (this->port && this->port == this->natt)
diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.in b/src/libcharon/plugins/socket_dynamic/Makefile.in
index 3d07b5407..595651f21 100644
--- a/src/libcharon/plugins/socket_dynamic/Makefile.in
+++ b/src/libcharon/plugins/socket_dynamic/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/socket_win/Makefile.in b/src/libcharon/plugins/socket_win/Makefile.in
index 692489845..8f1e43926 100644
--- a/src/libcharon/plugins/socket_win/Makefile.in
+++ b/src/libcharon/plugins/socket_win/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/sql/Makefile.in b/src/libcharon/plugins/sql/Makefile.in
index 581225b55..5c146190d 100644
--- a/src/libcharon/plugins/sql/Makefile.in
+++ b/src/libcharon/plugins/sql/Makefile.in
@@ -356,6 +356,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -378,6 +379,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c
index 88cac7f26..00ed693eb 100644
--- a/src/libcharon/plugins/sql/sql_config.c
+++ b/src/libcharon/plugins/sql/sql_config.c
@@ -173,7 +173,8 @@ static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e)
child_cfg_create_t child = {
.mode = mode,
.reqid = reqid,
- .ipcomp = ipcomp,
+ .options = (ipcomp ? OPT_IPCOMP : 0) |
+ (hostaccess ? OPT_HOSTACCESS : 0),
.lifetime = {
.time = {
.life = lifetime, .rekey = rekeytime, .jitter = jitter
@@ -183,7 +184,6 @@ static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e)
.dpd_action = dpd,
.close_action = close,
.updown = updown,
- .hostaccess = hostaccess,
};
child_cfg = child_cfg_create(name, &child);
add_esp_proposals(this, child_cfg, id);
@@ -504,11 +504,12 @@ typedef struct {
ike_cfg_t *current;
} ike_enumerator_t;
-/**
- * Implementation of ike_enumerator_t.public.enumerate
- */
-static bool ike_enumerator_enumerate(ike_enumerator_t *this, ike_cfg_t **cfg)
+METHOD(enumerator_t, ike_enumerator_enumerate, bool,
+ ike_enumerator_t *this, va_list args)
{
+ ike_cfg_t **cfg;
+
+ VA_ARGS_VGET(args, cfg);
DESTROY_IF(this->current);
this->current = build_ike_cfg(this->this, this->inner, this->me, this->other);
if (this->current)
@@ -519,10 +520,8 @@ static bool ike_enumerator_enumerate(ike_enumerator_t *this, ike_cfg_t **cfg)
return FALSE;
}
-/**
- * Implementation of ike_enumerator_t.public.destroy
- */
-static void ike_enumerator_destroy(ike_enumerator_t *this)
+METHOD(enumerator_t, ike_enumerator_destroy, void,
+ ike_enumerator_t *this)
{
DESTROY_IF(this->current);
this->inner->destroy(this->inner);
@@ -532,19 +531,22 @@ static void ike_enumerator_destroy(ike_enumerator_t *this)
METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
private_sql_config_t *this, host_t *me, host_t *other)
{
- ike_enumerator_t *e = malloc_thing(ike_enumerator_t);
-
- e->this = this;
- e->me = me;
- e->other = other;
- e->current = NULL;
- e->public.enumerate = (void*)ike_enumerator_enumerate;
- e->public.destroy = (void*)ike_enumerator_destroy;
+ ike_enumerator_t *e;
+ INIT(e,
+ .public = {
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _ike_enumerator_enumerate,
+ .destroy = _ike_enumerator_destroy,
+ },
+ .this = this,
+ .me = me,
+ .other = other,
+ );
e->inner = this->db->query(this->db,
- "SELECT id, certreq, force_encap, local, remote "
- "FROM ike_configs",
- DB_INT, DB_INT, DB_INT, DB_TEXT, DB_TEXT);
+ "SELECT id, certreq, force_encap, local, remote "
+ "FROM ike_configs",
+ DB_INT, DB_INT, DB_INT, DB_TEXT, DB_TEXT);
if (!e->inner)
{
free(e);
@@ -569,11 +571,12 @@ typedef struct {
peer_cfg_t *current;
} peer_enumerator_t;
-/**
- * Implementation of peer_enumerator_t.public.enumerate
- */
-static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
+METHOD(enumerator_t, peer_enumerator_enumerate, bool,
+ peer_enumerator_t *this, va_list args)
{
+ peer_cfg_t **cfg;
+
+ VA_ARGS_VGET(args, cfg);
DESTROY_IF(this->current);
this->current = build_peer_cfg(this->this, this->inner, this->me, this->other);
if (this->current)
@@ -584,10 +587,8 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
return FALSE;
}
-/**
- * Implementation of peer_enumerator_t.public.destroy
- */
-static void peer_enumerator_destroy(peer_enumerator_t *this)
+METHOD(enumerator_t, peer_enumerator_destroy, void,
+ peer_enumerator_t *this)
{
DESTROY_IF(this->current);
this->inner->destroy(this->inner);
@@ -597,14 +598,18 @@ static void peer_enumerator_destroy(peer_enumerator_t *this)
METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
private_sql_config_t *this, identification_t *me, identification_t *other)
{
- peer_enumerator_t *e = malloc_thing(peer_enumerator_t);
-
- e->this = this;
- e->me = me;
- e->other = other;
- e->current = NULL;
- e->public.enumerate = (void*)peer_enumerator_enumerate;
- e->public.destroy = (void*)peer_enumerator_destroy;
+ peer_enumerator_t *e;
+
+ INIT(e,
+ .public = {
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _peer_enumerator_enumerate,
+ .destroy = _peer_enumerator_destroy,
+ },
+ .this = this,
+ .me = me,
+ .other = other,
+ );
/* TODO: only get configs whose IDs match exactly or contain wildcards */
e->inner = this->db->query(this->db,
diff --git a/src/libcharon/plugins/sql/sql_cred.c b/src/libcharon/plugins/sql/sql_cred.c
index 117eec921..3317de6c8 100644
--- a/src/libcharon/plugins/sql/sql_cred.c
+++ b/src/libcharon/plugins/sql/sql_cred.c
@@ -52,11 +52,14 @@ typedef struct {
} private_enumerator_t;
METHOD(enumerator_t, private_enumerator_enumerate, bool,
- private_enumerator_t *this, private_key_t **key)
+ private_enumerator_t *this, va_list args)
{
+ private_key_t **key;
chunk_t blob;
int type;
+ VA_ARGS_VGET(args, key);
+
DESTROY_IF(this->current);
while (this->inner->enumerate(this->inner, &type, &blob))
{
@@ -88,7 +91,8 @@ METHOD(credential_set_t, create_private_enumerator, enumerator_t*,
INIT(e,
.public = {
- .enumerate = (void*)_private_enumerator_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _private_enumerator_enumerate,
.destroy = _private_enumerator_destroy,
},
);
@@ -132,11 +136,14 @@ typedef struct {
} cert_enumerator_t;
METHOD(enumerator_t, cert_enumerator_enumerate, bool,
- cert_enumerator_t *this, certificate_t **cert)
+ cert_enumerator_t *this, va_list args)
{
+ certificate_t **cert;
chunk_t blob;
int type;
+ VA_ARGS_VGET(args, cert);
+
DESTROY_IF(this->current);
while (this->inner->enumerate(this->inner, &type, &blob))
{
@@ -169,7 +176,8 @@ METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
INIT(e,
.public = {
- .enumerate = (void*)_cert_enumerator_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _cert_enumerator_enumerate,
.destroy = _cert_enumerator_destroy,
},
);
@@ -221,12 +229,15 @@ typedef struct {
} shared_enumerator_t;
METHOD(enumerator_t, shared_enumerator_enumerate, bool,
- shared_enumerator_t *this, shared_key_t **shared,
- id_match_t *me, id_match_t *other)
+ shared_enumerator_t *this, va_list args)
{
+ shared_key_t **shared;
+ id_match_t *me, *other;
chunk_t blob;
int type;
+ VA_ARGS_VGET(args, shared, me, other);
+
DESTROY_IF(this->current);
while (this->inner->enumerate(this->inner, &type, &blob))
{
@@ -265,7 +276,8 @@ METHOD(credential_set_t, create_shared_enumerator, enumerator_t*,
INIT(e,
.public = {
- .enumerate = (void*)_shared_enumerator_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _shared_enumerator_enumerate,
.destroy = _shared_enumerator_destroy,
},
.me = me,
@@ -340,9 +352,11 @@ typedef enum {
} cdp_type_t;
METHOD(enumerator_t, cdp_enumerator_enumerate, bool,
- cdp_enumerator_t *this, char **uri)
+ cdp_enumerator_t *this, va_list args)
{
- char *text;
+ char *text, **uri;
+
+ VA_ARGS_VGET(args, uri);
free(this->current);
while (this->inner->enumerate(this->inner, &text))
@@ -384,7 +398,8 @@ METHOD(credential_set_t, create_cdp_enumerator, enumerator_t*,
}
INIT(e,
.public = {
- .enumerate = (void*)_cdp_enumerator_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _cdp_enumerator_enumerate,
.destroy = _cdp_enumerator_destroy,
},
);
diff --git a/src/libcharon/plugins/stroke/Makefile.in b/src/libcharon/plugins/stroke/Makefile.in
index 50a6d5953..0af607fd7 100644
--- a/src/libcharon/plugins/stroke/Makefile.in
+++ b/src/libcharon/plugins/stroke/Makefile.in
@@ -360,6 +360,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -382,6 +383,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/stroke/stroke_attribute.c b/src/libcharon/plugins/stroke/stroke_attribute.c
index cd1b4d093..7835031c2 100644
--- a/src/libcharon/plugins/stroke/stroke_attribute.c
+++ b/src/libcharon/plugins/stroke/stroke_attribute.c
@@ -178,28 +178,32 @@ METHOD(attribute_provider_t, release_address, bool,
return found;
}
-/**
- * Filter function to convert host to DNS configuration attributes
- */
-static bool attr_filter(void *lock, host_t **in,
- configuration_attribute_type_t *type,
- void *dummy, chunk_t *data)
+CALLBACK(attr_filter, bool,
+ void *lock, enumerator_t *orig, va_list args)
{
- host_t *host = *in;
+ configuration_attribute_type_t *type;
+ chunk_t *data;
+ host_t *host;
- switch (host->get_family(host))
+ VA_ARGS_VGET(args, type, data);
+
+ while (orig->enumerate(orig, &host))
{
- case AF_INET:
- *type = INTERNAL_IP4_DNS;
- break;
- case AF_INET6:
- *type = INTERNAL_IP6_DNS;
- break;
- default:
- return FALSE;
+ switch (host->get_family(host))
+ {
+ case AF_INET:
+ *type = INTERNAL_IP4_DNS;
+ break;
+ case AF_INET6:
+ *type = INTERNAL_IP6_DNS;
+ break;
+ default:
+ continue;
+ }
+ *data = host->get_address(host);
+ return TRUE;
}
- *data = host->get_address(host);
- return TRUE;
+ return FALSE;
}
METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
@@ -223,7 +227,7 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
enumerator->destroy(enumerator);
return enumerator_create_filter(
attr->dns->create_enumerator(attr->dns),
- (void*)attr_filter, this->lock,
+ attr_filter, this->lock,
(void*)this->lock->unlock);
}
}
@@ -338,24 +342,28 @@ METHOD(stroke_attribute_t, del_dns, void,
this->lock->unlock(this->lock);
}
-/**
- * Pool enumerator filter function, converts pool_t to name, size, ...
- */
-static bool pool_filter(void *lock, mem_pool_t **poolp, const char **name,
- void *d1, u_int *size, void *d2, u_int *online,
- void *d3, u_int *offline)
+CALLBACK(pool_filter, bool,
+ void *lock, enumerator_t *orig, va_list args)
{
- mem_pool_t *pool = *poolp;
+ mem_pool_t *pool;
+ const char **name;
+ u_int *size, *online, *offline;
- if (pool->get_size(pool) == 0)
+ VA_ARGS_VGET(args, name, size, online, offline);
+
+ while (orig->enumerate(orig, &pool))
{
- return FALSE;
+ if (pool->get_size(pool) == 0)
+ {
+ continue;
+ }
+ *name = pool->get_name(pool);
+ *size = pool->get_size(pool);
+ *online = pool->get_online(pool);
+ *offline = pool->get_offline(pool);
+ return TRUE;
}
- *name = pool->get_name(pool);
- *size = pool->get_size(pool);
- *online = pool->get_online(pool);
- *offline = pool->get_offline(pool);
- return TRUE;
+ return FALSE;
}
METHOD(stroke_attribute_t, create_pool_enumerator, enumerator_t*,
@@ -363,7 +371,7 @@ METHOD(stroke_attribute_t, create_pool_enumerator, enumerator_t*,
{
this->lock->read_lock(this->lock);
return enumerator_create_filter(this->pools->create_enumerator(this->pools),
- (void*)pool_filter,
+ pool_filter,
this->lock, (void*)this->lock->unlock);
}
diff --git a/src/libcharon/plugins/stroke/stroke_ca.c b/src/libcharon/plugins/stroke/stroke_ca.c
index 13ed41e0e..4593e9bdc 100644
--- a/src/libcharon/plugins/stroke/stroke_ca.c
+++ b/src/libcharon/plugins/stroke/stroke_ca.c
@@ -171,26 +171,30 @@ typedef struct {
identification_t *id;
} cert_data_t;
-/**
- * destroy cert_data
- */
-static void cert_data_destroy(cert_data_t *data)
+CALLBACK(cert_data_destroy, void,
+ cert_data_t *data)
{
data->this->lock->unlock(data->this->lock);
free(data);
}
-/**
- * filter function for certs enumerator
- */
-static bool certs_filter(cert_data_t *data, ca_cert_t **in,
- certificate_t **out)
+CALLBACK(certs_filter, bool,
+ cert_data_t *data, enumerator_t *orig, va_list args)
{
+ ca_cert_t *cacert;
public_key_t *public;
- certificate_t *cert = (*in)->cert;
+ certificate_t **out;
+
+ VA_ARGS_VGET(args, out);
- if (data->cert == CERT_ANY || data->cert == cert->get_type(cert))
+ while (orig->enumerate(orig, &cacert))
{
+ certificate_t *cert = cacert->cert;
+
+ if (data->cert != CERT_ANY && data->cert != cert->get_type(cert))
+ {
+ continue;
+ }
public = cert->get_public_key(cert);
if (public)
{
@@ -208,9 +212,9 @@ static bool certs_filter(cert_data_t *data, ca_cert_t **in,
}
else if (data->key != KEY_ANY)
{
- return FALSE;
+ continue;
}
- if (data->id == NULL || cert->has_subject(cert, data->id))
+ if (!data->id || cert->has_subject(cert, data->id))
{
*out = cert;
return TRUE;
@@ -235,8 +239,8 @@ METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
this->lock->read_lock(this->lock);
enumerator = this->certs->create_enumerator(this->certs);
- return enumerator_create_filter(enumerator, (void*)certs_filter, data,
- (void*)cert_data_destroy);
+ return enumerator_create_filter(enumerator, certs_filter, data,
+ cert_data_destroy);
}
/**
@@ -354,11 +358,12 @@ METHOD(credential_set_t, create_cdp_enumerator, enumerator_t*,
data, (void*)cdp_data_destroy);
}
-/**
- * Compare the given certificate to the ca_cert_t items in the list
- */
-static bool match_cert(ca_cert_t *item, certificate_t *cert)
+CALLBACK(match_cert, bool,
+ ca_cert_t *item, va_list args)
{
+ certificate_t *cert;
+
+ VA_ARGS_VGET(args, cert);
return cert->equals(cert, item->cert);
}
@@ -405,8 +410,7 @@ static certificate_t *add_cert_internal(private_stroke_ca_t *this,
{
ca_cert_t *found;
- if (this->certs->find_first(this->certs, (linked_list_match_t)match_cert,
- (void**)&found, cert) == SUCCESS)
+ if (this->certs->find_first(this->certs, match_cert, (void**)&found, cert))
{
cert->destroy(cert);
cert = found->cert->get_ref(found->cert);
@@ -511,8 +515,7 @@ METHOD(stroke_ca_t, get_cert_ref, certificate_t*,
ca_cert_t *found;
this->lock->read_lock(this->lock);
- if (this->certs->find_first(this->certs, (linked_list_match_t)match_cert,
- (void**)&found, cert) == SUCCESS)
+ if (this->certs->find_first(this->certs, match_cert, (void**)&found, cert))
{
cert->destroy(cert);
cert = found->cert->get_ref(found->cert);
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index bbdc2116d..00f74831c 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -68,13 +68,20 @@ METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
(void*)this->mutex->unlock, this->mutex);
}
-/**
- * filter function for ike configs
- */
-static bool ike_filter(void *data, peer_cfg_t **in, ike_cfg_t **out)
+CALLBACK(ike_filter, bool,
+ void *data, enumerator_t *orig, va_list args)
{
- *out = (*in)->get_ike_cfg(*in);
- return TRUE;
+ peer_cfg_t *cfg;
+ ike_cfg_t **out;
+
+ VA_ARGS_VGET(args, out);
+
+ if (orig->enumerate(orig, &cfg))
+ {
+ *out = cfg->get_ike_cfg(cfg);
+ return TRUE;
+ }
+ return FALSE;
}
METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
@@ -82,7 +89,7 @@ METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
{
this->mutex->lock(this->mutex);
return enumerator_create_filter(this->list->create_enumerator(this->list),
- (void*)ike_filter, this->mutex,
+ ike_filter, this->mutex,
(void*)this->mutex->unlock);
}
@@ -1071,15 +1078,16 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
},
.reqid = msg->add_conn.reqid,
.mode = msg->add_conn.mode,
- .proxy_mode = msg->add_conn.proxy_mode,
- .ipcomp = msg->add_conn.ipcomp,
+ .options = (msg->add_conn.proxy_mode ? OPT_PROXY_MODE : 0) |
+ (msg->add_conn.ipcomp ? OPT_IPCOMP : 0) |
+ (msg->add_conn.me.hostaccess ? OPT_HOSTACCESS : 0) |
+ (msg->add_conn.install_policy ? 0 : OPT_NO_POLICIES) |
+ (msg->add_conn.sha256_96 ? OPT_SHA256_96 : 0),
.tfc = msg->add_conn.tfc,
.inactivity = msg->add_conn.inactivity,
.dpd_action = map_action(msg->add_conn.dpd.action),
.close_action = map_action(msg->add_conn.close_action),
.updown = msg->add_conn.me.updown,
- .hostaccess = msg->add_conn.me.hostaccess,
- .suppress_policies = !msg->add_conn.install_policy,
};
child_cfg = child_cfg_create(msg->add_conn.name, &child);
diff --git a/src/libcharon/plugins/stroke/stroke_handler.c b/src/libcharon/plugins/stroke/stroke_handler.c
index d0cc9afab..19d5a62a1 100644
--- a/src/libcharon/plugins/stroke/stroke_handler.c
+++ b/src/libcharon/plugins/stroke/stroke_handler.c
@@ -62,35 +62,39 @@ static void attributes_destroy(attributes_t *this)
free(this);
}
-/**
- * Filter function to convert host to DNS configuration attributes
- */
-static bool attr_filter(void *lock, host_t **in,
- configuration_attribute_type_t *type,
- void *dummy, chunk_t *data)
+CALLBACK(attr_filter, bool,
+ void *lock, enumerator_t *orig, va_list args)
{
- host_t *host = *in;
+ configuration_attribute_type_t *type;
+ chunk_t *data;
+ host_t *host;
- switch (host->get_family(host))
- {
- case AF_INET:
- *type = INTERNAL_IP4_DNS;
- break;
- case AF_INET6:
- *type = INTERNAL_IP6_DNS;
- break;
- default:
- return FALSE;
- }
- if (host->is_anyaddr(host))
- {
- *data = chunk_empty;
- }
- else
+ VA_ARGS_VGET(args, type, data);
+
+ while (orig->enumerate(orig, &host))
{
- *data = host->get_address(host);
+ switch (host->get_family(host))
+ {
+ case AF_INET:
+ *type = INTERNAL_IP4_DNS;
+ break;
+ case AF_INET6:
+ *type = INTERNAL_IP6_DNS;
+ break;
+ default:
+ continue;
+ }
+ if (host->is_anyaddr(host))
+ {
+ *data = chunk_empty;
+ }
+ else
+ {
+ *data = host->get_address(host);
+ }
+ return TRUE;
}
- return TRUE;
+ return FALSE;
}
METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
@@ -114,7 +118,7 @@ METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
enumerator->destroy(enumerator);
return enumerator_create_filter(
attr->dns->create_enumerator(attr->dns),
- (void*)attr_filter, this->lock,
+ attr_filter, this->lock,
(void*)this->lock->unlock);
}
}
diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c
index 92e368669..22992599d 100644
--- a/src/libcharon/plugins/stroke/stroke_list.c
+++ b/src/libcharon/plugins/stroke/stroke_list.c
@@ -218,7 +218,7 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa),
child_sa_state_names, child_sa->get_state(child_sa),
ipsec_mode_names, child_sa->get_mode(child_sa),
- config->use_proxy_mode(config) ? "_PROXY" : "",
+ config->has_option(config, OPT_PROXY_MODE) ? "_PROXY" : "",
child_sa->get_reqid(child_sa));
if (child_sa->get_state(child_sa) == CHILD_INSTALLED)
@@ -958,8 +958,7 @@ static void list_plugins(FILE *out)
{
case FEATURE_PROVIDE:
fp = &features[i];
- loaded = list->find_first(list, NULL,
- (void**)&fp) == SUCCESS;
+ loaded = list->find_first(list, NULL, (void**)&fp);
fprintf(out, " %s%s\n",
str, loaded ? "" : " (not loaded)");
break;
diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c
index 46de90ca6..65d345db3 100644
--- a/src/libcharon/plugins/stroke/stroke_socket.c
+++ b/src/libcharon/plugins/stroke/stroke_socket.c
@@ -216,6 +216,7 @@ static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
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(" sha256_96=%s", msg->add_conn.sha256_96 ? "yes" : "no");
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);
diff --git a/src/libcharon/plugins/systime_fix/Makefile.in b/src/libcharon/plugins/systime_fix/Makefile.in
index 78fd6e8d1..327443020 100644
--- a/src/libcharon/plugins/systime_fix/Makefile.in
+++ b/src/libcharon/plugins/systime_fix/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/tnc_ifmap/Makefile.in b/src/libcharon/plugins/tnc_ifmap/Makefile.in
index 7ec4eaad1..438001baf 100644
--- a/src/libcharon/plugins/tnc_ifmap/Makefile.in
+++ b/src/libcharon/plugins/tnc_ifmap/Makefile.in
@@ -361,6 +361,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -383,6 +384,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap_msg.c b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap_msg.c
index b86288683..db19bd575 100644
--- a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap_msg.c
+++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap_msg.c
@@ -55,7 +55,7 @@ struct private_tnc_ifmap_soap_msg_t {
static xmlNodePtr find_child(xmlNodePtr parent, const xmlChar* name)
{
xmlNodePtr child;
-
+
child = parent->xmlChildrenNode;
while (child)
{
@@ -80,7 +80,7 @@ METHOD(tnc_ifmap_soap_msg_t, post, bool,
xmlChar *xml_str, *errorCode, *errorString;
int xml_len, len, written;
chunk_t xml, http;
- char buf[4096];
+ char buf[4096] = { 0 };
status_t status;
DBG2(DBG_TNC, "sending ifmap %s", request->name);
@@ -131,7 +131,8 @@ METHOD(tnc_ifmap_soap_msg_t, post, bool,
xml = chunk_empty;
do
{
- len = this->tls->read(this->tls, buf, sizeof(buf), TRUE);
+ /* reduce size so the buffer is null-terminated */
+ len = this->tls->read(this->tls, buf, sizeof(buf)-1, TRUE);
if (len <= 0)
{
return FALSE;
@@ -150,7 +151,7 @@ METHOD(tnc_ifmap_soap_msg_t, post, bool,
DBG3(DBG_TNC, "parsing XML message %B", &xml);
this->doc = xmlParseMemory(xml.ptr, xml.len);
free(xml.ptr);
-
+
if (!this->doc)
{
DBG1(DBG_TNC, "failed to parse XML message");
diff --git a/src/libcharon/plugins/tnc_pdp/Makefile.in b/src/libcharon/plugins/tnc_pdp/Makefile.in
index 215e3b38e..abc77433a 100644
--- a/src/libcharon/plugins/tnc_pdp/Makefile.in
+++ b/src/libcharon/plugins/tnc_pdp/Makefile.in
@@ -362,6 +362,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -384,6 +385,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/uci/Makefile.in b/src/libcharon/plugins/uci/Makefile.in
index 64b4bca24..46f4e4f85 100644
--- a/src/libcharon/plugins/uci/Makefile.in
+++ b/src/libcharon/plugins/uci/Makefile.in
@@ -356,6 +356,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -378,6 +379,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c
index e0578fe9b..dcd4ae348 100644
--- a/src/libcharon/plugins/uci/uci_config.c
+++ b/src/libcharon/plugins/uci/uci_config.c
@@ -118,11 +118,12 @@ static u_int create_rekey(char *string)
}
METHOD(enumerator_t, peer_enumerator_enumerate, bool,
- peer_enumerator_t *this, peer_cfg_t **cfg)
+ peer_enumerator_t *this, va_list args)
{
char *name, *ike_proposal, *esp_proposal, *ike_rekey, *esp_rekey;
char *local_id, *local_addr, *local_net;
char *remote_id, *remote_addr, *remote_net;
+ peer_cfg_t **cfg;
child_cfg_t *child_cfg;
ike_cfg_t *ike_cfg;
auth_cfg_t *auth;
@@ -145,6 +146,8 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
.mode = MODE_TUNNEL,
};
+ VA_ARGS_VGET(args, cfg);
+
/* defaults */
name = "unnamed";
local_id = NULL;
@@ -212,7 +215,8 @@ METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
INIT(e,
.public = {
- .enumerate = (void*)_peer_enumerator_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _peer_enumerator_enumerate,
.destroy = _peer_enumerator_destroy,
},
.inner = this->parser->create_section_enumerator(this->parser,
@@ -241,10 +245,13 @@ typedef struct {
} ike_enumerator_t;
METHOD(enumerator_t, ike_enumerator_enumerate, bool,
- ike_enumerator_t *this, ike_cfg_t **cfg)
+ ike_enumerator_t *this, va_list args)
{
+ ike_cfg_t **cfg;
char *local_addr, *remote_addr, *ike_proposal;
+ VA_ARGS_VGET(args, cfg);
+
/* defaults */
local_addr = "0.0.0.0";
remote_addr = "0.0.0.0";
@@ -282,7 +289,8 @@ METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
INIT(e,
.public = {
- .enumerate = (void*)_ike_enumerator_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _ike_enumerator_enumerate,
.destroy = _ike_enumerator_destroy,
},
.inner = this->parser->create_section_enumerator(this->parser,
diff --git a/src/libcharon/plugins/uci/uci_creds.c b/src/libcharon/plugins/uci/uci_creds.c
index f5d5ace70..404a3e39f 100644
--- a/src/libcharon/plugins/uci/uci_creds.c
+++ b/src/libcharon/plugins/uci/uci_creds.c
@@ -52,12 +52,15 @@ typedef struct {
} shared_enumerator_t;
METHOD(enumerator_t, shared_enumerator_enumerate, bool,
- shared_enumerator_t *this, shared_key_t **key, id_match_t *me,
- id_match_t *other)
+ shared_enumerator_t *this, va_list args)
{
+ shared_key_t **key;
+ id_match_t *me, *other;
char *local_id, *remote_id, *psk;
identification_t *local, *remote;
+ VA_ARGS_VGET(args, key, me, other);
+
while (TRUE)
{
/* defaults */
@@ -126,7 +129,8 @@ METHOD(credential_set_t, create_shared_enumerator, enumerator_t*,
INIT(e,
.public = {
- .enumerate = (void*)_shared_enumerator_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _shared_enumerator_enumerate,
.destroy = _shared_enumerator_destroy,
},
.me = me,
diff --git a/src/libcharon/plugins/uci/uci_parser.c b/src/libcharon/plugins/uci/uci_parser.c
index 2429e9e44..e847dd393 100644
--- a/src/libcharon/plugins/uci/uci_parser.c
+++ b/src/libcharon/plugins/uci/uci_parser.c
@@ -58,11 +58,10 @@ typedef struct {
} section_enumerator_t;
METHOD(enumerator_t, section_enumerator_enumerate, bool,
- section_enumerator_t *this, ...)
+ section_enumerator_t *this, va_list args)
{
struct uci_element *element;
char **value;
- va_list args;
int i;
if (&this->current->list == this->list)
@@ -70,8 +69,6 @@ METHOD(enumerator_t, section_enumerator_enumerate, bool,
return FALSE;
}
- va_start(args, this);
-
value = va_arg(args, char**);
if (value)
{
@@ -96,7 +93,6 @@ METHOD(enumerator_t, section_enumerator_enumerate, bool,
*value = uci_to_option(element)->value;
}
}
- va_end(args);
this->current = list_to_element(this->current->list.next);
return TRUE;
@@ -124,7 +120,13 @@ METHOD(uci_parser_t, create_section_enumerator, enumerator_t*,
i++;
}
va_end(args);
- e = malloc(sizeof(section_enumerator_t) + sizeof(char*) * i);
+ INIT_EXTRA(e, sizeof(char*) * i,
+ .public = {
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _section_enumerator_enumerate,
+ .destroy = _section_enumerator_destroy,
+ },
+ );
i = 0;
va_start(args, this);
do
@@ -134,9 +136,6 @@ METHOD(uci_parser_t, create_section_enumerator, enumerator_t*,
while (e->keywords[i++]);
va_end(args);
- e->public.enumerate = (void*)_section_enumerator_enumerate;
- e->public.destroy = _section_enumerator_destroy;
-
/* load uci context */
e->ctx = uci_alloc_context();
if (uci_load(e->ctx, this->package, &e->package) != UCI_OK)
diff --git a/src/libcharon/plugins/unity/Makefile.in b/src/libcharon/plugins/unity/Makefile.in
index 6811eb737..245bbd471 100644
--- a/src/libcharon/plugins/unity/Makefile.in
+++ b/src/libcharon/plugins/unity/Makefile.in
@@ -357,6 +357,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -379,6 +380,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/unity/unity_handler.c b/src/libcharon/plugins/unity/unity_handler.c
index 25e0756b7..4a1478c6d 100644
--- a/src/libcharon/plugins/unity/unity_handler.c
+++ b/src/libcharon/plugins/unity/unity_handler.c
@@ -368,9 +368,12 @@ typedef struct {
} attribute_enumerator_t;
METHOD(enumerator_t, enumerate_attributes, bool,
- attribute_enumerator_t *this, configuration_attribute_type_t *type,
- chunk_t *data)
+ attribute_enumerator_t *this, va_list args)
{
+ configuration_attribute_type_t *type;
+ chunk_t *data;
+
+ VA_ARGS_VGET(args, type, data);
if (this->i < countof(attributes))
{
*type = attributes[this->i++];
@@ -393,7 +396,8 @@ METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *,
}
INIT(enumerator,
.public = {
- .enumerate = (void*)_enumerate_attributes,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _enumerate_attributes,
.destroy = (void*)free,
},
);
@@ -407,24 +411,27 @@ typedef struct {
ike_sa_id_t *id;
} include_filter_t;
-/**
- * Include enumerator filter function
- */
-static bool include_filter(include_filter_t *data,
- entry_t **entry, traffic_selector_t **ts)
+CALLBACK(include_filter, bool,
+ include_filter_t *data, enumerator_t *orig, va_list args)
{
- if (data->id->equals(data->id, (*entry)->id))
+ entry_t *entry;
+ traffic_selector_t **ts;
+
+ VA_ARGS_VGET(args, ts);
+
+ while (orig->enumerate(orig, &entry))
{
- *ts = (*entry)->ts;
- return TRUE;
+ if (data->id->equals(data->id, entry->id))
+ {
+ *ts = entry->ts;
+ return TRUE;
+ }
}
return FALSE;
}
-/**
- * Destroy include filter data, unlock mutex
- */
-static void destroy_filter(include_filter_t *data)
+CALLBACK(destroy_filter, void,
+ include_filter_t *data)
{
data->mutex->unlock(data->mutex);
free(data);
@@ -442,7 +449,7 @@ METHOD(unity_handler_t, create_include_enumerator, enumerator_t*,
data->mutex->lock(data->mutex);
return enumerator_create_filter(
this->include->create_enumerator(this->include),
- (void*)include_filter, data, (void*)destroy_filter);
+ include_filter, data, destroy_filter);
}
METHOD(unity_handler_t, destroy, void,
diff --git a/src/libcharon/plugins/unity/unity_provider.c b/src/libcharon/plugins/unity/unity_provider.c
index 07f5f9b61..b6a55648e 100644
--- a/src/libcharon/plugins/unity/unity_provider.c
+++ b/src/libcharon/plugins/unity/unity_provider.c
@@ -77,12 +77,15 @@ static void append_ts(bio_writer_t *writer, traffic_selector_t *ts)
}
METHOD(enumerator_t, attribute_enumerate, bool,
- attribute_enumerator_t *this, configuration_attribute_type_t *type,
- chunk_t *attr)
+ attribute_enumerator_t *this, va_list args)
{
+ configuration_attribute_type_t *type;
+ chunk_t *attr;
traffic_selector_t *ts;
bio_writer_t *writer;
+ VA_ARGS_VGET(args, type, attr);
+
if (this->list->get_count(this->list) == 0)
{
return FALSE;
@@ -183,7 +186,8 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
INIT(attr_enum,
.public = {
- .enumerate = (void*)_attribute_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _attribute_enumerate,
.destroy = _attribute_destroy,
},
.list = list,
diff --git a/src/libcharon/plugins/updown/Makefile.in b/src/libcharon/plugins/updown/Makefile.in
index 1a44e5566..ef0f33ce3 100644
--- a/src/libcharon/plugins/updown/Makefile.in
+++ b/src/libcharon/plugins/updown/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/updown/updown_listener.c b/src/libcharon/plugins/updown/updown_listener.c
index 6a1581c85..bbefd6a02 100644
--- a/src/libcharon/plugins/updown/updown_listener.c
+++ b/src/libcharon/plugins/updown/updown_listener.c
@@ -366,7 +366,7 @@ static void invoke_once(private_updown_listener_t *this, ike_sa_t *ike_sa,
push_env(envp, countof(envp), "PLUTO_IPCOMP=1");
}
push_dns_env(this, ike_sa, envp, countof(envp));
- if (config->get_hostaccess(config))
+ if (config->has_option(config, OPT_HOSTACCESS))
{
push_env(envp, countof(envp), "PLUTO_HOST_ACCESS=1");
}
diff --git a/src/libcharon/plugins/vici/Makefile.in b/src/libcharon/plugins/vici/Makefile.in
index cdefbff79..fd2b89849 100644
--- a/src/libcharon/plugins/vici/Makefile.in
+++ b/src/libcharon/plugins/vici/Makefile.in
@@ -454,6 +454,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -476,6 +477,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/vici/README.md b/src/libcharon/plugins/vici/README.md
index 9bda949d0..f47f80cad 100644
--- a/src/libcharon/plugins/vici/README.md
+++ b/src/libcharon/plugins/vici/README.md
@@ -480,11 +480,12 @@ Load a certificate into the daemon.
Load a private key into the daemon.
{
- type = <private key type, RSA|ECDSA>
+ type = <private key type, rsa|ecdsa|bliss|any>
data = <PEM or DER encoded key data>
} => {
success = <yes or no>
errmsg = <error string on failure>
+ id = <hex-encoded SHA-1 key identifier of the public key on success>
}
### unload-key() ###
diff --git a/src/libcharon/plugins/vici/perl/Makefile.in b/src/libcharon/plugins/vici/perl/Makefile.in
index 385aa9775..0e9626aa3 100644
--- a/src/libcharon/plugins/vici/perl/Makefile.in
+++ b/src/libcharon/plugins/vici/perl/Makefile.in
@@ -272,6 +272,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -294,6 +295,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/vici/python/Makefile.in b/src/libcharon/plugins/vici/python/Makefile.in
index f783d7068..7d5383290 100644
--- a/src/libcharon/plugins/vici/python/Makefile.in
+++ b/src/libcharon/plugins/vici/python/Makefile.in
@@ -294,6 +294,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -316,6 +317,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/vici/python/vici/protocol.py b/src/libcharon/plugins/vici/python/vici/protocol.py
index 919231d43..370229463 100644
--- a/src/libcharon/plugins/vici/python/vici/protocol.py
+++ b/src/libcharon/plugins/vici/python/vici/protocol.py
@@ -62,7 +62,7 @@ class Packet(object):
@classmethod
def _named_request(cls, request_type, request, message=None):
- requestdata = request.encode("UTF-8")
+ request = request.encode("UTF-8")
payload = struct.pack("!BB", request_type, len(request)) + request
if message is not None:
return payload + message
diff --git a/src/libcharon/plugins/vici/ruby/Makefile.in b/src/libcharon/plugins/vici/ruby/Makefile.in
index 125f44ee1..5691a74d1 100644
--- a/src/libcharon/plugins/vici/ruby/Makefile.in
+++ b/src/libcharon/plugins/vici/ruby/Makefile.in
@@ -272,6 +272,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -294,6 +295,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
@@ -468,8 +470,8 @@ distclean-generic:
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-@RUBY_GEMS_INSTALL_FALSE@install-data-local:
@RUBY_GEMS_INSTALL_FALSE@uninstall-local:
+@RUBY_GEMS_INSTALL_FALSE@install-data-local:
clean: clean-am
clean-am: clean-generic clean-libtool clean-local mostlyclean-am
diff --git a/src/libcharon/plugins/vici/suites/test_message.c b/src/libcharon/plugins/vici/suites/test_message.c
index 045e34fff..73bba239b 100644
--- a/src/libcharon/plugins/vici/suites/test_message.c
+++ b/src/libcharon/plugins/vici/suites/test_message.c
@@ -122,9 +122,14 @@ typedef struct {
endecode_test_t *next;
} endecode_enum_t;
-static bool endecode_enumerate(endecode_enum_t *this, vici_type_t *type,
- char **name, chunk_t *data)
+METHOD(enumerator_t, endecode_enumerate, bool,
+ endecode_enum_t *this, va_list args)
{
+ vici_type_t *type;
+ chunk_t *data;
+ char **name;
+
+ VA_ARGS_VGET(args, type, name, data);
if (this->next)
{
*type = this->next->type;
@@ -149,7 +154,8 @@ static enumerator_t *endecode_create_enumerator(endecode_test_t *test)
INIT(enumerator,
.public = {
- .enumerate = (void*)endecode_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _endecode_enumerate,
.destroy = (void*)free,
},
.next = test,
diff --git a/src/libcharon/plugins/vici/vici_attribute.c b/src/libcharon/plugins/vici/vici_attribute.c
index 4e1fa9708..ab765fa14 100644
--- a/src/libcharon/plugins/vici/vici_attribute.c
+++ b/src/libcharon/plugins/vici/vici_attribute.c
@@ -184,16 +184,22 @@ METHOD(attribute_provider_t, release_address, bool,
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)
+CALLBACK(attr_filter, bool,
+ void *data, enumerator_t *orig, va_list args)
{
- *type = (*attr)->type;
- *value = (*attr)->value;
- return TRUE;
+ attribute_t *attr;
+ configuration_attribute_type_t *type;
+ chunk_t *value;
+
+ VA_ARGS_VGET(args, type, value);
+
+ if (orig->enumerate(orig, &attr))
+ {
+ *type = attr->type;
+ *value = attr->value;
+ return TRUE;
+ }
+ return FALSE;
}
/**
@@ -203,7 +209,7 @@ CALLBACK(create_nested, enumerator_t*,
pool_t *pool, void *this)
{
return enumerator_create_filter(array_create_enumerator(pool->attrs),
- (void*)attr_filter, NULL, NULL);
+ attr_filter, NULL, NULL);
}
/**
diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c
index 12497ec5e..0c355e3a0 100644
--- a/src/libcharon/plugins/vici/vici_config.c
+++ b/src/libcharon/plugins/vici/vici_config.c
@@ -141,13 +141,20 @@ METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
(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)
+CALLBACK(ike_filter, bool,
+ void *data, enumerator_t *orig, va_list args)
{
- *out = (*in)->get_ike_cfg(*in);
- return TRUE;
+ peer_cfg_t *cfg;
+ ike_cfg_t **out;
+
+ VA_ARGS_VGET(args, out);
+
+ if (orig->enumerate(orig, &cfg))
+ {
+ *out = cfg->get_ike_cfg(cfg);
+ return TRUE;
+ }
+ return FALSE;
}
METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
@@ -155,7 +162,7 @@ METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
{
this->lock->read_lock(this->lock);
return enumerator_create_filter(this->conns->create_enumerator(this->conns),
- (void*)ike_filter, this->lock,
+ ike_filter, this->lock,
(void*)this->lock->unlock);
}
@@ -478,7 +485,6 @@ typedef struct {
linked_list_t *remote_ts;
uint32_t replay_window;
bool policies;
- bool policies_fwd_out;
child_cfg_create_t cfg;
} child_data_t;
@@ -500,12 +506,12 @@ static void log_child_data(child_data_t *data, char *name)
DBG2(DBG_CFG, " life_packets = %llu", cfg->lifetime.packets.life);
DBG2(DBG_CFG, " rand_packets = %llu", cfg->lifetime.packets.jitter);
DBG2(DBG_CFG, " updown = %s", cfg->updown);
- DBG2(DBG_CFG, " hostaccess = %u", cfg->hostaccess);
- DBG2(DBG_CFG, " ipcomp = %u", cfg->ipcomp);
+ DBG2(DBG_CFG, " hostaccess = %u", cfg->options & OPT_HOSTACCESS);
+ DBG2(DBG_CFG, " ipcomp = %u", cfg->options & OPT_IPCOMP);
DBG2(DBG_CFG, " mode = %N%s", ipsec_mode_names, cfg->mode,
- cfg->proxy_mode ? "_PROXY" : "");
+ cfg->options & OPT_PROXY_MODE ? "_PROXY" : "");
DBG2(DBG_CFG, " policies = %u", data->policies);
- DBG2(DBG_CFG, " policies_fwd_out = %u", data->policies_fwd_out);
+ DBG2(DBG_CFG, " policies_fwd_out = %u", cfg->options & OPT_FWD_OUT_POLICIES);
if (data->replay_window != REPLAY_UNDEFINED)
{
DBG2(DBG_CFG, " replay_window = %u", data->replay_window);
@@ -525,6 +531,8 @@ static void log_child_data(child_data_t *data, char *name)
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);
+ DBG2(DBG_CFG, " hw_offload = %u", cfg->options & OPT_HW_OFFLOAD);
+ DBG2(DBG_CFG, " sha256_96 = %u", cfg->options & OPT_SHA256_96);
}
/**
@@ -827,13 +835,80 @@ CALLBACK(parse_mode, bool,
if (parse_map(map, countof(map), &d, v))
{
cfg->mode = d;
- cfg->proxy_mode = (d == MODE_TRANSPORT) && (v.len > 9);
+ if ((d == MODE_TRANSPORT) && (v.len > 9))
+ {
+ cfg->options |= OPT_PROXY_MODE;
+ }
return TRUE;
}
return FALSE;
}
/**
+ * Enable a child_cfg_option_t
+ */
+static bool parse_option(child_cfg_option_t *out, child_cfg_option_t opt,
+ chunk_t v)
+{
+ bool val;
+
+ if (parse_bool(&val, v))
+ {
+ if (val)
+ {
+ *out |= opt;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse OPT_HOSTACCESS option
+ */
+CALLBACK(parse_opt_haccess, bool,
+ child_cfg_option_t *out, chunk_t v)
+{
+ return parse_option(out, OPT_HOSTACCESS, v);
+}
+
+/**
+ * Parse OPT_FWD_OUT_POLICIES option
+ */
+CALLBACK(parse_opt_fwd_out, bool,
+ child_cfg_option_t *out, chunk_t v)
+{
+ return parse_option(out, OPT_FWD_OUT_POLICIES, v);
+}
+
+/**
+ * Parse OPT_FWD_OUT_POLICIES option
+ */
+CALLBACK(parse_opt_ipcomp, bool,
+ child_cfg_option_t *out, chunk_t v)
+{
+ return parse_option(out, OPT_IPCOMP, v);
+}
+
+/**
+ * Parse OPT_HW_OFFLOAD option
+ */
+CALLBACK(parse_opt_hw_offl, bool,
+ child_cfg_option_t *out, chunk_t v)
+{
+ return parse_option(out, OPT_HW_OFFLOAD, v);
+}
+
+/**
+ * Parse OPT_SHA256_96 option
+ */
+CALLBACK(parse_opt_sha256_96, bool,
+ child_cfg_option_t *out, chunk_t v)
+{
+ return parse_option(out, OPT_SHA256_96, v);
+}
+
+/**
* Parse an action_t
*/
CALLBACK(parse_action, bool,
@@ -1336,6 +1411,7 @@ CALLBACK(parse_frag, bool,
{
enum_map_t map[] = {
{ "yes", FRAGMENTATION_YES },
+ { "accept", FRAGMENTATION_ACCEPT },
{ "no", FRAGMENTATION_NO },
{ "force", FRAGMENTATION_FORCE },
};
@@ -1465,10 +1541,10 @@ CALLBACK(child_kv, bool,
{
parse_rule_t rules[] = {
{ "updown", parse_string, &child->cfg.updown },
- { "hostaccess", parse_bool, &child->cfg.hostaccess },
+ { "hostaccess", parse_opt_haccess, &child->cfg.options },
{ "mode", parse_mode, &child->cfg },
{ "policies", parse_bool, &child->policies },
- { "policies_fwd_out", parse_bool, &child->policies_fwd_out },
+ { "policies_fwd_out", parse_opt_fwd_out, &child->cfg.options },
{ "replay_window", parse_uint32, &child->replay_window },
{ "rekey_time", parse_time, &child->cfg.lifetime.time.rekey },
{ "life_time", parse_time, &child->cfg.lifetime.time.life },
@@ -1482,7 +1558,7 @@ CALLBACK(child_kv, bool,
{ "dpd_action", parse_action, &child->cfg.dpd_action },
{ "start_action", parse_action, &child->cfg.start_action },
{ "close_action", parse_action, &child->cfg.close_action },
- { "ipcomp", parse_bool, &child->cfg.ipcomp },
+ { "ipcomp", parse_opt_ipcomp, &child->cfg.options },
{ "inactivity", parse_time, &child->cfg.inactivity },
{ "reqid", parse_uint32, &child->cfg.reqid },
{ "mark_in", parse_mark, &child->cfg.mark_in },
@@ -1490,6 +1566,8 @@ CALLBACK(child_kv, bool,
{ "tfc_padding", parse_tfc, &child->cfg.tfc },
{ "priority", parse_uint32, &child->cfg.priority },
{ "interface", parse_string, &child->cfg.interface },
+ { "hw_offload", parse_opt_hw_offl, &child->cfg.options },
+ { "sha256_96", parse_opt_sha256_96,&child->cfg.options },
};
return parse_rules(rules, countof(rules), name, value,
@@ -1755,8 +1833,7 @@ CALLBACK(children_sn, bool,
child.proposals->insert_last(child.proposals, proposal);
}
}
- child.cfg.suppress_policies = !child.policies;
- child.cfg.fwd_out_policies = child.policies_fwd_out;
+ child.cfg.options |= child.policies ? 0 : OPT_NO_POLICIES;
check_lifetimes(&child.cfg.lifetime);
diff --git a/src/libcharon/plugins/vici/vici_cred.c b/src/libcharon/plugins/vici/vici_cred.c
index 6c7c194c2..5d8bf2f05 100644
--- a/src/libcharon/plugins/vici/vici_cred.c
+++ b/src/libcharon/plugins/vici/vici_cred.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2015-2016 Andreas Steffen
- * Copyright (C) 2016 Tobias Brunner
+ * Copyright (C) 2016-2017 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* Copyright (C) 2014 Martin Willi
@@ -206,9 +206,10 @@ CALLBACK(load_cert, vici_message_t*,
CALLBACK(load_key, vici_message_t*,
private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
{
+ vici_builder_t *builder;
key_type_t type;
private_key_t *key;
- chunk_t data;
+ chunk_t data, fp;
char *str;
str = message->get_str(message, NULL, "type");
@@ -248,12 +249,19 @@ CALLBACK(load_key, vici_message_t*,
return create_reply("parsing %N private key failed",
key_type_names, type);
}
+ if (!key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &fp))
+ {
+ return create_reply("failed to get key id");
+ }
DBG1(DBG_CFG, "loaded %N private key", key_type_names, type);
+ builder = vici_builder_create();
+ builder->add_kv(builder, "success", "yes");
+ builder->add_kv(builder, "id", "%+B", &fp);
this->creds->add_key(this->creds, key);
- return create_reply(NULL);
+ return builder->finalize(builder);
}
CALLBACK(unload_key, vici_message_t*,
diff --git a/src/libcharon/plugins/vici/vici_message.c b/src/libcharon/plugins/vici/vici_message.c
index 58b896773..91d344994 100644
--- a/src/libcharon/plugins/vici/vici_message.c
+++ b/src/libcharon/plugins/vici/vici_message.c
@@ -135,11 +135,16 @@ typedef struct {
} parse_enumerator_t;
METHOD(enumerator_t, parse_enumerate, bool,
- parse_enumerator_t *this, vici_type_t *out, char **name, chunk_t *value)
+ parse_enumerator_t *this, va_list args)
{
+ vici_type_t *out;
+ chunk_t *value;
+ char **name;
uint8_t type;
chunk_t data;
+ VA_ARGS_VGET(args, out, name, value);
+
if (!this->reader->remaining(this->reader) ||
!this->reader->read_uint8(this->reader, &type))
{
@@ -218,7 +223,8 @@ METHOD(vici_message_t, create_enumerator, enumerator_t*,
INIT(enumerator,
.public = {
- .enumerate = (void*)_parse_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _parse_enumerate,
.destroy = _parse_destroy,
},
.reader = bio_reader_create(this->encoding),
diff --git a/src/libcharon/plugins/vici/vici_query.c b/src/libcharon/plugins/vici/vici_query.c
index c0f4e2de9..2cc59591f 100644
--- a/src/libcharon/plugins/vici/vici_query.c
+++ b/src/libcharon/plugins/vici/vici_query.c
@@ -107,7 +107,7 @@ static void list_mode(vici_builder_t *b, child_sa_t *child, child_cfg_t *cfg)
cfg = child->get_config(child);
}
mode = child ? child->get_mode(child) : cfg->get_mode(cfg);
- if (mode == MODE_TRANSPORT && cfg->use_proxy_mode(cfg))
+ if (mode == MODE_TRANSPORT && cfg->has_option(cfg, OPT_PROXY_MODE))
{ /* only report this if the negotiated mode is actually TRANSPORT */
sub_mode = "_PROXY";
}
diff --git a/src/libcharon/plugins/whitelist/Makefile.in b/src/libcharon/plugins/whitelist/Makefile.in
index b85961387..0347c5f53 100644
--- a/src/libcharon/plugins/whitelist/Makefile.in
+++ b/src/libcharon/plugins/whitelist/Makefile.in
@@ -365,6 +365,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -387,6 +388,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/whitelist/whitelist_listener.c b/src/libcharon/plugins/whitelist/whitelist_listener.c
index 7e5b2f4e0..136554674 100644
--- a/src/libcharon/plugins/whitelist/whitelist_listener.c
+++ b/src/libcharon/plugins/whitelist/whitelist_listener.c
@@ -119,14 +119,19 @@ METHOD(whitelist_listener_t, remove_, void,
DESTROY_IF(id);
}
-/**
- * Enumerator filter, from hashtable (key, value) to single identity
- */
-static bool whitelist_filter(rwlock_t *lock, identification_t **key,
- identification_t **id, identification_t **value)
+CALLBACK(whitelist_filter, bool,
+ rwlock_t *lock, enumerator_t *orig, va_list args)
{
- *id = *value;
- return TRUE;
+ identification_t *key, *value, **out;
+
+ VA_ARGS_VGET(args, out);
+
+ if (orig->enumerate(orig, &key, &value))
+ {
+ *out = value;
+ return TRUE;
+ }
+ return FALSE;
}
METHOD(whitelist_listener_t, create_enumerator, enumerator_t*,
@@ -134,7 +139,7 @@ METHOD(whitelist_listener_t, create_enumerator, enumerator_t*,
{
this->lock->read_lock(this->lock);
return enumerator_create_filter(this->ids->create_enumerator(this->ids),
- (void*)whitelist_filter, this->lock,
+ whitelist_filter, this->lock,
(void*)this->lock->unlock);
}
diff --git a/src/libcharon/plugins/xauth_eap/Makefile.in b/src/libcharon/plugins/xauth_eap/Makefile.in
index a6554d6a9..28158a373 100644
--- a/src/libcharon/plugins/xauth_eap/Makefile.in
+++ b/src/libcharon/plugins/xauth_eap/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/xauth_generic/Makefile.in b/src/libcharon/plugins/xauth_generic/Makefile.in
index 87d627bc3..1dc267545 100644
--- a/src/libcharon/plugins/xauth_generic/Makefile.in
+++ b/src/libcharon/plugins/xauth_generic/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/xauth_noauth/Makefile.in b/src/libcharon/plugins/xauth_noauth/Makefile.in
index 13fb71aef..a610bab2a 100644
--- a/src/libcharon/plugins/xauth_noauth/Makefile.in
+++ b/src/libcharon/plugins/xauth_noauth/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/plugins/xauth_pam/Makefile.in b/src/libcharon/plugins/xauth_pam/Makefile.in
index 821d46e6b..8c31f2472 100644
--- a/src/libcharon/plugins/xauth_pam/Makefile.in
+++ b/src/libcharon/plugins/xauth_pam/Makefile.in
@@ -358,6 +358,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -380,6 +381,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/processing/jobs/delete_child_sa_job.c b/src/libcharon/processing/jobs/delete_child_sa_job.c
index 70dbc1b4a..048b879f1 100644
--- a/src/libcharon/processing/jobs/delete_child_sa_job.c
+++ b/src/libcharon/processing/jobs/delete_child_sa_job.c
@@ -1,6 +1,7 @@
/*
+ * Copyright (C) 2017 Tobias Brunner
* Copyright (C) 2006 Martin Willi
- * Hochschule fuer Technik Rapperswil
+ * 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
@@ -24,19 +25,19 @@ typedef struct private_delete_child_sa_job_t private_delete_child_sa_job_t;
* Private data of an delete_child_sa_job_t object.
*/
struct private_delete_child_sa_job_t {
- /**
+ /**
* Public delete_child_sa_job_t interface.
*/
delete_child_sa_job_t public;
/**
- * protocol of the CHILD_SA (ESP/AH)
+ * Protocol of the CHILD_SA (ESP/AH)
*/
protocol_id_t protocol;
/**
- * inbound SPI of the CHILD_SA
+ * Inbound SPI of the CHILD_SA
*/
uint32_t spi;
@@ -49,12 +50,17 @@ struct private_delete_child_sa_job_t {
* Delete for an expired CHILD_SA
*/
bool expired;
+
+ /**
+ * Unique ID of the CHILD_SA
+ */
+ uint32_t id;
};
METHOD(job_t, destroy, void,
private_delete_child_sa_job_t *this)
{
- this->dst->destroy(this->dst);
+ DESTROY_IF(this->dst);
free(this);
}
@@ -63,17 +69,37 @@ METHOD(job_t, execute, job_requeue_t,
{
ike_sa_t *ike_sa;
- ike_sa = charon->child_sa_manager->checkout(charon->child_sa_manager,
- this->protocol, this->spi, this->dst, NULL);
- if (ike_sa == NULL)
+ if (this->id)
{
- DBG1(DBG_JOB, "CHILD_SA %N/0x%08x/%H not found for delete",
- protocol_id_names, this->protocol, htonl(this->spi), this->dst);
+ child_sa_t *child_sa;
+
+ ike_sa = charon->child_sa_manager->checkout_by_id(
+ charon->child_sa_manager, this->id, &child_sa);
+ if (!ike_sa)
+ {
+ DBG1(DBG_JOB, "CHILD_SA {%d} not found for delete", this->id);
+ }
+ else
+ {
+ this->spi = child_sa->get_spi(child_sa, TRUE);
+ this->protocol = child_sa->get_protocol(child_sa);
+ }
}
else
{
- ike_sa->delete_child_sa(ike_sa, this->protocol, this->spi, this->expired);
+ ike_sa = charon->child_sa_manager->checkout(charon->child_sa_manager,
+ this->protocol, this->spi, this->dst, NULL);
+ if (!ike_sa)
+ {
+ DBG1(DBG_JOB, "CHILD_SA %N/0x%08x/%H not found for delete",
+ protocol_id_names, this->protocol, htonl(this->spi), this->dst);
+ }
+ }
+ if (ike_sa)
+ {
+ ike_sa->delete_child_sa(ike_sa, this->protocol, this->spi,
+ this->expired);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
return JOB_REQUEUE_NONE;
@@ -109,3 +135,24 @@ delete_child_sa_job_t *delete_child_sa_job_create(protocol_id_t protocol,
return &this->public;
}
+
+/*
+ * Described in header
+ */
+delete_child_sa_job_t *delete_child_sa_job_create_id(uint32_t id)
+{
+ private_delete_child_sa_job_t *this;
+
+ INIT(this,
+ .public = {
+ .job_interface = {
+ .execute = _execute,
+ .get_priority = _get_priority,
+ .destroy = _destroy,
+ },
+ },
+ .id = id,
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/processing/jobs/delete_child_sa_job.h b/src/libcharon/processing/jobs/delete_child_sa_job.h
index 349f5debb..b2d5a11f6 100644
--- a/src/libcharon/processing/jobs/delete_child_sa_job.h
+++ b/src/libcharon/processing/jobs/delete_child_sa_job.h
@@ -1,6 +1,7 @@
/*
+ * Copyright (C) 2017 Tobias Brunner
* Copyright (C) 2006 Martin Willi
- * Hochschule fuer Technik Rapperswil
+ * 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
@@ -42,7 +43,7 @@ struct delete_child_sa_job_t {
};
/**
- * Creates a job of type DELETE_CHILD_SA.
+ * Creates a job that deletes a CHILD_SA.
*
* @param protocol protocol of the CHILD_SA
* @param spi security parameter index of the CHILD_SA
@@ -53,4 +54,12 @@ struct delete_child_sa_job_t {
delete_child_sa_job_t *delete_child_sa_job_create(protocol_id_t protocol,
uint32_t spi, host_t *dst, bool expired);
+/**
+ * Creates a job that deletes a CHILD_SA identified by its unique ID.
+ *
+ * @param id unique ID of the CHILD_SA
+ * @return delete_child_sa_job_t object
+ */
+delete_child_sa_job_t *delete_child_sa_job_create_id(uint32_t id);
+
#endif /** DELETE_CHILD_SA_JOB_H_ @}*/
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index b9dd59b07..3d9f6133b 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -1,6 +1,6 @@
/*
+ * Copyright (C) 2006-2017 Tobias Brunner
* Copyright (C) 2016 Andreas Steffen
- * Copyright (C) 2006-2016 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
@@ -40,6 +40,12 @@ ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING,
"DESTROYING",
);
+ENUM(child_sa_outbound_state_names, CHILD_OUTBOUND_NONE, CHILD_OUTBOUND_INSTALLED,
+ "NONE",
+ "REGISTERED",
+ "INSTALLED",
+);
+
typedef struct private_child_sa_t private_child_sa_t;
/**
@@ -92,6 +98,31 @@ struct private_child_sa_t {
array_t *other_ts;
/**
+ * Outbound encryption key cached during a rekeying
+ */
+ chunk_t encr_r;
+
+ /**
+ * Outbound integrity key cached during a rekeying
+ */
+ chunk_t integ_r;
+
+ /**
+ * Whether the outbound SA has only been registered yet during a rekeying
+ */
+ child_sa_outbound_state_t outbound_state;
+
+ /**
+ * Whether the peer supports TFCv3
+ */
+ bool tfcv3;
+
+ /**
+ * The outbound SPI of the CHILD_SA that replaced this one during a rekeying
+ */
+ uint32_t rekey_spi;
+
+ /**
* Protocol used to protect this SA, ESP|AH
*/
protocol_id_t protocol;
@@ -265,6 +296,10 @@ METHOD(child_sa_t, get_config, child_cfg_t*,
METHOD(child_sa_t, set_state, void,
private_child_sa_t *this, child_sa_state_t state)
{
+ DBG2(DBG_CHD, "CHILD_SA %s{%d} state change: %N => %N",
+ get_name(this), this->unique_id,
+ child_sa_state_names, this->state,
+ child_sa_state_names, state);
charon->bus->child_state_change(charon->bus, &this->public, state);
this->state = state;
}
@@ -275,6 +310,12 @@ METHOD(child_sa_t, get_state, child_sa_state_t,
return this->state;
}
+METHOD(child_sa_t, get_outbound_state, child_sa_outbound_state_t,
+ private_child_sa_t *this)
+{
+ return this->outbound_state;
+}
+
METHOD(child_sa_t, get_spi, uint32_t,
private_child_sa_t *this, bool inbound)
{
@@ -394,10 +435,11 @@ struct policy_enumerator_t {
};
METHOD(enumerator_t, policy_enumerate, bool,
- policy_enumerator_t *this, traffic_selector_t **my_out,
- traffic_selector_t **other_out)
+ policy_enumerator_t *this, va_list args)
{
- traffic_selector_t *other_ts;
+ traffic_selector_t *other_ts, **my_out, **other_out;
+
+ VA_ARGS_VGET(args, my_out, other_out);
while (this->ts || this->mine->enumerate(this->mine, &this->ts))
{
@@ -446,7 +488,8 @@ METHOD(child_sa_t, create_policy_enumerator, enumerator_t*,
INIT(e,
.public = {
- .enumerate = (void*)_policy_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _policy_enumerate,
.destroy = _policy_destroy,
},
.mine = array_create_enumerator(this->my_ts),
@@ -504,7 +547,7 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
}
else
{
- if (this->other_spi)
+ if (this->other_spi && this->outbound_state == CHILD_OUTBOUND_INSTALLED)
{
kernel_ipsec_sa_id_t id = {
.src = this->my_addr,
@@ -691,14 +734,16 @@ METHOD(child_sa_t, alloc_cpi, uint16_t,
return 0;
}
-METHOD(child_sa_t, install, status_t,
- private_child_sa_t *this, chunk_t encr, chunk_t integ, uint32_t spi,
- uint16_t cpi, bool initiator, bool inbound, bool tfcv3,
- linked_list_t *my_ts, linked_list_t *other_ts)
+/**
+ * Install the given SA in the kernel
+ */
+static status_t install_internal(private_child_sa_t *this, chunk_t encr,
+ chunk_t integ, uint32_t spi, uint16_t cpi, bool initiator, bool inbound,
+ bool tfcv3)
{
uint16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size;
uint16_t esn = NO_EXT_SEQ_NUMBERS;
- linked_list_t *src_ts = NULL, *dst_ts = NULL;
+ linked_list_t *my_ts, *other_ts, *src_ts, *dst_ts;
time_t now;
kernel_ipsec_sa_id_t id;
kernel_ipsec_add_sa_t sa;
@@ -708,6 +753,12 @@ METHOD(child_sa_t, install, status_t,
status_t status;
bool update = FALSE;
+ /* BEET requires the bound address from the traffic selectors */
+ my_ts = linked_list_create_from_enumerator(
+ array_create_enumerator(this->my_ts));
+ other_ts = linked_list_create_from_enumerator(
+ array_create_enumerator(this->other_ts));
+
/* now we have to decide which spi to use. Use self allocated, if "in",
* or the one in the proposal, if not "in" (others). Additionally,
* source and dest host switch depending on the role */
@@ -721,6 +772,8 @@ METHOD(child_sa_t, install, status_t,
}
this->my_spi = spi;
this->my_cpi = cpi;
+ dst_ts = my_ts;
+ src_ts = other_ts;
}
else
{
@@ -728,11 +781,14 @@ METHOD(child_sa_t, install, status_t,
dst = this->other_addr;
this->other_spi = spi;
this->other_cpi = cpi;
+ src_ts = my_ts;
+ dst_ts = other_ts;
if (tfcv3)
{
tfc = this->config->get_tfc(this->config);
}
+ this->outbound_state = CHILD_OUTBOUND_INSTALLED;
}
DBG2(DBG_CHD, "adding %s %N SA", inbound ? "inbound" : "outbound",
@@ -748,12 +804,22 @@ METHOD(child_sa_t, install, status_t,
this->proposal->get_algorithm(this->proposal, EXTENDED_SEQUENCE_NUMBERS,
&esn, NULL);
+ if (int_alg == AUTH_HMAC_SHA2_256_128 &&
+ this->config->has_option(this->config, OPT_SHA256_96))
+ {
+ DBG2(DBG_CHD, " using %N with 96-bit truncation",
+ integrity_algorithm_names, int_alg);
+ int_alg = AUTH_HMAC_SHA2_256_96;
+ }
+
if (!this->reqid_allocated && !this->static_reqid)
{
status = charon->kernel->alloc_reqid(charon->kernel, my_ts, other_ts,
this->mark_in, this->mark_out, &this->reqid);
if (status != SUCCESS)
{
+ my_ts->destroy(my_ts);
+ other_ts->destroy(other_ts);
return status;
}
this->reqid_allocated = TRUE;
@@ -783,18 +849,6 @@ METHOD(child_sa_t, install, status_t,
lifetime->time.rekey = 0;
}
- /* BEET requires the bound address from the traffic selectors */
- if (inbound)
- {
- dst_ts = my_ts;
- src_ts = other_ts;
- }
- else
- {
- src_ts = my_ts;
- dst_ts = other_ts;
- }
-
id = (kernel_ipsec_sa_id_t){
.src = src,
.dst = dst,
@@ -818,6 +872,7 @@ METHOD(child_sa_t, install, status_t,
.ipcomp = this->ipcomp,
.cpi = cpi,
.encap = this->encap,
+ .hw_offload = this->config->has_option(this->config, OPT_HW_OFFLOAD),
.esn = esn,
.initiator = initiator,
.inbound = inbound,
@@ -826,11 +881,21 @@ METHOD(child_sa_t, install, status_t,
status = charon->kernel->add_sa(charon->kernel, &id, &sa);
+ my_ts->destroy(my_ts);
+ other_ts->destroy(other_ts);
free(lifetime);
return status;
}
+METHOD(child_sa_t, install, status_t,
+ private_child_sa_t *this, chunk_t encr, chunk_t integ, uint32_t spi,
+ uint16_t cpi, bool initiator, bool inbound, bool tfcv3)
+{
+ return install_internal(this, encr, integ, spi, cpi, initiator, inbound,
+ tfcv3);
+}
+
/**
* Check kernel interface if policy updates are required
*/
@@ -887,34 +952,21 @@ static void prepare_sa_cfg(private_child_sa_t *this, ipsec_sa_cfg_t *my_sa,
}
/**
- * Install 3 policies: out, in and forward
+ * Install inbound policie(s): in, fwd
*/
-static status_t install_policies_internal(private_child_sa_t *this,
+static status_t install_policies_inbound(private_child_sa_t *this,
host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
ipsec_sa_cfg_t *other_sa, policy_type_t type,
policy_priority_t priority, uint32_t manual_prio)
{
- kernel_ipsec_policy_id_t out_id = {
- .dir = POLICY_OUT,
- .src_ts = my_ts,
- .dst_ts = other_ts,
- .mark = this->mark_out,
- .interface = this->config->get_interface(this->config),
- }, in_id = {
+ kernel_ipsec_policy_id_t in_id = {
.dir = POLICY_IN,
.src_ts = other_ts,
.dst_ts = my_ts,
.mark = this->mark_in,
};
- kernel_ipsec_manage_policy_t out_policy = {
- .type = type,
- .prio = priority,
- .manual_prio = manual_prio,
- .src = my_addr,
- .dst = other_addr,
- .sa = other_sa,
- }, in_policy = {
+ kernel_ipsec_manage_policy_t in_policy = {
.type = type,
.prio = priority,
.manual_prio = manual_prio,
@@ -924,13 +976,45 @@ static status_t install_policies_internal(private_child_sa_t *this,
};
status_t status = SUCCESS;
- status |= charon->kernel->add_policy(charon->kernel, &out_id, &out_policy);
status |= charon->kernel->add_policy(charon->kernel, &in_id, &in_policy);
if (this->mode != MODE_TRANSPORT)
{
in_id.dir = POLICY_FWD;
status |= charon->kernel->add_policy(charon->kernel, &in_id, &in_policy);
+ }
+ return status;
+}
+/**
+ * Install outbound policie(s): out, [fwd]
+ */
+static status_t install_policies_outbound(private_child_sa_t *this,
+ host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
+ traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
+ ipsec_sa_cfg_t *other_sa, policy_type_t type,
+ policy_priority_t priority, uint32_t manual_prio)
+{
+ kernel_ipsec_policy_id_t out_id = {
+ .dir = POLICY_OUT,
+ .src_ts = my_ts,
+ .dst_ts = other_ts,
+ .mark = this->mark_out,
+ .interface = this->config->get_interface(this->config),
+ };
+ kernel_ipsec_manage_policy_t out_policy = {
+ .type = type,
+ .prio = priority,
+ .manual_prio = manual_prio,
+ .src = my_addr,
+ .dst = other_addr,
+ .sa = other_sa,
+ };
+ status_t status = SUCCESS;
+
+ status |= charon->kernel->add_policy(charon->kernel, &out_id, &out_policy);
+
+ if (this->mode != MODE_TRANSPORT && this->policies_fwd_out)
+ {
/* install an "outbound" FWD policy in case there is a drop policy
* matching outbound forwarded traffic, to allow another tunnel to use
* the reversed subnets and do the same we don't set a reqid (this also
@@ -939,52 +1023,56 @@ static status_t install_policies_internal(private_child_sa_t *this,
* policies of two SAs we install them with reduced priority. As they
* basically act as bypass policies for drop policies we use a higher
* priority than is used for them. */
- if (this->policies_fwd_out)
+ out_id.dir = POLICY_FWD;
+ other_sa->reqid = 0;
+ if (priority == POLICY_PRIORITY_DEFAULT)
{
- out_id.dir = POLICY_FWD;
- other_sa->reqid = 0;
- if (priority == POLICY_PRIORITY_DEFAULT)
- {
- out_policy.prio = POLICY_PRIORITY_ROUTED;
- }
- status |= charon->kernel->add_policy(charon->kernel, &out_id,
- &out_policy);
- /* reset the reqid for any other further policies */
- other_sa->reqid = this->reqid;
+ out_policy.prio = POLICY_PRIORITY_ROUTED;
}
+ status |= charon->kernel->add_policy(charon->kernel, &out_id,
+ &out_policy);
+ /* reset the reqid for any other further policies */
+ other_sa->reqid = this->reqid;
}
return status;
}
/**
- * Delete 3 policies: out, in and forward
+ * Install all policies
*/
-static void del_policies_internal(private_child_sa_t *this,
+static status_t install_policies_internal(private_child_sa_t *this,
+ host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
+ traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
+ ipsec_sa_cfg_t *other_sa, policy_type_t type,
+ policy_priority_t priority, uint32_t manual_prio)
+{
+ status_t status = SUCCESS;
+
+ status |= install_policies_inbound(this, my_addr, other_addr, my_ts,
+ other_ts, my_sa, other_sa, type,
+ priority, manual_prio);
+ status |= install_policies_outbound(this, my_addr, other_addr, my_ts,
+ other_ts, my_sa, other_sa, type,
+ priority, manual_prio);
+ return status;
+}
+
+/**
+ * Delete inbound policies: in, fwd
+ */
+static void del_policies_inbound(private_child_sa_t *this,
host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
ipsec_sa_cfg_t *other_sa, policy_type_t type,
policy_priority_t priority, uint32_t manual_prio)
{
- kernel_ipsec_policy_id_t out_id = {
- .dir = POLICY_OUT,
- .src_ts = my_ts,
- .dst_ts = other_ts,
- .mark = this->mark_out,
- .interface = this->config->get_interface(this->config),
- }, in_id = {
+ kernel_ipsec_policy_id_t in_id = {
.dir = POLICY_IN,
.src_ts = other_ts,
.dst_ts = my_ts,
.mark = this->mark_in,
};
- kernel_ipsec_manage_policy_t out_policy = {
- .type = type,
- .prio = priority,
- .manual_prio = manual_prio,
- .src = my_addr,
- .dst = other_addr,
- .sa = other_sa,
- }, in_policy = {
+ kernel_ipsec_manage_policy_t in_policy = {
.type = type,
.prio = priority,
.manual_prio = manual_prio,
@@ -993,49 +1081,83 @@ static void del_policies_internal(private_child_sa_t *this,
.sa = my_sa,
};
- charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
charon->kernel->del_policy(charon->kernel, &in_id, &in_policy);
+
if (this->mode != MODE_TRANSPORT)
{
in_id.dir = POLICY_FWD;
charon->kernel->del_policy(charon->kernel, &in_id, &in_policy);
+ }
+}
- if (this->policies_fwd_out)
+/**
+ * Delete outbound policies: out, [fwd]
+ */
+static void del_policies_outbound(private_child_sa_t *this,
+ host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
+ traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
+ ipsec_sa_cfg_t *other_sa, policy_type_t type,
+ policy_priority_t priority, uint32_t manual_prio)
+{
+ kernel_ipsec_policy_id_t out_id = {
+ .dir = POLICY_OUT,
+ .src_ts = my_ts,
+ .dst_ts = other_ts,
+ .mark = this->mark_out,
+ .interface = this->config->get_interface(this->config),
+ };
+ kernel_ipsec_manage_policy_t out_policy = {
+ .type = type,
+ .prio = priority,
+ .manual_prio = manual_prio,
+ .src = my_addr,
+ .dst = other_addr,
+ .sa = other_sa,
+ };
+
+ charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
+
+ if (this->mode != MODE_TRANSPORT && this->policies_fwd_out)
+ {
+ out_id.dir = POLICY_FWD;
+ other_sa->reqid = 0;
+ if (priority == POLICY_PRIORITY_DEFAULT)
{
- out_id.dir = POLICY_FWD;
- other_sa->reqid = 0;
- if (priority == POLICY_PRIORITY_DEFAULT)
- {
- out_policy.prio = POLICY_PRIORITY_ROUTED;
- }
- charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
- other_sa->reqid = this->reqid;
+ out_policy.prio = POLICY_PRIORITY_ROUTED;
}
+ charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
+ other_sa->reqid = this->reqid;
}
}
-METHOD(child_sa_t, add_policies, status_t,
+/**
+ * Delete in- and outbound policies
+ */
+static void del_policies_internal(private_child_sa_t *this,
+ host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
+ traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
+ ipsec_sa_cfg_t *other_sa, policy_type_t type,
+ policy_priority_t priority, uint32_t manual_prio)
+{
+ del_policies_outbound(this, my_addr, other_addr, my_ts, other_ts, my_sa,
+ other_sa, type, priority, manual_prio);
+ del_policies_inbound(this, my_addr, other_addr, my_ts, other_ts, my_sa,
+ other_sa, type, priority, manual_prio);
+}
+
+METHOD(child_sa_t, set_policies, void,
private_child_sa_t *this, linked_list_t *my_ts_list,
linked_list_t *other_ts_list)
{
enumerator_t *enumerator;
traffic_selector_t *my_ts, *other_ts;
- status_t status = SUCCESS;
- if (!this->reqid_allocated && !this->static_reqid)
+ if (array_count(this->my_ts))
{
- /* trap policy, get or confirm reqid */
- status = charon->kernel->alloc_reqid(
- charon->kernel, my_ts_list, other_ts_list,
- this->mark_in, this->mark_out, &this->reqid);
- if (status != SUCCESS)
- {
- return status;
- }
- this->reqid_allocated = TRUE;
+ array_destroy_offset(this->my_ts,
+ offsetof(traffic_selector_t, destroy));
+ this->my_ts = array_create(0, 0);
}
-
- /* apply traffic selectors */
enumerator = my_ts_list->create_enumerator(my_ts_list);
while (enumerator->enumerate(enumerator, &my_ts))
{
@@ -1044,6 +1166,12 @@ METHOD(child_sa_t, add_policies, status_t,
enumerator->destroy(enumerator);
array_sort(this->my_ts, (void*)traffic_selector_cmp, NULL);
+ if (array_count(this->other_ts))
+ {
+ array_destroy_offset(this->other_ts,
+ offsetof(traffic_selector_t, destroy));
+ this->other_ts = array_create(0, 0);
+ }
enumerator = other_ts_list->create_enumerator(other_ts_list);
while (enumerator->enumerate(enumerator, &other_ts))
{
@@ -1051,12 +1179,40 @@ METHOD(child_sa_t, add_policies, status_t,
}
enumerator->destroy(enumerator);
array_sort(this->other_ts, (void*)traffic_selector_cmp, NULL);
+}
+
+METHOD(child_sa_t, install_policies, status_t,
+ private_child_sa_t *this)
+{
+ enumerator_t *enumerator;
+ linked_list_t *my_ts_list, *other_ts_list;
+ traffic_selector_t *my_ts, *other_ts;
+ status_t status = SUCCESS;
- if (this->config->install_policy(this->config))
+ if (!this->reqid_allocated && !this->static_reqid)
+ {
+ my_ts_list = linked_list_create_from_enumerator(
+ array_create_enumerator(this->my_ts));
+ other_ts_list = linked_list_create_from_enumerator(
+ array_create_enumerator(this->other_ts));
+ status = charon->kernel->alloc_reqid(
+ charon->kernel, my_ts_list, other_ts_list,
+ this->mark_in, this->mark_out, &this->reqid);
+ my_ts_list->destroy(my_ts_list);
+ other_ts_list->destroy(other_ts_list);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ this->reqid_allocated = TRUE;
+ }
+
+ if (!this->config->has_option(this->config, OPT_NO_POLICIES))
{
policy_priority_t priority;
ipsec_sa_cfg_t my_sa, other_sa;
uint32_t manual_prio;
+ bool install_outbound;
prepare_sa_cfg(this, &my_sa, &other_sa);
manual_prio = this->config->get_manual_prio(this->config);
@@ -1066,6 +1222,7 @@ METHOD(child_sa_t, add_policies, status_t,
this->trap = this->state == CHILD_CREATED;
priority = this->trap ? POLICY_PRIORITY_ROUTED
: POLICY_PRIORITY_DEFAULT;
+ install_outbound = this->outbound_state != CHILD_OUTBOUND_REGISTERED;
/* enumerate pairs of traffic selectors */
enumerator = create_policy_enumerator(this);
@@ -1074,20 +1231,27 @@ METHOD(child_sa_t, add_policies, status_t,
/* install outbound drop policy to avoid packets leaving unencrypted
* when updating policies */
if (priority == POLICY_PRIORITY_DEFAULT && manual_prio == 0 &&
- require_policy_update())
+ require_policy_update() && install_outbound)
{
- status |= install_policies_internal(this, this->my_addr,
+ status |= install_policies_outbound(this, this->my_addr,
this->other_addr, my_ts, other_ts,
&my_sa, &other_sa, POLICY_DROP,
POLICY_PRIORITY_FALLBACK, 0);
}
- /* install policies */
- status |= install_policies_internal(this, this->my_addr,
+ status |= install_policies_inbound(this, this->my_addr,
this->other_addr, my_ts, other_ts,
&my_sa, &other_sa, POLICY_IPSEC,
priority, manual_prio);
+ if (install_outbound)
+ {
+ status |= install_policies_outbound(this, this->my_addr,
+ this->other_addr, my_ts, other_ts,
+ &my_sa, &other_sa, POLICY_IPSEC,
+ priority, manual_prio);
+
+ }
if (status != SUCCESS)
{
break;
@@ -1103,13 +1267,150 @@ METHOD(child_sa_t, add_policies, status_t,
return status;
}
-/**
- * Callback to reinstall a virtual IP
- */
-static void reinstall_vip(host_t *vip, host_t *me)
+METHOD(child_sa_t, register_outbound, void,
+ private_child_sa_t *this, chunk_t encr, chunk_t integ, uint32_t spi,
+ uint16_t cpi, bool tfcv3)
+{
+ DBG2(DBG_CHD, "registering outbound %N SA", protocol_id_names,
+ this->protocol);
+ DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), this->my_addr,
+ this->other_addr);
+
+ this->other_spi = spi;
+ this->other_cpi = cpi;
+ this->encr_r = chunk_clone(encr);
+ this->integ_r = chunk_clone(integ);
+ this->tfcv3 = tfcv3;
+ this->outbound_state = CHILD_OUTBOUND_REGISTERED;
+}
+
+METHOD(child_sa_t, install_outbound, status_t,
+ private_child_sa_t *this)
+{
+ enumerator_t *enumerator;
+ traffic_selector_t *my_ts, *other_ts;
+ status_t status;
+
+ status = install_internal(this, this->encr_r, this->integ_r,
+ this->other_spi, this->other_cpi, FALSE, FALSE,
+ this->tfcv3);
+ chunk_clear(&this->encr_r);
+ chunk_clear(&this->integ_r);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ if (!this->config->has_option(this->config, OPT_NO_POLICIES))
+ {
+ ipsec_sa_cfg_t my_sa, other_sa;
+ uint32_t manual_prio;
+
+ prepare_sa_cfg(this, &my_sa, &other_sa);
+ manual_prio = this->config->get_manual_prio(this->config);
+
+ enumerator = create_policy_enumerator(this);
+ while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
+ {
+ /* install outbound drop policy to avoid packets leaving unencrypted
+ * when updating policies */
+ if (manual_prio == 0 && require_policy_update())
+ {
+ status |= install_policies_outbound(this, this->my_addr,
+ this->other_addr, my_ts, other_ts,
+ &my_sa, &other_sa, POLICY_DROP,
+ POLICY_PRIORITY_FALLBACK, 0);
+ }
+ status |= install_policies_outbound(this, this->my_addr,
+ this->other_addr, my_ts, other_ts,
+ &my_sa, &other_sa, POLICY_IPSEC,
+ POLICY_PRIORITY_DEFAULT, manual_prio);
+ if (status != SUCCESS)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ return status;
+}
+
+METHOD(child_sa_t, remove_outbound, void,
+ private_child_sa_t *this)
+{
+ enumerator_t *enumerator;
+ traffic_selector_t *my_ts, *other_ts;
+
+ switch (this->outbound_state)
+ {
+ case CHILD_OUTBOUND_INSTALLED:
+ break;
+ case CHILD_OUTBOUND_REGISTERED:
+ chunk_clear(&this->encr_r);
+ chunk_clear(&this->integ_r);
+ this->outbound_state = CHILD_OUTBOUND_NONE;
+ /* fall-through */
+ case CHILD_OUTBOUND_NONE:
+ return;
+ }
+
+ if (!this->config->has_option(this->config, OPT_NO_POLICIES))
+ {
+ ipsec_sa_cfg_t my_sa, other_sa;
+ uint32_t manual_prio;
+
+ prepare_sa_cfg(this, &my_sa, &other_sa);
+ manual_prio = this->config->get_manual_prio(this->config);
+
+ enumerator = create_policy_enumerator(this);
+ while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
+ {
+ del_policies_outbound(this, this->my_addr, this->other_addr,
+ my_ts, other_ts, &my_sa, &other_sa,
+ POLICY_IPSEC, POLICY_PRIORITY_DEFAULT,
+ manual_prio);
+ if (manual_prio == 0 && require_policy_update())
+ {
+ del_policies_outbound(this, this->my_addr, this->other_addr,
+ my_ts, other_ts, &my_sa, &other_sa,
+ POLICY_DROP, POLICY_PRIORITY_FALLBACK, 0);
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ kernel_ipsec_sa_id_t id = {
+ .src = this->my_addr,
+ .dst = this->other_addr,
+ .spi = this->other_spi,
+ .proto = proto_ike2ip(this->protocol),
+ .mark = this->mark_out,
+ };
+ kernel_ipsec_del_sa_t sa = {
+ .cpi = this->other_cpi,
+ };
+ charon->kernel->del_sa(charon->kernel, &id, &sa);
+ this->outbound_state = CHILD_OUTBOUND_NONE;
+}
+
+METHOD(child_sa_t, set_rekey_spi, void,
+ private_child_sa_t *this, uint32_t spi)
+{
+ this->rekey_spi = spi;
+}
+
+METHOD(child_sa_t, get_rekey_spi, uint32_t,
+ private_child_sa_t *this)
{
+ return this->rekey_spi;
+}
+
+CALLBACK(reinstall_vip, void,
+ host_t *vip, va_list args)
+{
+ host_t *me;
char *iface;
+ VA_ARGS_VGET(args, me);
if (charon->kernel->get_interface(charon->kernel, me, &iface))
{
charon->kernel->del_ip(charon->kernel, vip, -1, TRUE);
@@ -1134,8 +1435,9 @@ METHOD(child_sa_t, update, status_t,
old = this->state;
set_state(this, CHILD_UPDATING);
- transport_proxy_mode = this->config->use_proxy_mode(this->config) &&
- this->mode == MODE_TRANSPORT;
+ transport_proxy_mode = this->mode == MODE_TRANSPORT &&
+ this->config->has_option(this->config,
+ OPT_PROXY_MODE);
if (!transport_proxy_mode)
{
@@ -1189,7 +1491,8 @@ METHOD(child_sa_t, update, status_t,
}
}
- if (this->config->install_policy(this->config) && require_policy_update())
+ if (!this->config->has_option(this->config, OPT_NO_POLICIES) &&
+ require_policy_update())
{
if (!me->ip_equals(me, this->my_addr) ||
!other->ip_equals(other, this->other_addr))
@@ -1229,7 +1532,7 @@ METHOD(child_sa_t, update, status_t,
/* we reinstall the virtual IP to handle interface roaming
* correctly */
- vips->invoke_function(vips, (void*)reinstall_vip, me);
+ vips->invoke_function(vips, reinstall_vip, me);
/* reinstall updated policies */
install_policies_internal(this, me, other, my_ts, other_ts,
@@ -1239,12 +1542,12 @@ METHOD(child_sa_t, update, status_t,
/* update fallback policies after the new policy is in place */
if (manual_prio == 0)
{
- del_policies_internal(this, this->my_addr, this->other_addr,
+ del_policies_outbound(this, this->my_addr, this->other_addr,
old_my_ts ?: my_ts,
old_other_ts ?: other_ts,
&my_sa, &other_sa, POLICY_DROP,
POLICY_PRIORITY_FALLBACK, 0);
- install_policies_internal(this, me, other, my_ts, other_ts,
+ install_policies_outbound(this, me, other, my_ts, other_ts,
&my_sa, &other_sa, POLICY_DROP,
POLICY_PRIORITY_FALLBACK, 0);
}
@@ -1287,25 +1590,35 @@ METHOD(child_sa_t, destroy, void,
set_state(this, CHILD_DESTROYING);
- if (this->config->install_policy(this->config))
+ if (!this->config->has_option(this->config, OPT_NO_POLICIES))
{
ipsec_sa_cfg_t my_sa, other_sa;
uint32_t manual_prio;
+ bool del_outbound;
prepare_sa_cfg(this, &my_sa, &other_sa);
manual_prio = this->config->get_manual_prio(this->config);
+ del_outbound = this->trap ||
+ this->outbound_state == CHILD_OUTBOUND_INSTALLED;
/* delete all policies in the kernel */
enumerator = create_policy_enumerator(this);
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
- del_policies_internal(this, this->my_addr, this->other_addr,
- my_ts, other_ts, &my_sa, &other_sa,
- POLICY_IPSEC, priority, manual_prio);
- if (priority == POLICY_PRIORITY_DEFAULT && manual_prio == 0 &&
- require_policy_update())
+ if (del_outbound)
{
- del_policies_internal(this, this->my_addr, this->other_addr,
+ del_policies_outbound(this, this->my_addr,
+ this->other_addr, my_ts, other_ts,
+ &my_sa, &other_sa, POLICY_IPSEC,
+ priority, manual_prio);
+ }
+ del_policies_inbound(this, this->my_addr, this->other_addr,
+ my_ts, other_ts, &my_sa, &other_sa,
+ POLICY_IPSEC, priority, manual_prio);
+ if (!this->trap && manual_prio == 0 && require_policy_update() &&
+ del_outbound)
+ {
+ del_policies_outbound(this, this->my_addr, this->other_addr,
my_ts, other_ts, &my_sa, &other_sa,
POLICY_DROP, POLICY_PRIORITY_FALLBACK, 0);
}
@@ -1327,7 +1640,7 @@ METHOD(child_sa_t, destroy, void,
};
charon->kernel->del_sa(charon->kernel, &id, &sa);
}
- if (this->other_spi)
+ if (this->other_spi && this->outbound_state == CHILD_OUTBOUND_INSTALLED)
{
kernel_ipsec_sa_id_t id = {
.src = this->my_addr,
@@ -1357,6 +1670,8 @@ METHOD(child_sa_t, destroy, void,
this->other_addr->destroy(this->other_addr);
DESTROY_IF(this->proposal);
this->config->destroy(this->config);
+ chunk_clear(&this->encr_r);
+ chunk_clear(&this->integ_r);
free(this);
}
@@ -1414,6 +1729,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
.get_config = _get_config,
.get_state = _get_state,
.set_state = _set_state,
+ .get_outbound_state = _get_outbound_state,
.get_spi = _get_spi,
.get_cpi = _get_cpi,
.get_protocol = _get_protocol,
@@ -1436,8 +1752,14 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
.alloc_spi = _alloc_spi,
.alloc_cpi = _alloc_cpi,
.install = _install,
+ .register_outbound = _register_outbound,
+ .install_outbound = _install_outbound,
+ .remove_outbound = _remove_outbound,
+ .set_rekey_spi = _set_rekey_spi,
+ .get_rekey_spi = _get_rekey_spi,
.update = _update,
- .add_policies = _add_policies,
+ .set_policies = _set_policies,
+ .install_policies = _install_policies,
.create_ts_enumerator = _create_ts_enumerator,
.create_policy_enumerator = _create_policy_enumerator,
.destroy = _destroy,
@@ -1456,7 +1778,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
.mark_in = config->get_mark(config, TRUE),
.mark_out = config->get_mark(config, FALSE),
.install_time = time_monotonic(NULL),
- .policies_fwd_out = config->install_fwd_out_policy(config),
+ .policies_fwd_out = config->has_option(config, OPT_FWD_OUT_POLICIES),
);
this->config = config;
@@ -1509,7 +1831,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
/* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
if (config->get_mode(config) == MODE_TRANSPORT &&
- config->use_proxy_mode(config))
+ config->has_option(config, OPT_PROXY_MODE))
{
this->mode = MODE_TRANSPORT;
diff --git a/src/libcharon/sa/child_sa.h b/src/libcharon/sa/child_sa.h
index bc7df996a..b9a913da1 100644
--- a/src/libcharon/sa/child_sa.h
+++ b/src/libcharon/sa/child_sa.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2006-2008 Tobias Brunner
+ * Copyright (C) 2006-2017 Tobias Brunner
* Copyright (C) 2006-2008 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
- * Hochschule fuer Technik Rapperswil
+ * 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
@@ -24,6 +24,7 @@
#define CHILD_SA_H_
typedef enum child_sa_state_t child_sa_state_t;
+typedef enum child_sa_outbound_state_t child_sa_outbound_state_t;
typedef struct child_sa_t child_sa_t;
#include <library.h>
@@ -53,7 +54,7 @@ enum child_sa_state_t {
CHILD_INSTALLING,
/**
- * Installed an in-use CHILD_SA
+ * Installed both SAs of a CHILD_SA
*/
CHILD_INSTALLED,
@@ -94,6 +95,32 @@ enum child_sa_state_t {
extern enum_name_t *child_sa_state_names;
/**
+ * States of the outbound SA of a CHILD_SA
+ */
+enum child_sa_outbound_state_t {
+
+ /**
+ * Outbound SA is not installed
+ */
+ CHILD_OUTBOUND_NONE,
+
+ /**
+ * Data for the outbound SA has been registered, but not installed yet
+ */
+ CHILD_OUTBOUND_REGISTERED,
+
+ /**
+ * The outbound SA is currently installed
+ */
+ CHILD_OUTBOUND_INSTALLED,
+};
+
+/**
+ * enum strings for child_sa_outbound_state_t.
+ */
+extern enum_name_t *child_sa_outbound_state_names;
+
+/**
* Represents an IPsec SAs between two hosts.
*
* A child_sa_t contains two SAs. SAs for both
@@ -152,7 +179,14 @@ struct child_sa_t {
*
* @return CHILD_SA state
*/
- child_sa_state_t (*get_state) (child_sa_t *this);
+ child_sa_state_t (*get_state)(child_sa_t *this);
+
+ /**
+ * Get the state of the outbound SA.
+ *
+ * @return outbound SA state
+ */
+ child_sa_outbound_state_t (*get_outbound_state)(child_sa_t *this);
/**
* Set the state of the CHILD_SA.
@@ -347,6 +381,8 @@ struct child_sa_t {
/**
* Install an IPsec SA for one direction.
*
+ * set_policies() should be called before calling this.
+ *
* @param encr encryption key, if any
* @param integ integrity key
* @param spi SPI to use, allocated for inbound
@@ -354,26 +390,84 @@ struct child_sa_t {
* @param initiator TRUE if initiator of exchange resulting in this SA
* @param inbound TRUE to install an inbound SA, FALSE for outbound
* @param tfcv3 TRUE if peer supports ESPv3 TFC
- * @param my_ts negotiated local traffic selector list
- * @param other_ts negotiated remote traffic selector list
* @return SUCCESS or FAILED
*/
status_t (*install)(child_sa_t *this, chunk_t encr, chunk_t integ,
uint32_t spi, uint16_t cpi,
- bool initiator, bool inbound, bool tfcv3,
- linked_list_t *my_ts, linked_list_t *other_ts);
+ bool initiator, bool inbound, bool tfcv3);
+
+ /**
+ * Register data for the installation of an outbound SA as responder during
+ * a rekeying.
+ *
+ * The SA is not installed until install_outbound() is called.
+ *
+ * @param encr encryption key, if any (cloned)
+ * @param integ integrity key (cloned)
+ * @param spi SPI to use, allocated for inbound
+ * @param cpi CPI to use, allocated for outbound
+ * @param tfcv3 TRUE if peer supports ESPv3 TFC
+ */
+ void (*register_outbound)(child_sa_t *this, chunk_t encr, chunk_t integ,
+ uint32_t spi, uint16_t cpi, bool tfcv3);
+
+ /**
+ * Install the outbound SA and the outbound policies as responder during a
+ * rekeying.
+ *
+ * @return SUCCESS or FAILED
+ */
+ status_t (*install_outbound)(child_sa_t *this);
+
+ /**
+ * Remove the outbound SA and the outbound policies after a rekeying.
+ */
+ void (*remove_outbound)(child_sa_t *this);
+
/**
- * Install the policies using some traffic selectors.
+ * Configure the policies using some traffic selectors.
*
* Supplied lists of traffic_selector_t's specify the policies
* to use for this child sa.
*
- * @param my_ts traffic selectors for local site
- * @param other_ts traffic selectors for remote site
+ * Install the policies by calling install_policies().
+ *
+ * This should be called before calling install() so the traffic selectors
+ * may be passed to the kernel interface when installing the SAs.
+ *
+ * @param my_ts traffic selectors for local site (cloned)
+ * @param other_ts traffic selectors for remote site (cloned)
+ */
+ void (*set_policies)(child_sa_t *this, linked_list_t *my_ts_list,
+ linked_list_t *other_ts_list);
+
+ /**
+ * Install the configured policies.
+ *
+ * If register_outbound() was called previously this only installs the
+ * inbound and forward policies, the outbound policies are installed when
+ * install_outbound() is called.
+ *
* @return SUCCESS or FAILED
*/
- status_t (*add_policies)(child_sa_t *this, linked_list_t *my_ts_list,
- linked_list_t *other_ts_list);
+ status_t (*install_policies)(child_sa_t *this);
+
+ /**
+ * Set the outbound SPI of the CHILD_SA that replaced this CHILD_SA during
+ * a rekeying.
+ *
+ * @param spi outbound SPI of the CHILD_SA that replaced this CHILD_SA
+ */
+ void (*set_rekey_spi)(child_sa_t *this, uint32_t spi);
+
+ /**
+ * Get the outbound SPI of the CHILD_SA that replaced this CHILD_SA during
+ * a rekeying.
+ *
+ * @return outbound SPI of the CHILD_SA that replaced this CHILD_SA
+ */
+ uint32_t (*get_rekey_spi)(child_sa_t *this);
+
/**
* Update hosts and ecapulation mode in the kernel SAs and policies.
*
diff --git a/src/libcharon/sa/eap/eap_manager.c b/src/libcharon/sa/eap/eap_manager.c
index e4fcbc8f0..b2a57ccfb 100644
--- a/src/libcharon/sa/eap/eap_manager.c
+++ b/src/libcharon/sa/eap/eap_manager.c
@@ -105,31 +105,38 @@ METHOD(eap_manager_t, remove_method, void,
this->lock->unlock(this->lock);
}
-/**
- * filter the registered methods
- */
-static bool filter_methods(uintptr_t role, eap_entry_t **entry,
- eap_type_t *type, void *in, uint32_t *vendor)
+CALLBACK(filter_methods, bool,
+ uintptr_t role, enumerator_t *orig, va_list args)
{
- if ((*entry)->role != (eap_role_t)role)
- {
- return FALSE;
- }
- if ((*entry)->vendor == 0 &&
- ((*entry)->type < 4 || (*entry)->type == EAP_EXPANDED ||
- (*entry)->type > EAP_EXPERIMENTAL))
- { /* filter invalid types */
- return FALSE;
- }
- if (type)
- {
- *type = (*entry)->type;
- }
- if (vendor)
+ eap_entry_t *entry;
+ eap_type_t *type;
+ uint32_t *vendor;
+
+ VA_ARGS_VGET(args, type, vendor);
+
+ while (orig->enumerate(orig, &entry))
{
- *vendor = (*entry)->vendor;
+ if (entry->role != (eap_role_t)role)
+ {
+ continue;
+ }
+ if (entry->vendor == 0 &&
+ (entry->type < 4 || entry->type == EAP_EXPANDED ||
+ entry->type > EAP_EXPERIMENTAL))
+ { /* filter invalid types */
+ continue;
+ }
+ if (type)
+ {
+ *type = entry->type;
+ }
+ if (vendor)
+ {
+ *vendor = entry->vendor;
+ }
+ return TRUE;
}
- return TRUE;
+ return FALSE;
}
METHOD(eap_manager_t, create_enumerator, enumerator_t*,
@@ -139,7 +146,7 @@ METHOD(eap_manager_t, create_enumerator, enumerator_t*,
return enumerator_create_cleaner(
enumerator_create_filter(
this->methods->create_enumerator(this->methods),
- (void*)filter_methods, (void*)(uintptr_t)role, NULL),
+ filter_methods, (void*)(uintptr_t)role, NULL),
(void*)this->lock->unlock, this->lock);
}
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index 76e10691f..045858792 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -1200,12 +1200,20 @@ METHOD(ike_sa_t, generate_message, status_t,
return status;
}
-static bool filter_fragments(private_ike_sa_t *this, packet_t **fragment,
- packet_t **packet)
+CALLBACK(filter_fragments, bool,
+ private_ike_sa_t *this, enumerator_t *orig, va_list args)
{
- *packet = (*fragment)->clone(*fragment);
- set_dscp(this, *packet);
- return TRUE;
+ packet_t *fragment, **packet;
+
+ VA_ARGS_VGET(args, packet);
+
+ if (orig->enumerate(orig, &fragment))
+ {
+ *packet = fragment->clone(fragment);
+ set_dscp(this, *packet);
+ return TRUE;
+ }
+ return FALSE;
}
METHOD(ike_sa_t, generate_message_fragmented, status_t,
@@ -1265,7 +1273,7 @@ METHOD(ike_sa_t, generate_message_fragmented, status_t,
{
charon->bus->message(charon->bus, message, FALSE, FALSE);
}
- *packets = enumerator_create_filter(fragments, (void*)filter_fragments,
+ *packets = enumerator_create_filter(fragments, filter_fragments,
this, NULL);
}
return status;
@@ -1699,8 +1707,11 @@ typedef struct {
} child_enumerator_t;
METHOD(enumerator_t, child_enumerate, bool,
- child_enumerator_t *this, child_sa_t **child_sa)
+ child_enumerator_t *this, va_list args)
{
+ child_sa_t **child_sa;
+
+ VA_ARGS_VGET(args, child_sa);
if (this->inner->enumerate(this->inner, &this->current))
{
*child_sa = this->current;
@@ -1723,7 +1734,8 @@ METHOD(ike_sa_t, create_child_sa_enumerator, enumerator_t*,
INIT(enumerator,
.public = {
- .enumerate = (void*)_child_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _child_enumerate,
.destroy = _child_enumerator_destroy,
},
.inner = array_create_enumerator(this->child_sas),
@@ -2619,24 +2631,31 @@ METHOD(ike_sa_t, add_configuration_attribute, void,
array_insert(this->attributes, ARRAY_TAIL, &entry);
}
-/**
- * Enumerator filter for attributes
- */
-static bool filter_attribute(void *null, attribute_entry_t **in,
- configuration_attribute_type_t *type, void *in2,
- chunk_t *data, void *in3, bool *handled)
+CALLBACK(filter_attribute, bool,
+ void *null, enumerator_t *orig, va_list args)
{
- *type = (*in)->type;
- *data = (*in)->data;
- *handled = (*in)->handler != NULL;
- return TRUE;
+ attribute_entry_t *entry;
+ configuration_attribute_type_t *type;
+ chunk_t *data;
+ bool *handled;
+
+ VA_ARGS_VGET(args, type, data, handled);
+
+ if (orig->enumerate(orig, &entry))
+ {
+ *type = entry->type;
+ *data = entry->data;
+ *handled = entry->handler != NULL;
+ return TRUE;
+ }
+ return FALSE;
}
METHOD(ike_sa_t, create_attribute_enumerator, enumerator_t*,
private_ike_sa_t *this)
{
return enumerator_create_filter(array_create_enumerator(this->attributes),
- (void*)filter_attribute, NULL, NULL);
+ filter_attribute, NULL, NULL);
}
METHOD(ike_sa_t, create_task_enumerator, enumerator_t*,
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c
index 6bd49a086..c0bfebb83 100644
--- a/src/libcharon/sa/ike_sa_manager.c
+++ b/src/libcharon/sa/ike_sa_manager.c
@@ -151,8 +151,10 @@ static entry_t *entry_create()
/**
* Function that matches entry_t objects by ike_sa_id_t.
*/
-static bool entry_match_by_id(entry_t *entry, ike_sa_id_t *id)
+static bool entry_match_by_id(entry_t *entry, void *arg)
{
+ ike_sa_id_t *id = arg;
+
if (id->equals(id, entry->ike_sa_id))
{
return TRUE;
@@ -172,7 +174,7 @@ static bool entry_match_by_id(entry_t *entry, ike_sa_id_t *id)
/**
* Function that matches entry_t objects by ike_sa_t pointers.
*/
-static bool entry_match_by_sa(entry_t *entry, ike_sa_t *ike_sa)
+static bool entry_match_by_sa(entry_t *entry, void *ike_sa)
{
return entry->ike_sa == ike_sa;
}
@@ -276,9 +278,6 @@ typedef struct segment_t segment_t;
struct segment_t {
/** mutex to access a segment exclusively */
mutex_t *mutex;
-
- /** the number of entries in this segment */
- u_int count;
};
typedef struct shareable_segment_t shareable_segment_t;
@@ -371,6 +370,11 @@ struct private_ike_sa_manager_t {
refcount_t half_open_count_responder;
/**
+ * Total number of IKE_SAs registered with IKE_SA manager.
+ */
+ refcount_t total_sa_count;
+
+ /**
* Hash table with connected_peers_t objects.
*/
table_item_t **connected_peers_table;
@@ -511,8 +515,13 @@ struct private_enumerator_t {
};
METHOD(enumerator_t, enumerate, bool,
- private_enumerator_t *this, entry_t **entry, u_int *segment)
+ private_enumerator_t *this, va_list args)
{
+ entry_t **entry;
+ u_int *segment;
+
+ VA_ARGS_VGET(args, entry, segment);
+
if (this->entry)
{
this->entry->condvar->signal(this->entry->condvar);
@@ -570,7 +579,8 @@ static enumerator_t* create_table_enumerator(private_ike_sa_manager_t *this)
INIT(enumerator,
.enumerator = {
- .enumerate = (void*)_enumerate,
+ .enumerate = enumerator_enumerate_default,
+ .venumerate = _enumerate,
.destroy = _enumerator_destroy,
},
.manager = this,
@@ -601,7 +611,7 @@ static u_int put_entry(private_ike_sa_manager_t *this, entry_t *entry)
item->next = current;
}
this->ike_sa_table[row] = item;
- this->segments[segment].count++;
+ ref_get(&this->total_sa_count);
return segment;
}
@@ -612,10 +622,9 @@ static u_int put_entry(private_ike_sa_manager_t *this, entry_t *entry)
static void remove_entry(private_ike_sa_manager_t *this, entry_t *entry)
{
table_item_t *item, *prev = NULL;
- u_int row, segment;
+ u_int row;
row = ike_sa_id_hash(entry->ike_sa_id) & this->table_mask;
- segment = row & this->segment_mask;
item = this->ike_sa_table[row];
while (item)
{
@@ -629,7 +638,7 @@ static void remove_entry(private_ike_sa_manager_t *this, entry_t *entry)
{
this->ike_sa_table[row] = item->next;
}
- this->segments[segment].count--;
+ ignore_result(ref_put(&this->total_sa_count));
free(item);
break;
}
@@ -648,7 +657,7 @@ static void remove_entry_at(private_enumerator_t *this)
{
table_item_t *current = this->current;
- this->manager->segments[this->segment].count--;
+ ignore_result(ref_put(&this->manager->total_sa_count));
this->current = this->prev;
if (this->prev)
@@ -670,7 +679,7 @@ static void remove_entry_at(private_enumerator_t *this)
*/
static status_t get_entry_by_match_function(private_ike_sa_manager_t *this,
ike_sa_id_t *ike_sa_id, entry_t **entry, u_int *segment,
- linked_list_match_t match, void *param)
+ bool (*match)(entry_t*,void*), void *param)
{
table_item_t *item;
u_int row, seg;
@@ -703,7 +712,7 @@ static status_t get_entry_by_id(private_ike_sa_manager_t *this,
ike_sa_id_t *ike_sa_id, entry_t **entry, u_int *segment)
{
return get_entry_by_match_function(this, ike_sa_id, entry, segment,
- (linked_list_match_t)entry_match_by_id, ike_sa_id);
+ entry_match_by_id, ike_sa_id);
}
/**
@@ -714,7 +723,7 @@ static status_t get_entry_by_sa(private_ike_sa_manager_t *this,
ike_sa_id_t *ike_sa_id, ike_sa_t *ike_sa, entry_t **entry, u_int *segment)
{
return get_entry_by_match_function(this, ike_sa_id, entry, segment,
- (linked_list_match_t)entry_match_by_sa, ike_sa);
+ entry_match_by_sa, ike_sa);
}
/**
@@ -851,6 +860,15 @@ static void remove_half_open(private_ike_sa_manager_t *this, entry_t *entry)
lock->unlock(lock);
}
+CALLBACK(id_matches, bool,
+ ike_sa_id_t *a, va_list args)
+{
+ ike_sa_id_t *b;
+
+ VA_ARGS_VGET(args, b);
+ return a->equals(a, b);
+}
+
/**
* Put an SA between two peers into the hash table.
*/
@@ -879,8 +897,7 @@ static void put_connected_peers(private_ike_sa_manager_t *this, entry_t *entry)
entry->other_id, family))
{
if (connected_peers->sas->find_first(connected_peers->sas,
- (linked_list_match_t)entry->ike_sa_id->equals,
- NULL, entry->ike_sa_id) == SUCCESS)
+ id_matches, NULL, entry->ike_sa_id))
{
lock->unlock(lock);
return;
@@ -1555,42 +1572,52 @@ METHOD(ike_sa_manager_t, checkout_by_name, ike_sa_t*,
return ike_sa;
}
-/**
- * enumerator filter function, waiting variant
- */
-static bool enumerator_filter_wait(private_ike_sa_manager_t *this,
- entry_t **in, ike_sa_t **out, u_int *segment)
+CALLBACK(enumerator_filter_wait, bool,
+ private_ike_sa_manager_t *this, enumerator_t *orig, va_list args)
{
- if (wait_for_entry(this, *in, *segment))
+ entry_t *entry;
+ u_int segment;
+ ike_sa_t **out;
+
+ VA_ARGS_VGET(args, out);
+
+ while (orig->enumerate(orig, &entry, &segment))
{
- *out = (*in)->ike_sa;
- charon->bus->set_sa(charon->bus, *out);
- return TRUE;
+ if (wait_for_entry(this, entry, segment))
+ {
+ *out = entry->ike_sa;
+ charon->bus->set_sa(charon->bus, *out);
+ return TRUE;
+ }
}
return FALSE;
}
-/**
- * enumerator filter function, skipping variant
- */
-static bool enumerator_filter_skip(private_ike_sa_manager_t *this,
- entry_t **in, ike_sa_t **out, u_int *segment)
+CALLBACK(enumerator_filter_skip, bool,
+ private_ike_sa_manager_t *this, enumerator_t *orig, va_list args)
{
- if (!(*in)->driveout_new_threads &&
- !(*in)->driveout_waiting_threads &&
- !(*in)->checked_out)
+ entry_t *entry;
+ u_int segment;
+ ike_sa_t **out;
+
+ VA_ARGS_VGET(args, out);
+
+ while (orig->enumerate(orig, &entry, &segment))
{
- *out = (*in)->ike_sa;
- charon->bus->set_sa(charon->bus, *out);
- return TRUE;
+ if (!entry->driveout_new_threads &&
+ !entry->driveout_waiting_threads &&
+ !entry->checked_out)
+ {
+ *out = entry->ike_sa;
+ charon->bus->set_sa(charon->bus, *out);
+ return TRUE;
+ }
}
return FALSE;
}
-/**
- * Reset threads SA after enumeration
- */
-static void reset_sa(void *data)
+CALLBACK(reset_sa, void,
+ void *data)
{
charon->bus->set_sa(charon->bus, NULL);
}
@@ -2034,17 +2061,7 @@ METHOD(ike_sa_manager_t, has_contact, bool,
METHOD(ike_sa_manager_t, get_count, u_int,
private_ike_sa_manager_t *this)
{
- u_int segment, count = 0;
- mutex_t *mutex;
-
- for (segment = 0; segment < this->segment_count; segment++)
- {
- mutex = this->segments[segment & this->segment_mask].mutex;
- mutex->lock(mutex);
- count += this->segments[segment].count;
- mutex->unlock(mutex);
- }
- return count;
+ return (u_int)ref_cur(&this->total_sa_count);
}
METHOD(ike_sa_manager_t, get_half_open_count, u_int,
diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c
index 1da17ee50..48ec3e7f5 100644
--- a/src/libcharon/sa/ikev1/task_manager_v1.c
+++ b/src/libcharon/sa/ikev1/task_manager_v1.c
@@ -210,6 +210,16 @@ struct private_task_manager_t {
double retransmit_base;
/**
+ * Jitter to apply to calculated retransmit timeout (in percent)
+ */
+ u_int retransmit_jitter;
+
+ /**
+ * Limit retransmit timeout to this value
+ */
+ uint32_t retransmit_limit;
+
+ /**
* Sequence number for sending DPD requests
*/
uint32_t dpd_send;
@@ -345,7 +355,7 @@ static status_t retransmit_packet(private_task_manager_t *this, uint32_t seqnr,
u_int mid, u_int retransmitted, array_t *packets)
{
packet_t *packet;
- uint32_t t;
+ uint32_t t, max_jitter;
array_get(packets, 0, &packet);
if (retransmitted > this->retransmit_tries)
@@ -356,6 +366,15 @@ static status_t retransmit_packet(private_task_manager_t *this, uint32_t seqnr,
}
t = (uint32_t)(this->retransmit_timeout * 1000.0 *
pow(this->retransmit_base, retransmitted));
+ if (this->retransmit_limit)
+ {
+ t = min(t, this->retransmit_limit);
+ }
+ if (this->retransmit_jitter)
+ {
+ max_jitter = (t / 100.0) * this->retransmit_jitter;
+ t -= max_jitter * (random() / (RAND_MAX + 1.0));
+ }
if (retransmitted)
{
DBG1(DBG_IKE, "sending retransmit %u of %s message ID %u, seq %u",
@@ -2034,11 +2053,15 @@ task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa)
.active_tasks = linked_list_create(),
.passive_tasks = linked_list_create(),
.retransmit_tries = lib->settings->get_int(lib->settings,
- "%s.retransmit_tries", RETRANSMIT_TRIES, lib->ns),
+ "%s.retransmit_tries", RETRANSMIT_TRIES, lib->ns),
.retransmit_timeout = lib->settings->get_double(lib->settings,
- "%s.retransmit_timeout", RETRANSMIT_TIMEOUT, lib->ns),
+ "%s.retransmit_timeout", RETRANSMIT_TIMEOUT, lib->ns),
.retransmit_base = lib->settings->get_double(lib->settings,
- "%s.retransmit_base", RETRANSMIT_BASE, lib->ns),
+ "%s.retransmit_base", RETRANSMIT_BASE, lib->ns),
+ .retransmit_jitter = min(lib->settings->get_int(lib->settings,
+ "%s.retransmit_jitter", 0, lib->ns), RETRANSMIT_JITTER_MAX),
+ .retransmit_limit = lib->settings->get_int(lib->settings,
+ "%s.retransmit_limit", 0, lib->ns) * 1000,
);
if (!this->rng)
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c
index bbb885850..8be82ebe2 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c
@@ -325,6 +325,17 @@ static bool install(private_quick_mode_t *this)
return FALSE;
}
+ if (this->initiator)
+ {
+ this->child_sa->set_policies(this->child_sa, tsi, tsr);
+ }
+ else
+ {
+ this->child_sa->set_policies(this->child_sa, tsr, tsi);
+ }
+ tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
+ tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
+
if (this->keymat->derive_child_keys(this->keymat, this->proposal, this->dh,
this->spi_i, this->spi_r, this->nonce_i, this->nonce_r,
&encr_i, &integ_i, &encr_r, &integ_r))
@@ -333,19 +344,19 @@ static bool install(private_quick_mode_t *this)
{
status_i = this->child_sa->install(this->child_sa,
encr_r, integ_r, this->spi_i, this->cpi_i,
- this->initiator, TRUE, FALSE, tsi, tsr);
+ this->initiator, TRUE, FALSE);
status_o = this->child_sa->install(this->child_sa,
encr_i, integ_i, this->spi_r, this->cpi_r,
- this->initiator, FALSE, FALSE, tsi, tsr);
+ this->initiator, FALSE, FALSE);
}
else
{
status_i = this->child_sa->install(this->child_sa,
encr_i, integ_i, this->spi_r, this->cpi_r,
- this->initiator, TRUE, FALSE, tsr, tsi);
+ this->initiator, TRUE, FALSE);
status_o = this->child_sa->install(this->child_sa,
encr_r, integ_r, this->spi_i, this->cpi_i,
- this->initiator, FALSE, FALSE, tsr, tsi);
+ this->initiator, FALSE, FALSE);
}
}
@@ -355,22 +366,12 @@ static bool install(private_quick_mode_t *this)
(status_i != SUCCESS) ? "inbound " : "",
(status_i != SUCCESS && status_o != SUCCESS) ? "and ": "",
(status_o != SUCCESS) ? "outbound " : "");
- tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
- tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
status = FAILED;
}
else
{
- if (this->initiator)
- {
- status = this->child_sa->add_policies(this->child_sa, tsi, tsr);
- }
- else
- {
- status = this->child_sa->add_policies(this->child_sa, tsr, tsi);
- }
- tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
- tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
+ status = this->child_sa->install_policies(this->child_sa);
+
if (status != SUCCESS)
{
DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
@@ -853,7 +854,7 @@ METHOD(task_t, build_i, status_t,
add_nat_oa_payloads(this, message);
}
- if (this->config->use_ipcomp(this->config))
+ if (this->config->has_option(this->config, OPT_IPCOMP))
{
this->cpi_i = this->child_sa->alloc_cpi(this->child_sa);
if (!this->cpi_i)
@@ -1108,7 +1109,7 @@ METHOD(task_t, process_r, status_t,
return send_notify(this, INVALID_ID_INFORMATION);
}
- if (this->config->use_ipcomp(this->config))
+ if (this->config->has_option(this->config, OPT_IPCOMP))
{
list = sa_payload->get_ipcomp_proposals(sa_payload,
&this->cpi_i);
diff --git a/src/libcharon/sa/ikev2/connect_manager.c b/src/libcharon/sa/ikev2/connect_manager.c
index 280796d8c..35856788c 100644
--- a/src/libcharon/sa/ikev2/connect_manager.c
+++ b/src/libcharon/sa/ikev2/connect_manager.c
@@ -450,22 +450,21 @@ static initiate_data_t *initiate_data_create(check_list_t *checklist,
return this;
}
-/**
- * Find an initiated connection by the peers' ids
- */
-static bool match_initiated_by_ids(initiated_t *current, identification_t *id,
- identification_t *peer_id)
+CALLBACK(match_initiated_by_ids, bool,
+ initiated_t *current, va_list args)
{
+ identification_t *id, *peer_id;
+
+ VA_ARGS_VGET(args, id, peer_id);
return id->equals(id, current->id) && peer_id->equals(peer_id, current->peer_id);
}
-static status_t get_initiated_by_ids(private_connect_manager_t *this,
- identification_t *id,
- identification_t *peer_id,
- initiated_t **initiated)
+static bool get_initiated_by_ids(private_connect_manager_t *this,
+ identification_t *id,
+ identification_t *peer_id,
+ initiated_t **initiated)
{
- return this->initiated->find_first(this->initiated,
- (linked_list_match_t)match_initiated_by_ids,
+ return this->initiated->find_first(this->initiated, match_initiated_by_ids,
(void**)initiated, id, peer_id);
}
@@ -490,21 +489,20 @@ static void remove_initiated(private_connect_manager_t *this,
enumerator->destroy(enumerator);
}
-/**
- * Find the checklist with a specific connect ID
- */
-static bool match_checklist_by_id(check_list_t *current, chunk_t *connect_id)
+CALLBACK(match_checklist_by_id, bool,
+ check_list_t *current, va_list args)
{
- return chunk_equals(*connect_id, current->connect_id);
+ chunk_t connect_id;
+
+ VA_ARGS_VGET(args, connect_id);
+ return chunk_equals(connect_id, current->connect_id);
}
-static status_t get_checklist_by_id(private_connect_manager_t *this,
- chunk_t connect_id,
- check_list_t **check_list)
+static bool get_checklist_by_id(private_connect_manager_t *this,
+ chunk_t connect_id, check_list_t **check_list)
{
- return this->checklists->find_first(this->checklists,
- (linked_list_match_t)match_checklist_by_id,
- (void**)check_list, &connect_id);
+ return this->checklists->find_first(this->checklists, match_checklist_by_id,
+ (void**)check_list, connect_id);
}
/**
@@ -528,19 +526,19 @@ static void remove_checklist(private_connect_manager_t *this,
enumerator->destroy(enumerator);
}
-/**
- * Checks if a list of endpoint_notify_t contains a certain host_t
- */
-static bool match_endpoint_by_host(endpoint_notify_t *current, host_t *host)
+CALLBACK(match_endpoint_by_host, bool,
+ endpoint_notify_t *current, va_list args)
{
+ host_t *host;
+
+ VA_ARGS_VGET(args, host);
return host->equals(host, current->get_host(current));
}
-static status_t endpoints_contain(linked_list_t *endpoints, host_t *host,
+static bool endpoints_contain(linked_list_t *endpoints, host_t *host,
endpoint_notify_t **endpoint)
{
- return endpoints->find_first(endpoints,
- (linked_list_match_t)match_endpoint_by_host,
+ return endpoints->find_first(endpoints, match_endpoint_by_host,
(void**)endpoint, host);
}
@@ -560,39 +558,44 @@ static void insert_pair_by_priority(linked_list_t *pairs, endpoint_pair_t *pair)
enumerator->destroy(enumerator);
}
-/**
- * Searches a list of endpoint_pair_t for a pair with specific host_ts
- */
-static bool match_pair_by_hosts(endpoint_pair_t *current, host_t *local,
- host_t *remote)
+CALLBACK(match_pair_by_hosts, bool,
+ endpoint_pair_t *current, va_list args)
{
- return local->equals(local, current->local) && remote->equals(remote, current->remote);
+ host_t *local, *remote;
+
+ VA_ARGS_VGET(args, local, remote);
+ return local->equals(local, current->local) &&
+ remote->equals(remote, current->remote);
}
-static status_t get_pair_by_hosts(linked_list_t *pairs, host_t *local,
- host_t *remote, endpoint_pair_t **pair)
+static bool get_pair_by_hosts(linked_list_t *pairs, host_t *local,
+ host_t *remote, endpoint_pair_t **pair)
{
- return pairs->find_first(pairs, (linked_list_match_t)match_pair_by_hosts,
- (void**)pair, local, remote);
+ return pairs->find_first(pairs, match_pair_by_hosts, (void**)pair, local,
+ remote);
}
-static bool match_pair_by_id(endpoint_pair_t *current, uint32_t *id)
+CALLBACK(match_pair_by_id, bool,
+ endpoint_pair_t *current, va_list args)
{
- return current->id == *id;
+ uint32_t id;
+
+ VA_ARGS_VGET(args, id);
+ return current->id == id;
}
/**
* Searches for a pair with a specific id
*/
-static status_t get_pair_by_id(check_list_t *checklist, uint32_t id,
- endpoint_pair_t **pair)
+static bool get_pair_by_id(check_list_t *checklist, uint32_t id,
+ endpoint_pair_t **pair)
{
- return checklist->pairs->find_first(checklist->pairs,
- (linked_list_match_t)match_pair_by_id,
- (void**)pair, &id);
+ return checklist->pairs->find_first(checklist->pairs, match_pair_by_id,
+ (void**)pair, id);
}
-static bool match_succeeded_pair(endpoint_pair_t *current)
+CALLBACK(match_succeeded_pair, bool,
+ endpoint_pair_t *current, va_list args)
{
return current->state == CHECK_SUCCEEDED;
}
@@ -600,15 +603,14 @@ static bool match_succeeded_pair(endpoint_pair_t *current)
/**
* Returns the best pair of state CHECK_SUCCEEDED from a checklist.
*/
-static status_t get_best_valid_pair(check_list_t *checklist,
- endpoint_pair_t **pair)
+static bool get_best_valid_pair(check_list_t *checklist, endpoint_pair_t **pair)
{
- return checklist->pairs->find_first(checklist->pairs,
- (linked_list_match_t)match_succeeded_pair,
- (void**)pair);
+ return checklist->pairs->find_first(checklist->pairs, match_succeeded_pair,
+ (void**)pair);
}
-static bool match_waiting_pair(endpoint_pair_t *current)
+CALLBACK(match_waiting_pair, bool,
+ endpoint_pair_t *current, va_list args)
{
return current->state == CHECK_WAITING;
}
@@ -865,7 +867,7 @@ static job_requeue_t initiator_finish(callback_data_t *data)
this->mutex->lock(this->mutex);
check_list_t *checklist;
- if (get_checklist_by_id(this, data->connect_id, &checklist) != SUCCESS)
+ if (!get_checklist_by_id(this, data->connect_id, &checklist))
{
DBG1(DBG_IKE, "checklist with id '%#B' not found, can't finish "
"connectivity checks", &data->connect_id);
@@ -953,7 +955,7 @@ static job_requeue_t retransmit(callback_data_t *data)
this->mutex->lock(this->mutex);
check_list_t *checklist;
- if (get_checklist_by_id(this, data->connect_id, &checklist) != SUCCESS)
+ if (!get_checklist_by_id(this, data->connect_id, &checklist))
{
DBG1(DBG_IKE, "checklist with id '%#B' not found, can't retransmit "
"connectivity check", &data->connect_id);
@@ -962,7 +964,7 @@ static job_requeue_t retransmit(callback_data_t *data)
}
endpoint_pair_t *pair;
- if (get_pair_by_id(checklist, data->mid, &pair) != SUCCESS)
+ if (!get_pair_by_id(checklist, data->mid, &pair))
{
DBG1(DBG_IKE, "pair with id '%d' not found, can't retransmit "
"connectivity check", data->mid);
@@ -1108,7 +1110,7 @@ static job_requeue_t sender(callback_data_t *data)
this->mutex->lock(this->mutex);
check_list_t *checklist;
- if (get_checklist_by_id(this, data->connect_id, &checklist) != SUCCESS)
+ if (!get_checklist_by_id(this, data->connect_id, &checklist))
{
DBG1(DBG_IKE, "checklist with id '%#B' not found, can't send "
"connectivity check", &data->connect_id);
@@ -1124,9 +1126,8 @@ static job_requeue_t sender(callback_data_t *data)
{
DBG1(DBG_IKE, "no triggered check queued, sending an ordinary check");
- if (checklist->pairs->find_first(checklist->pairs,
- (linked_list_match_t)match_waiting_pair,
- (void**)&pair) != SUCCESS)
+ if (!checklist->pairs->find_first(checklist->pairs, match_waiting_pair,
+ (void**)&pair))
{
this->mutex->unlock(this->mutex);
DBG1(DBG_IKE, "no pairs in waiting state, aborting");
@@ -1182,7 +1183,7 @@ static job_requeue_t initiate_mediated(initiate_data_t *data)
initiated_t *initiated = data->initiated;
endpoint_pair_t *pair;
- if (get_best_valid_pair(checklist, &pair) == SUCCESS)
+ if (get_best_valid_pair(checklist, &pair))
{
ike_sa_id_t *waiting_sa;
enumerator_t *enumerator = initiated->mediated->create_enumerator(
@@ -1219,7 +1220,7 @@ static void finish_checks(private_connect_manager_t *this, check_list_t *checkli
{
initiated_t *initiated;
if (get_initiated_by_ids(this, checklist->initiator.id,
- checklist->responder.id, &initiated) == SUCCESS)
+ checklist->responder.id, &initiated))
{
callback_job_t *job;
@@ -1247,7 +1248,7 @@ static void process_response(private_connect_manager_t *this, check_t *check,
check_list_t *checklist)
{
endpoint_pair_t *pair;
- if (get_pair_by_id(checklist, check->mid, &pair) == SUCCESS)
+ if (get_pair_by_id(checklist, check->mid, &pair))
{
if (pair->local->equals(pair->local, check->dst) &&
pair->remote->equals(pair->remote, check->src))
@@ -1261,9 +1262,9 @@ static void process_response(private_connect_manager_t *this, check_t *check,
checklist->initiator.endpoints : checklist->responder.endpoints;
endpoint_notify_t *local_endpoint;
- if (endpoints_contain(local_endpoints,
- check->endpoint->get_host(check->endpoint),
- &local_endpoint) != SUCCESS)
+ if (!endpoints_contain(local_endpoints,
+ check->endpoint->get_host(check->endpoint),
+ &local_endpoint))
{
local_endpoint = endpoint_notify_create_from_host(PEER_REFLEXIVE,
check->endpoint->get_host(check->endpoint), pair->local);
@@ -1302,15 +1303,14 @@ static void process_request(private_connect_manager_t *this, check_t *check,
peer_reflexive->set_priority(peer_reflexive,
check->endpoint->get_priority(check->endpoint));
- if (endpoints_contain(remote_endpoints, check->src, &remote_endpoint) != SUCCESS)
+ if (!endpoints_contain(remote_endpoints, check->src, &remote_endpoint))
{
remote_endpoint = peer_reflexive->clone(peer_reflexive);
remote_endpoints->insert_last(remote_endpoints, remote_endpoint);
}
endpoint_pair_t *pair;
- if (get_pair_by_hosts(checklist->pairs, check->dst, check->src,
- &pair) == SUCCESS)
+ if (get_pair_by_hosts(checklist->pairs, check->dst, check->src, &pair))
{
switch(pair->state)
{
@@ -1389,7 +1389,7 @@ METHOD(connect_manager_t, process_check, void,
this->mutex->lock(this->mutex);
check_list_t *checklist;
- if (get_checklist_by_id(this, check->connect_id, &checklist) != SUCCESS)
+ if (!get_checklist_by_id(this, check->connect_id, &checklist))
{
DBG1(DBG_IKE, "checklist with id '%#B' not found",
&check->connect_id);
@@ -1423,6 +1423,15 @@ METHOD(connect_manager_t, process_check, void,
check_destroy(check);
}
+CALLBACK(id_matches, bool,
+ ike_sa_id_t *a, va_list args)
+{
+ ike_sa_id_t *b;
+
+ VA_ARGS_VGET(args, b);
+ return a->equals(a, b);
+}
+
METHOD(connect_manager_t, check_and_register, bool,
private_connect_manager_t *this, identification_t *id,
identification_t *peer_id, ike_sa_id_t *mediated_sa)
@@ -1432,7 +1441,7 @@ METHOD(connect_manager_t, check_and_register, bool,
this->mutex->lock(this->mutex);
- if (get_initiated_by_ids(this, id, peer_id, &initiated) != SUCCESS)
+ if (!get_initiated_by_ids(this, id, peer_id, &initiated))
{
DBG2(DBG_IKE, "registered waiting mediated connection with '%Y'",
peer_id);
@@ -1441,9 +1450,8 @@ METHOD(connect_manager_t, check_and_register, bool,
already_there = FALSE;
}
- if (initiated->mediated->find_first(initiated->mediated,
- (linked_list_match_t)mediated_sa->equals,
- NULL, mediated_sa) != SUCCESS)
+ if (!initiated->mediated->find_first(initiated->mediated, id_matches,
+ NULL, mediated_sa))
{
initiated->mediated->insert_last(initiated->mediated,
mediated_sa->clone(mediated_sa));
@@ -1462,7 +1470,7 @@ METHOD(connect_manager_t, check_and_initiate, void,
this->mutex->lock(this->mutex);
- if (get_initiated_by_ids(this, id, peer_id, &initiated) != SUCCESS)
+ if (!get_initiated_by_ids(this, id, peer_id, &initiated))
{
DBG2(DBG_IKE, "no waiting mediated connections with '%Y'", peer_id);
this->mutex->unlock(this->mutex);
@@ -1492,7 +1500,7 @@ METHOD(connect_manager_t, set_initiator_data, status_t,
this->mutex->lock(this->mutex);
- if (get_checklist_by_id(this, connect_id, NULL) == SUCCESS)
+ if (get_checklist_by_id(this, connect_id, NULL))
{
DBG1(DBG_IKE, "checklist with id '%#B' already exists, aborting",
&connect_id);
@@ -1517,7 +1525,7 @@ METHOD(connect_manager_t, set_responder_data, status_t,
this->mutex->lock(this->mutex);
- if (get_checklist_by_id(this, connect_id, &checklist) != SUCCESS)
+ if (!get_checklist_by_id(this, connect_id, &checklist))
{
DBG1(DBG_IKE, "checklist with id '%#B' not found",
&connect_id);
@@ -1547,7 +1555,7 @@ METHOD(connect_manager_t, stop_checks, status_t,
this->mutex->lock(this->mutex);
- if (get_checklist_by_id(this, connect_id, &checklist) != SUCCESS)
+ if (!get_checklist_by_id(this, connect_id, &checklist))
{
DBG1(DBG_IKE, "checklist with id '%#B' not found",
&connect_id);
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c
index e4a16faf0..c2ddbc588 100644
--- a/src/libcharon/sa/ikev2/task_manager_v2.c
+++ b/src/libcharon/sa/ikev2/task_manager_v2.c
@@ -161,6 +161,16 @@ struct private_task_manager_t {
double retransmit_base;
/**
+ * Jitter to apply to calculated retransmit timeout (in percent)
+ */
+ u_int retransmit_jitter;
+
+ /**
+ * Limit retransmit timeout to this value
+ */
+ uint32_t retransmit_limit;
+
+ /**
* Use make-before-break instead of break-before-make reauth?
*/
bool make_before_break;
@@ -321,7 +331,7 @@ METHOD(task_manager_t, retransmit, status_t,
if (message_id == this->initiating.mid &&
array_count(this->initiating.packets))
{
- uint32_t timeout;
+ uint32_t timeout, max_jitter;
job_t *job;
enumerator_t *enumerator;
packet_t *packet;
@@ -351,6 +361,16 @@ METHOD(task_manager_t, retransmit, status_t,
{
timeout = (uint32_t)(this->retransmit_timeout * 1000.0 *
pow(this->retransmit_base, this->initiating.retransmitted));
+
+ if (this->retransmit_limit)
+ {
+ timeout = min(timeout, this->retransmit_limit);
+ }
+ if (this->retransmit_jitter)
+ {
+ max_jitter = (timeout / 100.0) * this->retransmit_jitter;
+ timeout -= max_jitter * (random() / (RAND_MAX + 1.0));
+ }
}
else
{
@@ -2059,13 +2079,20 @@ METHOD(task_manager_t, reset, void,
this->reset = TRUE;
}
-/**
- * Filter queued tasks
- */
-static bool filter_queued(void *unused, queued_task_t **queued, task_t **task)
+CALLBACK(filter_queued, bool,
+ void *unused, enumerator_t *orig, va_list args)
{
- *task = (*queued)->task;
- return TRUE;
+ queued_task_t *queued;
+ task_t **task;
+
+ VA_ARGS_VGET(args, task);
+
+ if (orig->enumerate(orig, &queued))
+ {
+ *task = queued->task;
+ return TRUE;
+ }
+ return FALSE;
}
METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
@@ -2080,7 +2107,7 @@ METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
case TASK_QUEUE_QUEUED:
return enumerator_create_filter(
array_create_enumerator(this->queued_tasks),
- (void*)filter_queued, NULL, NULL);
+ filter_queued, NULL, NULL);
default:
return enumerator_create_empty();
}
@@ -2151,6 +2178,10 @@ task_manager_v2_t *task_manager_v2_create(ike_sa_t *ike_sa)
"%s.retransmit_timeout", RETRANSMIT_TIMEOUT, lib->ns),
.retransmit_base = lib->settings->get_double(lib->settings,
"%s.retransmit_base", RETRANSMIT_BASE, lib->ns),
+ .retransmit_jitter = min(lib->settings->get_int(lib->settings,
+ "%s.retransmit_jitter", 0, lib->ns), RETRANSMIT_JITTER_MAX),
+ .retransmit_limit = lib->settings->get_int(lib->settings,
+ "%s.retransmit_limit", 0, lib->ns) * 1000,
.make_before_break = lib->settings->get_bool(lib->settings,
"%s.make_before_break", FALSE, lib->ns),
);
diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c
index 71cb6b8ea..896cabb2b 100644
--- a/src/libcharon/sa/ikev2/tasks/child_create.c
+++ b/src/libcharon/sa/ikev2/tasks/child_create.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2016 Tobias Brunner
+ * Copyright (C) 2008-2017 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
@@ -602,7 +602,7 @@ static status_t select_and_install(private_child_create_t *this,
switch (this->mode)
{
case MODE_TRANSPORT:
- if (!this->config->use_proxy_mode(this->config) &&
+ if (!this->config->has_option(this->config, OPT_PROXY_MODE) &&
(!ts_list_is_host(this->tsi, other) ||
!ts_list_is_host(this->tsr, me))
)
@@ -630,6 +630,32 @@ static status_t select_and_install(private_child_create_t *this,
default:
break;
}
+ /* use a copy of the traffic selectors, as the POST hook should not
+ * change payloads */
+ my_ts = this->tsr->clone_offset(this->tsr,
+ offsetof(traffic_selector_t, clone));
+ other_ts = this->tsi->clone_offset(this->tsi,
+ offsetof(traffic_selector_t, clone));
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_RESPONDER_POST, my_ts, other_ts);
+
+ if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
+ {
+ my_ts->destroy_offset(my_ts,
+ offsetof(traffic_selector_t, destroy));
+ other_ts->destroy_offset(other_ts,
+ offsetof(traffic_selector_t, destroy));
+ return NOT_FOUND;
+ }
+ }
+
+ this->child_sa->set_policies(this->child_sa, my_ts, other_ts);
+ if (!this->initiator)
+ {
+ my_ts->destroy_offset(my_ts,
+ offsetof(traffic_selector_t, destroy));
+ other_ts->destroy_offset(other_ts,
+ offsetof(traffic_selector_t, destroy));
}
this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
@@ -651,19 +677,30 @@ static status_t select_and_install(private_child_create_t *this,
{
status_i = this->child_sa->install(this->child_sa, encr_r, integ_r,
this->my_spi, this->my_cpi, this->initiator,
- TRUE, this->tfcv3, my_ts, other_ts);
+ TRUE, this->tfcv3);
status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
this->other_spi, this->other_cpi, this->initiator,
- FALSE, this->tfcv3, my_ts, other_ts);
+ FALSE, this->tfcv3);
}
- else
+ else if (!this->rekey)
{
status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
this->my_spi, this->my_cpi, this->initiator,
- TRUE, this->tfcv3, my_ts, other_ts);
+ TRUE, this->tfcv3);
status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
this->other_spi, this->other_cpi, this->initiator,
- FALSE, this->tfcv3, my_ts, other_ts);
+ FALSE, this->tfcv3);
+ }
+ else
+ { /* as responder during a rekeying we only install the inbound
+ * SA now, the outbound SA and policies are installed when we
+ * receive the delete for the old SA */
+ status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
+ this->my_spi, this->my_cpi, this->initiator,
+ TRUE, this->tfcv3);
+ this->child_sa->register_outbound(this->child_sa, encr_r, integ_r,
+ this->other_spi, this->other_cpi, this->tfcv3);
+ status_o = SUCCESS;
}
}
@@ -679,36 +716,8 @@ static status_t select_and_install(private_child_create_t *this,
}
else
{
- if (this->initiator)
- {
- status = this->child_sa->add_policies(this->child_sa,
- my_ts, other_ts);
- }
- else
- {
- /* use a copy of the traffic selectors, as the POST hook should not
- * change payloads */
- my_ts = this->tsr->clone_offset(this->tsr,
- offsetof(traffic_selector_t, clone));
- other_ts = this->tsi->clone_offset(this->tsi,
- offsetof(traffic_selector_t, clone));
- charon->bus->narrow(charon->bus, this->child_sa,
- NARROW_RESPONDER_POST, my_ts, other_ts);
- if (my_ts->get_count(my_ts) == 0 ||
- other_ts->get_count(other_ts) == 0)
- {
- status = FAILED;
- }
- else
- {
- status = this->child_sa->add_policies(this->child_sa,
- my_ts, other_ts);
- }
- my_ts->destroy_offset(my_ts,
- offsetof(traffic_selector_t, destroy));
- other_ts->destroy_offset(other_ts,
- offsetof(traffic_selector_t, destroy));
- }
+ status = this->child_sa->install_policies(this->child_sa);
+
if (status != SUCCESS)
{
DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
@@ -736,7 +745,6 @@ static status_t select_and_install(private_child_create_t *this,
charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
this->dh, nonce_i, nonce_r);
- /* add to IKE_SA, and remove from task */
this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
this->established = TRUE;
@@ -748,16 +756,17 @@ static status_t select_and_install(private_child_create_t *this,
other_ts = linked_list_create_from_enumerator(
this->child_sa->create_ts_enumerator(this->child_sa, FALSE));
- DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
+ DBG0(DBG_IKE, "%sCHILD_SA %s{%d} established "
"with SPIs %.8x_i %.8x_o and TS %#R === %#R",
+ this->rekey && !this->initiator ? "inbound " : "",
this->child_sa->get_name(this->child_sa),
this->child_sa->get_unique_id(this->child_sa),
ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
- ntohl(this->child_sa->get_spi(this->child_sa, FALSE)), my_ts, other_ts);
+ ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
+ my_ts, other_ts);
my_ts->destroy(my_ts);
other_ts->destroy(other_ts);
-
return SUCCESS;
}
@@ -1073,7 +1082,7 @@ METHOD(task_t, build_i, status_t,
this->dh_group);
}
- if (this->config->use_ipcomp(this->config))
+ if (this->config->has_option(this->config, OPT_IPCOMP))
{
/* IPCOMP_DEFLATE is the only transform we support at the moment */
add_ipcomp_notify(this, message, IPCOMP_DEFLATE);
@@ -1327,7 +1336,7 @@ METHOD(task_t, build_r, status_t,
if (this->ipcomp_received != IPCOMP_NONE)
{
- if (this->config->use_ipcomp(this->config))
+ if (this->config->has_option(this->config, OPT_IPCOMP))
{
add_ipcomp_notify(this, message, this->ipcomp_received);
}
@@ -1690,7 +1699,6 @@ METHOD(task_t, destroy, void,
{
this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
}
-
DESTROY_IF(this->config);
DESTROY_IF(this->nonceg);
free(this);
diff --git a/src/libcharon/sa/ikev2/tasks/child_delete.c b/src/libcharon/sa/ikev2/tasks/child_delete.c
index 6fa8836ac..626796383 100644
--- a/src/libcharon/sa/ikev2/tasks/child_delete.c
+++ b/src/libcharon/sa/ikev2/tasks/child_delete.c
@@ -18,9 +18,14 @@
#include <daemon.h>
#include <encoding/payloads/delete_payload.h>
+#include <processing/jobs/delete_child_sa_job.h>
#include <sa/ikev2/tasks/child_create.h>
#include <sa/ikev2/tasks/child_rekey.h>
+#ifndef DELETE_REKEYED_DELAY
+#define DELETE_REKEYED_DELAY 5
+#endif
+
typedef struct private_child_delete_t private_child_delete_t;
/**
@@ -39,67 +44,80 @@ struct private_child_delete_t {
ike_sa_t *ike_sa;
/**
- * Are we the initiator?
+ * Whether we are the initiator of the exchange
*/
bool initiator;
/**
- * Protocol of CHILD_SA to delete
+ * Protocol of CHILD_SA to delete (as initiator)
*/
protocol_id_t protocol;
/**
- * Inbound SPI of CHILD_SA to delete
+ * Inbound SPI of CHILD_SA to delete (as initiator)
*/
uint32_t spi;
/**
- * whether to enforce delete action policy
- */
- bool check_delete_action;
-
- /**
- * is this delete exchange following a rekey?
- */
- bool rekeyed;
-
- /**
- * CHILD_SA already expired?
+ * CHILD_SA already expired (as initiator)
*/
bool expired;
/**
- * CHILD_SAs which get deleted
+ * CHILD_SAs which get deleted, entry_t*
*/
linked_list_t *child_sas;
};
/**
+ * Information about a deleted CHILD_SA
+ */
+typedef struct {
+ /** Deleted CHILD_SA */
+ child_sa_t *child_sa;
+ /** Whether the CHILD_SA was rekeyed */
+ bool rekeyed;
+ /** Whether to enforce any delete action policy */
+ bool check_delete_action;
+} entry_t;
+
+CALLBACK(match_child, bool,
+ entry_t *entry, va_list args)
+{
+ child_sa_t *child_sa;
+
+ VA_ARGS_VGET(args, child_sa);
+ return entry->child_sa == child_sa;
+}
+
+/**
* build the delete payloads from the listed child_sas
*/
static void build_payloads(private_child_delete_t *this, message_t *message)
{
delete_payload_t *ah = NULL, *esp = NULL;
enumerator_t *enumerator;
- child_sa_t *child_sa;
+ entry_t *entry;
+ protocol_id_t protocol;
+ uint32_t spi;
enumerator = this->child_sas->create_enumerator(this->child_sas);
- while (enumerator->enumerate(enumerator, (void**)&child_sa))
+ while (enumerator->enumerate(enumerator, (void**)&entry))
{
- protocol_id_t protocol = child_sa->get_protocol(child_sa);
- uint32_t spi = child_sa->get_spi(child_sa, TRUE);
+ protocol = entry->child_sa->get_protocol(entry->child_sa);
+ spi = entry->child_sa->get_spi(entry->child_sa, TRUE);
switch (protocol)
{
case PROTO_ESP:
- if (esp == NULL)
+ if (!esp)
{
esp = delete_payload_create(PLV2_DELETE, PROTO_ESP);
message->add_payload(message, (payload_t*)esp);
}
esp->add_spi(esp, spi);
DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x",
- protocol_id_names, protocol, ntohl(spi));
+ protocol_id_names, protocol, ntohl(spi));
break;
case PROTO_AH:
if (ah == NULL)
@@ -109,12 +127,12 @@ static void build_payloads(private_child_delete_t *this, message_t *message)
}
ah->add_spi(ah, spi);
DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x",
- protocol_id_names, protocol, ntohl(spi));
+ protocol_id_names, protocol, ntohl(spi));
break;
default:
break;
}
- child_sa->set_state(child_sa, CHILD_DELETING);
+ entry->child_sa->set_state(entry->child_sa, CHILD_DELETING);
}
enumerator->destroy(enumerator);
}
@@ -147,6 +165,57 @@ static bool is_redundant(private_child_delete_t *this, child_sa_t *child)
}
/**
+ * Install the outbound CHILD_SA with the given SPI
+ */
+static void install_outbound(private_child_delete_t *this,
+ protocol_id_t protocol, uint32_t spi)
+{
+ child_sa_t *child_sa;
+ linked_list_t *my_ts, *other_ts;
+ status_t status;
+
+ child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol,
+ spi, FALSE);
+ if (!child_sa)
+ {
+ DBG1(DBG_IKE, "CHILD_SA not found after rekeying");
+ return;
+ }
+ if (this->initiator && is_redundant(this, child_sa))
+ { /* if we won the rekey collision we don't want to install the
+ * redundant SA created by the peer */
+ return;
+ }
+
+ status = child_sa->install_outbound(child_sa);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_IKE, "unable to install outbound IPsec SA (SAD) in kernel");
+ charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_SA_FAILED,
+ child_sa);
+ /* FIXME: delete the new child_sa? */
+ return;
+ }
+ child_sa->set_state(child_sa, CHILD_INSTALLED);
+
+ my_ts = linked_list_create_from_enumerator(
+ child_sa->create_ts_enumerator(child_sa, TRUE));
+ other_ts = linked_list_create_from_enumerator(
+ child_sa->create_ts_enumerator(child_sa, FALSE));
+
+ DBG0(DBG_IKE, "outbound CHILD_SA %s{%d} established "
+ "with SPIs %.8x_i %.8x_o and TS %#R === %#R",
+ child_sa->get_name(child_sa),
+ child_sa->get_unique_id(child_sa),
+ ntohl(child_sa->get_spi(child_sa, TRUE)),
+ ntohl(child_sa->get_spi(child_sa, FALSE)),
+ my_ts, other_ts);
+
+ my_ts->destroy(my_ts);
+ other_ts->destroy(other_ts);
+}
+
+/**
* read in payloads and find the children to delete
*/
static void process_payloads(private_child_delete_t *this, message_t *message)
@@ -157,6 +226,7 @@ static void process_payloads(private_child_delete_t *this, message_t *message)
uint32_t spi;
protocol_id_t protocol;
child_sa_t *child_sa;
+ entry_t *entry;
payloads = message->create_payload_enumerator(message);
while (payloads->enumerate(payloads, &payload))
@@ -174,27 +244,37 @@ static void process_payloads(private_child_delete_t *this, message_t *message)
{
child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol,
spi, FALSE);
- if (child_sa == NULL)
+ if (!child_sa)
{
- DBG1(DBG_IKE, "received DELETE for %N CHILD_SA with SPI %.8x, "
- "but no such SA", protocol_id_names, protocol, ntohl(spi));
+ DBG1(DBG_IKE, "received DELETE for unknown %N CHILD_SA with"
+ " SPI %.8x", protocol_id_names, protocol, ntohl(spi));
continue;
}
DBG1(DBG_IKE, "received DELETE for %N CHILD_SA with SPI %.8x",
protocol_id_names, protocol, ntohl(spi));
+ if (this->child_sas->find_first(this->child_sas, match_child,
+ NULL, child_sa))
+ {
+ continue;
+ }
+ INIT(entry,
+ .child_sa = child_sa
+ );
switch (child_sa->get_state(child_sa))
{
case CHILD_REKEYED:
- this->rekeyed = TRUE;
+ entry->rekeyed = TRUE;
break;
case CHILD_DELETING:
- /* we don't send back a delete if we initiated ourself */
+ /* we don't send back a delete if we already initiated
+ * a delete ourself */
if (!this->initiator)
{
+ free(entry);
continue;
}
- /* fall through */
+ break;
case CHILD_REKEYING:
/* we reply as usual, rekeying will fail */
case CHILD_INSTALLED:
@@ -202,22 +282,18 @@ static void process_payloads(private_child_delete_t *this, message_t *message)
{
if (is_redundant(this, child_sa))
{
- this->rekeyed = TRUE;
+ entry->rekeyed = TRUE;
}
else
{
- this->check_delete_action = TRUE;
+ entry->check_delete_action = TRUE;
}
}
break;
default:
break;
}
- if (this->child_sas->find_first(this->child_sas, NULL,
- (void**)&child_sa) != SUCCESS)
- {
- this->child_sas->insert_last(this->child_sas, child_sa);
- }
+ this->child_sas->insert_last(this->child_sas, entry);
}
spis->destroy(spis);
}
@@ -231,29 +307,64 @@ static void process_payloads(private_child_delete_t *this, message_t *message)
static status_t destroy_and_reestablish(private_child_delete_t *this)
{
enumerator_t *enumerator;
+ entry_t *entry;
child_sa_t *child_sa;
child_cfg_t *child_cfg;
protocol_id_t protocol;
- uint32_t spi, reqid;
+ uint32_t spi, reqid, rekey_spi;
action_t action;
status_t status = SUCCESS;
+ time_t now, expire;
+ u_int delay;
+
+ now = time_monotonic(NULL);
+ delay = lib->settings->get_int(lib->settings, "%s.delete_rekeyed_delay",
+ DELETE_REKEYED_DELAY, lib->ns);
enumerator = this->child_sas->create_enumerator(this->child_sas);
- while (enumerator->enumerate(enumerator, (void**)&child_sa))
+ while (enumerator->enumerate(enumerator, (void**)&entry))
{
+ child_sa = entry->child_sa;
/* signal child down event if we weren't rekeying */
- if (!this->rekeyed)
+ protocol = child_sa->get_protocol(child_sa);
+ if (!entry->rekeyed)
{
charon->bus->child_updown(charon->bus, child_sa, FALSE);
}
+ else
+ {
+ rekey_spi = child_sa->get_rekey_spi(child_sa);
+ if (rekey_spi)
+ {
+ install_outbound(this, protocol, rekey_spi);
+ }
+ /* for rekeyed CHILD_SAs we uninstall the outbound SA but don't
+ * immediately destroy it, by default, so we can process delayed
+ * packets */
+ child_sa->remove_outbound(child_sa);
+ expire = child_sa->get_lifetime(child_sa, TRUE);
+ if (delay && (!expire || ((now + delay) < expire)))
+ {
+ lib->scheduler->schedule_job(lib->scheduler,
+ (job_t*)delete_child_sa_job_create_id(
+ child_sa->get_unique_id(child_sa)), delay);
+ continue;
+ }
+ else if (expire)
+ { /* let it expire naturally */
+ continue;
+ }
+ /* no delay and no lifetime, destroy it immediately */
+ }
spi = child_sa->get_spi(child_sa, TRUE);
reqid = child_sa->get_reqid(child_sa);
- protocol = child_sa->get_protocol(child_sa);
child_cfg = child_sa->get_config(child_sa);
child_cfg->get_ref(child_cfg);
action = child_sa->get_close_action(child_sa);
+
this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi);
- if (this->check_delete_action)
+
+ if (entry->check_delete_action)
{ /* enforce child_cfg policy if deleted passively */
switch (action)
{
@@ -288,12 +399,14 @@ static void log_children(private_child_delete_t *this)
{
linked_list_t *my_ts, *other_ts;
enumerator_t *enumerator;
+ entry_t *entry;
child_sa_t *child_sa;
uint64_t bytes_in, bytes_out;
enumerator = this->child_sas->create_enumerator(this->child_sas);
- while (enumerator->enumerate(enumerator, (void**)&child_sa))
+ while (enumerator->enumerate(enumerator, (void**)&entry))
{
+ child_sa = entry->child_sa;
my_ts = linked_list_create_from_enumerator(
child_sa->create_ts_enumerator(child_sa, TRUE));
other_ts = linked_list_create_from_enumerator(
@@ -328,6 +441,7 @@ METHOD(task_t, build_i, status_t,
private_child_delete_t *this, message_t *message)
{
child_sa_t *child_sa;
+ entry_t *entry;
child_sa = this->ike_sa->get_child_sa(this->ike_sa, this->protocol,
this->spi, TRUE);
@@ -342,15 +456,24 @@ METHOD(task_t, build_i, status_t,
/* we work only with the inbound SPI */
this->spi = child_sa->get_spi(child_sa, TRUE);
}
- this->child_sas->insert_last(this->child_sas, child_sa);
- if (child_sa->get_state(child_sa) == CHILD_REKEYED)
- {
- this->rekeyed = TRUE;
+
+ if (child_sa->get_state(child_sa) == CHILD_DELETING)
+ { /* DELETEs for this CHILD_SA were already exchanged, but it was not yet
+ * destroyed to allow delayed packets to get processed */
+ this->ike_sa->destroy_child_sa(this->ike_sa, this->protocol, this->spi);
+ message->set_exchange_type(message, EXCHANGE_TYPE_UNDEFINED);
+ return SUCCESS;
}
+
+ INIT(entry,
+ .child_sa = child_sa,
+ .rekeyed = child_sa->get_state(child_sa) == CHILD_REKEYED,
+ );
+ this->child_sas->insert_last(this->child_sas, entry);
log_children(this);
build_payloads(this, message);
- if (!this->rekeyed && this->expired)
+ if (!entry->rekeyed && this->expired)
{
child_cfg_t *child_cfg;
@@ -397,24 +520,28 @@ METHOD(child_delete_t , get_child, child_sa_t*,
private_child_delete_t *this)
{
child_sa_t *child_sa = NULL;
- this->child_sas->get_first(this->child_sas, (void**)&child_sa);
+ entry_t *entry;
+
+ if (this->child_sas->get_first(this->child_sas, (void**)&entry) == SUCCESS)
+ {
+ child_sa = entry->child_sa;
+ }
return child_sa;
}
METHOD(task_t, migrate, void,
private_child_delete_t *this, ike_sa_t *ike_sa)
{
- this->check_delete_action = FALSE;
this->ike_sa = ike_sa;
- this->child_sas->destroy(this->child_sas);
+ this->child_sas->destroy_function(this->child_sas, free);
this->child_sas = linked_list_create();
}
METHOD(task_t, destroy, void,
private_child_delete_t *this)
{
- this->child_sas->destroy(this->child_sas);
+ this->child_sas->destroy_function(this->child_sas, free);
free(this);
}
diff --git a/src/libcharon/sa/ikev2/tasks/child_rekey.c b/src/libcharon/sa/ikev2/tasks/child_rekey.c
index c04ec141f..761c860e7 100644
--- a/src/libcharon/sa/ikev2/tasks/child_rekey.c
+++ b/src/libcharon/sa/ikev2/tasks/child_rekey.c
@@ -132,6 +132,7 @@ static void find_child(private_child_rekey_t *this, message_t *message)
notify_payload_t *notify;
protocol_id_t protocol;
uint32_t spi;
+ child_sa_t *child_sa;
notify = message->get_notify(message, REKEY_SA);
if (notify)
@@ -141,8 +142,15 @@ static void find_child(private_child_rekey_t *this, message_t *message)
if (protocol == PROTO_ESP || protocol == PROTO_AH)
{
- this->child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol,
- spi, FALSE);
+ child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol,
+ spi, FALSE);
+ if (child_sa &&
+ child_sa->get_state(child_sa) == CHILD_DELETING &&
+ child_sa->get_outbound_state(child_sa) == CHILD_OUTBOUND_NONE)
+ { /* ignore rekeyed CHILD_SAs we keep around */
+ return;
+ }
+ this->child_sa = child_sa;
}
}
}
@@ -227,6 +235,7 @@ METHOD(task_t, build_r, status_t,
child_cfg_t *config;
uint32_t reqid;
child_sa_state_t state;
+ child_sa_t *child_sa;
if (!this->child_sa)
{
@@ -260,7 +269,10 @@ METHOD(task_t, build_r, status_t,
return SUCCESS;
}
+ child_sa = this->child_create->get_child(this->child_create);
this->child_sa->set_state(this->child_sa, CHILD_REKEYED);
+ this->child_sa->set_rekey_spi(this->child_sa,
+ child_sa->get_spi(child_sa, FALSE));
/* invoke rekey hook */
charon->bus->child_rekey(charon->bus, this->child_sa,
diff --git a/src/libcharon/sa/shunt_manager.c b/src/libcharon/sa/shunt_manager.c
index b0162751d..ad12f0579 100644
--- a/src/libcharon/sa/shunt_manager.c
+++ b/src/libcharon/sa/shunt_manager.c
@@ -381,14 +381,24 @@ METHOD(shunt_manager_t, uninstall, bool,
}
CALLBACK(filter_entries, bool,
- void *unused, entry_t **entry, char **ns, void **in, child_cfg_t **cfg)
+ void *unused, enumerator_t *orig, va_list args)
{
- if (ns)
+ entry_t *entry;
+ child_cfg_t **cfg;
+ char **ns;
+
+ VA_ARGS_VGET(args, ns, cfg);
+
+ if (orig->enumerate(orig, &entry))
{
- *ns = (*entry)->ns;
+ if (ns)
+ {
+ *ns = entry->ns;
+ }
+ *cfg = entry->cfg;
+ return TRUE;
}
- *cfg = (*entry)->cfg;
- return TRUE;
+ return FALSE;
}
METHOD(shunt_manager_t, create_enumerator, enumerator_t*,
@@ -397,7 +407,7 @@ METHOD(shunt_manager_t, create_enumerator, enumerator_t*,
this->lock->read_lock(this->lock);
return enumerator_create_filter(
this->shunts->create_enumerator(this->shunts),
- (void*)filter_entries, this->lock,
+ filter_entries, this->lock,
(void*)this->lock->unlock);
}
diff --git a/src/libcharon/sa/task_manager.c b/src/libcharon/sa/task_manager.c
index c42008ba9..bd1191406 100644
--- a/src/libcharon/sa/task_manager.c
+++ b/src/libcharon/sa/task_manager.c
@@ -15,10 +15,40 @@
#include "task_manager.h"
+#include <math.h>
#include <sa/ikev1/task_manager_v1.h>
#include <sa/ikev2/task_manager_v2.h>
-/**
+/*
+ * See header
+ */
+u_int task_manager_total_retransmit_timeout()
+{
+ double timeout, base, limit = 0, total = 0;
+ int tries, i;
+
+ tries = lib->settings->get_int(lib->settings, "%s.retransmit_tries",
+ RETRANSMIT_TRIES, lib->ns);
+ base = lib->settings->get_double(lib->settings, "%s.retransmit_base",
+ RETRANSMIT_BASE, lib->ns);
+ timeout = lib->settings->get_double(lib->settings, "%s.retransmit_timeout",
+ RETRANSMIT_TIMEOUT, lib->ns);
+ limit = lib->settings->get_double(lib->settings, "%s.retransmit_limit",
+ 0, lib->ns);
+
+ for (i = 0; i <= tries; i++)
+ {
+ double interval = timeout * pow(base, i);
+ if (limit)
+ {
+ interval = min(interval, limit);
+ }
+ total += interval;
+ }
+ return (u_int)total;
+}
+
+/*
* See header
*/
task_manager_t *task_manager_create(ike_sa_t *ike_sa)
diff --git a/src/libcharon/sa/task_manager.h b/src/libcharon/sa/task_manager.h
index 7e9262291..e3fddf39b 100644
--- a/src/libcharon/sa/task_manager.h
+++ b/src/libcharon/sa/task_manager.h
@@ -48,6 +48,11 @@ typedef enum task_queue_t task_queue_t;
#define RETRANSMIT_TRIES 5
/**
+ * Maximum jitter in percent.
+ */
+#define RETRANSMIT_JITTER_MAX 20
+
+/**
* Interval for mobike routability checks in ms.
*/
#define ROUTEABILITY_CHECK_INTERVAL 2500
@@ -298,6 +303,17 @@ struct task_manager_t {
};
/**
+ * Calculate total timeout of the retransmission mechanism.
+ *
+ * This is affected by modifications of retransmit_base, retransmit_timeout,
+ * retransmit_limit or retransmit_tries. The resulting value can then be used
+ * e.g. in kernel plugins to set the system's acquire timeout properly.
+ *
+ * @return calculated total retransmission timeout in seconds
+ */
+u_int task_manager_total_retransmit_timeout();
+
+/**
* Create a task manager instance for the correct IKE version.
*
* @param ike_sa IKE_SA to create a task manager for
diff --git a/src/libcharon/sa/trap_manager.c b/src/libcharon/sa/trap_manager.c
index 40a0682f2..f9fee5e7e 100644
--- a/src/libcharon/sa/trap_manager.c
+++ b/src/libcharon/sa/trap_manager.c
@@ -140,19 +140,21 @@ static void destroy_acquire(acquire_t *this)
free(this);
}
-/**
- * match an acquire entry by reqid
- */
-static bool acquire_by_reqid(acquire_t *this, uint32_t *reqid)
+CALLBACK(acquire_by_reqid, bool,
+ acquire_t *this, va_list args)
{
- return this->reqid == *reqid;
+ uint32_t reqid;
+
+ VA_ARGS_VGET(args, reqid);
+ return this->reqid == reqid;
}
-/**
- * match an acquire entry by destination address
- */
-static bool acquire_by_dst(acquire_t *this, host_t *dst)
+CALLBACK(acquire_by_dst, bool,
+ acquire_t *this, va_list args)
{
+ host_t *dst;
+
+ VA_ARGS_VGET(args, dst);
return this->dst && this->dst->ip_equals(this->dst, dst);
}
@@ -272,7 +274,8 @@ METHOD(trap_manager_t, install, uint32_t,
proposals->destroy_offset(proposals, offsetof(proposal_t, destroy));
child_sa->set_protocol(child_sa, proto);
child_sa->set_mode(child_sa, child->get_mode(child));
- status = child_sa->add_policies(child_sa, my_ts, other_ts);
+ child_sa->set_policies(child_sa, my_ts, other_ts);
+ status = child_sa->install_policies(child_sa);
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
if (status != SUCCESS)
@@ -334,25 +337,32 @@ METHOD(trap_manager_t, uninstall, bool,
return TRUE;
}
-/**
- * convert enumerated entries to peer_cfg, child_sa
- */
-static bool trap_filter(rwlock_t *lock, entry_t **entry, peer_cfg_t **peer_cfg,
- void *none, child_sa_t **child_sa)
+CALLBACK(trap_filter, bool,
+ rwlock_t *lock, enumerator_t *orig, va_list args)
{
- if (!(*entry)->child_sa)
- { /* skip entries that are currently being installed */
- return FALSE;
- }
- if (peer_cfg)
- {
- *peer_cfg = (*entry)->peer_cfg;
- }
- if (child_sa)
+ entry_t *entry;
+ peer_cfg_t **peer_cfg;
+ child_sa_t **child_sa;
+
+ VA_ARGS_VGET(args, peer_cfg, child_sa);
+
+ while (orig->enumerate(orig, &entry))
{
- *child_sa = (*entry)->child_sa;
+ if (!entry->child_sa)
+ { /* skip entries that are currently being installed */
+ continue;
+ }
+ if (peer_cfg)
+ {
+ *peer_cfg = entry->peer_cfg;
+ }
+ if (child_sa)
+ {
+ *child_sa = entry->child_sa;
+ }
+ return TRUE;
}
- return TRUE;
+ return FALSE;
}
METHOD(trap_manager_t, create_enumerator, enumerator_t*,
@@ -360,7 +370,7 @@ METHOD(trap_manager_t, create_enumerator, enumerator_t*,
{
this->lock->read_lock(this->lock);
return enumerator_create_filter(this->traps->create_enumerator(this->traps),
- (void*)trap_filter, this->lock,
+ trap_filter, this->lock,
(void*)this->lock->unlock);
}
@@ -431,8 +441,8 @@ METHOD(trap_manager_t, acquire, void,
uint8_t mask;
dst->to_subnet(dst, &host, &mask);
- if (this->acquires->find_first(this->acquires, (void*)acquire_by_dst,
- (void**)&acquire, host) == SUCCESS)
+ if (this->acquires->find_first(this->acquires, acquire_by_dst,
+ (void**)&acquire, host))
{
host->destroy(host);
ignore = TRUE;
@@ -448,8 +458,8 @@ METHOD(trap_manager_t, acquire, void,
}
else
{
- if (this->acquires->find_first(this->acquires, (void*)acquire_by_reqid,
- (void**)&acquire, &reqid) == SUCCESS)
+ if (this->acquires->find_first(this->acquires, acquire_by_reqid,
+ (void**)&acquire, reqid))
{
ignore = TRUE;
}
diff --git a/src/libcharon/tests/Makefile.in b/src/libcharon/tests/Makefile.in
index e922a7171..3070f429b 100644
--- a/src/libcharon/tests/Makefile.in
+++ b/src/libcharon/tests/Makefile.in
@@ -380,6 +380,7 @@ docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
+fuzz_plugins = @fuzz_plugins@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
host = @host@
@@ -402,6 +403,7 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libfuzzer = @libfuzzer@
libiptc_CFLAGS = @libiptc_CFLAGS@
libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
diff --git a/src/libcharon/tests/suites/test_child_rekey.c b/src/libcharon/tests/suites/test_child_rekey.c
index fcac49388..76b23f589 100644
--- a/src/libcharon/tests/suites/test_child_rekey.c
+++ b/src/libcharon/tests/suites/test_child_rekey.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Tobias Brunner
+ * Copyright (C) 2016-2017 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -28,7 +28,23 @@
assert_hook_not_called(child_updown); \
assert_hook_not_called(child_rekey); \
call_ikesa(sa, rekey_child_sa, PROTO_ESP, spi); \
- assert_child_sa_state(sa, spi, CHILD_REKEYING); \
+ assert_child_sa_state(sa, spi, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED); \
+ assert_hook(); \
+ assert_hook(); \
+})
+
+/**
+ * Destroy a rekeyed CHILD_SA that was kept around to accept inbound traffic.
+ * Simulates the job that's scheduled to do this.
+ */
+#define destroy_rekeyed(sa, spi) ({ \
+ assert_hook_not_called(child_updown); \
+ assert_hook_not_called(child_rekey); \
+ assert_no_jobs_scheduled(); \
+ assert_child_sa_state(sa, spi, CHILD_DELETING, CHILD_OUTBOUND_NONE); \
+ call_ikesa(sa, delete_child_sa, PROTO_ESP, spi, FALSE); \
+ assert_child_sa_not_exists(sa, spi); \
+ assert_scheduler(); \
assert_hook(); \
assert_hook(); \
})
@@ -53,6 +69,7 @@ START_TEST(test_regular)
&a, &b, NULL);
}
initiate_rekey(a, spi_a);
+ assert_ipsec_sas_installed(a, spi_a, spi_b);
/* this should never get called as this results in a successful rekeying */
assert_hook_not_called(child_updown);
@@ -61,33 +78,51 @@ START_TEST(test_regular)
assert_hook_called(child_rekey);
assert_notify(IN, REKEY_SA);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, spi_b, CHILD_REKEYED);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
+ assert_child_sa_state(b, spi_b, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(b, spi_a, spi_b, 4);
assert_hook();
/* <-- CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } */
assert_hook_called(child_rekey);
assert_no_notify(IN, REKEY_SA);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, spi_a, CHILD_DELETING);
- assert_child_sa_state(a, 3, CHILD_INSTALLED);
+ assert_child_sa_state(a, spi_a, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, 3, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(a, spi_a, spi_b, 3, 4);
assert_hook();
/* INFORMATIONAL { D } --> */
assert_hook_not_called(child_rekey);
+ assert_jobs_scheduled(1);
assert_single_payload(IN, PLV2_DELETE);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
- assert_child_sa_count(b, 1);
+ assert_child_sa_state(b, spi_b, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 2);
+ assert_ipsec_sas_installed(b, spi_b, 3, 4);
+ assert_scheduler();
assert_hook();
/* <-- INFORMATIONAL { D } */
assert_hook_not_called(child_rekey);
+ assert_jobs_scheduled(1);
assert_single_payload(IN, PLV2_DELETE);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 3, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, spi_a, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, 3, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 2);
+ assert_ipsec_sas_installed(a, spi_a, 3, 4);
+ assert_scheduler();
assert_hook();
+ /* simulate the execution of the scheduled jobs */
+ destroy_rekeyed(a, spi_a);
+ assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, 3, 4);
+ destroy_rekeyed(b, spi_b);
+ assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(a, 3, 4);
+
/* child_updown */
assert_hook();
@@ -125,6 +160,7 @@ START_TEST(test_regular_ke_invalid)
&a, &b, &conf);
}
initiate_rekey(a, spi_a);
+ assert_ipsec_sas_installed(a, spi_a, spi_b);
/* this should never get called as this results in a successful rekeying */
assert_hook_not_called(child_updown);
@@ -135,6 +171,7 @@ START_TEST(test_regular_ke_invalid)
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
assert_child_sa_state(b, spi_b, CHILD_INSTALLED);
assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(b, spi_a, spi_b);
assert_hook();
/* <-- CREATE_CHILD_SA { N(INVAL_KE) } */
@@ -143,6 +180,7 @@ START_TEST(test_regular_ke_invalid)
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
assert_child_sa_state(a, spi_a, CHILD_REKEYING);
assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, spi_a, spi_b);
assert_hook();
/* CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } --> */
@@ -150,7 +188,8 @@ START_TEST(test_regular_ke_invalid)
assert_notify(IN, REKEY_SA);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
assert_child_sa_state(b, spi_b, CHILD_REKEYED);
- assert_child_sa_state(b, 6, CHILD_INSTALLED);
+ assert_child_sa_state(b, 6, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(b, spi_a, spi_b, 6);
assert_hook();
/* <-- CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } */
@@ -158,24 +197,37 @@ START_TEST(test_regular_ke_invalid)
assert_no_notify(IN, REKEY_SA);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
assert_child_sa_state(a, spi_a, CHILD_DELETING);
- assert_child_sa_state(a, 5, CHILD_INSTALLED);
+ assert_child_sa_state(a, 5, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(a, spi_a, spi_b, 5, 6);
assert_hook();
/* INFORMATIONAL { D } --> */
assert_hook_not_called(child_rekey);
assert_single_payload(IN, PLV2_DELETE);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 6, CHILD_INSTALLED);
- assert_child_sa_count(b, 1);
+ assert_child_sa_state(b, spi_b, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, 6, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 2);
+ assert_ipsec_sas_installed(b, spi_b, 5, 6);
assert_hook();
/* <-- INFORMATIONAL { D } */
assert_hook_not_called(child_rekey);
assert_single_payload(IN, PLV2_DELETE);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
+ assert_child_sa_state(a, spi_a, CHILD_DELETING, CHILD_OUTBOUND_NONE);
assert_child_sa_state(a, 5, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_count(a, 2);
+ assert_ipsec_sas_installed(a, spi_a, 5, 6);
assert_hook();
+ /* simulate the execution of the scheduled jobs */
+ destroy_rekeyed(a, spi_a);
+ assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, 5, 6);
+ destroy_rekeyed(b, spi_b);
+ assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(b, 5, 6);
+
/* child_updown */
assert_hook();
@@ -195,6 +247,7 @@ START_TEST(test_regular_responder_ignore_soft_expire)
exchange_test_helper->establish_sa(exchange_test_helper,
&a, &b, NULL);
initiate_rekey(a, 1);
+ assert_ipsec_sas_installed(a, 1, 2);
/* this should never get called as this results in a successful rekeying */
assert_hook_not_called(child_updown);
@@ -204,7 +257,8 @@ START_TEST(test_regular_responder_ignore_soft_expire)
assert_notify(IN, REKEY_SA);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
assert_child_sa_state(b, 2, CHILD_REKEYED);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(b, 1, 2, 4);
assert_hook();
/* <-- CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } */
@@ -212,7 +266,8 @@ START_TEST(test_regular_responder_ignore_soft_expire)
assert_no_notify(IN, REKEY_SA);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
assert_child_sa_state(a, 1, CHILD_DELETING);
- assert_child_sa_state(a, 3, CHILD_INSTALLED);
+ assert_child_sa_state(a, 3, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(a, 1, 2, 3, 4);
assert_hook();
/* we don't expect this to get called anymore */
@@ -223,15 +278,31 @@ START_TEST(test_regular_responder_ignore_soft_expire)
assert_child_sa_state(b, 2, CHILD_REKEYED);
/* INFORMATIONAL { D } --> */
+ assert_jobs_scheduled(1);
assert_single_payload(IN, PLV2_DELETE);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
- assert_child_sa_count(b, 1);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 2);
+ assert_ipsec_sas_installed(b, 2, 3, 4);
+ assert_scheduler();
/* <-- INFORMATIONAL { D } */
+ assert_jobs_scheduled(1);
assert_single_payload(IN, PLV2_DELETE);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
+ assert_child_sa_state(a, 1, CHILD_DELETING, CHILD_OUTBOUND_NONE);
assert_child_sa_state(a, 3, CHILD_INSTALLED);
+ assert_child_sa_count(a, 2);
+ assert_ipsec_sas_installed(a, 1, 3, 4);
+ assert_scheduler();
+
+ /* simulate the execution of the scheduled jobs */
+ destroy_rekeyed(a, 1);
assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, 3, 4);
+ destroy_rekeyed(b, 2);
+ assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(b, 3, 4);
/* child_rekey/child_updown */
assert_hook();
@@ -254,6 +325,7 @@ START_TEST(test_regular_responder_handle_hard_expire)
exchange_test_helper->establish_sa(exchange_test_helper,
&a, &b, NULL);
initiate_rekey(a, 1);
+ assert_ipsec_sas_installed(a, 1, 2);
/* this should never get called as this results in a successful rekeying */
assert_hook_not_called(child_updown);
@@ -263,7 +335,8 @@ START_TEST(test_regular_responder_handle_hard_expire)
assert_notify(IN, REKEY_SA);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
assert_child_sa_state(b, 2, CHILD_REKEYED);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(b, 1, 2, 4);
assert_hook();
/* <-- CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } */
@@ -271,7 +344,8 @@ START_TEST(test_regular_responder_handle_hard_expire)
assert_no_notify(IN, REKEY_SA);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
assert_child_sa_state(a, 1, CHILD_DELETING);
- assert_child_sa_state(a, 3, CHILD_INSTALLED);
+ assert_child_sa_state(a, 3, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(a, 1, 2, 3, 4);
assert_hook();
/* we don't expect this to get called anymore */
@@ -279,28 +353,51 @@ START_TEST(test_regular_responder_handle_hard_expire)
/* this is similar to a regular delete collision */
assert_single_payload(OUT, PLV2_DELETE);
call_ikesa(b, delete_child_sa, PROTO_ESP, 2, TRUE);
- assert_child_sa_state(b, 2, CHILD_DELETING);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ /* since the SAs expired they would not actually be installed in the kernel
+ * anymore and since we have not yet installed a new outbound SA this
+ * will result in dropped packets and possibly acquires */
+ assert_ipsec_sas_installed(b, 1, 2, 4);
/* INFORMATIONAL { D } --> */
assert_single_payload(IN, PLV2_DELETE);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
- assert_child_sa_state(a, 2, CHILD_DELETING);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(b, 1, 2, 4);
/* <-- INFORMATIONAL { D } */
assert_single_payload(IN, PLV2_DELETE);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 3, CHILD_INSTALLED);
- assert_child_sa_state(a, 1, CHILD_DELETING);
+ assert_child_sa_state(a, 1, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, 3, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(a, 1, 2, 3, 4);
/* <-- INFORMATIONAL { } */
+ assert_jobs_scheduled(1);
assert_message_empty(IN);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 3, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, 1, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, 3, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 2);
+ assert_ipsec_sas_installed(a, 1, 3, 4);
+ assert_scheduler();
/* INFORMATIONAL { } --> */
+ assert_jobs_scheduled(1);
assert_message_empty(IN);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 2);
+ assert_ipsec_sas_installed(b, 2, 3, 4);
+ assert_scheduler();
+
+ /* simulate the execution of the scheduled jobs */
+ destroy_rekeyed(a, 1);
+ assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, 3, 4);
+ destroy_rekeyed(b, 2);
assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(b, 3, 4);
/* child_rekey/child_updown */
assert_hook();
@@ -350,8 +447,10 @@ START_TEST(test_collision)
exchange_test_helper->nonce_first_byte = data[_i].nonces[0];
initiate_rekey(a, 1);
+ assert_ipsec_sas_installed(a, 1, 2);
exchange_test_helper->nonce_first_byte = data[_i].nonces[1];
initiate_rekey(b, 2);
+ assert_ipsec_sas_installed(b, 1, 2);
/* this should never get called as this results in a successful rekeying */
assert_hook_not_called(child_updown);
@@ -360,15 +459,17 @@ START_TEST(test_collision)
exchange_test_helper->nonce_first_byte = data[_i].nonces[2];
assert_hook_rekey(child_rekey, 2, 5);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 2, CHILD_REKEYED);
- assert_child_sa_state(b, 5, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 5, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(b, 1, 2, 5);
assert_hook();
/* <-- CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } */
exchange_test_helper->nonce_first_byte = data[_i].nonces[3];
assert_hook_rekey(child_rekey, 1, 6);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 1, CHILD_REKEYED);
- assert_child_sa_state(a, 6, CHILD_INSTALLED);
+ assert_child_sa_state(a, 1, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, 6, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(a, 1, 2, 6);
assert_hook();
/* <-- CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } */
@@ -378,53 +479,113 @@ START_TEST(test_collision)
assert_hook_rekey(child_rekey, 1, data[_i].spi_a);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
assert_hook();
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_REKEYED,
+ CHILD_OUTBOUND_REGISTERED);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
}
else
{
assert_hook_not_called(child_rekey);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
assert_hook();
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_REKEYED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_REGISTERED);
}
- assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING);
- assert_child_sa_state(a, data[_i].spi_del_b, CHILD_REKEYED);
- assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED);
+ assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(a, 1, 2, 3, 5, 6);
/* CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } --> */
if (data[_i].spi_del_b == 2)
{
assert_hook_rekey(child_rekey, 2, data[_i].spi_b);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
assert_hook();
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED,
+ CHILD_OUTBOUND_REGISTERED);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
}
else
{
assert_hook_not_called(child_rekey);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
assert_hook();
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_REGISTERED);
}
- assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING);
- assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED);
- assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(b, 1, 2, 4, 5, 6);
/* we don't expect this hook to get called anymore */
assert_hook_not_called(child_rekey);
/* INFORMATIONAL { D } --> */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING);
- assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED);
- assert_child_sa_count(b, 2);
+ assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 3);
+ assert_ipsec_sas_installed(b, 2, 4, 5, 6,
+ data[_i].spi_del_b == 2 ? 1 : 3);
+ assert_scheduler();
/* <-- INFORMATIONAL { D } */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING);
- assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED);
- assert_child_sa_count(a, 2);
+ assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 3);
+ assert_ipsec_sas_installed(a, 1, 3, 5, 6,
+ data[_i].spi_del_a == 1 ? 2 : 4);
+ assert_scheduler();
/* <-- INFORMATIONAL { D } */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 3);
+ assert_ipsec_sas_installed(a, 1, 3, 6,
+ data[_i].spi_del_a == 1 ? 5 : 4);
+ assert_scheduler();
/* INFORMATIONAL { D } --> */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 3);
+ assert_ipsec_sas_installed(b, 2, 4, 5,
+ data[_i].spi_del_b == 2 ? 6 : 3);
+ assert_scheduler();
+
+ /* simulate the execution of the scheduled jobs */
+ destroy_rekeyed(a, data[_i].spi_del_a);
+ destroy_rekeyed(a, data[_i].spi_del_b);
+ assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, data[_i].spi_a, data[_i].spi_b);
+ destroy_rekeyed(b, data[_i].spi_del_a);
+ destroy_rekeyed(b, data[_i].spi_del_b);
assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(b, data[_i].spi_a, data[_i].spi_b);
/* child_rekey/child_updown */
assert_hook();
@@ -483,8 +644,10 @@ START_TEST(test_collision_delayed_response)
exchange_test_helper->nonce_first_byte = data[_i].nonces[0];
initiate_rekey(a, 1);
+ assert_ipsec_sas_installed(a, 1, 2);
exchange_test_helper->nonce_first_byte = data[_i].nonces[1];
initiate_rekey(b, 2);
+ assert_ipsec_sas_installed(b, 1, 2);
/* this should never get called as this results in a successful rekeying */
assert_hook_not_called(child_updown);
@@ -493,15 +656,17 @@ START_TEST(test_collision_delayed_response)
exchange_test_helper->nonce_first_byte = data[_i].nonces[2];
assert_hook_rekey(child_rekey, 2, 5);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 2, CHILD_REKEYED);
- assert_child_sa_state(b, 5, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 5, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(b, 1, 2, 5);
assert_hook();
/* <-- CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } */
exchange_test_helper->nonce_first_byte = data[_i].nonces[3];
assert_hook_rekey(child_rekey, 1, 6);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 1, CHILD_REKEYED);
- assert_child_sa_state(a, 6, CHILD_INSTALLED);
+ assert_child_sa_state(a, 1, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, 6, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(a, 1, 2, 6);
assert_hook();
/* delay the CREATE_CHILD_SA response from b to a */
@@ -513,35 +678,68 @@ START_TEST(test_collision_delayed_response)
assert_hook_rekey(child_rekey, 2, data[_i].spi_b);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
assert_hook();
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED,
+ CHILD_OUTBOUND_REGISTERED);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
}
else
{
assert_hook_not_called(child_rekey);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
assert_hook();
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_REGISTERED);
}
- assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING);
- assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED);
- assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(b, 1, 2, 4, 5, 6);
/* <-- INFORMATIONAL { D } */
assert_hook_not_called(child_rekey);
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
if (data[_i].spi_del_b == 2)
{
- assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, 1, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(a, 1, 4, 6);
}
else
{
- assert_child_sa_state(a, 1, CHILD_REKEYED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, 1, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_ipsec_sas_installed(a, 1, 2, 6);
}
+ assert_child_sa_count(a, 2);
+ assert_scheduler();
/* INFORMATIONAL { D } --> */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED);
- assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED);
- assert_child_sa_count(b, 2);
+ if (data[_i].spi_del_b == 2)
+ {
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED,
+ CHILD_OUTBOUND_REGISTERED);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(b, 2, 4, 5, 6);
+ }
+ else
+ {
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(b, 1, 2, 4, 5);
+ }
+ assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_count(b, 3);
+ assert_scheduler();
assert_hook();
/* <-- CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } (delayed) */
@@ -557,20 +755,54 @@ START_TEST(test_collision_delayed_response)
exchange_test_helper->process_message(exchange_test_helper, a, msg);
assert_hook();
}
- assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING);
- assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED);
- assert_child_sa_count(a, 2);
+ assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(a, 1, 3, 5, 6,
+ data[_i].spi_del_a == 1 ? 2 : 4);
+ assert_child_sa_count(a, 3);
/* we don't expect this hook to get called anymore */
assert_hook_not_called(child_rekey);
/* INFORMATIONAL { D } --> */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED);
- assert_child_sa_count(b, 1);
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(b, 2, 4, 5,
+ data[_i].spi_del_b == 2 ? 6 : 3);
+ assert_child_sa_count(b, 3);
+ assert_scheduler();
/* <-- INFORMATIONAL { D } */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED);
+ assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 3);
+ assert_ipsec_sas_installed(a, 1, 3, 6,
+ data[_i].spi_del_a == 1 ? 5 : 4);
+ assert_scheduler();
+
+ /* simulate the execution of the scheduled jobs */
+ destroy_rekeyed(a, data[_i].spi_del_a);
+ destroy_rekeyed(a, data[_i].spi_del_b);
assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, data[_i].spi_a, data[_i].spi_b);
+ destroy_rekeyed(b, data[_i].spi_del_a);
+ destroy_rekeyed(b, data[_i].spi_del_b);
+ assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(b, data[_i].spi_a, data[_i].spi_b);
/* child_rekey/child_updown */
assert_hook();
@@ -621,8 +853,10 @@ START_TEST(test_collision_delayed_request)
exchange_test_helper->nonce_first_byte = data[_i].nonces[0];
initiate_rekey(a, 1);
+ assert_ipsec_sas_installed(a, 1, 2);
exchange_test_helper->nonce_first_byte = data[_i].nonces[1];
initiate_rekey(b, 2);
+ assert_ipsec_sas_installed(b, 1, 2);
/* delay the CREATE_CHILD_SA request from a to b */
msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
@@ -634,14 +868,16 @@ START_TEST(test_collision_delayed_request)
exchange_test_helper->nonce_first_byte = data[_i].nonces[2];
assert_hook_rekey(child_rekey, 1, 5);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 1, CHILD_REKEYED);
- assert_child_sa_state(a, 5, CHILD_INSTALLED);
+ assert_child_sa_state(a, 1, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, 5, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(a, 1, 2, 5);
assert_hook();
/* CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } --> */
assert_hook_rekey(child_rekey, 2, 4);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 2, CHILD_DELETING);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(b, 1, 2, 4, 5);
assert_hook();
/* we don't expect this hook to get called anymore */
@@ -650,25 +886,43 @@ START_TEST(test_collision_delayed_request)
/* CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } --> (delayed) */
assert_single_notify(OUT, TEMPORARY_FAILURE);
exchange_test_helper->process_message(exchange_test_helper, b, msg);
- assert_child_sa_state(b, 2, CHILD_DELETING);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
/* <-- INFORMATIONAL { D } */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 5, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, 1, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, 5, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 2);
+ assert_ipsec_sas_installed(a, 1, 4, 5);
+ assert_scheduler();
/* <-- CREATE_CHILD_SA { N(TEMP_FAIL) } */
assert_no_jobs_scheduled();
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 5, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, 1, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, 5, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 2);
+ assert_ipsec_sas_installed(a, 1, 4, 5);
assert_scheduler();
/* INFORMATIONAL { D } --> */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 2);
+ assert_ipsec_sas_installed(b, 2, 4, 5);
+ assert_scheduler();
+
+ /* simulate the execution of the scheduled jobs */
+ destroy_rekeyed(a, 1);
+ assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, 4, 5);
+ destroy_rekeyed(b, 2);
assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(b, 4, 5);
/* child_rekey/child_updown */
assert_hook();
@@ -722,8 +976,10 @@ START_TEST(test_collision_delayed_request_more)
exchange_test_helper->nonce_first_byte = data[_i].nonces[0];
initiate_rekey(a, 1);
+ assert_ipsec_sas_installed(a, 1, 2);
exchange_test_helper->nonce_first_byte = data[_i].nonces[1];
initiate_rekey(b, 2);
+ assert_ipsec_sas_installed(b, 1, 2);
/* delay the CREATE_CHILD_SA request from a to b */
msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
@@ -735,40 +991,62 @@ START_TEST(test_collision_delayed_request_more)
exchange_test_helper->nonce_first_byte = data[_i].nonces[2];
assert_hook_rekey(child_rekey, 1, 5);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 1, CHILD_REKEYED);
- assert_child_sa_state(a, 5, CHILD_INSTALLED);
+ assert_child_sa_state(a, 1, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, 5, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
+ assert_ipsec_sas_installed(a, 1, 2, 5);
assert_hook();
/* CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } --> */
assert_hook_rekey(child_rekey, 2, 4);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 2, CHILD_DELETING);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_ipsec_sas_installed(b, 1, 2, 4, 5);
assert_hook();
/* we don't expect this hook to get called anymore */
assert_hook_not_called(child_rekey);
/* <-- INFORMATIONAL { D } */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 5, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, 1, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, 5, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 2);
+ assert_ipsec_sas_installed(a, 1, 4, 5);
+ assert_scheduler();
/* INFORMATIONAL { D } --> */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
- assert_child_sa_count(b, 1);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 2);
+ assert_ipsec_sas_installed(b, 2, 4, 5);
+ assert_scheduler();
/* CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } --> */
assert_single_notify(OUT, CHILD_SA_NOT_FOUND);
exchange_test_helper->process_message(exchange_test_helper, b, msg);
- assert_child_sa_state(b, 4, CHILD_INSTALLED);
- assert_child_sa_count(b, 1);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, 4, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 2);
+ assert_ipsec_sas_installed(b, 2, 4, 5);
/* <-- CREATE_CHILD_SA { N(NO_CHILD_SA) } */
assert_no_jobs_scheduled();
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 5, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, 1, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, 5, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 2);
+ assert_ipsec_sas_installed(a, 1, 4, 5);
assert_scheduler();
+ /* simulate the execution of the scheduled jobs */
+ destroy_rekeyed(a, 1);
+ assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, 4, 5);
+ destroy_rekeyed(b, 2);
+ assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(b, 4, 5);
+
/* child_rekey/child_updown */
assert_hook();
assert_hook();
@@ -842,13 +1120,13 @@ START_TEST(test_collision_ke_invalid)
/* CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } --> */
assert_hook_not_called(child_rekey);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 2, CHILD_REKEYING);
+ assert_child_sa_state(b, 2, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED);
assert_child_sa_count(b, 1);
assert_hook();
/* <-- CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } */
assert_hook_not_called(child_rekey);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 1, CHILD_REKEYING);
+ assert_child_sa_state(a, 1, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED);
assert_child_sa_count(a, 1);
assert_hook();
@@ -857,7 +1135,7 @@ START_TEST(test_collision_ke_invalid)
assert_hook_not_called(child_rekey);
assert_single_notify(IN, INVALID_KE_PAYLOAD);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 1, CHILD_REKEYING);
+ assert_child_sa_state(a, 1, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED);
assert_child_sa_count(a, 1);
assert_hook();
/* CREATE_CHILD_SA { N(INVAL_KE) } --> */
@@ -865,7 +1143,7 @@ START_TEST(test_collision_ke_invalid)
assert_hook_not_called(child_rekey);
assert_single_notify(IN, INVALID_KE_PAYLOAD);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 2, CHILD_REKEYING);
+ assert_child_sa_state(b, 2, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED);
assert_child_sa_count(b, 1);
assert_hook();
@@ -873,15 +1151,15 @@ START_TEST(test_collision_ke_invalid)
exchange_test_helper->nonce_first_byte = data[_i].nonces[2];
assert_hook_rekey(child_rekey, 2, 9);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 2, CHILD_REKEYED);
- assert_child_sa_state(b, 9, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 9, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
assert_hook();
/* <-- CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } */
exchange_test_helper->nonce_first_byte = data[_i].nonces[3];
assert_hook_rekey(child_rekey, 1, 10);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 1, CHILD_REKEYED);
- assert_child_sa_state(a,10, CHILD_INSTALLED);
+ assert_child_sa_state(a, 1, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a,10, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
assert_hook();
/* <-- CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } */
@@ -891,49 +1169,99 @@ START_TEST(test_collision_ke_invalid)
assert_hook_rekey(child_rekey, 1, data[_i].spi_a);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
assert_hook();
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_REKEYED,
+ CHILD_OUTBOUND_REGISTERED);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
}
else
{
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_REKEYED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_REGISTERED);
}
- assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING);
- assert_child_sa_state(a, data[_i].spi_del_b, CHILD_REKEYED);
- assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED);
+ assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_INSTALLED);
/* CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } --> */
if (data[_i].spi_del_b == 2)
{
assert_hook_rekey(child_rekey, 2, data[_i].spi_b);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
assert_hook();
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED,
+ CHILD_OUTBOUND_REGISTERED);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
}
else
{
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_REGISTERED);
}
- assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING);
- assert_child_sa_state(b, data[_i].spi_del_a, CHILD_REKEYED);
- assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_INSTALLED);
/* we don't expect this hook to get called anymore */
assert_hook_not_called(child_rekey);
/* INFORMATIONAL { D } --> */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING);
- assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED);
- assert_child_sa_count(b, 2);
+ assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 3);
+ assert_scheduler();
/* <-- INFORMATIONAL { D } */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING);
- assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED);
- assert_child_sa_count(a, 2);
+ assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 3);
+ assert_scheduler();
/* <-- INFORMATIONAL { D } */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 3);
+ assert_scheduler();
/* INFORMATIONAL { D } --> */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED);
+ assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, data[_i].spi_del_a, CHILD_DELETING,
+ CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
+ CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 3);
+ assert_scheduler();
+
+ /* simulate the execution of the scheduled jobs */
+ destroy_rekeyed(a, data[_i].spi_del_a);
+ destroy_rekeyed(a, data[_i].spi_del_b);
+ assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, data[_i].spi_a, data[_i].spi_b);
+ destroy_rekeyed(b, data[_i].spi_del_a);
+ destroy_rekeyed(b, data[_i].spi_del_b);
assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(b, data[_i].spi_a, data[_i].spi_b);
/* child_rekey/child_updown */
assert_hook();
@@ -1004,13 +1332,13 @@ START_TEST(test_collision_ke_invalid_delayed_retry)
/* CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } --> */
assert_hook_not_called(child_rekey);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 2, CHILD_REKEYING);
+ assert_child_sa_state(b, 2, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED);
assert_child_sa_count(b, 1);
assert_hook();
/* <-- CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } */
assert_hook_not_called(child_rekey);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 1, CHILD_REKEYING);
+ assert_child_sa_state(a, 1, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED);
assert_child_sa_count(a, 1);
assert_hook();
@@ -1019,7 +1347,7 @@ START_TEST(test_collision_ke_invalid_delayed_retry)
assert_hook_not_called(child_rekey);
assert_single_notify(IN, INVALID_KE_PAYLOAD);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 1, CHILD_REKEYING);
+ assert_child_sa_state(a, 1, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED);
assert_child_sa_count(a, 1);
assert_hook();
/* CREATE_CHILD_SA { N(INVAL_KE) } --> */
@@ -1027,7 +1355,7 @@ START_TEST(test_collision_ke_invalid_delayed_retry)
assert_hook_not_called(child_rekey);
assert_single_notify(IN, INVALID_KE_PAYLOAD);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 2, CHILD_REKEYING);
+ assert_child_sa_state(b, 2, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED);
assert_child_sa_count(b, 1);
assert_hook();
@@ -1038,14 +1366,14 @@ START_TEST(test_collision_ke_invalid_delayed_retry)
exchange_test_helper->nonce_first_byte = data[_i].nonces[2];
assert_hook_rekey(child_rekey, 1, 9);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 1, CHILD_REKEYED);
- assert_child_sa_state(a, 9, CHILD_INSTALLED);
+ assert_child_sa_state(a, 1, CHILD_REKEYED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(a, 9, CHILD_INSTALLED, CHILD_OUTBOUND_REGISTERED);
assert_hook();
/* CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } --> */
assert_hook_rekey(child_rekey, 2, 8);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 2, CHILD_DELETING);
- assert_child_sa_state(b, 8, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 8, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
assert_hook();
/* we don't expect this hook to get called anymore */
@@ -1054,25 +1382,40 @@ START_TEST(test_collision_ke_invalid_delayed_retry)
/* CREATE_CHILD_SA { N(REKEY_SA), SA, Ni, [KEi,] TSi, TSr } --> (delayed) */
assert_single_notify(OUT, TEMPORARY_FAILURE);
exchange_test_helper->process_message(exchange_test_helper, b, msg);
- assert_child_sa_state(b, 2, CHILD_DELETING);
- assert_child_sa_state(b, 8, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_state(b, 8, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
/* <-- INFORMATIONAL { D } */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 9, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, 1, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, 9, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 2);
+ assert_scheduler();
/* <-- CREATE_CHILD_SA { N(TEMP_FAIL) } */
assert_no_jobs_scheduled();
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, 9, CHILD_INSTALLED);
- assert_child_sa_count(a, 1);
+ assert_child_sa_state(a, 1, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(a, 9, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(a, 2);
assert_scheduler();
/* INFORMATIONAL { D } --> */
+ assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, 8, CHILD_INSTALLED);
+ assert_child_sa_state(b, 2, CHILD_DELETING, CHILD_OUTBOUND_NONE);
+ assert_child_sa_state(b, 8, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
+ assert_child_sa_count(b, 2);
+ assert_scheduler();
+
+ /* simulate the execution of the scheduled jobs */
+ destroy_rekeyed(a, 1);
+ assert_child_sa_count(a, 1);
+ assert_ipsec_sas_installed(a, 8, 9);
+ destroy_rekeyed(b, 2);
assert_child_sa_count(b, 1);
+ assert_ipsec_sas_installed(b, 8, 9);
/* child_rekey/child_updown */
assert_hook();
@@ -1114,7 +1457,7 @@ START_TEST(test_collision_delete)
}
initiate_rekey(a, spi_a);
call_ikesa(b, delete_child_sa, PROTO_ESP, spi_b, FALSE);
- assert_child_sa_state(b, spi_b, CHILD_DELETING);
+ assert_child_sa_state(b, spi_b, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
/* this should never get called as there is no successful rekeying on
* either side */
@@ -1129,7 +1472,7 @@ START_TEST(test_collision_delete)
assert_notify(IN, REKEY_SA);
assert_single_notify(OUT, TEMPORARY_FAILURE);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, spi_b, CHILD_DELETING);
+ assert_child_sa_state(b, spi_b, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
assert_hook();
/* RFC 7296, 2.25.1: If a peer receives a request to delete a CHILD_SA that
@@ -1201,7 +1544,7 @@ START_TEST(test_collision_delete_drop_delete)
}
initiate_rekey(a, spi_a);
call_ikesa(b, delete_child_sa, PROTO_ESP, spi_b, FALSE);
- assert_child_sa_state(b, spi_b, CHILD_DELETING);
+ assert_child_sa_state(b, spi_b, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
/* this should never get called as there is no successful rekeying on
* either side */
@@ -1216,7 +1559,7 @@ START_TEST(test_collision_delete_drop_delete)
assert_notify(IN, REKEY_SA);
assert_single_notify(OUT, TEMPORARY_FAILURE);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
- assert_child_sa_state(b, spi_b, CHILD_DELETING);
+ assert_child_sa_state(b, spi_b, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
assert_hook();
/* delay the DELETE request */
@@ -1227,7 +1570,7 @@ START_TEST(test_collision_delete_drop_delete)
/* we expect a job to retry the rekeying is scheduled */
assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, spi_a, CHILD_INSTALLED);
+ assert_child_sa_state(a, spi_a, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
assert_scheduler();
assert_hook();
@@ -1286,7 +1629,7 @@ END_TEST
}
initiate_rekey(a, spi_a);
call_ikesa(b, delete_child_sa, PROTO_ESP, spi_b, FALSE);
- assert_child_sa_state(b, spi_b, CHILD_DELETING);
+ assert_child_sa_state(b, spi_b, CHILD_DELETING, CHILD_OUTBOUND_INSTALLED);
/* this should never get called as there is no successful rekeying on
* either side */
@@ -1419,13 +1762,13 @@ START_TEST(test_collision_ike_rekey)
/* <-- CREATE_CHILD_SA { SA, Ni, KEi } */
assert_single_notify(OUT, TEMPORARY_FAILURE);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, spi_a, CHILD_REKEYING);
+ assert_child_sa_state(a, spi_a, CHILD_REKEYING, CHILD_OUTBOUND_INSTALLED);
/* <-- CREATE_CHILD_SA { N(TEMP_FAIL) } */
/* we expect a job to retry the rekeying is scheduled */
assert_jobs_scheduled(1);
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
- assert_child_sa_state(a, spi_a, CHILD_INSTALLED);
+ assert_child_sa_state(a, spi_a, CHILD_INSTALLED, CHILD_OUTBOUND_INSTALLED);
assert_scheduler();
/* CREATE_CHILD_SA { N(TEMP_FAIL) } --> */
diff --git a/src/libcharon/tests/utils/exchange_test_asserts.c b/src/libcharon/tests/utils/exchange_test_asserts.c
index 2602b97b7..8042d0b63 100644
--- a/src/libcharon/tests/utils/exchange_test_asserts.c
+++ b/src/libcharon/tests/utils/exchange_test_asserts.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Tobias Brunner
+ * Copyright (C) 2016-2017 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -18,6 +18,7 @@
#include <test_suite.h>
#include "exchange_test_asserts.h"
+#include "mock_ipsec.h"
/*
* Described in header
@@ -180,3 +181,57 @@ bool exchange_test_asserts_message(listener_t *listener, ike_sa_t *ike_sa,
}
return TRUE;
}
+
+/**
+ * Compare two SPIs
+ */
+static int spis_cmp(const void *a, const void *b)
+{
+ return *(const uint32_t*)a - *(const uint32_t*)b;
+}
+
+/**
+ * Compare two SPIs to sort them
+ */
+static int spis_sort(const void *a, const void *b, void *data)
+{
+ return spis_cmp(a, b);
+}
+
+
+/*
+ * Described in header
+ */
+void exchange_test_asserts_ipsec_sas(ipsec_sas_assert_t *sas)
+{
+ enumerator_t *enumerator;
+ array_t *spis;
+ ike_sa_t *ike_sa;
+ uint32_t spi;
+ int i;
+
+ spis = array_create(sizeof(uint32_t), 0);
+ for (i = 0; i < sas->count; i++)
+ {
+ array_insert(spis, ARRAY_TAIL, &sas->spis[i]);
+ }
+ array_sort(spis, spis_sort, NULL);
+
+ enumerator = mock_ipsec_create_sa_enumerator();
+ while (enumerator->enumerate(enumerator, &ike_sa, &spi))
+ {
+ if (ike_sa == sas->ike_sa)
+ {
+ i = array_bsearch(spis, &spi, spis_cmp, NULL);
+ assert_listener_msg(i != -1, sas, "unexpected IPsec SA %.8x", spi);
+ array_remove(spis, i, NULL);
+ }
+ }
+ enumerator->destroy(enumerator);
+ for (i = 0; i < array_count(spis); i++)
+ {
+ array_get(spis, i, &spi);
+ assert_listener_msg(!spi, sas, "expected IPsec SA %.8x not found", spi);
+ }
+ array_destroy(spis);
+}
diff --git a/src/libcharon/tests/utils/exchange_test_asserts.h b/src/libcharon/tests/utils/exchange_test_asserts.h
index 32afcc2e4..4d363edfd 100644
--- a/src/libcharon/tests/utils/exchange_test_asserts.h
+++ b/src/libcharon/tests/utils/exchange_test_asserts.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Tobias Brunner
+ * Copyright (C) 2016-2017 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -14,7 +14,7 @@
*/
/**
- * Special assertions using listener_t.
+ * Special assertions using listener_t etc.
*
* @defgroup exchange_test_asserts exchange_test_asserts
* @{ @ingroup test_utils_c
@@ -28,6 +28,7 @@
typedef struct listener_hook_assert_t listener_hook_assert_t;
typedef struct listener_message_assert_t listener_message_assert_t;
typedef struct listener_message_rule_t listener_message_rule_t;
+typedef struct ipsec_sas_assert_t ipsec_sas_assert_t;
struct listener_hook_assert_t {
@@ -340,4 +341,60 @@ bool exchange_test_asserts_message(listener_t *this, ike_sa_t *ike_sa,
exchange_test_helper->add_listener(exchange_test_helper, &_listener.listener); \
})
+/**
+ * Data used to check IPsec SAs
+ */
+struct ipsec_sas_assert_t {
+
+ /**
+ * Original source file
+ */
+ const char *file;
+
+ /**
+ * Source line
+ */
+ int line;
+
+ /**
+ * IKE_SA that installed the IPsec SAs
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * SPIs to check
+ */
+ uint32_t *spis;
+
+ /**
+ * Number of SPIs for IPsec SAs to check
+ */
+ int count;
+};
+
+/**
+ * Assert that all given IPsec SAs (and only these) are installed for the given
+ * IKE_SA.
+ */
+void exchange_test_asserts_ipsec_sas(ipsec_sas_assert_t *sas);
+
+/**
+ * Assert that the IPsec SAs with the given SPIs (and none other) are currently
+ * installed by the given IKE_SA.
+ *
+ * @param sa IKE_SA
+ * @param ... list of SPIs
+ */
+#define assert_ipsec_sas_installed(sa, ...) ({ \
+ uint32_t _spis[] = { __VA_ARGS__ }; \
+ ipsec_sas_assert_t _sas_assert = { \
+ .file = __FILE__, \
+ .line = __LINE__, \
+ .ike_sa = sa, \
+ .spis = _spis, \
+ .count = countof(_spis), \
+ }; \
+ exchange_test_asserts_ipsec_sas(&_sas_assert); \
+})
+
#endif /** EXCHANGE_TEST_ASSERTS_H_ @}*/
diff --git a/src/libcharon/tests/utils/mock_ipsec.c b/src/libcharon/tests/utils/mock_ipsec.c
index d57a26a87..d6172f5bd 100644
--- a/src/libcharon/tests/utils/mock_ipsec.c
+++ b/src/libcharon/tests/utils/mock_ipsec.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Tobias Brunner
+ * Copyright (C) 2016-2017 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* HSR Hochschule fuer Technik Rapperswil
*
@@ -16,6 +16,12 @@
#include "mock_ipsec.h"
+#include <daemon.h>
+#include <collections/hashtable.h>
+#include <collections/array.h>
+
+#include <assert.h>
+
typedef struct private_kernel_ipsec_t private_kernel_ipsec_t;
/**
@@ -29,16 +35,80 @@ struct private_kernel_ipsec_t {
kernel_ipsec_t public;
/**
+ * Rekey listener
+ */
+ listener_t listener;
+
+ /**
* Allocated SPI
*/
refcount_t spi;
+
+ /**
+ * Installed SAs
+ */
+ hashtable_t *sas;
};
+/**
+ * Global instance
+ */
+static private_kernel_ipsec_t *instance;
+
+/**
+ * Data about installed IPsec SAs
+ */
+typedef struct {
+ /**
+ * SPI of the SA
+ */
+ uint32_t spi;
+
+ /**
+ * Associated IKE_SA
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * TRUE if this was an allocated SPI
+ */
+ bool alloc;
+
+} entry_t;
+
+/**
+ * Hash an IPsec SA entry
+ */
+static u_int entry_hash(const void *key)
+{
+ entry_t *entry = (entry_t*)key;
+ return chunk_hash_inc(chunk_from_thing(entry->spi),
+ chunk_hash(chunk_from_thing(entry->ike_sa)));
+}
+
+/**
+ * Compare an IPsec SA entry
+ */
+static bool entry_equals(const void *key, const void *other_key)
+{
+ entry_t *a = (entry_t*)key, *b = (entry_t*)other_key;
+ return a->spi == b->spi && a->ike_sa == b->ike_sa;
+}
+
METHOD(kernel_ipsec_t, get_spi, status_t,
private_kernel_ipsec_t *this, host_t *src, host_t *dst, uint8_t protocol,
uint32_t *spi)
{
+ entry_t *entry;
+
*spi = (uint32_t)ref_get(&this->spi);
+ INIT(entry,
+ .spi = *spi,
+ .ike_sa = charon->bus->get_sa(charon->bus),
+ .alloc = TRUE,
+ );
+ entry = this->sas->put(this->sas, entry, entry);
+ assert(!entry);
return SUCCESS;
}
@@ -52,6 +122,23 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
private_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
kernel_ipsec_add_sa_t *data)
{
+ entry_t *entry;
+
+ INIT(entry,
+ .spi = id->spi,
+ .ike_sa = charon->bus->get_sa(charon->bus),
+ );
+ if (data->inbound)
+ {
+ entry = this->sas->put(this->sas, entry, entry);
+ assert(entry && entry->alloc);
+ free(entry);
+ }
+ else
+ {
+ entry = this->sas->put(this->sas, entry, entry);
+ assert(!entry);
+ }
return SUCCESS;
}
@@ -74,9 +161,47 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
private_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
kernel_ipsec_del_sa_t *data)
{
+ entry_t *entry, lookup = {
+ .spi = id->spi,
+ .ike_sa = charon->bus->get_sa(charon->bus),
+ };
+
+ entry = this->sas->remove(this->sas, &lookup);
+ assert(entry);
+ free(entry);
return SUCCESS;
}
+METHOD(listener_t, ike_rekey, bool,
+ listener_t *listener, ike_sa_t *old, ike_sa_t *new)
+{
+ enumerator_t *enumerator;
+ array_t *sas = NULL;
+ entry_t *entry;
+
+ enumerator = instance->sas->create_enumerator(instance->sas);
+ while (enumerator->enumerate(enumerator, &entry, NULL))
+ {
+ if (entry->ike_sa == old)
+ {
+ instance->sas->remove_at(instance->sas, enumerator);
+ array_insert_create(&sas, ARRAY_TAIL, entry);
+ }
+ }
+ enumerator->destroy(enumerator);
+ enumerator = array_create_enumerator(sas);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ array_remove_at(sas, enumerator);
+ entry->ike_sa = new;
+ entry = instance->sas->put(instance->sas, entry, entry);
+ assert(!entry);
+ }
+ enumerator->destroy(enumerator);
+ array_destroy(sas);
+ return TRUE;
+}
+
METHOD(kernel_ipsec_t, add_policy, status_t,
private_kernel_ipsec_t *this, kernel_ipsec_policy_id_t *id,
kernel_ipsec_manage_policy_t *data)
@@ -99,6 +224,14 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
return SUCCESS;
}
+METHOD(kernel_ipsec_t, destroy, void,
+ private_kernel_ipsec_t *this)
+{
+ charon->bus->remove_listener(charon->bus, &this->listener);
+ this->sas->destroy(this->sas);
+ free(this);
+}
+
/*
* Described in header
*/
@@ -121,8 +254,50 @@ kernel_ipsec_t *mock_ipsec_create()
.flush_policies = (void*)return_failed,
.bypass_socket = (void*)return_true,
.enable_udp_decap = (void*)return_true,
- .destroy = (void*)free,
+ .destroy = _destroy,
+ },
+ .listener = {
+ .ike_rekey = _ike_rekey,
},
+ .sas = hashtable_create(entry_hash, entry_equals, 8),
);
+
+ instance = this;
+
+ charon->bus->add_listener(charon->bus, &this->listener);
+
return &this->public;
}
+
+
+CALLBACK(filter_sas, bool,
+ void *data, enumerator_t *orig, va_list args)
+{
+ entry_t *entry;
+ ike_sa_t **ike_sa;
+ uint32_t *spi;
+
+ VA_ARGS_VGET(args, ike_sa, spi);
+
+ while (orig->enumerate(orig, &entry, NULL))
+ {
+ if (entry->alloc)
+ {
+ continue;
+ }
+ *ike_sa = entry->ike_sa;
+ *spi = entry->spi;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Described in header
+ */
+enumerator_t *mock_ipsec_create_sa_enumerator()
+{
+ return enumerator_create_filter(
+ instance->sas->create_enumerator(instance->sas),
+ filter_sas, NULL, NULL);
+}
diff --git a/src/libcharon/tests/utils/mock_ipsec.h b/src/libcharon/tests/utils/mock_ipsec.h
index cbf21524a..95038a561 100644
--- a/src/libcharon/tests/utils/mock_ipsec.h
+++ b/src/libcharon/tests/utils/mock_ipsec.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Tobias Brunner
+ * Copyright (C) 2016-2017 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -15,7 +15,7 @@
/**
* kernel_ipsec_t implementation used for exchange unit tests. Currently
- * returns sequential SPIs, all other methods are noops.
+ * returns sequential SPIs, and keeps track of installed SAs.
*
* @defgroup mock_ipsec mock_ipsec
* @{ @ingroup test_utils_c
@@ -33,4 +33,11 @@
*/
kernel_ipsec_t *mock_ipsec_create();
+/**
+ * Enumerate the installed SAs
+ *
+ * @return enumerator over (ike_sa_t*, uint32_t)
+ */
+enumerator_t *mock_ipsec_create_sa_enumerator();
+
#endif /** MOCK_IPSEC_H_ @}*/
diff --git a/src/libcharon/tests/utils/sa_asserts.h b/src/libcharon/tests/utils/sa_asserts.h
index 7afa3b55b..d23f724f1 100644
--- a/src/libcharon/tests/utils/sa_asserts.h
+++ b/src/libcharon/tests/utils/sa_asserts.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Tobias Brunner
+ * Copyright (C) 2016-2017 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -82,13 +82,38 @@
})
/**
+ * Check if the CHILD_SA with the given SPI is in the expected state, optionally
+ * check the state of the outbound SA.
+ */
+#define assert_child_sa_state(...) VA_ARGS_DISPATCH(assert_child_sa_state, __VA_ARGS__)(__VA_ARGS__)
+
+/**
* Check if the CHILD_SA with the given SPI is in the expected state.
*/
-#define assert_child_sa_state(ike_sa, spi, state) \
+#define assert_child_sa_state3(ike_sa, spi, state) \
+({ \
+ typeof(ike_sa) _sa = ike_sa; \
+ typeof(spi) _spi = spi; \
+ typeof(state) _state = state; \
+ child_sa_t *_child = _sa->get_child_sa(_sa, PROTO_ESP, _spi, TRUE) ?: \
+ _sa->get_child_sa(_sa, PROTO_ESP, _spi, FALSE); \
+ test_assert_msg(_child, "CHILD_SA with SPI %.8x does not exist", \
+ ntohl(_spi)); \
+ test_assert_msg(_state == _child->get_state(_child), "%N != %N", \
+ child_sa_state_names, _state, \
+ child_sa_state_names, _child->get_state(_child)); \
+})
+
+/**
+ * Check if the outbound SA of a CHILD_SA with the given SPI is in the
+ * expected state.
+ */
+#define assert_child_sa_state4(ike_sa, spi, state, outbound) \
({ \
typeof(ike_sa) _sa = ike_sa; \
typeof(spi) _spi = spi; \
typeof(state) _state = state; \
+ typeof(outbound) _outbound = outbound; \
child_sa_t *_child = _sa->get_child_sa(_sa, PROTO_ESP, _spi, TRUE) ?: \
_sa->get_child_sa(_sa, PROTO_ESP, _spi, FALSE); \
test_assert_msg(_child, "CHILD_SA with SPI %.8x does not exist", \
@@ -96,6 +121,9 @@
test_assert_msg(_state == _child->get_state(_child), "%N != %N", \
child_sa_state_names, _state, \
child_sa_state_names, _child->get_state(_child)); \
+ test_assert_msg(_outbound == _child->get_outbound_state(_child), "%N != %N", \
+ child_sa_outbound_state_names, _outbound, \
+ child_sa_outbound_state_names, _child->get_outbound_state(_child)); \
})
/**