summaryrefslogtreecommitdiff
path: root/src/charon/plugins/kernel_netlink
diff options
context:
space:
mode:
Diffstat (limited to 'src/charon/plugins/kernel_netlink')
-rw-r--r--src/charon/plugins/kernel_netlink/Makefile.in18
-rw-r--r--src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c185
-rw-r--r--src/charon/plugins/kernel_netlink/kernel_netlink_net.c5
-rw-r--r--src/charon/plugins/kernel_netlink/kernel_netlink_shared.c22
4 files changed, 145 insertions, 85 deletions
diff --git a/src/charon/plugins/kernel_netlink/Makefile.in b/src/charon/plugins/kernel_netlink/Makefile.in
index 658e0feea..b3b161315 100644
--- a/src/charon/plugins/kernel_netlink/Makefile.in
+++ b/src/charon/plugins/kernel_netlink/Makefile.in
@@ -88,22 +88,17 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
-CXX = @CXX@
-CXXCPP = @CXXCPP@
-CXXDEPMODE = @CXXDEPMODE@
-CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DSYMUTIL = @DSYMUTIL@
-ECHO = @ECHO@
+DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
-F77 = @F77@
-FFLAGS = @FFLAGS@
+FGREP = @FGREP@
GPERF = @GPERF@
GREP = @GREP@
INSTALL = @INSTALL@
@@ -113,6 +108,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
IPSEC_ROUTING_TABLE = @IPSEC_ROUTING_TABLE@
IPSEC_ROUTING_TABLE_PRIO = @IPSEC_ROUTING_TABLE_PRIO@
+LD = @LD@
LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
@@ -121,12 +117,16 @@ LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LINUX_HEADERS = @LINUX_HEADERS@
+LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
+NM = @NM@
NMEDIT = @NMEDIT@
OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
@@ -149,8 +149,7 @@ abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
-ac_ct_CXX = @ac_ct_CXX@
-ac_ct_F77 = @ac_ct_F77@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -189,6 +188,7 @@ libstrongswan_plugins = @libstrongswan_plugins@
linuxdir = @linuxdir@
localedir = @localedir@
localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
nm_CFLAGS = @nm_CFLAGS@
diff --git a/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c
index 70a0b3e7c..8a13ed489 100644
--- a/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -17,7 +17,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: kernel_netlink_ipsec.c 4662 2008-11-16 21:19:58Z andreas $
+ * $Id: kernel_netlink_ipsec.c 4831 2009-01-09 09:37:13Z andreas $
*/
#include <sys/types.h>
@@ -39,7 +39,7 @@
#include <daemon.h>
#include <utils/mutex.h>
-#include <utils/linked_list.h>
+#include <utils/hashtable.h>
#include <processing/jobs/callback_job.h>
#include <processing/jobs/acquire_job.h>
#include <processing/jobs/migrate_job.h>
@@ -57,6 +57,11 @@
#define IP_IPSEC_POLICY 16
#endif
+/* missing on uclibc */
+#ifndef IPV6_IPSEC_POLICY
+#define IPV6_IPSEC_POLICY 34
+#endif /*IPV6_IPSEC_POLICY*/
+
/** default priority of installed policies */
#define PRIO_LOW 3000
#define PRIO_HIGH 2000
@@ -92,13 +97,39 @@ struct kernel_algorithm_t {
* Identifier specified in IKEv2
*/
int ikev2;
-
+
/**
* Name of the algorithm in linux crypto API
*/
char *name;
};
+ENUM(xfrm_msg_names, XFRM_MSG_NEWSA, XFRM_MSG_MAPPING,
+ "XFRM_MSG_NEWSA",
+ "XFRM_MSG_DELSA",
+ "XFRM_MSG_GETSA",
+ "XFRM_MSG_NEWPOLICY",
+ "XFRM_MSG_DELPOLICY",
+ "XFRM_MSG_GETPOLICY",
+ "XFRM_MSG_ALLOCSPI",
+ "XFRM_MSG_ACQUIRE",
+ "XFRM_MSG_EXPIRE",
+ "XFRM_MSG_UPDPOLICY",
+ "XFRM_MSG_UPDSA",
+ "XFRM_MSG_POLEXPIRE",
+ "XFRM_MSG_FLUSHSA",
+ "XFRM_MSG_FLUSHPOLICY",
+ "XFRM_MSG_NEWAE",
+ "XFRM_MSG_GETAE",
+ "XFRM_MSG_REPORT",
+ "XFRM_MSG_MIGRATE",
+ "XFRM_MSG_NEWSADINFO",
+ "XFRM_MSG_GETSADINFO",
+ "XFRM_MSG_NEWSPDINFO",
+ "XFRM_MSG_GETSPDINFO",
+ "XFRM_MSG_MAPPING"
+);
+
ENUM(xfrm_attr_type_names, XFRMA_UNSPEC, XFRMA_KMADDRESS,
"XFRMA_UNSPEC",
"XFRMA_ALG_AUTH",
@@ -245,6 +276,24 @@ struct policy_entry_t {
u_int refcount;
};
+/**
+ * Hash function for policy_entry_t objects
+ */
+static u_int policy_hash(policy_entry_t *key)
+{
+ chunk_t chunk = chunk_create((void*)&key->sel, sizeof(struct xfrm_selector));
+ return chunk_hash(chunk);
+}
+
+/**
+ * Equality function for policy_entry_t objects
+ */
+static bool policy_equals(policy_entry_t *key, policy_entry_t *other_key)
+{
+ return memeq(&key->sel, &other_key->sel, sizeof(struct xfrm_selector)) &&
+ key->direction == other_key->direction;
+}
+
typedef struct private_kernel_netlink_ipsec_t private_kernel_netlink_ipsec_t;
/**
@@ -262,9 +311,9 @@ struct private_kernel_netlink_ipsec_t {
mutex_t *mutex;
/**
- * List of installed policies (policy_entry_t)
+ * Hash table of installed policies (policy_entry_t)
*/
- linked_list_t *policies;
+ hashtable_t *policies;
/**
* job receiving netlink events
@@ -418,51 +467,48 @@ static struct xfrm_selector ts2selector(traffic_selector_t *src,
*/
static traffic_selector_t* selector2ts(struct xfrm_selector *sel, bool src)
{
- int family;
- chunk_t addr;
+ u_char *addr;
u_int8_t prefixlen;
- u_int16_t port, port_mask;
- host_t *host;
- traffic_selector_t *ts;
-
+ u_int16_t port = 0;
+ host_t *host = NULL;
+
if (src)
{
- addr.ptr = (u_char*)&sel->saddr;
+ addr = (u_char*)&sel->saddr;
prefixlen = sel->prefixlen_s;
- port = sel->sport;
- port_mask = sel->sport_mask;
+ if (sel->sport_mask)
+ {
+ port = htons(sel->sport);
+ }
}
- else
+ else
{
- addr.ptr = (u_char*)&sel->daddr;
+ addr = (u_char*)&sel->daddr;
prefixlen = sel->prefixlen_d;
- port = sel->dport;
- port_mask = sel->dport_mask;
+ if (sel->dport_mask)
+ {
+ port = htons(sel->dport);
+ }
}
-
+
/* The Linux 2.6 kernel does not set the selector's family field,
- * so as a kludge we additionally test the prefix length.
+ * so as a kludge we additionally test the prefix length.
*/
if (sel->family == AF_INET || sel->prefixlen_s == 32)
{
- family = AF_INET;
- addr.len = 4;
+ host = host_create_from_chunk(AF_INET, chunk_create(addr, 4), 0);
}
else if (sel->family == AF_INET6 || sel->prefixlen_s == 128)
{
- family = AF_INET6;
- addr.len = 16;
+ host = host_create_from_chunk(AF_INET6, chunk_create(addr, 16), 0);
}
- else
+
+ if (host)
{
- return NULL;
+ return traffic_selector_create_from_subnet(host, prefixlen,
+ sel->proto, port);
}
- host = host_create_from_chunk(family, addr, 0);
- port = (port_mask == 0) ? 0 : ntohs(port);
-
- ts = traffic_selector_create_from_subnet(host, prefixlen, sel->proto, port);
- host->destroy(host);
- return ts;
+ return NULL;
}
/**
@@ -1064,7 +1110,7 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
* the IPsec checks it marks them "checksum ok" so OA isn't needed. */
rthdr = XFRM_RTA_NEXT(rthdr);
}
-
+
if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
{
DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
@@ -1370,7 +1416,7 @@ static status_t update_sa(private_kernel_netlink_ipsec_t *this,
rta = XFRM_RTA_NEXT(rta);
}
-
+
if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
{
DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi));
@@ -1394,7 +1440,6 @@ static status_t add_policy(private_kernel_netlink_ipsec_t *this,
ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
bool routed)
{
- iterator_t *iterator;
policy_entry_t *current, *policy;
bool found = FALSE;
netlink_buf_t request;
@@ -1409,27 +1454,21 @@ static status_t add_policy(private_kernel_netlink_ipsec_t *this,
/* find the policy, which matches EXACTLY */
this->mutex->lock(this->mutex);
- iterator = this->policies->create_iterator(this->policies, TRUE);
- while (iterator->iterate(iterator, (void**)&current))
+ current = this->policies->get(this->policies, policy);
+ if (current)
{
- if (memeq(&current->sel, &policy->sel, sizeof(struct xfrm_selector)) &&
- policy->direction == current->direction)
- {
- /* use existing policy */
- current->refcount++;
- DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing "
- "refcount", src_ts, dst_ts,
- policy_dir_names, direction);
- free(policy);
- policy = current;
- found = TRUE;
- break;
- }
+ /* use existing policy */
+ current->refcount++;
+ DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing "
+ "refcount", src_ts, dst_ts,
+ policy_dir_names, direction);
+ free(policy);
+ policy = current;
+ found = TRUE;
}
- iterator->destroy(iterator);
- if (!found)
+ else
{ /* apply the new one, if we have no such policy */
- this->policies->insert_last(this->policies, policy);
+ this->policies->put(this->policies, policy, policy);
policy->refcount = 1;
}
@@ -1657,7 +1696,6 @@ static status_t del_policy(private_kernel_netlink_ipsec_t *this,
netlink_buf_t request;
struct nlmsghdr *hdr;
struct xfrm_userpolicy_id *policy_id;
- enumerator_t *enumerator;
DBG2(DBG_KNL, "deleting policy %R === %R %N", src_ts, dst_ts,
policy_dir_names, direction);
@@ -1669,28 +1707,21 @@ static status_t del_policy(private_kernel_netlink_ipsec_t *this,
/* find the policy */
this->mutex->lock(this->mutex);
- enumerator = this->policies->create_enumerator(this->policies);
- while (enumerator->enumerate(enumerator, &current))
+ current = this->policies->get(this->policies, &policy);
+ if (current)
{
- if (memeq(&current->sel, &policy.sel, sizeof(struct xfrm_selector)) &&
- policy.direction == current->direction)
+ to_delete = current;
+ if (--to_delete->refcount > 0)
{
- to_delete = current;
- if (--to_delete->refcount > 0)
- {
- /* is used by more SAs, keep in kernel */
- DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed");
- this->mutex->unlock(this->mutex);
- enumerator->destroy(enumerator);
- return SUCCESS;
- }
- /* remove if last reference */
- this->policies->remove_at(this->policies, enumerator);
- break;
+ /* is used by more SAs, keep in kernel */
+ DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed");
+ this->mutex->unlock(this->mutex);
+ return SUCCESS;
}
+ /* remove if last reference */
+ this->policies->remove(this->policies, to_delete);
}
this->mutex->unlock(this->mutex);
- enumerator->destroy(enumerator);
if (!to_delete)
{
DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts,
@@ -1739,9 +1770,18 @@ static status_t del_policy(private_kernel_netlink_ipsec_t *this,
*/
static void destroy(private_kernel_netlink_ipsec_t *this)
{
+ enumerator_t *enumerator;
+ policy_entry_t *policy;
+
this->job->cancel(this->job);
close(this->socket_xfrm_events);
this->socket_xfrm->destroy(this->socket_xfrm);
+ enumerator = this->policies->create_enumerator(this->policies);
+ while (enumerator->enumerate(enumerator, &policy, &policy))
+ {
+ free(policy);
+ }
+ enumerator->destroy(enumerator);
this->policies->destroy(this->policies);
this->mutex->destroy(this->mutex);
free(this);
@@ -1832,7 +1872,8 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
this->public.interface.destroy = (void(*)(kernel_ipsec_t*)) destroy;
/* private members */
- this->policies = linked_list_create();
+ this->policies = hashtable_create((hashtable_hash_t)policy_hash,
+ (hashtable_equals_t)policy_equals, 32);
this->mutex = mutex_create(MUTEX_DEFAULT);
this->install_routes = lib->settings->get_bool(lib->settings,
"charon.install_routes", TRUE);
diff --git a/src/charon/plugins/kernel_netlink/kernel_netlink_net.c b/src/charon/plugins/kernel_netlink/kernel_netlink_net.c
index 69a781c14..6e4ddffe5 100644
--- a/src/charon/plugins/kernel_netlink/kernel_netlink_net.c
+++ b/src/charon/plugins/kernel_netlink/kernel_netlink_net.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: kernel_netlink_net.c 4660 2008-11-14 14:23:11Z martin $
+ * $Id: kernel_netlink_net.c 4671 2008-11-18 09:52:28Z martin $
*/
#include <sys/socket.h>
@@ -707,7 +707,8 @@ static bool is_interface_up(private_kernel_netlink_net_t *this, int index)
{
enumerator_t *ifaces;
iface_entry_t *iface;
- bool up = FALSE;
+ /* default to TRUE for interface we do not monitor (e.g. lo) */
+ bool up = TRUE;
ifaces = this->ifaces->create_enumerator(this->ifaces);
while (ifaces->enumerate(ifaces, &iface))
diff --git a/src/charon/plugins/kernel_netlink/kernel_netlink_shared.c b/src/charon/plugins/kernel_netlink/kernel_netlink_shared.c
index 3de56bf48..05bd4e397 100644
--- a/src/charon/plugins/kernel_netlink/kernel_netlink_shared.c
+++ b/src/charon/plugins/kernel_netlink/kernel_netlink_shared.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: kernel_netlink_shared.c 4579 2008-11-05 11:29:56Z martin $
+ * $Id: kernel_netlink_shared.c 4831 2009-01-09 09:37:13Z andreas $
*/
#include <sys/socket.h>
@@ -46,7 +46,12 @@ struct private_netlink_socket_t {
* current sequence number for netlink request
*/
int seq;
-
+
+ /**
+ * netlink socket protocol
+ */
+ int protocol;
+
/**
* netlink socket
*/
@@ -54,6 +59,11 @@ struct private_netlink_socket_t {
};
/**
+ * Imported from kernel_netlink_ipsec.c
+ */
+extern enum_name_t *xfrm_msg_names;
+
+/**
* Implementation of netlink_socket_t.send
*/
static status_t netlink_send(private_netlink_socket_t *this, struct nlmsghdr *in,
@@ -74,6 +84,13 @@ static status_t netlink_send(private_netlink_socket_t *this, struct nlmsghdr *in
addr.nl_pid = 0;
addr.nl_groups = 0;
+ if (this->protocol == NETLINK_XFRM)
+ {
+ chunk_t in_chunk = { (u_char*)in, in->nlmsg_len };
+
+ DBG3(DBG_KNL, "sending %N: %B", xfrm_msg_names, in->nlmsg_type, &in_chunk);
+ }
+
while (TRUE)
{
len = sendto(this->socket, in, in->nlmsg_len, 0,
@@ -245,6 +262,7 @@ netlink_socket_t *netlink_socket_create(int protocol) {
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
+ this->protocol = protocol;
this->socket = socket(AF_NETLINK, SOCK_RAW, protocol);
if (this->socket <= 0)
{