aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/charon/sa/task_manager.c1
-rw-r--r--src/charon/sa/tasks/child_create.c6
-rw-r--r--src/charon/sa/tasks/child_create.h4
-rw-r--r--src/charon/sa/tasks/child_delete.c11
-rw-r--r--src/charon/sa/tasks/child_delete.h8
-rw-r--r--src/charon/sa/tasks/child_rekey.c26
6 files changed, 47 insertions, 9 deletions
diff --git a/src/charon/sa/task_manager.c b/src/charon/sa/task_manager.c
index 8308c1425..3852d8f3b 100644
--- a/src/charon/sa/task_manager.c
+++ b/src/charon/sa/task_manager.c
@@ -463,7 +463,6 @@ static void handle_collisions(private_task_manager_t *this, task_t *task)
}
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;
diff --git a/src/charon/sa/tasks/child_create.c b/src/charon/sa/tasks/child_create.c
index 60172cf20..781d679f2 100644
--- a/src/charon/sa/tasks/child_create.c
+++ b/src/charon/sa/tasks/child_create.c
@@ -680,11 +680,7 @@ static void use_reqid(private_child_create_t *this, u_int32_t reqid)
*/
static child_sa_t* get_child(private_child_create_t *this)
{
- if (this->established)
- {
- return this->child_sa;
- }
- return NULL;
+ return this->child_sa;
}
/**
diff --git a/src/charon/sa/tasks/child_create.h b/src/charon/sa/tasks/child_create.h
index 7ff2fb22d..200d37457 100644
--- a/src/charon/sa/tasks/child_create.h
+++ b/src/charon/sa/tasks/child_create.h
@@ -68,9 +68,7 @@ struct child_create_t {
chunk_t (*get_lower_nonce) (child_create_t *this);
/**
- * @brief Get the CHILD_SA established by this task.
- *
- * This call returns a child only when it has been established successfully.
+ * @brief Get the CHILD_SA established/establishing by this task.
*
* @param this calling object
* @return child_sa
diff --git a/src/charon/sa/tasks/child_delete.c b/src/charon/sa/tasks/child_delete.c
index 30270f27e..23d509de5 100644
--- a/src/charon/sa/tasks/child_delete.c
+++ b/src/charon/sa/tasks/child_delete.c
@@ -231,6 +231,16 @@ static task_type_t get_type(private_child_delete_t *this)
}
/**
+ * Implementation of child_delete_t.get_child
+ */
+static child_sa_t* get_child(private_child_delete_t *this)
+{
+ child_sa_t *child_sa = NULL;
+ this->child_sas->get_first(this->child_sas, (void**)&child_sa);
+ return child_sa;
+}
+
+/**
* Implementation of task_t.migrate
*/
static void migrate(private_child_delete_t *this, ike_sa_t *ike_sa)
@@ -257,6 +267,7 @@ child_delete_t *child_delete_create(ike_sa_t *ike_sa, child_sa_t *child_sa)
{
private_child_delete_t *this = malloc_thing(private_child_delete_t);
+ this->public.get_child = (child_sa_t*(*)(child_delete_t*))get_child;
this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
this->public.task.destroy = (void(*)(task_t*))destroy;
diff --git a/src/charon/sa/tasks/child_delete.h b/src/charon/sa/tasks/child_delete.h
index 327a2ec15..a7e676a50 100644
--- a/src/charon/sa/tasks/child_delete.h
+++ b/src/charon/sa/tasks/child_delete.h
@@ -44,6 +44,14 @@ struct child_delete_t {
* Implements the task_t interface
*/
task_t task;
+
+ /**
+ * @brief Get the CHILD_SA to delete by this task.
+ *
+ * @param this calling object
+ * @return child_sa
+ */
+ child_sa_t* (*get_child) (child_delete_t *this);
};
/**
diff --git a/src/charon/sa/tasks/child_rekey.c b/src/charon/sa/tasks/child_rekey.c
index 84d10be1f..745895dbb 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 <sa/tasks/child_delete.h>
#include <queues/jobs/rekey_child_sa_job.h>
@@ -258,6 +259,31 @@ static task_type_t get_type(private_child_rekey_t *this)
*/
static void collide(private_child_rekey_t *this, task_t *other)
{
+ /* the task manager only detects exchange collision, but not if
+ * the collision is for the same child. we check it here. */
+ if (other->get_type(other) == CHILD_REKEY)
+ {
+ private_child_rekey_t *rekey = (private_child_rekey_t*)other;
+ if (rekey == NULL || rekey->child_sa != this->child_sa)
+ {
+ /* not the same child => no collision */
+ return;
+ }
+ }
+ else if (other->get_type(other) == CHILD_DELETE)
+ {
+ child_delete_t *del = (child_delete_t*)other;
+ if (del == NULL || del->get_child(del) != this->child_sa)
+ {
+ /* not the same child => no collision */
+ return;
+ }
+ }
+ else
+ {
+ /* any other task is not critical for collisisions, ignore */
+ return;
+ }
DESTROY_IF(this->collision);
this->collision = other;
}