aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2017-07-11 13:42:06 +0200
committerTobias Brunner <tobias@strongswan.org>2017-08-07 10:44:05 +0200
commita146b4c9efa46c537d04b5089a54f10dc106e14a (patch)
tree6ee3518c318ffdf0cfd8c5f601924cb8e5b1aa33
parent2c116ef589b76b78216f5c61dfc1afefd3ae8f87 (diff)
downloadstrongswan-a146b4c9efa46c537d04b5089a54f10dc106e14a.tar.bz2
strongswan-a146b4c9efa46c537d04b5089a54f10dc106e14a.tar.xz
child-sa: Install outbound SA immediately if kernel supports SPIs on policies
-rw-r--r--src/libcharon/sa/child_sa.c54
-rw-r--r--src/libcharon/sa/child_sa.h13
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_create.c6
3 files changed, 47 insertions, 26 deletions
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index 77d71ab15..6c6804c64 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -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;
}
diff --git a/src/libcharon/sa/child_sa.h b/src/libcharon/sa/child_sa.h
index e41157e79..082404d93 100644
--- a/src/libcharon/sa/child_sa.h
+++ b/src/libcharon/sa/child_sa.h
@@ -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
*/
diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c
index 747b9fac4..9d7d08c3b 100644
--- a/src/libcharon/sa/ikev2/tasks/child_create.c
+++ b/src/libcharon/sa/ikev2/tasks/child_create.c
@@ -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);
}
}