aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2015-08-21 18:21:24 +0200
committerTobias Brunner <tobias@strongswan.org>2015-08-21 18:21:24 +0200
commitd88cec920c9def7ed2d9906858f4b88a4b46a730 (patch)
treecc5798460efe4618077e8b17694ed6340071b6d4 /src
parentffa20bad6356732e840aaffc6f9ef8fd1e6eb88e (diff)
parent256e666d2235718a3711cf7ad9634354c10f7a7e (diff)
downloadstrongswan-d88cec920c9def7ed2d9906858f4b88a4b46a730.tar.bz2
strongswan-d88cec920c9def7ed2d9906858f4b88a4b46a730.tar.xz
Merge branch 'init-limits'
IKE_SAs that are initiated are now counted towards the half-open IKE_SAs limit. Optionally it is possible to enforce limits towards the number of half-open IKE_SAs and the job load also when initiating SAs. This is currently only possible via VICI.
Diffstat (limited to 'src')
-rw-r--r--src/charon-cmd/cmd/cmd_connection.c2
-rw-r--r--src/conftest/actions.c2
-rw-r--r--src/frontends/osx/charon-xpc/xpc_dispatch.c2
-rw-r--r--src/libcharon/control/controller.c54
-rw-r--r--src/libcharon/control/controller.h5
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_control.c2
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_plugin.c2
-rw-r--r--src/libcharon/plugins/medcli/medcli_config.c2
-rw-r--r--src/libcharon/plugins/smp/smp.c2
-rw-r--r--src/libcharon/plugins/stroke/stroke_control.c4
-rw-r--r--src/libcharon/plugins/uci/uci_control.c2
-rw-r--r--src/libcharon/plugins/vici/README.md1
-rw-r--r--src/libcharon/plugins/vici/suites/test_message.c31
-rw-r--r--src/libcharon/plugins/vici/vici_config.c2
-rw-r--r--src/libcharon/plugins/vici/vici_control.c9
-rw-r--r--src/libcharon/plugins/vici/vici_message.c40
-rw-r--r--src/libcharon/plugins/vici/vici_message.h23
-rw-r--r--src/libcharon/processing/jobs/initiate_mediation_job.c4
-rw-r--r--src/libcharon/processing/jobs/start_action_job.c2
-rw-r--r--src/libcharon/sa/ike_sa_manager.c1
20 files changed, 171 insertions, 21 deletions
diff --git a/src/charon-cmd/cmd/cmd_connection.c b/src/charon-cmd/cmd/cmd_connection.c
index 2c0b7b9d5..0c6a504e9 100644
--- a/src/charon-cmd/cmd/cmd_connection.c
+++ b/src/charon-cmd/cmd/cmd_connection.c
@@ -434,7 +434,7 @@ static job_requeue_t initiate(private_cmd_connection_t *this)
child_cfg = create_child_cfg(this, peer_cfg);
if (charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
- controller_cb_empty, NULL, 0) != SUCCESS)
+ controller_cb_empty, NULL, 0, FALSE) != SUCCESS)
{
terminate(pid);
}
diff --git a/src/conftest/actions.c b/src/conftest/actions.c
index 474672ca1..256b63d1b 100644
--- a/src/conftest/actions.c
+++ b/src/conftest/actions.c
@@ -65,7 +65,7 @@ static job_requeue_t initiate(char *config)
{
DBG1(DBG_CFG, "initiating IKE_SA for CHILD_SA config '%s'", config);
charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
- NULL, NULL, 0);
+ NULL, NULL, 0, FALSE);
}
else
{
diff --git a/src/frontends/osx/charon-xpc/xpc_dispatch.c b/src/frontends/osx/charon-xpc/xpc_dispatch.c
index 04aad8735..4b4c67cc4 100644
--- a/src/frontends/osx/charon-xpc/xpc_dispatch.c
+++ b/src/frontends/osx/charon-xpc/xpc_dispatch.c
@@ -196,7 +196,7 @@ void start_connection(private_xpc_dispatch_t *this,
peer_cfg->add_child_cfg(peer_cfg, child_cfg->get_ref(child_cfg));
if (charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
- (controller_cb_t)initiate_cb, &ike_sa, 0) == NEED_MORE)
+ (controller_cb_t)initiate_cb, &ike_sa, 0, FALSE) == NEED_MORE)
{
this->channels->add(this->channels, channel, ike_sa);
success = TRUE;
diff --git a/src/libcharon/control/controller.c b/src/libcharon/control/controller.c
index fd8349e2f..097f5ac2e 100644
--- a/src/libcharon/control/controller.c
+++ b/src/libcharon/control/controller.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2012 Tobias Brunner
+ * Copyright (C) 2011-2015 Tobias Brunner
* Copyright (C) 2007-2011 Martin Willi
* Copyright (C) 2011 revosec AG
* Hochschule fuer Technik Rapperswil
@@ -116,6 +116,11 @@ struct interface_listener_t {
* spinlock to update the IKE_SA handle properly
*/
spinlock_t *lock;
+
+ /**
+ * whether to check limits
+ */
+ bool limits;
};
@@ -358,7 +363,6 @@ METHOD(job_t, initiate_execute, job_requeue_t,
listener->child_cfg->destroy(listener->child_cfg);
peer_cfg->destroy(peer_cfg);
listener->status = FAILED;
- /* release listener */
listener_done(listener);
return JOB_REQUEUE_NONE;
}
@@ -372,6 +376,49 @@ METHOD(job_t, initiate_execute, job_requeue_t,
}
peer_cfg->destroy(peer_cfg);
+ if (listener->limits && ike_sa->get_state(ike_sa) == IKE_CREATED)
+ { /* only check if we are not reusing an IKE_SA */
+ u_int half_open, limit_half_open, limit_job_load;
+
+ half_open = charon->ike_sa_manager->get_half_open_count(
+ charon->ike_sa_manager, NULL);
+ limit_half_open = lib->settings->get_int(lib->settings,
+ "%s.init_limit_half_open", 0, lib->ns);
+ limit_job_load = lib->settings->get_int(lib->settings,
+ "%s.init_limit_job_load", 0, lib->ns);
+ if (limit_half_open && half_open >= limit_half_open)
+ {
+ DBG1(DBG_IKE, "abort IKE_SA initiation, half open IKE_SA count of "
+ "%d exceeds limit of %d", half_open, limit_half_open);
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
+ ike_sa);
+ listener->child_cfg->destroy(listener->child_cfg);
+ listener->status = INVALID_STATE;
+ listener_done(listener);
+ return JOB_REQUEUE_NONE;
+ }
+ if (limit_job_load)
+ {
+ u_int jobs = 0, i;
+
+ for (i = 0; i < JOB_PRIO_MAX; i++)
+ {
+ jobs += lib->processor->get_job_load(lib->processor, i);
+ }
+ if (jobs > limit_job_load)
+ {
+ DBG1(DBG_IKE, "abort IKE_SA initiation, job load of %d exceeds "
+ "limit of %d", jobs, limit_job_load);
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, ike_sa);
+ listener->child_cfg->destroy(listener->child_cfg);
+ listener->status = INVALID_STATE;
+ listener_done(listener);
+ return JOB_REQUEUE_NONE;
+ }
+ }
+ }
+
if (ike_sa->initiate(ike_sa, listener->child_cfg, 0, NULL, NULL) == SUCCESS)
{
if (!listener->logger.callback)
@@ -391,7 +438,7 @@ METHOD(job_t, initiate_execute, job_requeue_t,
METHOD(controller_t, initiate, status_t,
private_controller_t *this, peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
- controller_cb_t callback, void *param, u_int timeout)
+ controller_cb_t callback, void *param, u_int timeout, bool limits)
{
interface_job_t *job;
status_t status;
@@ -414,6 +461,7 @@ METHOD(controller_t, initiate, status_t,
.child_cfg = child_cfg,
.peer_cfg = peer_cfg,
.lock = spinlock_create(),
+ .limits = limits,
},
.public = {
.execute = _initiate_execute,
diff --git a/src/libcharon/control/controller.h b/src/libcharon/control/controller.h
index 02f4ebb2b..5ffeac522 100644
--- a/src/libcharon/control/controller.h
+++ b/src/libcharon/control/controller.h
@@ -82,15 +82,18 @@ struct controller_t {
* @param cb logging callback
* @param param parameter to include in each call of cb
* @param timeout timeout in ms to wait for callbacks, 0 to disable
+ * @param limits whether to check limits regarding IKE_SA initiation
* @return
* - SUCCESS, if CHILD_SA established
* - FAILED, if setup failed
* - NEED_MORE, if callback returned FALSE
* - OUT_OF_RES if timed out
+ * - INVALID_STATE if limits prevented initiation
*/
status_t (*initiate)(controller_t *this,
peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
- controller_cb_t callback, void *param, u_int timeout);
+ controller_cb_t callback, void *param, u_int timeout,
+ bool limits);
/**
* Terminate an IKE_SA and all of its CHILD_SAs.
diff --git a/src/libcharon/plugins/load_tester/load_tester_control.c b/src/libcharon/plugins/load_tester/load_tester_control.c
index 5f089f5db..24076d443 100644
--- a/src/libcharon/plugins/load_tester/load_tester_control.c
+++ b/src/libcharon/plugins/load_tester/load_tester_control.c
@@ -239,7 +239,7 @@ static bool on_accept(private_load_tester_control_t *this, stream_t *io)
switch (charon->controller->initiate(charon->controller,
peer_cfg, child_cfg->get_ref(child_cfg),
- (void*)initiate_cb, listener, 0))
+ (void*)initiate_cb, listener, 0, FALSE))
{
case NEED_MORE:
/* Callback returns FALSE once it got track of this IKE_SA.
diff --git a/src/libcharon/plugins/load_tester/load_tester_plugin.c b/src/libcharon/plugins/load_tester/load_tester_plugin.c
index e684f22ce..c7380b974 100644
--- a/src/libcharon/plugins/load_tester/load_tester_plugin.c
+++ b/src/libcharon/plugins/load_tester/load_tester_plugin.c
@@ -152,7 +152,7 @@ static job_requeue_t do_load_test(private_load_tester_plugin_t *this)
charon->controller->initiate(charon->controller,
peer_cfg, child_cfg->get_ref(child_cfg),
- NULL, NULL, 0);
+ NULL, NULL, 0, FALSE);
if (s)
{
sleep(s);
diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c
index 1fb57b928..25b138387 100644
--- a/src/libcharon/plugins/medcli/medcli_config.c
+++ b/src/libcharon/plugins/medcli/medcli_config.c
@@ -314,7 +314,7 @@ static job_requeue_t initiate_config(peer_cfg_t *peer_cfg)
peer_cfg->get_ref(peer_cfg);
enumerator->destroy(enumerator);
charon->controller->initiate(charon->controller,
- peer_cfg, child_cfg, NULL, NULL, 0);
+ peer_cfg, child_cfg, NULL, NULL, 0, FALSE);
}
else
{
diff --git a/src/libcharon/plugins/smp/smp.c b/src/libcharon/plugins/smp/smp.c
index 04bf382ed..2aa061fd2 100644
--- a/src/libcharon/plugins/smp/smp.c
+++ b/src/libcharon/plugins/smp/smp.c
@@ -488,7 +488,7 @@ static void request_control_initiate(xmlTextReaderPtr reader,
{
status = charon->controller->initiate(charon->controller,
peer, child, (controller_cb_t)xml_callback,
- writer, 0);
+ writer, 0, FALSE);
}
else
{
diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c
index 0084fbf93..0125d17c6 100644
--- a/src/libcharon/plugins/stroke/stroke_control.c
+++ b/src/libcharon/plugins/stroke/stroke_control.c
@@ -109,7 +109,7 @@ static void charon_initiate(private_stroke_control_t *this, peer_cfg_t *peer_cfg
if (msg->output_verbosity < 0)
{
charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
- NULL, NULL, 0);
+ NULL, NULL, 0, FALSE);
}
else
{
@@ -118,7 +118,7 @@ static void charon_initiate(private_stroke_control_t *this, peer_cfg_t *peer_cfg
status = charon->controller->initiate(charon->controller,
peer_cfg, child_cfg, (controller_cb_t)stroke_log,
- &info, this->timeout);
+ &info, this->timeout, FALSE);
switch (status)
{
case SUCCESS:
diff --git a/src/libcharon/plugins/uci/uci_control.c b/src/libcharon/plugins/uci/uci_control.c
index cebc389e7..a7d26e67d 100644
--- a/src/libcharon/plugins/uci/uci_control.c
+++ b/src/libcharon/plugins/uci/uci_control.c
@@ -147,7 +147,7 @@ static void initiate(private_uci_control_t *this, char *name)
if (enumerator->enumerate(enumerator, &child_cfg) &&
charon->controller->initiate(charon->controller, peer_cfg,
child_cfg->get_ref(child_cfg),
- controller_cb_empty, NULL, 0) == SUCCESS)
+ controller_cb_empty, NULL, 0, FALSE) == SUCCESS)
{
write_fifo(this, "connection '%s' established\n", name);
}
diff --git a/src/libcharon/plugins/vici/README.md b/src/libcharon/plugins/vici/README.md
index 1273bb8fc..e20e8ab26 100644
--- a/src/libcharon/plugins/vici/README.md
+++ b/src/libcharon/plugins/vici/README.md
@@ -259,6 +259,7 @@ Initiates an SA while streaming _control-log_ events.
{
child = <CHILD_SA configuration name to initiate>
timeout = <timeout in seconds before returning>
+ init-limits = <whether limits may prevent initiating the CHILD_SA>
loglevel = <loglevel to issue "control-log" events for>
} => {
success = <yes or no>
diff --git a/src/libcharon/plugins/vici/suites/test_message.c b/src/libcharon/plugins/vici/suites/test_message.c
index e76d27332..045e34fff 100644
--- a/src/libcharon/plugins/vici/suites/test_message.c
+++ b/src/libcharon/plugins/vici/suites/test_message.c
@@ -1,4 +1,7 @@
/*
+ * Copyright (C) 2015 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
@@ -355,6 +358,33 @@ START_TEST(test_get_int)
}
END_TEST
+START_TEST(test_get_bool)
+{
+ vici_message_t *m;
+
+ m = build_getter_msg();
+
+ ck_assert(m->get_bool(m, TRUE, "key1"));
+ ck_assert(m->get_bool(m, FALSE, "key1"));
+
+ ck_assert(m->get_bool(m, TRUE, "section1.key2"));
+ ck_assert(m->get_bool(m, TRUE, "section1.section2.key3"));
+ ck_assert(m->get_bool(m, TRUE, "section1.key4"));
+ ck_assert(m->get_bool(m, TRUE, "key5"));
+ ck_assert(m->get_bool(m, TRUE, "nonexistent"));
+ ck_assert(m->get_bool(m, TRUE, "n.o.n.e.x.i.s.t.e.n.t"));
+
+ ck_assert(!m->get_bool(m, FALSE, "section1.key2"));
+ ck_assert(!m->get_bool(m, FALSE, "section1.section2.key3"));
+ ck_assert(!m->get_bool(m, FALSE, "section1.key4"));
+ ck_assert(!m->get_bool(m, FALSE, "key5"));
+ ck_assert(!m->get_bool(m, FALSE, "nonexistent"));
+ ck_assert(!m->get_bool(m, FALSE, "n.o.n.e.x.i.s.t.e.n.t"));
+
+ m->destroy(m);
+}
+END_TEST
+
START_TEST(test_get_value)
{
vici_message_t *m;
@@ -400,6 +430,7 @@ Suite *message_suite_create()
tc = tcase_create("convenience getters");
tcase_add_test(tc, test_get_str);
tcase_add_test(tc, test_get_int);
+ tcase_add_test(tc, test_get_bool);
tcase_add_test(tc, test_get_value);
suite_add_tcase(s, tc);
diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c
index d442bd69e..ea6d2958a 100644
--- a/src/libcharon/plugins/vici/vici_config.c
+++ b/src/libcharon/plugins/vici/vici_config.c
@@ -1589,7 +1589,7 @@ static void run_start_action(private_vici_config_t *this, peer_cfg_t *peer_cfg,
DBG1(DBG_CFG, "initiating '%s'", child_cfg->get_name(child_cfg));
charon->controller->initiate(charon->controller,
peer_cfg->get_ref(peer_cfg), child_cfg->get_ref(child_cfg),
- NULL, NULL, 0);
+ NULL, NULL, 0, FALSE);
break;
case ACTION_ROUTE:
DBG1(DBG_CFG, "installing '%s'", child_cfg->get_name(child_cfg));
diff --git a/src/libcharon/plugins/vici/vici_control.c b/src/libcharon/plugins/vici/vici_control.c
index 408d29985..752007c24 100644
--- a/src/libcharon/plugins/vici/vici_control.c
+++ b/src/libcharon/plugins/vici/vici_control.c
@@ -163,6 +163,7 @@ CALLBACK(initiate, vici_message_t*,
peer_cfg_t *peer_cfg;
char *child;
u_int timeout;
+ bool limits;
log_info_t log = {
.dispatcher = this->dispatcher,
.id = id,
@@ -170,6 +171,7 @@ CALLBACK(initiate, vici_message_t*,
child = request->get_str(request, NULL, "child");
timeout = request->get_int(request, 0, "timeout");
+ limits = request->get_bool(request, FALSE, "init-limits");
log.level = request->get_int(request, 1, "loglevel");
if (!child)
@@ -184,14 +186,17 @@ CALLBACK(initiate, vici_message_t*,
{
return send_reply(this, "CHILD_SA config '%s' not found", child);
}
- switch (charon->controller->initiate(charon->controller,
- peer_cfg, child_cfg, (controller_cb_t)log_vici, &log, timeout))
+ switch (charon->controller->initiate(charon->controller, peer_cfg,
+ child_cfg, (controller_cb_t)log_vici, &log, timeout, limits))
{
case SUCCESS:
return send_reply(this, NULL);
case OUT_OF_RES:
return send_reply(this, "CHILD_SA '%s' not established after %dms",
child, timeout);
+ case INVALID_STATE:
+ return send_reply(this, "establishing CHILD_SA '%s' not possible "
+ "at the moment due to limits", child);
case FAILED:
default:
return send_reply(this, "establishing CHILD_SA '%s' failed", child);
diff --git a/src/libcharon/plugins/vici/vici_message.c b/src/libcharon/plugins/vici/vici_message.c
index e79fbc8d3..fb6e8a1ab 100644
--- a/src/libcharon/plugins/vici/vici_message.c
+++ b/src/libcharon/plugins/vici/vici_message.c
@@ -1,4 +1,7 @@
/*
+ * Copyright (C) 2015 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
@@ -385,6 +388,41 @@ METHOD(vici_message_t, get_int, int,
return val;
}
+METHOD(vici_message_t, vget_bool, bool,
+ private_vici_message_t *this, bool def, char *fmt, va_list args)
+{
+ chunk_t value;
+ bool found;
+ char buf[16];
+
+ found = find_value(this, &value, fmt, args);
+ if (found)
+ {
+ if (value.len == 0)
+ {
+ return def;
+ }
+ if (chunk_printable(value, NULL, 0))
+ {
+ snprintf(buf, sizeof(buf), "%.*s", (int)value.len, value.ptr);
+ return settings_value_as_bool(buf, def);
+ }
+ }
+ return def;
+}
+
+METHOD(vici_message_t, get_bool, bool,
+ private_vici_message_t *this, bool def, char *fmt, ...)
+{
+ va_list args;
+ bool val;
+
+ va_start(args, fmt);
+ val = vget_bool(this, def, fmt, args);
+ va_end(args);
+ return val;
+}
+
METHOD(vici_message_t, vget_value, chunk_t,
private_vici_message_t *this, chunk_t def, char *fmt, va_list args)
{
@@ -633,6 +671,8 @@ vici_message_t *vici_message_create_from_data(chunk_t data, bool cleanup)
.vget_str = _vget_str,
.get_int = _get_int,
.vget_int = _vget_int,
+ .get_bool = _get_bool,
+ .vget_bool = _vget_bool,
.get_value = _get_value,
.vget_value = _vget_value,
.get_encoding = _get_encoding,
diff --git a/src/libcharon/plugins/vici/vici_message.h b/src/libcharon/plugins/vici/vici_message.h
index 1a89cf829..7f357b8ec 100644
--- a/src/libcharon/plugins/vici/vici_message.h
+++ b/src/libcharon/plugins/vici/vici_message.h
@@ -1,4 +1,7 @@
/*
+ * Copyright (C) 2015 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
@@ -138,6 +141,26 @@ struct vici_message_t {
int (*vget_int)(vici_message_t *this, int def, char *fmt, va_list args);
/**
+ * Get the value of a key/value pair as boolean.
+ *
+ * @param def default value if not found
+ * @param fmt printf style format string for key, with sections
+ * @param ... arguments to fmt string
+ * @return value
+ */
+ bool (*get_bool)(vici_message_t *this, bool def, char *fmt, ...);
+
+ /**
+ * Get the value of a key/value pair as boolean, va_list variant
+ *
+ * @param def default value if not found
+ * @param fmt printf style format string for key, with sections
+ * @param args arguments to fmt string
+ * @return value
+ */
+ bool (*vget_bool)(vici_message_t *this, bool def, char *fmt, va_list args);
+
+ /**
* Get the raw value of a key/value pair.
*
* @param def default value if not found
diff --git a/src/libcharon/processing/jobs/initiate_mediation_job.c b/src/libcharon/processing/jobs/initiate_mediation_job.c
index 17ab83053..5b5fb9d98 100644
--- a/src/libcharon/processing/jobs/initiate_mediation_job.c
+++ b/src/libcharon/processing/jobs/initiate_mediation_job.c
@@ -119,8 +119,8 @@ METHOD(job_t, initiate, job_requeue_t,
/* we need an additional reference because initiate consumes one */
mediation_cfg->get_ref(mediation_cfg);
- if (charon->controller->initiate(charon->controller, mediation_cfg,
- NULL, (controller_cb_t)initiate_callback, this, 0) != SUCCESS)
+ if (charon->controller->initiate(charon->controller, mediation_cfg, NULL,
+ (controller_cb_t)initiate_callback, this, 0, FALSE) != SUCCESS)
{
mediation_cfg->destroy(mediation_cfg);
mediated_cfg->destroy(mediated_cfg);
diff --git a/src/libcharon/processing/jobs/start_action_job.c b/src/libcharon/processing/jobs/start_action_job.c
index 981473b5c..5e88ac230 100644
--- a/src/libcharon/processing/jobs/start_action_job.c
+++ b/src/libcharon/processing/jobs/start_action_job.c
@@ -61,7 +61,7 @@ METHOD(job_t, execute, job_requeue_t,
charon->controller->initiate(charon->controller,
peer_cfg->get_ref(peer_cfg),
child_cfg->get_ref(child_cfg),
- NULL, NULL, 0);
+ NULL, NULL, 0, FALSE);
break;
case ACTION_ROUTE:
DBG1(DBG_JOB, "start action: route '%s'", name);
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c
index 3e6496da5..137920a96 100644
--- a/src/libcharon/sa/ike_sa_manager.c
+++ b/src/libcharon/sa/ike_sa_manager.c
@@ -1572,7 +1572,6 @@ METHOD(ike_sa_manager_t, checkin, void,
put_half_open(this, entry);
}
else if (!entry->half_open &&
- !entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
ike_sa->get_state(ike_sa) == IKE_CONNECTING)
{
/* this is a new half-open SA */