It's optionally possible to wait for a timeout to destroy the SA.
{
id = ike_sa->get_unique_id(ike_sa);
enumerator->destroy(enumerator);
- charon->controller->terminate_ike(charon->controller, id,
+ charon->controller->terminate_ike(charon->controller, id, FALSE,
controller_cb_empty, NULL, 0);
return FALSE;
}
if (id)
{
DBG1(DBG_CFG, "closing IKE_SA '%s'", config);
- charon->controller->terminate_ike(charon->controller, id, NULL, NULL, 0);
+ charon->controller->terminate_ike(charon->controller, id, FALSE, NULL,
+ NULL, 0);
}
else
{
CALLBACK(terminate, job_requeue_t,
uint32_t *id)
{
- charon->controller->terminate_ike(charon->controller, *id,
+ charon->controller->terminate_ike(charon->controller, *id, FALSE,
controller_cb_empty, NULL, 0);
return JOB_REQUEUE_NONE;
}
{
status_t status;
- status = charon->controller->terminate_ike(charon->controller, ike_sa,
+ status = charon->controller->terminate_ike(charon->controller, ike_sa, FALSE,
NULL, NULL, 0);
xpc_dictionary_set_bool(reply, "success", status != NOT_FOUND);
}
*/
spinlock_t *lock;
- /**
- * whether to check limits
- */
- bool limits;
+ union {
+ /**
+ * whether to check limits during initiation
+ */
+ bool limits;
+
+ /**
+ * whether to force termination
+ */
+ bool force;
+ } options;
};
}
peer_cfg->destroy(peer_cfg);
- if (listener->limits && ike_sa->get_state(ike_sa) == IKE_CREATED)
+ if (listener->options.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;
.child_cfg = child_cfg,
.peer_cfg = peer_cfg,
.lock = spinlock_create(),
- .limits = limits,
+ .options.limits = limits,
},
.public = {
.execute = _initiate_execute,
listener->ike_sa = ike_sa;
listener->lock->unlock(listener->lock);
- if (ike_sa->delete(ike_sa, FALSE) != DESTROY_ME)
- { /* delete failed */
+ if (ike_sa->delete(ike_sa, listener->options.force) != DESTROY_ME)
+ { /* delete queued */
listener->status = FAILED;
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
}
METHOD(controller_t, terminate_ike, status_t,
- controller_t *this, uint32_t unique_id,
+ controller_t *this, uint32_t unique_id, bool force,
controller_cb_t callback, void *param, u_int timeout)
{
interface_job_t *job;
if (callback == NULL)
{
+ job->listener.options.force = force;
terminate_ike_execute(job);
}
else
{
+ if (!timeout)
+ {
+ job->listener.options.force = force;
+ }
if (wait_for_listener(job, timeout))
{
job->listener.status = OUT_OF_RES;
+
+ if (force)
+ { /* force termination once timeout is reached */
+ job->listener.options.force = TRUE;
+ terminate_ike_execute(job);
+ }
}
}
status = job->listener.status;
* until the IKE_SA is properly deleted, or the call timed out.
*
* @param unique_id unique id of the IKE_SA to terminate.
+ * @param force whether to immediately destroy the IKE_SA without
+ * waiting for a response or retransmitting the delete,
+ * if a callback is provided and timeout is > 0 the
+ * IKE_SA is destroyed once the timeout is reached but
+ * retransmits are sent until then
* @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
* - OUT_OF_RES if timed out
*/
status_t (*terminate_ike)(controller_t *this, uint32_t unique_id,
- controller_cb_t callback, void *param,
+ bool force, controller_cb_t callback, void *param,
u_int timeout);
/**
if (ike)
{
status = charon->controller->terminate_ike(
- charon->controller, id,
+ charon->controller, id, FALSE,
(controller_cb_t)xml_callback, writer, 0);
}
else
else
{
status = charon->controller->terminate_ike(charon->controller, id,
- (controller_cb_t)stroke_log, &info, this->timeout);
+ FALSE, (controller_cb_t)stroke_log, &info,
+ this->timeout);
}
report_terminate_status(this, status, out, id, child);
}
}
else
{
- charon->controller->terminate_ike(charon->controller, id,
+ charon->controller->terminate_ike(charon->controller, id, FALSE,
NULL, NULL, 0);
}
}
{
id = ike_sa->get_unique_id(ike_sa);
enumerator->destroy(enumerator);
- charon->controller->terminate_ike(charon->controller, id,
+ charon->controller->terminate_ike(charon->controller, id, FALSE,
controller_cb_empty, NULL, 0);
write_fifo(this, "connection '%s' terminated\n", name);
return;
while (array_remove(ikeids, ARRAY_HEAD, &id))
{
DBG1(DBG_CFG, "closing IKE_SA #%u", id);
- charon->controller->terminate_ike(charon->controller,
+ charon->controller->terminate_ike(charon->controller, FALSE,
id, NULL, NULL, 0);
}
array_destroy(ikeids);
}
else
{
- if (charon->controller->terminate_ike(charon->controller, *del,
+ if (charon->controller->terminate_ike(charon->controller, *del, FALSE,
log_cb, &log, timeout) == SUCCESS)
{
done++;