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