aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/charon/config/configuration.c19
-rwxr-xr-xsrc/charon/config/configuration.h15
-rw-r--r--src/charon/sa/task_manager.c73
-rw-r--r--src/charon/sa/tasks/child_rekey.c14
-rw-r--r--src/charon/sa/tasks/ike_rekey.c10
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;
}