2017-07-13 00:33:43 +03:00
/*
* proc sysctl test driver
*
* Copyright ( C ) 2017 Luis R . Rodriguez < mcgrof @ kernel . org >
*
* This program is free software ; 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 of the License , or at your option any
* later version ; or , when distributed separately from the Linux kernel or
* when incorporated into other software packages , subject to the following
* license :
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of copyleft - next ( version 0.3 .1 or later ) as published
* at http : //copyleft-next.org/.
*/
/*
2020-10-16 06:11:10 +03:00
* This module provides an interface to the proc sysctl interfaces . This
2017-07-13 00:33:43 +03:00
* driver requires CONFIG_PROC_SYSCTL . It will not normally be loaded by the
* system unless explicitly requested by name . You can also build this driver
* into your kernel .
*/
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
# include <linux/init.h>
# include <linux/list.h>
# include <linux/module.h>
# include <linux/printk.h>
# include <linux/fs.h>
# include <linux/miscdevice.h>
# include <linux/slab.h>
# include <linux/uaccess.h>
# include <linux/async.h>
# include <linux/delay.h>
# include <linux/vmalloc.h>
static int i_zero ;
static int i_one_hundred = 100 ;
struct test_sysctl_data {
int int_0001 ;
2017-07-13 00:33:52 +03:00
int int_0002 ;
2017-07-13 00:33:58 +03:00
int int_0003 [ 4 ] ;
2017-07-13 00:33:52 +03:00
2020-06-08 07:40:38 +03:00
int boot_int ;
2017-07-13 00:33:55 +03:00
unsigned int uint_0001 ;
2017-07-13 00:33:43 +03:00
char string_0001 [ 65 ] ;
2019-05-15 01:45:10 +03:00
# define SYSCTL_TEST_BITMAP_SIZE 65536
unsigned long * bitmap_0001 ;
2017-07-13 00:33:43 +03:00
} ;
static struct test_sysctl_data test_data = {
. int_0001 = 60 ,
2017-07-13 00:33:52 +03:00
. int_0002 = 1 ,
2017-07-13 00:33:58 +03:00
. int_0003 [ 0 ] = 0 ,
. int_0003 [ 1 ] = 1 ,
. int_0003 [ 2 ] = 2 ,
. int_0003 [ 3 ] = 3 ,
2020-06-08 07:40:38 +03:00
. boot_int = 0 ,
2017-07-13 00:33:55 +03:00
. uint_0001 = 314 ,
2017-07-13 00:33:43 +03:00
. string_0001 = " (none) " ,
} ;
/* These are all under /proc/sys/debug/test_sysctl/ */
static struct ctl_table test_table [ ] = {
{
. procname = " int_0001 " ,
. data = & test_data . int_0001 ,
. maxlen = sizeof ( int ) ,
. mode = 0644 ,
. proc_handler = proc_dointvec_minmax ,
. extra1 = & i_zero ,
. extra2 = & i_one_hundred ,
} ,
2017-07-13 00:33:52 +03:00
{
. procname = " int_0002 " ,
. data = & test_data . int_0002 ,
. maxlen = sizeof ( int ) ,
. mode = 0644 ,
. proc_handler = proc_dointvec ,
} ,
2017-07-13 00:33:58 +03:00
{
. procname = " int_0003 " ,
. data = & test_data . int_0003 ,
. maxlen = sizeof ( test_data . int_0003 ) ,
. mode = 0644 ,
. proc_handler = proc_dointvec ,
} ,
2020-06-08 07:40:38 +03:00
{
. procname = " boot_int " ,
. data = & test_data . boot_int ,
. maxlen = sizeof ( test_data . boot_int ) ,
. mode = 0644 ,
. proc_handler = proc_dointvec ,
. extra1 = SYSCTL_ZERO ,
. extra2 = SYSCTL_ONE ,
} ,
2017-07-13 00:33:55 +03:00
{
. procname = " uint_0001 " ,
. data = & test_data . uint_0001 ,
. maxlen = sizeof ( unsigned int ) ,
. mode = 0644 ,
. proc_handler = proc_douintvec ,
} ,
2017-07-13 00:33:43 +03:00
{
. procname = " string_0001 " ,
. data = & test_data . string_0001 ,
. maxlen = sizeof ( test_data . string_0001 ) ,
. mode = 0644 ,
. proc_handler = proc_dostring ,
} ,
2019-05-15 01:45:10 +03:00
{
. procname = " bitmap_0001 " ,
. data = & test_data . bitmap_0001 ,
. maxlen = SYSCTL_TEST_BITMAP_SIZE ,
. mode = 0644 ,
. proc_handler = proc_do_large_bitmap ,
} ,
2017-07-13 00:33:43 +03:00
{ }
} ;
static struct ctl_table test_sysctl_table [ ] = {
{
. procname = " test_sysctl " ,
. maxlen = 0 ,
. mode = 0555 ,
. child = test_table ,
} ,
{ }
} ;
static struct ctl_table test_sysctl_root_table [ ] = {
{
. procname = " debug " ,
. maxlen = 0 ,
. mode = 0555 ,
. child = test_sysctl_table ,
} ,
{ }
} ;
static struct ctl_table_header * test_sysctl_header ;
static int __init test_sysctl_init ( void )
{
2019-05-15 01:45:10 +03:00
test_data . bitmap_0001 = kzalloc ( SYSCTL_TEST_BITMAP_SIZE / 8 , GFP_KERNEL ) ;
if ( ! test_data . bitmap_0001 )
return - ENOMEM ;
2017-07-13 00:33:43 +03:00
test_sysctl_header = register_sysctl_table ( test_sysctl_root_table ) ;
2019-05-15 01:45:10 +03:00
if ( ! test_sysctl_header ) {
kfree ( test_data . bitmap_0001 ) ;
2017-07-13 00:33:43 +03:00
return - ENOMEM ;
2019-05-15 01:45:10 +03:00
}
2017-07-13 00:33:43 +03:00
return 0 ;
}
2020-05-28 17:52:16 +03:00
module_init ( test_sysctl_init ) ;
2017-07-13 00:33:43 +03:00
static void __exit test_sysctl_exit ( void )
{
2019-05-15 01:45:10 +03:00
kfree ( test_data . bitmap_0001 ) ;
2017-07-13 00:33:43 +03:00
if ( test_sysctl_header )
unregister_sysctl_table ( test_sysctl_header ) ;
}
module_exit ( test_sysctl_exit ) ;
MODULE_AUTHOR ( " Luis R. Rodriguez <mcgrof@kernel.org> " ) ;
MODULE_LICENSE ( " GPL " ) ;