diff --git a/src/libcharon/processing/jobs/retry_initiate_job.c b/src/libcharon/processing/jobs/retry_initiate_job.c index 11e573992..e6da3e362 100644 --- a/src/libcharon/processing/jobs/retry_initiate_job.c +++ b/src/libcharon/processing/jobs/retry_initiate_job.c @@ -54,7 +54,7 @@ METHOD(job_t, execute, void, } else { - if (ike_sa->initiate(ike_sa, NULL, 0, NULL, NULL) == DESTROY_ME) + if (ike_sa->retry_initiate(ike_sa) == DESTROY_ME) { charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa); diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c index 93a8ad850..c104ff973 100644 --- a/src/libcharon/sa/ike_sa.c +++ b/src/libcharon/sa/ike_sa.c @@ -222,6 +222,11 @@ struct private_ike_sa_t { */ u_int32_t retry_initiate_interval; + /** + * TRUE if a retry_initiate_job has been queued + */ + bool retry_initiate_queued; + /** * Timestamps for this IKE_SA */ @@ -1162,14 +1167,30 @@ METHOD(ike_sa_t, initiate, status_t, if (defer_initiate) { - job_t *job = (job_t*)retry_initiate_job_create(this->ike_sa_id); - lib->scheduler->schedule_job(lib->scheduler, (job_t*)job, - this->retry_initiate_interval); + if (!this->retry_initiate_queued) + { + job_t *job = (job_t*)retry_initiate_job_create(this->ike_sa_id); + lib->scheduler->schedule_job(lib->scheduler, (job_t*)job, + this->retry_initiate_interval); + this->retry_initiate_queued = TRUE; + } return SUCCESS; } + this->retry_initiate_queued = FALSE; return this->task_manager->initiate(this->task_manager); } +METHOD(ike_sa_t, retry_initiate, status_t, + private_ike_sa_t *this) +{ + if (this->retry_initiate_queued) + { + this->retry_initiate_queued = FALSE; + return initiate(this, NULL, 0, NULL, NULL); + } + return SUCCESS; +} + METHOD(ike_sa_t, process_message, status_t, private_ike_sa_t *this, message_t *message) { @@ -2089,6 +2110,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator, .set_statistic = _set_statistic, .process_message = _process_message, .initiate = _initiate, + .retry_initiate = _retry_initiate, .get_ike_cfg = _get_ike_cfg, .set_ike_cfg = _set_ike_cfg, .get_peer_cfg = _get_peer_cfg, diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h index a3c3de81c..5b2eb4ed1 100644 --- a/src/libcharon/sa/ike_sa.h +++ b/src/libcharon/sa/ike_sa.h @@ -694,6 +694,15 @@ struct ike_sa_t { u_int32_t reqid, traffic_selector_t *tsi, traffic_selector_t *tsr); + /** + * Retry initiation of this IKE_SA after it got deferred previously. + * + * @return + * - SUCCESS if initiation deferred or started + * - DESTROY_ME if initiation failed + */ + status_t (*retry_initiate) (ike_sa_t *this); + /** * Initiates the deletion of an IKE_SA. *