diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-25 14:17:34 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-25 14:17:34 -0500 |
commit | 4ba9920e5e9c0e16b5ed24292d45322907bb9035 (patch) | |
tree | 7d023baea59ed0886ded1f0b6d1c6385690b88f7 /net/xfrm/xfrm_policy.c | |
parent | 82c477669a4665eb4e52030792051e0559ee2a36 (diff) | |
parent | 8b662fe70c68282f78482dc272df0c4f355e49f5 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller:
1) BPF debugger and asm tool by Daniel Borkmann.
2) Speed up create/bind in AF_PACKET, also from Daniel Borkmann.
3) Correct reciprocal_divide and update users, from Hannes Frederic
Sowa and Daniel Borkmann.
4) Currently we only have a "set" operation for the hw timestamp socket
ioctl, add a "get" operation to match. From Ben Hutchings.
5) Add better trace events for debugging driver datapath problems, also
from Ben Hutchings.
6) Implement auto corking in TCP, from Eric Dumazet. Basically, if we
have a small send and a previous packet is already in the qdisc or
device queue, defer until TX completion or we get more data.
7) Allow userspace to manage ipv6 temporary addresses, from Jiri Pirko.
8) Add a qdisc bypass option for AF_PACKET sockets, from Daniel
Borkmann.
9) Share IP header compression code between Bluetooth and IEEE802154
layers, from Jukka Rissanen.
10) Fix ipv6 router reachability probing, from Jiri Benc.
11) Allow packets to be captured on macvtap devices, from Vlad Yasevich.
12) Support tunneling in GRO layer, from Jerry Chu.
13) Allow bonding to be configured fully using netlink, from Scott
Feldman.
14) Allow AF_PACKET users to obtain the VLAN TPID, just like they can
already get the TCI. From Atzm Watanabe.
15) New "Heavy Hitter" qdisc, from Terry Lam.
16) Significantly improve the IPSEC support in pktgen, from Fan Du.
17) Allow ipv4 tunnels to cache routes, just like sockets. From Tom
Herbert.
18) Add Proportional Integral Enhanced packet scheduler, from Vijay
Subramanian.
19) Allow openvswitch to mmap'd netlink, from Thomas Graf.
20) Key TCP metrics blobs also by source address, not just destination
address. From Christoph Paasch.
21) Support 10G in generic phylib. From Andy Fleming.
22) Try to short-circuit GRO flow compares using device provided RX
hash, if provided. From Tom Herbert.
The wireless and netfilter folks have been busy little bees too.
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (2064 commits)
net/cxgb4: Fix referencing freed adapter
ipv6: reallocate addrconf router for ipv6 address when lo device up
fib_frontend: fix possible NULL pointer dereference
rtnetlink: remove IFLA_BOND_SLAVE definition
rtnetlink: remove check for fill_slave_info in rtnl_have_link_slave_info
qlcnic: update version to 5.3.55
qlcnic: Enhance logic to calculate msix vectors.
qlcnic: Refactor interrupt coalescing code for all adapters.
qlcnic: Update poll controller code path
qlcnic: Interrupt code cleanup
qlcnic: Enhance Tx timeout debugging.
qlcnic: Use bool for rx_mac_learn.
bonding: fix u64 division
rtnetlink: add missing IFLA_BOND_AD_INFO_UNSPEC
sfc: Use the correct maximum TX DMA ring size for SFC9100
Add Shradha Shah as the sfc driver maintainer.
net/vxlan: Share RX skb de-marking and checksum checks with ovs
tulip: cleanup by using ARRAY_SIZE()
ip_tunnel: clear IPCB in ip_tunnel_xmit() in case dst_link_failure() is called
net/cxgb4: Don't retrieve stats during recovery
...
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
-rw-r--r-- | net/xfrm/xfrm_policy.c | 195 |
1 files changed, 96 insertions, 99 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 0d49945d0b9e..4b98b25793c5 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -39,12 +39,7 @@ | |||
39 | #define XFRM_QUEUE_TMO_MAX ((unsigned)(60*HZ)) | 39 | #define XFRM_QUEUE_TMO_MAX ((unsigned)(60*HZ)) |
40 | #define XFRM_MAX_QUEUE_LEN 100 | 40 | #define XFRM_MAX_QUEUE_LEN 100 |
41 | 41 | ||
42 | DEFINE_MUTEX(xfrm_cfg_mutex); | ||
43 | EXPORT_SYMBOL(xfrm_cfg_mutex); | ||
44 | |||
45 | static DEFINE_SPINLOCK(xfrm_policy_sk_bundle_lock); | ||
46 | static struct dst_entry *xfrm_policy_sk_bundles; | 42 | static struct dst_entry *xfrm_policy_sk_bundles; |
47 | static DEFINE_RWLOCK(xfrm_policy_lock); | ||
48 | 43 | ||
49 | static DEFINE_SPINLOCK(xfrm_policy_afinfo_lock); | 44 | static DEFINE_SPINLOCK(xfrm_policy_afinfo_lock); |
50 | static struct xfrm_policy_afinfo __rcu *xfrm_policy_afinfo[NPROTO] | 45 | static struct xfrm_policy_afinfo __rcu *xfrm_policy_afinfo[NPROTO] |
@@ -176,7 +171,7 @@ static inline unsigned long make_jiffies(long secs) | |||
176 | 171 | ||
177 | static void xfrm_policy_timer(unsigned long data) | 172 | static void xfrm_policy_timer(unsigned long data) |
178 | { | 173 | { |
179 | struct xfrm_policy *xp = (struct xfrm_policy*)data; | 174 | struct xfrm_policy *xp = (struct xfrm_policy *)data; |
180 | unsigned long now = get_seconds(); | 175 | unsigned long now = get_seconds(); |
181 | long next = LONG_MAX; | 176 | long next = LONG_MAX; |
182 | int warn = 0; | 177 | int warn = 0; |
@@ -438,7 +433,7 @@ static void xfrm_bydst_resize(struct net *net, int dir) | |||
438 | if (!ndst) | 433 | if (!ndst) |
439 | return; | 434 | return; |
440 | 435 | ||
441 | write_lock_bh(&xfrm_policy_lock); | 436 | write_lock_bh(&net->xfrm.xfrm_policy_lock); |
442 | 437 | ||
443 | for (i = hmask; i >= 0; i--) | 438 | for (i = hmask; i >= 0; i--) |
444 | xfrm_dst_hash_transfer(odst + i, ndst, nhashmask); | 439 | xfrm_dst_hash_transfer(odst + i, ndst, nhashmask); |
@@ -446,7 +441,7 @@ static void xfrm_bydst_resize(struct net *net, int dir) | |||
446 | net->xfrm.policy_bydst[dir].table = ndst; | 441 | net->xfrm.policy_bydst[dir].table = ndst; |
447 | net->xfrm.policy_bydst[dir].hmask = nhashmask; | 442 | net->xfrm.policy_bydst[dir].hmask = nhashmask; |
448 | 443 | ||
449 | write_unlock_bh(&xfrm_policy_lock); | 444 | write_unlock_bh(&net->xfrm.xfrm_policy_lock); |
450 | 445 | ||
451 | xfrm_hash_free(odst, (hmask + 1) * sizeof(struct hlist_head)); | 446 | xfrm_hash_free(odst, (hmask + 1) * sizeof(struct hlist_head)); |
452 | } | 447 | } |
@@ -463,7 +458,7 @@ static void xfrm_byidx_resize(struct net *net, int total) | |||
463 | if (!nidx) | 458 | if (!nidx) |
464 | return; | 459 | return; |
465 | 460 | ||
466 | write_lock_bh(&xfrm_policy_lock); | 461 | write_lock_bh(&net->xfrm.xfrm_policy_lock); |
467 | 462 | ||
468 | for (i = hmask; i >= 0; i--) | 463 | for (i = hmask; i >= 0; i--) |
469 | xfrm_idx_hash_transfer(oidx + i, nidx, nhashmask); | 464 | xfrm_idx_hash_transfer(oidx + i, nidx, nhashmask); |
@@ -471,7 +466,7 @@ static void xfrm_byidx_resize(struct net *net, int total) | |||
471 | net->xfrm.policy_byidx = nidx; | 466 | net->xfrm.policy_byidx = nidx; |
472 | net->xfrm.policy_idx_hmask = nhashmask; | 467 | net->xfrm.policy_idx_hmask = nhashmask; |
473 | 468 | ||
474 | write_unlock_bh(&xfrm_policy_lock); | 469 | write_unlock_bh(&net->xfrm.xfrm_policy_lock); |
475 | 470 | ||
476 | xfrm_hash_free(oidx, (hmask + 1) * sizeof(struct hlist_head)); | 471 | xfrm_hash_free(oidx, (hmask + 1) * sizeof(struct hlist_head)); |
477 | } | 472 | } |
@@ -504,7 +499,7 @@ static inline int xfrm_byidx_should_resize(struct net *net, int total) | |||
504 | 499 | ||
505 | void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si) | 500 | void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si) |
506 | { | 501 | { |
507 | read_lock_bh(&xfrm_policy_lock); | 502 | read_lock_bh(&net->xfrm.xfrm_policy_lock); |
508 | si->incnt = net->xfrm.policy_count[XFRM_POLICY_IN]; | 503 | si->incnt = net->xfrm.policy_count[XFRM_POLICY_IN]; |
509 | si->outcnt = net->xfrm.policy_count[XFRM_POLICY_OUT]; | 504 | si->outcnt = net->xfrm.policy_count[XFRM_POLICY_OUT]; |
510 | si->fwdcnt = net->xfrm.policy_count[XFRM_POLICY_FWD]; | 505 | si->fwdcnt = net->xfrm.policy_count[XFRM_POLICY_FWD]; |
@@ -513,7 +508,7 @@ void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si) | |||
513 | si->fwdscnt = net->xfrm.policy_count[XFRM_POLICY_FWD+XFRM_POLICY_MAX]; | 508 | si->fwdscnt = net->xfrm.policy_count[XFRM_POLICY_FWD+XFRM_POLICY_MAX]; |
514 | si->spdhcnt = net->xfrm.policy_idx_hmask; | 509 | si->spdhcnt = net->xfrm.policy_idx_hmask; |
515 | si->spdhmcnt = xfrm_policy_hashmax; | 510 | si->spdhmcnt = xfrm_policy_hashmax; |
516 | read_unlock_bh(&xfrm_policy_lock); | 511 | read_unlock_bh(&net->xfrm.xfrm_policy_lock); |
517 | } | 512 | } |
518 | EXPORT_SYMBOL(xfrm_spd_getinfo); | 513 | EXPORT_SYMBOL(xfrm_spd_getinfo); |
519 | 514 | ||
@@ -538,7 +533,7 @@ static void xfrm_hash_resize(struct work_struct *work) | |||
538 | 533 | ||
539 | /* Generate new index... KAME seems to generate them ordered by cost | 534 | /* Generate new index... KAME seems to generate them ordered by cost |
540 | * of an absolute inpredictability of ordering of rules. This will not pass. */ | 535 | * of an absolute inpredictability of ordering of rules. This will not pass. */ |
541 | static u32 xfrm_gen_index(struct net *net, int dir) | 536 | static u32 xfrm_gen_index(struct net *net, int dir, u32 index) |
542 | { | 537 | { |
543 | static u32 idx_generator; | 538 | static u32 idx_generator; |
544 | 539 | ||
@@ -548,8 +543,14 @@ static u32 xfrm_gen_index(struct net *net, int dir) | |||
548 | u32 idx; | 543 | u32 idx; |
549 | int found; | 544 | int found; |
550 | 545 | ||
551 | idx = (idx_generator | dir); | 546 | if (!index) { |
552 | idx_generator += 8; | 547 | idx = (idx_generator | dir); |
548 | idx_generator += 8; | ||
549 | } else { | ||
550 | idx = index; | ||
551 | index = 0; | ||
552 | } | ||
553 | |||
553 | if (idx == 0) | 554 | if (idx == 0) |
554 | idx = 8; | 555 | idx = 8; |
555 | list = net->xfrm.policy_byidx + idx_hash(net, idx); | 556 | list = net->xfrm.policy_byidx + idx_hash(net, idx); |
@@ -630,7 +631,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
630 | struct hlist_head *chain; | 631 | struct hlist_head *chain; |
631 | struct hlist_node *newpos; | 632 | struct hlist_node *newpos; |
632 | 633 | ||
633 | write_lock_bh(&xfrm_policy_lock); | 634 | write_lock_bh(&net->xfrm.xfrm_policy_lock); |
634 | chain = policy_hash_bysel(net, &policy->selector, policy->family, dir); | 635 | chain = policy_hash_bysel(net, &policy->selector, policy->family, dir); |
635 | delpol = NULL; | 636 | delpol = NULL; |
636 | newpos = NULL; | 637 | newpos = NULL; |
@@ -641,7 +642,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
641 | xfrm_sec_ctx_match(pol->security, policy->security) && | 642 | xfrm_sec_ctx_match(pol->security, policy->security) && |
642 | !WARN_ON(delpol)) { | 643 | !WARN_ON(delpol)) { |
643 | if (excl) { | 644 | if (excl) { |
644 | write_unlock_bh(&xfrm_policy_lock); | 645 | write_unlock_bh(&net->xfrm.xfrm_policy_lock); |
645 | return -EEXIST; | 646 | return -EEXIST; |
646 | } | 647 | } |
647 | delpol = pol; | 648 | delpol = pol; |
@@ -672,14 +673,14 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
672 | xfrm_policy_requeue(delpol, policy); | 673 | xfrm_policy_requeue(delpol, policy); |
673 | __xfrm_policy_unlink(delpol, dir); | 674 | __xfrm_policy_unlink(delpol, dir); |
674 | } | 675 | } |
675 | policy->index = delpol ? delpol->index : xfrm_gen_index(net, dir); | 676 | policy->index = delpol ? delpol->index : xfrm_gen_index(net, dir, policy->index); |
676 | hlist_add_head(&policy->byidx, net->xfrm.policy_byidx+idx_hash(net, policy->index)); | 677 | hlist_add_head(&policy->byidx, net->xfrm.policy_byidx+idx_hash(net, policy->index)); |
677 | policy->curlft.add_time = get_seconds(); | 678 | policy->curlft.add_time = get_seconds(); |
678 | policy->curlft.use_time = 0; | 679 | policy->curlft.use_time = 0; |
679 | if (!mod_timer(&policy->timer, jiffies + HZ)) | 680 | if (!mod_timer(&policy->timer, jiffies + HZ)) |
680 | xfrm_pol_hold(policy); | 681 | xfrm_pol_hold(policy); |
681 | list_add(&policy->walk.all, &net->xfrm.policy_all); | 682 | list_add(&policy->walk.all, &net->xfrm.policy_all); |
682 | write_unlock_bh(&xfrm_policy_lock); | 683 | write_unlock_bh(&net->xfrm.xfrm_policy_lock); |
683 | 684 | ||
684 | if (delpol) | 685 | if (delpol) |
685 | xfrm_policy_kill(delpol); | 686 | xfrm_policy_kill(delpol); |
@@ -699,7 +700,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type, | |||
699 | struct hlist_head *chain; | 700 | struct hlist_head *chain; |
700 | 701 | ||
701 | *err = 0; | 702 | *err = 0; |
702 | write_lock_bh(&xfrm_policy_lock); | 703 | write_lock_bh(&net->xfrm.xfrm_policy_lock); |
703 | chain = policy_hash_bysel(net, sel, sel->family, dir); | 704 | chain = policy_hash_bysel(net, sel, sel->family, dir); |
704 | ret = NULL; | 705 | ret = NULL; |
705 | hlist_for_each_entry(pol, chain, bydst) { | 706 | hlist_for_each_entry(pol, chain, bydst) { |
@@ -712,7 +713,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type, | |||
712 | *err = security_xfrm_policy_delete( | 713 | *err = security_xfrm_policy_delete( |
713 | pol->security); | 714 | pol->security); |
714 | if (*err) { | 715 | if (*err) { |
715 | write_unlock_bh(&xfrm_policy_lock); | 716 | write_unlock_bh(&net->xfrm.xfrm_policy_lock); |
716 | return pol; | 717 | return pol; |
717 | } | 718 | } |
718 | __xfrm_policy_unlink(pol, dir); | 719 | __xfrm_policy_unlink(pol, dir); |
@@ -721,7 +722,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type, | |||
721 | break; | 722 | break; |
722 | } | 723 | } |
723 | } | 724 | } |
724 | write_unlock_bh(&xfrm_policy_lock); | 725 | write_unlock_bh(&net->xfrm.xfrm_policy_lock); |
725 | 726 | ||
726 | if (ret && delete) | 727 | if (ret && delete) |
727 | xfrm_policy_kill(ret); | 728 | xfrm_policy_kill(ret); |
@@ -740,7 +741,7 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8 type, | |||
740 | return NULL; | 741 | return NULL; |
741 | 742 | ||
742 | *err = 0; | 743 | *err = 0; |
743 | write_lock_bh(&xfrm_policy_lock); | 744 | write_lock_bh(&net->xfrm.xfrm_policy_lock); |
744 | chain = net->xfrm.policy_byidx + idx_hash(net, id); | 745 | chain = net->xfrm.policy_byidx + idx_hash(net, id); |
745 | ret = NULL; | 746 | ret = NULL; |
746 | hlist_for_each_entry(pol, chain, byidx) { | 747 | hlist_for_each_entry(pol, chain, byidx) { |
@@ -751,7 +752,7 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8 type, | |||
751 | *err = security_xfrm_policy_delete( | 752 | *err = security_xfrm_policy_delete( |
752 | pol->security); | 753 | pol->security); |
753 | if (*err) { | 754 | if (*err) { |
754 | write_unlock_bh(&xfrm_policy_lock); | 755 | write_unlock_bh(&net->xfrm.xfrm_policy_lock); |
755 | return pol; | 756 | return pol; |
756 | } | 757 | } |
757 | __xfrm_policy_unlink(pol, dir); | 758 | __xfrm_policy_unlink(pol, dir); |
@@ -760,7 +761,7 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8 type, | |||
760 | break; | 761 | break; |
761 | } | 762 | } |
762 | } | 763 | } |
763 | write_unlock_bh(&xfrm_policy_lock); | 764 | write_unlock_bh(&net->xfrm.xfrm_policy_lock); |
764 | 765 | ||
765 | if (ret && delete) | 766 | if (ret && delete) |
766 | xfrm_policy_kill(ret); | 767 | xfrm_policy_kill(ret); |
@@ -823,7 +824,7 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) | |||
823 | { | 824 | { |
824 | int dir, err = 0, cnt = 0; | 825 | int dir, err = 0, cnt = 0; |
825 | 826 | ||
826 | write_lock_bh(&xfrm_policy_lock); | 827 | write_lock_bh(&net->xfrm.xfrm_policy_lock); |
827 | 828 | ||
828 | err = xfrm_policy_flush_secctx_check(net, type, audit_info); | 829 | err = xfrm_policy_flush_secctx_check(net, type, audit_info); |
829 | if (err) | 830 | if (err) |
@@ -839,7 +840,7 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) | |||
839 | if (pol->type != type) | 840 | if (pol->type != type) |
840 | continue; | 841 | continue; |
841 | __xfrm_policy_unlink(pol, dir); | 842 | __xfrm_policy_unlink(pol, dir); |
842 | write_unlock_bh(&xfrm_policy_lock); | 843 | write_unlock_bh(&net->xfrm.xfrm_policy_lock); |
843 | cnt++; | 844 | cnt++; |
844 | 845 | ||
845 | xfrm_audit_policy_delete(pol, 1, audit_info->loginuid, | 846 | xfrm_audit_policy_delete(pol, 1, audit_info->loginuid, |
@@ -848,7 +849,7 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) | |||
848 | 849 | ||
849 | xfrm_policy_kill(pol); | 850 | xfrm_policy_kill(pol); |
850 | 851 | ||
851 | write_lock_bh(&xfrm_policy_lock); | 852 | write_lock_bh(&net->xfrm.xfrm_policy_lock); |
852 | goto again1; | 853 | goto again1; |
853 | } | 854 | } |
854 | 855 | ||
@@ -860,7 +861,7 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) | |||
860 | if (pol->type != type) | 861 | if (pol->type != type) |
861 | continue; | 862 | continue; |
862 | __xfrm_policy_unlink(pol, dir); | 863 | __xfrm_policy_unlink(pol, dir); |
863 | write_unlock_bh(&xfrm_policy_lock); | 864 | write_unlock_bh(&net->xfrm.xfrm_policy_lock); |
864 | cnt++; | 865 | cnt++; |
865 | 866 | ||
866 | xfrm_audit_policy_delete(pol, 1, | 867 | xfrm_audit_policy_delete(pol, 1, |
@@ -869,7 +870,7 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) | |||
869 | audit_info->secid); | 870 | audit_info->secid); |
870 | xfrm_policy_kill(pol); | 871 | xfrm_policy_kill(pol); |
871 | 872 | ||
872 | write_lock_bh(&xfrm_policy_lock); | 873 | write_lock_bh(&net->xfrm.xfrm_policy_lock); |
873 | goto again2; | 874 | goto again2; |
874 | } | 875 | } |
875 | } | 876 | } |
@@ -878,7 +879,7 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) | |||
878 | if (!cnt) | 879 | if (!cnt) |
879 | err = -ESRCH; | 880 | err = -ESRCH; |
880 | out: | 881 | out: |
881 | write_unlock_bh(&xfrm_policy_lock); | 882 | write_unlock_bh(&net->xfrm.xfrm_policy_lock); |
882 | return err; | 883 | return err; |
883 | } | 884 | } |
884 | EXPORT_SYMBOL(xfrm_policy_flush); | 885 | EXPORT_SYMBOL(xfrm_policy_flush); |
@@ -898,7 +899,7 @@ int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk, | |||
898 | if (list_empty(&walk->walk.all) && walk->seq != 0) | 899 | if (list_empty(&walk->walk.all) && walk->seq != 0) |
899 | return 0; | 900 | return 0; |
900 | 901 | ||
901 | write_lock_bh(&xfrm_policy_lock); | 902 | write_lock_bh(&net->xfrm.xfrm_policy_lock); |
902 | if (list_empty(&walk->walk.all)) | 903 | if (list_empty(&walk->walk.all)) |
903 | x = list_first_entry(&net->xfrm.policy_all, struct xfrm_policy_walk_entry, all); | 904 | x = list_first_entry(&net->xfrm.policy_all, struct xfrm_policy_walk_entry, all); |
904 | else | 905 | else |
@@ -924,7 +925,7 @@ int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk, | |||
924 | } | 925 | } |
925 | list_del_init(&walk->walk.all); | 926 | list_del_init(&walk->walk.all); |
926 | out: | 927 | out: |
927 | write_unlock_bh(&xfrm_policy_lock); | 928 | write_unlock_bh(&net->xfrm.xfrm_policy_lock); |
928 | return error; | 929 | return error; |
929 | } | 930 | } |
930 | EXPORT_SYMBOL(xfrm_policy_walk); | 931 | EXPORT_SYMBOL(xfrm_policy_walk); |
@@ -938,14 +939,14 @@ void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type) | |||
938 | } | 939 | } |
939 | EXPORT_SYMBOL(xfrm_policy_walk_init); | 940 | EXPORT_SYMBOL(xfrm_policy_walk_init); |
940 | 941 | ||
941 | void xfrm_policy_walk_done(struct xfrm_policy_walk *walk) | 942 | void xfrm_policy_walk_done(struct xfrm_policy_walk *walk, struct net *net) |
942 | { | 943 | { |
943 | if (list_empty(&walk->walk.all)) | 944 | if (list_empty(&walk->walk.all)) |
944 | return; | 945 | return; |
945 | 946 | ||
946 | write_lock_bh(&xfrm_policy_lock); | 947 | write_lock_bh(&net->xfrm.xfrm_policy_lock); /*FIXME where is net? */ |
947 | list_del(&walk->walk.all); | 948 | list_del(&walk->walk.all); |
948 | write_unlock_bh(&xfrm_policy_lock); | 949 | write_unlock_bh(&net->xfrm.xfrm_policy_lock); |
949 | } | 950 | } |
950 | EXPORT_SYMBOL(xfrm_policy_walk_done); | 951 | EXPORT_SYMBOL(xfrm_policy_walk_done); |
951 | 952 | ||
@@ -990,7 +991,7 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(struct net *net, u8 type, | |||
990 | if (unlikely(!daddr || !saddr)) | 991 | if (unlikely(!daddr || !saddr)) |
991 | return NULL; | 992 | return NULL; |
992 | 993 | ||
993 | read_lock_bh(&xfrm_policy_lock); | 994 | read_lock_bh(&net->xfrm.xfrm_policy_lock); |
994 | chain = policy_hash_direct(net, daddr, saddr, family, dir); | 995 | chain = policy_hash_direct(net, daddr, saddr, family, dir); |
995 | ret = NULL; | 996 | ret = NULL; |
996 | hlist_for_each_entry(pol, chain, bydst) { | 997 | hlist_for_each_entry(pol, chain, bydst) { |
@@ -1026,7 +1027,7 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(struct net *net, u8 type, | |||
1026 | if (ret) | 1027 | if (ret) |
1027 | xfrm_pol_hold(ret); | 1028 | xfrm_pol_hold(ret); |
1028 | fail: | 1029 | fail: |
1029 | read_unlock_bh(&xfrm_policy_lock); | 1030 | read_unlock_bh(&net->xfrm.xfrm_policy_lock); |
1030 | 1031 | ||
1031 | return ret; | 1032 | return ret; |
1032 | } | 1033 | } |
@@ -1103,8 +1104,9 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, | |||
1103 | const struct flowi *fl) | 1104 | const struct flowi *fl) |
1104 | { | 1105 | { |
1105 | struct xfrm_policy *pol; | 1106 | struct xfrm_policy *pol; |
1107 | struct net *net = sock_net(sk); | ||
1106 | 1108 | ||
1107 | read_lock_bh(&xfrm_policy_lock); | 1109 | read_lock_bh(&net->xfrm.xfrm_policy_lock); |
1108 | if ((pol = sk->sk_policy[dir]) != NULL) { | 1110 | if ((pol = sk->sk_policy[dir]) != NULL) { |
1109 | bool match = xfrm_selector_match(&pol->selector, fl, | 1111 | bool match = xfrm_selector_match(&pol->selector, fl, |
1110 | sk->sk_family); | 1112 | sk->sk_family); |
@@ -1128,7 +1130,7 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, | |||
1128 | pol = NULL; | 1130 | pol = NULL; |
1129 | } | 1131 | } |
1130 | out: | 1132 | out: |
1131 | read_unlock_bh(&xfrm_policy_lock); | 1133 | read_unlock_bh(&net->xfrm.xfrm_policy_lock); |
1132 | return pol; | 1134 | return pol; |
1133 | } | 1135 | } |
1134 | 1136 | ||
@@ -1166,9 +1168,11 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, | |||
1166 | 1168 | ||
1167 | int xfrm_policy_delete(struct xfrm_policy *pol, int dir) | 1169 | int xfrm_policy_delete(struct xfrm_policy *pol, int dir) |
1168 | { | 1170 | { |
1169 | write_lock_bh(&xfrm_policy_lock); | 1171 | struct net *net = xp_net(pol); |
1172 | |||
1173 | write_lock_bh(&net->xfrm.xfrm_policy_lock); | ||
1170 | pol = __xfrm_policy_unlink(pol, dir); | 1174 | pol = __xfrm_policy_unlink(pol, dir); |
1171 | write_unlock_bh(&xfrm_policy_lock); | 1175 | write_unlock_bh(&net->xfrm.xfrm_policy_lock); |
1172 | if (pol) { | 1176 | if (pol) { |
1173 | xfrm_policy_kill(pol); | 1177 | xfrm_policy_kill(pol); |
1174 | return 0; | 1178 | return 0; |
@@ -1187,12 +1191,12 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) | |||
1187 | return -EINVAL; | 1191 | return -EINVAL; |
1188 | #endif | 1192 | #endif |
1189 | 1193 | ||
1190 | write_lock_bh(&xfrm_policy_lock); | 1194 | write_lock_bh(&net->xfrm.xfrm_policy_lock); |
1191 | old_pol = sk->sk_policy[dir]; | 1195 | old_pol = sk->sk_policy[dir]; |
1192 | sk->sk_policy[dir] = pol; | 1196 | sk->sk_policy[dir] = pol; |
1193 | if (pol) { | 1197 | if (pol) { |
1194 | pol->curlft.add_time = get_seconds(); | 1198 | pol->curlft.add_time = get_seconds(); |
1195 | pol->index = xfrm_gen_index(net, XFRM_POLICY_MAX+dir); | 1199 | pol->index = xfrm_gen_index(net, XFRM_POLICY_MAX+dir, 0); |
1196 | __xfrm_policy_link(pol, XFRM_POLICY_MAX+dir); | 1200 | __xfrm_policy_link(pol, XFRM_POLICY_MAX+dir); |
1197 | } | 1201 | } |
1198 | if (old_pol) { | 1202 | if (old_pol) { |
@@ -1204,7 +1208,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) | |||
1204 | */ | 1208 | */ |
1205 | __xfrm_policy_unlink(old_pol, XFRM_POLICY_MAX+dir); | 1209 | __xfrm_policy_unlink(old_pol, XFRM_POLICY_MAX+dir); |
1206 | } | 1210 | } |
1207 | write_unlock_bh(&xfrm_policy_lock); | 1211 | write_unlock_bh(&net->xfrm.xfrm_policy_lock); |
1208 | 1212 | ||
1209 | if (old_pol) { | 1213 | if (old_pol) { |
1210 | xfrm_policy_kill(old_pol); | 1214 | xfrm_policy_kill(old_pol); |
@@ -1215,6 +1219,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) | |||
1215 | static struct xfrm_policy *clone_policy(const struct xfrm_policy *old, int dir) | 1219 | static struct xfrm_policy *clone_policy(const struct xfrm_policy *old, int dir) |
1216 | { | 1220 | { |
1217 | struct xfrm_policy *newp = xfrm_policy_alloc(xp_net(old), GFP_ATOMIC); | 1221 | struct xfrm_policy *newp = xfrm_policy_alloc(xp_net(old), GFP_ATOMIC); |
1222 | struct net *net = xp_net(old); | ||
1218 | 1223 | ||
1219 | if (newp) { | 1224 | if (newp) { |
1220 | newp->selector = old->selector; | 1225 | newp->selector = old->selector; |
@@ -1233,9 +1238,9 @@ static struct xfrm_policy *clone_policy(const struct xfrm_policy *old, int dir) | |||
1233 | newp->type = old->type; | 1238 | newp->type = old->type; |
1234 | memcpy(newp->xfrm_vec, old->xfrm_vec, | 1239 | memcpy(newp->xfrm_vec, old->xfrm_vec, |
1235 | newp->xfrm_nr*sizeof(struct xfrm_tmpl)); | 1240 | newp->xfrm_nr*sizeof(struct xfrm_tmpl)); |
1236 | write_lock_bh(&xfrm_policy_lock); | 1241 | write_lock_bh(&net->xfrm.xfrm_policy_lock); |
1237 | __xfrm_policy_link(newp, XFRM_POLICY_MAX+dir); | 1242 | __xfrm_policy_link(newp, XFRM_POLICY_MAX+dir); |
1238 | write_unlock_bh(&xfrm_policy_lock); | 1243 | write_unlock_bh(&net->xfrm.xfrm_policy_lock); |
1239 | xfrm_pol_put(newp); | 1244 | xfrm_pol_put(newp); |
1240 | } | 1245 | } |
1241 | return newp; | 1246 | return newp; |
@@ -1281,7 +1286,7 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, const struct flowi *fl, | |||
1281 | xfrm_address_t *saddr = xfrm_flowi_saddr(fl, family); | 1286 | xfrm_address_t *saddr = xfrm_flowi_saddr(fl, family); |
1282 | xfrm_address_t tmp; | 1287 | xfrm_address_t tmp; |
1283 | 1288 | ||
1284 | for (nx=0, i = 0; i < policy->xfrm_nr; i++) { | 1289 | for (nx = 0, i = 0; i < policy->xfrm_nr; i++) { |
1285 | struct xfrm_state *x; | 1290 | struct xfrm_state *x; |
1286 | xfrm_address_t *remote = daddr; | 1291 | xfrm_address_t *remote = daddr; |
1287 | xfrm_address_t *local = saddr; | 1292 | xfrm_address_t *local = saddr; |
@@ -1311,9 +1316,9 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, const struct flowi *fl, | |||
1311 | error = (x->km.state == XFRM_STATE_ERROR ? | 1316 | error = (x->km.state == XFRM_STATE_ERROR ? |
1312 | -EINVAL : -EAGAIN); | 1317 | -EINVAL : -EAGAIN); |
1313 | xfrm_state_put(x); | 1318 | xfrm_state_put(x); |
1314 | } | 1319 | } else if (error == -ESRCH) { |
1315 | else if (error == -ESRCH) | ||
1316 | error = -EAGAIN; | 1320 | error = -EAGAIN; |
1321 | } | ||
1317 | 1322 | ||
1318 | if (!tmpl->optional) | 1323 | if (!tmpl->optional) |
1319 | goto fail; | 1324 | goto fail; |
@@ -1321,7 +1326,7 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, const struct flowi *fl, | |||
1321 | return nx; | 1326 | return nx; |
1322 | 1327 | ||
1323 | fail: | 1328 | fail: |
1324 | for (nx--; nx>=0; nx--) | 1329 | for (nx--; nx >= 0; nx--) |
1325 | xfrm_state_put(xfrm[nx]); | 1330 | xfrm_state_put(xfrm[nx]); |
1326 | return error; | 1331 | return error; |
1327 | } | 1332 | } |
@@ -1358,7 +1363,7 @@ xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, const struct flowi *fl, | |||
1358 | return cnx; | 1363 | return cnx; |
1359 | 1364 | ||
1360 | fail: | 1365 | fail: |
1361 | for (cnx--; cnx>=0; cnx--) | 1366 | for (cnx--; cnx >= 0; cnx--) |
1362 | xfrm_state_put(tpp[cnx]); | 1367 | xfrm_state_put(tpp[cnx]); |
1363 | return error; | 1368 | return error; |
1364 | 1369 | ||
@@ -1636,20 +1641,22 @@ free_dst: | |||
1636 | goto out; | 1641 | goto out; |
1637 | } | 1642 | } |
1638 | 1643 | ||
1639 | static int inline | 1644 | #ifdef CONFIG_XFRM_SUB_POLICY |
1640 | xfrm_dst_alloc_copy(void **target, const void *src, int size) | 1645 | static int xfrm_dst_alloc_copy(void **target, const void *src, int size) |
1641 | { | 1646 | { |
1642 | if (!*target) { | 1647 | if (!*target) { |
1643 | *target = kmalloc(size, GFP_ATOMIC); | 1648 | *target = kmalloc(size, GFP_ATOMIC); |
1644 | if (!*target) | 1649 | if (!*target) |
1645 | return -ENOMEM; | 1650 | return -ENOMEM; |
1646 | } | 1651 | } |
1652 | |||
1647 | memcpy(*target, src, size); | 1653 | memcpy(*target, src, size); |
1648 | return 0; | 1654 | return 0; |
1649 | } | 1655 | } |
1656 | #endif | ||
1650 | 1657 | ||
1651 | static int inline | 1658 | static int xfrm_dst_update_parent(struct dst_entry *dst, |
1652 | xfrm_dst_update_parent(struct dst_entry *dst, const struct xfrm_selector *sel) | 1659 | const struct xfrm_selector *sel) |
1653 | { | 1660 | { |
1654 | #ifdef CONFIG_XFRM_SUB_POLICY | 1661 | #ifdef CONFIG_XFRM_SUB_POLICY |
1655 | struct xfrm_dst *xdst = (struct xfrm_dst *)dst; | 1662 | struct xfrm_dst *xdst = (struct xfrm_dst *)dst; |
@@ -1660,8 +1667,8 @@ xfrm_dst_update_parent(struct dst_entry *dst, const struct xfrm_selector *sel) | |||
1660 | #endif | 1667 | #endif |
1661 | } | 1668 | } |
1662 | 1669 | ||
1663 | static int inline | 1670 | static int xfrm_dst_update_origin(struct dst_entry *dst, |
1664 | xfrm_dst_update_origin(struct dst_entry *dst, const struct flowi *fl) | 1671 | const struct flowi *fl) |
1665 | { | 1672 | { |
1666 | #ifdef CONFIG_XFRM_SUB_POLICY | 1673 | #ifdef CONFIG_XFRM_SUB_POLICY |
1667 | struct xfrm_dst *xdst = (struct xfrm_dst *)dst; | 1674 | struct xfrm_dst *xdst = (struct xfrm_dst *)dst; |
@@ -1699,7 +1706,7 @@ static int xfrm_expand_policies(const struct flowi *fl, u16 family, | |||
1699 | xfrm_pols_put(pols, *num_pols); | 1706 | xfrm_pols_put(pols, *num_pols); |
1700 | return PTR_ERR(pols[1]); | 1707 | return PTR_ERR(pols[1]); |
1701 | } | 1708 | } |
1702 | (*num_pols) ++; | 1709 | (*num_pols)++; |
1703 | (*num_xfrms) += pols[1]->xfrm_nr; | 1710 | (*num_xfrms) += pols[1]->xfrm_nr; |
1704 | } | 1711 | } |
1705 | } | 1712 | } |
@@ -1753,7 +1760,7 @@ xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols, | |||
1753 | } | 1760 | } |
1754 | 1761 | ||
1755 | xdst->num_pols = num_pols; | 1762 | xdst->num_pols = num_pols; |
1756 | memcpy(xdst->pols, pols, sizeof(struct xfrm_policy*) * num_pols); | 1763 | memcpy(xdst->pols, pols, sizeof(struct xfrm_policy *) * num_pols); |
1757 | xdst->policy_genid = atomic_read(&pols[0]->genid); | 1764 | xdst->policy_genid = atomic_read(&pols[0]->genid); |
1758 | 1765 | ||
1759 | return xdst; | 1766 | return xdst; |
@@ -1896,8 +1903,7 @@ static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net, | |||
1896 | if (IS_ERR(xdst)) | 1903 | if (IS_ERR(xdst)) |
1897 | return xdst; | 1904 | return xdst; |
1898 | 1905 | ||
1899 | if (net->xfrm.sysctl_larval_drop || num_xfrms <= 0 || | 1906 | if (net->xfrm.sysctl_larval_drop || num_xfrms <= 0) |
1900 | (fl->flowi_flags & FLOWI_FLAG_CAN_SLEEP)) | ||
1901 | return xdst; | 1907 | return xdst; |
1902 | 1908 | ||
1903 | dst1 = &xdst->u.dst; | 1909 | dst1 = &xdst->u.dst; |
@@ -2023,7 +2029,7 @@ make_dummy_bundle: | |||
2023 | } | 2029 | } |
2024 | xdst->num_pols = num_pols; | 2030 | xdst->num_pols = num_pols; |
2025 | xdst->num_xfrms = num_xfrms; | 2031 | xdst->num_xfrms = num_xfrms; |
2026 | memcpy(xdst->pols, pols, sizeof(struct xfrm_policy*) * num_pols); | 2032 | memcpy(xdst->pols, pols, sizeof(struct xfrm_policy *) * num_pols); |
2027 | 2033 | ||
2028 | dst_hold(&xdst->u.dst); | 2034 | dst_hold(&xdst->u.dst); |
2029 | return &xdst->flo; | 2035 | return &xdst->flo; |
@@ -2072,7 +2078,6 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, | |||
2072 | u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT); | 2078 | u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT); |
2073 | int i, err, num_pols, num_xfrms = 0, drop_pols = 0; | 2079 | int i, err, num_pols, num_xfrms = 0, drop_pols = 0; |
2074 | 2080 | ||
2075 | restart: | ||
2076 | dst = NULL; | 2081 | dst = NULL; |
2077 | xdst = NULL; | 2082 | xdst = NULL; |
2078 | route = NULL; | 2083 | route = NULL; |
@@ -2106,10 +2111,10 @@ restart: | |||
2106 | 2111 | ||
2107 | dst_hold(&xdst->u.dst); | 2112 | dst_hold(&xdst->u.dst); |
2108 | 2113 | ||
2109 | spin_lock_bh(&xfrm_policy_sk_bundle_lock); | 2114 | spin_lock_bh(&net->xfrm.xfrm_policy_sk_bundle_lock); |
2110 | xdst->u.dst.next = xfrm_policy_sk_bundles; | 2115 | xdst->u.dst.next = xfrm_policy_sk_bundles; |
2111 | xfrm_policy_sk_bundles = &xdst->u.dst; | 2116 | xfrm_policy_sk_bundles = &xdst->u.dst; |
2112 | spin_unlock_bh(&xfrm_policy_sk_bundle_lock); | 2117 | spin_unlock_bh(&net->xfrm.xfrm_policy_sk_bundle_lock); |
2113 | 2118 | ||
2114 | route = xdst->route; | 2119 | route = xdst->route; |
2115 | } | 2120 | } |
@@ -2133,7 +2138,7 @@ restart: | |||
2133 | 2138 | ||
2134 | num_pols = xdst->num_pols; | 2139 | num_pols = xdst->num_pols; |
2135 | num_xfrms = xdst->num_xfrms; | 2140 | num_xfrms = xdst->num_xfrms; |
2136 | memcpy(pols, xdst->pols, sizeof(struct xfrm_policy*) * num_pols); | 2141 | memcpy(pols, xdst->pols, sizeof(struct xfrm_policy *) * num_pols); |
2137 | route = xdst->route; | 2142 | route = xdst->route; |
2138 | } | 2143 | } |
2139 | 2144 | ||
@@ -2152,23 +2157,8 @@ restart: | |||
2152 | 2157 | ||
2153 | return make_blackhole(net, family, dst_orig); | 2158 | return make_blackhole(net, family, dst_orig); |
2154 | } | 2159 | } |
2155 | if (fl->flowi_flags & FLOWI_FLAG_CAN_SLEEP) { | ||
2156 | DECLARE_WAITQUEUE(wait, current); | ||
2157 | 2160 | ||
2158 | add_wait_queue(&net->xfrm.km_waitq, &wait); | 2161 | err = -EAGAIN; |
2159 | set_current_state(TASK_INTERRUPTIBLE); | ||
2160 | schedule(); | ||
2161 | set_current_state(TASK_RUNNING); | ||
2162 | remove_wait_queue(&net->xfrm.km_waitq, &wait); | ||
2163 | |||
2164 | if (!signal_pending(current)) { | ||
2165 | dst_release(dst); | ||
2166 | goto restart; | ||
2167 | } | ||
2168 | |||
2169 | err = -ERESTART; | ||
2170 | } else | ||
2171 | err = -EAGAIN; | ||
2172 | 2162 | ||
2173 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); | 2163 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); |
2174 | goto error; | 2164 | goto error; |
@@ -2344,7 +2334,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
2344 | if (skb->sp) { | 2334 | if (skb->sp) { |
2345 | int i; | 2335 | int i; |
2346 | 2336 | ||
2347 | for (i=skb->sp->len-1; i>=0; i--) { | 2337 | for (i = skb->sp->len-1; i >= 0; i--) { |
2348 | struct xfrm_state *x = skb->sp->xvec[i]; | 2338 | struct xfrm_state *x = skb->sp->xvec[i]; |
2349 | if (!xfrm_selector_match(&x->sel, &fl, family)) { | 2339 | if (!xfrm_selector_match(&x->sel, &fl, family)) { |
2350 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMISMATCH); | 2340 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMISMATCH); |
@@ -2390,7 +2380,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
2390 | pol->curlft.use_time = get_seconds(); | 2380 | pol->curlft.use_time = get_seconds(); |
2391 | 2381 | ||
2392 | pols[0] = pol; | 2382 | pols[0] = pol; |
2393 | npols ++; | 2383 | npols++; |
2394 | #ifdef CONFIG_XFRM_SUB_POLICY | 2384 | #ifdef CONFIG_XFRM_SUB_POLICY |
2395 | if (pols[0]->type != XFRM_POLICY_TYPE_MAIN) { | 2385 | if (pols[0]->type != XFRM_POLICY_TYPE_MAIN) { |
2396 | pols[1] = xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_MAIN, | 2386 | pols[1] = xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_MAIN, |
@@ -2402,7 +2392,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
2402 | return 0; | 2392 | return 0; |
2403 | } | 2393 | } |
2404 | pols[1]->curlft.use_time = get_seconds(); | 2394 | pols[1]->curlft.use_time = get_seconds(); |
2405 | npols ++; | 2395 | npols++; |
2406 | } | 2396 | } |
2407 | } | 2397 | } |
2408 | #endif | 2398 | #endif |
@@ -2434,7 +2424,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
2434 | } | 2424 | } |
2435 | xfrm_nr = ti; | 2425 | xfrm_nr = ti; |
2436 | if (npols > 1) { | 2426 | if (npols > 1) { |
2437 | xfrm_tmpl_sort(stp, tpp, xfrm_nr, family); | 2427 | xfrm_tmpl_sort(stp, tpp, xfrm_nr, family, net); |
2438 | tpp = stp; | 2428 | tpp = stp; |
2439 | } | 2429 | } |
2440 | 2430 | ||
@@ -2563,10 +2553,10 @@ static void __xfrm_garbage_collect(struct net *net) | |||
2563 | { | 2553 | { |
2564 | struct dst_entry *head, *next; | 2554 | struct dst_entry *head, *next; |
2565 | 2555 | ||
2566 | spin_lock_bh(&xfrm_policy_sk_bundle_lock); | 2556 | spin_lock_bh(&net->xfrm.xfrm_policy_sk_bundle_lock); |
2567 | head = xfrm_policy_sk_bundles; | 2557 | head = xfrm_policy_sk_bundles; |
2568 | xfrm_policy_sk_bundles = NULL; | 2558 | xfrm_policy_sk_bundles = NULL; |
2569 | spin_unlock_bh(&xfrm_policy_sk_bundle_lock); | 2559 | spin_unlock_bh(&net->xfrm.xfrm_policy_sk_bundle_lock); |
2570 | 2560 | ||
2571 | while (head) { | 2561 | while (head) { |
2572 | next = head->next; | 2562 | next = head->next; |
@@ -2950,6 +2940,13 @@ static int __net_init xfrm_net_init(struct net *net) | |||
2950 | rv = xfrm_sysctl_init(net); | 2940 | rv = xfrm_sysctl_init(net); |
2951 | if (rv < 0) | 2941 | if (rv < 0) |
2952 | goto out_sysctl; | 2942 | goto out_sysctl; |
2943 | |||
2944 | /* Initialize the per-net locks here */ | ||
2945 | spin_lock_init(&net->xfrm.xfrm_state_lock); | ||
2946 | rwlock_init(&net->xfrm.xfrm_policy_lock); | ||
2947 | spin_lock_init(&net->xfrm.xfrm_policy_sk_bundle_lock); | ||
2948 | mutex_init(&net->xfrm.xfrm_cfg_mutex); | ||
2949 | |||
2953 | return 0; | 2950 | return 0; |
2954 | 2951 | ||
2955 | out_sysctl: | 2952 | out_sysctl: |
@@ -2992,7 +2989,7 @@ static void xfrm_audit_common_policyinfo(struct xfrm_policy *xp, | |||
2992 | audit_log_format(audit_buf, " sec_alg=%u sec_doi=%u sec_obj=%s", | 2989 | audit_log_format(audit_buf, " sec_alg=%u sec_doi=%u sec_obj=%s", |
2993 | ctx->ctx_alg, ctx->ctx_doi, ctx->ctx_str); | 2990 | ctx->ctx_alg, ctx->ctx_doi, ctx->ctx_str); |
2994 | 2991 | ||
2995 | switch(sel->family) { | 2992 | switch (sel->family) { |
2996 | case AF_INET: | 2993 | case AF_INET: |
2997 | audit_log_format(audit_buf, " src=%pI4", &sel->saddr.a4); | 2994 | audit_log_format(audit_buf, " src=%pI4", &sel->saddr.a4); |
2998 | if (sel->prefixlen_s != 32) | 2995 | if (sel->prefixlen_s != 32) |
@@ -3069,15 +3066,15 @@ static bool xfrm_migrate_selector_match(const struct xfrm_selector *sel_cmp, | |||
3069 | return false; | 3066 | return false; |
3070 | } | 3067 | } |
3071 | 3068 | ||
3072 | static struct xfrm_policy * xfrm_migrate_policy_find(const struct xfrm_selector *sel, | 3069 | static struct xfrm_policy *xfrm_migrate_policy_find(const struct xfrm_selector *sel, |
3073 | u8 dir, u8 type) | 3070 | u8 dir, u8 type, struct net *net) |
3074 | { | 3071 | { |
3075 | struct xfrm_policy *pol, *ret = NULL; | 3072 | struct xfrm_policy *pol, *ret = NULL; |
3076 | struct hlist_head *chain; | 3073 | struct hlist_head *chain; |
3077 | u32 priority = ~0U; | 3074 | u32 priority = ~0U; |
3078 | 3075 | ||
3079 | read_lock_bh(&xfrm_policy_lock); | 3076 | read_lock_bh(&net->xfrm.xfrm_policy_lock); /*FIXME*/ |
3080 | chain = policy_hash_direct(&init_net, &sel->daddr, &sel->saddr, sel->family, dir); | 3077 | chain = policy_hash_direct(net, &sel->daddr, &sel->saddr, sel->family, dir); |
3081 | hlist_for_each_entry(pol, chain, bydst) { | 3078 | hlist_for_each_entry(pol, chain, bydst) { |
3082 | if (xfrm_migrate_selector_match(sel, &pol->selector) && | 3079 | if (xfrm_migrate_selector_match(sel, &pol->selector) && |
3083 | pol->type == type) { | 3080 | pol->type == type) { |
@@ -3086,7 +3083,7 @@ static struct xfrm_policy * xfrm_migrate_policy_find(const struct xfrm_selector | |||
3086 | break; | 3083 | break; |
3087 | } | 3084 | } |
3088 | } | 3085 | } |
3089 | chain = &init_net.xfrm.policy_inexact[dir]; | 3086 | chain = &net->xfrm.policy_inexact[dir]; |
3090 | hlist_for_each_entry(pol, chain, bydst) { | 3087 | hlist_for_each_entry(pol, chain, bydst) { |
3091 | if (xfrm_migrate_selector_match(sel, &pol->selector) && | 3088 | if (xfrm_migrate_selector_match(sel, &pol->selector) && |
3092 | pol->type == type && | 3089 | pol->type == type && |
@@ -3099,7 +3096,7 @@ static struct xfrm_policy * xfrm_migrate_policy_find(const struct xfrm_selector | |||
3099 | if (ret) | 3096 | if (ret) |
3100 | xfrm_pol_hold(ret); | 3097 | xfrm_pol_hold(ret); |
3101 | 3098 | ||
3102 | read_unlock_bh(&xfrm_policy_lock); | 3099 | read_unlock_bh(&net->xfrm.xfrm_policy_lock); |
3103 | 3100 | ||
3104 | return ret; | 3101 | return ret; |
3105 | } | 3102 | } |
@@ -3210,7 +3207,7 @@ static int xfrm_migrate_check(const struct xfrm_migrate *m, int num_migrate) | |||
3210 | 3207 | ||
3211 | int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, | 3208 | int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, |
3212 | struct xfrm_migrate *m, int num_migrate, | 3209 | struct xfrm_migrate *m, int num_migrate, |
3213 | struct xfrm_kmaddress *k) | 3210 | struct xfrm_kmaddress *k, struct net *net) |
3214 | { | 3211 | { |
3215 | int i, err, nx_cur = 0, nx_new = 0; | 3212 | int i, err, nx_cur = 0, nx_new = 0; |
3216 | struct xfrm_policy *pol = NULL; | 3213 | struct xfrm_policy *pol = NULL; |
@@ -3223,14 +3220,14 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, | |||
3223 | goto out; | 3220 | goto out; |
3224 | 3221 | ||
3225 | /* Stage 1 - find policy */ | 3222 | /* Stage 1 - find policy */ |
3226 | if ((pol = xfrm_migrate_policy_find(sel, dir, type)) == NULL) { | 3223 | if ((pol = xfrm_migrate_policy_find(sel, dir, type, net)) == NULL) { |
3227 | err = -ENOENT; | 3224 | err = -ENOENT; |
3228 | goto out; | 3225 | goto out; |
3229 | } | 3226 | } |
3230 | 3227 | ||
3231 | /* Stage 2 - find and update state(s) */ | 3228 | /* Stage 2 - find and update state(s) */ |
3232 | for (i = 0, mp = m; i < num_migrate; i++, mp++) { | 3229 | for (i = 0, mp = m; i < num_migrate; i++, mp++) { |
3233 | if ((x = xfrm_migrate_state_find(mp))) { | 3230 | if ((x = xfrm_migrate_state_find(mp, net))) { |
3234 | x_cur[nx_cur] = x; | 3231 | x_cur[nx_cur] = x; |
3235 | nx_cur++; | 3232 | nx_cur++; |
3236 | if ((xc = xfrm_state_migrate(x, mp))) { | 3233 | if ((xc = xfrm_state_migrate(x, mp))) { |