summaryrefslogtreecommitdiff
path: root/src/libcharon/sa/child_sa.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/sa/child_sa.c')
-rw-r--r--src/libcharon/sa/child_sa.c178
1 files changed, 91 insertions, 87 deletions
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index 73f2ec9d3..b0f163c83 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -413,8 +413,14 @@ METHOD(enumerator_t, policy_enumerate, bool,
{ /* protocol mismatch */
continue;
}
- *my_out = this->ts;
- *other_out = other_ts;
+ if (my_out)
+ {
+ *my_out = this->ts;
+ }
+ if (other_out)
+ {
+ *other_out = other_ts;
+ }
return TRUE;
}
return FALSE;
@@ -775,6 +781,50 @@ static bool require_policy_update()
}
/**
+ * Prepare SA config to install/delete policies
+ */
+static void prepare_sa_cfg(private_child_sa_t *this, ipsec_sa_cfg_t *my_sa,
+ ipsec_sa_cfg_t *other_sa)
+{
+ enumerator_t *enumerator;
+
+ *my_sa = (ipsec_sa_cfg_t){
+ .mode = this->mode,
+ .reqid = this->reqid,
+ .ipcomp = {
+ .transform = this->ipcomp,
+ },
+ };
+ *other_sa = *my_sa;
+
+ my_sa->ipcomp.cpi = this->my_cpi;
+ other_sa->ipcomp.cpi = this->other_cpi;
+
+ if (this->protocol == PROTO_ESP)
+ {
+ my_sa->esp.use = TRUE;
+ my_sa->esp.spi = this->my_spi;
+ other_sa->esp.use = TRUE;
+ other_sa->esp.spi = this->other_spi;
+ }
+ else
+ {
+ my_sa->ah.use = TRUE;
+ my_sa->ah.spi = this->my_spi;
+ other_sa->ah.use = TRUE;
+ other_sa->ah.spi = this->other_spi;
+ }
+
+ enumerator = create_policy_enumerator(this);
+ while (enumerator->enumerate(enumerator, NULL, NULL))
+ {
+ my_sa->policy_count++;
+ other_sa->policy_count++;
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
* Install 3 policies: out, in and forward
*/
static status_t install_policies_internal(private_child_sa_t *this,
@@ -806,20 +856,22 @@ static status_t install_policies_internal(private_child_sa_t *this,
* Delete 3 policies: out, in and forward
*/
static void del_policies_internal(private_child_sa_t *this,
- traffic_selector_t *my_ts, traffic_selector_t *other_ts,
- policy_priority_t priority)
+ host_t *my_addr, host_t *other_addr, traffic_selector_t *my_ts,
+ traffic_selector_t *other_ts, ipsec_sa_cfg_t *my_sa,
+ ipsec_sa_cfg_t *other_sa, policy_type_t type, policy_priority_t priority)
{
+
hydra->kernel_interface->del_policy(hydra->kernel_interface,
- my_ts, other_ts, POLICY_OUT, this->reqid,
- this->mark_out, priority);
+ my_addr, other_addr, my_ts, other_ts, POLICY_OUT, type,
+ other_sa, this->mark_out, priority);
hydra->kernel_interface->del_policy(hydra->kernel_interface,
- other_ts, my_ts, POLICY_IN, this->reqid,
- this->mark_in, priority);
+ other_addr, my_addr, other_ts, my_ts, POLICY_IN,
+ type, my_sa, this->mark_in, priority);
if (this->mode != MODE_TRANSPORT)
{
hydra->kernel_interface->del_policy(hydra->kernel_interface,
- other_ts, my_ts, POLICY_FWD, this->reqid,
- this->mark_in, priority);
+ other_addr, my_addr, other_ts, my_ts, POLICY_FWD,
+ type, my_sa, this->mark_in, priority);
}
}
@@ -864,31 +916,9 @@ METHOD(child_sa_t, add_policies, status_t,
if (this->config->install_policy(this->config))
{
policy_priority_t priority;
- ipsec_sa_cfg_t my_sa = {
- .mode = this->mode,
- .reqid = this->reqid,
- .ipcomp = {
- .transform = this->ipcomp,
- },
- }, other_sa = my_sa;
-
- my_sa.ipcomp.cpi = this->my_cpi;
- other_sa.ipcomp.cpi = this->other_cpi;
-
- if (this->protocol == PROTO_ESP)
- {
- my_sa.esp.use = TRUE;
- my_sa.esp.spi = this->my_spi;
- other_sa.esp.use = TRUE;
- other_sa.esp.spi = this->other_spi;
- }
- else
- {
- my_sa.ah.use = TRUE;
- my_sa.ah.spi = this->my_spi;
- other_sa.ah.use = TRUE;
- other_sa.ah.spi = this->other_spi;
- }
+ ipsec_sa_cfg_t my_sa, other_sa;
+
+ prepare_sa_cfg(this, &my_sa, &other_sa);
/* if we're not in state CHILD_INSTALLING (i.e. if there is no SAD
* entry) we install a trap policy */
@@ -896,14 +926,6 @@ METHOD(child_sa_t, add_policies, status_t,
priority = this->trap ? POLICY_PRIORITY_ROUTED
: POLICY_PRIORITY_DEFAULT;
- enumerator = create_policy_enumerator(this);
- while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
- {
- my_sa.policy_count++;
- other_sa.policy_count++;
- }
- enumerator->destroy(enumerator);
-
/* enumerate pairs of traffic selectors */
enumerator = create_policy_enumerator(this);
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
@@ -1006,47 +1028,24 @@ METHOD(child_sa_t, update, status_t,
if (this->config->install_policy(this->config) && require_policy_update())
{
- ipsec_sa_cfg_t my_sa = {
- .mode = this->mode,
- .reqid = this->reqid,
- .ipcomp = {
- .transform = this->ipcomp,
- },
- }, other_sa = my_sa;
-
- my_sa.ipcomp.cpi = this->my_cpi;
- other_sa.ipcomp.cpi = this->other_cpi;
-
- if (this->protocol == PROTO_ESP)
- {
- my_sa.esp.use = TRUE;
- my_sa.esp.spi = this->my_spi;
- other_sa.esp.use = TRUE;
- other_sa.esp.spi = this->other_spi;
- }
- else
- {
- my_sa.ah.use = TRUE;
- my_sa.ah.spi = this->my_spi;
- other_sa.ah.use = TRUE;
- other_sa.ah.spi = this->other_spi;
- }
-
- /* update policies */
if (!me->ip_equals(me, this->my_addr) ||
!other->ip_equals(other, this->other_addr))
{
+ ipsec_sa_cfg_t my_sa, other_sa;
enumerator_t *enumerator;
traffic_selector_t *my_ts, *other_ts;
+ prepare_sa_cfg(this, &my_sa, &other_sa);
+
/* always use high priorities, as hosts getting updated are INSTALLED */
enumerator = create_policy_enumerator(this);
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
traffic_selector_t *old_my_ts = NULL, *old_other_ts = NULL;
/* remove old policies first */
- del_policies_internal(this, my_ts, other_ts,
- POLICY_PRIORITY_DEFAULT);
+ del_policies_internal(this, this->my_addr, this->other_addr,
+ my_ts, other_ts, &my_sa, &other_sa,
+ POLICY_IPSEC, POLICY_PRIORITY_DEFAULT);
/* check if we have to update a "dynamic" traffic selector */
if (!me->ip_equals(me, this->my_addr) &&
@@ -1068,21 +1067,20 @@ METHOD(child_sa_t, update, status_t,
/* reinstall updated policies */
install_policies_internal(this, me, other, my_ts, other_ts,
- &my_sa, &other_sa, POLICY_IPSEC,
- POLICY_PRIORITY_DEFAULT);
+ &my_sa, &other_sa, POLICY_IPSEC,
+ POLICY_PRIORITY_DEFAULT);
/* update fallback policies after the new policy is in place */
- if (old_my_ts || old_other_ts)
- {
- del_policies_internal(this, old_my_ts ?: my_ts,
- old_other_ts ?: other_ts,
+ del_policies_internal(this, this->my_addr, this->other_addr,
+ old_my_ts ?: my_ts,
+ old_other_ts ?: other_ts,
+ &my_sa, &other_sa, POLICY_DROP,
+ POLICY_PRIORITY_FALLBACK);
+ install_policies_internal(this, me, other, my_ts, other_ts,
+ &my_sa, &other_sa, POLICY_DROP,
POLICY_PRIORITY_FALLBACK);
- install_policies_internal(this, me, other, my_ts, other_ts,
- &my_sa, &other_sa, POLICY_DROP,
- POLICY_PRIORITY_FALLBACK);
- DESTROY_IF(old_my_ts);
- DESTROY_IF(old_other_ts);
- }
+ DESTROY_IF(old_my_ts);
+ DESTROY_IF(old_other_ts);
}
enumerator->destroy(enumerator);
}
@@ -1122,15 +1120,21 @@ METHOD(child_sa_t, destroy, void,
if (this->config->install_policy(this->config))
{
+ ipsec_sa_cfg_t my_sa, other_sa;
+
+ prepare_sa_cfg(this, &my_sa, &other_sa);
+
/* delete all policies in the kernel */
enumerator = create_policy_enumerator(this);
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
- del_policies_internal(this, my_ts, other_ts, priority);
+ del_policies_internal(this, this->my_addr, this->other_addr,
+ my_ts, other_ts, &my_sa, &other_sa, POLICY_IPSEC, priority);
if (priority == POLICY_PRIORITY_DEFAULT && require_policy_update())
{
- del_policies_internal(this, my_ts, other_ts,
- POLICY_PRIORITY_FALLBACK);
+ del_policies_internal(this, this->my_addr, this->other_addr,
+ my_ts, other_ts, &my_sa, &other_sa, POLICY_DROP,
+ POLICY_PRIORITY_FALLBACK);
}
}
enumerator->destroy(enumerator);