aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-12-22 16:26:31 -0500
committerDavid S. Miller <davem@davemloft.net>2015-12-22 16:26:31 -0500
commit024f35c55233fb6041e2b31165271f5b941802e6 (patch)
tree10a167131329e876cb48ad8d4410b96c7d221265
parente459dfeeb64008b2d23bdf600f03b3605dbb8152 (diff)
parenta8a572a6b5f2a79280d6e302cb3c1cb1fbaeb3e8 (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.c46
-rw-r--r--net/ipv6/xfrm6_policy.c53
-rw-r--r--net/xfrm/xfrm_policy.c38
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
262static struct dst_ops xfrm4_dst_ops = { 262static 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
274static struct xfrm_policy_afinfo xfrm4_policy_afinfo = { 274static 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
298static int __net_init xfrm4_net_init(struct net *net) 298static 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
326static void __net_exit xfrm4_net_exit(struct net *net) 326static 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 */
339static int inline xfrm4_net_sysctl_init(struct net *net)
340{
341 return 0;
342}
343
344static void inline xfrm4_net_sysctl_exit(struct net *net)
345{
346}
347#endif
348
349static 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
366static 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
339static struct pernet_operations __net_initdata xfrm4_net_ops = { 372static 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
345static void __init xfrm4_policy_init(void) 377static void __init xfrm4_policy_init(void)
346{ 378{
@@ -349,13 +381,9 @@ static void __init xfrm4_policy_init(void)
349 381
350void __init xfrm4_init(void) 382void __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
282static struct dst_ops xfrm6_dst_ops = { 282static 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
294static struct xfrm_policy_afinfo xfrm6_policy_afinfo = { 294static 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
328static int __net_init xfrm6_net_init(struct net *net) 328static 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
356static void __net_exit xfrm6_net_exit(struct net *net) 356static 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 */
369static int inline xfrm6_net_sysctl_init(struct net *net)
370{
371 return 0;
372}
373
374static void inline xfrm6_net_sysctl_exit(struct net *net)
375{
376}
377#endif
378
379static 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
396static 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
369static struct pernet_operations xfrm6_net_ops = { 402static 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
375int __init xfrm6_init(void) 407int __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
397out: 423out:
398 return ret; 424 return ret;
399out_state: 425out_state:
@@ -405,11 +431,8 @@ out_policy:
405 431
406void xfrm6_fini(void) 432void 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
2827int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) 2827int 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}
2882EXPORT_SYMBOL(xfrm_policy_register_afinfo); 2861EXPORT_SYMBOL(xfrm_policy_register_afinfo);
@@ -2912,22 +2891,6 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo)
2912} 2891}
2913EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); 2892EXPORT_SYMBOL(xfrm_policy_unregister_afinfo);
2914 2893
2915static 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
2931static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr) 2894static 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;