child-sa: Install outbound SA immediately if kernel supports SPIs on policies
authorTobias Brunner <tobias@strongswan.org>
Tue, 11 Jul 2017 11:42:06 +0000 (13:42 +0200)
committerTobias Brunner <tobias@strongswan.org>
Mon, 7 Aug 2017 08:44:05 +0000 (10:44 +0200)
src/libcharon/sa/child_sa.c
src/libcharon/sa/child_sa.h
src/libcharon/sa/ikev2/tasks/child_create.c

index 77d71ab..6c6804c 100644 (file)
@@ -1271,21 +1271,35 @@ METHOD(child_sa_t, install_policies, status_t,
        return status;
 }
 
-METHOD(child_sa_t, register_outbound, void,
+METHOD(child_sa_t, register_outbound, status_t,
        private_child_sa_t *this, chunk_t encr, chunk_t integ, uint32_t spi,
        uint16_t cpi, bool tfcv3)
 {
-       DBG2(DBG_CHD, "registering outbound %N SA", protocol_id_names,
-                this->protocol);
-       DBG2(DBG_CHD, "  SPI 0x%.8x, src %H dst %H", ntohl(spi), this->my_addr,
-                this->other_addr);
-
-       this->other_spi = spi;
-       this->other_cpi = cpi;
-       this->encr_r = chunk_clone(encr);
-       this->integ_r = chunk_clone(integ);
-       this->tfcv3 = tfcv3;
+       status_t status;
+
+       /* if the kernel supports installing SPIs with policies we install the
+        * SA immediately as it will only be used once we update the policies */
+       if (charon->kernel->get_features(charon->kernel) & KERNEL_POLICY_SPI)
+       {
+               status = install_internal(this, encr, integ, spi, cpi, FALSE, FALSE,
+                                                                 tfcv3);
+       }
+       else
+       {
+               DBG2(DBG_CHD, "registering outbound %N SA", protocol_id_names,
+                        this->protocol);
+               DBG2(DBG_CHD, "  SPI 0x%.8x, src %H dst %H", ntohl(spi), this->my_addr,
+                        this->other_addr);
+
+               this->other_spi = spi;
+               this->other_cpi = cpi;
+               this->encr_r = chunk_clone(encr);
+               this->integ_r = chunk_clone(integ);
+               this->tfcv3 = tfcv3;
+               status = SUCCESS;
+       }
        this->outbound_state |= CHILD_OUTBOUND_REGISTERED;
+       return status;
 }
 
 METHOD(child_sa_t, install_outbound, status_t,
@@ -1295,18 +1309,21 @@ METHOD(child_sa_t, install_outbound, status_t,
        traffic_selector_t *my_ts, *other_ts;
        status_t status = SUCCESS;
 
-       status = install_internal(this, this->encr_r, this->integ_r,
-                                                         this->other_spi, this->other_cpi, FALSE,
-                                                         FALSE, this->tfcv3);
-       chunk_clear(&this->encr_r);
-       chunk_clear(&this->integ_r);
+       if (!(this->outbound_state & CHILD_OUTBOUND_SA))
+       {
+               status = install_internal(this, this->encr_r, this->integ_r,
+                                                                 this->other_spi, this->other_cpi, FALSE,
+                                                                 FALSE, this->tfcv3);
+               chunk_clear(&this->encr_r);
+               chunk_clear(&this->integ_r);
+       }
        this->outbound_state &= ~CHILD_OUTBOUND_REGISTERED;
        if (status != SUCCESS)
        {
                return status;
        }
-       this->outbound_state |= CHILD_OUTBOUND_POLICIES;
-       if (!this->config->has_option(this->config, OPT_NO_POLICIES))
+       if (!this->config->has_option(this->config, OPT_NO_POLICIES) &&
+               !(this->outbound_state & CHILD_OUTBOUND_POLICIES))
        {
                ipsec_sa_cfg_t my_sa, other_sa;
                uint32_t manual_prio;
@@ -1337,6 +1354,7 @@ METHOD(child_sa_t, install_outbound, status_t,
                }
                enumerator->destroy(enumerator);
        }
+       this->outbound_state |= CHILD_OUTBOUND_POLICIES;
        return status;
 }
 
index e41157e..082404d 100644 (file)
@@ -411,20 +411,23 @@ struct child_sa_t {
         * Register data for the installation of an outbound SA as responder during
         * a rekeying.
         *
-        * The SA is not installed until install_outbound() is called.
+        * If the kernel is able to handle SPIs on policies the SA is installed
+        * immediately, if not it won't be installed until install_outbound() is
+        * called.
         *
         * @param encr          encryption key, if any (cloned)
         * @param integ         integrity key (cloned)
         * @param spi           SPI to use, allocated for inbound
         * @param cpi           CPI to use, allocated for outbound
         * @param tfcv3         TRUE if peer supports ESPv3 TFC
+        * @return                      SUCCESS or FAILED
         */
-       void (*register_outbound)(child_sa_t *this, chunk_t encr, chunk_t integ,
-                                                         uint32_t spi, uint16_t cpi, bool tfcv3);
+       status_t (*register_outbound)(child_sa_t *this, chunk_t encr, chunk_t integ,
+                                                                 uint32_t spi, uint16_t cpi, bool tfcv3);
 
        /**
-        * Install the outbound SA and the outbound policies as responder during a
-        * rekeying.
+        * Install the outbound policies and, if not already done, the outbound SA
+        * as responder during a rekeying.
         *
         * @return                      SUCCESS or FAILED
         */
index 747b9fa..9d7d08c 100644 (file)
@@ -698,9 +698,9 @@ static status_t select_and_install(private_child_create_t *this,
                        status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
                                                        this->my_spi, this->my_cpi, this->initiator,
                                                        TRUE, this->tfcv3);
-                       this->child_sa->register_outbound(this->child_sa, encr_r, integ_r,
-                                                       this->other_spi, this->other_cpi, this->tfcv3);
-                       status_o = SUCCESS;
+                       status_o = this->child_sa->register_outbound(this->child_sa, encr_r,
+                                                       integ_r, this->other_spi, this->other_cpi,
+                                                       this->tfcv3);
                }
        }