diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2006-08-25 18:46:46 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-09-22 18:18:05 -0400 |
commit | acba48e1a3c95082af1e12c5efaaca3506103a92 (patch) | |
tree | a6c001ca19cfb67427aaec822952c32bb0916568 /net | |
parent | 65e3d72654d9a33cdccd5c19777a5515ae9dd37d (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>
Diffstat (limited to 'net')
-rw-r--r-- | net/xfrm/xfrm_policy.c | 19 |
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; |