aboutsummaryrefslogtreecommitdiffstats
path: root/src/charon/sa/child_sa.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/charon/sa/child_sa.c')
-rw-r--r--src/charon/sa/child_sa.c118
1 files changed, 52 insertions, 66 deletions
diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c
index 24d91a5da..95c7735de 100644
--- a/src/charon/sa/child_sa.c
+++ b/src/charon/sa/child_sa.c
@@ -30,6 +30,7 @@
ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING,
"CREATED",
"ROUTED",
+ "INSTALLING",
"INSTALLED",
"UPDATING",
"REKEYING",
@@ -444,7 +445,7 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal,
ipsec_mode_t mode, chunk_t integ, chunk_t encr, bool in)
{
u_int16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size;
- u_int32_t spi, cpi, soft, hard, now;
+ u_int32_t spi, soft, hard, now;
host_t *src, *dst;
status_t status;
@@ -461,7 +462,7 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal,
if (this->alloc_ah_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->my_addr, this->alloc_ah_spi, PROTO_AH);
+ this->my_addr, this->alloc_ah_spi, 0, PROTO_AH);
}
}
else
@@ -470,7 +471,7 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal,
if (this->alloc_esp_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->my_addr, this->alloc_esp_spi, PROTO_ESP);
+ this->my_addr, this->alloc_esp_spi, 0, PROTO_ESP);
}
}
spi = this->my_spi;
@@ -491,16 +492,6 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal,
/* send SA down to the kernel */
DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
- if (this->ipcomp != IPCOMP_NONE)
- {
- /* we install an additional IPComp SA */
- cpi = htonl(ntohs(in ? this->my_cpi : this->other_cpi));
- charon->kernel_interface->add_sa(charon->kernel_interface,
- src, dst, cpi, IPPROTO_COMP, this->reqid, 0, 0,
- ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty,
- mode, this->ipcomp, FALSE, in);
- }
-
proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &enc_alg, &size);
proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &int_alg, &size);
@@ -509,7 +500,8 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal,
status = charon->kernel_interface->add_sa(charon->kernel_interface,
src, dst, spi, this->protocol, this->reqid,
in ? soft : 0, hard, enc_alg, encr, int_alg, integ,
- mode, IPCOMP_NONE, this->encap, in);
+ mode, this->ipcomp, in ? this->my_cpi : this->other_cpi,
+ this->encap, in);
now = time(NULL);
this->rekey_time = now + soft;
@@ -588,12 +580,8 @@ static status_t add_policies(private_child_sa_t *this,
enumerator_t *enumerator;
traffic_selector_t *my_ts, *other_ts;
status_t status = SUCCESS;
- bool high_prio = TRUE;
+ bool routed = (this->state == CHILD_CREATED);
- if (this->state == CHILD_CREATED)
- { /* use low prio for ROUTED policies */
- high_prio = FALSE;
- }
if (this->protocol == PROTO_NONE)
{ /* update if not set yet */
this->protocol = proto;
@@ -622,17 +610,20 @@ static status_t add_policies(private_child_sa_t *this,
/* install 3 policies: out, in and forward */
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->my_addr, this->other_addr, my_ts, other_ts, POLICY_OUT,
- this->protocol, this->reqid, high_prio, mode, this->ipcomp);
-
+ this->other_spi, this->protocol, this->reqid, mode, this->ipcomp,
+ this->other_cpi, routed);
+
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->other_addr, this->my_addr, other_ts, my_ts, POLICY_IN,
- this->protocol, this->reqid, high_prio, mode, this->ipcomp);
+ this->my_spi, this->protocol, this->reqid, mode, this->ipcomp,
+ this->my_cpi, routed);
if (mode == MODE_TUNNEL)
{
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
- this->other_addr, this->my_addr, other_ts, my_ts, POLICY_FWD,
- this->protocol, this->reqid, high_prio, mode, this->ipcomp);
+ this->other_addr, this->my_addr, other_ts, my_ts, POLICY_FWD,
+ this->my_spi, this->protocol, this->reqid, mode, this->ipcomp,
+ this->my_cpi, routed);
}
if (status != SUCCESS)
@@ -682,26 +673,23 @@ static status_t update_hosts(private_child_sa_t *this,
old = this->state;
set_state(this, CHILD_UPDATING);
- this->encap = encap;
-
- if (this->ipcomp != IPCOMP_NONE)
+ /* update our (initator) SA */
+ if (charon->kernel_interface->update_sa(charon->kernel_interface, this->my_spi,
+ this->protocol, this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
+ this->other_addr, this->my_addr, other, me,
+ this->encap, encap) == NOT_SUPPORTED)
{
- /* update our (initator) IPComp SA */
- charon->kernel_interface->update_sa(charon->kernel_interface,
- htonl(ntohs(this->my_cpi)), IPPROTO_COMP,
- this->other_addr, this->my_addr, other, me, FALSE);
- /* update his (responder) IPComp SA */
- charon->kernel_interface->update_sa(charon->kernel_interface,
- htonl(ntohs(this->other_cpi)), IPPROTO_COMP,
- this->my_addr, this->other_addr, me, other, FALSE);
+ return NOT_SUPPORTED;
}
- /* update our (initator) SA */
- charon->kernel_interface->update_sa(charon->kernel_interface, this->my_spi,
- this->protocol, this->other_addr, this->my_addr, other, me, encap);
/* update his (responder) SA */
- charon->kernel_interface->update_sa(charon->kernel_interface, this->other_spi,
- this->protocol, this->my_addr, this->other_addr, me, other, encap);
+ if (charon->kernel_interface->update_sa(charon->kernel_interface, this->other_spi,
+ this->protocol, this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
+ this->my_addr, this->other_addr, me, other,
+ this->encap, encap) == NOT_SUPPORTED)
+ {
+ return NOT_SUPPORTED;
+ }
if (this->config->install_policy(this->config))
{
@@ -718,13 +706,13 @@ static status_t update_hosts(private_child_sa_t *this,
{
/* remove old policies first */
charon->kernel_interface->del_policy(charon->kernel_interface,
- my_ts, other_ts, POLICY_OUT);
+ my_ts, other_ts, POLICY_OUT, FALSE);
charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_IN);
+ other_ts, my_ts, POLICY_IN, FALSE);
if (this->mode == MODE_TUNNEL)
{
charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_FWD);
+ other_ts, my_ts, POLICY_FWD, FALSE);
}
/* check whether we have to update a "dynamic" traffic selector */
@@ -749,16 +737,19 @@ static status_t update_hosts(private_child_sa_t *this,
/* reinstall updated policies */
charon->kernel_interface->add_policy(charon->kernel_interface,
- me, other, my_ts, other_ts, POLICY_OUT, this->protocol,
- this->reqid, TRUE, this->mode, this->ipcomp);
+ me, other, my_ts, other_ts, POLICY_OUT, this->other_spi,
+ this->protocol, this->reqid, this->mode, this->ipcomp,
+ this->other_cpi, FALSE);
charon->kernel_interface->add_policy(charon->kernel_interface,
- other, me, other_ts, my_ts, POLICY_IN, this->protocol,
- this->reqid, TRUE, this->mode, this->ipcomp);
+ other, me, other_ts, my_ts, POLICY_IN, this->my_spi,
+ this->protocol, this->reqid, this->mode, this->ipcomp,
+ this->my_cpi, FALSE);
if (this->mode == MODE_TUNNEL)
{
charon->kernel_interface->add_policy(charon->kernel_interface,
- other, me, other_ts, my_ts, POLICY_FWD, this->protocol,
- this->reqid, TRUE, this->mode, this->ipcomp);
+ other, me, other_ts, my_ts, POLICY_FWD, this->my_spi,
+ this->protocol, this->reqid, this->mode, this->ipcomp,
+ this->my_cpi, FALSE);
}
}
enumerator->destroy(enumerator);
@@ -779,6 +770,8 @@ static status_t update_hosts(private_child_sa_t *this,
this->other_addr = other->clone(other);
}
}
+ this->encap = encap;
+
set_state(this, old);
return SUCCESS;
@@ -815,6 +808,7 @@ static void destroy(private_child_sa_t *this)
{
enumerator_t *enumerator;
traffic_selector_t *my_ts, *other_ts;
+ bool unrouted = (this->state == CHILD_ROUTED);
set_state(this, CHILD_DESTROYING);
@@ -822,32 +816,24 @@ static void destroy(private_child_sa_t *this)
if (this->my_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->my_addr, this->my_spi, this->protocol);
+ this->my_addr, this->my_spi, this->protocol,
+ this->my_cpi);
}
if (this->alloc_esp_spi && this->alloc_esp_spi != this->my_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->my_addr, this->alloc_esp_spi, PROTO_ESP);
+ this->my_addr, this->alloc_esp_spi, PROTO_ESP, 0);
}
if (this->alloc_ah_spi && this->alloc_ah_spi != this->my_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->my_addr, this->alloc_ah_spi, PROTO_AH);
+ this->my_addr, this->alloc_ah_spi, PROTO_AH, 0);
}
if (this->other_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->other_addr, this->other_spi, this->protocol);
- }
- if (this->my_cpi)
- {
- charon->kernel_interface->del_sa(charon->kernel_interface,
- this->my_addr, htonl(ntohs(this->my_cpi)), IPPROTO_COMP);
- }
- if (this->other_cpi)
- {
- charon->kernel_interface->del_sa(charon->kernel_interface,
- this->other_addr, htonl(ntohs(this->other_cpi)), IPPROTO_COMP);
+ this->other_addr, this->other_spi, this->protocol,
+ this->other_cpi);
}
if (this->config->install_policy(this->config))
@@ -857,13 +843,13 @@ static void destroy(private_child_sa_t *this)
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
charon->kernel_interface->del_policy(charon->kernel_interface,
- my_ts, other_ts, POLICY_OUT);
+ my_ts, other_ts, POLICY_OUT, unrouted);
charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_IN);
+ other_ts, my_ts, POLICY_IN, unrouted);
if (this->mode == MODE_TUNNEL)
{
charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_FWD);
+ other_ts, my_ts, POLICY_FWD, unrouted);
}
}
enumerator->destroy(enumerator);