1 /* 2 * proc sysctl test driver 3 * 4 * Copyright (C) 2017 Luis R. Rodriguez <[email protected]> 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the Free 8 * Software Foundation; either version 2 of the License, or at your option any 9 * later version; or, when distributed separately from the Linux kernel or 10 * when incorporated into other software packages, subject to the following 11 * license: 12 * 13 * This program is free software; you can redistribute it and/or modify it 14 * under the terms of copyleft-next (version 0.3.1 or later) as published 15 * at http://copyleft-next.org/. 16 */ 17 18 /* 19 * This module provides an interface to the the proc sysctl interfaces. This 20 * driver requires CONFIG_PROC_SYSCTL. It will not normally be loaded by the 21 * system unless explicitly requested by name. You can also build this driver 22 * into your kernel. 23 */ 24 25 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 26 27 #include <linux/init.h> 28 #include <linux/list.h> 29 #include <linux/module.h> 30 #include <linux/printk.h> 31 #include <linux/fs.h> 32 #include <linux/miscdevice.h> 33 #include <linux/slab.h> 34 #include <linux/uaccess.h> 35 #include <linux/async.h> 36 #include <linux/delay.h> 37 #include <linux/vmalloc.h> 38 39 static int i_zero; 40 static int i_one_hundred = 100; 41 42 struct test_sysctl_data { 43 int int_0001; 44 int int_0002; 45 46 char string_0001[65]; 47 }; 48 49 static struct test_sysctl_data test_data = { 50 .int_0001 = 60, 51 .int_0002 = 1, 52 53 .string_0001 = "(none)", 54 }; 55 56 /* These are all under /proc/sys/debug/test_sysctl/ */ 57 static struct ctl_table test_table[] = { 58 { 59 .procname = "int_0001", 60 .data = &test_data.int_0001, 61 .maxlen = sizeof(int), 62 .mode = 0644, 63 .proc_handler = proc_dointvec_minmax, 64 .extra1 = &i_zero, 65 .extra2 = &i_one_hundred, 66 }, 67 { 68 .procname = "int_0002", 69 .data = &test_data.int_0002, 70 .maxlen = sizeof(int), 71 .mode = 0644, 72 .proc_handler = proc_dointvec, 73 }, 74 { 75 .procname = "string_0001", 76 .data = &test_data.string_0001, 77 .maxlen = sizeof(test_data.string_0001), 78 .mode = 0644, 79 .proc_handler = proc_dostring, 80 }, 81 { } 82 }; 83 84 static struct ctl_table test_sysctl_table[] = { 85 { 86 .procname = "test_sysctl", 87 .maxlen = 0, 88 .mode = 0555, 89 .child = test_table, 90 }, 91 { } 92 }; 93 94 static struct ctl_table test_sysctl_root_table[] = { 95 { 96 .procname = "debug", 97 .maxlen = 0, 98 .mode = 0555, 99 .child = test_sysctl_table, 100 }, 101 { } 102 }; 103 104 static struct ctl_table_header *test_sysctl_header; 105 106 static int __init test_sysctl_init(void) 107 { 108 test_sysctl_header = register_sysctl_table(test_sysctl_root_table); 109 if (!test_sysctl_header) 110 return -ENOMEM; 111 return 0; 112 } 113 late_initcall(test_sysctl_init); 114 115 static void __exit test_sysctl_exit(void) 116 { 117 if (test_sysctl_header) 118 unregister_sysctl_table(test_sysctl_header); 119 } 120 121 module_exit(test_sysctl_exit); 122 123 MODULE_AUTHOR("Luis R. Rodriguez <[email protected]>"); 124 MODULE_LICENSE("GPL"); 125