[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 <dlezcano@fr.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Daniel Lezcano 2008-01-10 02:53:43 -08:00 committed by David S. Miller
parent 89918fc270
commit 760f2d0186
5 changed files with 89 additions and 14 deletions

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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 = {