mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-28 20:37:27 +00:00
4344475797
register_sysctl_rotable never caught on as an interesting way to register sysctls. My take on the situation is that what we want are sysctls that we can only see in the initial network namespace. What we have implemented with register_sysctl_rotable are sysctls that we can see in all of the network namespaces and can only change in the initial network namespace. That is a very silly way to go. Just register the network sysctls in the initial network namespace and we don't have any weird special cases to deal with. The sysctls affected are: /proc/sys/net/ipv4/ipfrag_secret_interval /proc/sys/net/ipv4/ipfrag_max_dist /proc/sys/net/ipv6/ip6frag_secret_interval /proc/sys/net/ipv6/mld_max_msf I really don't expect anyone will miss them if they can't read them in a child user namespace. CC: Pavel Emelyanov <xemul@openvz.org> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Acked-by: Pavel Emelyanov <xemul@parallels.com> Signed-off-by: David S. Miller <davem@davemloft.net>
178 lines
3.5 KiB
C
178 lines
3.5 KiB
C
/*
|
|
* sysctl_net_ipv6.c: sysctl interface to net IPV6 subsystem.
|
|
*
|
|
* Changes:
|
|
* YOSHIFUJI Hideaki @USAGI: added icmp sysctl table.
|
|
*/
|
|
|
|
#include <linux/mm.h>
|
|
#include <linux/sysctl.h>
|
|
#include <linux/in6.h>
|
|
#include <linux/ipv6.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/export.h>
|
|
#include <net/ndisc.h>
|
|
#include <net/ipv6.h>
|
|
#include <net/addrconf.h>
|
|
#include <net/inet_frag.h>
|
|
|
|
static struct ctl_table empty[1];
|
|
|
|
static ctl_table ipv6_static_skeleton[] = {
|
|
{
|
|
.procname = "neigh",
|
|
.maxlen = 0,
|
|
.mode = 0555,
|
|
.child = empty,
|
|
},
|
|
{ }
|
|
};
|
|
|
|
static ctl_table ipv6_table_template[] = {
|
|
{
|
|
.procname = "route",
|
|
.maxlen = 0,
|
|
.mode = 0555,
|
|
.child = ipv6_route_table_template
|
|
},
|
|
{
|
|
.procname = "icmp",
|
|
.maxlen = 0,
|
|
.mode = 0555,
|
|
.child = ipv6_icmp_table_template
|
|
},
|
|
{
|
|
.procname = "bindv6only",
|
|
.data = &init_net.ipv6.sysctl.bindv6only,
|
|
.maxlen = sizeof(int),
|
|
.mode = 0644,
|
|
.proc_handler = proc_dointvec
|
|
},
|
|
{ }
|
|
};
|
|
|
|
static ctl_table ipv6_rotable[] = {
|
|
{
|
|
.procname = "mld_max_msf",
|
|
.data = &sysctl_mld_max_msf,
|
|
.maxlen = sizeof(int),
|
|
.mode = 0644,
|
|
.proc_handler = proc_dointvec
|
|
},
|
|
{ }
|
|
};
|
|
|
|
struct ctl_path net_ipv6_ctl_path[] = {
|
|
{ .procname = "net", },
|
|
{ .procname = "ipv6", },
|
|
{ },
|
|
};
|
|
EXPORT_SYMBOL_GPL(net_ipv6_ctl_path);
|
|
|
|
static int __net_init ipv6_sysctl_net_init(struct net *net)
|
|
{
|
|
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_table[0].child = ipv6_route_table;
|
|
|
|
ipv6_icmp_table = ipv6_icmp_sysctl_init(net);
|
|
if (!ipv6_icmp_table)
|
|
goto out_ipv6_route_table;
|
|
ipv6_table[1].child = ipv6_icmp_table;
|
|
|
|
ipv6_table[2].data = &net->ipv6.sysctl.bindv6only;
|
|
|
|
net->ipv6.sysctl.table = register_net_sysctl_table(net, net_ipv6_ctl_path,
|
|
ipv6_table);
|
|
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 __net_exit ipv6_sysctl_net_exit(struct net *net)
|
|
{
|
|
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 = {
|
|
.init = ipv6_sysctl_net_init,
|
|
.exit = ipv6_sysctl_net_exit,
|
|
};
|
|
|
|
static struct ctl_table_header *ip6_header;
|
|
|
|
int ipv6_sysctl_register(void)
|
|
{
|
|
int err = -ENOMEM;
|
|
|
|
ip6_header = register_net_sysctl(&init_net, "net/ipv6", 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)
|
|
{
|
|
ip6_base = register_sysctl_paths(net_ipv6_ctl_path, ipv6_static_skeleton);
|
|
if (ip6_base == NULL)
|
|
return -ENOMEM;
|
|
return 0;
|
|
}
|
|
|
|
void ipv6_static_sysctl_unregister(void)
|
|
{
|
|
unregister_net_sysctl_table(ip6_base);
|
|
}
|