diff options
Diffstat (limited to 'src/libcharon/sa/ikev2/tasks/ike_rekey.c')
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/ike_rekey.c | 36 |
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; } |