aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2008-05-08 16:19:11 +0000
committerTobias Brunner <tobias@strongswan.org>2008-05-08 16:19:11 +0000
commitd4aad55434b121df0a774265aac81082b4525ddf (patch)
tree4d460cd8f328f1645ada771d9dcadc1956c1f583
parent0f074a4344f002fa3f1440fbcdfc5b28ce0b5afb (diff)
downloadstrongswan-d4aad55434b121df0a774265aac81082b4525ddf.tar.bz2
strongswan-d4aad55434b121df0a774265aac81082b4525ddf.tar.xz
IPComp for IKEv2
-rw-r--r--src/charon/config/child_cfg.c27
-rw-r--r--src/charon/config/child_cfg.h32
-rw-r--r--src/charon/encoding/payloads/notify_payload.c8
-rw-r--r--src/charon/kernel/kernel_interface.c175
-rw-r--r--src/charon/kernel/kernel_interface.h23
-rw-r--r--src/charon/plugins/sql/mysql.sql1
-rw-r--r--src/charon/plugins/sql/sql_config.c8
-rw-r--r--src/charon/plugins/sql/sqlite.sql3
-rw-r--r--src/charon/plugins/stroke/stroke_config.c2
-rw-r--r--src/charon/sa/child_sa.c94
-rw-r--r--src/charon/sa/child_sa.h19
-rw-r--r--src/charon/sa/ike_sa.c2
-rw-r--r--src/charon/sa/tasks/child_create.c112
-rw-r--r--src/starter/starterstroke.c1
-rw-r--r--src/stroke/stroke_msg.h1
15 files changed, 452 insertions, 56 deletions
diff --git a/src/charon/config/child_cfg.c b/src/charon/config/child_cfg.c
index 2c7201972..33dd73c44 100644
--- a/src/charon/config/child_cfg.c
+++ b/src/charon/config/child_cfg.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2008 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -34,6 +35,15 @@ ENUM(action_names, ACTION_NONE, ACTION_RESTART,
"ACTION_RESTART",
);
+ENUM_BEGIN(ipcomp_transform_names, IPCOMP_NONE, IPCOMP_NONE,
+ "IPCOMP_NONE");
+ENUM_NEXT(ipcomp_transform_names, IPCOMP_OUI, IPCOMP_LZJH, IPCOMP_NONE,
+ "IPCOMP_OUI",
+ "IPCOMP_DEFLATE",
+ "IPCOMP_LZS",
+ "IPCOMP_LZJH");
+ENUM_END(ipcomp_transform_names, IPCOMP_LZJH);
+
typedef struct private_child_cfg_t private_child_cfg_t;
/**
@@ -111,6 +121,11 @@ struct private_child_cfg_t {
* substracted from rekeytime.
*/
u_int32_t jitter;
+
+ /**
+ * enable IPComp
+ */
+ bool use_ipcomp;
};
/**
@@ -399,6 +414,14 @@ static diffie_hellman_group_t get_dh_group(private_child_cfg_t *this)
}
/**
+ * Implementation of child_cfg_t.use_ipcomp.
+ */
+static bool use_ipcomp(private_child_cfg_t *this)
+{
+ return this->use_ipcomp;
+}
+
+/**
* Implementation of child_cfg_t.get_name
*/
static child_cfg_t* get_ref(private_child_cfg_t *this)
@@ -432,7 +455,7 @@ static void destroy(private_child_cfg_t *this)
child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
u_int32_t rekeytime, u_int32_t jitter,
char *updown, bool hostaccess, mode_t mode,
- action_t dpd_action, action_t close_action)
+ action_t dpd_action, action_t close_action, bool ipcomp)
{
private_child_cfg_t *this = malloc_thing(private_child_cfg_t);
@@ -449,6 +472,7 @@ child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
this->public.get_close_action = (action_t (*) (child_cfg_t *))get_close_action;
this->public.get_lifetime = (u_int32_t (*) (child_cfg_t *,bool))get_lifetime;
this->public.get_dh_group = (diffie_hellman_group_t(*)(child_cfg_t*)) get_dh_group;
+ this->public.use_ipcomp = (bool (*) (child_cfg_t *))use_ipcomp;
this->public.get_ref = (child_cfg_t* (*) (child_cfg_t*))get_ref;
this->public.destroy = (void (*) (child_cfg_t*))destroy;
@@ -461,6 +485,7 @@ child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
this->mode = mode;
this->dpd_action = dpd_action;
this->close_action = close_action;
+ this->use_ipcomp = ipcomp;
this->refcount = 1;
this->proposals = linked_list_create();
this->my_ts = linked_list_create();
diff --git a/src/charon/config/child_cfg.h b/src/charon/config/child_cfg.h
index 3d4889b53..228f0d888 100644
--- a/src/charon/config/child_cfg.h
+++ b/src/charon/config/child_cfg.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2008 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -26,6 +27,7 @@
typedef enum mode_t mode_t;
typedef enum action_t action_t;
+typedef enum ipcomp_transform_t ipcomp_transform_t;
typedef struct child_cfg_t child_cfg_t;
#include <library.h>
@@ -69,6 +71,22 @@ enum action_t {
extern enum_name_t *action_names;
/**
+ * IPComp transform IDs, as in RFC 4306
+ */
+enum ipcomp_transform_t {
+ IPCOMP_NONE = 241,
+ IPCOMP_OUI = 1,
+ IPCOMP_DEFLATE = 2,
+ IPCOMP_LZS = 3,
+ IPCOMP_LZJH = 4,
+};
+
+/**
+ * enum strings for ipcomp_transform_t.
+ */
+extern enum_name_t *ipcomp_transform_names;
+
+/**
* A child_cfg_t defines the config template for a CHILD_SA.
*
* After creation, proposals and traffic selectors may be added to the config.
@@ -214,6 +232,14 @@ struct child_cfg_t {
diffie_hellman_group_t (*get_dh_group)(child_cfg_t *this);
/**
+ * Check whether IPComp should be used, if the other peer supports it.
+ *
+ * @return TRUE, if IPComp should be used
+ * FALSE, otherwise
+ */
+ bool (*use_ipcomp)(child_cfg_t *this);
+
+ /**
* Increase the reference count.
*
* @return reference to this
@@ -247,12 +273,14 @@ struct child_cfg_t {
* @param hostaccess TRUE to allow access to the local host
* @param mode mode to propose for CHILD_SA, transport, tunnel or BEET
* @param dpd_action DPD action
- * @param close_action lose action
+ * @param close_action close action
+ * @param ipcomp use IPComp, if peer supports it
* @return child_cfg_t object
*/
child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
u_int32_t rekeytime, u_int32_t jitter,
char *updown, bool hostaccess, mode_t mode,
- action_t dpd_action, action_t close_action);
+ action_t dpd_action, action_t close_action,
+ bool ipcomp);
#endif /* CHILD_CFG_H_ @} */
diff --git a/src/charon/encoding/payloads/notify_payload.c b/src/charon/encoding/payloads/notify_payload.c
index ec22d0688..6bf260d68 100644
--- a/src/charon/encoding/payloads/notify_payload.c
+++ b/src/charon/encoding/payloads/notify_payload.c
@@ -332,6 +332,14 @@ static status_t verify(private_notify_payload_t *this)
}
break;
}
+ case IPCOMP_SUPPORTED:
+ {
+ if (this->notification_data.len != 3)
+ {
+ bad_length = TRUE;
+ }
+ break;
+ }
case ME_ENDPOINT:
if (this->notification_data.len != 8 &&
this->notification_data.len != 12 &&
diff --git a/src/charon/kernel/kernel_interface.c b/src/charon/kernel/kernel_interface.c
index b1cabfa06..43837a29c 100644
--- a/src/charon/kernel/kernel_interface.c
+++ b/src/charon/kernel/kernel_interface.c
@@ -1,6 +1,6 @@
/*
+ * Copyright (C) 2006-2008 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
- * Copyright (C) 2006-2007 Tobias Brunner
* Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
@@ -143,6 +143,17 @@ static kernel_algorithm_t integrity_algs[] = {
};
/**
+ * Algorithms for IPComp
+ */
+static kernel_algorithm_t compression_algs[] = {
+/* {IPCOMP_OUI, "***", 0}, */
+ {IPCOMP_DEFLATE, "deflate", 0},
+ {IPCOMP_LZS, "lzs", 0},
+ {IPCOMP_LZJH, "lzjh", 0},
+ {END_OF_LIST, NULL, 0},
+};
+
+/**
* Look up a kernel algorithm name and its key size
*/
static char* lookup_algorithm(kernel_algorithm_t *kernel_algo,
@@ -153,8 +164,8 @@ static char* lookup_algorithm(kernel_algorithm_t *kernel_algo,
if (ikev2_algo == kernel_algo->ikev2_id)
{
/* match, evaluate key length */
- if (*key_size == 0)
- { /* update key size of not set */
+ if (key_size && *key_size == 0)
+ { /* update key size if not set */
*key_size = kernel_algo->key_size;
}
return kernel_algo->name;
@@ -518,11 +529,20 @@ static void process_expire(private_kernel_interface_t *this, struct nlmsghdr *hd
struct xfrm_user_expire *expire;
expire = (struct xfrm_user_expire*)NLMSG_DATA(hdr);
- protocol = expire->state.id.proto == KERNEL_ESP ? PROTO_ESP : PROTO_AH;
+ protocol = expire->state.id.proto;
+ protocol = (protocol == KERNEL_ESP) ? PROTO_ESP : (protocol == KERNEL_AH) ? PROTO_AH : protocol;
spi = expire->state.id.spi;
reqid = expire->state.reqid;
DBG2(DBG_KNL, "received a XFRM_MSG_EXPIRE");
+
+ if (protocol != PROTO_ESP && protocol != PROTO_AH)
+ {
+ DBG2(DBG_KNL, "ignoring XFRM_MSG_EXPIRE for SA 0x%x (reqid %d) which is "
+ "not a CHILD_SA", ntohl(spi), reqid);
+ return;
+ }
+
DBG1(DBG_KNL, "creating %s job for %N CHILD_SA 0x%x (reqid %d)",
expire->hard ? "delete" : "rekey", protocol_id_names,
protocol, ntohl(spi), reqid);
@@ -1814,12 +1834,11 @@ static status_t del_ip(private_kernel_interface_t *this, host_t *virtual_ip)
}
/**
- * Implementation of kernel_interface_t.get_spi.
+ * Get an SPI for a specific protocol from the kernel.
*/
-static status_t get_spi(private_kernel_interface_t *this,
- host_t *src, host_t *dst,
- protocol_id_t protocol, u_int32_t reqid,
- u_int32_t *spi)
+static status_t get_spi_internal(private_kernel_interface_t *this,
+ host_t *src, host_t *dst, u_int8_t proto, u_int32_t min, u_int32_t max,
+ u_int32_t reqid, u_int32_t *spi)
{
unsigned char request[BUFFER_SIZE];
struct nlmsghdr *hdr, *out;
@@ -1829,8 +1848,6 @@ static status_t get_spi(private_kernel_interface_t *this,
memset(&request, 0, sizeof(request));
- DBG2(DBG_KNL, "getting SPI for reqid %d", reqid);
-
hdr = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST;
hdr->nlmsg_type = XFRM_MSG_ALLOCSPI;
@@ -1839,12 +1856,12 @@ static status_t get_spi(private_kernel_interface_t *this,
userspi = (struct xfrm_userspi_info*)NLMSG_DATA(hdr);
host2xfrm(src, &userspi->info.saddr);
host2xfrm(dst, &userspi->info.id.daddr);
- userspi->info.id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
+ userspi->info.id.proto = proto;
userspi->info.mode = TRUE; /* tunnel mode */
userspi->info.reqid = reqid;
userspi->info.family = src->get_family(src);
- userspi->min = 0xc0000000;
- userspi->max = 0xcFFFFFFF;
+ userspi->min = min;
+ userspi->max = max;
if (netlink_send(this, this->socket_xfrm, hdr, &out, &len) == SUCCESS)
{
@@ -1880,13 +1897,57 @@ static status_t get_spi(private_kernel_interface_t *this,
if (received_spi == 0)
{
+ return FAILED;
+ }
+
+ *spi = received_spi;
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.get_spi.
+ */
+static status_t get_spi(private_kernel_interface_t *this,
+ host_t *src, host_t *dst,
+ protocol_id_t protocol, u_int32_t reqid,
+ u_int32_t *spi)
+{
+ DBG2(DBG_KNL, "getting SPI for reqid %d", reqid);
+
+ if (get_spi_internal(this, src, dst,
+ (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH,
+ 0xc0000000, 0xcFFFFFFF, reqid, spi) != SUCCESS)
+ {
DBG1(DBG_KNL, "unable to get SPI for reqid %d", reqid);
return FAILED;
}
- DBG2(DBG_KNL, "got SPI 0x%x for reqid %d", received_spi, reqid);
+ DBG2(DBG_KNL, "got SPI 0x%x for reqid %d", *spi, reqid);
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.get_cpi.
+ */
+static status_t get_cpi(private_kernel_interface_t *this,
+ host_t *src, host_t *dst,
+ u_int32_t reqid, u_int16_t *cpi)
+{
+ u_int32_t received_spi = 0;
+ DBG2(DBG_KNL, "getting CPI for reqid %d", reqid);
+
+ if (get_spi_internal(this, src, dst,
+ IPPROTO_COMP, 0x100, 0xEFFF, reqid, &received_spi) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to get CPI for reqid %d", reqid);
+ return FAILED;
+ }
+
+ *cpi = htons((u_int16_t)ntohl(received_spi));
+
+ DBG2(DBG_KNL, "got CPI 0x%x for reqid %d", *cpi, reqid);
- *spi = received_spi;
return SUCCESS;
}
@@ -1899,7 +1960,8 @@ static status_t add_sa(private_kernel_interface_t *this,
u_int64_t expire_soft, u_int64_t expire_hard,
u_int16_t enc_alg, u_int16_t enc_size,
u_int16_t int_alg, u_int16_t int_size,
- prf_plus_t *prf_plus, mode_t mode, bool encap,
+ prf_plus_t *prf_plus, mode_t mode,
+ u_int16_t ipcomp, bool encap,
bool replace)
{
unsigned char request[BUFFER_SIZE];
@@ -1909,7 +1971,7 @@ static status_t add_sa(private_kernel_interface_t *this,
memset(&request, 0, sizeof(request));
- DBG2(DBG_KNL, "adding SAD entry with SPI 0x%x", spi);
+ DBG2(DBG_KNL, "adding SAD entry with SPI 0x%x and reqid %d", spi, reqid);
hdr = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
@@ -1920,10 +1982,10 @@ static status_t add_sa(private_kernel_interface_t *this,
host2xfrm(src, &sa->saddr);
host2xfrm(dst, &sa->id.daddr);
sa->id.spi = spi;
- sa->id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
+ sa->id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : (protocol == PROTO_AH) ? KERNEL_AH : protocol;
sa->family = src->get_family(src);
sa->mode = mode;
- sa->replay_window = 32;
+ sa->replay_window = (protocol == IPPROTO_COMP) ? 0 : 32;
sa->reqid = reqid;
/* we currently do not expire SAs by volume/packet count */
sa->lft.soft_byte_limit = XFRM_INF;
@@ -1994,7 +2056,32 @@ static status_t add_sa(private_kernel_interface_t *this,
rthdr = XFRM_RTA_NEXT(rthdr);
}
- /* TODO: add IPComp here */
+ if (ipcomp != IPCOMP_NONE)
+ {
+ rthdr->rta_type = XFRMA_ALG_COMP;
+ alg_name = lookup_algorithm(compression_algs, ipcomp, NULL);
+ if (alg_name == NULL)
+ {
+ DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
+ ipcomp_transform_names, ipcomp);
+ return FAILED;
+ }
+ DBG2(DBG_KNL, " using compression algorithm %N",
+ ipcomp_transform_names, ipcomp);
+
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo));
+ hdr->nlmsg_len += rthdr->rta_len;
+ if (hdr->nlmsg_len > sizeof(request))
+ {
+ return FAILED;
+ }
+
+ struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr);
+ algo->alg_key_len = 0;
+ strcpy(algo->alg_name, alg_name);
+
+ rthdr = XFRM_RTA_NEXT(rthdr);
+ }
if (encap)
{
@@ -2062,7 +2149,7 @@ static status_t update_sa(private_kernel_interface_t *this,
sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
host2xfrm(dst, &sa_id->daddr);
sa_id->spi = spi;
- sa_id->proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
+ sa_id->proto = (protocol == PROTO_ESP) ? KERNEL_ESP : (protocol == PROTO_AH) ? KERNEL_AH : protocol;
sa_id->family = dst->get_family(dst);
if (netlink_send(this, this->socket_xfrm, hdr, &out, &len) == SUCCESS)
@@ -2190,7 +2277,7 @@ static status_t query_sa(private_kernel_interface_t *this, host_t *dst,
sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
host2xfrm(dst, &sa_id->daddr);
sa_id->spi = spi;
- sa_id->proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
+ sa_id->proto = (protocol == PROTO_ESP) ? KERNEL_ESP : (protocol == PROTO_AH) ? KERNEL_AH : protocol;
sa_id->family = dst->get_family(dst);
if (netlink_send(this, this->socket_xfrm, hdr, &out, &len) == SUCCESS)
@@ -2256,7 +2343,7 @@ static status_t del_sa(private_kernel_interface_t *this, host_t *dst,
sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
host2xfrm(dst, &sa_id->daddr);
sa_id->spi = spi;
- sa_id->proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
+ sa_id->proto = (protocol == PROTO_ESP) ? KERNEL_ESP : (protocol == PROTO_AH) ? KERNEL_AH : protocol;
sa_id->family = dst->get_family(dst);
if (netlink_send_ack(this, this->socket_xfrm, hdr) != SUCCESS)
@@ -2276,7 +2363,8 @@ static status_t add_policy(private_kernel_interface_t *this,
traffic_selector_t *src_ts,
traffic_selector_t *dst_ts,
policy_dir_t direction, protocol_id_t protocol,
- u_int32_t reqid, bool high_prio, mode_t mode)
+ u_int32_t reqid, bool high_prio, mode_t mode,
+ u_int16_t ipcomp)
{
iterator_t *iterator;
policy_entry_t *current, *policy;
@@ -2301,7 +2389,7 @@ static status_t add_policy(private_kernel_interface_t *this,
{
/* use existing policy */
current->refcount++;
- DBG2(DBG_KNL, "policy %R===%R already exists, increasing ",
+ DBG2(DBG_KNL, "policy %R===%R already exists, increasing "
"refcount", src_ts, dst_ts);
free(policy);
policy = current;
@@ -2348,10 +2436,8 @@ static status_t add_policy(private_kernel_interface_t *this,
struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_userpolicy_info);
rthdr->rta_type = XFRMA_TMPL;
-
- rthdr->rta_len = sizeof(struct xfrm_user_tmpl);
- rthdr->rta_len = RTA_LENGTH(rthdr->rta_len);
-
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_user_tmpl));
+
hdr->nlmsg_len += rthdr->rta_len;
if (hdr->nlmsg_len > sizeof(request))
{
@@ -2359,6 +2445,30 @@ static status_t add_policy(private_kernel_interface_t *this,
}
struct xfrm_user_tmpl *tmpl = (struct xfrm_user_tmpl*)RTA_DATA(rthdr);
+
+ if (ipcomp != IPCOMP_NONE)
+ {
+ tmpl->reqid = reqid;
+ tmpl->id.proto = IPPROTO_COMP;
+ tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
+ tmpl->mode = mode;
+ tmpl->optional = direction != POLICY_OUT;
+ tmpl->family = src->get_family(src);
+
+ host2xfrm(src, &tmpl->saddr);
+ host2xfrm(dst, &tmpl->id.daddr);
+
+ /* add an additional xfrm_user_tmpl */
+ rthdr->rta_len += RTA_LENGTH(sizeof(struct xfrm_user_tmpl));
+ hdr->nlmsg_len += RTA_LENGTH(sizeof(struct xfrm_user_tmpl));
+ if (hdr->nlmsg_len > sizeof(request))
+ {
+ return FAILED;
+ }
+
+ tmpl++;
+ }
+
tmpl->reqid = reqid;
tmpl->id.proto = (protocol == PROTO_AH) ? KERNEL_AH : KERNEL_ESP;
tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
@@ -2588,11 +2698,12 @@ kernel_interface_t *kernel_interface_create()
/* public functions */
this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
- this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,u_int16_t,u_int16_t,u_int16_t,prf_plus_t*,mode_t,bool,bool))add_sa;
+ this->public.get_cpi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
+ this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,u_int16_t,u_int16_t,u_int16_t,prf_plus_t*,mode_t,u_int16_t,bool,bool))add_sa;
this->public.update_sa = (status_t(*)(kernel_interface_t*,u_int32_t,protocol_id_t,host_t*,host_t*,host_t*,host_t*,bool))update_sa;
this->public.query_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t*))query_sa;
this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa;
- this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,protocol_id_t,u_int32_t,bool,mode_t))add_policy;
+ this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,protocol_id_t,u_int32_t,bool,mode_t,u_int16_t))add_policy;
this->public.query_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy;
this->public.del_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t))del_policy;
this->public.get_interface = (char*(*)(kernel_interface_t*,host_t*))get_interface_name;
diff --git a/src/charon/kernel/kernel_interface.h b/src/charon/kernel/kernel_interface.h
index 5e2bff5d8..0978b05e3 100644
--- a/src/charon/kernel/kernel_interface.h
+++ b/src/charon/kernel/kernel_interface.h
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
+ * Copyright (C) 2006-2008 Tobias Brunner
+ * Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -78,6 +79,18 @@ struct kernel_interface_t {
protocol_id_t protocol, u_int32_t reqid, u_int32_t *spi);
/**
+ * Get a Compression Parameter Index (CPI) from the kernel.
+ *
+ * @param src source address of SA
+ * @param dst destination address of SA
+ * @param reqid unique ID for the corresponding SA
+ * @param cpi allocated cpi
+ * @return SUCCESS if operation completed
+ */
+ status_t (*get_cpi)(kernel_interface_t *this, host_t *src, host_t *dst,
+ u_int32_t reqid, u_int16_t *cpi);
+
+ /**
* Add an SA to the SAD.
*
* add_sa() may update an already allocated
@@ -101,6 +114,7 @@ struct kernel_interface_t {
* @param int_size key length of integrity algorithm, if dynamic
* @param prf_plus PRF to derive keys from
* @param mode mode of the SA (tunnel, transport)
+ * @param ipcomp IPComp transform to use
* @param encap enable UDP encapsulation for NAT traversal
* @param replace Should an already installed SA be updated?
* @return SUCCESS if operation completed
@@ -111,7 +125,8 @@ struct kernel_interface_t {
u_int64_t expire_soft, u_int64_t expire_hard,
u_int16_t enc_alg, u_int16_t enc_size,
u_int16_t int_alg, u_int16_t int_size,
- prf_plus_t *prf_plus, mode_t mode, bool encap,
+ prf_plus_t *prf_plus, mode_t mode,
+ u_int16_t ipcomp, bool encap,
bool update);
/**
@@ -177,6 +192,7 @@ struct kernel_interface_t {
* @param reqid uniqe ID of an SA to use to enforce policy
* @param high_prio if TRUE, uses a higher priority than any with FALSE
* @param mode mode of SA (tunnel, transport)
+ * @param ipcomp the IPComp transform used
* @return SUCCESS if operation completed
*/
status_t (*add_policy) (kernel_interface_t *this,
@@ -184,7 +200,8 @@ struct kernel_interface_t {
traffic_selector_t *src_ts,
traffic_selector_t *dst_ts,
policy_dir_t direction, protocol_id_t protocol,
- u_int32_t reqid, bool high_prio, mode_t mode);
+ u_int32_t reqid, bool high_prio, mode_t mode,
+ u_int16_t ipcomp);
/**
* Query the use time of a policy.
diff --git a/src/charon/plugins/sql/mysql.sql b/src/charon/plugins/sql/mysql.sql
index aca8b83af..6c04aef68 100644
--- a/src/charon/plugins/sql/mysql.sql
+++ b/src/charon/plugins/sql/mysql.sql
@@ -22,6 +22,7 @@ CREATE TABLE `child_configs` (
`mode` tinyint(4) unsigned NOT NULL default '1',
`dpd_action` tinyint(4) unsigned NOT NULL default '0',
`close_action` tinyint(4) unsigned NOT NULL default '0',
+ `ipcomp` tinyint(4) unsigned NOT NULL default '0',
PRIMARY KEY (`id`),
INDEX (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
diff --git a/src/charon/plugins/sql/sql_config.c b/src/charon/plugins/sql/sql_config.c
index 3777c6ebb..9b703643b 100644
--- a/src/charon/plugins/sql/sql_config.c
+++ b/src/charon/plugins/sql/sql_config.c
@@ -125,15 +125,15 @@ static void add_traffic_selectors(private_sql_config_t *this,
*/
static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e)
{
- int id, lifetime, rekeytime, jitter, hostaccess, mode, dpd, close;
+ int id, lifetime, rekeytime, jitter, hostaccess, mode, dpd, close, ipcomp;
char *name, *updown;
child_cfg_t *child_cfg;
if (e->enumerate(e, &id, &name, &lifetime, &rekeytime, &jitter,
- &updown, &hostaccess, &mode, &dpd, &close))
+ &updown, &hostaccess, &mode, &dpd, &close, &ipcomp))
{
child_cfg = child_cfg_create(name, lifetime, rekeytime, jitter,
- updown, hostaccess, mode, dpd, close);
+ updown, hostaccess, mode, dpd, close, ipcomp);
/* TODO: read proposal from db */
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
add_traffic_selectors(this, child_cfg, id);
@@ -152,7 +152,7 @@ static void add_child_cfgs(private_sql_config_t *this, peer_cfg_t *peer, int id)
e = this->db->query(this->db,
"SELECT id, name, lifetime, rekeytime, jitter, "
- "updown, hostaccess, mode, dpd_action, close_action "
+ "updown, hostaccess, mode, dpd_action, close_action, ipcomp "
"FROM child_configs JOIN peer_config_child_config ON id = child_cfg "
"WHERE peer_cfg = ?",
DB_INT, id,
diff --git a/src/charon/plugins/sql/sqlite.sql b/src/charon/plugins/sql/sqlite.sql
index a3f527b90..97c304a16 100644
--- a/src/charon/plugins/sql/sqlite.sql
+++ b/src/charon/plugins/sql/sqlite.sql
@@ -20,7 +20,8 @@ CREATE TABLE child_configs (
hostaccess INTEGER NOT NULL DEFAULT '0',
mode INTEGER NOT NULL DEFAULT '1',
dpd_action INTEGER NOT NULL DEFAULT '0',
- close_action INTEGER NOT NULL DEFAULT '0'
+ close_action INTEGER NOT NULL DEFAULT '0',
+ ipcomp INTEGER NOT NULL DEFAULT '0'
);
DROP INDEX IF EXISTS child_configs_name;
CREATE INDEX child_configs_name ON child_configs (
diff --git a/src/charon/plugins/stroke/stroke_config.c b/src/charon/plugins/stroke/stroke_config.c
index 54b3bf896..f8b4db063 100644
--- a/src/charon/plugins/stroke/stroke_config.c
+++ b/src/charon/plugins/stroke/stroke_config.c
@@ -710,7 +710,7 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100,
msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
- msg->add_conn.mode, dpd, ACTION_NONE);
+ msg->add_conn.mode, dpd, ACTION_NONE, msg->add_conn.ipcomp);
add_ts(this, &msg->add_conn.me, child_cfg, TRUE);
add_ts(this, &msg->add_conn.other, child_cfg, FALSE);
diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c
index 7cd36d68e..21f29a35e 100644
--- a/src/charon/sa/child_sa.c
+++ b/src/charon/sa/child_sa.c
@@ -1,6 +1,7 @@
/*
+ * 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
*
@@ -70,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;
/**
@@ -148,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;
@@ -570,10 +583,21 @@ 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 */
+ 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, this->encap, mine);
+ prf_plus, mode, IPCOMP_NONE, this->encap, mine);
this->install_time = time(NULL);
this->rekey_time = this->install_time + soft;
@@ -677,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)
{
@@ -786,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);
@@ -837,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);
}
@@ -875,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)
@@ -907,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)
@@ -967,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;
@@ -976,10 +1046,14 @@ 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;
diff --git a/src/charon/sa/child_sa.h b/src/charon/sa/child_sa.h
index b8186ef51..018f9225c 100644
--- a/src/charon/sa/child_sa.h
+++ b/src/charon/sa/child_sa.h
@@ -1,6 +1,7 @@
/*
+ * Copyright (C) 2006-2008 Tobias Brunner
* Copyright (C) 2006-2007 Martin Willi
- * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
+ * Copyright (C) 2006 Daniel Roethlisberger
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -254,6 +255,22 @@ struct child_sa_t {
void (*set_virtual_ip) (child_sa_t *this, host_t *ip);
/**
+ * Activate IPComp by setting the transform ID and CPI values.
+ *
+ * @param ipcomp the IPComp transform to use
+ * @param other_cpi other Compression Parameter Index
+ */
+ void (*activate_ipcomp) (child_sa_t *this, ipcomp_transform_t ipcomp,
+ u_int16_t other_cpi);
+
+ /**
+ * Returns the Compression Parameter Index (CPI) allocated from the kernel.
+ *
+ * @return allocated CPI
+ */
+ u_int16_t (*get_my_cpi) (child_sa_t *this);
+
+ /**
* Destroys a child_sa.
*/
void (*destroy) (child_sa_t *this);
diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c
index 1b2ce47ba..eb5e67739 100644
--- a/src/charon/sa/ike_sa.c
+++ b/src/charon/sa/ike_sa.c
@@ -1219,7 +1219,7 @@ static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg)
/* install kernel policies */
child_sa = child_sa_create(this->my_host, this->other_host, this->my_id,
- this->other_id, child_cfg, FALSE, 0);
+ this->other_id, child_cfg, 0, FALSE);
me = this->my_host;
if (this->my_virtual_ip)
{
diff --git a/src/charon/sa/tasks/child_create.c b/src/charon/sa/tasks/child_create.c
index 9dd5add8f..456eafd3c 100644
--- a/src/charon/sa/tasks/child_create.c
+++ b/src/charon/sa/tasks/child_create.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2008 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -100,6 +101,21 @@ struct private_child_create_t {
mode_t mode;
/**
+ * IPComp transform to use
+ */
+ ipcomp_transform_t ipcomp;
+
+ /**
+ * IPComp transform proposed or accepted by the other peer
+ */
+ ipcomp_transform_t ipcomp_received;
+
+ /**
+ * Other Compression Parameter Index (CPI)
+ */
+ u_int16_t other_cpi;
+
+ /**
* reqid to use if we are rekeying
*/
u_int32_t reqid;
@@ -326,6 +342,12 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
}
prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
+ if (this->ipcomp != IPCOMP_NONE)
+ {
+ this->child_sa->activate_ipcomp(this->child_sa, this->ipcomp,
+ this->other_cpi);
+ }
+
if (this->initiator)
{
status = this->child_sa->update(this->child_sa, this->proposal,
@@ -416,6 +438,36 @@ static void build_payloads(private_child_create_t *this, message_t *message)
}
/**
+ * Adds an IPCOMP_SUPPORTED notify to the message, if possible
+ */
+static void build_ipcomp_supported_notify(private_child_create_t *this, message_t *message)
+{
+ if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
+ {
+ DBG1(DBG_IKE, "IPComp is not supported if either peer is natted, IPComp is disabled");
+ this->ipcomp = IPCOMP_NONE;
+ return;
+ }
+
+ u_int16_t cpi = this->child_sa->get_my_cpi(this->child_sa);
+ if (cpi)
+ {
+ chunk_t cpi_chunk, tid_chunk, data;
+ u_int8_t tid = this->ipcomp;
+ cpi_chunk = chunk_from_thing(cpi);
+ tid_chunk = chunk_from_thing(tid);
+ data = chunk_cat("cc", cpi_chunk, tid_chunk);
+ message->add_notify(message, FALSE, IPCOMP_SUPPORTED, data);
+ chunk_free(&data);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "unable to allocate a CPI from kernel, IPComp is disabled");
+ this->ipcomp = IPCOMP_NONE;
+ }
+}
+
+/**
* Read payloads from message
*/
static void process_payloads(private_child_create_t *this, message_t *message)
@@ -470,6 +522,25 @@ static void process_payloads(private_child_create_t *this, message_t *message)
case USE_BEET_MODE:
this->mode = MODE_BEET;
break;
+ case IPCOMP_SUPPORTED:
+ {
+ chunk_t data = notify_payload->get_notification_data(notify_payload);
+ u_int16_t cpi = *(u_int16_t*)data.ptr;
+ ipcomp_transform_t ipcomp = (ipcomp_transform_t)(*(data.ptr + 2));
+ switch(ipcomp)
+ {
+ case IPCOMP_DEFLATE:
+ this->other_cpi = cpi;
+ this->ipcomp_received = ipcomp;
+ break;
+ case IPCOMP_LZS:
+ case IPCOMP_LZJH:
+ default:
+ DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify with a transform"
+ " ID we don't support %N", ipcomp_transform_names, ipcomp);
+ break;
+ }
+ }
default:
break;
}
@@ -576,6 +647,12 @@ static status_t build_i(private_child_create_t *this, message_t *message)
this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
}
+ if (this->config->use_ipcomp(this->config)) {
+ /* IPCOMP_DEFLATE is the only transform we support at the moment */
+ this->ipcomp = IPCOMP_DEFLATE;
+ build_ipcomp_supported_notify(this, message);
+ }
+
build_payloads(this, message);
this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
@@ -693,6 +770,16 @@ static status_t build_r(private_child_create_t *this, message_t *message)
this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid,
this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
+ if (this->config->use_ipcomp(this->config) && this->ipcomp_received != IPCOMP_NONE)
+ {
+ this->ipcomp = this->ipcomp_received;
+ build_ipcomp_supported_notify(this, message);
+ }
+ else if (this->ipcomp_received != IPCOMP_NONE)
+ {
+ DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify but IPComp is disabled, ignoring");
+ }
+
switch (select_and_install(this, no_dh))
{
case SUCCESS:
@@ -799,6 +886,25 @@ static status_t process_i(private_child_create_t *this, message_t *message)
process_payloads(this, message);
+ if (this->ipcomp == IPCOMP_NONE && this->ipcomp_received != IPCOMP_NONE)
+ {
+ SIG(CHILD_UP_FAILED, "received an IPCOMP_SUPPORTED notify but we did not "
+ "send one previously, no CHILD_SA built");
+ return SUCCESS;
+ }
+ else if (this->ipcomp != IPCOMP_NONE && this->ipcomp_received == IPCOMP_NONE)
+ {
+ DBG1(DBG_IKE, "peer didn't accept our proposed IPComp transforms, "
+ "IPComp is disabled");
+ this->ipcomp = IPCOMP_NONE;
+ }
+ else if (this->ipcomp != IPCOMP_NONE && this->ipcomp != this->ipcomp_received)
+ {
+ SIG(CHILD_UP_FAILED, "received an IPCOMP_SUPPORTED notify for a transform "
+ "we did not propose, no CHILD_SA built");
+ return SUCCESS;
+ }
+
if (select_and_install(this, no_dh) == SUCCESS)
{
SIG(CHILD_UP_SUCCESS, "CHILD_SA '%s' established successfully",
@@ -877,6 +983,9 @@ static void migrate(private_child_create_t *this, ike_sa_t *ike_sa)
this->dh = NULL;
this->child_sa = NULL;
this->mode = MODE_TUNNEL;
+ this->ipcomp = IPCOMP_NONE;
+ this->ipcomp_received = IPCOMP_NONE;
+ this->other_cpi = 0;
this->reqid = 0;
this->established = FALSE;
}
@@ -950,6 +1059,9 @@ child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config)
this->dh_group = MODP_NONE;
this->child_sa = NULL;
this->mode = MODE_TUNNEL;
+ this->ipcomp = IPCOMP_NONE;
+ this->ipcomp_received = IPCOMP_NONE;
+ this->other_cpi = 0;
this->reqid = 0;
this->established = FALSE;
diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c
index 66b007e39..4aacbce77 100644
--- a/src/starter/starterstroke.c
+++ b/src/starter/starterstroke.c
@@ -253,6 +253,7 @@ int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn)
}
msg.add_conn.mobike = conn->policy & POLICY_MOBIKE;
msg.add_conn.force_encap = conn->policy & POLICY_FORCE_ENCAP;
+ msg.add_conn.ipcomp = conn->policy & POLICY_COMPRESS;
msg.add_conn.crl_policy = cfg->setup.strictcrlpolicy;
msg.add_conn.unique = cfg->setup.uniqueids;
msg.add_conn.algorithms.ike = push_string(&msg, conn->ike);
diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h
index 9fa3449ec..8258fdc7d 100644
--- a/src/stroke/stroke_msg.h
+++ b/src/stroke/stroke_msg.h
@@ -198,6 +198,7 @@ struct stroke_msg_t {
int mode;
int mobike;
int force_encap;
+ int ipcomp;
crl_policy_t crl_policy;
int unique;
struct {