2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Mike Karels at Berkeley Software Design, Inc.
8 * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD
9 * project, to make these variables more userfriendly.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
41 #include "opt_compat.h"
42 #include "opt_ktrace.h"
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/sysctl.h>
48 #include <sys/malloc.h>
53 #include <sys/mutex.h>
55 #include <sys/sysproto.h>
58 #include <sys/ktrace.h>
63 #include <security/mac/mac_framework.h>
66 #include <vm/vm_extern.h>
68 static MALLOC_DEFINE(M_SYSCTL, "sysctl", "sysctl internal magic");
69 static MALLOC_DEFINE(M_SYSCTLOID, "sysctloid", "sysctl dynamic oids");
70 static MALLOC_DEFINE(M_SYSCTLTMP, "sysctltmp", "sysctl temp output buffer");
73 * The sysctllock protects the MIB tree. It also protects sysctl
74 * contexts used with dynamic sysctls. The sysctl_register_oid() and
75 * sysctl_unregister_oid() routines require the sysctllock to already
76 * be held, so the sysctl_lock() and sysctl_unlock() routines are
77 * provided for the few places in the kernel which need to use that
78 * API rather than using the dynamic API. Use of the dynamic API is
79 * strongly encouraged for most code.
81 * The sysctlmemlock is used to limit the amount of user memory wired for
82 * sysctl requests. This is implemented by serializing any userland
83 * sysctl requests larger than a single page via an exclusive lock.
85 static struct sx sysctllock;
86 static struct sx sysctlmemlock;
88 #define SYSCTL_SLOCK() sx_slock(&sysctllock)
89 #define SYSCTL_SUNLOCK() sx_sunlock(&sysctllock)
90 #define SYSCTL_XLOCK() sx_xlock(&sysctllock)
91 #define SYSCTL_XUNLOCK() sx_xunlock(&sysctllock)
92 #define SYSCTL_ASSERT_XLOCKED() sx_assert(&sysctllock, SA_XLOCKED)
93 #define SYSCTL_ASSERT_LOCKED() sx_assert(&sysctllock, SA_LOCKED)
94 #define SYSCTL_INIT() sx_init(&sysctllock, "sysctl lock")
96 static int sysctl_root(SYSCTL_HANDLER_ARGS);
98 struct sysctl_oid_list sysctl__children; /* root list */
100 static int sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del,
103 static struct sysctl_oid *
104 sysctl_find_oidname(const char *name, struct sysctl_oid_list *list)
106 struct sysctl_oid *oidp;
108 SYSCTL_ASSERT_LOCKED();
109 SLIST_FOREACH(oidp, list, oid_link) {
110 if (strcmp(oidp->oid_name, name) == 0) {
118 * Initialization of the MIB tree.
120 * Order by number in each list.
137 sysctl_register_oid(struct sysctl_oid *oidp)
139 struct sysctl_oid_list *parent = oidp->oid_parent;
140 struct sysctl_oid *p;
141 struct sysctl_oid *q;
144 * First check if another oid with the same name already
145 * exists in the parent's list.
147 SYSCTL_ASSERT_XLOCKED();
148 p = sysctl_find_oidname(oidp->oid_name, parent);
150 if ((p->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
154 printf("can't re-use a leaf (%s)!\n", p->oid_name);
159 * If this oid has a number OID_AUTO, give it a number which
160 * is greater than any current oid.
161 * NOTE: DO NOT change the starting value here, change it in
162 * <sys/sysctl.h>, and make sure it is at least 256 to
163 * accomodate e.g. net.inet.raw as a static sysctl node.
165 if (oidp->oid_number == OID_AUTO) {
166 static int newoid = CTL_AUTO_START;
168 oidp->oid_number = newoid++;
169 if (newoid == 0x7fffffff)
170 panic("out of oids");
173 else if (oidp->oid_number >= CTL_AUTO_START) {
174 /* do not panic; this happens when unregistering sysctl sets */
175 printf("static sysctl oid too high: %d", oidp->oid_number);
180 * Insert the oid into the parent's list in order.
183 SLIST_FOREACH(p, parent, oid_link) {
184 if (oidp->oid_number < p->oid_number)
189 SLIST_INSERT_AFTER(q, oidp, oid_link);
191 SLIST_INSERT_HEAD(parent, oidp, oid_link);
195 sysctl_unregister_oid(struct sysctl_oid *oidp)
197 struct sysctl_oid *p;
200 SYSCTL_ASSERT_XLOCKED();
202 if (oidp->oid_number == OID_AUTO) {
205 SLIST_FOREACH(p, oidp->oid_parent, oid_link) {
207 SLIST_REMOVE(oidp->oid_parent, oidp,
208 sysctl_oid, oid_link);
216 * This can happen when a module fails to register and is
217 * being unloaded afterwards. It should not be a panic()
221 printf("%s: failed to unregister sysctl\n", __func__);
224 /* Initialize a new context to keep track of dynamically added sysctls. */
226 sysctl_ctx_init(struct sysctl_ctx_list *c)
234 * No locking here, the caller is responsible for not adding
235 * new nodes to a context until after this function has
242 /* Free the context, and destroy all dynamic oids registered in this context */
244 sysctl_ctx_free(struct sysctl_ctx_list *clist)
246 struct sysctl_ctx_entry *e, *e1;
251 * First perform a "dry run" to check if it's ok to remove oids.
253 * XXX This algorithm is a hack. But I don't know any
254 * XXX better solution for now...
257 TAILQ_FOREACH(e, clist, link) {
258 error = sysctl_remove_oid_locked(e->entry, 0, 0);
263 * Restore deregistered entries, either from the end,
264 * or from the place where error occured.
265 * e contains the entry that was not unregistered
268 e1 = TAILQ_PREV(e, sysctl_ctx_list, link);
270 e1 = TAILQ_LAST(clist, sysctl_ctx_list);
272 sysctl_register_oid(e1->entry);
273 e1 = TAILQ_PREV(e1, sysctl_ctx_list, link);
279 /* Now really delete the entries */
280 e = TAILQ_FIRST(clist);
282 e1 = TAILQ_NEXT(e, link);
283 error = sysctl_remove_oid_locked(e->entry, 1, 0);
285 panic("sysctl_remove_oid: corrupt tree, entry: %s",
287 free(e, M_SYSCTLOID);
294 /* Add an entry to the context */
295 struct sysctl_ctx_entry *
296 sysctl_ctx_entry_add(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
298 struct sysctl_ctx_entry *e;
300 SYSCTL_ASSERT_XLOCKED();
301 if (clist == NULL || oidp == NULL)
303 e = malloc(sizeof(struct sysctl_ctx_entry), M_SYSCTLOID, M_WAITOK);
305 TAILQ_INSERT_HEAD(clist, e, link);
309 /* Find an entry in the context */
310 struct sysctl_ctx_entry *
311 sysctl_ctx_entry_find(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
313 struct sysctl_ctx_entry *e;
315 SYSCTL_ASSERT_LOCKED();
316 if (clist == NULL || oidp == NULL)
318 TAILQ_FOREACH(e, clist, link) {
326 * Delete an entry from the context.
327 * NOTE: this function doesn't free oidp! You have to remove it
328 * with sysctl_remove_oid().
331 sysctl_ctx_entry_del(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
333 struct sysctl_ctx_entry *e;
335 if (clist == NULL || oidp == NULL)
338 e = sysctl_ctx_entry_find(clist, oidp);
340 TAILQ_REMOVE(clist, e, link);
342 free(e, M_SYSCTLOID);
351 * Remove dynamically created sysctl trees.
352 * oidp - top of the tree to be removed
353 * del - if 0 - just deregister, otherwise free up entries as well
354 * recurse - if != 0 traverse the subtree to be deleted
357 sysctl_remove_oid(struct sysctl_oid *oidp, int del, int recurse)
362 error = sysctl_remove_oid_locked(oidp, del, recurse);
368 sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del, int recurse)
370 struct sysctl_oid *p;
373 SYSCTL_ASSERT_XLOCKED();
376 if ((oidp->oid_kind & CTLFLAG_DYN) == 0) {
377 printf("can't remove non-dynamic nodes!\n");
381 * WARNING: normal method to do this should be through
382 * sysctl_ctx_free(). Use recursing as the last resort
383 * method to purge your sysctl tree of leftovers...
384 * However, if some other code still references these nodes,
387 if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
388 if (oidp->oid_refcnt == 1) {
389 SLIST_FOREACH(p, SYSCTL_CHILDREN(oidp), oid_link) {
392 error = sysctl_remove_oid_locked(p, del,
398 free(SYSCTL_CHILDREN(oidp), M_SYSCTLOID);
401 if (oidp->oid_refcnt > 1 ) {
404 if (oidp->oid_refcnt == 0) {
405 printf("Warning: bad oid_refcnt=%u (%s)!\n",
406 oidp->oid_refcnt, oidp->oid_name);
409 sysctl_unregister_oid(oidp);
412 free((void *)(uintptr_t)(const void *)oidp->oid_descr, M_SYSCTLOID);
413 free((void *)(uintptr_t)(const void *)oidp->oid_name,
415 free(oidp, M_SYSCTLOID);
422 * Create new sysctls at run time.
423 * clist may point to a valid context initialized with sysctl_ctx_init().
426 sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
427 int number, const char *name, int kind, void *arg1, int arg2,
428 int (*handler)(SYSCTL_HANDLER_ARGS), const char *fmt, const char *descr)
430 struct sysctl_oid *oidp;
434 /* You have to hook up somewhere.. */
437 /* Check if the node already exists, otherwise create it */
439 oidp = sysctl_find_oidname(name, parent);
441 if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
443 /* Update the context */
445 sysctl_ctx_entry_add(clist, oidp);
450 printf("can't re-use a leaf (%s)!\n", name);
454 oidp = malloc(sizeof(struct sysctl_oid), M_SYSCTLOID, M_WAITOK|M_ZERO);
455 oidp->oid_parent = parent;
456 SLIST_NEXT(oidp, oid_link) = NULL;
457 oidp->oid_number = number;
458 oidp->oid_refcnt = 1;
460 newname = malloc(len + 1, M_SYSCTLOID, M_WAITOK);
461 bcopy(name, newname, len + 1);
463 oidp->oid_name = newname;
464 oidp->oid_handler = handler;
465 oidp->oid_kind = CTLFLAG_DYN | kind;
466 if ((kind & CTLTYPE) == CTLTYPE_NODE) {
467 /* Allocate space for children */
468 SYSCTL_CHILDREN_SET(oidp, malloc(sizeof(struct sysctl_oid_list),
469 M_SYSCTLOID, M_WAITOK));
470 SLIST_INIT(SYSCTL_CHILDREN(oidp));
472 oidp->oid_arg1 = arg1;
473 oidp->oid_arg2 = arg2;
477 int len = strlen(descr) + 1;
478 oidp->oid_descr = malloc(len, M_SYSCTLOID, M_WAITOK);
480 strcpy((char *)(uintptr_t)(const void *)oidp->oid_descr, descr);
482 /* Update the context, if used */
484 sysctl_ctx_entry_add(clist, oidp);
485 /* Register this oid */
486 sysctl_register_oid(oidp);
492 * Rename an existing oid.
495 sysctl_rename_oid(struct sysctl_oid *oidp, const char *name)
502 newname = malloc(len + 1, M_SYSCTLOID, M_WAITOK);
503 bcopy(name, newname, len + 1);
506 oldname = (void *)(uintptr_t)(const void *)oidp->oid_name;
507 oidp->oid_name = newname;
509 free(oldname, M_SYSCTLOID);
513 * Reparent an existing oid.
516 sysctl_move_oid(struct sysctl_oid *oid, struct sysctl_oid_list *parent)
518 struct sysctl_oid *oidp;
521 if (oid->oid_parent == parent) {
525 oidp = sysctl_find_oidname(oid->oid_name, parent);
530 sysctl_unregister_oid(oid);
531 oid->oid_parent = parent;
532 oid->oid_number = OID_AUTO;
533 sysctl_register_oid(oid);
539 * Register the kernel's oids on startup.
541 SET_DECLARE(sysctl_set, struct sysctl_oid);
544 sysctl_register_all(void *arg)
546 struct sysctl_oid **oidp;
548 sx_init(&sysctlmemlock, "sysctl mem");
551 SET_FOREACH(oidp, sysctl_set)
552 sysctl_register_oid(*oidp);
555 SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_register_all, 0);
560 * These functions implement a presently undocumented interface
561 * used by the sysctl program to walk the tree, and get the type
562 * so it can print the value.
563 * This interface is under work and consideration, and should probably
564 * be killed with a big axe by the first person who can find the time.
565 * (be aware though, that the proper interface isn't as obvious as it
566 * may seem, there are various conflicting requirements.
568 * {0,0} printf the entire MIB-tree.
569 * {0,1,...} return the name of the "..." OID.
570 * {0,2,...} return the next OID.
571 * {0,3} return the OID of the name in "new"
572 * {0,4,...} return the kind & format info for the "..." OID.
573 * {0,5,...} return the description the "..." OID.
578 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list *l, int i)
581 struct sysctl_oid *oidp;
583 SYSCTL_ASSERT_LOCKED();
584 SLIST_FOREACH(oidp, l, oid_link) {
589 printf("%d %s ", oidp->oid_number, oidp->oid_name);
592 oidp->oid_kind & CTLFLAG_RD ? 'R':' ',
593 oidp->oid_kind & CTLFLAG_WR ? 'W':' ');
595 if (oidp->oid_handler)
598 switch (oidp->oid_kind & CTLTYPE) {
601 if (!oidp->oid_handler) {
602 sysctl_sysctl_debug_dump_node(
603 oidp->oid_arg1, i+2);
606 case CTLTYPE_INT: printf(" Int\n"); break;
607 case CTLTYPE_STRING: printf(" String\n"); break;
608 case CTLTYPE_QUAD: printf(" Quad\n"); break;
609 case CTLTYPE_OPAQUE: printf(" Opaque/struct\n"); break;
610 default: printf("\n");
617 sysctl_sysctl_debug(SYSCTL_HANDLER_ARGS)
621 error = priv_check(req->td, PRIV_SYSCTL_DEBUG);
624 sysctl_sysctl_debug_dump_node(&sysctl__children, 0);
628 SYSCTL_PROC(_sysctl, 0, debug, CTLTYPE_STRING|CTLFLAG_RD,
629 0, 0, sysctl_sysctl_debug, "-", "");
633 sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
635 int *name = (int *) arg1;
636 u_int namelen = arg2;
638 struct sysctl_oid *oid;
639 struct sysctl_oid_list *lsp = &sysctl__children, *lsp2;
642 SYSCTL_ASSERT_LOCKED();
645 snprintf(buf,sizeof(buf),"%d",*name);
647 error = SYSCTL_OUT(req, ".", 1);
649 error = SYSCTL_OUT(req, buf, strlen(buf));
657 SLIST_FOREACH(oid, lsp, oid_link) {
658 if (oid->oid_number != *name)
662 error = SYSCTL_OUT(req, ".", 1);
664 error = SYSCTL_OUT(req, oid->oid_name,
665 strlen(oid->oid_name));
672 if ((oid->oid_kind & CTLTYPE) != CTLTYPE_NODE)
675 if (oid->oid_handler)
678 lsp2 = (struct sysctl_oid_list *)oid->oid_arg1;
683 return (SYSCTL_OUT(req, "", 1));
686 static SYSCTL_NODE(_sysctl, 1, name, CTLFLAG_RD, sysctl_sysctl_name, "");
689 sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen,
690 int *next, int *len, int level, struct sysctl_oid **oidpp)
692 struct sysctl_oid *oidp;
694 SYSCTL_ASSERT_LOCKED();
696 SLIST_FOREACH(oidp, lsp, oid_link) {
697 *next = oidp->oid_number;
700 if (oidp->oid_kind & CTLFLAG_SKIP)
704 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
706 if (oidp->oid_handler)
707 /* We really should call the handler here...*/
709 lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
710 if (!sysctl_sysctl_next_ls(lsp, 0, 0, next+1,
711 len, level+1, oidpp))
716 if (oidp->oid_number < *name)
719 if (oidp->oid_number > *name) {
720 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
722 if (oidp->oid_handler)
724 lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
725 if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1,
726 next+1, len, level+1, oidpp))
730 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
733 if (oidp->oid_handler)
736 lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
737 if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, next+1,
738 len, level+1, oidpp))
749 sysctl_sysctl_next(SYSCTL_HANDLER_ARGS)
751 int *name = (int *) arg1;
752 u_int namelen = arg2;
754 struct sysctl_oid *oid;
755 struct sysctl_oid_list *lsp = &sysctl__children;
756 int newoid[CTL_MAXNAME];
758 i = sysctl_sysctl_next_ls(lsp, name, namelen, newoid, &j, 1, &oid);
761 error = SYSCTL_OUT(req, newoid, j * sizeof (int));
765 static SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD, sysctl_sysctl_next, "");
768 name2oid(char *name, int *oid, int *len, struct sysctl_oid **oidpp)
771 struct sysctl_oid *oidp;
772 struct sysctl_oid_list *lsp = &sysctl__children;
775 SYSCTL_ASSERT_LOCKED();
780 p = name + strlen(name) - 1 ;
786 for (p = name; *p && *p != '.'; p++)
792 oidp = SLIST_FIRST(lsp);
794 while (oidp && *len < CTL_MAXNAME) {
795 if (strcmp(name, oidp->oid_name)) {
796 oidp = SLIST_NEXT(oidp, oid_link);
799 *oid++ = oidp->oid_number;
808 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
811 if (oidp->oid_handler)
814 lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
815 oidp = SLIST_FIRST(lsp);
817 for (p = name; *p && *p != '.'; p++)
827 sysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS)
830 int error, oid[CTL_MAXNAME], len;
831 struct sysctl_oid *op = 0;
833 SYSCTL_ASSERT_LOCKED();
837 if (req->newlen >= MAXPATHLEN) /* XXX arbitrary, undocumented */
838 return (ENAMETOOLONG);
840 p = malloc(req->newlen+1, M_SYSCTL, M_WAITOK);
842 error = SYSCTL_IN(req, p, req->newlen);
848 p [req->newlen] = '\0';
850 error = name2oid(p, oid, &len, &op);
857 error = SYSCTL_OUT(req, oid, len * sizeof *oid);
861 SYSCTL_PROC(_sysctl, 3, name2oid, CTLFLAG_RW|CTLFLAG_ANYBODY|CTLFLAG_MPSAFE,
862 0, 0, sysctl_sysctl_name2oid, "I", "");
865 sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS)
867 struct sysctl_oid *oid;
870 error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
876 error = SYSCTL_OUT(req, &oid->oid_kind, sizeof(oid->oid_kind));
879 error = SYSCTL_OUT(req, oid->oid_fmt, strlen(oid->oid_fmt) + 1);
884 static SYSCTL_NODE(_sysctl, 4, oidfmt, CTLFLAG_RD|CTLFLAG_MPSAFE,
885 sysctl_sysctl_oidfmt, "");
888 sysctl_sysctl_oiddescr(SYSCTL_HANDLER_ARGS)
890 struct sysctl_oid *oid;
893 error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
899 error = SYSCTL_OUT(req, oid->oid_descr, strlen(oid->oid_descr) + 1);
903 static SYSCTL_NODE(_sysctl, 5, oiddescr, CTLFLAG_RD, sysctl_sysctl_oiddescr, "");
906 * Default "handler" functions.
910 * Handle an int, signed or unsigned.
912 * a variable: point arg1 at it.
913 * a constant: pass it in arg2.
917 sysctl_handle_int(SYSCTL_HANDLER_ARGS)
919 int tmpout, error = 0;
922 * Attempt to get a coherent snapshot by making a copy of the data.
925 tmpout = *(int *)arg1;
928 error = SYSCTL_OUT(req, &tmpout, sizeof(int));
930 if (error || !req->newptr)
936 error = SYSCTL_IN(req, arg1, sizeof(int));
941 * Based on on sysctl_handle_int() convert milliseconds into ticks.
942 * Note: this is used by TCP.
946 sysctl_msec_to_ticks(SYSCTL_HANDLER_ARGS)
951 s = (int)((int64_t)tt * 1000 / hz);
953 error = sysctl_handle_int(oidp, &s, 0, req);
954 if (error || !req->newptr)
957 tt = (int)((int64_t)s * hz / 1000);
967 * Handle a long, signed or unsigned. arg1 points to it.
971 sysctl_handle_long(SYSCTL_HANDLER_ARGS)
980 * Attempt to get a coherent snapshot by making a copy of the data.
984 tmplong = *(long *)arg1;
986 if (req->flags & SCTL_MASK32) {
988 error = SYSCTL_OUT(req, &tmpint, sizeof(int));
991 error = SYSCTL_OUT(req, &tmplong, sizeof(long));
993 if (error || !req->newptr)
997 if (req->flags & SCTL_MASK32) {
998 error = SYSCTL_IN(req, &tmpint, sizeof(int));
999 *(long *)arg1 = (long)tmpint;
1002 error = SYSCTL_IN(req, arg1, sizeof(long));
1007 * Handle a 64 bit int, signed or unsigned. arg1 points to it.
1011 sysctl_handle_quad(SYSCTL_HANDLER_ARGS)
1017 * Attempt to get a coherent snapshot by making a copy of the data.
1021 tmpout = *(uint64_t *)arg1;
1022 error = SYSCTL_OUT(req, &tmpout, sizeof(uint64_t));
1024 if (error || !req->newptr)
1027 error = SYSCTL_IN(req, arg1, sizeof(uint64_t));
1032 * Handle our generic '\0' terminated 'C' string.
1034 * a variable string: point arg1 at it, arg2 is max length.
1035 * a constant string: point arg1 at it, arg2 is zero.
1039 sysctl_handle_string(SYSCTL_HANDLER_ARGS)
1046 * Attempt to get a coherent snapshot by copying to a
1047 * temporary kernel buffer.
1050 outlen = strlen((char *)arg1)+1;
1051 tmparg = malloc(outlen, M_SYSCTLTMP, M_WAITOK);
1053 if (strlcpy(tmparg, (char *)arg1, outlen) >= outlen) {
1054 free(tmparg, M_SYSCTLTMP);
1058 error = SYSCTL_OUT(req, tmparg, outlen);
1059 free(tmparg, M_SYSCTLTMP);
1061 if (error || !req->newptr)
1064 if ((req->newlen - req->newidx) >= arg2) {
1067 arg2 = (req->newlen - req->newidx);
1068 error = SYSCTL_IN(req, arg1, arg2);
1069 ((char *)arg1)[arg2] = '\0';
1076 * Handle any kind of opaque data.
1077 * arg1 points to it, arg2 is the size.
1081 sysctl_handle_opaque(SYSCTL_HANDLER_ARGS)
1085 struct sysctl_req req2;
1088 * Attempt to get a coherent snapshot, by using the thread
1089 * pre-emption counter updated from within mi_switch() to
1090 * determine if we were pre-empted during a bcopy() or
1091 * copyout(). Make 3 attempts at doing this before giving up.
1092 * If we encounter an error, stop immediately.
1097 generation = curthread->td_generation;
1098 error = SYSCTL_OUT(req, arg1, arg2);
1102 if (generation != curthread->td_generation && tries < 3) {
1107 error = SYSCTL_IN(req, arg1, arg2);
1113 * Transfer functions to/from kernel space.
1114 * XXX: rather untested at this point
1117 sysctl_old_kernel(struct sysctl_req *req, const void *p, size_t l)
1123 if (req->oldlen <= req->oldidx)
1126 if (i > req->oldlen - req->oldidx)
1127 i = req->oldlen - req->oldidx;
1129 bcopy(p, (char *)req->oldptr + req->oldidx, i);
1132 if (req->oldptr && i != l)
1138 sysctl_new_kernel(struct sysctl_req *req, void *p, size_t l)
1142 if (req->newlen - req->newidx < l)
1144 bcopy((char *)req->newptr + req->newidx, p, l);
1150 kernel_sysctl(struct thread *td, int *name, u_int namelen, void *old,
1151 size_t *oldlenp, void *new, size_t newlen, size_t *retval, int flags)
1154 struct sysctl_req req;
1156 bzero(&req, sizeof req);
1162 req.oldlen = *oldlenp;
1164 req.validlen = req.oldlen;
1171 req.newlen = newlen;
1175 req.oldfunc = sysctl_old_kernel;
1176 req.newfunc = sysctl_new_kernel;
1177 req.lock = REQ_LOCKED;
1180 error = sysctl_root(0, name, namelen, &req);
1183 if (req.lock == REQ_WIRED && req.validlen > 0)
1184 vsunlock(req.oldptr, req.validlen);
1186 if (error && error != ENOMEM)
1190 if (req.oldptr && req.oldidx > req.validlen)
1191 *retval = req.validlen;
1193 *retval = req.oldidx;
1199 kernel_sysctlbyname(struct thread *td, char *name, void *old, size_t *oldlenp,
1200 void *new, size_t newlen, size_t *retval, int flags)
1202 int oid[CTL_MAXNAME];
1203 size_t oidlen, plen;
1206 oid[0] = 0; /* sysctl internal magic */
1207 oid[1] = 3; /* name2oid */
1208 oidlen = sizeof(oid);
1210 error = kernel_sysctl(td, oid, 2, oid, &oidlen,
1211 (void *)name, strlen(name), &plen, flags);
1215 error = kernel_sysctl(td, oid, plen / sizeof(int), old, oldlenp,
1216 new, newlen, retval, flags);
1221 * Transfer function to/from user space.
1224 sysctl_old_user(struct sysctl_req *req, const void *p, size_t l)
1227 size_t i, len, origidx;
1229 origidx = req->oldidx;
1231 if (req->oldptr == NULL)
1234 * If we have not wired the user supplied buffer and we are currently
1235 * holding locks, drop a witness warning, as it's possible that
1236 * write operations to the user page can sleep.
1238 if (req->lock != REQ_WIRED)
1239 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
1240 "sysctl_old_user()");
1242 len = req->validlen;
1246 if (i > len - origidx)
1248 error = copyout(p, (char *)req->oldptr + origidx, i);
1258 sysctl_new_user(struct sysctl_req *req, void *p, size_t l)
1264 if (req->newlen - req->newidx < l)
1266 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
1267 "sysctl_new_user()");
1268 error = copyin((char *)req->newptr + req->newidx, p, l);
1274 * Wire the user space destination buffer. If set to a value greater than
1275 * zero, the len parameter limits the maximum amount of wired memory.
1278 sysctl_wire_old_buffer(struct sysctl_req *req, size_t len)
1283 wiredlen = (len > 0 && len < req->oldlen) ? len : req->oldlen;
1285 if (req->lock == REQ_LOCKED && req->oldptr &&
1286 req->oldfunc == sysctl_old_user) {
1287 if (wiredlen != 0) {
1288 ret = vslock(req->oldptr, wiredlen);
1295 req->lock = REQ_WIRED;
1296 req->validlen = wiredlen;
1302 sysctl_find_oid(int *name, u_int namelen, struct sysctl_oid **noid,
1303 int *nindx, struct sysctl_req *req)
1305 struct sysctl_oid *oid;
1308 SYSCTL_ASSERT_LOCKED();
1309 oid = SLIST_FIRST(&sysctl__children);
1311 while (oid && indx < CTL_MAXNAME) {
1312 if (oid->oid_number == name[indx]) {
1314 if (oid->oid_kind & CTLFLAG_NOLOCK)
1315 req->lock = REQ_UNLOCKED;
1316 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
1317 if (oid->oid_handler != NULL ||
1325 (struct sysctl_oid_list *)oid->oid_arg1);
1326 } else if (indx == namelen) {
1335 oid = SLIST_NEXT(oid, oid_link);
1342 * Traverse our tree, and find the right node, execute whatever it points
1343 * to, and return the resulting error code.
1347 sysctl_root(SYSCTL_HANDLER_ARGS)
1349 struct sysctl_oid *oid;
1350 int error, indx, lvl;
1352 SYSCTL_ASSERT_LOCKED();
1354 error = sysctl_find_oid(arg1, arg2, &oid, &indx, req);
1358 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
1360 * You can't call a sysctl when it's a node, but has
1361 * no handler. Inform the user that it's a node.
1362 * The indx may or may not be the same as namelen.
1364 if (oid->oid_handler == NULL)
1368 /* Is this sysctl writable? */
1369 if (req->newptr && !(oid->oid_kind & CTLFLAG_WR))
1372 KASSERT(req->td != NULL, ("sysctl_root(): req->td == NULL"));
1374 /* Is this sysctl sensitive to securelevels? */
1375 if (req->newptr && (oid->oid_kind & CTLFLAG_SECURE)) {
1376 lvl = (oid->oid_kind & CTLMASK_SECURE) >> CTLSHIFT_SECURE;
1377 error = securelevel_gt(req->td->td_ucred, lvl);
1382 /* Is this sysctl writable by only privileged users? */
1383 if (req->newptr && !(oid->oid_kind & CTLFLAG_ANYBODY)) {
1386 if (oid->oid_kind & CTLFLAG_PRISON)
1387 priv = PRIV_SYSCTL_WRITEJAIL;
1389 else if ((oid->oid_kind & CTLFLAG_VNET) &&
1390 prison_owns_vnet(req->td->td_ucred))
1391 priv = PRIV_SYSCTL_WRITEJAIL;
1394 priv = PRIV_SYSCTL_WRITE;
1395 error = priv_check(req->td, priv);
1400 if (!oid->oid_handler)
1403 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
1404 arg1 = (int *)arg1 + indx;
1407 arg1 = oid->oid_arg1;
1408 arg2 = oid->oid_arg2;
1411 error = mac_system_check_sysctl(req->td->td_ucred, oid, arg1, arg2,
1416 if (!(oid->oid_kind & CTLFLAG_MPSAFE))
1418 error = oid->oid_handler(oid, arg1, arg2, req);
1419 if (!(oid->oid_kind & CTLFLAG_MPSAFE))
1425 #ifndef _SYS_SYSPROTO_H_
1426 struct sysctl_args {
1436 __sysctl(struct thread *td, struct sysctl_args *uap)
1438 int error, i, name[CTL_MAXNAME];
1441 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1444 error = copyin(uap->name, &name, uap->namelen * sizeof(int));
1448 error = userland_sysctl(td, name, uap->namelen,
1449 uap->old, uap->oldlenp, 0,
1450 uap->new, uap->newlen, &j, 0);
1451 if (error && error != ENOMEM)
1454 i = copyout(&j, uap->oldlenp, sizeof(j));
1462 * This is used from various compatibility syscalls too. That's why name
1463 * must be in kernel space.
1466 userland_sysctl(struct thread *td, int *name, u_int namelen, void *old,
1467 size_t *oldlenp, int inkernel, void *new, size_t newlen, size_t *retval,
1470 int error = 0, memlocked;
1471 struct sysctl_req req;
1473 bzero(&req, sizeof req);
1480 req.oldlen = *oldlenp;
1482 error = copyin(oldlenp, &req.oldlen, sizeof(*oldlenp));
1487 req.validlen = req.oldlen;
1490 if (!useracc(old, req.oldlen, VM_PROT_WRITE))
1496 if (!useracc(new, newlen, VM_PROT_READ))
1498 req.newlen = newlen;
1502 req.oldfunc = sysctl_old_user;
1503 req.newfunc = sysctl_new_user;
1504 req.lock = REQ_LOCKED;
1507 if (KTRPOINT(curthread, KTR_SYSCTL))
1508 ktrsysctl(name, namelen);
1511 if (req.oldlen > PAGE_SIZE) {
1513 sx_xlock(&sysctlmemlock);
1516 CURVNET_SET(TD_TO_VNET(td));
1522 error = sysctl_root(0, name, namelen, &req);
1524 if (error != EAGAIN)
1531 if (req.lock == REQ_WIRED && req.validlen > 0)
1532 vsunlock(req.oldptr, req.validlen);
1534 sx_xunlock(&sysctlmemlock);
1536 if (error && error != ENOMEM)
1540 if (req.oldptr && req.oldidx > req.validlen)
1541 *retval = req.validlen;
1543 *retval = req.oldidx;