Do not query CHILD_SA during delete if they already expired
authorMartin Willi <martin@revosec.ch>
Mon, 2 Jan 2012 14:40:31 +0000 (15:40 +0100)
committerMartin Willi <martin@revosec.ch>
Tue, 20 Mar 2012 16:31:31 +0000 (17:31 +0100)
18 files changed:
src/libcharon/control/controller.c
src/libcharon/kernel/kernel_handler.c
src/libcharon/plugins/ha/ha_cache.c
src/libcharon/processing/jobs/delete_child_sa_job.c
src/libcharon/processing/jobs/delete_child_sa_job.h
src/libcharon/processing/jobs/inactivity_job.c
src/libcharon/sa/ike_sa.c
src/libcharon/sa/ike_sa.h
src/libcharon/sa/ikev1/task_manager_v1.c
src/libcharon/sa/ikev1/tasks/informational.c
src/libcharon/sa/ikev1/tasks/quick_delete.c
src/libcharon/sa/ikev1/tasks/quick_delete.h
src/libcharon/sa/ikev1/tasks/quick_mode.c
src/libcharon/sa/ikev2/task_manager_v2.c
src/libcharon/sa/ikev2/tasks/child_delete.c
src/libcharon/sa/ikev2/tasks/child_delete.h
src/libcharon/sa/ikev2/tasks/child_rekey.c
src/libcharon/sa/task_manager.h

index 4aded8f..11f4038 100644 (file)
@@ -368,7 +368,7 @@ METHOD(job_t, terminate_child_execute, void,
 
        charon->bus->set_sa(charon->bus, ike_sa);
        if (ike_sa->delete_child_sa(ike_sa, child_sa->get_protocol(child_sa),
-                                                               child_sa->get_spi(child_sa, TRUE)) != DESTROY_ME)
+                                       child_sa->get_spi(child_sa, TRUE), FALSE) != DESTROY_ME)
        {
                charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
                listener->status = SUCCESS;
index 51fccb1..aa5c4e0 100644 (file)
@@ -84,7 +84,7 @@ METHOD(kernel_listener_t, expire, bool,
                                  protocol_id_names, proto, ntohl(spi), reqid);
        if (hard)
        {
-               job = (job_t*)delete_child_sa_job_create(reqid, proto, spi);
+               job = (job_t*)delete_child_sa_job_create(reqid, proto, spi, hard);
        }
        else
        {
index 970a8a2..7b7a953 100644 (file)
@@ -212,7 +212,8 @@ static status_t rekey_children(ike_sa_t *ike_sa)
                        DBG1(DBG_CFG, "resyncing CHILD_SA using a delete");
                        status = ike_sa->delete_child_sa(ike_sa,
                                                                                         child_sa->get_protocol(child_sa),
-                                                                                        child_sa->get_spi(child_sa, TRUE));
+                                                                                        child_sa->get_spi(child_sa, TRUE),
+                                                                                        FALSE);
                }
                else
                {
index bd8bb95..ac1dfd6 100644 (file)
@@ -44,6 +44,11 @@ struct private_delete_child_sa_job_t {
         * inbound SPI of the CHILD_SA
         */
        u_int32_t spi;
+
+       /**
+        * Delete for an expired CHILD_SA
+        */
+       bool expired;
 };
 
 METHOD(job_t, destroy, void,
@@ -66,7 +71,7 @@ METHOD(job_t, execute, void,
        }
        else
        {
-               ike_sa->delete_child_sa(ike_sa, this->protocol, this->spi);
+               ike_sa->delete_child_sa(ike_sa, this->protocol, this->spi, this->expired);
 
                charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
        }
@@ -83,8 +88,7 @@ METHOD(job_t, get_priority, job_priority_t,
  * Described in header
  */
 delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid,
-                                                                                                 protocol_id_t protocol,
-                                                                                                 u_int32_t spi)
+                                                       protocol_id_t protocol, u_int32_t spi, bool expired)
 {
        private_delete_child_sa_job_t *this;
 
@@ -99,6 +103,7 @@ delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid,
                .reqid = reqid,
                .protocol = protocol,
                .spi = spi,
+               .expired = expired,
        );
 
        return &this->public;
index fc0e2b5..be6d578 100644 (file)
@@ -50,10 +50,10 @@ struct delete_child_sa_job_t {
  * @param reqid                reqid of the CHILD_SA, as used in kernel
  * @param protocol     protocol of the CHILD_SA
  * @param spi          security parameter index of the CHILD_SA
+ * @param expired      TRUE if CHILD_SA already expired
  * @return                     delete_child_sa_job_t object
  */
 delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid,
-                                                                                                 protocol_id_t protocol,
-                                                                                                 u_int32_t spi);
+                                                       protocol_id_t protocol, u_int32_t spi, bool expired);
 
 #endif /** DELETE_CHILD_SA_JOB_H_ @}*/
