aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2008-12-19 02:22:57 -0500
committerTakashi Iwai <tiwai@suse.de>2008-12-19 02:22:57 -0500
commit0ff555192a8d20385d49d1c420e2e8d409b3c0da (patch)
treeb6e4b6cae1028a310a3488ebf745954c51694bfc /net/xfrm
parent3218c178b41b420cb7e0d120c7a137a3969242e5 (diff)
parent9e43f0de690211cf7153b5f3ec251bc315647ada (diff)
Merge branch 'fix/hda' into topic/hda
Diffstat (limited to 'net/xfrm')
-rw-r--r--net/xfrm/xfrm_policy.c125
-rw-r--r--net/xfrm/xfrm_state.c84
-rw-r--r--net/xfrm/xfrm_user.c61
3 files changed, 163 insertions, 107 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index b7754b1b73a4..fb216c9adf86 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -34,7 +34,7 @@
34 34
35#include "xfrm_hash.h" 35#include "xfrm_hash.h"
36 36
37int sysctl_xfrm_larval_drop __read_mostly; 37int sysctl_xfrm_larval_drop __read_mostly = 1;
38 38
39#ifdef CONFIG_XFRM_STATISTICS 39#ifdef CONFIG_XFRM_STATISTICS
40DEFINE_SNMP_STAT(struct linux_xfrm_mib, xfrm_statistics) __read_mostly; 40DEFINE_SNMP_STAT(struct linux_xfrm_mib, xfrm_statistics) __read_mostly;
@@ -46,7 +46,7 @@ EXPORT_SYMBOL(xfrm_cfg_mutex);
46 46
47static DEFINE_RWLOCK(xfrm_policy_lock); 47static DEFINE_RWLOCK(xfrm_policy_lock);
48 48
49static struct list_head xfrm_policy_bytype[XFRM_POLICY_TYPE_MAX]; 49static struct list_head xfrm_policy_all;
50unsigned int xfrm_policy_count[XFRM_POLICY_MAX*2]; 50unsigned int xfrm_policy_count[XFRM_POLICY_MAX*2];
51EXPORT_SYMBOL(xfrm_policy_count); 51EXPORT_SYMBOL(xfrm_policy_count);
52 52
@@ -164,7 +164,7 @@ static void xfrm_policy_timer(unsigned long data)
164 164
165 read_lock(&xp->lock); 165 read_lock(&xp->lock);
166 166
167 if (xp->dead) 167 if (xp->walk.dead)
168 goto out; 168 goto out;
169 169
170 dir = xfrm_policy_id2dir(xp->index); 170 dir = xfrm_policy_id2dir(xp->index);
@@ -236,7 +236,7 @@ struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp)
236 policy = kzalloc(sizeof(struct xfrm_policy), gfp); 236 policy = kzalloc(sizeof(struct xfrm_policy), gfp);
237 237
238 if (policy) { 238 if (policy) {
239 INIT_LIST_HEAD(&policy->bytype); 239 INIT_LIST_HEAD(&policy->walk.all);
240 INIT_HLIST_NODE(&policy->bydst); 240 INIT_HLIST_NODE(&policy->bydst);
241 INIT_HLIST_NODE(&policy->byidx); 241 INIT_HLIST_NODE(&policy->byidx);
242 rwlock_init(&policy->lock); 242 rwlock_init(&policy->lock);
@@ -252,17 +252,13 @@ EXPORT_SYMBOL(xfrm_policy_alloc);
252 252
253void xfrm_policy_destroy(struct xfrm_policy *policy) 253void xfrm_policy_destroy(struct xfrm_policy *policy)
254{ 254{
255 BUG_ON(!policy->dead); 255 BUG_ON(!policy->walk.dead);
256 256
257 BUG_ON(policy->bundles); 257 BUG_ON(policy->bundles);
258 258
259 if (del_timer(&policy->timer)) 259 if (del_timer(&policy->timer))
260 BUG(); 260 BUG();
261 261
262 write_lock_bh(&xfrm_policy_lock);
263 list_del(&policy->bytype);
264 write_unlock_bh(&xfrm_policy_lock);
265
266 security_xfrm_policy_free(policy->security); 262 security_xfrm_policy_free(policy->security);
267 kfree(policy); 263 kfree(policy);
268} 264}
@@ -310,8 +306,8 @@ static void xfrm_policy_kill(struct xfrm_policy *policy)
310 int dead; 306 int dead;
311 307
312 write_lock_bh(&policy->lock); 308 write_lock_bh(&policy->lock);
313 dead = policy->dead; 309 dead = policy->walk.dead;
314 policy->dead = 1; 310 policy->walk.dead = 1;
315 write_unlock_bh(&policy->lock); 311 write_unlock_bh(&policy->lock);
316 312
317 if (unlikely(dead)) { 313 if (unlikely(dead)) {
@@ -319,9 +315,9 @@ static void xfrm_policy_kill(struct xfrm_policy *policy)
319 return; 315 return;
320 } 316 }
321 317
322 spin_lock(&xfrm_policy_gc_lock); 318 spin_lock_bh(&xfrm_policy_gc_lock);
323 hlist_add_head(&policy->bydst, &xfrm_policy_gc_list); 319 hlist_add_head(&policy->bydst, &xfrm_policy_gc_list);
324 spin_unlock(&xfrm_policy_gc_lock); 320 spin_unlock_bh(&xfrm_policy_gc_lock);
325 321
326 schedule_work(&xfrm_policy_gc_work); 322 schedule_work(&xfrm_policy_gc_work);
327} 323}
@@ -609,6 +605,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
609 if (delpol) { 605 if (delpol) {
610 hlist_del(&delpol->bydst); 606 hlist_del(&delpol->bydst);
611 hlist_del(&delpol->byidx); 607 hlist_del(&delpol->byidx);
608 list_del(&delpol->walk.all);
612 xfrm_policy_count[dir]--; 609 xfrm_policy_count[dir]--;
613 } 610 }
614 policy->index = delpol ? delpol->index : xfrm_gen_index(policy->type, dir); 611 policy->index = delpol ? delpol->index : xfrm_gen_index(policy->type, dir);
@@ -617,7 +614,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
617 policy->curlft.use_time = 0; 614 policy->curlft.use_time = 0;
618 if (!mod_timer(&policy->timer, jiffies + HZ)) 615 if (!mod_timer(&policy->timer, jiffies + HZ))
619 xfrm_pol_hold(policy); 616 xfrm_pol_hold(policy);
620 list_add_tail(&policy->bytype, &xfrm_policy_bytype[policy->type]); 617 list_add(&policy->walk.all, &xfrm_policy_all);
621 write_unlock_bh(&xfrm_policy_lock); 618 write_unlock_bh(&xfrm_policy_lock);
622 619
623 if (delpol) 620 if (delpol)
@@ -684,6 +681,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
684 } 681 }
685 hlist_del(&pol->bydst); 682 hlist_del(&pol->bydst);
686 hlist_del(&pol->byidx); 683 hlist_del(&pol->byidx);
684 list_del(&pol->walk.all);
687 xfrm_policy_count[dir]--; 685 xfrm_policy_count[dir]--;
688 } 686 }
689 ret = pol; 687 ret = pol;
@@ -727,6 +725,7 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete,
727 } 725 }
728 hlist_del(&pol->bydst); 726 hlist_del(&pol->bydst);
729 hlist_del(&pol->byidx); 727 hlist_del(&pol->byidx);
728 list_del(&pol->walk.all);
730 xfrm_policy_count[dir]--; 729 xfrm_policy_count[dir]--;
731 } 730 }
732 ret = pol; 731 ret = pol;
@@ -818,6 +817,7 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
818 continue; 817 continue;
819 hlist_del(&pol->bydst); 818 hlist_del(&pol->bydst);
820 hlist_del(&pol->byidx); 819 hlist_del(&pol->byidx);
820 list_del(&pol->walk.all);
821 write_unlock_bh(&xfrm_policy_lock); 821 write_unlock_bh(&xfrm_policy_lock);
822 822
823 xfrm_audit_policy_delete(pol, 1, audit_info->loginuid, 823 xfrm_audit_policy_delete(pol, 1, audit_info->loginuid,
@@ -840,6 +840,7 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
840 continue; 840 continue;
841 hlist_del(&pol->bydst); 841 hlist_del(&pol->bydst);
842 hlist_del(&pol->byidx); 842 hlist_del(&pol->byidx);
843 list_del(&pol->walk.all);
843 write_unlock_bh(&xfrm_policy_lock); 844 write_unlock_bh(&xfrm_policy_lock);
844 845
845 xfrm_audit_policy_delete(pol, 1, 846 xfrm_audit_policy_delete(pol, 1,
@@ -867,60 +868,68 @@ int xfrm_policy_walk(struct xfrm_policy_walk *walk,
867 int (*func)(struct xfrm_policy *, int, int, void*), 868 int (*func)(struct xfrm_policy *, int, int, void*),
868 void *data) 869 void *data)
869{ 870{
870 struct xfrm_policy *old, *pol, *last = NULL; 871 struct xfrm_policy *pol;
872 struct xfrm_policy_walk_entry *x;
871 int error = 0; 873 int error = 0;
872 874
873 if (walk->type >= XFRM_POLICY_TYPE_MAX && 875 if (walk->type >= XFRM_POLICY_TYPE_MAX &&
874 walk->type != XFRM_POLICY_TYPE_ANY) 876 walk->type != XFRM_POLICY_TYPE_ANY)
875 return -EINVAL; 877 return -EINVAL;
876 878
877 if (walk->policy == NULL && walk->count != 0) 879 if (list_empty(&walk->walk.all) && walk->seq != 0)
878 return 0; 880 return 0;
879 881
880 old = pol = walk->policy; 882 write_lock_bh(&xfrm_policy_lock);
881 walk->policy = NULL; 883 if (list_empty(&walk->walk.all))
882 read_lock_bh(&xfrm_policy_lock); 884 x = list_first_entry(&xfrm_policy_all, struct xfrm_policy_walk_entry, all);
883 885 else
884 for (; walk->cur_type < XFRM_POLICY_TYPE_MAX; walk->cur_type++) { 886 x = list_entry(&walk->walk.all, struct xfrm_policy_walk_entry, all);
885 if (walk->type != walk->cur_type && 887 list_for_each_entry_from(x, &xfrm_policy_all, all) {
886 walk->type != XFRM_POLICY_TYPE_ANY) 888 if (x->dead)
887 continue; 889 continue;
888 890 pol = container_of(x, struct xfrm_policy, walk);
889 if (pol == NULL) { 891 if (walk->type != XFRM_POLICY_TYPE_ANY &&
890 pol = list_first_entry(&xfrm_policy_bytype[walk->cur_type], 892 walk->type != pol->type)
891 struct xfrm_policy, bytype); 893 continue;
892 } 894 error = func(pol, xfrm_policy_id2dir(pol->index),
893 list_for_each_entry_from(pol, &xfrm_policy_bytype[walk->cur_type], bytype) { 895 walk->seq, data);
894 if (pol->dead) 896 if (error) {
895 continue; 897 list_move_tail(&walk->walk.all, &x->all);
896 if (last) { 898 goto out;
897 error = func(last, xfrm_policy_id2dir(last->index),
898 walk->count, data);
899 if (error) {
900 xfrm_pol_hold(last);
901 walk->policy = last;
902 goto out;
903 }
904 }
905 last = pol;
906 walk->count++;
907 } 899 }
908 pol = NULL; 900 walk->seq++;
909 } 901 }
910 if (walk->count == 0) { 902 if (walk->seq == 0) {
911 error = -ENOENT; 903 error = -ENOENT;
912 goto out; 904 goto out;
913 } 905 }
914 if (last) 906 list_del_init(&walk->walk.all);
915 error = func(last, xfrm_policy_id2dir(last->index), 0, data);
916out: 907out:
917 read_unlock_bh(&xfrm_policy_lock); 908 write_unlock_bh(&xfrm_policy_lock);
918 if (old != NULL)
919 xfrm_pol_put(old);
920 return error; 909 return error;
921} 910}
922EXPORT_SYMBOL(xfrm_policy_walk); 911EXPORT_SYMBOL(xfrm_policy_walk);
923 912
913void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type)
914{
915 INIT_LIST_HEAD(&walk->walk.all);
916 walk->walk.dead = 1;
917 walk->type = type;
918 walk->seq = 0;
919}
920EXPORT_SYMBOL(xfrm_policy_walk_init);
921
922void xfrm_policy_walk_done(struct xfrm_policy_walk *walk)
923{
924 if (list_empty(&walk->walk.all))
925 return;
926
927 write_lock_bh(&xfrm_policy_lock);
928 list_del(&walk->walk.all);
929 write_unlock_bh(&xfrm_policy_lock);
930}
931EXPORT_SYMBOL(xfrm_policy_walk_done);
932
924/* 933/*
925 * Find policy to apply to this flow. 934 * Find policy to apply to this flow.
926 * 935 *
@@ -1077,7 +1086,7 @@ static void __xfrm_policy_link(struct xfrm_policy *pol, int dir)
1077 struct hlist_head *chain = policy_hash_bysel(&pol->selector, 1086 struct hlist_head *chain = policy_hash_bysel(&pol->selector,
1078 pol->family, dir); 1087 pol->family, dir);
1079 1088
1080 list_add_tail(&pol->bytype, &xfrm_policy_bytype[pol->type]); 1089 list_add(&pol->walk.all, &xfrm_policy_all);
1081 hlist_add_head(&pol->bydst, chain); 1090 hlist_add_head(&pol->bydst, chain);
1082 hlist_add_head(&pol->byidx, xfrm_policy_byidx+idx_hash(pol->index)); 1091 hlist_add_head(&pol->byidx, xfrm_policy_byidx+idx_hash(pol->index));
1083 xfrm_policy_count[dir]++; 1092 xfrm_policy_count[dir]++;
@@ -1095,6 +1104,7 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
1095 1104
1096 hlist_del(&pol->bydst); 1105 hlist_del(&pol->bydst);
1097 hlist_del(&pol->byidx); 1106 hlist_del(&pol->byidx);
1107 list_del(&pol->walk.all);
1098 xfrm_policy_count[dir]--; 1108 xfrm_policy_count[dir]--;
1099 1109
1100 return pol; 1110 return pol;
@@ -1242,6 +1252,8 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl,
1242 -EINVAL : -EAGAIN); 1252 -EINVAL : -EAGAIN);
1243 xfrm_state_put(x); 1253 xfrm_state_put(x);
1244 } 1254 }
1255 else if (error == -ESRCH)
1256 error = -EAGAIN;
1245 1257
1246 if (!tmpl->optional) 1258 if (!tmpl->optional)
1247 goto fail; 1259 goto fail;
@@ -1720,7 +1732,7 @@ restart:
1720 1732
1721 for (pi = 0; pi < npols; pi++) { 1733 for (pi = 0; pi < npols; pi++) {
1722 read_lock_bh(&pols[pi]->lock); 1734 read_lock_bh(&pols[pi]->lock);
1723 pol_dead |= pols[pi]->dead; 1735 pol_dead |= pols[pi]->walk.dead;
1724 read_unlock_bh(&pols[pi]->lock); 1736 read_unlock_bh(&pols[pi]->lock);
1725 } 1737 }
1726 1738
@@ -2415,9 +2427,7 @@ static void __init xfrm_policy_init(void)
2415 panic("XFRM: failed to allocate bydst hash\n"); 2427 panic("XFRM: failed to allocate bydst hash\n");
2416 } 2428 }
2417 2429
2418 for (dir = 0; dir < XFRM_POLICY_TYPE_MAX; dir++) 2430 INIT_LIST_HEAD(&xfrm_policy_all);
2419 INIT_LIST_HEAD(&xfrm_policy_bytype[dir]);
2420
2421 INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task); 2431 INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task);
2422 register_netdevice_notifier(&xfrm_dev_notifier); 2432 register_netdevice_notifier(&xfrm_dev_notifier);
2423} 2433}
@@ -2601,7 +2611,7 @@ static int xfrm_policy_migrate(struct xfrm_policy *pol,
2601 int i, j, n = 0; 2611 int i, j, n = 0;
2602 2612
2603 write_lock_bh(&pol->lock); 2613 write_lock_bh(&pol->lock);
2604 if (unlikely(pol->dead)) { 2614 if (unlikely(pol->walk.dead)) {
2605 /* target policy has been deleted */ 2615 /* target policy has been deleted */
2606 write_unlock_bh(&pol->lock); 2616 write_unlock_bh(&pol->lock);
2607 return -ENOENT; 2617 return -ENOENT;
@@ -2672,7 +2682,8 @@ static int xfrm_migrate_check(struct xfrm_migrate *m, int num_migrate)
2672} 2682}
2673 2683
2674int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, 2684int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
2675 struct xfrm_migrate *m, int num_migrate) 2685 struct xfrm_migrate *m, int num_migrate,
2686 struct xfrm_kmaddress *k)
2676{ 2687{
2677 int i, err, nx_cur = 0, nx_new = 0; 2688 int i, err, nx_cur = 0, nx_new = 0;
2678 struct xfrm_policy *pol = NULL; 2689 struct xfrm_policy *pol = NULL;
@@ -2716,7 +2727,7 @@ int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
2716 } 2727 }
2717 2728
2718 /* Stage 5 - announce */ 2729 /* Stage 5 - announce */
2719 km_migrate(sel, dir, type, m, num_migrate); 2730 km_migrate(sel, dir, type, m, num_migrate, k);
2720 2731
2721 xfrm_pol_put(pol); 2732 xfrm_pol_put(pol);
2722 2733
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 0a8f09c3144c..508337f97249 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -408,11 +408,10 @@ static void xfrm_state_gc_task(struct work_struct *data)
408 struct hlist_head gc_list; 408 struct hlist_head gc_list;
409 409
410 spin_lock_bh(&xfrm_state_gc_lock); 410 spin_lock_bh(&xfrm_state_gc_lock);
411 gc_list.first = xfrm_state_gc_list.first; 411 hlist_move_list(&xfrm_state_gc_list, &gc_list);
412 INIT_HLIST_HEAD(&xfrm_state_gc_list);
413 spin_unlock_bh(&xfrm_state_gc_lock); 412 spin_unlock_bh(&xfrm_state_gc_lock);
414 413
415 hlist_for_each_entry_safe(x, entry, tmp, &gc_list, bydst) 414 hlist_for_each_entry_safe(x, entry, tmp, &gc_list, gclist)
416 xfrm_state_gc_destroy(x); 415 xfrm_state_gc_destroy(x);
417 416
418 wake_up(&km_waitq); 417 wake_up(&km_waitq);
@@ -514,7 +513,7 @@ struct xfrm_state *xfrm_state_alloc(void)
514 if (x) { 513 if (x) {
515 atomic_set(&x->refcnt, 1); 514 atomic_set(&x->refcnt, 1);
516 atomic_set(&x->tunnel_users, 0); 515 atomic_set(&x->tunnel_users, 0);
517 INIT_LIST_HEAD(&x->all); 516 INIT_LIST_HEAD(&x->km.all);
518 INIT_HLIST_NODE(&x->bydst); 517 INIT_HLIST_NODE(&x->bydst);
519 INIT_HLIST_NODE(&x->bysrc); 518 INIT_HLIST_NODE(&x->bysrc);
520 INIT_HLIST_NODE(&x->byspi); 519 INIT_HLIST_NODE(&x->byspi);
@@ -540,12 +539,8 @@ void __xfrm_state_destroy(struct xfrm_state *x)
540{ 539{
541 WARN_ON(x->km.state != XFRM_STATE_DEAD); 540 WARN_ON(x->km.state != XFRM_STATE_DEAD);
542 541
543 spin_lock_bh(&xfrm_state_lock);
544 list_del(&x->all);
545 spin_unlock_bh(&xfrm_state_lock);
546
547 spin_lock_bh(&xfrm_state_gc_lock); 542 spin_lock_bh(&xfrm_state_gc_lock);
548 hlist_add_head(&x->bydst, &xfrm_state_gc_list); 543 hlist_add_head(&x->gclist, &xfrm_state_gc_list);
549 spin_unlock_bh(&xfrm_state_gc_lock); 544 spin_unlock_bh(&xfrm_state_gc_lock);
550 schedule_work(&xfrm_state_gc_work); 545 schedule_work(&xfrm_state_gc_work);
551} 546}
@@ -558,6 +553,7 @@ int __xfrm_state_delete(struct xfrm_state *x)
558 if (x->km.state != XFRM_STATE_DEAD) { 553 if (x->km.state != XFRM_STATE_DEAD) {
559 x->km.state = XFRM_STATE_DEAD; 554 x->km.state = XFRM_STATE_DEAD;
560 spin_lock(&xfrm_state_lock); 555 spin_lock(&xfrm_state_lock);
556 list_del(&x->km.all);
561 hlist_del(&x->bydst); 557 hlist_del(&x->bydst);
562 hlist_del(&x->bysrc); 558 hlist_del(&x->bysrc);
563 if (x->id.spi) 559 if (x->id.spi)
@@ -858,7 +854,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
858 854
859 if (km_query(x, tmpl, pol) == 0) { 855 if (km_query(x, tmpl, pol) == 0) {
860 x->km.state = XFRM_STATE_ACQ; 856 x->km.state = XFRM_STATE_ACQ;
861 list_add_tail(&x->all, &xfrm_state_all); 857 list_add(&x->km.all, &xfrm_state_all);
862 hlist_add_head(&x->bydst, xfrm_state_bydst+h); 858 hlist_add_head(&x->bydst, xfrm_state_bydst+h);
863 h = xfrm_src_hash(daddr, saddr, family); 859 h = xfrm_src_hash(daddr, saddr, family);
864 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); 860 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
@@ -927,7 +923,7 @@ static void __xfrm_state_insert(struct xfrm_state *x)
927 923
928 x->genid = ++xfrm_state_genid; 924 x->genid = ++xfrm_state_genid;
929 925
930 list_add_tail(&x->all, &xfrm_state_all); 926 list_add(&x->km.all, &xfrm_state_all);
931 927
932 h = xfrm_dst_hash(&x->id.daddr, &x->props.saddr, 928 h = xfrm_dst_hash(&x->id.daddr, &x->props.saddr,
933 x->props.reqid, x->props.family); 929 x->props.reqid, x->props.family);
@@ -1056,7 +1052,7 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re
1056 xfrm_state_hold(x); 1052 xfrm_state_hold(x);
1057 x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ; 1053 x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ;
1058 add_timer(&x->timer); 1054 add_timer(&x->timer);
1059 list_add_tail(&x->all, &xfrm_state_all); 1055 list_add(&x->km.all, &xfrm_state_all);
1060 hlist_add_head(&x->bydst, xfrm_state_bydst+h); 1056 hlist_add_head(&x->bydst, xfrm_state_bydst+h);
1061 h = xfrm_src_hash(daddr, saddr, family); 1057 h = xfrm_src_hash(daddr, saddr, family);
1062 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); 1058 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
@@ -1553,47 +1549,62 @@ int xfrm_state_walk(struct xfrm_state_walk *walk,
1553 int (*func)(struct xfrm_state *, int, void*), 1549 int (*func)(struct xfrm_state *, int, void*),
1554 void *data) 1550 void *data)
1555{ 1551{
1556 struct xfrm_state *old, *x, *last = NULL; 1552 struct xfrm_state *state;
1553 struct xfrm_state_walk *x;
1557 int err = 0; 1554 int err = 0;
1558 1555
1559 if (walk->state == NULL && walk->count != 0) 1556 if (walk->seq != 0 && list_empty(&walk->all))
1560 return 0; 1557 return 0;
1561 1558
1562 old = x = walk->state;
1563 walk->state = NULL;
1564 spin_lock_bh(&xfrm_state_lock); 1559 spin_lock_bh(&xfrm_state_lock);
1565 if (x == NULL) 1560 if (list_empty(&walk->all))
1566 x = list_first_entry(&xfrm_state_all, struct xfrm_state, all); 1561 x = list_first_entry(&xfrm_state_all, struct xfrm_state_walk, all);
1562 else
1563 x = list_entry(&walk->all, struct xfrm_state_walk, all);
1567 list_for_each_entry_from(x, &xfrm_state_all, all) { 1564 list_for_each_entry_from(x, &xfrm_state_all, all) {
1568 if (x->km.state == XFRM_STATE_DEAD) 1565 if (x->state == XFRM_STATE_DEAD)
1569 continue; 1566 continue;
1570 if (!xfrm_id_proto_match(x->id.proto, walk->proto)) 1567 state = container_of(x, struct xfrm_state, km);
1568 if (!xfrm_id_proto_match(state->id.proto, walk->proto))
1571 continue; 1569 continue;
1572 if (last) { 1570 err = func(state, walk->seq, data);
1573 err = func(last, walk->count, data); 1571 if (err) {
1574 if (err) { 1572 list_move_tail(&walk->all, &x->all);
1575 xfrm_state_hold(last); 1573 goto out;
1576 walk->state = last;
1577 goto out;
1578 }
1579 } 1574 }
1580 last = x; 1575 walk->seq++;
1581 walk->count++;
1582 } 1576 }
1583 if (walk->count == 0) { 1577 if (walk->seq == 0) {
1584 err = -ENOENT; 1578 err = -ENOENT;
1585 goto out; 1579 goto out;
1586 } 1580 }
1587 if (last) 1581 list_del_init(&walk->all);
1588 err = func(last, 0, data);
1589out: 1582out:
1590 spin_unlock_bh(&xfrm_state_lock); 1583 spin_unlock_bh(&xfrm_state_lock);
1591 if (old != NULL)
1592 xfrm_state_put(old);
1593 return err; 1584 return err;
1594} 1585}
1595EXPORT_SYMBOL(xfrm_state_walk); 1586EXPORT_SYMBOL(xfrm_state_walk);
1596 1587
1588void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto)
1589{
1590 INIT_LIST_HEAD(&walk->all);
1591 walk->proto = proto;
1592 walk->state = XFRM_STATE_DEAD;
1593 walk->seq = 0;
1594}
1595EXPORT_SYMBOL(xfrm_state_walk_init);
1596
1597void xfrm_state_walk_done(struct xfrm_state_walk *walk)
1598{
1599 if (list_empty(&walk->all))
1600 return;
1601
1602 spin_lock_bh(&xfrm_state_lock);
1603 list_del(&walk->all);
1604 spin_lock_bh(&xfrm_state_lock);
1605}
1606EXPORT_SYMBOL(xfrm_state_walk_done);
1607
1597 1608
1598void xfrm_replay_notify(struct xfrm_state *x, int event) 1609void xfrm_replay_notify(struct xfrm_state *x, int event)
1599{ 1610{
@@ -1803,7 +1814,8 @@ EXPORT_SYMBOL(km_policy_expired);
1803 1814
1804#ifdef CONFIG_XFRM_MIGRATE 1815#ifdef CONFIG_XFRM_MIGRATE
1805int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, 1816int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
1806 struct xfrm_migrate *m, int num_migrate) 1817 struct xfrm_migrate *m, int num_migrate,
1818 struct xfrm_kmaddress *k)
1807{ 1819{
1808 int err = -EINVAL; 1820 int err = -EINVAL;
1809 int ret; 1821 int ret;
@@ -1812,7 +1824,7 @@ int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
1812 read_lock(&xfrm_km_lock); 1824 read_lock(&xfrm_km_lock);
1813 list_for_each_entry(km, &xfrm_km_list, list) { 1825 list_for_each_entry(km, &xfrm_km_list, list) {
1814 if (km->migrate) { 1826 if (km->migrate) {
1815 ret = km->migrate(sel, dir, type, m, num_migrate); 1827 ret = km->migrate(sel, dir, type, m, num_migrate, k);
1816 if (!ret) 1828 if (!ret)
1817 err = ret; 1829 err = ret;
1818 } 1830 }
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 04c41504f84c..a278a6f3b991 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1102,7 +1102,7 @@ static struct xfrm_policy *xfrm_policy_construct(struct xfrm_userpolicy_info *p,
1102 return xp; 1102 return xp;
1103 error: 1103 error:
1104 *errp = err; 1104 *errp = err;
1105 xp->dead = 1; 1105 xp->walk.dead = 1;
1106 xfrm_policy_destroy(xp); 1106 xfrm_policy_destroy(xp);
1107 return NULL; 1107 return NULL;
1108} 1108}
@@ -1595,7 +1595,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
1595 return -ENOENT; 1595 return -ENOENT;
1596 1596
1597 read_lock(&xp->lock); 1597 read_lock(&xp->lock);
1598 if (xp->dead) { 1598 if (xp->walk.dead) {
1599 read_unlock(&xp->lock); 1599 read_unlock(&xp->lock);
1600 goto out; 1600 goto out;
1601 } 1601 }
@@ -1710,12 +1710,23 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
1710 1710
1711#ifdef CONFIG_XFRM_MIGRATE 1711#ifdef CONFIG_XFRM_MIGRATE
1712static int copy_from_user_migrate(struct xfrm_migrate *ma, 1712static int copy_from_user_migrate(struct xfrm_migrate *ma,
1713 struct xfrm_kmaddress *k,
1713 struct nlattr **attrs, int *num) 1714 struct nlattr **attrs, int *num)
1714{ 1715{
1715 struct nlattr *rt = attrs[XFRMA_MIGRATE]; 1716 struct nlattr *rt = attrs[XFRMA_MIGRATE];
1716 struct xfrm_user_migrate *um; 1717 struct xfrm_user_migrate *um;
1717 int i, num_migrate; 1718 int i, num_migrate;
1718 1719
1720 if (k != NULL) {
1721 struct xfrm_user_kmaddress *uk;
1722
1723 uk = nla_data(attrs[XFRMA_KMADDRESS]);
1724 memcpy(&k->local, &uk->local, sizeof(k->local));
1725 memcpy(&k->remote, &uk->remote, sizeof(k->remote));
1726 k->family = uk->family;
1727 k->reserved = uk->reserved;
1728 }
1729
1719 um = nla_data(rt); 1730 um = nla_data(rt);
1720 num_migrate = nla_len(rt) / sizeof(*um); 1731 num_migrate = nla_len(rt) / sizeof(*um);
1721 1732
@@ -1745,6 +1756,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
1745{ 1756{
1746 struct xfrm_userpolicy_id *pi = nlmsg_data(nlh); 1757 struct xfrm_userpolicy_id *pi = nlmsg_data(nlh);
1747 struct xfrm_migrate m[XFRM_MAX_DEPTH]; 1758 struct xfrm_migrate m[XFRM_MAX_DEPTH];
1759 struct xfrm_kmaddress km, *kmp;
1748 u8 type; 1760 u8 type;
1749 int err; 1761 int err;
1750 int n = 0; 1762 int n = 0;
@@ -1752,19 +1764,20 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
1752 if (attrs[XFRMA_MIGRATE] == NULL) 1764 if (attrs[XFRMA_MIGRATE] == NULL)
1753 return -EINVAL; 1765 return -EINVAL;
1754 1766
1767 kmp = attrs[XFRMA_KMADDRESS] ? &km : NULL;
1768
1755 err = copy_from_user_policy_type(&type, attrs); 1769 err = copy_from_user_policy_type(&type, attrs);
1756 if (err) 1770 if (err)
1757 return err; 1771 return err;
1758 1772
1759 err = copy_from_user_migrate((struct xfrm_migrate *)m, 1773 err = copy_from_user_migrate((struct xfrm_migrate *)m, kmp, attrs, &n);
1760 attrs, &n);
1761 if (err) 1774 if (err)
1762 return err; 1775 return err;
1763 1776
1764 if (!n) 1777 if (!n)
1765 return 0; 1778 return 0;
1766 1779
1767 xfrm_migrate(&pi->sel, pi->dir, type, m, n); 1780 xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp);
1768 1781
1769 return 0; 1782 return 0;
1770} 1783}
@@ -1795,16 +1808,30 @@ static int copy_to_user_migrate(struct xfrm_migrate *m, struct sk_buff *skb)
1795 return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um); 1808 return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um);
1796} 1809}
1797 1810
1798static inline size_t xfrm_migrate_msgsize(int num_migrate) 1811static int copy_to_user_kmaddress(struct xfrm_kmaddress *k, struct sk_buff *skb)
1812{
1813 struct xfrm_user_kmaddress uk;
1814
1815 memset(&uk, 0, sizeof(uk));
1816 uk.family = k->family;
1817 uk.reserved = k->reserved;
1818 memcpy(&uk.local, &k->local, sizeof(uk.local));
1819 memcpy(&uk.remote, &k->remote, sizeof(uk.remote));
1820
1821 return nla_put(skb, XFRMA_KMADDRESS, sizeof(uk), &uk);
1822}
1823
1824static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma)
1799{ 1825{
1800 return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id)) 1826 return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id))
1801 + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate) 1827 + (with_kma ? nla_total_size(sizeof(struct xfrm_kmaddress)) : 0)
1802 + userpolicy_type_attrsize(); 1828 + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate)
1829 + userpolicy_type_attrsize();
1803} 1830}
1804 1831
1805static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m, 1832static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m,
1806 int num_migrate, struct xfrm_selector *sel, 1833 int num_migrate, struct xfrm_kmaddress *k,
1807 u8 dir, u8 type) 1834 struct xfrm_selector *sel, u8 dir, u8 type)
1808{ 1835{
1809 struct xfrm_migrate *mp; 1836 struct xfrm_migrate *mp;
1810 struct xfrm_userpolicy_id *pol_id; 1837 struct xfrm_userpolicy_id *pol_id;
@@ -1821,6 +1848,9 @@ static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m,
1821 memcpy(&pol_id->sel, sel, sizeof(pol_id->sel)); 1848 memcpy(&pol_id->sel, sel, sizeof(pol_id->sel));
1822 pol_id->dir = dir; 1849 pol_id->dir = dir;
1823 1850
1851 if (k != NULL && (copy_to_user_kmaddress(k, skb) < 0))
1852 goto nlmsg_failure;
1853
1824 if (copy_to_user_policy_type(type, skb) < 0) 1854 if (copy_to_user_policy_type(type, skb) < 0)
1825 goto nlmsg_failure; 1855 goto nlmsg_failure;
1826 1856
@@ -1836,23 +1866,25 @@ nlmsg_failure:
1836} 1866}
1837 1867
1838static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, 1868static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
1839 struct xfrm_migrate *m, int num_migrate) 1869 struct xfrm_migrate *m, int num_migrate,
1870 struct xfrm_kmaddress *k)
1840{ 1871{
1841 struct sk_buff *skb; 1872 struct sk_buff *skb;
1842 1873
1843 skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate), GFP_ATOMIC); 1874 skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k), GFP_ATOMIC);
1844 if (skb == NULL) 1875 if (skb == NULL)
1845 return -ENOMEM; 1876 return -ENOMEM;
1846 1877
1847 /* build migrate */ 1878 /* build migrate */
1848 if (build_migrate(skb, m, num_migrate, sel, dir, type) < 0) 1879 if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0)
1849 BUG(); 1880 BUG();
1850 1881
1851 return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC); 1882 return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC);
1852} 1883}
1853#else 1884#else
1854static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, 1885static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
1855 struct xfrm_migrate *m, int num_migrate) 1886 struct xfrm_migrate *m, int num_migrate,
1887 struct xfrm_kmaddress *k)
1856{ 1888{
1857 return -ENOPROTOOPT; 1889 return -ENOPROTOOPT;
1858} 1890}
@@ -1901,6 +1933,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
1901 [XFRMA_COADDR] = { .len = sizeof(xfrm_address_t) }, 1933 [XFRMA_COADDR] = { .len = sizeof(xfrm_address_t) },
1902 [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)}, 1934 [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)},
1903 [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) }, 1935 [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) },
1936 [XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) },
1904}; 1937};
1905 1938
1906static struct xfrm_link { 1939static struct xfrm_link {