2019-05-29 16:57:50 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2008-09-22 20:08:39 -07:00
/*
* File : sysctl . c
*
* Phonet / proc / sys / net / phonet interface implementation
*
* Copyright ( C ) 2008 Nokia Corporation .
*
2012-06-13 22:29:03 +00:00
* Author : Rémi Denis - Courmont
2008-09-22 20:08:39 -07:00
*/
# include <linux/seqlock.h>
# include <linux/sysctl.h>
# include <linux/errno.h>
# include <linux/init.h>
2012-04-12 03:39:17 +00:00
# include <net/sock.h>
# include <linux/phonet.h>
# include <net/phonet/phonet.h>
2008-09-22 20:08:39 -07: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 05:58:06 +00:00
unsigned int seq ;
2008-09-22 20:08:39 -07: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 ) ) ;
}
2013-06-11 23:04:25 -07:00
static int proc_local_port_range ( struct ctl_table * table , int write ,
2020-04-24 08:43:38 +02:00
void * buffer , size_t * lenp , loff_t * ppos )
2008-09-22 20:08:39 -07:00
{
int ret ;
int range [ 2 ] = { local_port_range [ 0 ] , local_port_range [ 1 ] } ;
2013-06-11 23:04:25 -07:00
struct ctl_table tmp = {
2008-09-22 20:08:39 -07:00
. data = & range ,
. maxlen = sizeof ( range ) ,
. mode = table - > mode ,
. extra1 = & local_port_range_min ,
. extra2 = & local_port_range_max ,
} ;
2009-09-23 15:57:19 -07:00
ret = proc_dointvec_minmax ( & tmp , write , buffer , lenp , ppos ) ;
2008-09-22 20:08:39 -07: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-03 18:21:05 -08:00
. proc_handler = proc_local_port_range ,
2008-09-22 20:08:39 -07:00
} ,
2009-11-05 13:32:03 -08:00
{ }
2008-09-22 20:08:39 -07:00
} ;
int __init phonet_sysctl_init ( void )
{
2012-04-19 13:44:49 +00:00
phonet_table_hrd = register_net_sysctl ( & init_net , " net/phonet " , phonet_table ) ;
2008-09-22 20:08:39 -07:00
return phonet_table_hrd = = NULL ? - ENOMEM : 0 ;
}
void phonet_sysctl_exit ( void )
{
2012-04-19 13:24:33 +00:00
unregister_net_sysctl_table ( phonet_table_hrd ) ;
2008-09-22 20:08:39 -07:00
}