diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/xfrm/xfrm_policy.c | 55 |
1 files changed, 25 insertions, 30 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index f6c77bd36fdd..4f04222698d9 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -860,33 +860,12 @@ EXPORT_SYMBOL(xfrm_policy_flush); | |||
860 | int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*), | 860 | int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*), |
861 | void *data) | 861 | void *data) |
862 | { | 862 | { |
863 | struct xfrm_policy *pol; | 863 | struct xfrm_policy *pol, *last = NULL; |
864 | struct hlist_node *entry; | 864 | struct hlist_node *entry; |
865 | int dir, count, error; | 865 | int dir, last_dir = 0, count, error; |
866 | 866 | ||
867 | read_lock_bh(&xfrm_policy_lock); | 867 | read_lock_bh(&xfrm_policy_lock); |
868 | count = 0; | 868 | count = 0; |
869 | for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) { | ||
870 | struct hlist_head *table = xfrm_policy_bydst[dir].table; | ||
871 | int i; | ||
872 | |||
873 | hlist_for_each_entry(pol, entry, | ||
874 | &xfrm_policy_inexact[dir], bydst) { | ||
875 | if (pol->type == type) | ||
876 | count++; | ||
877 | } | ||
878 | for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) { | ||
879 | hlist_for_each_entry(pol, entry, table + i, bydst) { | ||
880 | if (pol->type == type) | ||
881 | count++; | ||
882 | } | ||
883 | } | ||
884 | } | ||
885 | |||
886 | if (count == 0) { | ||
887 | error = -ENOENT; | ||
888 | goto out; | ||
889 | } | ||
890 | 869 | ||
891 | for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) { | 870 | for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) { |
892 | struct hlist_head *table = xfrm_policy_bydst[dir].table; | 871 | struct hlist_head *table = xfrm_policy_bydst[dir].table; |
@@ -896,21 +875,37 @@ int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*) | |||
896 | &xfrm_policy_inexact[dir], bydst) { | 875 | &xfrm_policy_inexact[dir], bydst) { |
897 | if (pol->type != type) | 876 | if (pol->type != type) |
898 | continue; | 877 | continue; |
899 | error = func(pol, dir % XFRM_POLICY_MAX, --count, data); | 878 | if (last) { |
900 | if (error) | 879 | error = func(last, last_dir % XFRM_POLICY_MAX, |
901 | goto out; | 880 | count, data); |
881 | if (error) | ||
882 | goto out; | ||
883 | } | ||
884 | last = pol; | ||
885 | last_dir = dir; | ||
886 | count++; | ||
902 | } | 887 | } |
903 | for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) { | 888 | for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) { |
904 | hlist_for_each_entry(pol, entry, table + i, bydst) { | 889 | hlist_for_each_entry(pol, entry, table + i, bydst) { |
905 | if (pol->type != type) | 890 | if (pol->type != type) |
906 | continue; | 891 | continue; |
907 | error = func(pol, dir % XFRM_POLICY_MAX, --count, data); | 892 | if (last) { |
908 | if (error) | 893 | error = func(last, last_dir % XFRM_POLICY_MAX, |
909 | goto out; | 894 | count, data); |
895 | if (error) | ||
896 | goto out; | ||
897 | } | ||
898 | last = pol; | ||
899 | last_dir = dir; | ||
900 | count++; | ||
910 | } | 901 | } |
911 | } | 902 | } |
912 | } | 903 | } |
913 | error = 0; | 904 | if (count == 0) { |
905 | error = -ENOENT; | ||
906 | goto out; | ||
907 | } | ||
908 | error = func(last, last_dir % XFRM_POLICY_MAX, 0, data); | ||
914 | out: | 909 | out: |
915 | read_unlock_bh(&xfrm_policy_lock); | 910 | read_unlock_bh(&xfrm_policy_lock); |
916 | return error; | 911 | return error; |