summaryrefslogtreecommitdiff
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.c169
1 files changed, 117 insertions, 52 deletions
diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c
index b6c71a8b5..2a6b6f67c 100644
--- a/src/charon/sa/child_sa.c
+++ b/src/charon/sa/child_sa.c
@@ -1,13 +1,7 @@
-/**
- * @file child_sa.c
- *
- * @brief Implementation of child_sa_t.
- *
- */
-
/*
+ * Copyright (C) 2006-2008 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
- * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
+ * Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -20,6 +14,8 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
+ *
+ * $Id: child_sa.c 3920 2008-05-08 16:19:11Z tobias $
*/
#define _GNU_SOURCE
@@ -75,6 +71,8 @@ struct private_child_sa_t {
identification_t *id;
/** actual used SPI, 0 if unused */
u_int32_t spi;
+ /** Compression Parameter Index (CPI) used, 0 if unused */
+ u_int16_t cpi;
} me, other;
/**
@@ -115,12 +113,22 @@ struct private_child_sa_t {
/**
* encryption algorithm used for this SA
*/
- algorithm_t encryption;
+ u_int16_t enc_alg;
+
+ /**
+ * key size of enc_alg
+ */
+ u_int16_t enc_size;
/**
* integrity protection algorithm used for this SA
*/
- algorithm_t integrity;
+ u_int16_t int_alg;
+
+ /**
+ * key size of int_alg
+ */
+ u_int16_t int_size;
/**
* time, on which SA was installed
@@ -143,6 +151,16 @@ struct private_child_sa_t {
bool encap;
/**
+ * Specifies the IPComp transform used (IPCOMP_NONE if disabled)
+ */
+ ipcomp_transform_t ipcomp;
+
+ /**
+ * TRUE if we allocated (or tried to allocate) a CPI
+ */
+ bool cpi_allocated;
+
+ /**
* mode this SA uses, tunnel/transport
*/
mode_t mode;
@@ -251,10 +269,10 @@ static void get_stats(private_child_sa_t *this, mode_t *mode,
iterator->destroy(iterator);
*mode = this->mode;
- *encr_algo = this->encryption.algorithm;
- *encr_len = this->encryption.key_size;
- *int_algo = this->integrity.algorithm;
- *int_len = this->integrity.key_size;
+ *encr_algo = this->enc_alg;
+ *encr_len = this->enc_size;
+ *int_algo = this->int_alg;
+ *int_len = this->int_size;
*rekey = this->rekey_time;
*use_in = in;
*use_out = out;
@@ -498,10 +516,7 @@ static status_t alloc(private_child_sa_t *this, linked_list_t *proposals)
static status_t install(private_child_sa_t *this, proposal_t *proposal,
mode_t mode, prf_plus_t *prf_plus, bool mine)
{
- u_int32_t spi, soft, hard;;
- algorithm_t *enc_algo, *int_algo;
- algorithm_t enc_algo_none = {ENCR_UNDEFINED, 0};
- algorithm_t int_algo_none = {AUTH_UNDEFINED, 0};
+ u_int32_t spi, soft, hard;
host_t *src;
host_t *dst;
status_t status;
@@ -549,43 +564,43 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal,
protocol_id_names, this->protocol);
/* select encryption algo */
- if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &enc_algo))
+ if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
+ &this->enc_alg, &this->enc_size))
{
- DBG2(DBG_CHD, " using %N for encryption",
- encryption_algorithm_names, enc_algo->algorithm);
- }
- else
- {
- enc_algo = &enc_algo_none;
+ DBG2(DBG_CHD, " using %N for encryption",
+ encryption_algorithm_names, this->enc_alg);
}
/* select integrity algo */
- if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &int_algo))
+ if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
+ &this->int_alg, &this->int_size))
{
DBG2(DBG_CHD, " using %N for integrity",
- integrity_algorithm_names, int_algo->algorithm);
- }
- else
- {
- int_algo = &int_algo_none;
+ integrity_algorithm_names, this->int_alg);
}
-
soft = this->config->get_lifetime(this->config, TRUE);
hard = this->config->get_lifetime(this->config, FALSE);
/* send SA down to the kernel */
DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
- status = charon->kernel_interface->add_sa(charon->kernel_interface,
- src, dst, spi, this->protocol,
- this->reqid, mine ? soft : 0,
- hard, enc_algo, int_algo,
- prf_plus, mode, this->encap, mine);
- this->encryption = *enc_algo;
- this->integrity = *int_algo;
+ if (this->ipcomp != IPCOMP_NONE)
+ {
+ /* we install an additional IPComp SA */
+ u_int32_t cpi = htonl(ntohs(mine ? this->me.cpi : this->other.cpi));
+ status = charon->kernel_interface->add_sa(charon->kernel_interface,
+ src, dst, cpi, IPPROTO_COMP, this->reqid, 0, 0,
+ ENCR_UNDEFINED, 0, AUTH_UNDEFINED, 0, NULL, mode,
+ this->ipcomp, FALSE, mine);
+ }
+
+ status = charon->kernel_interface->add_sa(charon->kernel_interface,
+ src, dst, spi, this->protocol, this->reqid, mine ? soft : 0, hard,
+ this->enc_alg, this->enc_size, this->int_alg, this->int_size,
+ prf_plus, mode, IPCOMP_NONE, this->encap, mine);
+
this->install_time = time(NULL);
this->rekey_time = this->install_time + soft;
-
return status;
}
@@ -686,15 +701,15 @@ 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->me.addr, this->other.addr, my_ts, other_ts, POLICY_OUT,
- this->protocol, this->reqid, high_prio, mode);
+ this->protocol, this->reqid, high_prio, mode, this->ipcomp);
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->other.addr, this->me.addr, other_ts, my_ts, POLICY_IN,
- this->protocol, this->reqid, high_prio, mode);
+ this->protocol, this->reqid, high_prio, mode, this->ipcomp);
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->other.addr, this->me.addr, other_ts, my_ts, POLICY_FWD,
- this->protocol, this->reqid, high_prio, mode);
+ this->protocol, this->reqid, high_prio, mode, this->ipcomp);
if (status != SUCCESS)
{
@@ -795,10 +810,20 @@ static status_t update_hosts(private_child_sa_t *this,
this->encap = encap;
- /* update our (initator) SAs */
+ if (this->ipcomp != IPCOMP_NONE)
+ {
+ /* update our (initator) IPComp SA */
+ charon->kernel_interface->update_sa(charon->kernel_interface, htonl(ntohs(this->me.cpi)),
+ IPPROTO_COMP, this->other.addr, this->me.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->me.addr, this->other.addr, me, other, FALSE);
+ }
+
+ /* update our (initator) SA */
charon->kernel_interface->update_sa(charon->kernel_interface, this->me.spi,
this->protocol, this->other.addr, this->me.addr, other, me, encap);
- /* update his (responder) SAs */
+ /* update his (responder) SA */
charon->kernel_interface->update_sa(charon->kernel_interface, this->other.spi,
this->protocol, this->me.addr, this->other.addr, me, other, encap);
@@ -846,13 +871,13 @@ static status_t update_hosts(private_child_sa_t *this,
/* reinstall updated policies */
charon->kernel_interface->add_policy(charon->kernel_interface,
me, other, policy->my_ts, policy->other_ts, POLICY_OUT,
- this->protocol, this->reqid, TRUE, this->mode);
+ this->protocol, this->reqid, TRUE, this->mode, this->ipcomp);
charon->kernel_interface->add_policy(charon->kernel_interface,
other, me, policy->other_ts, policy->my_ts, POLICY_IN,
- this->protocol, this->reqid, TRUE, this->mode);
+ this->protocol, this->reqid, TRUE, this->mode, this->ipcomp);
charon->kernel_interface->add_policy(charon->kernel_interface,
other, me, policy->other_ts, policy->my_ts, POLICY_FWD,
- this->protocol, this->reqid, TRUE, this->mode);
+ this->protocol, this->reqid, TRUE, this->mode, this->ipcomp);
}
iterator->destroy(iterator);
}
@@ -884,6 +909,30 @@ static void set_virtual_ip(private_child_sa_t *this, host_t *ip)
}
/**
+ * Implementation of child_sa_t.activate_ipcomp.
+ */
+static void activate_ipcomp(private_child_sa_t *this, ipcomp_transform_t ipcomp,
+ u_int16_t other_cpi)
+{
+ this->ipcomp = ipcomp;
+ this->other.cpi = other_cpi;
+}
+
+/**
+ * Implementation of child_sa_t.get_my_cpi.
+ */
+static u_int16_t get_my_cpi(private_child_sa_t *this)
+{
+ if (!this->cpi_allocated)
+ {
+ charon->kernel_interface->get_cpi(charon->kernel_interface,
+ this->other.addr, this->me.addr, this->reqid, &this->me.cpi);
+ this->cpi_allocated = TRUE;
+ }
+ return this->me.cpi;
+}
+
+/**
* Implementation of child_sa_t.destroy.
*/
static void destroy(private_child_sa_t *this)
@@ -916,6 +965,16 @@ static void destroy(private_child_sa_t *this)
charon->kernel_interface->del_sa(charon->kernel_interface,
this->other.addr, this->other.spi, this->protocol);
}
+ if (this->me.cpi)
+ {
+ charon->kernel_interface->del_sa(charon->kernel_interface,
+ this->other.addr, htonl(ntohs(this->me.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);
+ }
/* delete all policies in the kernel */
while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS)
@@ -976,6 +1035,8 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
this->public.set_state = (void(*)(child_sa_t*,child_sa_state_t))set_state;
this->public.get_state = (child_sa_state_t(*)(child_sa_t*))get_state;
this->public.get_config = (child_cfg_t*(*)(child_sa_t*))get_config;
+ this->public.activate_ipcomp = (void(*)(child_sa_t*,ipcomp_transform_t,u_int16_t))activate_ipcomp;
+ this->public.get_my_cpi = (u_int16_t(*)(child_sa_t*))get_my_cpi;
this->public.set_virtual_ip = (void(*)(child_sa_t*,host_t*))set_virtual_ip;
this->public.destroy = (void(*)(child_sa_t*))destroy;
@@ -985,17 +1046,21 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
this->me.id = my_id->clone(my_id);
this->other.id = other_id->clone(other_id);
this->me.spi = 0;
+ this->me.cpi = 0;
this->other.spi = 0;
+ this->other.cpi = 0;
this->alloc_ah_spi = 0;
this->alloc_esp_spi = 0;
this->encap = encap;
+ this->cpi_allocated = FALSE;
+ this->ipcomp = IPCOMP_NONE;
this->state = CHILD_CREATED;
/* reuse old reqid if we are rekeying an existing CHILD_SA */
this->reqid = rekey ? rekey : ++reqid;
- this->encryption.algorithm = ENCR_UNDEFINED;
- this->encryption.key_size = 0;
- this->integrity.algorithm = AUTH_UNDEFINED;
- this->encryption.key_size = 0;
+ this->enc_alg = ENCR_UNDEFINED;
+ this->enc_size = 0;
+ this->int_alg = AUTH_UNDEFINED;
+ this->int_size = 0;
this->policies = linked_list_create();
this->my_ts = linked_list_create();
this->other_ts = linked_list_create();