diff options
author | David S. Miller <davem@davemloft.net> | 2015-12-22 16:26:31 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-12-22 16:26:31 -0500 |
commit | 024f35c55233fb6041e2b31165271f5b941802e6 (patch) | |
tree | 10a167131329e876cb48ad8d4410b96c7d221265 | |
parent | e459dfeeb64008b2d23bdf600f03b3605dbb8152 (diff) | |
parent | a8a572a6b5f2a79280d6e302cb3c1cb1fbaeb3e8 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says:
====================
pull request (net): ipsec 2015-12-22
Just one patch to fix dst_entries_init with multiple namespaces.
From Dan Streetman.
Please pull or let me know if there are problems.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv4/xfrm4_policy.c | 46 | ||||
-rw-r--r-- | net/ipv6/xfrm6_policy.c | 53 | ||||
-rw-r--r-- | net/xfrm/xfrm_policy.c | 38 |
3 files changed, 75 insertions, 62 deletions
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 1e0c3c835a63..7b0edb37a115 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
@@ -259,7 +259,7 @@ static void xfrm4_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
259 | xfrm_dst_ifdown(dst, dev); | 259 | xfrm_dst_ifdown(dst, dev); |
260 | } | 260 | } |
261 | 261 | ||
262 | static struct dst_ops xfrm4_dst_ops = { | 262 | static struct dst_ops xfrm4_dst_ops_template = { |
263 | .family = AF_INET, | 263 | .family = AF_INET, |
264 | .gc = xfrm4_garbage_collect, | 264 | .gc = xfrm4_garbage_collect, |
265 | .update_pmtu = xfrm4_update_pmtu, | 265 | .update_pmtu = xfrm4_update_pmtu, |
@@ -273,7 +273,7 @@ static struct dst_ops xfrm4_dst_ops = { | |||
273 | 273 | ||
274 | static struct xfrm_policy_afinfo xfrm4_policy_afinfo = { | 274 | static struct xfrm_policy_afinfo xfrm4_policy_afinfo = { |
275 | .family = AF_INET, | 275 | .family = AF_INET, |
276 | .dst_ops = &xfrm4_dst_ops, | 276 | .dst_ops = &xfrm4_dst_ops_template, |
277 | .dst_lookup = xfrm4_dst_lookup, | 277 | .dst_lookup = xfrm4_dst_lookup, |
278 | .get_saddr = xfrm4_get_saddr, | 278 | .get_saddr = xfrm4_get_saddr, |
279 | .decode_session = _decode_session4, | 279 | .decode_session = _decode_session4, |
@@ -295,7 +295,7 @@ static struct ctl_table xfrm4_policy_table[] = { | |||
295 | { } | 295 | { } |
296 | }; | 296 | }; |
297 | 297 | ||
298 | static int __net_init xfrm4_net_init(struct net *net) | 298 | static int __net_init xfrm4_net_sysctl_init(struct net *net) |
299 | { | 299 | { |
300 | struct ctl_table *table; | 300 | struct ctl_table *table; |
301 | struct ctl_table_header *hdr; | 301 | struct ctl_table_header *hdr; |
@@ -323,7 +323,7 @@ err_alloc: | |||
323 | return -ENOMEM; | 323 | return -ENOMEM; |
324 | } | 324 | } |
325 | 325 | ||
326 | static void __net_exit xfrm4_net_exit(struct net *net) | 326 | static void __net_exit xfrm4_net_sysctl_exit(struct net *net) |
327 | { | 327 | { |
328 | struct ctl_table *table; | 328 | struct ctl_table *table; |
329 | 329 | ||
@@ -335,12 +335,44 @@ static void __net_exit xfrm4_net_exit(struct net *net) | |||
335 | if (!net_eq(net, &init_net)) | 335 | if (!net_eq(net, &init_net)) |
336 | kfree(table); | 336 | kfree(table); |
337 | } | 337 | } |
338 | #else /* CONFIG_SYSCTL */ | ||
339 | static int inline xfrm4_net_sysctl_init(struct net *net) | ||
340 | { | ||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static void inline xfrm4_net_sysctl_exit(struct net *net) | ||
345 | { | ||
346 | } | ||
347 | #endif | ||
348 | |||
349 | static int __net_init xfrm4_net_init(struct net *net) | ||
350 | { | ||
351 | int ret; | ||
352 | |||
353 | memcpy(&net->xfrm.xfrm4_dst_ops, &xfrm4_dst_ops_template, | ||
354 | sizeof(xfrm4_dst_ops_template)); | ||
355 | ret = dst_entries_init(&net->xfrm.xfrm4_dst_ops); | ||
356 | if (ret) | ||
357 | return ret; | ||
358 | |||
359 | ret = xfrm4_net_sysctl_init(net); | ||
360 | if (ret) | ||
361 | dst_entries_destroy(&net->xfrm.xfrm4_dst_ops); | ||
362 | |||
363 | return ret; | ||
364 | } | ||
365 | |||
366 | static void __net_exit xfrm4_net_exit(struct net *net) | ||
367 | { | ||
368 | xfrm4_net_sysctl_exit(net); | ||
369 | dst_entries_destroy(&net->xfrm.xfrm4_dst_ops); | ||
370 | } | ||
338 | 371 | ||
339 | static struct pernet_operations __net_initdata xfrm4_net_ops = { | 372 | static struct pernet_operations __net_initdata xfrm4_net_ops = { |
340 | .init = xfrm4_net_init, | 373 | .init = xfrm4_net_init, |
341 | .exit = xfrm4_net_exit, | 374 | .exit = xfrm4_net_exit, |
342 | }; | 375 | }; |
343 | #endif | ||
344 | 376 | ||
345 | static void __init xfrm4_policy_init(void) | 377 | static void __init xfrm4_policy_init(void) |
346 | { | 378 | { |
@@ -349,13 +381,9 @@ static void __init xfrm4_policy_init(void) | |||
349 | 381 | ||
350 | void __init xfrm4_init(void) | 382 | void __init xfrm4_init(void) |
351 | { | 383 | { |
352 | dst_entries_init(&xfrm4_dst_ops); | ||
353 | |||
354 | xfrm4_state_init(); | 384 | xfrm4_state_init(); |
355 | xfrm4_policy_init(); | 385 | xfrm4_policy_init(); |
356 | xfrm4_protocol_init(); | 386 | xfrm4_protocol_init(); |
357 | #ifdef CONFIG_SYSCTL | ||
358 | register_pernet_subsys(&xfrm4_net_ops); | 387 | register_pernet_subsys(&xfrm4_net_ops); |
359 | #endif | ||
360 | } | 388 | } |
361 | 389 | ||
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 5643423fe67a..c074771a10f7 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -279,7 +279,7 @@ static void xfrm6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
279 | xfrm_dst_ifdown(dst, dev); | 279 | xfrm_dst_ifdown(dst, dev); |
280 | } | 280 | } |
281 | 281 | ||
282 | static struct dst_ops xfrm6_dst_ops = { | 282 | static struct dst_ops xfrm6_dst_ops_template = { |
283 | .family = AF_INET6, | 283 | .family = AF_INET6, |
284 | .gc = xfrm6_garbage_collect, | 284 | .gc = xfrm6_garbage_collect, |
285 | .update_pmtu = xfrm6_update_pmtu, | 285 | .update_pmtu = xfrm6_update_pmtu, |
@@ -293,7 +293,7 @@ static struct dst_ops xfrm6_dst_ops = { | |||
293 | 293 | ||
294 | static struct xfrm_policy_afinfo xfrm6_policy_afinfo = { | 294 | static struct xfrm_policy_afinfo xfrm6_policy_afinfo = { |
295 | .family = AF_INET6, | 295 | .family = AF_INET6, |
296 | .dst_ops = &xfrm6_dst_ops, | 296 | .dst_ops = &xfrm6_dst_ops_template, |
297 | .dst_lookup = xfrm6_dst_lookup, | 297 | .dst_lookup = xfrm6_dst_lookup, |
298 | .get_saddr = xfrm6_get_saddr, | 298 | .get_saddr = xfrm6_get_saddr, |
299 | .decode_session = _decode_session6, | 299 | .decode_session = _decode_session6, |
@@ -325,7 +325,7 @@ static struct ctl_table xfrm6_policy_table[] = { | |||
325 | { } | 325 | { } |
326 | }; | 326 | }; |
327 | 327 | ||
328 | static int __net_init xfrm6_net_init(struct net *net) | 328 | static int __net_init xfrm6_net_sysctl_init(struct net *net) |
329 | { | 329 | { |
330 | struct ctl_table *table; | 330 | struct ctl_table *table; |
331 | struct ctl_table_header *hdr; | 331 | struct ctl_table_header *hdr; |
@@ -353,7 +353,7 @@ err_alloc: | |||
353 | return -ENOMEM; | 353 | return -ENOMEM; |
354 | } | 354 | } |
355 | 355 | ||
356 | static void __net_exit xfrm6_net_exit(struct net *net) | 356 | static void __net_exit xfrm6_net_sysctl_exit(struct net *net) |
357 | { | 357 | { |
358 | struct ctl_table *table; | 358 | struct ctl_table *table; |
359 | 359 | ||
@@ -365,24 +365,52 @@ static void __net_exit xfrm6_net_exit(struct net *net) | |||
365 | if (!net_eq(net, &init_net)) | 365 | if (!net_eq(net, &init_net)) |
366 | kfree(table); | 366 | kfree(table); |
367 | } | 367 | } |
368 | #else /* CONFIG_SYSCTL */ | ||
369 | static int inline xfrm6_net_sysctl_init(struct net *net) | ||
370 | { | ||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | static void inline xfrm6_net_sysctl_exit(struct net *net) | ||
375 | { | ||
376 | } | ||
377 | #endif | ||
378 | |||
379 | static int __net_init xfrm6_net_init(struct net *net) | ||
380 | { | ||
381 | int ret; | ||
382 | |||
383 | memcpy(&net->xfrm.xfrm6_dst_ops, &xfrm6_dst_ops_template, | ||
384 | sizeof(xfrm6_dst_ops_template)); | ||
385 | ret = dst_entries_init(&net->xfrm.xfrm6_dst_ops); | ||
386 | if (ret) | ||
387 | return ret; | ||
388 | |||
389 | ret = xfrm6_net_sysctl_init(net); | ||
390 | if (ret) | ||
391 | dst_entries_destroy(&net->xfrm.xfrm6_dst_ops); | ||
392 | |||
393 | return ret; | ||
394 | } | ||
395 | |||
396 | static void __net_exit xfrm6_net_exit(struct net *net) | ||
397 | { | ||
398 | xfrm6_net_sysctl_exit(net); | ||
399 | dst_entries_destroy(&net->xfrm.xfrm6_dst_ops); | ||
400 | } | ||
368 | 401 | ||
369 | static struct pernet_operations xfrm6_net_ops = { | 402 | static struct pernet_operations xfrm6_net_ops = { |
370 | .init = xfrm6_net_init, | 403 | .init = xfrm6_net_init, |
371 | .exit = xfrm6_net_exit, | 404 | .exit = xfrm6_net_exit, |
372 | }; | 405 | }; |
373 | #endif | ||
374 | 406 | ||
375 | int __init xfrm6_init(void) | 407 | int __init xfrm6_init(void) |
376 | { | 408 | { |
377 | int ret; | 409 | int ret; |
378 | 410 | ||
379 | dst_entries_init(&xfrm6_dst_ops); | ||
380 | |||
381 | ret = xfrm6_policy_init(); | 411 | ret = xfrm6_policy_init(); |
382 | if (ret) { | 412 | if (ret) |
383 | dst_entries_destroy(&xfrm6_dst_ops); | ||
384 | goto out; | 413 | goto out; |
385 | } | ||
386 | ret = xfrm6_state_init(); | 414 | ret = xfrm6_state_init(); |
387 | if (ret) | 415 | if (ret) |
388 | goto out_policy; | 416 | goto out_policy; |
@@ -391,9 +419,7 @@ int __init xfrm6_init(void) | |||
391 | if (ret) | 419 | if (ret) |
392 | goto out_state; | 420 | goto out_state; |
393 | 421 | ||
394 | #ifdef CONFIG_SYSCTL | ||
395 | register_pernet_subsys(&xfrm6_net_ops); | 422 | register_pernet_subsys(&xfrm6_net_ops); |
396 | #endif | ||
397 | out: | 423 | out: |
398 | return ret; | 424 | return ret; |
399 | out_state: | 425 | out_state: |
@@ -405,11 +431,8 @@ out_policy: | |||
405 | 431 | ||
406 | void xfrm6_fini(void) | 432 | void xfrm6_fini(void) |
407 | { | 433 | { |
408 | #ifdef CONFIG_SYSCTL | ||
409 | unregister_pernet_subsys(&xfrm6_net_ops); | 434 | unregister_pernet_subsys(&xfrm6_net_ops); |
410 | #endif | ||
411 | xfrm6_protocol_fini(); | 435 | xfrm6_protocol_fini(); |
412 | xfrm6_policy_fini(); | 436 | xfrm6_policy_fini(); |
413 | xfrm6_state_fini(); | 437 | xfrm6_state_fini(); |
414 | dst_entries_destroy(&xfrm6_dst_ops); | ||
415 | } | 438 | } |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 948fa5560de5..b5e665b3cfb0 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -2826,7 +2826,6 @@ static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst, | |||
2826 | 2826 | ||
2827 | int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) | 2827 | int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) |
2828 | { | 2828 | { |
2829 | struct net *net; | ||
2830 | int err = 0; | 2829 | int err = 0; |
2831 | if (unlikely(afinfo == NULL)) | 2830 | if (unlikely(afinfo == NULL)) |
2832 | return -EINVAL; | 2831 | return -EINVAL; |
@@ -2857,26 +2856,6 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) | |||
2857 | } | 2856 | } |
2858 | spin_unlock(&xfrm_policy_afinfo_lock); | 2857 | spin_unlock(&xfrm_policy_afinfo_lock); |
2859 | 2858 | ||
2860 | rtnl_lock(); | ||
2861 | for_each_net(net) { | ||
2862 | struct dst_ops *xfrm_dst_ops; | ||
2863 | |||
2864 | switch (afinfo->family) { | ||
2865 | case AF_INET: | ||
2866 | xfrm_dst_ops = &net->xfrm.xfrm4_dst_ops; | ||
2867 | break; | ||
2868 | #if IS_ENABLED(CONFIG_IPV6) | ||
2869 | case AF_INET6: | ||
2870 | xfrm_dst_ops = &net->xfrm.xfrm6_dst_ops; | ||
2871 | break; | ||
2872 | #endif | ||
2873 | default: | ||
2874 | BUG(); | ||
2875 | } | ||
2876 | *xfrm_dst_ops = *afinfo->dst_ops; | ||
2877 | } | ||
2878 | rtnl_unlock(); | ||
2879 | |||
2880 | return err; | 2859 | return err; |
2881 | } | 2860 | } |
2882 | EXPORT_SYMBOL(xfrm_policy_register_afinfo); | 2861 | EXPORT_SYMBOL(xfrm_policy_register_afinfo); |
@@ -2912,22 +2891,6 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo) | |||
2912 | } | 2891 | } |
2913 | EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); | 2892 | EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); |
2914 | 2893 | ||
2915 | static void __net_init xfrm_dst_ops_init(struct net *net) | ||
2916 | { | ||
2917 | struct xfrm_policy_afinfo *afinfo; | ||
2918 | |||
2919 | rcu_read_lock(); | ||
2920 | afinfo = rcu_dereference(xfrm_policy_afinfo[AF_INET]); | ||
2921 | if (afinfo) | ||
2922 | net->xfrm.xfrm4_dst_ops = *afinfo->dst_ops; | ||
2923 | #if IS_ENABLED(CONFIG_IPV6) | ||
2924 | afinfo = rcu_dereference(xfrm_policy_afinfo[AF_INET6]); | ||
2925 | if (afinfo) | ||
2926 | net->xfrm.xfrm6_dst_ops = *afinfo->dst_ops; | ||
2927 | #endif | ||
2928 | rcu_read_unlock(); | ||
2929 | } | ||
2930 | |||
2931 | static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr) | 2894 | static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr) |
2932 | { | 2895 | { |
2933 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | 2896 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
@@ -3076,7 +3039,6 @@ static int __net_init xfrm_net_init(struct net *net) | |||
3076 | rv = xfrm_policy_init(net); | 3039 | rv = xfrm_policy_init(net); |
3077 | if (rv < 0) | 3040 | if (rv < 0) |
3078 | goto out_policy; | 3041 | goto out_policy; |
3079 | xfrm_dst_ops_init(net); | ||
3080 | rv = xfrm_sysctl_init(net); | 3042 | rv = xfrm_sysctl_init(net); |
3081 | if (rv < 0) | 3043 | if (rv < 0) |
3082 | goto out_sysctl; | 3044 | goto out_sysctl; |