Skip to content

Commit

Permalink
[NETNS][IPV6]: Make multiple instance of sysctl tables.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Daniel Lezcano authored and David S. Miller committed Jan 28, 2008
1 parent 89918fc commit 760f2d0
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 14 deletions.
4 changes: 2 additions & 2 deletions include/net/ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
9 changes: 9 additions & 0 deletions include/net/netns/ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
12 changes: 11 additions & 1 deletion net/ipv6/icmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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

11 changes: 10 additions & 1 deletion net/ipv6/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down
67 changes: 57 additions & 10 deletions net/ipv6/sysctl_net_ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 = {
Expand Down

0 comments on commit 760f2d0

Please sign in to comment.