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);
}
{
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
{
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;
/*
- * 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
* spinlock to update the IKE_SA handle properly
*/
spinlock_t *lock;
+
+ /**
+ * whether to check limits
+ */
+ bool limits;
};
listener->child_cfg->destroy(listener->child_cfg);
peer_cfg->destroy(peer_cfg);
listener->status = FAILED;
- /* release listener */
listener_done(listener);
return JOB_REQUEUE_NONE;
}
}
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)
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;
.child_cfg = child_cfg,
.peer_cfg = peer_cfg,
.lock = spinlock_create(),
+ .limits = limits,
},
.public = {
.execute = _initiate_execute,
* @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.
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.
charon->controller->initiate(charon->controller,
peer_cfg, child_cfg->get_ref(child_cfg),
- NULL, NULL, 0);
+ NULL, NULL, 0, FALSE);
if (s)
{
sleep(s);
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
{
{
status = charon->controller->initiate(charon->controller,
peer, child, (controller_cb_t)xml_callback,
- writer, 0);
+ writer, 0, FALSE);
}
else
{
if (msg->output_verbosity < 0)
{
charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
- NULL, NULL, 0);
+ NULL, NULL, 0, FALSE);
}
else
{
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:
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);
}
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));
{
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, FALSE))
{
case SUCCESS:
return send_reply(this, NULL);
/* 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);
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);