summaryrefslogtreecommitdiff
path: root/src/libcharon/sa/ikev2/tasks/ike_rekey.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/sa/ikev2/tasks/ike_rekey.c')
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_rekey.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/src/libcharon/sa/ikev2/tasks/ike_rekey.c b/src/libcharon/sa/ikev2/tasks/ike_rekey.c
index 444ac6ade..1855517ce 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_rekey.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_rekey.c
@@ -22,6 +22,7 @@
#include <sa/ikev2/tasks/ike_delete.h>
#include <processing/jobs/delete_ike_sa_job.h>
#include <processing/jobs/rekey_ike_sa_job.h>
+#include <processing/jobs/initiate_tasks_job.h>
typedef struct private_ike_rekey_t private_ike_rekey_t;
@@ -68,12 +69,33 @@ struct private_ike_rekey_t {
};
/**
+ * Check if an IKE_SA has any queued tasks, return initiation job
+ */
+static job_t* check_queued_tasks(ike_sa_t *ike_sa)
+{
+ enumerator_t *enumerator;
+ task_t *task;
+ job_t *job = NULL;
+
+ enumerator = ike_sa->create_task_enumerator(ike_sa, TASK_QUEUE_QUEUED);
+ if (enumerator->enumerate(enumerator, &task))
+ {
+ job = (job_t*)initiate_tasks_job_create(ike_sa->get_id(ike_sa));
+ }
+ enumerator->destroy(enumerator);
+
+ return job;
+}
+
+/**
* Establish the new replacement IKE_SA
*/
static void establish_new(private_ike_rekey_t *this)
{
if (this->new_sa)
{
+ job_t *job;
+
this->new_sa->set_state(this->new_sa, IKE_ESTABLISHED);
DBG0(DBG_IKE, "IKE_SA %s[%d] rekeyed between %H[%Y]...%H[%Y]",
this->new_sa->get_name(this->new_sa),
@@ -85,7 +107,14 @@ static void establish_new(private_ike_rekey_t *this)
this->new_sa->inherit_post(this->new_sa, this->ike_sa);
charon->bus->ike_rekey(charon->bus, this->ike_sa, this->new_sa);
+ job = check_queued_tasks(this->new_sa);
+ /* don't queue job before checkin(), as the IKE_SA is not yet
+ * registered at the manager */
charon->ike_sa_manager->checkin(charon->ike_sa_manager, this->new_sa);
+ if (job)
+ {
+ lib->processor->queue_job(lib->processor, job);
+ }
this->new_sa = NULL;
/* set threads active IKE_SA after checkin */
charon->bus->set_sa(charon->bus, this->ike_sa);
@@ -163,6 +192,7 @@ METHOD(task_t, process_r, status_t,
{
case CHILD_CREATED:
case CHILD_REKEYING:
+ case CHILD_RETRYING:
case CHILD_DELETING:
/* we do not allow rekeying while we have children in-progress */
DBG1(DBG_IKE, "peer initiated rekeying, but a child is half-open");
@@ -209,6 +239,12 @@ METHOD(task_t, build_r, status_t,
this->public.task.build = _build_r_delete;
this->public.task.process = _process_r_delete;
+ /* the peer does have to delete the IKE_SA. If it does not, we get a
+ * unusable IKE_SA in REKEYING state without a replacement. We consider
+ * this a timeout condition by the peer, and trigger a delete actively. */
+ lib->scheduler->schedule_job(lib->scheduler, (job_t*)
+ delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE), 90);
+
return NEED_MORE;
}