summaryrefslogtreecommitdiff
path: root/net/xfrm
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-08-25 15:46:46 -0700
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 15:18:05 -0700
commitacba48e1a3c95082af1e12c5efaaca3506103a92 (patch)
treea6c001ca19cfb67427aaec822952c32bb0916568 /net/xfrm
parent65e3d72654d9a33cdccd5c19777a5515ae9dd37d (diff)
downloadlinux-3.10-acba48e1a3c95082af1e12c5efaaca3506103a92.tar.gz
linux-3.10-acba48e1a3c95082af1e12c5efaaca3506103a92.tar.bz2
linux-3.10-acba48e1a3c95082af1e12c5efaaca3506103a92.zip
[XFRM]: Respect priority in policy lookups.
Even if we find an exact match in the hash table, we must inspect the inexact list to look for a match with a better priority. Noticed by Masahide NAKAMURA <nakam@linux-ipv6.org>. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/xfrm')
-rw-r--r--net/xfrm/xfrm_policy.c19
1 files changed, 10 insertions, 9 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index b446ca31fec..1cf3209cdf4 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -908,6 +908,7 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl,
xfrm_address_t *daddr, *saddr;
struct hlist_node *entry;
struct hlist_head *chain;
+ u32 priority = ~0U;
daddr = xfrm_flowi_daddr(fl, family);
saddr = xfrm_flowi_saddr(fl, family);
@@ -919,21 +920,21 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl,
ret = NULL;
hlist_for_each_entry(pol, entry, chain, bydst) {
if (xfrm_policy_match(pol, fl, type, family, dir)) {
- xfrm_pol_hold(pol);
ret = pol;
+ priority = ret->priority;
break;
}
}
- if (!ret) {
- chain = &xfrm_policy_inexact[dir];
- hlist_for_each_entry(pol, entry, chain, bydst) {
- if (xfrm_policy_match(pol, fl, type, family, dir)) {
- xfrm_pol_hold(pol);
- ret = pol;
- break;
- }
+ chain = &xfrm_policy_inexact[dir];
+ hlist_for_each_entry(pol, entry, chain, bydst) {
+ if (xfrm_policy_match(pol, fl, type, family, dir) &&
+ pol->priority < priority) {
+ ret = pol;
+ break;
}
}
+ if (ret)
+ xfrm_pol_hold(ret);
read_unlock_bh(&xfrm_policy_lock);
return ret;