index 251b9ab..55fc009 100644 (file)
@@ -108,7 +108,7 @@ METHOD(job_t, execute, void,
                        {
                                DBG1(DBG_JOB, "deleting CHILD_SA after %d seconds "
                                         "of inactivity", this->timeout);
-                               status = ike_sa->delete_child_sa(ike_sa, proto, delete);
+                               status = ike_sa->delete_child_sa(ike_sa, proto, delete, FALSE);
                        }
                }
                if (status == DESTROY_ME)
index 442eb72..e5b2f8f 100644 (file)
@@ -1256,9 +1256,10 @@ METHOD(ike_sa_t, rekey_child_sa, status_t,
 }
 
 METHOD(ike_sa_t, delete_child_sa, status_t,
-       private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi)
+       private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi, bool expired)
 {
-       this->task_manager->queue_child_delete(this->task_manager, protocol, spi);
+       this->task_manager->queue_child_delete(this->task_manager,
+                                                                                  protocol, spi, expired);
        return this->task_manager->initiate(this->task_manager);
 }
 
index e503564..c5bf60b 100644 (file)
@@ -845,11 +845,13 @@ struct ike_sa_t {
         *
         * @param protocol              protocol of the SA
         * @param spi                   inbound SPI of the CHILD_SA
+        * @param expired               TRUE if CHILD_SA is expired
         * @return
         *                                              - NOT_FOUND, if IKE_SA has no such CHILD_SA
         *                                              - SUCCESS, if delete message sent
         */
-       status_t (*delete_child_sa) (ike_sa_t *this, protocol_id_t protocol, u_int32_t spi);
+       status_t (*delete_child_sa)(ike_sa_t *this, protocol_id_t protocol,
+                                                               u_int32_t spi, bool expired);
 
        /**
         * Destroy a CHILD SA with the specified protocol/SPI.
index ea4cb8a..3a6cf51 100644 (file)
@@ -1141,7 +1141,7 @@ METHOD(task_manager_t, queue_ike_delete, void,
        {
                queue_task(this, (task_t*)
                        quick_delete_create(this->ike_sa, child_sa->get_protocol(child_sa),
-                                                               child_sa->get_spi(child_sa, TRUE), FALSE));
+                                                               child_sa->get_spi(child_sa, TRUE), FALSE, FALSE));
        }
        enumerator->destroy(enumerator);
 
@@ -1190,10 +1190,11 @@ METHOD(task_manager_t, queue_child_rekey, void,
 }
 
 METHOD(task_manager_t, queue_child_delete, void,
-       private_task_manager_t *this, protocol_id_t protocol, u_int32_t spi)
+       private_task_manager_t *this, protocol_id_t protocol, u_int32_t spi,
+       bool expired)
 {
        queue_task(this, (task_t*)quick_delete_create(this->ike_sa, protocol,
-                                                                                                 spi, FALSE));
+                                                                                                 spi, FALSE, expired));
 }
 
 METHOD(task_manager_t, queue_dpd, void,
index 9de5c2e..999b497 100644 (file)
@@ -108,7 +108,7 @@ METHOD(task_t, process_r, status_t,
                                        else
                                        {
                                                this->del = (task_t*)quick_delete_create(this->ike_sa,
-                                                                                                               PROTO_NONE, 0, FALSE);
+                                                                                               PROTO_NONE, 0, FALSE, FALSE);
                                        }
                                }
                                break;
index bb7d20b..9a502f5 100644 (file)
@@ -54,6 +54,11 @@ struct private_quick_delete_t {
         * Send delete even if SA does not exist
         */
        bool force;
+
+       /**
+        * SA already expired?
+        */
+       bool expired;
 };
 
 /**
@@ -78,16 +83,29 @@ static bool delete_child(private_quick_delete_t *this,
 
        child_sa->set_state(child_sa, CHILD_DELETING);
 
-       child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in);
-       child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out);
-
-       DBG0(DBG_IKE, "closing CHILD_SA %s{%d} "
-                "with SPIs %.8x_i (%llu bytes) %.8x_o (%llu bytes) and TS %#R=== %#R",
-                child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
-                ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in,
-                ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out,
-                child_sa->get_traffic_selectors(child_sa, TRUE),
-                child_sa->get_traffic_selectors(child_sa, FALSE));
+       if (this->expired)
+       {
+               DBG0(DBG_IKE, "closing expired CHILD_SA %s{%d} "
+                        "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
+                        child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
+                        ntohl(child_sa->get_spi(child_sa, TRUE)),
+                        ntohl(child_sa->get_spi(child_sa, FALSE)),
+                        child_sa->get_traffic_selectors(child_sa, TRUE),
+                        child_sa->get_traffic_selectors(child_sa, FALSE));
+       }
+       else
+       {
+               child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in);
+               child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out);
+
+               DBG0(DBG_IKE, "closing CHILD_SA %s{%d} with SPIs "
+                        "%.8x_i (%llu bytes) %.8x_o (%llu bytes) and TS %#R=== %#R",
+                        child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
+                        ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in,
+                        ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out,
+                        child_sa->get_traffic_selectors(child_sa, TRUE),
+                        child_sa->get_traffic_selectors(child_sa, FALSE));
+       }
 
        charon->bus->child_updown(charon->bus, child_sa, FALSE);
 
@@ -190,7 +208,7 @@ METHOD(task_t, destroy, void,
  * Described in header.
  */
 quick_delete_t *quick_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
