diff options
Diffstat (limited to 'net/xfrm')
| -rw-r--r-- | net/xfrm/xfrm_policy.c | 75 | ||||
| -rw-r--r-- | net/xfrm/xfrm_state.c | 6 | ||||
| -rw-r--r-- | net/xfrm/xfrm_user.c | 14 |
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 | ||
| 472 | void xfrm_spd_getinfo(struct xfrmk_spdinfo *si) | 472 | void 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 | ||
| 1312 | static inline struct xfrm_dst *xfrm_alloc_dst(int family) | 1312 | static 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 | ||
| 2280 | int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) | 2294 | int 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 | } |
| 2307 | EXPORT_SYMBOL(xfrm_policy_register_afinfo); | 2343 | EXPORT_SYMBOL(xfrm_policy_register_afinfo); |
| @@ -2332,6 +2368,22 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo) | |||
| 2332 | } | 2368 | } |
| 2333 | EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); | 2369 | EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); |
| 2334 | 2370 | ||
| 2371 | static 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 | |||
| 2335 | static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family) | 2387 | static 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 | } |
| 642 | EXPORT_SYMBOL(xfrm_state_flush); | 642 | EXPORT_SYMBOL(xfrm_state_flush); |
| 643 | 643 | ||
| 644 | void xfrm_sad_getinfo(struct xfrmk_sadinfo *si) | 644 | void 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 | ||
| 784 | static int build_spdinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags) | 784 | static 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 | ||
| 844 | static int build_sadinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags) | 845 | static 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); |
