2008-01-11 17:57:09 +03:00
/* SCTP kernel implementation
2005-04-17 02:20:36 +04:00
* ( C ) Copyright IBM Corp . 2002 , 2004
* Copyright ( c ) 2002 Intel Corp .
*
2008-01-11 17:57:09 +03:00
* This file is part of the SCTP kernel implementation
2005-04-17 02:20:36 +04:00
*
* Sysctl related interfaces for SCTP .
*
2008-01-11 17:57:09 +03:00
* This SCTP implementation is free software ;
2005-04-17 02:20:36 +04:00
* you can redistribute it and / or modify it under the terms of
* the GNU General Public License as published by
* the Free Software Foundation ; either version 2 , or ( at your option )
* any later version .
*
2008-01-11 17:57:09 +03:00
* This SCTP implementation is distributed in the hope that it
2005-04-17 02:20:36 +04:00
* 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
2013-12-06 18:28:48 +04:00
* along with GNU CC ; see the file COPYING . If not , see
* < http : //www.gnu.org/licenses/>.
2005-04-17 02:20:36 +04:00
*
* Please send any bug reports or fixes you make to the
* email address ( es ) :
2013-07-23 16:51:47 +04:00
* lksctp developers < linux - sctp @ vger . kernel . org >
2005-04-17 02:20:36 +04:00
*
* Written or modified by :
* Mingqin Liu < liuming @ us . ibm . com >
* Jon Grimm < jgrimm @ us . ibm . com >
* Ardelle Fan < ardelle . fan @ intel . com >
* Ryan Layer < rmlayer @ us . ibm . com >
* Sridhar Samudrala < sri @ us . ibm . com >
*/
# include <net/sctp/structs.h>
2005-09-06 05:07:42 +04:00
# include <net/sctp/sctp.h>
2005-04-17 02:20:36 +04:00
# include <linux/sysctl.h>
2006-08-23 00:29:17 +04:00
static int zero = 0 ;
static int one = 1 ;
static int timer_max = 86400000 ; /* ms in one day */
static int int_max = INT_MAX ;
2009-05-13 02:03:20 +04:00
static int sack_timer_min = 1 ;
static int sack_timer_max = 500 ;
2009-09-03 15:55:47 +04:00
static int addr_scope_max = 3 ; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */
2009-11-23 23:53:57 +03:00
static int rwnd_scale_max = 16 ;
2011-12-16 16:44:15 +04:00
static unsigned long max_autoclose_min = 0 ;
static unsigned long max_autoclose_max =
( MAX_SCHEDULE_TIMEOUT / HZ > UINT_MAX )
? UINT_MAX : MAX_SCHEDULE_TIMEOUT / HZ ;
2005-04-17 02:20:36 +04:00
2010-11-10 02:24:26 +03:00
extern long sysctl_sctp_mem [ 3 ] ;
2007-09-17 03:04:37 +04:00
extern int sysctl_sctp_rmem [ 3 ] ;
extern int sysctl_sctp_wmem [ 3 ] ;
2007-08-16 03:07:44 +04:00
2013-12-11 05:50:40 +04:00
static int proc_sctp_do_hmac_alg ( struct ctl_table * ctl , int write ,
2012-10-24 13:20:03 +04:00
void __user * buffer , size_t * lenp ,
loff_t * ppos ) ;
2013-12-11 05:50:39 +04:00
static int proc_sctp_do_rto_min ( struct ctl_table * ctl , int write ,
void __user * buffer , size_t * lenp ,
loff_t * ppos ) ;
static int proc_sctp_do_rto_max ( struct ctl_table * ctl , int write ,
2012-10-24 13:20:03 +04:00
void __user * buffer , size_t * lenp ,
loff_t * ppos ) ;
2013-12-11 05:50:39 +04:00
2013-06-12 10:04:25 +04:00
static struct ctl_table sctp_table [ ] = {
2012-08-07 11:29:57 +04:00
{
. procname = " sctp_mem " ,
. data = & sysctl_sctp_mem ,
. maxlen = sizeof ( sysctl_sctp_mem ) ,
. mode = 0644 ,
. proc_handler = proc_doulongvec_minmax
} ,
{
. procname = " sctp_rmem " ,
. data = & sysctl_sctp_rmem ,
. maxlen = sizeof ( sysctl_sctp_rmem ) ,
. mode = 0644 ,
. proc_handler = proc_dointvec ,
} ,
{
. procname = " sctp_wmem " ,
. data = & sysctl_sctp_wmem ,
. maxlen = sizeof ( sysctl_sctp_wmem ) ,
. mode = 0644 ,
. proc_handler = proc_dointvec ,
} ,
{ /* sentinel */ }
} ;
2013-06-12 10:04:25 +04:00
static struct ctl_table sctp_net_table [ ] = {
2005-04-17 02:20:36 +04:00
{
. procname = " rto_initial " ,
2012-08-07 11:29:57 +04:00
. data = & init_net . sctp . rto_initial ,
2006-08-23 00:29:17 +04:00
. maxlen = sizeof ( unsigned int ) ,
2005-04-17 02:20:36 +04:00
. mode = 0644 ,
2008-11-04 05:21:05 +03:00
. proc_handler = proc_dointvec_minmax ,
2006-08-23 00:29:17 +04:00
. extra1 = & one ,
. extra2 = & timer_max
2005-04-17 02:20:36 +04:00
} ,
{
. procname = " rto_min " ,
2012-08-07 11:29:57 +04:00
. data = & init_net . sctp . rto_min ,
2006-08-23 00:29:17 +04:00
. maxlen = sizeof ( unsigned int ) ,
2005-04-17 02:20:36 +04:00
. mode = 0644 ,
2013-12-11 05:50:39 +04:00
. proc_handler = proc_sctp_do_rto_min ,
2006-08-23 00:29:17 +04:00
. extra1 = & one ,
2013-12-11 05:50:39 +04:00
. extra2 = & init_net . sctp . rto_max
2005-04-17 02:20:36 +04:00
} ,
{
. procname = " rto_max " ,
2012-08-07 11:29:57 +04:00
. data = & init_net . sctp . rto_max ,
2006-08-23 00:29:17 +04:00
. maxlen = sizeof ( unsigned int ) ,
2005-04-17 02:20:36 +04:00
. mode = 0644 ,
2013-12-11 05:50:39 +04:00
. proc_handler = proc_sctp_do_rto_max ,
. extra1 = & init_net . sctp . rto_min ,
2006-08-23 00:29:17 +04:00
. extra2 = & timer_max
2005-04-17 02:20:36 +04:00
} ,
{
2012-08-07 11:29:57 +04:00
. procname = " rto_alpha_exp_divisor " ,
. data = & init_net . sctp . rto_alpha ,
. maxlen = sizeof ( int ) ,
. mode = 0444 ,
. proc_handler = proc_dointvec ,
} ,
{
. procname = " rto_beta_exp_divisor " ,
. data = & init_net . sctp . rto_beta ,
. maxlen = sizeof ( int ) ,
. mode = 0444 ,
. proc_handler = proc_dointvec ,
2005-04-17 02:20:36 +04:00
} ,
{
. procname = " max_burst " ,
2012-08-07 11:29:57 +04:00
. data = & init_net . sctp . max_burst ,
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_minmax ,
2006-08-23 00:29:17 +04:00
. extra1 = & zero ,
. extra2 = & int_max
2005-04-17 02:20:36 +04:00
} ,
{
2012-08-07 11:29:57 +04:00
. procname = " cookie_preserve_enable " ,
. data = & init_net . sctp . cookie_preserve_enable ,
2005-04-17 02:20:36 +04:00
. maxlen = sizeof ( int ) ,
. mode = 0644 ,
2012-08-07 11:29:57 +04:00
. proc_handler = proc_dointvec ,
} ,
2012-10-24 13:20:03 +04:00
{
. procname = " cookie_hmac_alg " ,
. maxlen = 8 ,
. mode = 0644 ,
. proc_handler = proc_sctp_do_hmac_alg ,
} ,
2012-08-07 11:29:57 +04:00
{
. procname = " valid_cookie_life " ,
. data = & init_net . sctp . valid_cookie_life ,
. maxlen = sizeof ( unsigned int ) ,
. mode = 0644 ,
2008-11-04 05:21:05 +03:00
. proc_handler = proc_dointvec_minmax ,
2012-08-07 11:29:57 +04:00
. extra1 = & one ,
. extra2 = & timer_max
2005-04-17 02:20:36 +04:00
} ,
2005-04-28 23:02:04 +04:00
{
2012-08-07 11:29:57 +04:00
. procname = " sack_timeout " ,
. data = & init_net . sctp . sack_timeout ,
2005-04-28 23:02:04 +04:00
. maxlen = sizeof ( int ) ,
. mode = 0644 ,
2012-08-07 11:29:57 +04:00
. proc_handler = proc_dointvec_minmax ,
. extra1 = & sack_timer_min ,
. extra2 = & sack_timer_max ,
2005-04-28 23:02:04 +04:00
} ,
2005-11-12 03:08:24 +03:00
{
2012-08-07 11:29:57 +04:00
. procname = " hb_interval " ,
. data = & init_net . sctp . hb_interval ,
. maxlen = sizeof ( unsigned int ) ,
2005-11-12 03:08:24 +03:00
. mode = 0644 ,
2012-08-07 11:29:57 +04:00
. proc_handler = proc_dointvec_minmax ,
. extra1 = & one ,
. extra2 = & timer_max
2005-11-12 03:08:24 +03:00
} ,
2005-04-17 02:20:36 +04:00
{
2012-08-07 11:29:57 +04:00
. procname = " association_max_retrans " ,
. data = & init_net . sctp . max_retrans_association ,
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_minmax ,
2006-08-23 00:29:17 +04:00
. extra1 = & one ,
. extra2 = & int_max
2005-04-17 02:20:36 +04:00
} ,
2012-07-21 11:56:07 +04:00
{
2012-08-07 11:29:57 +04:00
. procname = " path_max_retrans " ,
. data = & init_net . sctp . max_retrans_path ,
2012-07-21 11:56:07 +04:00
. maxlen = sizeof ( int ) ,
. mode = 0644 ,
. proc_handler = proc_dointvec_minmax ,
2012-08-07 11:29:57 +04:00
. extra1 = & one ,
2012-07-21 11:56:07 +04:00
. extra2 = & int_max
} ,
2005-04-17 02:20:36 +04:00
{
. procname = " max_init_retransmits " ,
2012-08-07 11:29:57 +04:00
. data = & init_net . sctp . max_retrans_init ,
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_minmax ,
2006-08-23 00:29:17 +04:00
. extra1 = & one ,
. extra2 = & int_max
2005-04-17 02:20:36 +04:00
} ,
{
2012-08-07 11:29:57 +04:00
. procname = " pf_retrans " ,
. data = & init_net . sctp . pf_retrans ,
. maxlen = sizeof ( int ) ,
2005-04-17 02:20:36 +04:00
. mode = 0644 ,
2008-11-04 05:21:05 +03:00
. proc_handler = proc_dointvec_minmax ,
2012-08-07 11:29:57 +04:00
. extra1 = & zero ,
. extra2 = & int_max
2005-04-17 02:20:36 +04:00
} ,
{
2012-08-07 11:29:57 +04:00
. procname = " sndbuf_policy " ,
. data = & init_net . sctp . sndbuf_policy ,
2006-01-17 22:55:17 +03:00
. maxlen = sizeof ( int ) ,
2005-04-17 02:20:36 +04:00
. mode = 0644 ,
2008-11-04 05:21:05 +03:00
. proc_handler = proc_dointvec ,
2005-04-17 02:20:36 +04:00
} ,
{
2012-08-07 11:29:57 +04:00
. procname = " rcvbuf_policy " ,
. data = & init_net . sctp . rcvbuf_policy ,
2011-04-26 12:36:05 +04:00
. maxlen = sizeof ( int ) ,
. mode = 0644 ,
. proc_handler = proc_dointvec ,
} ,
{
. procname = " default_auto_asconf " ,
2012-08-07 11:29:57 +04:00
. data = & init_net . sctp . default_auto_asconf ,
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
} ,
{
2012-08-07 11:29:57 +04:00
. procname = " addip_enable " ,
. data = & init_net . sctp . addip_enable ,
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
} ,
2005-06-29 00:24:23 +04:00
{
2012-08-07 11:29:57 +04:00
. procname = " addip_noauth_enable " ,
. data = & init_net . sctp . addip_noauth ,
2009-05-13 02:03:20 +04:00
. maxlen = sizeof ( int ) ,
2005-06-29 00:24:23 +04:00
. mode = 0644 ,
2008-11-04 05:21:05 +03:00
. proc_handler = proc_dointvec ,
2007-08-16 03:07:44 +04:00
} ,
{
2012-08-07 11:29:57 +04:00
. procname = " prsctp_enable " ,
. data = & init_net . sctp . prsctp_enable ,
2007-09-17 06:31:35 +04:00
. maxlen = sizeof ( int ) ,
. mode = 0644 ,
2008-11-04 05:21:05 +03:00
. proc_handler = proc_dointvec ,
2007-09-17 06:31:35 +04:00
} ,
2007-10-25 01:24:26 +04:00
{
2012-08-07 11:29:57 +04:00
. procname = " auth_enable " ,
. data = & init_net . sctp . auth_enable ,
2007-10-25 01:24:26 +04:00
. maxlen = sizeof ( int ) ,
. mode = 0644 ,
2008-11-04 05:21:05 +03:00
. proc_handler = proc_dointvec ,
2007-10-25 01:24:26 +04:00
} ,
2009-09-03 15:55:47 +04:00
{
. procname = " addr_scope_policy " ,
2012-08-07 11:29:57 +04:00
. data = & init_net . sctp . scope_policy ,
2009-09-03 15:55:47 +04:00
. maxlen = sizeof ( int ) ,
. mode = 0644 ,
2009-11-16 14:11:48 +03:00
. proc_handler = proc_dointvec_minmax ,
2009-09-03 15:55:47 +04:00
. extra1 = & zero ,
. extra2 = & addr_scope_max ,
} ,
2009-11-23 23:53:57 +03:00
{
. procname = " rwnd_update_shift " ,
2012-08-07 11:29:57 +04:00
. data = & init_net . sctp . rwnd_upd_shift ,
2009-11-23 23:53:57 +03:00
. maxlen = sizeof ( int ) ,
. mode = 0644 ,
. proc_handler = & proc_dointvec_minmax ,
. extra1 = & one ,
. extra2 = & rwnd_scale_max ,
} ,
2011-12-16 16:44:15 +04:00
{
. procname = " max_autoclose " ,
2012-08-07 11:29:57 +04:00
. data = & init_net . sctp . max_autoclose ,
2011-12-16 16:44:15 +04:00
. maxlen = sizeof ( unsigned long ) ,
. mode = 0644 ,
. proc_handler = & proc_doulongvec_minmax ,
. extra1 = & max_autoclose_min ,
. extra2 = & max_autoclose_max ,
} ,
2013-08-10 00:09:41 +04:00
2009-12-08 18:55:01 +03:00
{ /* sentinel */ }
2005-04-17 02:20:36 +04:00
} ;
2013-12-11 05:50:40 +04:00
static int proc_sctp_do_hmac_alg ( struct ctl_table * ctl , int write ,
2012-10-24 13:20:03 +04:00
void __user * buffer , size_t * lenp ,
loff_t * ppos )
{
struct net * net = current - > nsproxy - > net_ns ;
char tmp [ 8 ] ;
2013-06-12 10:04:25 +04:00
struct ctl_table tbl ;
2012-10-24 13:20:03 +04:00
int ret ;
int changed = 0 ;
char * none = " none " ;
memset ( & tbl , 0 , sizeof ( struct ctl_table ) ) ;
if ( write ) {
tbl . data = tmp ;
tbl . maxlen = 8 ;
} else {
tbl . data = net - > sctp . sctp_hmac_alg ? : none ;
tbl . maxlen = strlen ( tbl . data ) ;
}
ret = proc_dostring ( & tbl , write , buffer , lenp , ppos ) ;
if ( write ) {
# ifdef CONFIG_CRYPTO_MD5
if ( ! strncmp ( tmp , " md5 " , 3 ) ) {
net - > sctp . sctp_hmac_alg = " md5 " ;
changed = 1 ;
}
# endif
# ifdef CONFIG_CRYPTO_SHA1
if ( ! strncmp ( tmp , " sha1 " , 4 ) ) {
net - > sctp . sctp_hmac_alg = " sha1 " ;
changed = 1 ;
}
# endif
if ( ! strncmp ( tmp , " none " , 4 ) ) {
net - > sctp . sctp_hmac_alg = NULL ;
changed = 1 ;
}
if ( ! changed )
ret = - EINVAL ;
}
return ret ;
}
2013-12-11 05:50:39 +04:00
static int proc_sctp_do_rto_min ( struct ctl_table * ctl , int write ,
void __user * buffer , size_t * lenp ,
loff_t * ppos )
{
struct net * net = current - > nsproxy - > net_ns ;
int new_value ;
struct ctl_table tbl ;
unsigned int min = * ( unsigned int * ) ctl - > extra1 ;
unsigned int max = * ( unsigned int * ) ctl - > extra2 ;
int ret ;
memset ( & tbl , 0 , sizeof ( struct ctl_table ) ) ;
tbl . maxlen = sizeof ( unsigned int ) ;
if ( write )
tbl . data = & new_value ;
else
tbl . data = & net - > sctp . rto_min ;
ret = proc_dointvec ( & tbl , write , buffer , lenp , ppos ) ;
if ( write ) {
if ( ret | | new_value > max | | new_value < min )
return - EINVAL ;
net - > sctp . rto_min = new_value ;
}
return ret ;
}
static int proc_sctp_do_rto_max ( struct ctl_table * ctl , int write ,
void __user * buffer , size_t * lenp ,
loff_t * ppos )
{
struct net * net = current - > nsproxy - > net_ns ;
int new_value ;
struct ctl_table tbl ;
unsigned int min = * ( unsigned int * ) ctl - > extra1 ;
unsigned int max = * ( unsigned int * ) ctl - > extra2 ;
int ret ;
memset ( & tbl , 0 , sizeof ( struct ctl_table ) ) ;
tbl . maxlen = sizeof ( unsigned int ) ;
if ( write )
tbl . data = & new_value ;
else
tbl . data = & net - > sctp . rto_max ;
ret = proc_dointvec ( & tbl , write , buffer , lenp , ppos ) ;
if ( write ) {
if ( ret | | new_value > max | | new_value < min )
return - EINVAL ;
net - > sctp . rto_max = new_value ;
}
return ret ;
}
2012-08-07 11:23:59 +04:00
int sctp_sysctl_net_register ( struct net * net )
{
struct ctl_table * table ;
2012-08-07 11:29:57 +04:00
int i ;
2012-08-07 11:23:59 +04:00
table = kmemdup ( sctp_net_table , sizeof ( sctp_net_table ) , GFP_KERNEL ) ;
if ( ! table )
return - ENOMEM ;
2012-08-07 11:29:57 +04:00
for ( i = 0 ; table [ i ] . data ; i + + )
table [ i ] . data + = ( char * ) ( & net - > sctp ) - ( char * ) & init_net . sctp ;
2012-08-07 11:23:59 +04:00
net - > sctp . sysctl_header = register_net_sysctl ( net , " net/sctp " , table ) ;
return 0 ;
}
void sctp_sysctl_net_unregister ( struct net * net )
{
2013-01-24 20:02:47 +04:00
struct ctl_table * table ;
table = net - > sctp . sysctl_header - > ctl_table_arg ;
2012-08-07 11:23:59 +04:00
unregister_net_sysctl_table ( net - > sctp . sysctl_header ) ;
2013-01-24 20:02:47 +04:00
kfree ( table ) ;
2012-08-07 11:23:59 +04:00
}
2013-12-23 08:16:51 +04:00
static struct ctl_table_header * sctp_sysctl_header ;
2005-04-17 02:20:36 +04:00
/* Sysctl registration. */
void sctp_sysctl_register ( void )
{
2012-04-19 17:44:49 +04:00
sctp_sysctl_header = register_net_sysctl ( & init_net , " net/sctp " , sctp_table ) ;
2005-04-17 02:20:36 +04:00
}
/* Sysctl deregistration. */
void sctp_sysctl_unregister ( void )
{
2012-04-19 17:24:33 +04:00
unregister_net_sysctl_table ( sctp_sysctl_header ) ;
2005-04-17 02:20:36 +04:00
}