aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorGao feng <gaofeng@cn.fujitsu.com>2013-01-21 17:10:24 -0500
committerPablo Neira Ayuso <pablo@netfilter.org>2013-01-23 06:53:35 -0500
commitf94161c1bbdf7af11729cf106b4452f2432448e0 (patch)
treec1f76b19cf4daf088421e0f75fd0fff6371c4a9c /net/netfilter
parent8a454ab95e5ccbffd04363e9c028f60739bc3fa4 (diff)
netfilter: nf_conntrack: move initialization out of pernet operations
nf_conntrack initialization and cleanup codes happens in pernet operations function. This task should be done in module_init/exit. We can't use init_net to identify if it's the right time to initialize or cleanup since we cannot make assumption on the order netns are created/destroyed. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/nf_conntrack_core.c96
-rw-r--r--net/netfilter/nf_conntrack_standalone.c56
2 files changed, 71 insertions, 81 deletions
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 85aa4b7149c5..fb3e514c461e 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1334,8 +1334,14 @@ static int untrack_refs(void)
1334 return cnt; 1334 return cnt;
1335} 1335}
1336 1336
1337static void nf_conntrack_cleanup_init_net(void) 1337void nf_conntrack_cleanup_start(void)
1338{ 1338{
1339 RCU_INIT_POINTER(ip_ct_attach, NULL);
1340}
1341
1342void nf_conntrack_cleanup_end(void)
1343{
1344 RCU_INIT_POINTER(nf_ct_destroy, NULL);
1339 while (untrack_refs() > 0) 1345 while (untrack_refs() > 0)
1340 schedule(); 1346 schedule();
1341 1347
@@ -1344,8 +1350,18 @@ static void nf_conntrack_cleanup_init_net(void)
1344#endif 1350#endif
1345} 1351}
1346 1352
1347static void nf_conntrack_cleanup_net(struct net *net) 1353/*
1354 * Mishearing the voices in his head, our hero wonders how he's
1355 * supposed to kill the mall.
1356 */
1357void nf_conntrack_cleanup_net(struct net *net)
1348{ 1358{
1359 /*
1360 * This makes sure all current packets have passed through
1361 * netfilter framework. Roll on, two-stage module
1362 * delete...
1363 */
1364 synchronize_net();
1349 i_see_dead_people: 1365 i_see_dead_people:
1350 nf_ct_iterate_cleanup(net, kill_all, NULL); 1366 nf_ct_iterate_cleanup(net, kill_all, NULL);
1351 nf_ct_release_dying_list(net); 1367 nf_ct_release_dying_list(net);
@@ -1355,6 +1371,7 @@ static void nf_conntrack_cleanup_net(struct net *net)
1355 } 1371 }
1356 1372
1357 nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size); 1373 nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size);
1374 nf_conntrack_proto_fini(net);
1358 nf_conntrack_labels_fini(net); 1375 nf_conntrack_labels_fini(net);
1359 nf_conntrack_helper_fini(net); 1376 nf_conntrack_helper_fini(net);
1360 nf_conntrack_timeout_fini(net); 1377 nf_conntrack_timeout_fini(net);
@@ -1367,27 +1384,6 @@ static void nf_conntrack_cleanup_net(struct net *net)
1367 free_percpu(net->ct.stat); 1384 free_percpu(net->ct.stat);
1368} 1385}
1369 1386
1370/* Mishearing the voices in his head, our hero wonders how he's
1371 supposed to kill the mall. */
1372void nf_conntrack_cleanup(struct net *net)
1373{
1374 if (net_eq(net, &init_net))
1375 RCU_INIT_POINTER(ip_ct_attach, NULL);
1376
1377 /* This makes sure all current packets have passed through
1378 netfilter framework. Roll on, two-stage module
1379 delete... */
1380 synchronize_net();
1381 nf_conntrack_proto_fini(net);
1382 nf_conntrack_cleanup_net(net);
1383}
1384
1385void nf_conntrack_cleanup_end(void)
1386{
1387 RCU_INIT_POINTER(nf_ct_destroy, NULL);
1388 nf_conntrack_cleanup_init_net();
1389}
1390
1391void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls) 1387void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls)
1392{ 1388{
1393 struct hlist_nulls_head *hash; 1389 struct hlist_nulls_head *hash;
@@ -1478,7 +1474,7 @@ void nf_ct_untracked_status_or(unsigned long bits)
1478} 1474}
1479EXPORT_SYMBOL_GPL(nf_ct_untracked_status_or); 1475EXPORT_SYMBOL_GPL(nf_ct_untracked_status_or);
1480 1476
1481static int nf_conntrack_init_init_net(void) 1477int nf_conntrack_init_start(void)
1482{ 1478{
1483 int max_factor = 8; 1479 int max_factor = 8;
1484 int ret, cpu; 1480 int ret, cpu;
@@ -1526,6 +1522,16 @@ err_extend:
1526 return ret; 1522 return ret;
1527} 1523}
1528 1524
1525void nf_conntrack_init_end(void)
1526{
1527 /* For use by REJECT target */
1528 RCU_INIT_POINTER(ip_ct_attach, nf_conntrack_attach);
1529 RCU_INIT_POINTER(nf_ct_destroy, destroy_conntrack);
1530
1531 /* Howto get NAT offsets */
1532 RCU_INIT_POINTER(nf_ct_nat_offset, NULL);
1533}
1534
1529/* 1535/*
1530 * We need to use special "null" values, not used in hash table 1536 * We need to use special "null" values, not used in hash table
1531 */ 1537 */
@@ -1533,7 +1539,7 @@ err_extend:
1533#define DYING_NULLS_VAL ((1<<30)+1) 1539#define DYING_NULLS_VAL ((1<<30)+1)
1534#define TEMPLATE_NULLS_VAL ((1<<30)+2) 1540#define TEMPLATE_NULLS_VAL ((1<<30)+2)
1535 1541
1536static int nf_conntrack_init_net(struct net *net) 1542int nf_conntrack_init_net(struct net *net)
1537{ 1543{
1538 int ret; 1544 int ret;
1539 1545
@@ -1592,8 +1598,13 @@ static int nf_conntrack_init_net(struct net *net)
1592 if (ret < 0) 1598 if (ret < 0)
1593 goto err_labels; 1599 goto err_labels;
1594 1600
1601 ret = nf_conntrack_proto_init(net);
1602 if (ret < 0)
1603 goto err_proto;
1595 return 0; 1604 return 0;
1596 1605
1606err_proto:
1607 nf_conntrack_labels_fini(net);
1597err_labels: 1608err_labels:
1598 nf_conntrack_helper_fini(net); 1609 nf_conntrack_helper_fini(net);
1599err_helper: 1610err_helper:
@@ -1622,38 +1633,3 @@ s16 (*nf_ct_nat_offset)(const struct nf_conn *ct,
1622 enum ip_conntrack_dir dir, 1633 enum ip_conntrack_dir dir,
1623 u32 seq); 1634 u32 seq);
1624EXPORT_SYMBOL_GPL(nf_ct_nat_offset); 1635EXPORT_SYMBOL_GPL(nf_ct_nat_offset);
1625
1626int nf_conntrack_init(struct net *net)
1627{
1628 int ret;
1629
1630 if (net_eq(net, &init_net)) {
1631 ret = nf_conntrack_init_init_net();
1632 if (ret < 0)
1633 goto out_init_net;
1634 }
1635 ret = nf_conntrack_proto_init(net);
1636 if (ret < 0)
1637 goto out_proto;
1638 ret = nf_conntrack_init_net(net);
1639 if (ret < 0)
1640 goto out_net;
1641
1642 if (net_eq(net, &init_net)) {
1643 /* For use by REJECT target */
1644 RCU_INIT_POINTER(ip_ct_attach, nf_conntrack_attach);
1645 RCU_INIT_POINTER(nf_ct_destroy, destroy_conntrack);
1646
1647 /* Howto get NAT offsets */
1648 RCU_INIT_POINTER(nf_ct_nat_offset, NULL);
1649 }
1650 return 0;
1651
1652out_net:
1653 nf_conntrack_proto_fini(net);
1654out_proto:
1655 if (net_eq(net, &init_net))
1656 nf_conntrack_cleanup_init_net();
1657out_init_net:
1658 return ret;
1659}
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index e7185c684816..725bf04a2fb9 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -472,13 +472,6 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net)
472{ 472{
473 struct ctl_table *table; 473 struct ctl_table *table;
474 474
475 if (net_eq(net, &init_net)) {
476 nf_ct_netfilter_header =
477 register_net_sysctl(&init_net, "net", nf_ct_netfilter_table);
478 if (!nf_ct_netfilter_header)
479 goto out;
480 }
481
482 table = kmemdup(nf_ct_sysctl_table, sizeof(nf_ct_sysctl_table), 475 table = kmemdup(nf_ct_sysctl_table, sizeof(nf_ct_sysctl_table),
483 GFP_KERNEL); 476 GFP_KERNEL);
484 if (!table) 477 if (!table)
@@ -502,10 +495,6 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net)
502out_unregister_netfilter: 495out_unregister_netfilter:
503 kfree(table); 496 kfree(table);
504out_kmemdup: 497out_kmemdup:
505 if (net_eq(net, &init_net))
506 unregister_net_sysctl_table(nf_ct_netfilter_header);
507out:
508 printk(KERN_ERR "nf_conntrack: can't register to sysctl.\n");
509 return -ENOMEM; 498 return -ENOMEM;
510} 499}
511 500
@@ -513,8 +502,6 @@ static void nf_conntrack_standalone_fini_sysctl(struct net *net)
513{ 502{
514 struct ctl_table *table; 503 struct ctl_table *table;
515 504
516 if (net_eq(net, &init_net))
517 unregister_net_sysctl_table(nf_ct_netfilter_header);
518 table = net->ct.sysctl_header->ctl_table_arg; 505 table = net->ct.sysctl_header->ctl_table_arg;
519 unregister_net_sysctl_table(net->ct.sysctl_header); 506 unregister_net_sysctl_table(net->ct.sysctl_header);
520 kfree(table); 507 kfree(table);
@@ -530,51 +517,78 @@ static void nf_conntrack_standalone_fini_sysctl(struct net *net)
530} 517}
531#endif /* CONFIG_SYSCTL */ 518#endif /* CONFIG_SYSCTL */
532 519
533static int nf_conntrack_net_init(struct net *net) 520static int nf_conntrack_pernet_init(struct net *net)
534{ 521{
535 int ret; 522 int ret;
536 523
537 ret = nf_conntrack_init(net); 524 ret = nf_conntrack_init_net(net);
538 if (ret < 0) 525 if (ret < 0)
539 goto out_init; 526 goto out_init;
527
540 ret = nf_conntrack_standalone_init_proc(net); 528 ret = nf_conntrack_standalone_init_proc(net);
541 if (ret < 0) 529 if (ret < 0)
542 goto out_proc; 530 goto out_proc;
531
543 net->ct.sysctl_checksum = 1; 532 net->ct.sysctl_checksum = 1;
544 net->ct.sysctl_log_invalid = 0; 533 net->ct.sysctl_log_invalid = 0;
545 ret = nf_conntrack_standalone_init_sysctl(net); 534 ret = nf_conntrack_standalone_init_sysctl(net);
546 if (ret < 0) 535 if (ret < 0)
547 goto out_sysctl; 536 goto out_sysctl;
537
548 return 0; 538 return 0;
549 539
550out_sysctl: 540out_sysctl:
551 nf_conntrack_standalone_fini_proc(net); 541 nf_conntrack_standalone_fini_proc(net);
552out_proc: 542out_proc:
553 nf_conntrack_cleanup(net); 543 nf_conntrack_cleanup_net(net);
554out_init: 544out_init:
555 return ret; 545 return ret;
556} 546}
557 547
558static void nf_conntrack_net_exit(struct net *net) 548static void nf_conntrack_pernet_exit(struct net *net)
559{ 549{
560 nf_conntrack_standalone_fini_sysctl(net); 550 nf_conntrack_standalone_fini_sysctl(net);
561 nf_conntrack_standalone_fini_proc(net); 551 nf_conntrack_standalone_fini_proc(net);
562 nf_conntrack_cleanup(net); 552 nf_conntrack_cleanup_net(net);
563} 553}
564 554
565static struct pernet_operations nf_conntrack_net_ops = { 555static struct pernet_operations nf_conntrack_net_ops = {
566 .init = nf_conntrack_net_init, 556 .init = nf_conntrack_pernet_init,
567 .exit = nf_conntrack_net_exit, 557 .exit = nf_conntrack_pernet_exit,
568}; 558};
569 559
570static int __init nf_conntrack_standalone_init(void) 560static int __init nf_conntrack_standalone_init(void)
571{ 561{
572 return register_pernet_subsys(&nf_conntrack_net_ops); 562 int ret = nf_conntrack_init_start();
563 if (ret < 0)
564 goto out_start;
565
566 nf_ct_netfilter_header =
567 register_net_sysctl(&init_net, "net", nf_ct_netfilter_table);
568 if (!nf_ct_netfilter_header)
569 goto out_sysctl;
570
571 ret = register_pernet_subsys(&nf_conntrack_net_ops);
572 if (ret < 0)
573 goto out_pernet;
574
575 nf_conntrack_init_end();
576 return 0;
577
578out_pernet:
579 unregister_net_sysctl_table(nf_ct_netfilter_header);
580out_sysctl:
581 pr_err("nf_conntrack: can't register to sysctl.\n");
582 nf_conntrack_cleanup_end();
583out_start:
584 return ret;
573} 585}
574 586
575static void __exit nf_conntrack_standalone_fini(void) 587static void __exit nf_conntrack_standalone_fini(void)
576{ 588{
589 nf_conntrack_cleanup_start();
577 unregister_pernet_subsys(&nf_conntrack_net_ops); 590 unregister_pernet_subsys(&nf_conntrack_net_ops);
591 unregister_net_sysctl_table(nf_ct_netfilter_header);
578 nf_conntrack_cleanup_end(); 592 nf_conntrack_cleanup_end();
579} 593}
580 594