aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/xfrm/xfrm_policy.c55
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);
860int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*), 860int 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);
914out: 909out:
915 read_unlock_bh(&xfrm_policy_lock); 910 read_unlock_bh(&xfrm_policy_lock);
916 return error; 911 return error;