Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 760f2d01 authored by Daniel Lezcano's avatar Daniel Lezcano Committed by David S. Miller
Browse files

[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: default avatarDaniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 89918fc2
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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);
+9 −0
Original line number Diff line number Diff line
@@ -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
+11 −1
Original line number Diff line number Diff line
@@ -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
+10 −1
Original line number Diff line number Diff line
@@ -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)
+57 −10
Original line number Diff line number Diff line
@@ -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,
	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 (!ipv6_sysctl_header)
	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 = {