aboutsummaryrefslogtreecommitdiffstats
path: root/src/libhydra/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/libhydra/plugins')
-rw-r--r--src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c17
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c47
-rw-r--r--src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c51
3 files changed, 76 insertions, 39 deletions
diff --git a/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c b/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c
index aca00ddb4..25287aa77 100644
--- a/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c
+++ b/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c
@@ -1971,7 +1971,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst,
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
- mark_t mark, bool routed)
+ mark_t mark, policy_priority_t priority)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -2013,7 +2013,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
this->policies->insert_last(this->policies, policy);
}
- if (routed)
+ if (priority == POLICY_PRIORITY_ROUTED)
{
/* we install this as a %trap eroute in the kernel, later to be
* triggered by packets matching the policy (-> ACQUIRE). */
@@ -2049,9 +2049,11 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
msg = (struct sadb_msg*)request;
/* FIXME: SADB_X_SAFLAGS_INFLOW may be required, if we add an inbound policy for an IPIP SA */
- build_addflow(msg, satype, spi, routed ? NULL : src, routed ? NULL : dst,
- policy->src.net, policy->src.mask, policy->dst.net, policy->dst.mask,
- policy->src.proto, found != NULL);
+ build_addflow(msg, satype, spi,
+ priority == POLICY_PRIORITY_ROUTED ? NULL : src,
+ priority == POLICY_PRIORITY_ROUTED ? NULL : dst,
+ policy->src.net, policy->src.mask, policy->dst.net,
+ policy->dst.mask, policy->src.proto, found != NULL);
this->mutex->unlock(this->mutex);
@@ -2348,7 +2350,7 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
METHOD(kernel_ipsec_t, del_policy, status_t,
private_kernel_klips_ipsec_t *this, traffic_selector_t *src_ts,
traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t reqid,
- mark_t mark, bool unrouted)
+ mark_t mark, policy_priority_t priority)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg = (struct sadb_msg*)request, *out;
@@ -2382,7 +2384,8 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
policy_entry_destroy(policy);
/* decrease appropriate counter */
- unrouted ? found->trapcount-- : found->activecount--;
+ priority == POLICY_PRIORITY_ROUTED ? found->trapcount--
+ : found->activecount--;
if (found->trapcount == 0)
{
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
index 9f906fc78..26919a613 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -59,8 +59,7 @@
#endif /*IPV6_XFRM_POLICY*/
/** Default priority of installed policies */
-#define PRIO_LOW 1024
-#define PRIO_HIGH 512
+#define PRIO_BASE 512
/** Default replay window size, if not set using charon.replay_window */
#define DEFAULT_REPLAY_WINDOW 32
@@ -568,6 +567,30 @@ static bool policy_equals(policy_entry_t *key, policy_entry_t *other_key)
}
/**
+ * Calculate the priority of a policy
+ */
+static inline u_int32_t get_priority(policy_entry_t *policy,
+ policy_priority_t prio)
+{
+ u_int32_t priority = PRIO_BASE;
+ switch (prio)
+ {
+ case POLICY_PRIORITY_ROUTED:
+ priority <<= 1;
+ /* fall-through */
+ case POLICY_PRIORITY_DEFAULT:
+ break;
+ }
+ /* calculate priority based on selector size, small size = high prio */
+ priority -= policy->sel.prefixlen_s;
+ priority -= policy->sel.prefixlen_d;
+ priority <<= 2; /* make some room for the two flags */
+ priority += policy->sel.sport_mask || policy->sel.dport_mask ? 0 : 2;
+ priority += policy->sel.proto ? 0 : 1;
+ return priority;
+}
+
+/**
* Convert the general ipsec mode to the one defined in xfrm.h
*/
static u_int8_t mode2kernel(ipsec_mode_t mode)
@@ -2149,7 +2172,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
- mark_t mark, bool routed)
+ mark_t mark, policy_priority_t priority)
{
policy_entry_t *policy, *current;
policy_sa_t *assigned_sa, *current_sa;
@@ -2195,15 +2218,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
/* cache the assigned IPsec SA */
assigned_sa = policy_sa_create(this, direction, type, src, dst, src_ts,
dst_ts, mark, sa);
-
- /* calculate priority based on selector size, small size = high prio */
- assigned_sa->priority = routed ? PRIO_LOW : PRIO_HIGH;
- assigned_sa->priority -= policy->sel.prefixlen_s;
- assigned_sa->priority -= policy->sel.prefixlen_d;
- assigned_sa->priority <<= 2; /* make some room for the two flags */
- assigned_sa->priority += policy->sel.sport_mask ||
- policy->sel.dport_mask ? 0 : 2;
- assigned_sa->priority += policy->sel.proto ? 0 : 1;
+ assigned_sa->priority = get_priority(policy, priority);
/* insert the SA according to its priority */
enumerator = policy->used_by->create_enumerator(policy->used_by);
@@ -2354,7 +2369,7 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
METHOD(kernel_ipsec_t, del_policy, status_t,
private_kernel_netlink_ipsec_t *this, traffic_selector_t *src_ts,
traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t reqid,
- mark_t mark, bool unrouted)
+ mark_t mark, policy_priority_t prio)
{
policy_entry_t *current, policy;
enumerator_t *enumerator;
@@ -2363,6 +2378,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
struct nlmsghdr *hdr;
struct xfrm_userpolicy_id *policy_id;
bool is_installed = TRUE;
+ u_int32_t priority;
if (mark.value)
{
@@ -2402,11 +2418,12 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
return NOT_FOUND;
}
- /* remove mapping to SA by reqid */
+ /* remove mapping to SA by reqid and priority */
+ priority = get_priority(current, prio);
enumerator = current->used_by->create_enumerator(current->used_by);
while (enumerator->enumerate(enumerator, (void**)&mapping))
{
- if (reqid == mapping->sa->cfg.reqid)
+ if (reqid == mapping->sa->cfg.reqid && priority == mapping->priority)
{
current->used_by->remove_at(current->used_by, enumerator);
policy_sa_destroy(mapping, &direction, this);
diff --git a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
index efdf9c928..f96dbcf23 100644
--- a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
+++ b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
@@ -100,8 +100,7 @@
#endif
/** default priority of installed policies */
-#define PRIO_LOW 1024
-#define PRIO_HIGH 512
+#define PRIO_BASE 512
#ifdef __APPLE__
/** from xnu/bsd/net/pfkeyv2.h */
@@ -501,6 +500,32 @@ static inline bool policy_entry_match_byindex(policy_entry_t *current,
return current->index == *index;
}
+/**
+ * Calculate the priority of a policy
+ */
+static inline u_int32_t get_priority(policy_entry_t *policy,
+ policy_priority_t prio)
+{
+ u_int32_t priority = PRIO_BASE;
+ switch (prio)
+ {
+ case POLICY_PRIORITY_ROUTED:
+ priority <<= 1;
+ /* fall-through */
+ case POLICY_PRIORITY_DEFAULT:
+ break;
+ }
+ /* calculate priority based on selector size, small size = high prio */
+ priority -= policy->src.mask;
+ priority -= policy->dst.mask;
+ priority <<= 2; /* make some room for the two flags */
+ priority += policy->src.net->get_port(policy->src.net) ||
+ policy->dst.net->get_port(policy->dst.net) ?
+ 0 : 2;
+ priority += policy->src.proto != IPSEC_PROTO_ANY ? 0 : 1;
+ return priority;
+}
+
typedef struct pfkey_msg_t pfkey_msg_t;
struct pfkey_msg_t
@@ -2008,7 +2033,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
- mark_t mark, bool routed)
+ mark_t mark, policy_priority_t priority)
{
policy_entry_t *policy, *found = NULL;
policy_sa_t *assigned_sa, *current_sa;
@@ -2043,17 +2068,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
/* cache the assigned IPsec SA */
assigned_sa = policy_sa_create(this, direction, type, src, dst, src_ts,
dst_ts, sa);
-
-
- /* calculate priority based on selector size, small size = high prio */
- assigned_sa->priority = routed ? PRIO_LOW : PRIO_HIGH;
- assigned_sa->priority -= policy->src.mask;
- assigned_sa->priority -= policy->dst.mask;
- assigned_sa->priority <<= 2; /* make some room for the two flags */
- assigned_sa->priority += policy->src.net->get_port(policy->src.net) ||
- policy->dst.net->get_port(policy->dst.net) ?
- 0 : 2;
- assigned_sa->priority += policy->src.proto != IPSEC_PROTO_ANY ? 0 : 1;
+ assigned_sa->priority = get_priority(policy, priority);
/* insert the SA according to its priority */
enumerator = policy->used_by->create_enumerator(policy->used_by);
@@ -2197,7 +2212,7 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
METHOD(kernel_ipsec_t, del_policy, status_t,
private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts,
traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t reqid,
- mark_t mark, bool unrouted)
+ mark_t mark, policy_priority_t prio)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -2206,6 +2221,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
policy_sa_t *mapping;
enumerator_t *enumerator;
bool is_installed = TRUE;
+ u_int32_t priority;
size_t len;
if (dir2kernel(direction) == IPSEC_DIR_INVALID)
@@ -2234,11 +2250,12 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
policy_entry_destroy(policy, this);
policy = found;
- /* remove mapping to SA by reqid */
+ /* remove mapping to SA by reqid and priority */
+ priority = get_priority(policy, prio);
enumerator = policy->used_by->create_enumerator(policy->used_by);
while (enumerator->enumerate(enumerator, (void**)&mapping))
{
- if (reqid == mapping->sa->cfg.reqid)
+ if (reqid == mapping->sa->cfg.reqid && priority == mapping->priority)
{
policy->used_by->remove_at(policy->used_by, enumerator);
break;