summaryrefslogtreecommitdiff
path: root/src/libhydra/plugins/kernel_netlink
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2013-08-25 15:37:26 +0200
committerYves-Alexis Perez <corsac@debian.org>2013-08-25 15:37:26 +0200
commit6b99c8d9cff7b3e8ae8f3204b99e7ea40f791349 (patch)
tree009fc492961e13860d2a4bc2de8caf2bbe2975e7 /src/libhydra/plugins/kernel_netlink
parentc83921a2b566aa9d55d8ccc7258f04fca6292ee6 (diff)
downloadvyos-strongswan-6b99c8d9cff7b3e8ae8f3204b99e7ea40f791349.tar.gz
vyos-strongswan-6b99c8d9cff7b3e8ae8f3204b99e7ea40f791349.zip
Imported Upstream version 5.1.0
Diffstat (limited to 'src/libhydra/plugins/kernel_netlink')
-rw-r--r--src/libhydra/plugins/kernel_netlink/Makefile.am14
-rw-r--r--src/libhydra/plugins/kernel_netlink/Makefile.in78
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c82
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c80
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.c8
5 files changed, 169 insertions, 93 deletions
diff --git a/src/libhydra/plugins/kernel_netlink/Makefile.am b/src/libhydra/plugins/kernel_netlink/Makefile.am
index 1ad379421..ad573523e 100644
--- a/src/libhydra/plugins/kernel_netlink/Makefile.am
+++ b/src/libhydra/plugins/kernel_netlink/Makefile.am
@@ -1,10 +1,12 @@
+AM_CPPFLAGS = \
+ -I${linux_headers} \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -DROUTING_TABLE=${routing_table} \
+ -DROUTING_TABLE_PRIO=${routing_table_prio}
-INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
- -I$(top_srcdir)/src/libhydra
-
-AM_CFLAGS = -rdynamic \
--DROUTING_TABLE=${routing_table} \
--DROUTING_TABLE_PRIO=${routing_table_prio}
+AM_CFLAGS = \
+ -rdynamic
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-kernel-netlink.la
diff --git a/src/libhydra/plugins/kernel_netlink/Makefile.in b/src/libhydra/plugins/kernel_netlink/Makefile.in
index 9702010bb..9cb988c8d 100644
--- a/src/libhydra/plugins/kernel_netlink/Makefile.in
+++ b/src/libhydra/plugins/kernel_netlink/Makefile.in
@@ -62,7 +62,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
$(top_srcdir)/m4/macros/with.m4 \
$(top_srcdir)/m4/macros/enable-disable.m4 \
$(top_srcdir)/m4/macros/add-plugin.m4 \
- $(top_srcdir)/configure.in
+ $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@@ -104,7 +104,10 @@ am_libstrongswan_kernel_netlink_la_OBJECTS = kernel_netlink_plugin.lo \
kernel_netlink_shared.lo
libstrongswan_kernel_netlink_la_OBJECTS = \
$(am_libstrongswan_kernel_netlink_la_OBJECTS)
-libstrongswan_kernel_netlink_la_LINK = $(LIBTOOL) --tag=CC \
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+libstrongswan_kernel_netlink_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
$(AM_CFLAGS) $(CFLAGS) \
$(libstrongswan_kernel_netlink_la_LDFLAGS) $(LDFLAGS) -o $@
@@ -117,13 +120,26 @@ am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
- $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
CCLD = $(CC)
-LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
- $(LDFLAGS) -o $@
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
SOURCES = $(libstrongswan_kernel_netlink_la_SOURCES)
DIST_SOURCES = $(libstrongswan_kernel_netlink_la_SOURCES)
am__can_run_installinfo = \
@@ -137,6 +153,7 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
@@ -149,6 +166,8 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CHECK_CFLAGS = @CHECK_CFLAGS@
CHECK_LIBS = @CHECK_LIBS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
@@ -164,6 +183,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
GREP = @GREP@
@@ -172,6 +192,7 @@ INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
LD = @LD@
LDFLAGS = @LDFLAGS@
LEX = @LEX@
@@ -218,6 +239,7 @@ SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SOCKLIB = @SOCKLIB@
STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
VERSION = @VERSION@
YACC = @YACC@
YFLAGS = @YFLAGS@
@@ -246,6 +268,7 @@ charon_natt_port = @charon_natt_port@
charon_plugins = @charon_plugins@
charon_udp_port = @charon_udp_port@
clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
@@ -323,12 +346,15 @@ top_srcdir = @top_srcdir@
urandom_device = @urandom_device@
xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
-INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
- -I$(top_srcdir)/src/libhydra
+AM_CPPFLAGS = \
+ -I${linux_headers} \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -DROUTING_TABLE=${routing_table} \
+ -DROUTING_TABLE_PRIO=${routing_table_prio}
-AM_CFLAGS = -rdynamic \
--DROUTING_TABLE=${routing_table} \
--DROUTING_TABLE_PRIO=${routing_table_prio}
+AM_CFLAGS = \
+ -rdynamic
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-kernel-netlink.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-kernel-netlink.la
@@ -415,7 +441,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-kernel-netlink.la: $(libstrongswan_kernel_netlink_la_OBJECTS) $(libstrongswan_kernel_netlink_la_DEPENDENCIES) $(EXTRA_libstrongswan_kernel_netlink_la_DEPENDENCIES)
- $(libstrongswan_kernel_netlink_la_LINK) $(am_libstrongswan_kernel_netlink_la_rpath) $(libstrongswan_kernel_netlink_la_OBJECTS) $(libstrongswan_kernel_netlink_la_LIBADD) $(LIBS)
+ $(AM_V_CCLD)$(libstrongswan_kernel_netlink_la_LINK) $(am_libstrongswan_kernel_netlink_la_rpath) $(libstrongswan_kernel_netlink_la_OBJECTS) $(libstrongswan_kernel_netlink_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -429,25 +455,25 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_netlink_shared.Plo@am__quote@
.c.o:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
.c.obj:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
.c.lo:
-@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
index 9b4ade533..b34fa149c 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -37,11 +37,9 @@
#include <hydra.h>
#include <utils/debug.h>
-#include <threading/thread.h>
#include <threading/mutex.h>
#include <collections/hashtable.h>
#include <collections/linked_list.h>
-#include <processing/jobs/callback_job.h>
/** Required for Linux 2.6.26 kernel and later */
#ifndef XFRM_STATE_AF_UNSPEC
@@ -558,6 +556,9 @@ struct policy_entry_t {
/** List of SAs this policy is used by, ordered by priority */
linked_list_t *used_by;
+
+ /** reqid for this policy */
+ u_int32_t reqid;
};
/**
@@ -969,40 +970,37 @@ static void process_mapping(private_kernel_netlink_ipsec_t *this,
/**
* Receives events from kernel
*/
-static job_requeue_t receive_events(private_kernel_netlink_ipsec_t *this)
+static bool receive_events(private_kernel_netlink_ipsec_t *this, int fd,
+ watcher_event_t event)
{
char response[1024];
struct nlmsghdr *hdr = (struct nlmsghdr*)response;
struct sockaddr_nl addr;
socklen_t addr_len = sizeof(addr);
int len;
- bool oldstate;
-
- oldstate = thread_cancelability(TRUE);
- len = recvfrom(this->socket_xfrm_events, response, sizeof(response), 0,
- (struct sockaddr*)&addr, &addr_len);
- thread_cancelability(oldstate);
+ len = recvfrom(this->socket_xfrm_events, response, sizeof(response),
+ MSG_DONTWAIT, (struct sockaddr*)&addr, &addr_len);
if (len < 0)
{
switch (errno)
{
case EINTR:
/* interrupted, try again */
- return JOB_REQUEUE_DIRECT;
+ return TRUE;
case EAGAIN:
/* no data ready, select again */
- return JOB_REQUEUE_DIRECT;
+ return TRUE;
default:
DBG1(DBG_KNL, "unable to receive from xfrm event socket");
sleep(1);
- return JOB_REQUEUE_FAIR;
+ return TRUE;
}
}
if (addr.nl_pid != 0)
{ /* not from kernel. not interested, try another one */
- return JOB_REQUEUE_DIRECT;
+ return TRUE;
}
while (NLMSG_OK(hdr, len))
@@ -1028,7 +1026,7 @@ static job_requeue_t receive_events(private_kernel_netlink_ipsec_t *this)
}
hdr = NLMSG_NEXT(hdr, len);
}
- return JOB_REQUEUE_DIRECT;
+ return TRUE;
}
METHOD(kernel_ipsec_t, get_features, kernel_feature_t,
@@ -1170,7 +1168,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
u_int32_t tfc, lifetime_cfg_t *lifetime, 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,
- u_int16_t cpi, bool encap, bool esn, bool inbound,
+ u_int16_t cpi, bool initiator, bool encap, bool esn, bool inbound,
traffic_selector_t* src_ts, traffic_selector_t* dst_ts)
{
netlink_buf_t request;
@@ -1187,7 +1185,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
lifetime_cfg_t lft = {{0,0,0},{0,0,0},{0,0,0}};
add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark,
tfc, &lft, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED,
- chunk_empty, mode, ipcomp, 0, FALSE, FALSE, inbound, NULL, NULL);
+ chunk_empty, mode, ipcomp, 0, initiator, FALSE, FALSE, inbound,
+ NULL, NULL);
ipcomp = IPCOMP_NONE;
/* use transport mode ESP SA, IPComp uses tunnel mode */
mode = MODE_TRANSPORT;
@@ -1220,6 +1219,12 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
if(src_ts && dst_ts)
{
sa->sel = ts2selector(src_ts, dst_ts);
+ /* don't install proto/port on SA. This would break
+ * potential secondary SAs for the same address using a
+ * different prot/port. */
+ sa->sel.proto = 0;
+ sa->sel.dport = sa->sel.dport_mask = 0;
+ sa->sel.sport = sa->sel.sport_mask = 0;
}
break;
default:
@@ -1595,7 +1600,7 @@ static void get_replay_state(private_kernel_netlink_ipsec_t *this,
METHOD(kernel_ipsec_t, query_sa, status_t,
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
u_int32_t spi, u_int8_t protocol, mark_t mark,
- u_int64_t *bytes, u_int64_t *packets)
+ u_int64_t *bytes, u_int64_t *packets, u_int32_t *time)
{
netlink_buf_t request;
struct nlmsghdr *out = NULL, *hdr;
@@ -1680,6 +1685,12 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
{
*packets = sa->curlft.packets;
}
+ if (time)
+ { /* curlft contains an "use" time, but that contains a timestamp
+ * of the first use, not the last. Last use time must be queried
+ * on the policy on Linux */
+ *time = 0;
+ }
status = SUCCESS;
}
memwipe(out, len);
@@ -2041,7 +2052,7 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
{
continue;
}
- tmpl->reqid = ipsec->cfg.reqid;
+ tmpl->reqid = policy->reqid;
tmpl->id.proto = protos[i].proto;
tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
tmpl->mode = mode2kernel(proto_mode);
@@ -2049,7 +2060,7 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
policy->direction != POLICY_OUT;
tmpl->family = ipsec->src->get_family(ipsec->src);
- if (proto_mode == MODE_TUNNEL)
+ if (proto_mode == MODE_TUNNEL || proto_mode == MODE_BEET)
{ /* only for tunnel mode */
host2xfrm(ipsec->src, &tmpl->saddr);
host2xfrm(ipsec->dst, &tmpl->id.daddr);
@@ -2102,7 +2113,7 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
);
if (hydra->kernel_interface->get_address_by_ts(hydra->kernel_interface,
- fwd->dst_ts, &route->src_ip) == SUCCESS)
+ fwd->dst_ts, &route->src_ip, NULL) == SUCCESS)
{
/* get the nexthop to src (src as we are in POLICY_FWD) */
route->gateway = hydra->kernel_interface->get_nexthop(
@@ -2197,6 +2208,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
.sel = ts2selector(src_ts, dst_ts),
.mark = mark.value & mark.mask,
.direction = direction,
+ .reqid = sa->reqid,
);
/* find the policy, which matches EXACTLY */
@@ -2204,6 +2216,16 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
current = this->policies->get(this->policies, policy);
if (current)
{
+ if (current->reqid != sa->reqid)
+ {
+ DBG1(DBG_CFG, "unable to install policy %R === %R %N (mark "
+ "%u/0x%08x) for reqid %u, the same policy for reqid %u exists",
+ src_ts, dst_ts, policy_dir_names, direction,
+ mark.value, mark.mask, sa->reqid, current->reqid);
+ policy_entry_destroy(this, policy);
+ this->mutex->unlock(this->mutex);
+ return INVALID_STATE;
+ }
/* use existing policy */
DBG2(DBG_KNL, "policy %R === %R %N (mark %u/0x%08x) "
"already exists, increasing refcount",
@@ -2375,7 +2397,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
/* find the policy */
this->mutex->lock(this->mutex);
current = this->policies->get(this->policies, &policy);
- if (!current)
+ if (!current || current->reqid != reqid)
{
if (mark.value)
{
@@ -2398,8 +2420,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
enumerator = current->used_by->create_enumerator(current->used_by);
while (enumerator->enumerate(enumerator, (void**)&mapping))
{
- if (reqid == mapping->sa->cfg.reqid &&
- priority == mapping->priority)
+ if (priority == mapping->priority)
{
current->used_by->remove_at(current->used_by, enumerator);
policy_sa_destroy(mapping, &direction, this);
@@ -2579,6 +2600,7 @@ METHOD(kernel_ipsec_t, destroy, void,
if (this->socket_xfrm_events > 0)
{
+ lib->watcher->remove(lib->watcher, this->socket_xfrm_events);
close(this->socket_xfrm_events);
}
DESTROY_IF(this->socket_xfrm);
@@ -2638,13 +2660,7 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
this->replay_bmp = (this->replay_window + sizeof(u_int32_t) * 8 - 1) /
(sizeof(u_int32_t) * 8);
- if (streq(hydra->daemon, "pluto"))
- { /* no routes for pluto, they are installed via updown script */
- this->install_routes = FALSE;
- /* no policy history for pluto */
- this->policy_history = FALSE;
- }
- else if (streq(hydra->daemon, "starter"))
+ if (streq(hydra->daemon, "starter"))
{ /* starter has no threads, so we do not register for kernel events */
register_for_events = FALSE;
}
@@ -2687,10 +2703,8 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
destroy(this);
return NULL;
}
- lib->processor->queue_job(lib->processor,
- (job_t*)callback_job_create_with_prio(
- (callback_job_cb_t)receive_events, this, NULL,
- (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
+ lib->watcher->add(lib->watcher, this->socket_xfrm_events, WATCHER_READ,
+ (watcher_cb_t)receive_events, this);
}
return &this->public;
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
index 3e0725a35..e129ab131 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2012 Tobias Brunner
+ * Copyright (C) 2008-2013 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -50,7 +50,6 @@
#include <hydra.h>
#include <utils/debug.h>
-#include <threading/thread.h>
#include <threading/mutex.h>
#include <threading/rwlock.h>
#include <threading/rwlock_condvar.h>
@@ -68,6 +67,14 @@
/** maximum recursion when searching for addresses in get_route() */
#define MAX_ROUTE_RECURSION 2
+#ifndef ROUTING_TABLE
+#define ROUTING_TABLE 0
+#endif
+
+#ifndef ROUTING_TABLE_PRIO
+#define ROUTING_TABLE_PRIO 0
+#endif
+
typedef struct addr_entry_t addr_entry_t;
/**
@@ -257,7 +264,7 @@ static route_entry_t *route_entry_clone(route_entry_t *this)
INIT(route,
.if_name = strdup(this->if_name),
.src_ip = this->src_ip->clone(this->src_ip),
- .gateway = this->gateway->clone(this->gateway),
+ .gateway = this->gateway ? this->gateway->clone(this->gateway) : NULL,
.dst_net = chunk_clone(this->dst_net),
.prefixlen = this->prefixlen,
);
@@ -290,10 +297,14 @@ static u_int route_entry_hash(route_entry_t *this)
*/
static bool route_entry_equals(route_entry_t *a, route_entry_t *b)
{
- return a->if_name && b->if_name && streq(a->if_name, b->if_name) &&
- a->src_ip->ip_equals(a->src_ip, b->src_ip) &&
- a->gateway->ip_equals(a->gateway, b->gateway) &&
- chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen;
+ if (a->if_name && b->if_name && streq(a->if_name, b->if_name) &&
+ a->src_ip->ip_equals(a->src_ip, b->src_ip) &&
+ chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen)
+ {
+ return (!a->gateway && !b->gateway) || (a->gateway && b->gateway &&
+ a->gateway->ip_equals(a->gateway, b->gateway));
+ }
+ return FALSE;
}
typedef struct net_change_t net_change_t;
@@ -428,6 +439,11 @@ struct private_kernel_netlink_net_t {
bool process_route;
/**
+ * whether to trigger roam events
+ */
+ bool roam_events;
+
+ /**
* whether to actually install virtual IPs
*/
bool install_virtual_ip;
@@ -695,6 +711,11 @@ static void fire_roam_event(private_kernel_netlink_net_t *this, bool address)
timeval_t now;
job_t *job;
+ if (!this->roam_events)
+ {
+ return;
+ }
+
time_monotonic(&now);
this->roam_lock->lock(this->roam_lock);
if (!timercmp(&now, &this->next_roam, >))
@@ -1057,40 +1078,37 @@ static void process_route(private_kernel_netlink_net_t *this, struct nlmsghdr *h
/**
* Receives events from kernel
*/
-static job_requeue_t receive_events(private_kernel_netlink_net_t *this)
+static bool receive_events(private_kernel_netlink_net_t *this, int fd,
+ watcher_event_t event)
{
char response[1024];
struct nlmsghdr *hdr = (struct nlmsghdr*)response;
struct sockaddr_nl addr;
socklen_t addr_len = sizeof(addr);
int len;
- bool oldstate;
-
- oldstate = thread_cancelability(TRUE);
- len = recvfrom(this->socket_events, response, sizeof(response), 0,
- (struct sockaddr*)&addr, &addr_len);
- thread_cancelability(oldstate);
+ len = recvfrom(this->socket_events, response, sizeof(response),
+ MSG_DONTWAIT, (struct sockaddr*)&addr, &addr_len);
if (len < 0)
{
switch (errno)
{
case EINTR:
/* interrupted, try again */
- return JOB_REQUEUE_DIRECT;
+ return TRUE;
case EAGAIN:
/* no data ready, select again */
- return JOB_REQUEUE_DIRECT;
+ return TRUE;
default:
DBG1(DBG_KNL, "unable to receive from rt event socket");
sleep(1);
- return JOB_REQUEUE_FAIR;
+ return TRUE;
}
}
if (addr.nl_pid != 0)
{ /* not from kernel. not interested, try another one */
- return JOB_REQUEUE_DIRECT;
+ return TRUE;
}
while (NLMSG_OK(hdr, len))
@@ -1118,7 +1136,7 @@ static job_requeue_t receive_events(private_kernel_netlink_net_t *this)
}
hdr = NLMSG_NEXT(hdr, len);
}
- return JOB_REQUEUE_DIRECT;
+ return TRUE;
}
/** enumerator over addresses */
@@ -1147,6 +1165,10 @@ static bool filter_addresses(address_enumerator_t *data,
{ /* skip virtual interfaces added by us */
return FALSE;
}
+ if (!(data->which & ADDR_TYPE_REGULAR) && !(*in)->refcount)
+ { /* address is regular, but not requested */
+ return FALSE;
+ }
if ((*in)->scope >= RT_SCOPE_LINK)
{ /* skip addresses with a unusable scope */
return FALSE;
@@ -1191,9 +1213,12 @@ static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in,
METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
private_kernel_netlink_net_t *this, kernel_address_type_t which)
{
- address_enumerator_t *data = malloc_thing(address_enumerator_t);
- data->this = this;
- data->which = which;
+ address_enumerator_t *data;
+
+ INIT(data,
+ .this = this,
+ .which = which,
+ );
this->lock->read_lock(this->lock);
return enumerator_create_nested(
@@ -1237,7 +1262,7 @@ METHOD(kernel_net_t, get_interface_name, bool,
if (name)
{
*name = strdup(entry->iface->ifname);
- DBG2(DBG_KNL, "virtual %H is on interface %s", ip, *name);
+ DBG2(DBG_KNL, "virtual IP %H is on interface %s", ip, *name);
}
this->lock->unlock(this->lock);
return TRUE;
@@ -2146,6 +2171,7 @@ METHOD(kernel_net_t, destroy, void,
}
if (this->socket_events > 0)
{
+ lib->watcher->remove(lib->watcher, this->socket_events);
close(this->socket_events);
}
enumerator = this->routes->create_enumerator(this->routes);
@@ -2227,6 +2253,8 @@ kernel_netlink_net_t *kernel_netlink_net_create()
"%s.install_virtual_ip", TRUE, hydra->daemon),
.install_virtual_ip_on = lib->settings->get_str(lib->settings,
"%s.install_virtual_ip_on", NULL, hydra->daemon),
+ .roam_events = lib->settings->get_bool(lib->settings,
+ "%s.plugins.kernel-netlink.roam_events", TRUE, hydra->daemon),
);
timerclear(&this->last_route_reinstall);
timerclear(&this->next_roam);
@@ -2283,10 +2311,8 @@ kernel_netlink_net_t *kernel_netlink_net_create()
return NULL;
}
- lib->processor->queue_job(lib->processor,
- (job_t*)callback_job_create_with_prio(
- (callback_job_cb_t)receive_events, this, NULL,
- (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
+ lib->watcher->add(lib->watcher, this->socket_events, WATCHER_READ,
+ (watcher_cb_t)receive_events, this);
}
if (init_address_list(this) != SUCCESS)
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.c
index 0eb00dadf..8d5a0d5e8 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.c
@@ -65,6 +65,14 @@ plugin_t *kernel_netlink_plugin_create()
{
private_kernel_netlink_plugin_t *this;
+ if (!lib->caps->keep(lib->caps, CAP_NET_ADMIN))
+ { /* required to bind/use XFRM sockets / create/modify routing tables, but
+ * not if only the read-only parts of kernel-netlink-net are used, so
+ * we don't fail here */
+ DBG1(DBG_KNL, "kernel-netlink plugin might require CAP_NET_ADMIN "
+ "capability");
+ }
+
INIT(this,
.public = {
.plugin = {