diff options
-rwxr-xr-x | src/charon/config/configuration.c | 19 | ||||
-rwxr-xr-x | src/charon/config/configuration.h | 15 | ||||
-rw-r--r-- | src/charon/sa/task_manager.c | 73 | ||||
-rw-r--r-- | src/charon/sa/tasks/child_rekey.c | 14 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_rekey.c | 10 |
5 files changed, 88 insertions, 43 deletions
diff --git a/src/charon/config/configuration.c b/src/charon/config/configuration.c index f43afdaa4..bed0f6397 100755 --- a/src/charon/config/configuration.c +++ b/src/charon/config/configuration.c @@ -72,6 +72,16 @@ */ #define KEEPALIVE_INTERVAL 20 +/** + * retry interval in seconds. + */ +#define RETRY_INTERVAL 15 + +/** + * jitter to user for retrying + */ +#define RETRY_JITTER 5 + typedef struct private_configuration_t private_configuration_t; @@ -119,6 +129,14 @@ static u_int32_t get_keepalive_interval (private_configuration_t *this) } /** + * Implementation of configuration_t.get_retry_interval. + */ +static u_int32_t get_retry_interval (private_configuration_t *this) +{ + return RETRY_INTERVAL - (random() % RETRY_JITTER); +} + +/** * Implementation of configuration_t.destroy. */ static void destroy(private_configuration_t *this) @@ -138,6 +156,7 @@ configuration_t *configuration_create() this->public.get_retransmit_timeout = (u_int32_t (*) (configuration_t*,u_int32_t))get_retransmit_timeout; this->public.get_half_open_ike_sa_timeout = (u_int32_t (*) (configuration_t*)) get_half_open_ike_sa_timeout; this->public.get_keepalive_interval = (u_int32_t (*) (configuration_t*)) get_keepalive_interval; + this->public.get_retry_interval = (u_int32_t (*) (configuration_t*)) get_retry_interval; return (&this->public); } diff --git a/src/charon/config/configuration.h b/src/charon/config/configuration.h index 77d1fd85d..c1207171d 100755 --- a/src/charon/config/configuration.h +++ b/src/charon/config/configuration.h @@ -61,17 +61,28 @@ struct configuration_t { u_int32_t (*get_half_open_ike_sa_timeout) (configuration_t *this); /** - * @brief Returns the keepalive interval in ms. + * @brief Returns the keepalive interval in s. * * The keepalive interval defines the idle time after which a * NAT keepalive packet should be sent. * * @param this calling object - * @return interval in seconds + * @return interval in s */ u_int32_t (*get_keepalive_interval) (configuration_t *this); /** + * @brief Returns the interval to retry a failed action again. + * + * In some situations, the protocol may be in a state where processing + * is not possible and an action must be retried (e.g. rekeying). + * + * @param this calling object + * @return interval in s + */ + u_int32_t (*get_retry_interval) (configuration_t *this); + + /** * @brief Destroys a configuration_t object. * * @param this calling object diff --git a/src/charon/sa/task_manager.c b/src/charon/sa/task_manager.c index d63c614c0..8308c1425 100644 --- a/src/charon/sa/task_manager.c +++ b/src/charon/sa/task_manager.c @@ -444,43 +444,43 @@ static void handle_collisions(private_task_manager_t *this, task_t *task) type = task->get_type(task); - /* check if we have initiated rekeying ourself */ - if (this->initiating.type != CREATE_CHILD_SA || - (type != IKE_REKEY && type != CHILD_REKEY && type != CHILD_DELETE)) - { - task->destroy(task); - return; + /* do we have to check */ + if (type == IKE_REKEY || type == CHILD_REKEY || + type == CHILD_DELETE || type == IKE_DELETE) + { + /* find an exchange collision, and notify these tasks */ + iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE); + while (iterator->iterate(iterator, (void**)&active)) + { + switch (active->get_type(active)) + { + case IKE_REKEY: + if (type == IKE_REKEY || type == IKE_DELETE) + { + ike_rekey_t *rekey = (ike_rekey_t*)active; + rekey->collide(rekey, task); + break; + } + continue; + case CHILD_REKEY: + /* TODO: check if it is the SAME child we are talking about! */ + if (type == CHILD_REKEY || type == CHILD_DELETE) + { + child_rekey_t *rekey = (child_rekey_t*)active; + rekey->collide(rekey, task); + break; + } + continue; + default: + continue; + } + iterator->destroy(iterator); + return; + } + iterator->destroy(iterator); } - - /* find an exchange collision, and notify these tasks */ - iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE); - while (iterator->iterate(iterator, (void**)&active)) - { - switch (active->get_type(active)) - { - case IKE_REKEY: - if (type == IKE_REKEY || type == IKE_DELETE) - { - ike_rekey_t *rekey = (ike_rekey_t*)active; - rekey->collide(rekey, task); - break; - } - continue; - case CHILD_REKEY: - /* TODO: check if it is the SAME child we are talking about! */ - if (type == CHILD_REKEY || type == CHILD_DELETE) - { - child_rekey_t *rekey = (child_rekey_t*)active; - rekey->collide(rekey, task); - break; - } - continue; - default: - continue; - } - break; - } - iterator->destroy(iterator); + /* destroy task if not registered in any active task */ + task->destroy(task); } /** @@ -633,7 +633,6 @@ static status_t process_request(private_task_manager_t *this, task = (task_t*)ike_rekey_create(this->ike_sa, FALSE); } this->passive_tasks->insert_last(this->passive_tasks, task); - break; } case INFORMATIONAL: diff --git a/src/charon/sa/tasks/child_rekey.c b/src/charon/sa/tasks/child_rekey.c index 3fb4a54f6..84d10be1f 100644 --- a/src/charon/sa/tasks/child_rekey.c +++ b/src/charon/sa/tasks/child_rekey.c @@ -26,6 +26,7 @@ #include <daemon.h> #include <encoding/payloads/notify_payload.h> #include <sa/tasks/child_create.h> +#include <queues/jobs/rekey_child_sa_job.h> typedef struct private_child_rekey_t private_child_rekey_t; @@ -165,12 +166,10 @@ static status_t build_r(private_child_rekey_t *this, message_t *message) { /* rekeying failed, reuse old child */ this->child_sa->set_state(this->child_sa, CHILD_INSTALLED); - /* TODO: reschedule rekeying */ return SUCCESS; } this->child_sa->set_state(this->child_sa, CHILD_REKEYING); - return SUCCESS; } @@ -191,8 +190,17 @@ static status_t process_i(private_child_rekey_t *this, message_t *message) if (!(this->collision && this->collision->get_type(this->collision) == CHILD_DELETE)) { + job_t *job; + u_int32_t retry = charon->configuration->get_retry_interval( + charon->configuration); + job = (job_t*)rekey_child_sa_job_create( + this->child_sa->get_reqid(this->child_sa), + this->child_sa->get_protocol(this->child_sa), + this->child_sa->get_spi(this->child_sa, TRUE)); + DBG1(DBG_IKE, "CHILD_SA rekeying failed, " + "trying again in %d seconds", retry); this->child_sa->set_state(this->child_sa, CHILD_INSTALLED); - /* TODO: rescedule rekeying */ + charon->event_queue->add_relative(charon->event_queue, job, retry * 1000); } return SUCCESS; } diff --git a/src/charon/sa/tasks/ike_rekey.c b/src/charon/sa/tasks/ike_rekey.c index 879a3ee62..1ed542e7f 100644 --- a/src/charon/sa/tasks/ike_rekey.c +++ b/src/charon/sa/tasks/ike_rekey.c @@ -27,6 +27,7 @@ #include <encoding/payloads/notify_payload.h> #include <sa/tasks/ike_init.h> #include <queues/jobs/delete_ike_sa_job.h> +#include <queues/jobs/rekey_ike_sa_job.h> typedef struct private_ike_rekey_t private_ike_rekey_t; @@ -180,8 +181,15 @@ static status_t process_i(private_ike_rekey_t *this, message_t *message) if (!(this->collision && this->collision->get_type(this->collision) == IKE_DELETE)) { + job_t *job; + u_int32_t retry = charon->configuration->get_retry_interval( + charon->configuration); + job = (job_t*)rekey_ike_sa_job_create( + this->ike_sa->get_id(this->ike_sa), FALSE); + DBG1(DBG_IKE, "IKE_SA rekeying failed, " + "trying again in %d seconds", retry); this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED); - /* TODO: reschedule rekeying */ + charon->event_queue->add_relative(charon->event_queue, job, retry * 1000); } return SUCCESS; } |