sysctl.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:37k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * sysctl.c: General linux system control interface
  3.  *
  4.  * Begun 24 March 1995, Stephen Tweedie
  5.  * Added /proc support, Dec 1995
  6.  * Added bdflush entry and intvec min/max checking, 2/23/96, Tom Dyas.
  7.  * Added hooks for /proc/sys/net (minor, minor patch), 96/4/1, Mike Shaver.
  8.  * Added kernel/java-{interpreter,appletviewer}, 96/5/10, Mike Shaver.
  9.  * Dynamic registration fixes, Stephen Tweedie.
  10.  * Added kswapd-interval, ctrl-alt-del, printk stuff, 1/8/97, Chris Horn.
  11.  * Made sysctl support optional via CONFIG_SYSCTL, 1/10/97, Chris
  12.  *  Horn.
  13.  * Added proc_doulongvec_ms_jiffies_minmax, 09/08/99, Carlos H. Bauer.
  14.  * Added proc_doulongvec_minmax, 09/08/99, Carlos H. Bauer.
  15.  * Changed linked lists to use list.h instead of lists.h, 02/24/00, Bill
  16.  *  Wendling.
  17.  * The list_for_each() macro wasn't appropriate for the sysctl loop.
  18.  *  Removed it and replaced it with older style, 03/23/00, Bill Wendling
  19.  */
  20. #include <linux/config.h>
  21. #include <linux/slab.h>
  22. #include <linux/sysctl.h>
  23. #include <linux/swapctl.h>
  24. #include <linux/proc_fs.h>
  25. #include <linux/ctype.h>
  26. #include <linux/utsname.h>
  27. #include <linux/capability.h>
  28. #include <linux/smp_lock.h>
  29. #include <linux/init.h>
  30. #include <linux/sysrq.h>
  31. #include <linux/highuid.h>
  32. #include <asm/uaccess.h>
  33. #ifdef CONFIG_ROOT_NFS
  34. #include <linux/nfs_fs.h>
  35. #endif
  36. #if defined(CONFIG_SYSCTL)
  37. /* External variables not in a header file. */
  38. extern int panic_timeout;
  39. extern int C_A_D;
  40. extern int bdf_prm[], bdflush_min[], bdflush_max[];
  41. extern int sysctl_overcommit_memory;
  42. extern int max_threads;
  43. extern atomic_t nr_queued_signals;
  44. extern int max_queued_signals;
  45. extern int sysrq_enabled;
  46. extern int core_uses_pid;
  47. extern int cad_pid;
  48. /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
  49. static int maxolduid = 65535;
  50. static int minolduid;
  51. #ifdef CONFIG_KMOD
  52. extern char modprobe_path[];
  53. #endif
  54. #ifdef CONFIG_HOTPLUG
  55. extern char hotplug_path[];
  56. #endif
  57. #ifdef CONFIG_CHR_DEV_SG
  58. extern int sg_big_buff;
  59. #endif
  60. #ifdef CONFIG_SYSVIPC
  61. extern size_t shm_ctlmax;
  62. extern size_t shm_ctlall;
  63. extern int shm_ctlmni;
  64. extern int msg_ctlmax;
  65. extern int msg_ctlmnb;
  66. extern int msg_ctlmni;
  67. extern int sem_ctls[];
  68. #endif
  69. #ifdef __sparc__
  70. extern char reboot_command [];
  71. extern int stop_a_enabled;
  72. #endif
  73. #ifdef CONFIG_ARCH_S390
  74. #ifdef CONFIG_MATHEMU
  75. extern int sysctl_ieee_emulation_warnings;
  76. #endif
  77. extern int sysctl_userprocess_debug;
  78. #endif
  79. #ifdef CONFIG_PPC32
  80. extern unsigned long zero_paged_on, powersave_nap;
  81. int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
  82.   void *buffer, size_t *lenp);
  83. #endif
  84. #ifdef CONFIG_BSD_PROCESS_ACCT
  85. extern int acct_parm[];
  86. #endif
  87. extern int pgt_cache_water[];
  88. static int parse_table(int *, int, void *, size_t *, void *, size_t,
  89.        ctl_table *, void **);
  90. static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
  91.   void *buffer, size_t *lenp);
  92. static ctl_table root_table[];
  93. static struct ctl_table_header root_table_header =
  94. { root_table, LIST_HEAD_INIT(root_table_header.ctl_entry) };
  95. static ctl_table kern_table[];
  96. static ctl_table vm_table[];
  97. #ifdef CONFIG_NET
  98. extern ctl_table net_table[];
  99. #endif
  100. static ctl_table proc_table[];
  101. static ctl_table fs_table[];
  102. static ctl_table debug_table[];
  103. static ctl_table dev_table[];
  104. extern ctl_table random_table[];
  105. /* /proc declarations: */
  106. #ifdef CONFIG_PROC_FS
  107. static ssize_t proc_readsys(struct file *, char *, size_t, loff_t *);
  108. static ssize_t proc_writesys(struct file *, const char *, size_t, loff_t *);
  109. static int proc_sys_permission(struct inode *, int);
  110. struct file_operations proc_sys_file_operations = {
  111. read: proc_readsys,
  112. write: proc_writesys,
  113. };
  114. static struct inode_operations proc_sys_inode_operations = {
  115. permission: proc_sys_permission,
  116. };
  117. extern struct proc_dir_entry *proc_sys_root;
  118. static void register_proc_table(ctl_table *, struct proc_dir_entry *);
  119. static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
  120. #endif
  121. /* The default sysctl tables: */
  122. static ctl_table root_table[] = {
  123. {CTL_KERN, "kernel", NULL, 0, 0555, kern_table},
  124. {CTL_VM, "vm", NULL, 0, 0555, vm_table},
  125. #ifdef CONFIG_NET
  126. {CTL_NET, "net", NULL, 0, 0555, net_table},
  127. #endif
  128. {CTL_PROC, "proc", NULL, 0, 0555, proc_table},
  129. {CTL_FS, "fs", NULL, 0, 0555, fs_table},
  130. {CTL_DEBUG, "debug", NULL, 0, 0555, debug_table},
  131.         {CTL_DEV, "dev", NULL, 0, 0555, dev_table},
  132. {0}
  133. };
  134. static ctl_table kern_table[] = {
  135. {KERN_OSTYPE, "ostype", system_utsname.sysname, 64,
  136.  0444, NULL, &proc_doutsstring, &sysctl_string},
  137. {KERN_OSRELEASE, "osrelease", system_utsname.release, 64,
  138.  0444, NULL, &proc_doutsstring, &sysctl_string},
  139. {KERN_VERSION, "version", system_utsname.version, 64,
  140.  0444, NULL, &proc_doutsstring, &sysctl_string},
  141. {KERN_NODENAME, "hostname", system_utsname.nodename, 64,
  142.  0644, NULL, &proc_doutsstring, &sysctl_string},
  143. {KERN_DOMAINNAME, "domainname", system_utsname.domainname, 64,
  144.  0644, NULL, &proc_doutsstring, &sysctl_string},
  145. {KERN_PANIC, "panic", &panic_timeout, sizeof(int),
  146.  0644, NULL, &proc_dointvec},
  147. {KERN_CORE_USES_PID, "core_uses_pid", &core_uses_pid, sizeof(int),
  148.  0644, NULL, &proc_dointvec},
  149. {KERN_TAINTED, "tainted", &tainted, sizeof(int),
  150.  0644, NULL, &proc_dointvec},
  151. {KERN_CAP_BSET, "cap-bound", &cap_bset, sizeof(kernel_cap_t),
  152.  0600, NULL, &proc_dointvec_bset},
  153. #ifdef CONFIG_BLK_DEV_INITRD
  154. {KERN_REALROOTDEV, "real-root-dev", &real_root_dev, sizeof(int),
  155.  0644, NULL, &proc_dointvec},
  156. #endif
  157. #ifdef __sparc__
  158. {KERN_SPARC_REBOOT, "reboot-cmd", reboot_command,
  159.  256, 0644, NULL, &proc_dostring, &sysctl_string },
  160. {KERN_SPARC_STOP_A, "stop-a", &stop_a_enabled, sizeof (int),
  161.  0644, NULL, &proc_dointvec},
  162. #endif
  163. #ifdef CONFIG_PPC32
  164. {KERN_PPC_ZEROPAGED, "zero-paged", &zero_paged_on, sizeof(int),
  165.  0644, NULL, &proc_dointvec},
  166. {KERN_PPC_POWERSAVE_NAP, "powersave-nap", &powersave_nap, sizeof(int),
  167.  0644, NULL, &proc_dointvec},
  168. {KERN_PPC_L2CR, "l2cr", NULL, 0,
  169.  0644, NULL, &proc_dol2crvec},
  170. #endif
  171. {KERN_CTLALTDEL, "ctrl-alt-del", &C_A_D, sizeof(int),
  172.  0644, NULL, &proc_dointvec},
  173. {KERN_PRINTK, "printk", &console_loglevel, 4*sizeof(int),
  174.  0644, NULL, &proc_dointvec},
  175. #ifdef CONFIG_KMOD
  176. {KERN_MODPROBE, "modprobe", &modprobe_path, 256,
  177.  0644, NULL, &proc_dostring, &sysctl_string },
  178. #endif
  179. #ifdef CONFIG_HOTPLUG
  180. {KERN_HOTPLUG, "hotplug", &hotplug_path, 256,
  181.  0644, NULL, &proc_dostring, &sysctl_string },
  182. #endif
  183. #ifdef CONFIG_CHR_DEV_SG
  184. {KERN_SG_BIG_BUFF, "sg-big-buff", &sg_big_buff, sizeof (int),
  185.  0444, NULL, &proc_dointvec},
  186. #endif
  187. #ifdef CONFIG_BSD_PROCESS_ACCT
  188. {KERN_ACCT, "acct", &acct_parm, 3*sizeof(int),
  189. 0644, NULL, &proc_dointvec},
  190. #endif
  191. {KERN_RTSIGNR, "rtsig-nr", &nr_queued_signals, sizeof(int),
  192.  0444, NULL, &proc_dointvec},
  193. {KERN_RTSIGMAX, "rtsig-max", &max_queued_signals, sizeof(int),
  194.  0644, NULL, &proc_dointvec},
  195. #ifdef CONFIG_SYSVIPC
  196. {KERN_SHMMAX, "shmmax", &shm_ctlmax, sizeof (size_t),
  197.  0644, NULL, &proc_doulongvec_minmax},
  198. {KERN_SHMALL, "shmall", &shm_ctlall, sizeof (size_t),
  199.  0644, NULL, &proc_doulongvec_minmax},
  200. {KERN_SHMMNI, "shmmni", &shm_ctlmni, sizeof (int),
  201.  0644, NULL, &proc_dointvec},
  202. {KERN_MSGMAX, "msgmax", &msg_ctlmax, sizeof (int),
  203.  0644, NULL, &proc_dointvec},
  204. {KERN_MSGMNI, "msgmni", &msg_ctlmni, sizeof (int),
  205.  0644, NULL, &proc_dointvec},
  206. {KERN_MSGMNB, "msgmnb", &msg_ctlmnb, sizeof (int),
  207.  0644, NULL, &proc_dointvec},
  208. {KERN_SEM, "sem", &sem_ctls, 4*sizeof (int),
  209.  0644, NULL, &proc_dointvec},
  210. #endif
  211. #ifdef CONFIG_MAGIC_SYSRQ
  212. {KERN_SYSRQ, "sysrq", &sysrq_enabled, sizeof (int),
  213.  0644, NULL, &proc_dointvec},
  214. #endif  
  215. {KERN_CADPID, "cad_pid", &cad_pid, sizeof (int),
  216.  0600, NULL, &proc_dointvec},
  217. {KERN_MAX_THREADS, "threads-max", &max_threads, sizeof(int),
  218.  0644, NULL, &proc_dointvec},
  219. {KERN_RANDOM, "random", NULL, 0, 0555, random_table},
  220. {KERN_OVERFLOWUID, "overflowuid", &overflowuid, sizeof(int), 0644, NULL,
  221.  &proc_dointvec_minmax, &sysctl_intvec, NULL,
  222.  &minolduid, &maxolduid},
  223. {KERN_OVERFLOWGID, "overflowgid", &overflowgid, sizeof(int), 0644, NULL,
  224.  &proc_dointvec_minmax, &sysctl_intvec, NULL,
  225.  &minolduid, &maxolduid},
  226. #ifdef CONFIG_ARCH_S390
  227. #ifdef CONFIG_MATHEMU
  228. {KERN_IEEE_EMULATION_WARNINGS,"ieee_emulation_warnings",
  229.  &sysctl_ieee_emulation_warnings,sizeof(int),0644,NULL,&proc_dointvec},
  230. #endif
  231. {KERN_S390_USER_DEBUG_LOGGING,"userprocess_debug",
  232.  &sysctl_userprocess_debug,sizeof(int),0644,NULL,&proc_dointvec},
  233. #endif
  234. {0}
  235. };
  236. static ctl_table vm_table[] = {
  237. {VM_BDFLUSH, "bdflush", &bdf_prm, 9*sizeof(int), 0644, NULL,
  238.  &proc_dointvec_minmax, &sysctl_intvec, NULL,
  239.  &bdflush_min, &bdflush_max},
  240. {VM_OVERCOMMIT_MEMORY, "overcommit_memory", &sysctl_overcommit_memory,
  241.  sizeof(sysctl_overcommit_memory), 0644, NULL, &proc_dointvec},
  242. {VM_PAGERDAEMON, "kswapd",
  243.  &pager_daemon, sizeof(pager_daemon_t), 0644, NULL, &proc_dointvec},
  244. {VM_PGT_CACHE, "pagetable_cache", 
  245.  &pgt_cache_water, 2*sizeof(int), 0644, NULL, &proc_dointvec},
  246. {VM_PAGE_CLUSTER, "page-cluster", 
  247.  &page_cluster, sizeof(int), 0644, NULL, &proc_dointvec},
  248. {VM_MIN_READAHEAD, "min-readahead",
  249. &vm_min_readahead,sizeof(int), 0644, NULL, &proc_dointvec},
  250. {VM_MAX_READAHEAD, "max-readahead",
  251. &vm_max_readahead,sizeof(int), 0644, NULL, &proc_dointvec},
  252. {VM_MAX_MAP_COUNT, "max_map_count",
  253.  &max_map_count, sizeof(int), 0644, NULL, &proc_dointvec},
  254. {0}
  255. };
  256. static ctl_table proc_table[] = {
  257. {0}
  258. };
  259. static ctl_table fs_table[] = {
  260. {FS_NRINODE, "inode-nr", &inodes_stat, 2*sizeof(int),
  261.  0444, NULL, &proc_dointvec},
  262. {FS_STATINODE, "inode-state", &inodes_stat, 7*sizeof(int),
  263.  0444, NULL, &proc_dointvec},
  264. {FS_NRFILE, "file-nr", &files_stat, 3*sizeof(int),
  265.  0444, NULL, &proc_dointvec},
  266. {FS_MAXFILE, "file-max", &files_stat.max_files, sizeof(int),
  267.  0644, NULL, &proc_dointvec},
  268. {FS_NRDQUOT, "dquot-nr", &nr_dquots, 2*sizeof(int),
  269.  0444, NULL, &proc_dointvec},
  270. {FS_DENTRY, "dentry-state", &dentry_stat, 6*sizeof(int),
  271.  0444, NULL, &proc_dointvec},
  272. {FS_OVERFLOWUID, "overflowuid", &fs_overflowuid, sizeof(int), 0644, NULL,
  273.  &proc_dointvec_minmax, &sysctl_intvec, NULL,
  274.  &minolduid, &maxolduid},
  275. {FS_OVERFLOWGID, "overflowgid", &fs_overflowgid, sizeof(int), 0644, NULL,
  276.  &proc_dointvec_minmax, &sysctl_intvec, NULL,
  277.  &minolduid, &maxolduid},
  278. {FS_LEASES, "leases-enable", &leases_enable, sizeof(int),
  279.  0644, NULL, &proc_dointvec},
  280. {FS_DIR_NOTIFY, "dir-notify-enable", &dir_notify_enable,
  281.  sizeof(int), 0644, NULL, &proc_dointvec},
  282. {FS_LEASE_TIME, "lease-break-time", &lease_break_time, sizeof(int),
  283.  0644, NULL, &proc_dointvec},
  284. {0}
  285. };
  286. static ctl_table debug_table[] = {
  287. {0}
  288. };
  289. static ctl_table dev_table[] = {
  290. {0}
  291. };  
  292. extern void init_irq_proc (void);
  293. void __init sysctl_init(void)
  294. {
  295. #ifdef CONFIG_PROC_FS
  296. register_proc_table(root_table, proc_sys_root);
  297. init_irq_proc();
  298. #endif
  299. }
  300. int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp,
  301.        void *newval, size_t newlen)
  302. {
  303. struct list_head *tmp;
  304. if (nlen <= 0 || nlen >= CTL_MAXNAME)
  305. return -ENOTDIR;
  306. if (oldval) {
  307. int old_len;
  308. if (!oldlenp || get_user(old_len, oldlenp))
  309. return -EFAULT;
  310. }
  311. tmp = &root_table_header.ctl_entry;
  312. do {
  313. struct ctl_table_header *head =
  314. list_entry(tmp, struct ctl_table_header, ctl_entry);
  315. void *context = NULL;
  316. int error = parse_table(name, nlen, oldval, oldlenp, 
  317. newval, newlen, head->ctl_table,
  318. &context);
  319. if (context)
  320. kfree(context);
  321. if (error != -ENOTDIR)
  322. return error;
  323. tmp = tmp->next;
  324. } while (tmp != &root_table_header.ctl_entry);
  325. return -ENOTDIR;
  326. }
  327. extern asmlinkage long sys_sysctl(struct __sysctl_args *args)
  328. {
  329. struct __sysctl_args tmp;
  330. int error;
  331. if (copy_from_user(&tmp, args, sizeof(tmp)))
  332. return -EFAULT;
  333. lock_kernel();
  334. error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp,
  335.   tmp.newval, tmp.newlen);
  336. unlock_kernel();
  337. return error;
  338. }
  339. /*
  340.  * ctl_perm does NOT grant the superuser all rights automatically, because
  341.  * some sysctl variables are readonly even to root.
  342.  */
  343. static int test_perm(int mode, int op)
  344. {
  345. if (!current->euid)
  346. mode >>= 6;
  347. else if (in_egroup_p(0))
  348. mode >>= 3;
  349. if ((mode & op & 0007) == op)
  350. return 0;
  351. return -EACCES;
  352. }
  353. static inline int ctl_perm(ctl_table *table, int op)
  354. {
  355. return test_perm(table->mode, op);
  356. }
  357. static int parse_table(int *name, int nlen,
  358.        void *oldval, size_t *oldlenp,
  359.        void *newval, size_t newlen,
  360.        ctl_table *table, void **context)
  361. {
  362. int n;
  363. repeat:
  364. if (!nlen)
  365. return -ENOTDIR;
  366. if (get_user(n, name))
  367. return -EFAULT;
  368. for ( ; table->ctl_name; table++) {
  369. if (n == table->ctl_name || table->ctl_name == CTL_ANY) {
  370. int error;
  371. if (table->child) {
  372. if (ctl_perm(table, 001))
  373. return -EPERM;
  374. if (table->strategy) {
  375. error = table->strategy(
  376. table, name, nlen,
  377. oldval, oldlenp,
  378. newval, newlen, context);
  379. if (error)
  380. return error;
  381. }
  382. name++;
  383. nlen--;
  384. table = table->child;
  385. goto repeat;
  386. }
  387. error = do_sysctl_strategy(table, name, nlen,
  388.    oldval, oldlenp,
  389.    newval, newlen, context);
  390. return error;
  391. }
  392. }
  393. return -ENOTDIR;
  394. }
  395. /* Perform the actual read/write of a sysctl table entry. */
  396. int do_sysctl_strategy (ctl_table *table, 
  397. int *name, int nlen,
  398. void *oldval, size_t *oldlenp,
  399. void *newval, size_t newlen, void **context)
  400. {
  401. int op = 0, rc;
  402. size_t len;
  403. if (oldval)
  404. op |= 004;
  405. if (newval) 
  406. op |= 002;
  407. if (ctl_perm(table, op))
  408. return -EPERM;
  409. if (table->strategy) {
  410. rc = table->strategy(table, name, nlen, oldval, oldlenp,
  411.      newval, newlen, context);
  412. if (rc < 0)
  413. return rc;
  414. if (rc > 0)
  415. return 0;
  416. }
  417. /* If there is no strategy routine, or if the strategy returns
  418.  * zero, proceed with automatic r/w */
  419. if (table->data && table->maxlen) {
  420. if (oldval && oldlenp) {
  421. get_user(len, oldlenp);
  422. if (len) {
  423. if (len > table->maxlen)
  424. len = table->maxlen;
  425. if(copy_to_user(oldval, table->data, len))
  426. return -EFAULT;
  427. if(put_user(len, oldlenp))
  428. return -EFAULT;
  429. }
  430. }
  431. if (newval && newlen) {
  432. len = newlen;
  433. if (len > table->maxlen)
  434. len = table->maxlen;
  435. if(copy_from_user(table->data, newval, len))
  436. return -EFAULT;
  437. }
  438. }
  439. return 0;
  440. }
  441. /**
  442.  * register_sysctl_table - register a sysctl hierarchy
  443.  * @table: the top-level table structure
  444.  * @insert_at_head: whether the entry should be inserted in front or at the end
  445.  *
  446.  * Register a sysctl table hierarchy. @table should be a filled in ctl_table
  447.  * array. An entry with a ctl_name of 0 terminates the table. 
  448.  *
  449.  * The members of the &ctl_table structure are used as follows:
  450.  *
  451.  * ctl_name - This is the numeric sysctl value used by sysctl(2). The number
  452.  *            must be unique within that level of sysctl
  453.  *
  454.  * procname - the name of the sysctl file under /proc/sys. Set to %NULL to not
  455.  *            enter a sysctl file
  456.  *
  457.  * data - a pointer to data for use by proc_handler
  458.  *
  459.  * maxlen - the maximum size in bytes of the data
  460.  *
  461.  * mode - the file permissions for the /proc/sys file, and for sysctl(2)
  462.  *
  463.  * child - a pointer to the child sysctl table if this entry is a directory, or
  464.  *         %NULL.
  465.  *
  466.  * proc_handler - the text handler routine (described below)
  467.  *
  468.  * strategy - the strategy routine (described below)
  469.  *
  470.  * de - for internal use by the sysctl routines
  471.  *
  472.  * extra1, extra2 - extra pointers usable by the proc handler routines
  473.  *
  474.  * Leaf nodes in the sysctl tree will be represented by a single file
  475.  * under /proc; non-leaf nodes will be represented by directories.
  476.  *
  477.  * sysctl(2) can automatically manage read and write requests through
  478.  * the sysctl table.  The data and maxlen fields of the ctl_table
  479.  * struct enable minimal validation of the values being written to be
  480.  * performed, and the mode field allows minimal authentication.
  481.  *
  482.  * More sophisticated management can be enabled by the provision of a
  483.  * strategy routine with the table entry.  This will be called before
  484.  * any automatic read or write of the data is performed.
  485.  *
  486.  * The strategy routine may return
  487.  *
  488.  * < 0 - Error occurred (error is passed to user process)
  489.  *
  490.  * 0   - OK - proceed with automatic read or write.
  491.  *
  492.  * > 0 - OK - read or write has been done by the strategy routine, so
  493.  *       return immediately.
  494.  *
  495.  * There must be a proc_handler routine for any terminal nodes
  496.  * mirrored under /proc/sys (non-terminals are handled by a built-in
  497.  * directory handler).  Several default handlers are available to
  498.  * cover common cases -
  499.  *
  500.  * proc_dostring(), proc_dointvec(), proc_dointvec_jiffies(),
  501.  * proc_dointvec_minmax(), proc_doulongvec_ms_jiffies_minmax(),
  502.  * proc_doulongvec_minmax()
  503.  *
  504.  * It is the handler's job to read the input buffer from user memory
  505.  * and process it. The handler should return 0 on success.
  506.  *
  507.  * This routine returns %NULL on a failure to register, and a pointer
  508.  * to the table header on success.
  509.  */
  510. struct ctl_table_header *register_sysctl_table(ctl_table * table, 
  511.        int insert_at_head)
  512. {
  513. struct ctl_table_header *tmp;
  514. tmp = kmalloc(sizeof(struct ctl_table_header), GFP_KERNEL);
  515. if (!tmp)
  516. return NULL;
  517. tmp->ctl_table = table;
  518. INIT_LIST_HEAD(&tmp->ctl_entry);
  519. if (insert_at_head)
  520. list_add(&tmp->ctl_entry, &root_table_header.ctl_entry);
  521. else
  522. list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
  523. #ifdef CONFIG_PROC_FS
  524. register_proc_table(table, proc_sys_root);
  525. #endif
  526. return tmp;
  527. }
  528. /**
  529.  * unregister_sysctl_table - unregister a sysctl table hierarchy
  530.  * @header: the header returned from register_sysctl_table
  531.  *
  532.  * Unregisters the sysctl table and all children. proc entries may not
  533.  * actually be removed until they are no longer used by anyone.
  534.  */
  535. void unregister_sysctl_table(struct ctl_table_header * header)
  536. {
  537. list_del(&header->ctl_entry);
  538. #ifdef CONFIG_PROC_FS
  539. unregister_proc_table(header->ctl_table, proc_sys_root);
  540. #endif
  541. kfree(header);
  542. }
  543. /*
  544.  * /proc/sys support
  545.  */
  546. #ifdef CONFIG_PROC_FS
  547. /* Scan the sysctl entries in table and add them all into /proc */
  548. static void register_proc_table(ctl_table * table, struct proc_dir_entry *root)
  549. {
  550. struct proc_dir_entry *de;
  551. int len;
  552. mode_t mode;
  553. for (; table->ctl_name; table++) {
  554. /* Can't do anything without a proc name. */
  555. if (!table->procname)
  556. continue;
  557. /* Maybe we can't do anything with it... */
  558. if (!table->proc_handler && !table->child) {
  559. printk(KERN_WARNING "SYSCTL: Can't register %sn",
  560. table->procname);
  561. continue;
  562. }
  563. len = strlen(table->procname);
  564. mode = table->mode;
  565. de = NULL;
  566. if (table->proc_handler)
  567. mode |= S_IFREG;
  568. else {
  569. mode |= S_IFDIR;
  570. for (de = root->subdir; de; de = de->next) {
  571. if (proc_match(len, table->procname, de))
  572. break;
  573. }
  574. /* If the subdir exists already, de is non-NULL */
  575. }
  576. if (!de) {
  577. de = create_proc_entry(table->procname, mode, root);
  578. if (!de)
  579. continue;
  580. de->data = (void *) table;
  581. if (table->proc_handler) {
  582. de->proc_fops = &proc_sys_file_operations;
  583. de->proc_iops = &proc_sys_inode_operations;
  584. }
  585. }
  586. table->de = de;
  587. if (de->mode & S_IFDIR)
  588. register_proc_table(table->child, de);
  589. }
  590. }
  591. /*
  592.  * Unregister a /proc sysctl table and any subdirectories.
  593.  */
  594. static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root)
  595. {
  596. struct proc_dir_entry *de;
  597. for (; table->ctl_name; table++) {
  598. if (!(de = table->de))
  599. continue;
  600. if (de->mode & S_IFDIR) {
  601. if (!table->child) {
  602. printk (KERN_ALERT "Help - malformed sysctl tree on freen");
  603. continue;
  604. }
  605. unregister_proc_table(table->child, de);
  606. /* Don't unregister directories which still have entries.. */
  607. if (de->subdir)
  608. continue;
  609. }
  610. /* Don't unregister proc entries that are still being used.. */
  611. if (atomic_read(&de->count))
  612. continue;
  613. table->de = NULL;
  614. remove_proc_entry(table->procname, root);
  615. }
  616. }
  617. static ssize_t do_rw_proc(int write, struct file * file, char * buf,
  618.   size_t count, loff_t *ppos)
  619. {
  620. int op;
  621. struct proc_dir_entry *de;
  622. struct ctl_table *table;
  623. size_t res;
  624. ssize_t error;
  625. de = (struct proc_dir_entry*) file->f_dentry->d_inode->u.generic_ip;
  626. if (!de || !de->data)
  627. return -ENOTDIR;
  628. table = (struct ctl_table *) de->data;
  629. if (!table || !table->proc_handler)
  630. return -ENOTDIR;
  631. op = (write ? 002 : 004);
  632. if (ctl_perm(table, op))
  633. return -EPERM;
  634. res = count;
  635. /*
  636.  * FIXME: we need to pass on ppos to the handler.
  637.  */
  638. error = (*table->proc_handler) (table, write, file, buf, &res);
  639. if (error)
  640. return error;
  641. return res;
  642. }
  643. static ssize_t proc_readsys(struct file * file, char * buf,
  644.     size_t count, loff_t *ppos)
  645. {
  646. return do_rw_proc(0, file, buf, count, ppos);
  647. }
  648. static ssize_t proc_writesys(struct file * file, const char * buf,
  649.      size_t count, loff_t *ppos)
  650. {
  651. return do_rw_proc(1, file, (char *) buf, count, ppos);
  652. }
  653. static int proc_sys_permission(struct inode *inode, int op)
  654. {
  655. return test_perm(inode->i_mode, op);
  656. }
  657. /**
  658.  * proc_dostring - read a string sysctl
  659.  * @table: the sysctl table
  660.  * @write: %TRUE if this is a write to the sysctl file
  661.  * @filp: the file structure
  662.  * @buffer: the user buffer
  663.  * @lenp: the size of the user buffer
  664.  *
  665.  * Reads/writes a string from/to the user buffer. If the kernel
  666.  * buffer provided is not large enough to hold the string, the
  667.  * string is truncated. The copied string is %NULL-terminated.
  668.  * If the string is being read by the user process, it is copied
  669.  * and a newline 'n' is added. It is truncated if the buffer is
  670.  * not large enough.
  671.  *
  672.  * Returns 0 on success.
  673.  */
  674. int proc_dostring(ctl_table *table, int write, struct file *filp,
  675.   void *buffer, size_t *lenp)
  676. {
  677. size_t len;
  678. char *p, c;
  679. if (!table->data || !table->maxlen || !*lenp ||
  680.     (filp->f_pos && !write)) {
  681. *lenp = 0;
  682. return 0;
  683. }
  684. if (write) {
  685. len = 0;
  686. p = buffer;
  687. while (len < *lenp) {
  688. if(get_user(c, p++))
  689. return -EFAULT;
  690. if (c == 0 || c == 'n')
  691. break;
  692. len++;
  693. }
  694. if (len >= table->maxlen)
  695. len = table->maxlen-1;
  696. if(copy_from_user(table->data, buffer, len))
  697. return -EFAULT;
  698. ((char *) table->data)[len] = 0;
  699. filp->f_pos += *lenp;
  700. } else {
  701. len = strlen(table->data);
  702. if (len > table->maxlen)
  703. len = table->maxlen;
  704. if (len > *lenp)
  705. len = *lenp;
  706. if (len)
  707. if(copy_to_user(buffer, table->data, len))
  708. return -EFAULT;
  709. if (len < *lenp) {
  710. if(put_user('n', ((char *) buffer) + len))
  711. return -EFAULT;
  712. len++;
  713. }
  714. *lenp = len;
  715. filp->f_pos += len;
  716. }
  717. return 0;
  718. }
  719. /*
  720.  * Special case of dostring for the UTS structure. This has locks
  721.  * to observe. Should this be in kernel/sys.c ????
  722.  */
  723.  
  724. static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
  725.   void *buffer, size_t *lenp)
  726. {
  727. int r;
  728. if (!write) {
  729. down_read(&uts_sem);
  730. r=proc_dostring(table,0,filp,buffer,lenp);
  731. up_read(&uts_sem);
  732. } else {
  733. down_write(&uts_sem);
  734. r=proc_dostring(table,1,filp,buffer,lenp);
  735. up_write(&uts_sem);
  736. }
  737. return r;
  738. }
  739. #define OP_SET 0
  740. #define OP_AND 1
  741. #define OP_OR 2
  742. #define OP_MAX 3
  743. #define OP_MIN 4
  744. static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
  745.   void *buffer, size_t *lenp, int conv, int op)
  746. {
  747. int *i, vleft, first=1, neg, val;
  748. size_t left, len;
  749. #define TMPBUFLEN 20
  750. char buf[TMPBUFLEN], *p;
  751. if (!table->data || !table->maxlen || !*lenp ||
  752.     (filp->f_pos && !write)) {
  753. *lenp = 0;
  754. return 0;
  755. }
  756. i = (int *) table->data;
  757. vleft = table->maxlen / sizeof(int);
  758. left = *lenp;
  759. for (; left && vleft--; i++, first=0) {
  760. if (write) {
  761. while (left) {
  762. char c;
  763. if(get_user(c,(char *) buffer))
  764. return -EFAULT;
  765. if (!isspace(c))
  766. break;
  767. left--;
  768. ((char *) buffer)++;
  769. }
  770. if (!left)
  771. break;
  772. neg = 0;
  773. len = left;
  774. if (len > TMPBUFLEN-1)
  775. len = TMPBUFLEN-1;
  776. if(copy_from_user(buf, buffer, len))
  777. return -EFAULT;
  778. buf[len] = 0;
  779. p = buf;
  780. if (*p == '-' && left > 1) {
  781. neg = 1;
  782. left--, p++;
  783. }
  784. if (*p < '0' || *p > '9')
  785. break;
  786. val = simple_strtoul(p, &p, 0) * conv;
  787. len = p-buf;
  788. if ((len < left) && *p && !isspace(*p))
  789. break;
  790. if (neg)
  791. val = -val;
  792. buffer += len;
  793. left -= len;
  794. switch(op) {
  795. case OP_SET: *i = val; break;
  796. case OP_AND: *i &= val; break;
  797. case OP_OR: *i |= val; break;
  798. case OP_MAX: if(*i < val)
  799. *i = val;
  800. break;
  801. case OP_MIN: if(*i > val)
  802. *i = val;
  803. break;
  804. }
  805. } else {
  806. p = buf;
  807. if (!first)
  808. *p++ = 't';
  809. sprintf(p, "%d", (*i) / conv);
  810. len = strlen(buf);
  811. if (len > left)
  812. len = left;
  813. if(copy_to_user(buffer, buf, len))
  814. return -EFAULT;
  815. left -= len;
  816. buffer += len;
  817. }
  818. }
  819. if (!write && !first && left) {
  820. if(put_user('n', (char *) buffer))
  821. return -EFAULT;
  822. left--, buffer++;
  823. }
  824. if (write) {
  825. p = (char *) buffer;
  826. while (left) {
  827. char c;
  828. if(get_user(c, p++))
  829. return -EFAULT;
  830. if (!isspace(c))
  831. break;
  832. left--;
  833. }
  834. }
  835. if (write && first)
  836. return -EINVAL;
  837. *lenp -= left;
  838. filp->f_pos += *lenp;
  839. return 0;
  840. }
  841. /**
  842.  * proc_dointvec - read a vector of integers
  843.  * @table: the sysctl table
  844.  * @write: %TRUE if this is a write to the sysctl file
  845.  * @filp: the file structure
  846.  * @buffer: the user buffer
  847.  * @lenp: the size of the user buffer
  848.  *
  849.  * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
  850.  * values from/to the user buffer, treated as an ASCII string. 
  851.  *
  852.  * Returns 0 on success.
  853.  */
  854. int proc_dointvec(ctl_table *table, int write, struct file *filp,
  855.      void *buffer, size_t *lenp)
  856. {
  857.     return do_proc_dointvec(table,write,filp,buffer,lenp,1,OP_SET);
  858. }
  859. /*
  860.  * init may raise the set.
  861.  */
  862.  
  863. int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
  864. void *buffer, size_t *lenp)
  865. {
  866. if (!capable(CAP_SYS_MODULE)) {
  867. return -EPERM;
  868. }
  869. return do_proc_dointvec(table,write,filp,buffer,lenp,1,
  870. (current->pid == 1) ? OP_SET : OP_AND);
  871. }
  872. /**
  873.  * proc_dointvec_minmax - read a vector of integers with min/max values
  874.  * @table: the sysctl table
  875.  * @write: %TRUE if this is a write to the sysctl file
  876.  * @filp: the file structure
  877.  * @buffer: the user buffer
  878.  * @lenp: the size of the user buffer
  879.  *
  880.  * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
  881.  * values from/to the user buffer, treated as an ASCII string.
  882.  *
  883.  * This routine will ensure the values are within the range specified by
  884.  * table->extra1 (min) and table->extra2 (max).
  885.  *
  886.  * Returns 0 on success.
  887.  */
  888. int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
  889.   void *buffer, size_t *lenp)
  890. {
  891. int *i, *min, *max, vleft, first=1, neg, val;
  892. size_t len, left;
  893. #define TMPBUFLEN 20
  894. char buf[TMPBUFLEN], *p;
  895. if (!table->data || !table->maxlen || !*lenp ||
  896.     (filp->f_pos && !write)) {
  897. *lenp = 0;
  898. return 0;
  899. }
  900. i = (int *) table->data;
  901. min = (int *) table->extra1;
  902. max = (int *) table->extra2;
  903. vleft = table->maxlen / sizeof(int);
  904. left = *lenp;
  905. for (; left && vleft--; i++, min++, max++, first=0) {
  906. if (write) {
  907. while (left) {
  908. char c;
  909. if(get_user(c, (char *) buffer))
  910. return -EFAULT;
  911. if (!isspace(c))
  912. break;
  913. left--;
  914. ((char *) buffer)++;
  915. }
  916. if (!left)
  917. break;
  918. neg = 0;
  919. len = left;
  920. if (len > TMPBUFLEN-1)
  921. len = TMPBUFLEN-1;
  922. if(copy_from_user(buf, buffer, len))
  923. return -EFAULT;
  924. buf[len] = 0;
  925. p = buf;
  926. if (*p == '-' && left > 1) {
  927. neg = 1;
  928. left--, p++;
  929. }
  930. if (*p < '0' || *p > '9')
  931. break;
  932. val = simple_strtoul(p, &p, 0);
  933. len = p-buf;
  934. if ((len < left) && *p && !isspace(*p))
  935. break;
  936. if (neg)
  937. val = -val;
  938. buffer += len;
  939. left -= len;
  940. if ((min && val < *min) || (max && val > *max))
  941. continue;
  942. *i = val;
  943. } else {
  944. p = buf;
  945. if (!first)
  946. *p++ = 't';
  947. sprintf(p, "%d", *i);
  948. len = strlen(buf);
  949. if (len > left)
  950. len = left;
  951. if(copy_to_user(buffer, buf, len))
  952. return -EFAULT;
  953. left -= len;
  954. buffer += len;
  955. }
  956. }
  957. if (!write && !first && left) {
  958. if(put_user('n', (char *) buffer))
  959. return -EFAULT;
  960. left--, buffer++;
  961. }
  962. if (write) {
  963. p = (char *) buffer;
  964. while (left) {
  965. char c;
  966. if(get_user(c, p++))
  967. return -EFAULT;
  968. if (!isspace(c))
  969. break;
  970. left--;
  971. }
  972. }
  973. if (write && first)
  974. return -EINVAL;
  975. *lenp -= left;
  976. filp->f_pos += *lenp;
  977. return 0;
  978. }
  979. static int do_proc_doulongvec_minmax(ctl_table *table, int write,
  980.      struct file *filp,
  981.      void *buffer, size_t *lenp,
  982.      unsigned long convmul,
  983.      unsigned long convdiv)
  984. {
  985. #define TMPBUFLEN 20
  986. unsigned long *i, *min, *max, val;
  987. int vleft, first=1, neg;
  988. size_t len, left;
  989. char buf[TMPBUFLEN], *p;
  990. if (!table->data || !table->maxlen || !*lenp ||
  991.     (filp->f_pos && !write)) {
  992. *lenp = 0;
  993. return 0;
  994. }
  995. i = (unsigned long *) table->data;
  996. min = (unsigned long *) table->extra1;
  997. max = (unsigned long *) table->extra2;
  998. vleft = table->maxlen / sizeof(unsigned long);
  999. left = *lenp;
  1000. for (; left && vleft--; i++, first=0) {
  1001. if (write) {
  1002. while (left) {
  1003. char c;
  1004. if(get_user(c, (char *) buffer))
  1005. return -EFAULT;
  1006. if (!isspace(c))
  1007. break;
  1008. left--;
  1009. ((char *) buffer)++;
  1010. }
  1011. if (!left)
  1012. break;
  1013. neg = 0;
  1014. len = left;
  1015. if (len > TMPBUFLEN-1)
  1016. len = TMPBUFLEN-1;
  1017. if(copy_from_user(buf, buffer, len))
  1018. return -EFAULT;
  1019. buf[len] = 0;
  1020. p = buf;
  1021. if (*p == '-' && left > 1) {
  1022. neg = 1;
  1023. left--, p++;
  1024. }
  1025. if (*p < '0' || *p > '9')
  1026. break;
  1027. val = simple_strtoul(p, &p, 0) * convmul / convdiv ;
  1028. len = p-buf;
  1029. if ((len < left) && *p && !isspace(*p))
  1030. break;
  1031. if (neg)
  1032. val = -val;
  1033. buffer += len;
  1034. left -= len;
  1035. if(neg)
  1036. continue;
  1037. if (min && val < *min++)
  1038. continue;
  1039. if (max && val > *max++)
  1040. continue;
  1041. *i = val;
  1042. } else {
  1043. p = buf;
  1044. if (!first)
  1045. *p++ = 't';
  1046. sprintf(p, "%lu", convdiv * (*i) / convmul);
  1047. len = strlen(buf);
  1048. if (len > left)
  1049. len = left;
  1050. if(copy_to_user(buffer, buf, len))
  1051. return -EFAULT;
  1052. left -= len;
  1053. buffer += len;
  1054. }
  1055. }
  1056. if (!write && !first && left) {
  1057. if(put_user('n', (char *) buffer))
  1058. return -EFAULT;
  1059. left--, buffer++;
  1060. }
  1061. if (write) {
  1062. p = (char *) buffer;
  1063. while (left) {
  1064. char c;
  1065. if(get_user(c, p++))
  1066. return -EFAULT;
  1067. if (!isspace(c))
  1068. break;
  1069. left--;
  1070. }
  1071. }
  1072. if (write && first)
  1073. return -EINVAL;
  1074. *lenp -= left;
  1075. filp->f_pos += *lenp;
  1076. return 0;
  1077. #undef TMPBUFLEN
  1078. }
  1079. /**
  1080.  * proc_doulongvec_minmax - read a vector of long integers with min/max values
  1081.  * @table: the sysctl table
  1082.  * @write: %TRUE if this is a write to the sysctl file
  1083.  * @filp: the file structure
  1084.  * @buffer: the user buffer
  1085.  * @lenp: the size of the user buffer
  1086.  *
  1087.  * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
  1088.  * values from/to the user buffer, treated as an ASCII string.
  1089.  *
  1090.  * This routine will ensure the values are within the range specified by
  1091.  * table->extra1 (min) and table->extra2 (max).
  1092.  *
  1093.  * Returns 0 on success.
  1094.  */
  1095. int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
  1096.    void *buffer, size_t *lenp)
  1097. {
  1098.     return do_proc_doulongvec_minmax(table, write, filp, buffer, lenp, 1l, 1l);
  1099. }
  1100. /**
  1101.  * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values
  1102.  * @table: the sysctl table
  1103.  * @write: %TRUE if this is a write to the sysctl file
  1104.  * @filp: the file structure
  1105.  * @buffer: the user buffer
  1106.  * @lenp: the size of the user buffer
  1107.  *
  1108.  * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
  1109.  * values from/to the user buffer, treated as an ASCII string. The values
  1110.  * are treated as milliseconds, and converted to jiffies when they are stored.
  1111.  *
  1112.  * This routine will ensure the values are within the range specified by
  1113.  * table->extra1 (min) and table->extra2 (max).
  1114.  *
  1115.  * Returns 0 on success.
  1116.  */
  1117. int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
  1118.       struct file *filp,
  1119.       void *buffer, size_t *lenp)
  1120. {
  1121.     return do_proc_doulongvec_minmax(table, write, filp, buffer,
  1122.      lenp, HZ, 1000l);
  1123. }
  1124. /**
  1125.  * proc_dointvec_jiffies - read a vector of integers as seconds
  1126.  * @table: the sysctl table
  1127.  * @write: %TRUE if this is a write to the sysctl file
  1128.  * @filp: the file structure
  1129.  * @buffer: the user buffer
  1130.  * @lenp: the size of the user buffer
  1131.  *
  1132.  * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
  1133.  * values from/to the user buffer, treated as an ASCII string. 
  1134.  * The values read are assumed to be in seconds, and are converted into
  1135.  * jiffies.
  1136.  *
  1137.  * Returns 0 on success.
  1138.  */
  1139. int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
  1140.   void *buffer, size_t *lenp)
  1141. {
  1142.     return do_proc_dointvec(table,write,filp,buffer,lenp,HZ,OP_SET);
  1143. }
  1144. #else /* CONFIG_PROC_FS */
  1145. int proc_dostring(ctl_table *table, int write, struct file *filp,
  1146.   void *buffer, size_t *lenp)
  1147. {
  1148. return -ENOSYS;
  1149. }
  1150. static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
  1151.     void *buffer, size_t *lenp)
  1152. {
  1153. return -ENOSYS;
  1154. }
  1155. int proc_dointvec(ctl_table *table, int write, struct file *filp,
  1156.   void *buffer, size_t *lenp)
  1157. {
  1158. return -ENOSYS;
  1159. }
  1160. int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
  1161. void *buffer, size_t *lenp)
  1162. {
  1163. return -ENOSYS;
  1164. }
  1165. int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
  1166.     void *buffer, size_t *lenp)
  1167. {
  1168. return -ENOSYS;
  1169. }
  1170. int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
  1171.     void *buffer, size_t *lenp)
  1172. {
  1173. return -ENOSYS;
  1174. }
  1175. int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
  1176.     void *buffer, size_t *lenp)
  1177. {
  1178. return -ENOSYS;
  1179. }
  1180. int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
  1181.       struct file *filp,
  1182.       void *buffer, size_t *lenp)
  1183. {
  1184.     return -ENOSYS;
  1185. }
  1186. #endif /* CONFIG_PROC_FS */
  1187. /*
  1188.  * General sysctl support routines 
  1189.  */
  1190. /* The generic string strategy routine: */
  1191. int sysctl_string(ctl_table *table, int *name, int nlen,
  1192.   void *oldval, size_t *oldlenp,
  1193.   void *newval, size_t newlen, void **context)
  1194. {
  1195. size_t l, len;
  1196. if (!table->data || !table->maxlen) 
  1197. return -ENOTDIR;
  1198. if (oldval && oldlenp) {
  1199. if(get_user(len, oldlenp))
  1200. return -EFAULT;
  1201. if (len) {
  1202. l = strlen(table->data);
  1203. if (len > l) len = l;
  1204. if (len >= table->maxlen)
  1205. len = table->maxlen;
  1206. if(copy_to_user(oldval, table->data, len))
  1207. return -EFAULT;
  1208. if(put_user(0, ((char *) oldval) + len))
  1209. return -EFAULT;
  1210. if(put_user(len, oldlenp))
  1211. return -EFAULT;
  1212. }
  1213. }
  1214. if (newval && newlen) {
  1215. len = newlen;
  1216. if (len > table->maxlen)
  1217. len = table->maxlen;
  1218. if(copy_from_user(table->data, newval, len))
  1219. return -EFAULT;
  1220. if (len == table->maxlen)
  1221. len--;
  1222. ((char *) table->data)[len] = 0;
  1223. }
  1224. return 0;
  1225. }
  1226. /*
  1227.  * This function makes sure that all of the integers in the vector
  1228.  * are between the minimum and maximum values given in the arrays
  1229.  * table->extra1 and table->extra2, respectively.
  1230.  */
  1231. int sysctl_intvec(ctl_table *table, int *name, int nlen,
  1232. void *oldval, size_t *oldlenp,
  1233. void *newval, size_t newlen, void **context)
  1234. {
  1235. int i, *vec, *min, *max;
  1236. size_t length;
  1237. if (newval && newlen) {
  1238. if (newlen % sizeof(int) != 0)
  1239. return -EINVAL;
  1240. if (!table->extra1 && !table->extra2)
  1241. return 0;
  1242. if (newlen > table->maxlen)
  1243. newlen = table->maxlen;
  1244. length = newlen / sizeof(int);
  1245. vec = (int *) newval;
  1246. min = (int *) table->extra1;
  1247. max = (int *) table->extra2;
  1248. for (i = 0; i < length; i++) {
  1249. int value;
  1250. get_user(value, vec + i);
  1251. if (min && value < min[i])
  1252. return -EINVAL;
  1253. if (max && value > max[i])
  1254. return -EINVAL;
  1255. }
  1256. }
  1257. return 0;
  1258. }
  1259. /* Strategy function to convert jiffies to seconds */ 
  1260. int sysctl_jiffies(ctl_table *table, int *name, int nlen,
  1261. void *oldval, size_t *oldlenp,
  1262. void *newval, size_t newlen, void **context)
  1263. {
  1264. if (oldval) {
  1265. size_t olen;
  1266. if (oldlenp) { 
  1267. if (get_user(olen, oldlenp))
  1268. return -EFAULT;
  1269. if (olen!=sizeof(int))
  1270. return -EINVAL; 
  1271. }
  1272. if (put_user(*(int *)(table->data) / HZ, (int *)oldval) || 
  1273.     (oldlenp && put_user(sizeof(int),oldlenp)))
  1274. return -EFAULT;
  1275. }
  1276. if (newval && newlen) { 
  1277. int new;
  1278. if (newlen != sizeof(int))
  1279. return -EINVAL; 
  1280. if (get_user(new, (int *)newval))
  1281. return -EFAULT;
  1282. *(int *)(table->data) = new*HZ; 
  1283. }
  1284. return 1;
  1285. }
  1286. #else /* CONFIG_SYSCTL */
  1287. extern asmlinkage long sys_sysctl(struct __sysctl_args *args)
  1288. {
  1289. return -ENOSYS;
  1290. }
  1291. int sysctl_string(ctl_table *table, int *name, int nlen,
  1292.   void *oldval, size_t *oldlenp,
  1293.   void *newval, size_t newlen, void **context)
  1294. {
  1295. return -ENOSYS;
  1296. }
  1297. int sysctl_intvec(ctl_table *table, int *name, int nlen,
  1298. void *oldval, size_t *oldlenp,
  1299. void *newval, size_t newlen, void **context)
  1300. {
  1301. return -ENOSYS;
  1302. }
  1303. int sysctl_jiffies(ctl_table *table, int *name, int nlen,
  1304. void *oldval, size_t *oldlenp,
  1305. void *newval, size_t newlen, void **context)
  1306. {
  1307. return -ENOSYS;
  1308. }
  1309. int proc_dostring(ctl_table *table, int write, struct file *filp,
  1310.   void *buffer, size_t *lenp)
  1311. {
  1312. return -ENOSYS;
  1313. }
  1314. int proc_dointvec(ctl_table *table, int write, struct file *filp,
  1315.   void *buffer, size_t *lenp)
  1316. {
  1317. return -ENOSYS;
  1318. }
  1319. int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
  1320. void *buffer, size_t *lenp)
  1321. {
  1322. return -ENOSYS;
  1323. }
  1324. int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
  1325.     void *buffer, size_t *lenp)
  1326. {
  1327. return -ENOSYS;
  1328. }
  1329. int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
  1330.   void *buffer, size_t *lenp)
  1331. {
  1332. return -ENOSYS;
  1333. }
  1334. int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
  1335.     void *buffer, size_t *lenp)
  1336. {
  1337. return -ENOSYS;
  1338. }
  1339. int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
  1340.       struct file *filp,
  1341.       void *buffer, size_t *lenp)
  1342. {
  1343.     return -ENOSYS;
  1344. }
  1345. struct ctl_table_header * register_sysctl_table(ctl_table * table, 
  1346. int insert_at_head)
  1347. {
  1348. return 0;
  1349. }
  1350. void unregister_sysctl_table(struct ctl_table_header * table)
  1351. {
  1352. }
  1353. #endif /* CONFIG_SYSCTL */