-                                                                       u_int32_t spi, bool force)
+                                                                       u_int32_t spi, bool force, bool expired)
 {
        private_quick_delete_t *this;
 
@@ -206,6 +224,7 @@ quick_delete_t *quick_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
                .protocol = protocol,
                .spi = spi,
                .force = force,
+               .expired = expired,
        );
 
        if (protocol != PROTO_NONE)
index 1cdf07c..8642623 100644 (file)
@@ -46,9 +46,10 @@ struct quick_delete_t {
  * @param protocol             protocol of CHILD_SA to delete, PROTO_NONE as responder
  * @param spi                  inbound SPI of CHILD_SA to delete
  * @param force                        send delete even if SA does not exist
+ * @param expired              TRUE if SA already expired
  * @return                             quick_delete task to handle by the task_manager
  */
 quick_delete_t *quick_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
-                                                                       u_int32_t spi, bool force);
+                                                                       u_int32_t spi, bool force, bool expired);
 
 #endif /** QUICK_DELETE_H_ @}*/
index b9acdb0..dc0a010 100644 (file)
@@ -773,7 +773,7 @@ METHOD(task_t, process_r, status_t,
                                this->ike_sa->queue_task(this->ike_sa,
                                        (task_t*)quick_delete_create(this->ike_sa,
                                                                this->proposal->get_protocol(this->proposal),
-                                                               this->spi_i, TRUE));
+                                                               this->spi_i, TRUE, TRUE));
                                return ALREADY_DONE;
                        }
                        return SUCCESS;
index 23ef054..36252a8 100644 (file)
@@ -825,7 +825,7 @@ static status_t process_request(private_task_manager_t *this,
                                                        else
                                                        {
                                                                task = (task_t*)child_delete_create(this->ike_sa,
-                                                                                                                               PROTO_NONE, 0);
+                                                                                                               PROTO_NONE, 0, FALSE);
                                                        }
                                                        break;
                                                }
