2005-04-17 02:20:36 +04:00
/*
* 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 <net/ndisc.h>
# include <net/ipv6.h>
# include <net/addrconf.h>
2007-10-15 13:33:45 +04:00
# include <net/inet_frag.h>
2005-04-17 02:20:36 +04:00
2008-01-10 13:53:43 +03:00
static ctl_table ipv6_table_template [ ] = {
2005-04-17 02:20:36 +04:00
{
. procname = " route " ,
. maxlen = 0 ,
. mode = 0555 ,
2008-01-10 13:53:43 +03:00
. child = ipv6_route_table_template
2005-04-17 02:20:36 +04:00
} ,
{
. procname = " icmp " ,
. maxlen = 0 ,
. mode = 0555 ,
2008-01-10 13:53:43 +03:00
. child = ipv6_icmp_table_template
2005-04-17 02:20:36 +04:00
} ,
{
. procname = " bindv6only " ,
2008-01-10 13:54:53 +03:00
. data = & init_net . ipv6 . sysctl . bindv6only ,
2005-04-17 02:20:36 +04:00
. maxlen = sizeof ( int ) ,
. mode = 0644 ,
2008-11-04 05:21:05 +03:00
. proc_handler = proc_dointvec
2005-04-17 02:20:36 +04:00
} ,
2009-11-06 00:32:03 +03:00
{ }
2008-05-20 00:53:30 +04:00
} ;
2009-07-28 13:48:07 +04:00
static ctl_table ipv6_rotable [ ] = {
2005-04-17 02:20:36 +04:00
{
. procname = " mld_max_msf " ,
. data = & sysctl_mld_max_msf ,
. maxlen = sizeof ( int ) ,
. mode = 0644 ,
2008-11-04 05:21:05 +03:00
. proc_handler = proc_dointvec
2005-04-17 02:20:36 +04:00
} ,
2009-11-06 00:32:03 +03:00
{ }
2005-04-17 02:20:36 +04:00
} ;
2008-01-09 11:33:11 +03:00
struct ctl_path net_ipv6_ctl_path [ ] = {
2009-11-06 00:32:03 +03:00
{ . procname = " net " , } ,
{ . procname = " ipv6 " , } ,
2007-12-05 12:44:02 +03:00
{ } ,
2005-04-17 02:20:36 +04:00
} ;
2008-01-09 11:33:11 +03:00
EXPORT_SYMBOL_GPL ( net_ipv6_ctl_path ) ;
2005-04-17 02:20:36 +04:00
2010-01-17 06:35:32 +03:00
static int __net_init ipv6_sysctl_net_init ( struct net * net )
2005-04-17 02:20:36 +04:00
{
2008-01-10 13:53:43 +03:00
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 ;
2008-02-27 18:24:28 +03:00
ipv6_table [ 0 ] . child = ipv6_route_table ;
2008-01-10 13:53:43 +03:00
ipv6_icmp_table = ipv6_icmp_sysctl_init ( net ) ;
if ( ! ipv6_icmp_table )
goto out_ipv6_route_table ;
ipv6_table [ 1 ] . child = ipv6_icmp_table ;
2008-01-10 13:54:53 +03:00
ipv6_table [ 2 ] . data = & net - > ipv6 . sysctl . bindv6only ;
2008-01-10 13:53:43 +03:00
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 ;
2008-01-10 13:47:55 +03:00
2008-01-10 13:53:43 +03:00
out_ipv6_icmp_table :
kfree ( ipv6_icmp_table ) ;
out_ipv6_route_table :
kfree ( ipv6_route_table ) ;
out_ipv6_table :
kfree ( ipv6_table ) ;
goto out ;
2005-04-17 02:20:36 +04:00
}
2010-01-17 06:35:32 +03:00
static void __net_exit ipv6_sysctl_net_exit ( struct net * net )
2008-01-10 13:49:34 +03:00
{
2008-01-10 13:53:43 +03:00
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 ) ;
2008-01-10 13:49:34 +03:00
}
static struct pernet_operations ipv6_sysctl_net_ops = {
. init = ipv6_sysctl_net_init ,
. exit = ipv6_sysctl_net_exit ,
} ;
2008-05-20 00:53:30 +04:00
static struct ctl_table_header * ip6_header ;
2008-01-10 13:49:34 +03:00
int ipv6_sysctl_register ( void )
{
2009-01-08 05:09:08 +03:00
int err = - ENOMEM ;
2008-05-20 00:53:30 +04:00
2009-07-28 13:48:07 +04:00
ip6_header = register_net_sysctl_rotable ( net_ipv6_ctl_path , ipv6_rotable ) ;
2008-05-20 00:53:30 +04:00
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 ;
2008-01-10 13:49:34 +03:00
}
2005-04-17 02:20:36 +04:00
void ipv6_sysctl_unregister ( void )
{
2008-05-20 00:53:30 +04:00
unregister_net_sysctl_table ( ip6_header ) ;
2008-01-10 13:49:34 +03:00
unregister_pernet_subsys ( & ipv6_sysctl_net_ops ) ;
2005-04-17 02:20:36 +04:00
}
2008-07-27 11:59:33 +04:00
static struct ctl_table_header * ip6_base ;
int ipv6_static_sysctl_register ( void )
{
static struct ctl_table empty [ 1 ] ;
2008-08-26 02:18:15 +04:00
ip6_base = register_sysctl_paths ( net_ipv6_ctl_path , empty ) ;
2008-07-27 11:59:33 +04:00
if ( ip6_base = = NULL )
return - ENOMEM ;
return 0 ;
}
void ipv6_static_sysctl_unregister ( void )
{
unregister_net_sysctl_table ( ip6_base ) ;
}