aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-08-25 18:46:46 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 18:18:05 -0400
commitacba48e1a3c95082af1e12c5efaaca3506103a92 (patch)
treea6c001ca19cfb67427aaec822952c32bb0916568
parent65e3d72654d9a33cdccd5c19777a5515ae9dd37d (diff)
[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>
-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 b446ca31fecc..1cf3209cdf4b 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,
908 xfrm_address_t *daddr, *saddr; 908 xfrm_address_t *daddr, *saddr;
909 struct hlist_node *entry; 909 struct hlist_node *entry;
910 struct hlist_head *chain; 910 struct hlist_head *chain;
911 u32 priority = ~0U;
911 912
912 daddr = xfrm_flowi_daddr(fl, family); 913 daddr = xfrm_flowi_daddr(fl, family);
913 saddr = xfrm_flowi_saddr(fl, family); 914 saddr = xfrm_flowi_saddr(fl, family);
@@ -919,21 +920,21 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl,
919 ret = NULL; 920 ret = NULL;
920 hlist_for_each_entry(pol, entry, chain, bydst) { 921 hlist_for_each_entry(pol, entry, chain, bydst) {
921 if (xfrm_policy_match(pol, fl, type, family, dir)) { 922 if (xfrm_policy_match(pol, fl, type, family, dir)) {
922 xfrm_pol_hold(pol);
923 ret = pol; 923 ret = pol;
924 priority = ret->priority;
924 break; 925 break;
925 } 926 }
926 } 927 }
927 if (!ret) { 928 chain = &xfrm_policy_inexact[dir];
928 chain = &xfrm_policy_inexact[dir]; 929 hlist_for_each_entry(pol, entry, chain, bydst) {
929 hlist_for_each_entry(pol, entry, chain, bydst) { 930 if (xfrm_policy_match(pol, fl, type, family, dir) &&
930 if (xfrm_policy_match(pol, fl, type, family, dir)) { 931 pol->priority < priority) {
931 xfrm_pol_hold(pol); 932 ret = pol;
932 ret = pol; 933 break;
933 break;
934 }
935 } 934 }
936 } 935 }
936 if (ret)
937 xfrm_pol_hold(ret);
937 read_unlock_bh(&xfrm_policy_lock); 938 read_unlock_bh(&xfrm_policy_lock);
938 939
939 return ret; 940 return ret;