2008-09-23 07:08:39 +04:00
/*
* File : sysctl . c
*
* Phonet / proc / sys / net / phonet interface implementation
*
* Copyright ( C ) 2008 Nokia Corporation .
*
2012-06-14 02:29:03 +04:00
* Author : Rémi Denis - Courmont
2008-09-23 07:08:39 +04:00
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA
* 02110 - 1301 USA
*/
# include <linux/seqlock.h>
# include <linux/sysctl.h>
# include <linux/errno.h>
# include <linux/init.h>
2012-04-12 07:39:17 +04:00
# include <net/sock.h>
# include <linux/phonet.h>
# include <net/phonet/phonet.h>
2008-09-23 07:08:39 +04:00
# define DYNAMIC_PORT_MIN 0x40
# define DYNAMIC_PORT_MAX 0x7f
static DEFINE_SEQLOCK ( local_port_range_lock ) ;
static int local_port_range_min [ 2 ] = { 0 , 0 } ;
static int local_port_range_max [ 2 ] = { 1023 , 1023 } ;
static int local_port_range [ 2 ] = { DYNAMIC_PORT_MIN , DYNAMIC_PORT_MAX } ;
static struct ctl_table_header * phonet_table_hrd ;
static void set_local_port_range ( int range [ 2 ] )
{
write_seqlock ( & local_port_range_lock ) ;
local_port_range [ 0 ] = range [ 0 ] ;
local_port_range [ 1 ] = range [ 1 ] ;
write_sequnlock ( & local_port_range_lock ) ;
}
void phonet_get_local_port_range ( int * min , int * max )
{
2012-04-15 09:58:06 +04:00
unsigned int seq ;
2008-09-23 07:08:39 +04:00
do {
seq = read_seqbegin ( & local_port_range_lock ) ;
if ( min )
* min = local_port_range [ 0 ] ;
if ( max )
* max = local_port_range [ 1 ] ;
} while ( read_seqretry ( & local_port_range_lock , seq ) ) ;
}
2009-09-24 02:57:19 +04:00
static int proc_local_port_range ( ctl_table * table , int write ,
2008-09-23 07:08:39 +04:00
void __user * buffer ,
size_t * lenp , loff_t * ppos )
{
int ret ;
int range [ 2 ] = { local_port_range [ 0 ] , local_port_range [ 1 ] } ;
ctl_table tmp = {
. data = & range ,
. maxlen = sizeof ( range ) ,
. mode = table - > mode ,
. extra1 = & local_port_range_min ,
. extra2 = & local_port_range_max ,
} ;
2009-09-24 02:57:19 +04:00
ret = proc_dointvec_minmax ( & tmp , write , buffer , lenp , ppos ) ;
2008-09-23 07:08:39 +04:00
if ( write & & ret = = 0 ) {
if ( range [ 1 ] < range [ 0 ] )
ret = - EINVAL ;
else
set_local_port_range ( range ) ;
}
return ret ;
}
static struct ctl_table phonet_table [ ] = {
{
. procname = " local_port_range " ,
. data = & local_port_range ,
. maxlen = sizeof ( local_port_range ) ,
. mode = 0644 ,
2008-11-04 05:21:05 +03:00
. proc_handler = proc_local_port_range ,
2008-09-23 07:08:39 +04:00
} ,
2009-11-06 00:32:03 +03:00
{ }
2008-09-23 07:08:39 +04:00
} ;
int __init phonet_sysctl_init ( void )
{
2012-04-19 17:44:49 +04:00
phonet_table_hrd = register_net_sysctl ( & init_net , " net/phonet " , phonet_table ) ;
2008-09-23 07:08:39 +04:00
return phonet_table_hrd = = NULL ? - ENOMEM : 0 ;
}
void phonet_sysctl_exit ( void )
{
2012-04-19 17:24:33 +04:00
unregister_net_sysctl_table ( phonet_table_hrd ) ;
2008-09-23 07:08:39 +04:00
}