IPComp for IKEv2

This commit is contained in:
Tobias Brunner
2008-05-08 16:19:11 +00:00
parent 0f074a4344
commit d4aad55434
15 changed files with 452 additions and 56 deletions
+26 -1
View File
@@ -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;
};
/**
@@ -398,6 +413,14 @@ static diffie_hellman_group_t get_dh_group(private_child_cfg_t *this)
return dh_group;
}
/**
* 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
*/
@@ -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();
+30 -2
View File
@@ -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>
@@ -68,6 +70,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.
*
@@ -213,6 +231,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.
*
@@ -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_ @} */
@@ -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 &&
+143 -32
View File
@@ -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
@@ -142,6 +142,17 @@ static kernel_algorithm_t integrity_algs[] = {
{END_OF_LIST, NULL, 0},
};
/**
* 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
*/
@@ -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)
{
@@ -1879,14 +1896,58 @@ 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;
+20 -3
View File
@@ -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
@@ -77,6 +78,18 @@ struct kernel_interface_t {
status_t (*get_spi)(kernel_interface_t *this, host_t *src, host_t *dst,
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.
*
@@ -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.
+1
View File
@@ -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;
+4 -4
View File
@@ -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,
+2 -1
View File
@@ -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 (
+1 -1
View File
@@ -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);
+84 -10
View File
@@ -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;
/**
@@ -147,6 +150,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
*/
@@ -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);
}
@@ -874,6 +908,30 @@ static void set_virtual_ip(private_child_sa_t *this, host_t *ip)
this->virtual_ip = ip->clone(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.
*/
@@ -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;
+18 -1
View File
@@ -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
@@ -253,6 +254,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.
*/
+1 -1
View File
@@ -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)
{
+112
View File
@@ -1,4 +1,5 @@
/*
* Copyright (C) 2008 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -99,6 +100,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
*/
@@ -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,
@@ -415,6 +437,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
*/
@@ -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;
+1
View File
@@ -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);
+1
View File
@@ -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 {