fixed deferred CHILD_SA rekeying while IKE_SA rekeying in progress
authorMartin Willi <martin@strongswan.org>
Tue, 27 Mar 2007 13:32:12 +0000 (13:32 -0000)
committerMartin Willi <martin@strongswan.org>
Tue, 27 Mar 2007 13:32:12 +0000 (13:32 -0000)
src/charon/sa/ike_sa.c
src/charon/sa/ike_sa.h
src/charon/sa/task_manager.c
src/charon/sa/tasks/ike_rekey.c

index 70f6dec..e4e603e 100644 (file)
@@ -1609,7 +1609,7 @@ static void reestablish(private_ike_sa_t *this)
 /**
  * Implementation of ike_sa_t.inherit.
  */
-static void inherit(private_ike_sa_t *this, private_ike_sa_t *other)
+static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other)
 {
        child_sa_t *child_sa;
        host_t *ip;
@@ -1649,6 +1649,12 @@ static void inherit(private_ike_sa_t *this, private_ike_sa_t *other)
        {
                this->child_sas->insert_first(this->child_sas, (void*)child_sa);
        }
+       
+       /* move pending tasks to the new IKE_SA */
+       this->task_manager->adopt_tasks(this->task_manager, other->task_manager);
+       
+       /* we have to initate here, there may be new tasks to handle */
+       return this->task_manager->initiate(this->task_manager);
 }
 
 /**
@@ -1989,7 +1995,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        this->public.is_natt_enabled = (bool(*)(ike_sa_t*)) is_natt_enabled;
        this->public.rekey = (status_t(*)(ike_sa_t*))rekey;
        this->public.reestablish = (void(*)(ike_sa_t*))reestablish;
-       this->public.inherit = (void(*)(ike_sa_t*,ike_sa_t*))inherit;
+       this->public.inherit = (status_t(*)(ike_sa_t*,ike_sa_t*))inherit;
        this->public.generate_message = (status_t(*)(ike_sa_t*,message_t*,packet_t**))generate_message;
        this->public.reset = (void(*)(ike_sa_t*))reset;
        this->public.get_unique_id = (u_int32_t(*)(ike_sa_t*))get_unique_id;
index 2ba9313..604ec94 100644 (file)
@@ -613,10 +613,13 @@ struct ike_sa_t {
         *
         * When rekeying is completed, all CHILD_SAs, the virtual IP and all
         * outstanding tasks are moved from other to this.
+        * As this call may initiate inherited tasks, a status is returned.
         *
         * @param this                  calling object
+        * @param other                 other task to inherit from
+        * @return                              DESTROY_ME if initiation of inherited task failed
         */
-       void (*inherit) (ike_sa_t *this, ike_sa_t *other);
+       status_t (*inherit) (ike_sa_t *this, ike_sa_t *other);
                
        /**
         * @brief Reset the IKE_SA, useable when initiating fails
index 3852d8f..5bfc048 100644 (file)
@@ -761,6 +761,7 @@ static void adopt_tasks(private_task_manager_t *this, private_task_manager_t *ot
        while (other->queued_tasks->remove_last(other->queued_tasks,
                                                                                                (void**)&task) == SUCCESS)
        {
+               DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
                task->migrate(task, this->ike_sa);
                this->queued_tasks->insert_first(this->queued_tasks, task);
        }
@@ -769,6 +770,7 @@ static void adopt_tasks(private_task_manager_t *this, private_task_manager_t *ot
        while (other->active_tasks->remove_last(other->active_tasks,
                                                                                                (void**)&task) == SUCCESS)
        {
+               DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task));
                task->migrate(task, this->ike_sa);
                this->queued_tasks->insert_first(this->queued_tasks, task);
        }
index 1ed542e..7a6b353 100644 (file)
@@ -282,9 +282,9 @@ static void destroy(private_ike_rekey_t *this)
 {
        if (this->new_sa)
        {
-               if (this->new_sa->get_state(this->new_sa) == IKE_ESTABLISHED)
+               if (this->new_sa->get_state(this->new_sa) == IKE_ESTABLISHED &&
+                       this->new_sa->inherit(this->new_sa, this->ike_sa) != DESTROY_ME)
                {
-                       this->new_sa->inherit(this->new_sa, this->ike_sa);
                        charon->ike_sa_manager->checkin(charon->ike_sa_manager, this->new_sa);
                }
                else