]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
ikev2: Allow tasks to do work after generating requests/responses
authorTobias Brunner <tobias@strongswan.org>
Thu, 28 Jun 2018 08:44:40 +0000 (10:44 +0200)
committerTobias Brunner <tobias@strongswan.org>
Tue, 14 May 2019 08:53:14 +0000 (10:53 +0200)
src/libcharon/sa/ikev2/task_manager_v2.c

index ee3422c068e16cba22b57702aaeeb423f536caf7..37e7aa592495858b8c33f303b2aa58a1f1227655 100644 (file)
@@ -456,6 +456,7 @@ METHOD(task_manager_t, initiate, status_t,
        message_t *message;
        host_t *me, *other;
        exchange_type_t exchange = 0;
+       bool result;
 
        if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED)
        {
@@ -669,16 +670,46 @@ METHOD(task_manager_t, initiate, status_t,
                return initiate(this);
        }
 
-       if (!generate_message(this, message, &this->initiating.packets))
+       result = generate_message(this, message, &this->initiating.packets);
+
+       if (result)
        {
-               /* message generation failed. There is nothing more to do than to
+               enumerator = array_create_enumerator(this->active_tasks);
+               while (enumerator->enumerate(enumerator, &task))
+               {
+                       if (!task->post_build)
+                       {
+                               continue;
+                       }
+                       switch (task->post_build(task, message))
+                       {
+                               case SUCCESS:
+                                       array_remove_at(this->active_tasks, enumerator);
+                                       task->destroy(task);
+                                       break;
+                               case NEED_MORE:
+                                       break;
+                               default:
+                                       /* critical failure, destroy IKE_SA */
+                                       result = FALSE;
+                                       break;
+                       }
+               }
+               enumerator->destroy(enumerator);
+       }
+       message->destroy(message);
+
+       if (!result)
+       {       /* message generation failed. There is nothing more to do than to
                 * close the SA */
-               message->destroy(message);
                flush(this);
-               charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+               if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING &&
+                       this->ike_sa->get_state(this->ike_sa) != IKE_REKEYED)
+               {
+                       charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
+               }
                return DESTROY_ME;
        }
-       message->destroy(message);
 
        array_compress(this->active_tasks);
        array_compress(this->queued_tasks);
@@ -913,7 +944,34 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
        /* message complete, send it */
        clear_packets(this->responding.packets);
        result = generate_message(this, message, &this->responding.packets);
+
+       if (result && !delete)
+       {
+               enumerator = array_create_enumerator(this->passive_tasks);
+               while (enumerator->enumerate(enumerator, &task))
+               {
+                       if (!task->post_build)
+                       {
+                               continue;
+                       }
+                       switch (task->post_build(task, message))
+                       {
+                               case SUCCESS:
+                                       array_remove_at(this->passive_tasks, enumerator);
+                                       task->destroy(task);
+                                       break;
+                               case NEED_MORE:
+                                       break;
+                               default:
+                                       /* critical failure, destroy IKE_SA */
+                                       result = FALSE;
+                                       break;
+                       }
+               }
+               enumerator->destroy(enumerator);
+       }
        message->destroy(message);
+
        if (id)
        {
                id->set_responder_spi(id, responder_spi);