aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm')
-rw-r--r--net/xfrm/xfrm_policy.c75
-rw-r--r--net/xfrm/xfrm_state.c6
-rw-r--r--net/xfrm/xfrm_user.c14
3 files changed, 75 insertions, 20 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 4725a549ad4d..0ecb16a9a883 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -469,16 +469,16 @@ static inline int xfrm_byidx_should_resize(struct net *net, int total)
469 return 0; 469 return 0;
470} 470}
471 471
472void xfrm_spd_getinfo(struct xfrmk_spdinfo *si) 472void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si)
473{ 473{
474 read_lock_bh(&xfrm_policy_lock); 474 read_lock_bh(&xfrm_policy_lock);
475 si->incnt = init_net.xfrm.policy_count[XFRM_POLICY_IN]; 475 si->incnt = net->xfrm.policy_count[XFRM_POLICY_IN];
476 si->outcnt = init_net.xfrm.policy_count[XFRM_POLICY_OUT]; 476 si->outcnt = net->xfrm.policy_count[XFRM_POLICY_OUT];
477 si->fwdcnt = init_net.xfrm.policy_count[XFRM_POLICY_FWD]; 477 si->fwdcnt = net->xfrm.policy_count[XFRM_POLICY_FWD];
478 si->inscnt = init_net.xfrm.policy_count[XFRM_POLICY_IN+XFRM_POLICY_MAX]; 478 si->inscnt = net->xfrm.policy_count[XFRM_POLICY_IN+XFRM_POLICY_MAX];
479 si->outscnt = init_net.xfrm.policy_count[XFRM_POLICY_OUT+XFRM_POLICY_MAX]; 479 si->outscnt = net->xfrm.policy_count[XFRM_POLICY_OUT+XFRM_POLICY_MAX];
480 si->fwdscnt = init_net.xfrm.policy_count[XFRM_POLICY_FWD+XFRM_POLICY_MAX]; 480 si->fwdscnt = net->xfrm.policy_count[XFRM_POLICY_FWD+XFRM_POLICY_MAX];
481 si->spdhcnt = init_net.xfrm.policy_idx_hmask; 481 si->spdhcnt = net->xfrm.policy_idx_hmask;
482 si->spdhmcnt = xfrm_policy_hashmax; 482 si->spdhmcnt = xfrm_policy_hashmax;
483 read_unlock_bh(&xfrm_policy_lock); 483 read_unlock_bh(&xfrm_policy_lock);
484} 484}
@@ -1309,15 +1309,28 @@ static inline int xfrm_get_tos(struct flowi *fl, int family)
1309 return tos; 1309 return tos;
1310} 1310}
1311 1311
1312static inline struct xfrm_dst *xfrm_alloc_dst(int family) 1312static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family)
1313{ 1313{
1314 struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); 1314 struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
1315 struct dst_ops *dst_ops;
1315 struct xfrm_dst *xdst; 1316 struct xfrm_dst *xdst;
1316 1317
1317 if (!afinfo) 1318 if (!afinfo)
1318 return ERR_PTR(-EINVAL); 1319 return ERR_PTR(-EINVAL);
1319 1320
1320 xdst = dst_alloc(afinfo->dst_ops) ?: ERR_PTR(-ENOBUFS); 1321 switch (family) {
1322 case AF_INET:
1323 dst_ops = &net->xfrm.xfrm4_dst_ops;
1324 break;
1325#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
1326 case AF_INET6:
1327 dst_ops = &net->xfrm.xfrm6_dst_ops;
1328 break;
1329#endif
1330 default:
1331 BUG();
1332 }
1333 xdst = dst_alloc(dst_ops) ?: ERR_PTR(-ENOBUFS);
1321 1334
1322 xfrm_policy_put_afinfo(afinfo); 1335 xfrm_policy_put_afinfo(afinfo);
1323 1336
@@ -1366,6 +1379,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
1366 struct flowi *fl, 1379 struct flowi *fl,
1367 struct dst_entry *dst) 1380 struct dst_entry *dst)
1368{ 1381{
1382 struct net *net = xp_net(policy);
1369 unsigned long now = jiffies; 1383 unsigned long now = jiffies;
1370 struct net_device *dev; 1384 struct net_device *dev;
1371 struct dst_entry *dst_prev = NULL; 1385 struct dst_entry *dst_prev = NULL;
@@ -1389,7 +1403,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
1389 dst_hold(dst); 1403 dst_hold(dst);
1390 1404
1391 for (; i < nx; i++) { 1405 for (; i < nx; i++) {
1392 struct xfrm_dst *xdst = xfrm_alloc_dst(family); 1406 struct xfrm_dst *xdst = xfrm_alloc_dst(net, family);
1393 struct dst_entry *dst1 = &xdst->u.dst; 1407 struct dst_entry *dst1 = &xdst->u.dst;
1394 1408
1395 err = PTR_ERR(xdst); 1409 err = PTR_ERR(xdst);
@@ -2279,6 +2293,7 @@ EXPORT_SYMBOL(xfrm_bundle_ok);
2279 2293
2280int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) 2294int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
2281{ 2295{
2296 struct net *net;
2282 int err = 0; 2297 int err = 0;
2283 if (unlikely(afinfo == NULL)) 2298 if (unlikely(afinfo == NULL))
2284 return -EINVAL; 2299 return -EINVAL;
@@ -2302,6 +2317,27 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
2302 xfrm_policy_afinfo[afinfo->family] = afinfo; 2317 xfrm_policy_afinfo[afinfo->family] = afinfo;
2303 } 2318 }
2304 write_unlock_bh(&xfrm_policy_afinfo_lock); 2319 write_unlock_bh(&xfrm_policy_afinfo_lock);
2320
2321 rtnl_lock();
2322 for_each_net(net) {
2323 struct dst_ops *xfrm_dst_ops;
2324
2325 switch (afinfo->family) {
2326 case AF_INET:
2327 xfrm_dst_ops = &net->xfrm.xfrm4_dst_ops;
2328 break;
2329#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
2330 case AF_INET6:
2331 xfrm_dst_ops = &net->xfrm.xfrm6_dst_ops;
2332 break;
2333#endif
2334 default:
2335 BUG();
2336 }
2337 *xfrm_dst_ops = *afinfo->dst_ops;
2338 }
2339 rtnl_unlock();
2340
2305 return err; 2341 return err;
2306} 2342}
2307EXPORT_SYMBOL(xfrm_policy_register_afinfo); 2343EXPORT_SYMBOL(xfrm_policy_register_afinfo);
@@ -2332,6 +2368,22 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo)
2332} 2368}
2333EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); 2369EXPORT_SYMBOL(xfrm_policy_unregister_afinfo);
2334 2370
2371static void __net_init xfrm_dst_ops_init(struct net *net)
2372{
2373 struct xfrm_policy_afinfo *afinfo;
2374
2375 read_lock_bh(&xfrm_policy_afinfo_lock);
2376 afinfo = xfrm_policy_afinfo[AF_INET];
2377 if (afinfo)
2378 net->xfrm.xfrm4_dst_ops = *afinfo->dst_ops;
2379#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
2380 afinfo = xfrm_policy_afinfo[AF_INET6];
2381 if (afinfo)
2382 net->xfrm.xfrm6_dst_ops = *afinfo->dst_ops;
2383#endif
2384 read_unlock_bh(&xfrm_policy_afinfo_lock);
2385}
2386
2335static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family) 2387static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family)
2336{ 2388{
2337 struct xfrm_policy_afinfo *afinfo; 2389 struct xfrm_policy_afinfo *afinfo;
@@ -2494,6 +2546,7 @@ static int __net_init xfrm_net_init(struct net *net)
2494 rv = xfrm_policy_init(net); 2546 rv = xfrm_policy_init(net);
2495 if (rv < 0) 2547 if (rv < 0)
2496 goto out_policy; 2548 goto out_policy;
2549 xfrm_dst_ops_init(net);
2497 rv = xfrm_sysctl_init(net); 2550 rv = xfrm_sysctl_init(net);
2498 if (rv < 0) 2551 if (rv < 0)
2499 goto out_sysctl; 2552 goto out_sysctl;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index d847f1a52b44..b36cc344474b 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -641,11 +641,11 @@ out:
641} 641}
642EXPORT_SYMBOL(xfrm_state_flush); 642EXPORT_SYMBOL(xfrm_state_flush);
643 643
644void xfrm_sad_getinfo(struct xfrmk_sadinfo *si) 644void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si)
645{ 645{
646 spin_lock_bh(&xfrm_state_lock); 646 spin_lock_bh(&xfrm_state_lock);
647 si->sadcnt = init_net.xfrm.state_num; 647 si->sadcnt = net->xfrm.state_num;
648 si->sadhcnt = init_net.xfrm.state_hmask; 648 si->sadhcnt = net->xfrm.state_hmask;
649 si->sadhmcnt = xfrm_state_hashmax; 649 si->sadhmcnt = xfrm_state_hashmax;
650 spin_unlock_bh(&xfrm_state_lock); 650 spin_unlock_bh(&xfrm_state_lock);
651} 651}
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 1ada6186933c..d5a712976004 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -781,7 +781,8 @@ static inline size_t xfrm_spdinfo_msgsize(void)
781 + nla_total_size(sizeof(struct xfrmu_spdhinfo)); 781 + nla_total_size(sizeof(struct xfrmu_spdhinfo));
782} 782}
783 783
784static int build_spdinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags) 784static int build_spdinfo(struct sk_buff *skb, struct net *net,
785 u32 pid, u32 seq, u32 flags)
785{ 786{
786 struct xfrmk_spdinfo si; 787 struct xfrmk_spdinfo si;
787 struct xfrmu_spdinfo spc; 788 struct xfrmu_spdinfo spc;
@@ -795,7 +796,7 @@ static int build_spdinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags)
795 796
796 f = nlmsg_data(nlh); 797 f = nlmsg_data(nlh);
797 *f = flags; 798 *f = flags;
798 xfrm_spd_getinfo(&si); 799 xfrm_spd_getinfo(net, &si);
799 spc.incnt = si.incnt; 800 spc.incnt = si.incnt;
800 spc.outcnt = si.outcnt; 801 spc.outcnt = si.outcnt;
801 spc.fwdcnt = si.fwdcnt; 802 spc.fwdcnt = si.fwdcnt;
@@ -828,7 +829,7 @@ static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
828 if (r_skb == NULL) 829 if (r_skb == NULL)
829 return -ENOMEM; 830 return -ENOMEM;
830 831
831 if (build_spdinfo(r_skb, spid, seq, *flags) < 0) 832 if (build_spdinfo(r_skb, net, spid, seq, *flags) < 0)
832 BUG(); 833 BUG();
833 834
834 return nlmsg_unicast(net->xfrm.nlsk, r_skb, spid); 835 return nlmsg_unicast(net->xfrm.nlsk, r_skb, spid);
@@ -841,7 +842,8 @@ static inline size_t xfrm_sadinfo_msgsize(void)
841 + nla_total_size(4); /* XFRMA_SAD_CNT */ 842 + nla_total_size(4); /* XFRMA_SAD_CNT */
842} 843}
843 844
844static int build_sadinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags) 845static int build_sadinfo(struct sk_buff *skb, struct net *net,
846 u32 pid, u32 seq, u32 flags)
845{ 847{
846 struct xfrmk_sadinfo si; 848 struct xfrmk_sadinfo si;
847 struct xfrmu_sadhinfo sh; 849 struct xfrmu_sadhinfo sh;
@@ -854,7 +856,7 @@ static int build_sadinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags)
854 856
855 f = nlmsg_data(nlh); 857 f = nlmsg_data(nlh);
856 *f = flags; 858 *f = flags;
857 xfrm_sad_getinfo(&si); 859 xfrm_sad_getinfo(net, &si);
858 860
859 sh.sadhmcnt = si.sadhmcnt; 861 sh.sadhmcnt = si.sadhmcnt;
860 sh.sadhcnt = si.sadhcnt; 862 sh.sadhcnt = si.sadhcnt;
@@ -882,7 +884,7 @@ static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
882 if (r_skb == NULL) 884 if (r_skb == NULL)
883 return -ENOMEM; 885 return -ENOMEM;
884 886
885 if (build_sadinfo(r_skb, spid, seq, *flags) < 0) 887 if (build_sadinfo(r_skb, net, spid, seq, *flags) < 0)
886 BUG(); 888 BUG();
887 889
888 return nlmsg_unicast(net->xfrm.nlsk, r_skb, spid); 890 return nlmsg_unicast(net->xfrm.nlsk, r_skb, spid);