net: spread __net_init, __net_exit
[linux-3.10.git] / net / ipv6 / sysctl_net_ipv6.c
index b4ba422..f841d93 100644 (file)
 #include <net/addrconf.h>
 #include <net/inet_frag.h>
 
-extern struct ctl_table *ipv6_route_sysctl_init(struct net *net);
-extern struct ctl_table *ipv6_icmp_sysctl_init(struct net *net);
-
 static ctl_table ipv6_table_template[] = {
        {
-               .ctl_name       = NET_IPV6_ROUTE,
                .procname       = "route",
                .maxlen         = 0,
                .mode           = 0555,
                .child          = ipv6_route_table_template
        },
        {
-               .ctl_name       = NET_IPV6_ICMP,
                .procname       = "icmp",
                .maxlen         = 0,
                .mode           = 0555,
                .child          = ipv6_icmp_table_template
        },
        {
-               .ctl_name       = NET_IPV6_BINDV6ONLY,
                .procname       = "bindv6only",
                .data           = &init_net.ipv6.sysctl.bindv6only,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = &proc_dointvec
-       },
-       {
-               .ctl_name       = NET_IPV6_IP6FRAG_HIGH_THRESH,
-               .procname       = "ip6frag_high_thresh",
-               .data           = &init_net.ipv6.sysctl.frags.high_thresh,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec
-       },
-       {
-               .ctl_name       = NET_IPV6_IP6FRAG_LOW_THRESH,
-               .procname       = "ip6frag_low_thresh",
-               .data           = &init_net.ipv6.sysctl.frags.low_thresh,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec
-       },
-       {
-               .ctl_name       = NET_IPV6_IP6FRAG_TIME,
-               .procname       = "ip6frag_time",
-               .data           = &init_net.ipv6.sysctl.frags.timeout,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec_jiffies,
-               .strategy       = &sysctl_jiffies,
-       },
-       {
-               .ctl_name       = NET_IPV6_IP6FRAG_SECRET_INTERVAL,
-               .procname       = "ip6frag_secret_interval",
-               .data           = &init_net.ipv6.sysctl.frags.secret_interval,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec_jiffies,
-               .strategy       = &sysctl_jiffies
+               .proc_handler   = proc_dointvec
        },
+       { }
+};
+
+static ctl_table ipv6_rotable[] = {
        {
-               .ctl_name       = NET_IPV6_MLD_MAX_MSF,
                .procname       = "mld_max_msf",
                .data           = &sysctl_mld_max_msf,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = &proc_dointvec
+               .proc_handler   = proc_dointvec
        },
-       { .ctl_name = 0 }
+       { }
 };
 
 struct ctl_path net_ipv6_ctl_path[] = {
-       { .procname = "net", .ctl_name = CTL_NET, },
-       { .procname = "ipv6", .ctl_name = NET_IPV6, },
+       { .procname = "net", },
+       { .procname = "ipv6", },
        { },
 };
 EXPORT_SYMBOL_GPL(net_ipv6_ctl_path);
 
-static int ipv6_sysctl_net_init(struct net *net)
+static int __net_init ipv6_sysctl_net_init(struct net *net)
 {
        struct ctl_table *ipv6_table;
        struct ctl_table *ipv6_route_table;
@@ -108,43 +71,18 @@ static int ipv6_sysctl_net_init(struct net *net)
        ipv6_route_table = ipv6_route_sysctl_init(net);
        if (!ipv6_route_table)
                goto out_ipv6_table;
+       ipv6_table[0].child = ipv6_route_table;
 
        ipv6_icmp_table = ipv6_icmp_sysctl_init(net);
        if (!ipv6_icmp_table)
                goto out_ipv6_route_table;
-
-       ipv6_route_table[0].data = &net->ipv6.sysctl.flush_delay;
-       /* ipv6_route_table[1].data will be handled when we have
-          routes per namespace */
-       ipv6_route_table[2].data = &net->ipv6.sysctl.ip6_rt_max_size;
-       ipv6_route_table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval;
-       ipv6_route_table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout;
-       ipv6_route_table[5].data = &net->ipv6.sysctl.ip6_rt_gc_interval;
-       ipv6_route_table[6].data = &net->ipv6.sysctl.ip6_rt_gc_elasticity;
-       ipv6_route_table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires;
-       ipv6_route_table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss;
-       ipv6_table[0].child = ipv6_route_table;
-
        ipv6_table[1].child = ipv6_icmp_table;
 
        ipv6_table[2].data = &net->ipv6.sysctl.bindv6only;
-       ipv6_table[3].data = &net->ipv6.sysctl.frags.high_thresh;
-       ipv6_table[4].data = &net->ipv6.sysctl.frags.low_thresh;
-       ipv6_table[5].data = &net->ipv6.sysctl.frags.timeout;
-       ipv6_table[6].data = &net->ipv6.sysctl.frags.secret_interval;
-
-       /* We don't want this value to be per namespace, it should be global
-          to all namespaces, so make it read-only when we are not in the
-          init network namespace */
-       if (net != &init_net)
-               ipv6_table[7].mode = 0444;
 
        net->ipv6.sysctl.table = register_net_sysctl_table(net, net_ipv6_ctl_path,
                                                           ipv6_table);
        if (!net->ipv6.sysctl.table)
-               return -ENOMEM;
-
-       if (!net->ipv6.sysctl.table)
                goto out_ipv6_icmp_table;
 
        err = 0;
@@ -160,7 +98,7 @@ out_ipv6_table:
        goto out;
 }
 
-static void ipv6_sysctl_net_exit(struct net *net)
+static void __net_exit ipv6_sysctl_net_exit(struct net *net)
 {
        struct ctl_table *ipv6_table;
        struct ctl_table *ipv6_route_table;
@@ -182,12 +120,45 @@ static struct pernet_operations ipv6_sysctl_net_ops = {
        .exit = ipv6_sysctl_net_exit,
 };
 
+static struct ctl_table_header *ip6_header;
+
 int ipv6_sysctl_register(void)
 {
-       return register_pernet_subsys(&ipv6_sysctl_net_ops);
+       int err = -ENOMEM;
+
+       ip6_header = register_net_sysctl_rotable(net_ipv6_ctl_path, ipv6_rotable);
+       if (ip6_header == NULL)
+               goto out;
+
+       err = register_pernet_subsys(&ipv6_sysctl_net_ops);
+       if (err)
+               goto err_pernet;
+out:
+       return err;
+
+err_pernet:
+       unregister_net_sysctl_table(ip6_header);
+       goto out;
 }
 
 void ipv6_sysctl_unregister(void)
 {
+       unregister_net_sysctl_table(ip6_header);
        unregister_pernet_subsys(&ipv6_sysctl_net_ops);
 }
+
+static struct ctl_table_header *ip6_base;
+
+int ipv6_static_sysctl_register(void)
+{
+       static struct ctl_table empty[1];
+       ip6_base = register_sysctl_paths(net_ipv6_ctl_path, empty);
+       if (ip6_base == NULL)
+               return -ENOMEM;
+       return 0;
+}
+
+void ipv6_static_sysctl_unregister(void)
+{
+       unregister_net_sysctl_table(ip6_base);
+}