@@ -1308,9 +1308,11 @@ METHOD(task_manager_t, queue_child_rekey, void,
 }
 
 METHOD(task_manager_t, queue_child_delete, void,
-       private_task_manager_t *this, protocol_id_t protocol, u_int32_t spi)
+       private_task_manager_t *this, protocol_id_t protocol, u_int32_t spi,
+       bool expired)
 {
-       queue_task(this, (task_t*)child_delete_create(this->ike_sa, protocol, spi));
+       queue_task(this, (task_t*)child_delete_create(this->ike_sa,
+                                                                                                 protocol, spi, expired));
 }
 
 METHOD(task_manager_t, queue_dpd, void,
index c5151ab..644af78 100644 (file)
@@ -62,6 +62,11 @@ struct private_child_delete_t {
        bool rekeyed;
 
        /**
+        * CHILD_SA already expired?
+        */
+       bool expired;
+
+       /**
         * CHILD_SAs which get deleted
         */
        linked_list_t *child_sas;
@@ -247,16 +252,29 @@ static void log_children(private_child_delete_t *this)
        enumerator = this->child_sas->create_enumerator(this->child_sas);
        while (enumerator->enumerate(enumerator, (void**)&child_sa))
        {
-               child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in);
-               child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out);
-
-               DBG0(DBG_IKE, "closing CHILD_SA %s{%d} "
-                        "with SPIs %.8x_i (%llu bytes) %.8x_o (%llu bytes) and TS %#R=== %#R",
-                        child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
-                        ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in,
-                        ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out,
-                        child_sa->get_traffic_selectors(child_sa, TRUE),
-                        child_sa->get_traffic_selectors(child_sa, FALSE));
+               if (this->expired)
+               {
+                       DBG0(DBG_IKE, "closing expired CHILD_SA %s{%d} "
+                                "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
+                                child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
+                                ntohl(child_sa->get_spi(child_sa, TRUE)),
+                                ntohl(child_sa->get_spi(child_sa, FALSE)),
+                                child_sa->get_traffic_selectors(child_sa, TRUE),
+                                child_sa->get_traffic_selectors(child_sa, FALSE));
+               }
+               else
+               {
+                       child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in);
+                       child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out);
+
+                       DBG0(DBG_IKE, "closing CHILD_SA %s{%d} with SPIs %.8x_i "
+                                "(%llu bytes) %.8x_o (%llu bytes) and TS %#R=== %#R",
+                                child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
+                                ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in,
+                                ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out,
+                                child_sa->get_traffic_selectors(child_sa, TRUE),
+                                child_sa->get_traffic_selectors(child_sa, FALSE));
+               }
        }
        enumerator->destroy(enumerator);
 }
@@ -356,7 +374,7 @@ METHOD(task_t, destroy, void,
  * Described in header.
  */
 child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
-                                                                       u_int32_t spi)
+                                                                       u_int32_t spi, bool expired)
 {
        private_child_delete_t *this;
 
@@ -373,6 +391,7 @@ child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
                .child_sas = linked_list_create(),
                .protocol = protocol,
                .spi = spi,
+               .expired = expired,
        );
 
        if (protocol != PROTO_NONE)
index 34d399c..4c8b349 100644 (file)
@@ -52,9 +52,10 @@ struct child_delete_t {
  * @param ike_sa               IKE_SA this task works for
  * @param protocol             protocol of CHILD_SA to delete, PROTO_NONE as responder
  * @param spi                  inbound SPI of CHILD_SA to delete
+ * @param expired              TRUE if CHILD_SA already expired
  * @return                             child_delete task to handle by the task_manager
  */
 child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
-                                                                       u_int32_t spi);
+                                                                       u_int32_t spi, bool expired);
 
 #endif /** CHILD_DELETE_H_ @}*/
index 50a8aad..28de072 100644 (file)
@@ -352,7 +352,7 @@ METHOD(task_t, process_i, status_t,
        protocol = to_delete->get_protocol(to_delete);
 
        /* rekeying done, delete the obsolete CHILD_SA using a subtask */
-       this->child_delete = child_delete_create(this->ike_sa, protocol, spi);
+       this->child_delete = child_delete_create(this->ike_sa, protocol, spi, FALSE);
        this->public.task.build = (status_t(*)(task_t*,message_t*))build_i_delete;
        this->public.task.process = (status_t(*)(task_t*,message_t*))process_i_delete;
 
index 5602069..b49c9a9 100644 (file)
@@ -177,9 +177,10 @@ struct task_manager_t {
         *
         * @param protocol              CHILD_SA protocol, AH|ESP
         * @param spi                   CHILD_SA SPI to rekey
+        * @param expired               TRUE if SA already expired
         */
        void (*queue_child_delete)(task_manager_t *this, protocol_id_t protocol,
-                                                          u_int32_t spi);
+                                                          u_int32_t spi, bool expired);
 
        /**
         * Queue liveness checking tasks.