/*
* Copyright (C) 2006-2008 Tobias Brunner
- * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
#include <processing/jobs/acquire_job.h>
#include <processing/jobs/rekey_child_sa_job.h>
#include <processing/jobs/delete_child_sa_job.h>
+#include <processing/jobs/update_sa_job.h>
/** required for Linux 2.6.26 kernel and later */
#ifndef XFRM_STATE_AF_UNSPEC
#define PRIO_HIGH 2000
/**
+ * Create ORable bitfield of XFRM NL groups
+ */
+#define XFRMNLGRP(x) (1<<(XFRMNLGRP_##x-1))
+
+/**
* returns a pointer to the first rtattr following the nlmsghdr *nlh and the
* 'usual' netlink data x like 'struct xfrm_usersa_info'
*/
typedef struct kernel_algorithm_t kernel_algorithm_t;
/**
- * Mapping from the algorithms defined in IKEv2 to
- * kernel level algorithm names and their key length
+ * Mapping of IKEv2 kernel identifier to linux crypto API names
*/
struct kernel_algorithm_t {
/**
* Identifier specified in IKEv2
*/
- int ikev2_id;
+ int ikev2;
/**
- * Name of the algorithm, as used as kernel identifier
+ * Name of the algorithm in linux crypto API
*/
char *name;
-
- /**
- * Key length in bits, if fixed size
- */
- u_int key_size;
};
-ENUM(policy_dir_names, POLICY_IN, POLICY_FWD,
- "in",
- "out",
- "fwd"
-);
-
#define END_OF_LIST -1
/**
* Algorithms for encryption
*/
static kernel_algorithm_t encryption_algs[] = {
-/* {ENCR_DES_IV64, "***", 0}, */
- {ENCR_DES, "des", 64},
- {ENCR_3DES, "des3_ede", 192},
-/* {ENCR_RC5, "***", 0}, */
-/* {ENCR_IDEA, "***", 0}, */
- {ENCR_CAST, "cast128", 0},
- {ENCR_BLOWFISH, "blowfish", 0},
-/* {ENCR_3IDEA, "***", 0}, */
-/* {ENCR_DES_IV32, "***", 0}, */
- {ENCR_NULL, "cipher_null", 0},
- {ENCR_AES_CBC, "aes", 0},
-/* {ENCR_AES_CTR, "***", 0}, */
- {ENCR_AES_CCM_ICV8, "rfc4309(ccm(aes))", 64}, /* key_size = ICV size */
- {ENCR_AES_CCM_ICV12, "rfc4309(ccm(aes))", 96}, /* key_size = ICV size */
- {ENCR_AES_CCM_ICV16, "rfc4309(ccm(aes))", 128}, /* key_size = ICV size */
- {ENCR_AES_GCM_ICV8, "rfc4106(gcm(aes))", 64}, /* key_size = ICV size */
- {ENCR_AES_GCM_ICV12, "rfc4106(gcm(aes))", 96}, /* key_size = ICV size */
- {ENCR_AES_GCM_ICV16, "rfc4106(gcm(aes))", 128}, /* key_size = ICV size */
- {END_OF_LIST, NULL, 0},
+/* {ENCR_DES_IV64, "***" }, */
+ {ENCR_DES, "des" },
+ {ENCR_3DES, "des3_ede" },
+/* {ENCR_RC5, "***" }, */
+/* {ENCR_IDEA, "***" }, */
+ {ENCR_CAST, "cast128" },
+ {ENCR_BLOWFISH, "blowfish" },
+/* {ENCR_3IDEA, "***" }, */
+/* {ENCR_DES_IV32, "***" }, */
+ {ENCR_NULL, "cipher_null" },
+ {ENCR_AES_CBC, "aes" },
+/* {ENCR_AES_CTR, "***" }, */
+ {ENCR_AES_CCM_ICV8, "rfc4309(ccm(aes))" },
+ {ENCR_AES_CCM_ICV12, "rfc4309(ccm(aes))" },
+ {ENCR_AES_CCM_ICV16, "rfc4309(ccm(aes))" },
+ {ENCR_AES_GCM_ICV8, "rfc4106(gcm(aes))" },
+ {ENCR_AES_GCM_ICV12, "rfc4106(gcm(aes))" },
+ {ENCR_AES_GCM_ICV16, "rfc4106(gcm(aes))" },
+ {END_OF_LIST, NULL },
};
/**
* Algorithms for integrity protection
*/
static kernel_algorithm_t integrity_algs[] = {
- {AUTH_HMAC_MD5_96, "md5", 128},
- {AUTH_HMAC_SHA1_96, "sha1", 160},
- {AUTH_HMAC_SHA2_256_128, "sha256", 256},
- {AUTH_HMAC_SHA2_384_192, "sha384", 384},
- {AUTH_HMAC_SHA2_512_256, "sha512", 512},
-/* {AUTH_DES_MAC, "***", 0}, */
-/* {AUTH_KPDK_MD5, "***", 0}, */
- {AUTH_AES_XCBC_96, "xcbc(aes)", 128},
- {END_OF_LIST, NULL, 0},
+ {AUTH_HMAC_MD5_96, "md5" },
+ {AUTH_HMAC_SHA1_96, "sha1" },
+ {AUTH_HMAC_SHA2_256_128, "sha256" },
+ {AUTH_HMAC_SHA2_384_192, "sha384" },
+ {AUTH_HMAC_SHA2_512_256, "sha512" },
+/* {AUTH_DES_MAC, "***" }, */
+/* {AUTH_KPDK_MD5, "***" }, */
+ {AUTH_AES_XCBC_96, "xcbc(aes)" },
+ {END_OF_LIST, NULL },
};
/**
* 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},
+/* {IPCOMP_OUI, "***" }, */
+ {IPCOMP_DEFLATE, "deflate" },
+ {IPCOMP_LZS, "lzs" },
+ {IPCOMP_LZJH, "lzjh" },
+ {END_OF_LIST, NULL },
};
/**
* Look up a kernel algorithm name and its key size
*/
-static char* lookup_algorithm(kernel_algorithm_t *kernel_algo,
- u_int16_t ikev2_algo, u_int16_t *key_size)
+static char* lookup_algorithm(kernel_algorithm_t *list, int ikev2)
{
- while (kernel_algo->ikev2_id != END_OF_LIST)
+ while (list->ikev2 != END_OF_LIST)
{
- if (ikev2_algo == kernel_algo->ikev2_id)
+ if (list->ikev2 == ikev2)
{
- /* match, evaluate key length */
- if (key_size && *key_size == 0)
- { /* update key size if not set */
- *key_size = kernel_algo->key_size;
- }
- return kernel_algo->name;
+ return list->name;
}
- kernel_algo++;
+ list++;
}
return NULL;
}
/** direction of this policy: in, out, forward */
u_int8_t direction;
- /** reqid of the policy */
- u_int32_t reqid;
-
/** parameters of installed policy */
struct xfrm_selector sel;
}
/**
- * convert a traffic selector address range to subnet and its mask.
+ * convert a struct xfrm_address to a host_t
*/
-static void ts2subnet(traffic_selector_t* ts,
- xfrm_address_t *net, u_int8_t *mask)
+static host_t* xfrm2host(int family, xfrm_address_t *xfrm, u_int16_t port)
{
- /* there is no way to do this cleanly, as the address range may
- * be anything else but a subnet. We use from_addr as subnet
- * and try to calculate a usable subnet mask.
- */
- int byte, bit;
- bool found = FALSE;
- chunk_t from, to;
- size_t size = (ts->get_type(ts) == TS_IPV4_ADDR_RANGE) ? 4 : 16;
-
- from = ts->get_from_address(ts);
- to = ts->get_to_address(ts);
+ chunk_t chunk;
- *mask = (size * 8);
- /* go trough all bits of the addresses, beginning in the front.
- * as long as they are equal, the subnet gets larger
- */
- for (byte = 0; byte < size; byte++)
+ switch (family)
{
- for (bit = 7; bit >= 0; bit--)
- {
- if ((1<<bit & from.ptr[byte]) != (1<<bit & to.ptr[byte]))
- {
- *mask = ((7 - bit) + (byte * 8));
- found = TRUE;
- break;
- }
- }
- if (found)
- {
+ case AF_INET:
+ chunk = chunk_create((u_char*)&xfrm->a4, sizeof(xfrm->a4));
break;
- }
+ case AF_INET6:
+ chunk = chunk_create((u_char*)&xfrm->a6, sizeof(xfrm->a6));
+ break;
+ default:
+ return NULL;
}
- memcpy(net, from.ptr, from.len);
- chunk_free(&from);
- chunk_free(&to);
+ return host_create_from_chunk(family, chunk, ntohs(port));
+}
+
+/**
+ * convert a traffic selector address range to subnet and its mask.
+ */
+static void ts2subnet(traffic_selector_t* ts,
+ xfrm_address_t *net, u_int8_t *mask)
+{
+ host_t *net_host;
+ chunk_t net_chunk;
+
+ ts->to_subnet(ts, &net_host, mask);
+ net_chunk = net_host->get_address(net_host);
+ memcpy(net, net_chunk.ptr, net_chunk.len);
+ net_host->destroy(net_host);
}
/**
return sel;
}
+/**
+ * convert a xfrm_selector to a src|dst traffic_selector
+ */
+static traffic_selector_t* selector2ts(struct xfrm_selector *sel, bool src)
+{
+ ts_type_t type;
+ chunk_t addr;
+ u_int16_t port, port_mask, from_port, to_port;
+
+ if (src)
+ {
+ addr.ptr = (u_char*)&sel->saddr;
+ port = sel->sport;
+ port_mask = sel->sport_mask;
+ }
+ else
+ {
+ addr.ptr = (u_char*)&sel->daddr;
+ port = sel->dport;
+ port_mask = sel->dport_mask;
+ }
+ /* The Linux 2.6 kernel does not set the selector's family field,
+ * so as a kludge we additionally test the prefix length.
+ */
+ if (sel->family == AF_INET || sel->prefixlen_d == 32)
+ {
+ type = TS_IPV4_ADDR_RANGE;
+ addr.len = 4;
+ }
+ else
+ {
+ type = TS_IPV6_ADDR_RANGE;
+ addr.len = 16;
+ }
+ if (port_mask == 0)
+ {
+ from_port = 0;
+ to_port = 65535;
+ }
+ else
+ {
+ from_port = to_port = ntohs(port);
+ }
+
+ return traffic_selector_create_from_bytes(sel->proto, type,
+ addr, from_port, addr, to_port);
+}
/**
* process a XFRM_MSG_ACQUIRE from kernel
{
u_int32_t reqid = 0;
int proto = 0;
+ traffic_selector_t *src_ts, *dst_ts;
+ struct xfrm_user_acquire *acquire;
+ struct rtattr *rtattr;
+ size_t rtsize;
job_t *job;
- struct rtattr *rtattr = XFRM_RTA(hdr, struct xfrm_user_acquire);
- size_t rtsize = XFRM_PAYLOAD(hdr, struct xfrm_user_tmpl);
+ rtattr = XFRM_RTA(hdr, struct xfrm_user_acquire);
+ rtsize = XFRM_PAYLOAD(hdr, struct xfrm_user_tmpl);
+
if (RTA_OK(rtattr, rtsize))
{
if (rtattr->rta_type == XFRMA_TMPL)
{
- struct xfrm_user_tmpl* tmpl = (struct xfrm_user_tmpl*)RTA_DATA(rtattr);
+ struct xfrm_user_tmpl* tmpl;
+
+ tmpl = (struct xfrm_user_tmpl*)RTA_DATA(rtattr);
reqid = tmpl->reqid;
proto = tmpl->id.proto;
}
/* acquire for AH/ESP only, not for IPCOMP */
return;
}
- if (reqid == 0)
- {
- DBG1(DBG_KNL, "received a XFRM_MSG_ACQUIRE, but no reqid found");
- return;
- }
DBG2(DBG_KNL, "received a XFRM_MSG_ACQUIRE");
- DBG1(DBG_KNL, "creating acquire job for CHILD_SA with reqid {%d}", reqid);
- job = (job_t*)acquire_job_create(reqid);
+
+ acquire = (struct xfrm_user_acquire*)NLMSG_DATA(hdr);
+ src_ts = selector2ts(&acquire->sel, TRUE);
+ dst_ts = selector2ts(&acquire->sel, FALSE);
+ DBG1(DBG_KNL, "creating acquire job %R === %R for CHILD_SA with reqid {%d}",
+ src_ts, dst_ts, reqid);
+ job = (job_t*)acquire_job_create(reqid, src_ts, dst_ts);
charon->processor->queue_job(charon->processor, job);
}
}
/**
+ * process a XFRM_MSG_MIGRATE from kernel
+ */
+static void process_migrate(private_kernel_netlink_ipsec_t *this, struct nlmsghdr *hdr)
+{
+ DBG2(DBG_KNL, "received a XFRM_MSG_MIGRATE");
+}
+
+/**
+ * process a XFRM_MSG_MAPPING from kernel
+ */
+static void process_mapping(private_kernel_netlink_ipsec_t *this,
+ struct nlmsghdr *hdr)
+{
+ job_t *job;
+ u_int32_t spi, reqid;
+ struct xfrm_user_mapping *mapping;
+ host_t *host;
+
+ mapping = (struct xfrm_user_mapping*)NLMSG_DATA(hdr);
+ spi = mapping->id.spi;
+ reqid = mapping->reqid;
+
+ DBG2(DBG_KNL, "received a XFRM_MSG_MAPPING");
+
+ if (proto_kernel2ike(mapping->id.proto) == PROTO_ESP)
+ {
+ host = xfrm2host(mapping->id.family, &mapping->new_saddr,
+ mapping->new_sport);
+ if (host)
+ {
+ DBG1(DBG_KNL, "NAT mappings of ESP CHILD_SA with SPI %.8x and "
+ "reqid {%d} changed, queuing update job", ntohl(spi), reqid);
+ job = (job_t*)update_sa_job_create(reqid, host);
+ charon->processor->queue_job(charon->processor, job);
+ }
+ }
+}
+
+/**
* Receives events from kernel
*/
static job_requeue_t receive_events(private_kernel_netlink_ipsec_t *this)
case XFRM_MSG_EXPIRE:
process_expire(this, hdr);
break;
+ case XFRM_MSG_MIGRATE:
+ process_migrate(this, hdr);
+ break;
+ case XFRM_MSG_MAPPING:
+ process_mapping(this, hdr);
+ break;
default:
break;
}
}
/**
- * Tries to find an ip address of a local interface that is included in the
- * supplied traffic selector.
- */
-static status_t get_address_by_ts(private_kernel_netlink_ipsec_t *this,
- traffic_selector_t *ts, host_t **ip)
-{
- enumerator_t *addrs;
- host_t *host;
- int family;
- bool found = FALSE;
-
- DBG2(DBG_KNL, "getting a local address in traffic selector %R", ts);
-
- /* if we have a family which includes localhost, we do not
- * search for an IP, we use the default */
- family = ts->get_type(ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6;
-
- if (family == AF_INET)
- {
- host = host_create_from_string("127.0.0.1", 0);
- }
- else
- {
- host = host_create_from_string("::1", 0);
- }
-
- if (ts->includes(ts, host))
- {
- *ip = host_create_any(family);
- host->destroy(host);
- DBG2(DBG_KNL, "using host %H", *ip);
- return SUCCESS;
- }
- host->destroy(host);
-
- addrs = charon->kernel_interface->create_address_enumerator(
- charon->kernel_interface, TRUE, TRUE);
- while (addrs->enumerate(addrs, (void**)&host))
- {
- if (ts->includes(ts, host))
- {
- found = TRUE;
- *ip = host->clone(host);
- break;
- }
- }
- addrs->destroy(addrs);
-
- if (!found)
- {
- DBG1(DBG_KNL, "no local address found in traffic selector %R", ts);
- return FAILED;
- }
- DBG2(DBG_KNL, "using host %H", *ip);
- return SUCCESS;
-}
-
-/**
* Get an SPI for a specific protocol from the kernel.
*/
static status_t get_spi_internal(private_kernel_netlink_ipsec_t *this,
host_t *src, host_t *dst, u_int32_t spi,
protocol_id_t protocol, u_int32_t reqid,
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,
- u_int16_t ipcomp, bool encap,
+ u_int16_t enc_alg, chunk_t enc_key,
+ u_int16_t int_alg, chunk_t int_key,
+ ipsec_mode_t mode, u_int16_t ipcomp, bool encap,
bool replace)
{
unsigned char request[NETLINK_BUFFER_SIZE];
char *alg_name;
- /* additional 4 octets KEYMAT required for AES-GCM as of RFC4106 8.1. */
- u_int16_t add_keymat = 32;
struct nlmsghdr *hdr;
struct xfrm_usersa_info *sa;
+ u_int16_t icv_size = 64;
memset(&request, 0, sizeof(request));
- DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%d}", ntohl(spi), reqid);
-
+ DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%d}",
+ ntohl(spi), reqid);
+
hdr = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
hdr->nlmsg_type = replace ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
case ENCR_UNDEFINED:
/* no encryption */
break;
- case ENCR_AES_CCM_ICV8:
- case ENCR_AES_CCM_ICV12:
case ENCR_AES_CCM_ICV16:
- /* AES-CCM needs only 3 additional octets KEYMAT as of RFC 4309 7.1. */
- add_keymat = 24;
- /* fall-through */
- case ENCR_AES_GCM_ICV8:
- case ENCR_AES_GCM_ICV12:
case ENCR_AES_GCM_ICV16:
+ icv_size += 32;
+ /* FALL */
+ case ENCR_AES_CCM_ICV12:
+ case ENCR_AES_GCM_ICV12:
+ icv_size += 32;
+ /* FALL */
+ case ENCR_AES_CCM_ICV8:
+ case ENCR_AES_GCM_ICV8:
{
- u_int16_t icv_size = 0;
rthdr->rta_type = XFRMA_ALG_AEAD;
- alg_name = lookup_algorithm(encryption_algs, enc_alg, &icv_size);
+ alg_name = lookup_algorithm(encryption_algs, enc_alg);
if (alg_name == NULL)
{
DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
return FAILED;
}
DBG2(DBG_KNL, " using encryption algorithm %N with key size %d",
- encryption_algorithm_names, enc_alg, enc_size);
+ encryption_algorithm_names, enc_alg, enc_key.len * 8);
- /* additional KEYMAT required */
- enc_size += add_keymat;
-
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_aead) + enc_size / 8);
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_aead) + enc_key.len);
hdr->nlmsg_len += rthdr->rta_len;
if (hdr->nlmsg_len > sizeof(request))
{
}
struct xfrm_algo_aead* algo = (struct xfrm_algo_aead*)RTA_DATA(rthdr);
- algo->alg_key_len = enc_size;
+ algo->alg_key_len = enc_key.len * 8;
algo->alg_icv_len = icv_size;
strcpy(algo->alg_name, alg_name);
- prf_plus->get_bytes(prf_plus, enc_size / 8, algo->alg_key);
+ memcpy(algo->alg_key, enc_key.ptr, enc_key.len);
rthdr = XFRM_RTA_NEXT(rthdr);
break;
default:
{
rthdr->rta_type = XFRMA_ALG_CRYPT;
- alg_name = lookup_algorithm(encryption_algs, enc_alg, &enc_size);
+ alg_name = lookup_algorithm(encryption_algs, enc_alg);
if (alg_name == NULL)
{
DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
return FAILED;
}
DBG2(DBG_KNL, " using encryption algorithm %N with key size %d",
- encryption_algorithm_names, enc_alg, enc_size);
+ encryption_algorithm_names, enc_alg, enc_key.len * 8);
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + enc_size / 8);
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + enc_key.len);
hdr->nlmsg_len += rthdr->rta_len;
if (hdr->nlmsg_len > sizeof(request))
{
}
struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr);
- algo->alg_key_len = enc_size;
+ algo->alg_key_len = enc_key.len * 8;
strcpy(algo->alg_name, alg_name);
- prf_plus->get_bytes(prf_plus, enc_size / 8, algo->alg_key);
+ memcpy(algo->alg_key, enc_key.ptr, enc_key.len);
rthdr = XFRM_RTA_NEXT(rthdr);
break;
if (int_alg != AUTH_UNDEFINED)
{
rthdr->rta_type = XFRMA_ALG_AUTH;
- alg_name = lookup_algorithm(integrity_algs, int_alg, &int_size);
+ alg_name = lookup_algorithm(integrity_algs, int_alg);
if (alg_name == NULL)
{
DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
return FAILED;
}
DBG2(DBG_KNL, " using integrity algorithm %N with key size %d",
- integrity_algorithm_names, int_alg, int_size);
+ integrity_algorithm_names, int_alg, int_key.len * 8);
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + int_size / 8);
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + int_key.len);
hdr->nlmsg_len += rthdr->rta_len;
if (hdr->nlmsg_len > sizeof(request))
{
}
struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr);
- algo->alg_key_len = int_size;
+ algo->alg_key_len = int_key.len * 8;
strcpy(algo->alg_name, alg_name);
- prf_plus->get_bytes(prf_plus, int_size / 8, algo->alg_key);
+ memcpy(algo->alg_key, int_key.ptr, int_key.len);
rthdr = XFRM_RTA_NEXT(rthdr);
}
if (ipcomp != IPCOMP_NONE)
{
rthdr->rta_type = XFRMA_ALG_COMP;
- alg_name = lookup_algorithm(compression_algs, ipcomp, NULL);
+ alg_name = lookup_algorithm(compression_algs, ipcomp);
if (alg_name == NULL)
{
DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
}
/**
- * Implementation of kernel_interface_t.query_sa.
- */
-static status_t query_sa(private_kernel_netlink_ipsec_t *this, host_t *dst,
- u_int32_t spi, protocol_id_t protocol,
- u_int32_t *use_time)
-{
- unsigned char request[NETLINK_BUFFER_SIZE];
- struct nlmsghdr *out = NULL, *hdr;
- struct xfrm_usersa_id *sa_id;
- struct xfrm_usersa_info *sa = NULL;
- size_t len;
-
- DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi));
- memset(&request, 0, sizeof(request));
-
- hdr = (struct nlmsghdr*)request;
- hdr->nlmsg_flags = NLM_F_REQUEST;
- hdr->nlmsg_type = XFRM_MSG_GETSA;
- hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
-
- sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
- host2xfrm(dst, &sa_id->daddr);
- sa_id->spi = spi;
- sa_id->proto = proto_ike2kernel(protocol);
- sa_id->family = dst->get_family(dst);
-
- if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
- {
- hdr = out;
- while (NLMSG_OK(hdr, len))
- {
- switch (hdr->nlmsg_type)
- {
- case XFRM_MSG_NEWSA:
- {
- sa = NLMSG_DATA(hdr);
- break;
- }
- case NLMSG_ERROR:
- {
- struct nlmsgerr *err = NLMSG_DATA(hdr);
- DBG1(DBG_KNL, "querying SAD entry failed: %s (%d)",
- strerror(-err->error), -err->error);
- break;
- }
- default:
- hdr = NLMSG_NEXT(hdr, len);
- continue;
- case NLMSG_DONE:
- break;
- }
- break;
- }
- }
-
- if (sa == NULL)
- {
- DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi));
- free(out);
- return FAILED;
- }
-
- *use_time = sa->curlft.use_time;
- free (out);
- return SUCCESS;
-}
-
-/**
* Implementation of kernel_interface_t.del_sa.
*/
static status_t del_sa(private_kernel_netlink_ipsec_t *this, host_t *dst,
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, ipsec_mode_t mode,
u_int16_t ipcomp)
{
iterator_t *iterator;
{
route_entry_t *route = malloc_thing(route_entry_t);
- if (get_address_by_ts(this, dst_ts, &route->src_ip) == SUCCESS)
+ if (charon->kernel_interface->get_address_by_ts(charon->kernel_interface,
+ dst_ts, &route->src_ip) == SUCCESS)
{
/* get the nexthop to src (src as we are in POLICY_FWD).*/
route->gateway = charon->kernel_interface->get_nexthop(
iterator = this->policies->create_iterator_locked(this->policies, &this->mutex);
while (iterator->iterate(iterator, (void**)¤t))
{
- if (memcmp(¤t->sel, &policy.sel, sizeof(struct xfrm_selector)) == 0 &&
+ if (memeq(¤t->sel, &policy.sel, sizeof(struct xfrm_selector)) &&
policy.direction == current->direction)
{
to_delete = current;
/* public functions */
this->public.interface.get_spi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
this->public.interface.get_cpi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
- this->public.interface.add_sa = (status_t(*)(kernel_ipsec_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.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,bool,bool))add_sa;
this->public.interface.update_sa = (status_t(*)(kernel_ipsec_t*,u_int32_t,protocol_id_t,host_t*,host_t*,host_t*,host_t*,bool))update_sa;
- this->public.interface.query_sa = (status_t(*)(kernel_ipsec_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t*))query_sa;
this->public.interface.del_sa = (status_t(*)(kernel_ipsec_t*,host_t*,u_int32_t,protocol_id_t))del_sa;
- this->public.interface.add_policy = (status_t(*)(kernel_ipsec_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.interface.add_policy = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,protocol_id_t,u_int32_t,bool,ipsec_mode_t,u_int16_t))add_policy;
this->public.interface.query_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy;
this->public.interface.del_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t))del_policy;
this->public.interface.destroy = (void(*)(kernel_ipsec_t*)) destroy;
{
charon->kill(charon, "unable to create XFRM event socket");
}
- addr.nl_groups = XFRMGRP_ACQUIRE | XFRMGRP_EXPIRE;
+ addr.nl_groups = XFRMNLGRP(ACQUIRE) | XFRMNLGRP(EXPIRE) | XFRMNLGRP(MAPPING);
if (bind(this->socket_xfrm_events, (struct sockaddr*)&addr, sizeof(addr)))
{
charon->kill(charon, "unable to bind XFRM event socket");