aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteffen Klassert <steffen.klassert@secunet.com>2013-02-11 01:02:36 -0500
committerSteffen Klassert <steffen.klassert@secunet.com>2013-02-11 08:07:01 -0500
commit7cb8a93968e395e40a72a50da0b6114e752304b4 (patch)
tree2d2ab4468555120fb04b86097fce9e31b584154f
parent8d068875caca3b507ffa8a57d521483fd4eebcc7 (diff)
xfrm: Allow inserting policies with matching mark and different priorities
We currently can not insert policies with mark and mask such that some flows would be matched from both policies. We make this possible when the priority of these policies are different. If both policies match a flow, the one with the higher priority is used. Reported-by: Emmanuel Thierry <emmanuel.thierry@telecom-bretagne.eu> Reported-by: Romain Kuntz <r.kuntz@ipflavors.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
-rw-r--r--net/xfrm/xfrm_policy.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 456b11b0f049..257dfb18aef4 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -607,6 +607,21 @@ static void xfrm_policy_requeue(struct xfrm_policy *old,
607 spin_unlock_bh(&pq->hold_queue.lock); 607 spin_unlock_bh(&pq->hold_queue.lock);
608} 608}
609 609
610static bool xfrm_policy_mark_match(struct xfrm_policy *policy,
611 struct xfrm_policy *pol)
612{
613 u32 mark = policy->mark.v & policy->mark.m;
614
615 if (policy->mark.v == pol->mark.v && policy->mark.m == pol->mark.m)
616 return true;
617
618 if ((mark & pol->mark.m) == pol->mark.v &&
619 policy->priority == pol->priority)
620 return true;
621
622 return false;
623}
624
610int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) 625int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
611{ 626{
612 struct net *net = xp_net(policy); 627 struct net *net = xp_net(policy);
@@ -614,7 +629,6 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
614 struct xfrm_policy *delpol; 629 struct xfrm_policy *delpol;
615 struct hlist_head *chain; 630 struct hlist_head *chain;
616 struct hlist_node *entry, *newpos; 631 struct hlist_node *entry, *newpos;
617 u32 mark = policy->mark.v & policy->mark.m;
618 632
619 write_lock_bh(&xfrm_policy_lock); 633 write_lock_bh(&xfrm_policy_lock);
620 chain = policy_hash_bysel(net, &policy->selector, policy->family, dir); 634 chain = policy_hash_bysel(net, &policy->selector, policy->family, dir);
@@ -623,7 +637,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
623 hlist_for_each_entry(pol, entry, chain, bydst) { 637 hlist_for_each_entry(pol, entry, chain, bydst) {
624 if (pol->type == policy->type && 638 if (pol->type == policy->type &&
625 !selector_cmp(&pol->selector, &policy->selector) && 639 !selector_cmp(&pol->selector, &policy->selector) &&
626 (mark & pol->mark.m) == pol->mark.v && 640 xfrm_policy_mark_match(policy, pol) &&
627 xfrm_sec_ctx_match(pol->security, policy->security) && 641 xfrm_sec_ctx_match(pol->security, policy->security) &&
628 !WARN_ON(delpol)) { 642 !WARN_ON(delpol)) {
629 if (excl) { 643 if (excl) {