added CHILD_SA compare check for rekeying collisions
authorMartin Willi <martin@strongswan.org>
Thu, 22 Mar 2007 07:34:42 +0000 (07:34 -0000)
committerMartin Willi <martin@strongswan.org>
Thu, 22 Mar 2007 07:34:42 +0000 (07:34 -0000)
src/charon/sa/task_manager.c
src/charon/sa/tasks/child_create.c
src/charon/sa/tasks/child_create.h
src/charon/sa/tasks/child_delete.c
src/charon/sa/tasks/child_delete.h
src/charon/sa/tasks/child_rekey.c

index 8308c14..3852d8f 100644 (file)
@@ -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;
index 60172cf..781d679 100644 (file)
@@ -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;
 }
 
 /**
index 7ff2fb2..200d374 100644 (file)
@@ -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
index 30270f2..23d509d 100644 (file)
@@ -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;
index 327a2ec..a7e676a 100644 (file)
@@ -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);
 };
 
 /**
index 84d10be..745895d 100644 (file)
@@ -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;
 }