Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=760f2d0186225f06d46e07232d65219c5055cad3
Commit:     760f2d0186225f06d46e07232d65219c5055cad3
Parent:     89918fc270bb77cb1a0703f0ea566a692b32e324
Author:     Daniel Lezcano <[EMAIL PROTECTED]>
AuthorDate: Thu Jan 10 02:53:43 2008 -0800
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Mon Jan 28 15:01:17 2008 -0800

    [NETNS][IPV6]: Make multiple instance of sysctl tables.
    
    Each network namespace wants its own set of sysctl value, eg. we
    should not be able from a namespace to set a sysctl value for another
    namespace , especially for the initial network namespace.
    
    This patch duplicates the sysctl table when we register a new network
    namespace for ipv6. The duplicated table are postfixed with the
    "template" word to notify the developper the table is cloned.
    
    Signed-off-by: Daniel Lezcano <[EMAIL PROTECTED]>
    Signed-off-by: David S. Miller <[EMAIL PROTECTED]>
---
 include/net/ipv6.h         |    4 +-
 include/net/netns/ipv6.h   |    9 ++++++
 net/ipv6/icmp.c            |   12 +++++++-
 net/ipv6/route.c           |   11 ++++++-
 net/ipv6/sysctl_net_ipv6.c |   67 +++++++++++++++++++++++++++++++++++++------
 5 files changed, 89 insertions(+), 14 deletions(-)

diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 3e086f8..5519035 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -619,8 +619,8 @@ static inline int snmp6_unregister_dev(struct inet6_dev 
*idev)
 #endif
 
 #ifdef CONFIG_SYSCTL
-extern ctl_table ipv6_route_table[];
-extern ctl_table ipv6_icmp_table[];
+extern ctl_table ipv6_route_table_template[];
+extern ctl_table ipv6_icmp_table_template[];
 
 extern int ipv6_sysctl_register(void);
 extern void ipv6_sysctl_unregister(void);
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index 6f82046..58fbf30 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -5,6 +5,15 @@
 #ifndef __NETNS_IPV6_H__
 #define __NETNS_IPV6_H__
 
+struct ctl_table_header;
+
+struct netns_sysctl_ipv6 {
+#ifdef CONFIG_SYSCTL
+       struct ctl_table_header *table;
+#endif
+};
+
 struct netns_ipv6 {
+       struct netns_sysctl_ipv6 sysctl;
 };
 #endif
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index c3bbd86..dfe3b37 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -907,7 +907,7 @@ int icmpv6_err_convert(int type, int code, int *err)
 EXPORT_SYMBOL(icmpv6_err_convert);
 
 #ifdef CONFIG_SYSCTL
-ctl_table ipv6_icmp_table[] = {
+ctl_table ipv6_icmp_table_template[] = {
        {
                .ctl_name       = NET_IPV6_ICMP_RATELIMIT,
                .procname       = "ratelimit",
@@ -918,5 +918,15 @@ ctl_table ipv6_icmp_table[] = {
        },
        { .ctl_name = 0 },
 };
+
+struct ctl_table *ipv6_icmp_sysctl_init(struct net *net)
+{
+       struct ctl_table *table;
+
+       table = kmemdup(ipv6_icmp_table_template,
+                       sizeof(ipv6_icmp_table_template),
+                       GFP_KERNEL);
+       return table;
+}
 #endif
 
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index b80ef57..0c7382f 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2409,7 +2409,7 @@ int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, 
struct file * filp,
                return -EINVAL;
 }
 
-ctl_table ipv6_route_table[] = {
+ctl_table ipv6_route_table_template[] = {
        {
                .procname       =       "flush",
                .data           =       &flush_delay,
@@ -2499,6 +2499,15 @@ ctl_table ipv6_route_table[] = {
        { .ctl_name = 0 }
 };
 
+struct ctl_table *ipv6_route_sysctl_init(struct net *net)
+{
+       struct ctl_table *table;
+
+       table = kmemdup(ipv6_route_table_template,
+                       sizeof(ipv6_route_table_template),
+                       GFP_KERNEL);
+       return table;
+}
 #endif
 
 int __init ip6_route_init(void)
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index 7329dec..7970f33 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -14,20 +14,23 @@
 #include <net/addrconf.h>
 #include <net/inet_frag.h>
 
-static ctl_table ipv6_table[] = {
+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
+               .child          = ipv6_route_table_template
        },
        {
                .ctl_name       = NET_IPV6_ICMP,
                .procname       = "icmp",
                .maxlen         = 0,
                .mode           = 0555,
-               .child          = ipv6_icmp_table
+               .child          = ipv6_icmp_table_template
        },
        {
                .ctl_name       = NET_IPV6_BINDV6ONLY,
@@ -89,22 +92,66 @@ struct ctl_path net_ipv6_ctl_path[] = {
 };
 EXPORT_SYMBOL_GPL(net_ipv6_ctl_path);
 
-static struct ctl_table_header *ipv6_sysctl_header;
-
 static int ipv6_sysctl_net_init(struct net *net)
 {
-       ipv6_sysctl_header = register_net_sysctl_table(net, net_ipv6_ctl_path,
-                                                      ipv6_table);
-       if (!ipv6_sysctl_header)
+       struct ctl_table *ipv6_table;
+       struct ctl_table *ipv6_route_table;
+       struct ctl_table *ipv6_icmp_table;
+       int err;
+
+       err = -ENOMEM;
+       ipv6_table = kmemdup(ipv6_table_template, sizeof(ipv6_table_template),
+                            GFP_KERNEL);
+       if (!ipv6_table)
+               goto out;
+
+       ipv6_route_table = ipv6_route_sysctl_init(net);
+       if (!ipv6_route_table)
+               goto out_ipv6_table;
+
+       ipv6_icmp_table = ipv6_icmp_sysctl_init(net);
+       if (!ipv6_icmp_table)
+               goto out_ipv6_route_table;
+
+       ipv6_table[0].child = ipv6_route_table;
+       ipv6_table[1].child = ipv6_icmp_table;
+
+       net->ipv6.sysctl.table = register_net_sysctl_table(net, 
net_ipv6_ctl_path,
+                                                          ipv6_table);
+       if (!net->ipv6.sysctl.table)
                return -ENOMEM;
 
-       return 0;
+       if (!net->ipv6.sysctl.table)
+               goto out_ipv6_icmp_table;
+
+       err = 0;
+out:
+       return err;
 
+out_ipv6_icmp_table:
+       kfree(ipv6_icmp_table);
+out_ipv6_route_table:
+       kfree(ipv6_route_table);
+out_ipv6_table:
+       kfree(ipv6_table);
+       goto out;
 }
 
 static void ipv6_sysctl_net_exit(struct net *net)
 {
-       unregister_net_sysctl_table(ipv6_sysctl_header);
+       struct ctl_table *ipv6_table;
+       struct ctl_table *ipv6_route_table;
+       struct ctl_table *ipv6_icmp_table;
+
+       ipv6_table = net->ipv6.sysctl.table->ctl_table_arg;
+       ipv6_route_table = ipv6_table[0].child;
+       ipv6_icmp_table = ipv6_table[1].child;
+
+       unregister_net_sysctl_table(net->ipv6.sysctl.table);
+
+       kfree(ipv6_table);
+       kfree(ipv6_route_table);
+       kfree(ipv6_icmp_table);
 }
 
 static struct pernet_operations ipv6_sysctl_net_ops = {
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to