]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/kern/kern_sysctl.c
Merge ACPICA 20191018.
[FreeBSD/FreeBSD.git] / sys / kern / kern_sysctl.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1982, 1986, 1989, 1993
5  *      The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Mike Karels at Berkeley Software Design, Inc.
9  *
10  * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD
11  * project, to make these variables more userfriendly.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  *      @(#)kern_sysctl.c       8.4 (Berkeley) 4/14/94
38  */
39
40 #include <sys/cdefs.h>
41 __FBSDID("$FreeBSD$");
42
43 #include "opt_capsicum.h"
44 #include "opt_ddb.h"
45 #include "opt_ktrace.h"
46
47 #include <sys/param.h>
48 #include <sys/fail.h>
49 #include <sys/systm.h>
50 #include <sys/capsicum.h>
51 #include <sys/kernel.h>
52 #include <sys/limits.h>
53 #include <sys/sysctl.h>
54 #include <sys/malloc.h>
55 #include <sys/priv.h>
56 #include <sys/proc.h>
57 #include <sys/jail.h>
58 #include <sys/kdb.h>
59 #include <sys/lock.h>
60 #include <sys/mutex.h>
61 #include <sys/rmlock.h>
62 #include <sys/sbuf.h>
63 #include <sys/sx.h>
64 #include <sys/sysproto.h>
65 #include <sys/uio.h>
66 #ifdef KTRACE
67 #include <sys/ktrace.h>
68 #endif
69
70 #ifdef DDB
71 #include <ddb/ddb.h>
72 #include <ddb/db_lex.h>
73 #endif
74
75 #include <net/vnet.h>
76
77 #include <security/mac/mac_framework.h>
78
79 #include <vm/vm.h>
80 #include <vm/vm_extern.h>
81
82 static MALLOC_DEFINE(M_SYSCTL, "sysctl", "sysctl internal magic");
83 static MALLOC_DEFINE(M_SYSCTLOID, "sysctloid", "sysctl dynamic oids");
84 static MALLOC_DEFINE(M_SYSCTLTMP, "sysctltmp", "sysctl temp output buffer");
85
86 /*
87  * The sysctllock protects the MIB tree.  It also protects sysctl
88  * contexts used with dynamic sysctls.  The sysctl_register_oid() and
89  * sysctl_unregister_oid() routines require the sysctllock to already
90  * be held, so the sysctl_wlock() and sysctl_wunlock() routines are
91  * provided for the few places in the kernel which need to use that
92  * API rather than using the dynamic API.  Use of the dynamic API is
93  * strongly encouraged for most code.
94  *
95  * The sysctlmemlock is used to limit the amount of user memory wired for
96  * sysctl requests.  This is implemented by serializing any userland
97  * sysctl requests larger than a single page via an exclusive lock.
98  */
99 static struct rmlock sysctllock;
100 static struct sx __exclusive_cache_line sysctlmemlock;
101
102 #define SYSCTL_WLOCK()          rm_wlock(&sysctllock)
103 #define SYSCTL_WUNLOCK()        rm_wunlock(&sysctllock)
104 #define SYSCTL_RLOCK(tracker)   rm_rlock(&sysctllock, (tracker))
105 #define SYSCTL_RUNLOCK(tracker) rm_runlock(&sysctllock, (tracker))
106 #define SYSCTL_WLOCKED()        rm_wowned(&sysctllock)
107 #define SYSCTL_ASSERT_LOCKED()  rm_assert(&sysctllock, RA_LOCKED)
108 #define SYSCTL_ASSERT_WLOCKED() rm_assert(&sysctllock, RA_WLOCKED)
109 #define SYSCTL_ASSERT_RLOCKED() rm_assert(&sysctllock, RA_RLOCKED)
110 #define SYSCTL_INIT()           rm_init_flags(&sysctllock, "sysctl lock", \
111                                     RM_SLEEPABLE)
112 #define SYSCTL_SLEEP(ch, wmesg, timo)                                   \
113                                 rm_sleep(ch, &sysctllock, 0, wmesg, timo)
114
115 static int sysctl_root(SYSCTL_HANDLER_ARGS);
116
117 /* Root list */
118 struct sysctl_oid_list sysctl__children = SLIST_HEAD_INITIALIZER(&sysctl__children);
119
120 static int      sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del,
121                     int recurse);
122 static int      sysctl_old_kernel(struct sysctl_req *, const void *, size_t);
123 static int      sysctl_new_kernel(struct sysctl_req *, void *, size_t);
124
125 static struct sysctl_oid *
126 sysctl_find_oidname(const char *name, struct sysctl_oid_list *list)
127 {
128         struct sysctl_oid *oidp;
129
130         SYSCTL_ASSERT_LOCKED();
131         SLIST_FOREACH(oidp, list, oid_link) {
132                 if (strcmp(oidp->oid_name, name) == 0) {
133                         return (oidp);
134                 }
135         }
136         return (NULL);
137 }
138
139 /*
140  * Initialization of the MIB tree.
141  *
142  * Order by number in each list.
143  */
144 void
145 sysctl_wlock(void)
146 {
147
148         SYSCTL_WLOCK();
149 }
150
151 void
152 sysctl_wunlock(void)
153 {
154
155         SYSCTL_WUNLOCK();
156 }
157
158 static int
159 sysctl_root_handler_locked(struct sysctl_oid *oid, void *arg1, intmax_t arg2,
160     struct sysctl_req *req, struct rm_priotracker *tracker)
161 {
162         int error;
163
164         if (oid->oid_kind & CTLFLAG_DYN)
165                 atomic_add_int(&oid->oid_running, 1);
166
167         if (tracker != NULL)
168                 SYSCTL_RUNLOCK(tracker);
169         else
170                 SYSCTL_WUNLOCK();
171
172         if (!(oid->oid_kind & CTLFLAG_MPSAFE))
173                 mtx_lock(&Giant);
174         error = oid->oid_handler(oid, arg1, arg2, req);
175         if (!(oid->oid_kind & CTLFLAG_MPSAFE))
176                 mtx_unlock(&Giant);
177
178         KFAIL_POINT_ERROR(_debug_fail_point, sysctl_running, error);
179
180         if (tracker != NULL)
181                 SYSCTL_RLOCK(tracker);
182         else
183                 SYSCTL_WLOCK();
184
185         if (oid->oid_kind & CTLFLAG_DYN) {
186                 if (atomic_fetchadd_int(&oid->oid_running, -1) == 1 &&
187                     (oid->oid_kind & CTLFLAG_DYING) != 0)
188                         wakeup(&oid->oid_running);
189         }
190
191         return (error);
192 }
193
194 static void
195 sysctl_load_tunable_by_oid_locked(struct sysctl_oid *oidp)
196 {
197         struct sysctl_req req;
198         struct sysctl_oid *curr;
199         char *penv = NULL;
200         char path[96];
201         ssize_t rem = sizeof(path);
202         ssize_t len;
203         uint8_t data[512] __aligned(sizeof(uint64_t));
204         int size;
205         int error;
206
207         path[--rem] = 0;
208
209         for (curr = oidp; curr != NULL; curr = SYSCTL_PARENT(curr)) {
210                 len = strlen(curr->oid_name);
211                 rem -= len;
212                 if (curr != oidp)
213                         rem -= 1;
214                 if (rem < 0) {
215                         printf("OID path exceeds %d bytes\n", (int)sizeof(path));
216                         return;
217                 }
218                 memcpy(path + rem, curr->oid_name, len);
219                 if (curr != oidp)
220                         path[rem + len] = '.';
221         }
222
223         memset(&req, 0, sizeof(req));
224
225         req.td = curthread;
226         req.oldfunc = sysctl_old_kernel;
227         req.newfunc = sysctl_new_kernel;
228         req.lock = REQ_UNWIRED;
229
230         switch (oidp->oid_kind & CTLTYPE) {
231         case CTLTYPE_INT:
232                 if (getenv_array(path + rem, data, sizeof(data), &size,
233                     sizeof(int), GETENV_SIGNED) == 0)
234                         return;
235                 req.newlen = size;
236                 req.newptr = data;
237                 break;
238         case CTLTYPE_UINT:
239                 if (getenv_array(path + rem, data, sizeof(data), &size,
240                     sizeof(int), GETENV_UNSIGNED) == 0)
241                         return;
242                 req.newlen = size;
243                 req.newptr = data;
244                 break;
245         case CTLTYPE_LONG:
246                 if (getenv_array(path + rem, data, sizeof(data), &size,
247                     sizeof(long), GETENV_SIGNED) == 0)
248                         return;
249                 req.newlen = size;
250                 req.newptr = data;
251                 break;
252         case CTLTYPE_ULONG:
253                 if (getenv_array(path + rem, data, sizeof(data), &size,
254                     sizeof(long), GETENV_UNSIGNED) == 0)
255                         return;
256                 req.newlen = size;
257                 req.newptr = data;
258                 break;
259         case CTLTYPE_S8:
260                 if (getenv_array(path + rem, data, sizeof(data), &size,
261                     sizeof(int8_t), GETENV_SIGNED) == 0)
262                         return;
263                 req.newlen = size;
264                 req.newptr = data;
265                 break;
266         case CTLTYPE_S16:
267                 if (getenv_array(path + rem, data, sizeof(data), &size,
268                     sizeof(int16_t), GETENV_SIGNED) == 0)
269                         return;
270                 req.newlen = size;
271                 req.newptr = data;
272                 break;
273         case CTLTYPE_S32:
274                 if (getenv_array(path + rem, data, sizeof(data), &size,
275                     sizeof(int32_t), GETENV_SIGNED) == 0)
276                         return;
277                 req.newlen = size;
278                 req.newptr = data;
279                 break;
280         case CTLTYPE_S64:
281                 if (getenv_array(path + rem, data, sizeof(data), &size,
282                     sizeof(int64_t), GETENV_SIGNED) == 0)
283                         return;
284                 req.newlen = size;
285                 req.newptr = data;
286                 break;
287         case CTLTYPE_U8:
288                 if (getenv_array(path + rem, data, sizeof(data), &size,
289                     sizeof(uint8_t), GETENV_UNSIGNED) == 0)
290                         return;
291                 req.newlen = size;
292                 req.newptr = data;
293                 break;
294         case CTLTYPE_U16:
295                 if (getenv_array(path + rem, data, sizeof(data), &size,
296                     sizeof(uint16_t), GETENV_UNSIGNED) == 0)
297                         return;
298                 req.newlen = size;
299                 req.newptr = data;
300                 break;
301         case CTLTYPE_U32:
302                 if (getenv_array(path + rem, data, sizeof(data), &size,
303                     sizeof(uint32_t), GETENV_UNSIGNED) == 0)
304                         return;
305                 req.newlen = size;
306                 req.newptr = data;
307                 break;
308         case CTLTYPE_U64:
309                 if (getenv_array(path + rem, data, sizeof(data), &size,
310                     sizeof(uint64_t), GETENV_UNSIGNED) == 0)
311                         return;
312                 req.newlen = size;
313                 req.newptr = data;
314                 break;
315         case CTLTYPE_STRING:
316                 penv = kern_getenv(path + rem);
317                 if (penv == NULL)
318                         return;
319                 req.newlen = strlen(penv);
320                 req.newptr = penv;
321                 break;
322         default:
323                 return;
324         }
325         error = sysctl_root_handler_locked(oidp, oidp->oid_arg1,
326             oidp->oid_arg2, &req, NULL);
327         if (error != 0)
328                 printf("Setting sysctl %s failed: %d\n", path + rem, error);
329         if (penv != NULL)
330                 freeenv(penv);
331 }
332
333 /*
334  * Locate the path to a given oid.  Returns the length of the resulting path,
335  * or -1 if the oid was not found.  nodes must have room for CTL_MAXNAME
336  * elements and be NULL initialized.
337  */
338 static int
339 sysctl_search_oid(struct sysctl_oid **nodes, struct sysctl_oid *needle)
340 {
341         int indx;
342
343         SYSCTL_ASSERT_LOCKED();
344         indx = 0;
345         while (indx < CTL_MAXNAME && indx >= 0) {
346                 if (nodes[indx] == NULL && indx == 0)
347                         nodes[indx] = SLIST_FIRST(&sysctl__children);
348                 else if (nodes[indx] == NULL)
349                         nodes[indx] = SLIST_FIRST(&nodes[indx - 1]->oid_children);
350                 else
351                         nodes[indx] = SLIST_NEXT(nodes[indx], oid_link);
352
353                 if (nodes[indx] == needle)
354                         return (indx + 1);
355
356                 if (nodes[indx] == NULL) {
357                         indx--;
358                         continue;
359                 }
360
361                 if ((nodes[indx]->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
362                         indx++;
363                         continue;
364                 }
365         }
366         return (-1);
367 }
368
369 static void
370 sysctl_warn_reuse(const char *func, struct sysctl_oid *leaf)
371 {
372         struct sysctl_oid *nodes[CTL_MAXNAME];
373         char buf[128];
374         struct sbuf sb;
375         int rc, i;
376
377         (void)sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN | SBUF_INCLUDENUL);
378         sbuf_set_drain(&sb, sbuf_printf_drain, NULL);
379
380         sbuf_printf(&sb, "%s: can't re-use a leaf (", __func__);
381
382         memset(nodes, 0, sizeof(nodes));
383         rc = sysctl_search_oid(nodes, leaf);
384         if (rc > 0) {
385                 for (i = 0; i < rc; i++)
386                         sbuf_printf(&sb, "%s%.*s", nodes[i]->oid_name,
387                             i != (rc - 1), ".");
388         } else {
389                 sbuf_printf(&sb, "%s", leaf->oid_name);
390         }
391         sbuf_printf(&sb, ")!\n");
392
393         (void)sbuf_finish(&sb);
394 }
395
396 #ifdef SYSCTL_DEBUG
397 static int
398 sysctl_reuse_test(SYSCTL_HANDLER_ARGS)
399 {
400         struct rm_priotracker tracker;
401
402         SYSCTL_RLOCK(&tracker);
403         sysctl_warn_reuse(__func__, oidp);
404         SYSCTL_RUNLOCK(&tracker);
405         return (0);
406 }
407 SYSCTL_PROC(_sysctl, 0, reuse_test, CTLTYPE_STRING|CTLFLAG_RD|CTLFLAG_MPSAFE,
408         0, 0, sysctl_reuse_test, "-", "");
409 #endif
410
411 void
412 sysctl_register_oid(struct sysctl_oid *oidp)
413 {
414         struct sysctl_oid_list *parent = oidp->oid_parent;
415         struct sysctl_oid *p;
416         struct sysctl_oid *q;
417         int oid_number;
418         int timeout = 2;
419
420         /*
421          * First check if another oid with the same name already
422          * exists in the parent's list.
423          */
424         SYSCTL_ASSERT_WLOCKED();
425         p = sysctl_find_oidname(oidp->oid_name, parent);
426         if (p != NULL) {
427                 if ((p->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
428                         p->oid_refcnt++;
429                         return;
430                 } else {
431                         sysctl_warn_reuse(__func__, p);
432                         return;
433                 }
434         }
435         /* get current OID number */
436         oid_number = oidp->oid_number;
437
438 #if (OID_AUTO >= 0)
439 #error "OID_AUTO is expected to be a negative value"
440 #endif  
441         /*
442          * Any negative OID number qualifies as OID_AUTO. Valid OID
443          * numbers should always be positive.
444          *
445          * NOTE: DO NOT change the starting value here, change it in
446          * <sys/sysctl.h>, and make sure it is at least 256 to
447          * accommodate e.g. net.inet.raw as a static sysctl node.
448          */
449         if (oid_number < 0) {
450                 static int newoid;
451
452                 /*
453                  * By decrementing the next OID number we spend less
454                  * time inserting the OIDs into a sorted list.
455                  */
456                 if (--newoid < CTL_AUTO_START)
457                         newoid = 0x7fffffff;
458
459                 oid_number = newoid;
460         }
461
462         /*
463          * Insert the OID into the parent's list sorted by OID number.
464          */
465 retry:
466         q = NULL;
467         SLIST_FOREACH(p, parent, oid_link) {
468                 /* check if the current OID number is in use */
469                 if (oid_number == p->oid_number) {
470                         /* get the next valid OID number */
471                         if (oid_number < CTL_AUTO_START ||
472                             oid_number == 0x7fffffff) {
473                                 /* wraparound - restart */
474                                 oid_number = CTL_AUTO_START;
475                                 /* don't loop forever */
476                                 if (!timeout--)
477                                         panic("sysctl: Out of OID numbers\n");
478                                 goto retry;
479                         } else {
480                                 oid_number++;
481                         }
482                 } else if (oid_number < p->oid_number)
483                         break;
484                 q = p;
485         }
486         /* check for non-auto OID number collision */
487         if (oidp->oid_number >= 0 && oidp->oid_number < CTL_AUTO_START &&
488             oid_number >= CTL_AUTO_START) {
489                 printf("sysctl: OID number(%d) is already in use for '%s'\n",
490                     oidp->oid_number, oidp->oid_name);
491         }
492         /* update the OID number, if any */
493         oidp->oid_number = oid_number;
494         if (q != NULL)
495                 SLIST_INSERT_AFTER(q, oidp, oid_link);
496         else
497                 SLIST_INSERT_HEAD(parent, oidp, oid_link);
498
499         if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE &&
500 #ifdef VIMAGE
501             (oidp->oid_kind & CTLFLAG_VNET) == 0 &&
502 #endif
503             (oidp->oid_kind & CTLFLAG_TUN) != 0 &&
504             (oidp->oid_kind & CTLFLAG_NOFETCH) == 0) {
505                 /* only fetch value once */
506                 oidp->oid_kind |= CTLFLAG_NOFETCH;
507                 /* try to fetch value from kernel environment */
508                 sysctl_load_tunable_by_oid_locked(oidp);
509         }
510 }
511
512 void
513 sysctl_register_disabled_oid(struct sysctl_oid *oidp)
514 {
515
516         /*
517          * Mark the leaf as dormant if it's not to be immediately enabled.
518          * We do not disable nodes as they can be shared between modules
519          * and it is always safe to access a node.
520          */
521         KASSERT((oidp->oid_kind & CTLFLAG_DORMANT) == 0,
522             ("internal flag is set in oid_kind"));
523         if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
524                 oidp->oid_kind |= CTLFLAG_DORMANT;
525         sysctl_register_oid(oidp);
526 }
527
528 void
529 sysctl_enable_oid(struct sysctl_oid *oidp)
530 {
531
532         SYSCTL_ASSERT_WLOCKED();
533         if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
534                 KASSERT((oidp->oid_kind & CTLFLAG_DORMANT) == 0,
535                     ("sysctl node is marked as dormant"));
536                 return;
537         }
538         KASSERT((oidp->oid_kind & CTLFLAG_DORMANT) != 0,
539             ("enabling already enabled sysctl oid"));
540         oidp->oid_kind &= ~CTLFLAG_DORMANT;
541 }
542
543 void
544 sysctl_unregister_oid(struct sysctl_oid *oidp)
545 {
546         struct sysctl_oid *p;
547         int error;
548
549         SYSCTL_ASSERT_WLOCKED();
550         if (oidp->oid_number == OID_AUTO) {
551                 error = EINVAL;
552         } else {
553                 error = ENOENT;
554                 SLIST_FOREACH(p, oidp->oid_parent, oid_link) {
555                         if (p == oidp) {
556                                 SLIST_REMOVE(oidp->oid_parent, oidp,
557                                     sysctl_oid, oid_link);
558                                 error = 0;
559                                 break;
560                         }
561                 }
562         }
563
564         /* 
565          * This can happen when a module fails to register and is
566          * being unloaded afterwards.  It should not be a panic()
567          * for normal use.
568          */
569         if (error) {
570                 printf("%s: failed(%d) to unregister sysctl(%s)\n",
571                     __func__, error, oidp->oid_name);
572         }
573 }
574
575 /* Initialize a new context to keep track of dynamically added sysctls. */
576 int
577 sysctl_ctx_init(struct sysctl_ctx_list *c)
578 {
579
580         if (c == NULL) {
581                 return (EINVAL);
582         }
583
584         /*
585          * No locking here, the caller is responsible for not adding
586          * new nodes to a context until after this function has
587          * returned.
588          */
589         TAILQ_INIT(c);
590         return (0);
591 }
592
593 /* Free the context, and destroy all dynamic oids registered in this context */
594 int
595 sysctl_ctx_free(struct sysctl_ctx_list *clist)
596 {
597         struct sysctl_ctx_entry *e, *e1;
598         int error;
599
600         error = 0;
601         /*
602          * First perform a "dry run" to check if it's ok to remove oids.
603          * XXX FIXME
604          * XXX This algorithm is a hack. But I don't know any
605          * XXX better solution for now...
606          */
607         SYSCTL_WLOCK();
608         TAILQ_FOREACH(e, clist, link) {
609                 error = sysctl_remove_oid_locked(e->entry, 0, 0);
610                 if (error)
611                         break;
612         }
613         /*
614          * Restore deregistered entries, either from the end,
615          * or from the place where error occurred.
616          * e contains the entry that was not unregistered
617          */
618         if (error)
619                 e1 = TAILQ_PREV(e, sysctl_ctx_list, link);
620         else
621                 e1 = TAILQ_LAST(clist, sysctl_ctx_list);
622         while (e1 != NULL) {
623                 sysctl_register_oid(e1->entry);
624                 e1 = TAILQ_PREV(e1, sysctl_ctx_list, link);
625         }
626         if (error) {
627                 SYSCTL_WUNLOCK();
628                 return(EBUSY);
629         }
630         /* Now really delete the entries */
631         e = TAILQ_FIRST(clist);
632         while (e != NULL) {
633                 e1 = TAILQ_NEXT(e, link);
634                 error = sysctl_remove_oid_locked(e->entry, 1, 0);
635                 if (error)
636                         panic("sysctl_remove_oid: corrupt tree, entry: %s",
637                             e->entry->oid_name);
638                 free(e, M_SYSCTLOID);
639                 e = e1;
640         }
641         SYSCTL_WUNLOCK();
642         return (error);
643 }
644
645 /* Add an entry to the context */
646 struct sysctl_ctx_entry *
647 sysctl_ctx_entry_add(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
648 {
649         struct sysctl_ctx_entry *e;
650
651         SYSCTL_ASSERT_WLOCKED();
652         if (clist == NULL || oidp == NULL)
653                 return(NULL);
654         e = malloc(sizeof(struct sysctl_ctx_entry), M_SYSCTLOID, M_WAITOK);
655         e->entry = oidp;
656         TAILQ_INSERT_HEAD(clist, e, link);
657         return (e);
658 }
659
660 /* Find an entry in the context */
661 struct sysctl_ctx_entry *
662 sysctl_ctx_entry_find(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
663 {
664         struct sysctl_ctx_entry *e;
665
666         SYSCTL_ASSERT_WLOCKED();
667         if (clist == NULL || oidp == NULL)
668                 return(NULL);
669         TAILQ_FOREACH(e, clist, link) {
670                 if(e->entry == oidp)
671                         return(e);
672         }
673         return (e);
674 }
675
676 /*
677  * Delete an entry from the context.
678  * NOTE: this function doesn't free oidp! You have to remove it
679  * with sysctl_remove_oid().
680  */
681 int
682 sysctl_ctx_entry_del(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
683 {
684         struct sysctl_ctx_entry *e;
685
686         if (clist == NULL || oidp == NULL)
687                 return (EINVAL);
688         SYSCTL_WLOCK();
689         e = sysctl_ctx_entry_find(clist, oidp);
690         if (e != NULL) {
691                 TAILQ_REMOVE(clist, e, link);
692                 SYSCTL_WUNLOCK();
693                 free(e, M_SYSCTLOID);
694                 return (0);
695         } else {
696                 SYSCTL_WUNLOCK();
697                 return (ENOENT);
698         }
699 }
700
701 /*
702  * Remove dynamically created sysctl trees.
703  * oidp - top of the tree to be removed
704  * del - if 0 - just deregister, otherwise free up entries as well
705  * recurse - if != 0 traverse the subtree to be deleted
706  */
707 int
708 sysctl_remove_oid(struct sysctl_oid *oidp, int del, int recurse)
709 {
710         int error;
711
712         SYSCTL_WLOCK();
713         error = sysctl_remove_oid_locked(oidp, del, recurse);
714         SYSCTL_WUNLOCK();
715         return (error);
716 }
717
718 int
719 sysctl_remove_name(struct sysctl_oid *parent, const char *name,
720     int del, int recurse)
721 {
722         struct sysctl_oid *p, *tmp;
723         int error;
724
725         error = ENOENT;
726         SYSCTL_WLOCK();
727         SLIST_FOREACH_SAFE(p, SYSCTL_CHILDREN(parent), oid_link, tmp) {
728                 if (strcmp(p->oid_name, name) == 0) {
729                         error = sysctl_remove_oid_locked(p, del, recurse);
730                         break;
731                 }
732         }
733         SYSCTL_WUNLOCK();
734
735         return (error);
736 }
737
738
739 static int
740 sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del, int recurse)
741 {
742         struct sysctl_oid *p, *tmp;
743         int error;
744
745         SYSCTL_ASSERT_WLOCKED();
746         if (oidp == NULL)
747                 return(EINVAL);
748         if ((oidp->oid_kind & CTLFLAG_DYN) == 0) {
749                 printf("Warning: can't remove non-dynamic nodes (%s)!\n",
750                     oidp->oid_name);
751                 return (EINVAL);
752         }
753         /*
754          * WARNING: normal method to do this should be through
755          * sysctl_ctx_free(). Use recursing as the last resort
756          * method to purge your sysctl tree of leftovers...
757          * However, if some other code still references these nodes,
758          * it will panic.
759          */
760         if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
761                 if (oidp->oid_refcnt == 1) {
762                         SLIST_FOREACH_SAFE(p,
763                             SYSCTL_CHILDREN(oidp), oid_link, tmp) {
764                                 if (!recurse) {
765                                         printf("Warning: failed attempt to "
766                                             "remove oid %s with child %s\n",
767                                             oidp->oid_name, p->oid_name);
768                                         return (ENOTEMPTY);
769                                 }
770                                 error = sysctl_remove_oid_locked(p, del,
771                                     recurse);
772                                 if (error)
773                                         return (error);
774                         }
775                 }
776         }
777         if (oidp->oid_refcnt > 1 ) {
778                 oidp->oid_refcnt--;
779         } else {
780                 if (oidp->oid_refcnt == 0) {
781                         printf("Warning: bad oid_refcnt=%u (%s)!\n",
782                                 oidp->oid_refcnt, oidp->oid_name);
783                         return (EINVAL);
784                 }
785                 sysctl_unregister_oid(oidp);
786                 if (del) {
787                         /*
788                          * Wait for all threads running the handler to drain.
789                          * This preserves the previous behavior when the
790                          * sysctl lock was held across a handler invocation,
791                          * and is necessary for module unload correctness.
792                          */
793                         while (oidp->oid_running > 0) {
794                                 oidp->oid_kind |= CTLFLAG_DYING;
795                                 SYSCTL_SLEEP(&oidp->oid_running, "oidrm", 0);
796                         }
797                         if (oidp->oid_descr)
798                                 free(__DECONST(char *, oidp->oid_descr),
799                                     M_SYSCTLOID);
800                         if (oidp->oid_label)
801                                 free(__DECONST(char *, oidp->oid_label),
802                                     M_SYSCTLOID);
803                         free(__DECONST(char *, oidp->oid_name), M_SYSCTLOID);
804                         free(oidp, M_SYSCTLOID);
805                 }
806         }
807         return (0);
808 }
809 /*
810  * Create new sysctls at run time.
811  * clist may point to a valid context initialized with sysctl_ctx_init().
812  */
813 struct sysctl_oid *
814 sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
815         int number, const char *name, int kind, void *arg1, intmax_t arg2,
816         int (*handler)(SYSCTL_HANDLER_ARGS), const char *fmt, const char *descr,
817         const char *label)
818 {
819         struct sysctl_oid *oidp;
820
821         /* You have to hook up somewhere.. */
822         if (parent == NULL)
823                 return(NULL);
824         /* Check if the node already exists, otherwise create it */
825         SYSCTL_WLOCK();
826         oidp = sysctl_find_oidname(name, parent);
827         if (oidp != NULL) {
828                 if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
829                         oidp->oid_refcnt++;
830                         /* Update the context */
831                         if (clist != NULL)
832                                 sysctl_ctx_entry_add(clist, oidp);
833                         SYSCTL_WUNLOCK();
834                         return (oidp);
835                 } else {
836                         sysctl_warn_reuse(__func__, oidp);
837                         SYSCTL_WUNLOCK();
838                         return (NULL);
839                 }
840         }
841         oidp = malloc(sizeof(struct sysctl_oid), M_SYSCTLOID, M_WAITOK|M_ZERO);
842         oidp->oid_parent = parent;
843         SLIST_INIT(&oidp->oid_children);
844         oidp->oid_number = number;
845         oidp->oid_refcnt = 1;
846         oidp->oid_name = strdup(name, M_SYSCTLOID);
847         oidp->oid_handler = handler;
848         oidp->oid_kind = CTLFLAG_DYN | kind;
849         oidp->oid_arg1 = arg1;
850         oidp->oid_arg2 = arg2;
851         oidp->oid_fmt = fmt;
852         if (descr != NULL)
853                 oidp->oid_descr = strdup(descr, M_SYSCTLOID);
854         if (label != NULL)
855                 oidp->oid_label = strdup(label, M_SYSCTLOID);
856         /* Update the context, if used */
857         if (clist != NULL)
858                 sysctl_ctx_entry_add(clist, oidp);
859         /* Register this oid */
860         sysctl_register_oid(oidp);
861         SYSCTL_WUNLOCK();
862         return (oidp);
863 }
864
865 /*
866  * Rename an existing oid.
867  */
868 void
869 sysctl_rename_oid(struct sysctl_oid *oidp, const char *name)
870 {
871         char *newname;
872         char *oldname;
873
874         newname = strdup(name, M_SYSCTLOID);
875         SYSCTL_WLOCK();
876         oldname = __DECONST(char *, oidp->oid_name);
877         oidp->oid_name = newname;
878         SYSCTL_WUNLOCK();
879         free(oldname, M_SYSCTLOID);
880 }
881
882 /*
883  * Reparent an existing oid.
884  */
885 int
886 sysctl_move_oid(struct sysctl_oid *oid, struct sysctl_oid_list *parent)
887 {
888         struct sysctl_oid *oidp;
889
890         SYSCTL_WLOCK();
891         if (oid->oid_parent == parent) {
892                 SYSCTL_WUNLOCK();
893                 return (0);
894         }
895         oidp = sysctl_find_oidname(oid->oid_name, parent);
896         if (oidp != NULL) {
897                 SYSCTL_WUNLOCK();
898                 return (EEXIST);
899         }
900         sysctl_unregister_oid(oid);
901         oid->oid_parent = parent;
902         oid->oid_number = OID_AUTO;
903         sysctl_register_oid(oid);
904         SYSCTL_WUNLOCK();
905         return (0);
906 }
907
908 /*
909  * Register the kernel's oids on startup.
910  */
911 SET_DECLARE(sysctl_set, struct sysctl_oid);
912
913 static void
914 sysctl_register_all(void *arg)
915 {
916         struct sysctl_oid **oidp;
917
918         sx_init(&sysctlmemlock, "sysctl mem");
919         SYSCTL_INIT();
920         SYSCTL_WLOCK();
921         SET_FOREACH(oidp, sysctl_set)
922                 sysctl_register_oid(*oidp);
923         SYSCTL_WUNLOCK();
924 }
925 SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_FIRST, sysctl_register_all, NULL);
926
927 /*
928  * "Staff-functions"
929  *
930  * These functions implement a presently undocumented interface 
931  * used by the sysctl program to walk the tree, and get the type
932  * so it can print the value.
933  * This interface is under work and consideration, and should probably
934  * be killed with a big axe by the first person who can find the time.
935  * (be aware though, that the proper interface isn't as obvious as it
936  * may seem, there are various conflicting requirements.
937  *
938  * {CTL_SYSCTL, CTL_SYSCTL_DEBUG}               printf the entire MIB-tree.
939  * {CTL_SYSCTL, CTL_SYSCTL_NAME, ...}           return the name of the "..."
940  *                                              OID.
941  * {CTL_SYSCTL, CTL_SYSCTL_NEXT, ...}           return the next OID.
942  * {CTL_SYSCTL, CTL_SYSCTL_NAME2OID}            return the OID of the name in
943  *                                              "new"
944  * {CTL_SYSCTL, CTL_SYSCTL_OIDFMT, ...}         return the kind & format info
945  *                                              for the "..." OID.
946  * {CTL_SYSCTL, CTL_SYSCTL_OIDDESCR, ...}       return the description of the
947  *                                              "..." OID.
948  * {CTL_SYSCTL, CTL_SYSCTL_OIDLABEL, ...}       return the aggregation label of
949  *                                              the "..." OID.
950  */
951
952 #ifdef SYSCTL_DEBUG
953 static void
954 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list *l, int i)
955 {
956         int k;
957         struct sysctl_oid *oidp;
958
959         SYSCTL_ASSERT_LOCKED();
960         SLIST_FOREACH(oidp, l, oid_link) {
961
962                 for (k=0; k<i; k++)
963                         printf(" ");
964
965                 printf("%d %s ", oidp->oid_number, oidp->oid_name);
966
967                 printf("%c%c",
968                         oidp->oid_kind & CTLFLAG_RD ? 'R':' ',
969                         oidp->oid_kind & CTLFLAG_WR ? 'W':' ');
970
971                 if (oidp->oid_handler)
972                         printf(" *Handler");
973
974                 switch (oidp->oid_kind & CTLTYPE) {
975                         case CTLTYPE_NODE:
976                                 printf(" Node\n");
977                                 if (!oidp->oid_handler) {
978                                         sysctl_sysctl_debug_dump_node(
979                                             SYSCTL_CHILDREN(oidp), i + 2);
980                                 }
981                                 break;
982                         case CTLTYPE_INT:    printf(" Int\n"); break;
983                         case CTLTYPE_UINT:   printf(" u_int\n"); break;
984                         case CTLTYPE_LONG:   printf(" Long\n"); break;
985                         case CTLTYPE_ULONG:  printf(" u_long\n"); break;
986                         case CTLTYPE_STRING: printf(" String\n"); break;
987                         case CTLTYPE_S8:     printf(" int8_t\n"); break;
988                         case CTLTYPE_S16:    printf(" int16_t\n"); break;
989                         case CTLTYPE_S32:    printf(" int32_t\n"); break;
990                         case CTLTYPE_S64:    printf(" int64_t\n"); break;
991                         case CTLTYPE_U8:     printf(" uint8_t\n"); break;
992                         case CTLTYPE_U16:    printf(" uint16_t\n"); break;
993                         case CTLTYPE_U32:    printf(" uint32_t\n"); break;
994                         case CTLTYPE_U64:    printf(" uint64_t\n"); break;
995                         case CTLTYPE_OPAQUE: printf(" Opaque/struct\n"); break;
996                         default:             printf("\n");
997                 }
998
999         }
1000 }
1001
1002 static int
1003 sysctl_sysctl_debug(SYSCTL_HANDLER_ARGS)
1004 {
1005         struct rm_priotracker tracker;
1006         int error;
1007
1008         error = priv_check(req->td, PRIV_SYSCTL_DEBUG);
1009         if (error)
1010                 return (error);
1011         SYSCTL_RLOCK(&tracker);
1012         sysctl_sysctl_debug_dump_node(&sysctl__children, 0);
1013         SYSCTL_RUNLOCK(&tracker);
1014         return (ENOENT);
1015 }
1016
1017 SYSCTL_PROC(_sysctl, CTL_SYSCTL_DEBUG, debug, CTLTYPE_STRING | CTLFLAG_RD |
1018     CTLFLAG_MPSAFE, 0, 0, sysctl_sysctl_debug, "-", "");
1019 #endif
1020
1021 static int
1022 sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
1023 {
1024         int *name = (int *) arg1;
1025         u_int namelen = arg2;
1026         int error = 0;
1027         struct sysctl_oid *oid;
1028         struct sysctl_oid_list *lsp = &sysctl__children, *lsp2;
1029         struct rm_priotracker tracker;
1030         char buf[10];
1031
1032         SYSCTL_RLOCK(&tracker);
1033         while (namelen) {
1034                 if (!lsp) {
1035                         snprintf(buf,sizeof(buf),"%d",*name);
1036                         if (req->oldidx)
1037                                 error = SYSCTL_OUT(req, ".", 1);
1038                         if (!error)
1039                                 error = SYSCTL_OUT(req, buf, strlen(buf));
1040                         if (error)
1041                                 goto out;
1042                         namelen--;
1043                         name++;
1044                         continue;
1045                 }
1046                 lsp2 = NULL;
1047                 SLIST_FOREACH(oid, lsp, oid_link) {
1048                         if (oid->oid_number != *name)
1049                                 continue;
1050
1051                         if (req->oldidx)
1052                                 error = SYSCTL_OUT(req, ".", 1);
1053                         if (!error)
1054                                 error = SYSCTL_OUT(req, oid->oid_name,
1055                                         strlen(oid->oid_name));
1056                         if (error)
1057                                 goto out;
1058
1059                         namelen--;
1060                         name++;
1061
1062                         if ((oid->oid_kind & CTLTYPE) != CTLTYPE_NODE) 
1063                                 break;
1064
1065                         if (oid->oid_handler)
1066                                 break;
1067
1068                         lsp2 = SYSCTL_CHILDREN(oid);
1069                         break;
1070                 }
1071                 lsp = lsp2;
1072         }
1073         error = SYSCTL_OUT(req, "", 1);
1074  out:
1075         SYSCTL_RUNLOCK(&tracker);
1076         return (error);
1077 }
1078
1079 /*
1080  * XXXRW/JA: Shouldn't return name data for nodes that we don't permit in
1081  * capability mode.
1082  */
1083 static SYSCTL_NODE(_sysctl, CTL_SYSCTL_NAME, name, CTLFLAG_RD |
1084     CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_name, "");
1085
1086 static int
1087 sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen, 
1088         int *next, int *len, int level, struct sysctl_oid **oidpp)
1089 {
1090         struct sysctl_oid *oidp;
1091
1092         SYSCTL_ASSERT_LOCKED();
1093         *len = level;
1094         SLIST_FOREACH(oidp, lsp, oid_link) {
1095                 *next = oidp->oid_number;
1096                 *oidpp = oidp;
1097
1098                 if ((oidp->oid_kind & (CTLFLAG_SKIP | CTLFLAG_DORMANT)) != 0)
1099                         continue;
1100
1101                 if (!namelen) {
1102                         if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) 
1103                                 return (0);
1104                         if (oidp->oid_handler) 
1105                                 /* We really should call the handler here...*/
1106                                 return (0);
1107                         lsp = SYSCTL_CHILDREN(oidp);
1108                         if (!sysctl_sysctl_next_ls(lsp, 0, 0, next+1, 
1109                                 len, level+1, oidpp))
1110                                 return (0);
1111                         goto emptynode;
1112                 }
1113
1114                 if (oidp->oid_number < *name)
1115                         continue;
1116
1117                 if (oidp->oid_number > *name) {
1118                         if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
1119                                 return (0);
1120                         if (oidp->oid_handler)
1121                                 return (0);
1122                         lsp = SYSCTL_CHILDREN(oidp);
1123                         if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, 
1124                                 next+1, len, level+1, oidpp))
1125                                 return (0);
1126                         goto next;
1127                 }
1128                 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
1129                         continue;
1130
1131                 if (oidp->oid_handler)
1132                         continue;
1133
1134                 lsp = SYSCTL_CHILDREN(oidp);
1135                 if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, next+1, 
1136                         len, level+1, oidpp))
1137                         return (0);
1138         next:
1139                 namelen = 1;
1140         emptynode:
1141                 *len = level;
1142         }
1143         return (1);
1144 }
1145
1146 static int
1147 sysctl_sysctl_next(SYSCTL_HANDLER_ARGS)
1148 {
1149         int *name = (int *) arg1;
1150         u_int namelen = arg2;
1151         int i, j, error;
1152         struct sysctl_oid *oid;
1153         struct sysctl_oid_list *lsp = &sysctl__children;
1154         struct rm_priotracker tracker;
1155         int newoid[CTL_MAXNAME];
1156
1157         SYSCTL_RLOCK(&tracker);
1158         i = sysctl_sysctl_next_ls(lsp, name, namelen, newoid, &j, 1, &oid);
1159         SYSCTL_RUNLOCK(&tracker);
1160         if (i)
1161                 return (ENOENT);
1162         error = SYSCTL_OUT(req, newoid, j * sizeof (int));
1163         return (error);
1164 }
1165
1166 /*
1167  * XXXRW/JA: Shouldn't return next data for nodes that we don't permit in
1168  * capability mode.
1169  */
1170 static SYSCTL_NODE(_sysctl, CTL_SYSCTL_NEXT, next, CTLFLAG_RD |
1171     CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_next, "");
1172
1173 static int
1174 name2oid(char *name, int *oid, int *len, struct sysctl_oid **oidpp)
1175 {
1176         struct sysctl_oid *oidp;
1177         struct sysctl_oid_list *lsp = &sysctl__children;
1178         char *p;
1179
1180         SYSCTL_ASSERT_LOCKED();
1181
1182         for (*len = 0; *len < CTL_MAXNAME;) {
1183                 p = strsep(&name, ".");
1184
1185                 oidp = SLIST_FIRST(lsp);
1186                 for (;; oidp = SLIST_NEXT(oidp, oid_link)) {
1187                         if (oidp == NULL)
1188                                 return (ENOENT);
1189                         if (strcmp(p, oidp->oid_name) == 0)
1190                                 break;
1191                 }
1192                 *oid++ = oidp->oid_number;
1193                 (*len)++;
1194
1195                 if (name == NULL || *name == '\0') {
1196                         if (oidpp)
1197                                 *oidpp = oidp;
1198                         return (0);
1199                 }
1200
1201                 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
1202                         break;
1203
1204                 if (oidp->oid_handler)
1205                         break;
1206
1207                 lsp = SYSCTL_CHILDREN(oidp);
1208         }
1209         return (ENOENT);
1210 }
1211
1212 static int
1213 sysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS)
1214 {
1215         char *p;
1216         int error, oid[CTL_MAXNAME], len = 0;
1217         struct sysctl_oid *op = NULL;
1218         struct rm_priotracker tracker;
1219         char buf[32];
1220
1221         if (!req->newlen) 
1222                 return (ENOENT);
1223         if (req->newlen >= MAXPATHLEN)  /* XXX arbitrary, undocumented */
1224                 return (ENAMETOOLONG);
1225
1226         p = buf;
1227         if (req->newlen >= sizeof(buf))
1228                 p = malloc(req->newlen+1, M_SYSCTL, M_WAITOK);
1229
1230         error = SYSCTL_IN(req, p, req->newlen);
1231         if (error) {
1232                 if (p != buf)
1233                         free(p, M_SYSCTL);
1234                 return (error);
1235         }
1236
1237         p [req->newlen] = '\0';
1238
1239         SYSCTL_RLOCK(&tracker);
1240         error = name2oid(p, oid, &len, &op);
1241         SYSCTL_RUNLOCK(&tracker);
1242
1243         if (p != buf)
1244                 free(p, M_SYSCTL);
1245
1246         if (error)
1247                 return (error);
1248
1249         error = SYSCTL_OUT(req, oid, len * sizeof *oid);
1250         return (error);
1251 }
1252
1253 /*
1254  * XXXRW/JA: Shouldn't return name2oid data for nodes that we don't permit in
1255  * capability mode.
1256  */
1257 SYSCTL_PROC(_sysctl, CTL_SYSCTL_NAME2OID, name2oid, CTLTYPE_INT | CTLFLAG_RW |
1258     CTLFLAG_ANYBODY | CTLFLAG_MPSAFE | CTLFLAG_CAPRW, 0, 0,
1259     sysctl_sysctl_name2oid, "I", "");
1260
1261 static int
1262 sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS)
1263 {
1264         struct sysctl_oid *oid;
1265         struct rm_priotracker tracker;
1266         int error;
1267
1268         SYSCTL_RLOCK(&tracker);
1269         error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
1270         if (error)
1271                 goto out;
1272
1273         if (oid->oid_fmt == NULL) {
1274                 error = ENOENT;
1275                 goto out;
1276         }
1277         error = SYSCTL_OUT(req, &oid->oid_kind, sizeof(oid->oid_kind));
1278         if (error)
1279                 goto out;
1280         error = SYSCTL_OUT(req, oid->oid_fmt, strlen(oid->oid_fmt) + 1);
1281  out:
1282         SYSCTL_RUNLOCK(&tracker);
1283         return (error);
1284 }
1285
1286
1287 static SYSCTL_NODE(_sysctl, CTL_SYSCTL_OIDFMT, oidfmt, CTLFLAG_RD |
1288     CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_oidfmt, "");
1289
1290 static int
1291 sysctl_sysctl_oiddescr(SYSCTL_HANDLER_ARGS)
1292 {
1293         struct sysctl_oid *oid;
1294         struct rm_priotracker tracker;
1295         int error;
1296
1297         SYSCTL_RLOCK(&tracker);
1298         error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
1299         if (error)
1300                 goto out;
1301
1302         if (oid->oid_descr == NULL) {
1303                 error = ENOENT;
1304                 goto out;
1305         }
1306         error = SYSCTL_OUT(req, oid->oid_descr, strlen(oid->oid_descr) + 1);
1307  out:
1308         SYSCTL_RUNLOCK(&tracker);
1309         return (error);
1310 }
1311
1312 static SYSCTL_NODE(_sysctl, CTL_SYSCTL_OIDDESCR, oiddescr, CTLFLAG_RD |
1313     CTLFLAG_MPSAFE|CTLFLAG_CAPRD, sysctl_sysctl_oiddescr, "");
1314
1315 static int
1316 sysctl_sysctl_oidlabel(SYSCTL_HANDLER_ARGS)
1317 {
1318         struct sysctl_oid *oid;
1319         struct rm_priotracker tracker;
1320         int error;
1321
1322         SYSCTL_RLOCK(&tracker);
1323         error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
1324         if (error)
1325                 goto out;
1326
1327         if (oid->oid_label == NULL) {
1328                 error = ENOENT;
1329                 goto out;
1330         }
1331         error = SYSCTL_OUT(req, oid->oid_label, strlen(oid->oid_label) + 1);
1332  out:
1333         SYSCTL_RUNLOCK(&tracker);
1334         return (error);
1335 }
1336
1337 static SYSCTL_NODE(_sysctl, CTL_SYSCTL_OIDLABEL, oidlabel, CTLFLAG_RD |
1338     CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_oidlabel, "");
1339
1340 /*
1341  * Default "handler" functions.
1342  */
1343
1344 /*
1345  * Handle a bool.
1346  * Two cases:
1347  *     a variable:  point arg1 at it.
1348  *     a constant:  pass it in arg2.
1349  */
1350
1351 int
1352 sysctl_handle_bool(SYSCTL_HANDLER_ARGS)
1353 {
1354         uint8_t temp;
1355         int error;
1356
1357         /*
1358          * Attempt to get a coherent snapshot by making a copy of the data.
1359          */
1360         if (arg1)
1361                 temp = *(bool *)arg1 ? 1 : 0;
1362         else
1363                 temp = arg2 ? 1 : 0;
1364
1365         error = SYSCTL_OUT(req, &temp, sizeof(temp));
1366         if (error || !req->newptr)
1367                 return (error);
1368
1369         if (!arg1)
1370                 error = EPERM;
1371         else {
1372                 error = SYSCTL_IN(req, &temp, sizeof(temp));
1373                 if (!error)
1374                         *(bool *)arg1 = temp ? 1 : 0;
1375         }
1376         return (error);
1377 }
1378
1379 /*
1380  * Handle an int8_t, signed or unsigned.
1381  * Two cases:
1382  *     a variable:  point arg1 at it.
1383  *     a constant:  pass it in arg2.
1384  */
1385
1386 int
1387 sysctl_handle_8(SYSCTL_HANDLER_ARGS)
1388 {
1389         int8_t tmpout;
1390         int error = 0;
1391
1392         /*
1393          * Attempt to get a coherent snapshot by making a copy of the data.
1394          */
1395         if (arg1)
1396                 tmpout = *(int8_t *)arg1;
1397         else
1398                 tmpout = arg2;
1399         error = SYSCTL_OUT(req, &tmpout, sizeof(tmpout));
1400
1401         if (error || !req->newptr)
1402                 return (error);
1403
1404         if (!arg1)
1405                 error = EPERM;
1406         else
1407                 error = SYSCTL_IN(req, arg1, sizeof(tmpout));
1408         return (error);
1409 }
1410
1411 /*
1412  * Handle an int16_t, signed or unsigned.
1413  * Two cases:
1414  *     a variable:  point arg1 at it.
1415  *     a constant:  pass it in arg2.
1416  */
1417
1418 int
1419 sysctl_handle_16(SYSCTL_HANDLER_ARGS)
1420 {
1421         int16_t tmpout;
1422         int error = 0;
1423
1424         /*
1425          * Attempt to get a coherent snapshot by making a copy of the data.
1426          */
1427         if (arg1)
1428                 tmpout = *(int16_t *)arg1;
1429         else
1430                 tmpout = arg2;
1431         error = SYSCTL_OUT(req, &tmpout, sizeof(tmpout));
1432
1433         if (error || !req->newptr)
1434                 return (error);
1435
1436         if (!arg1)
1437                 error = EPERM;
1438         else
1439                 error = SYSCTL_IN(req, arg1, sizeof(tmpout));
1440         return (error);
1441 }
1442
1443 /*
1444  * Handle an int32_t, signed or unsigned.
1445  * Two cases:
1446  *     a variable:  point arg1 at it.
1447  *     a constant:  pass it in arg2.
1448  */
1449
1450 int
1451 sysctl_handle_32(SYSCTL_HANDLER_ARGS)
1452 {
1453         int32_t tmpout;
1454         int error = 0;
1455
1456         /*
1457          * Attempt to get a coherent snapshot by making a copy of the data.
1458          */
1459         if (arg1)
1460                 tmpout = *(int32_t *)arg1;
1461         else
1462                 tmpout = arg2;
1463         error = SYSCTL_OUT(req, &tmpout, sizeof(tmpout));
1464
1465         if (error || !req->newptr)
1466                 return (error);
1467
1468         if (!arg1)
1469                 error = EPERM;
1470         else
1471                 error = SYSCTL_IN(req, arg1, sizeof(tmpout));
1472         return (error);
1473 }
1474
1475 /*
1476  * Handle an int, signed or unsigned.
1477  * Two cases:
1478  *     a variable:  point arg1 at it.
1479  *     a constant:  pass it in arg2.
1480  */
1481
1482 int
1483 sysctl_handle_int(SYSCTL_HANDLER_ARGS)
1484 {
1485         int tmpout, error = 0;
1486
1487         /*
1488          * Attempt to get a coherent snapshot by making a copy of the data.
1489          */
1490         if (arg1)
1491                 tmpout = *(int *)arg1;
1492         else
1493                 tmpout = arg2;
1494         error = SYSCTL_OUT(req, &tmpout, sizeof(int));
1495
1496         if (error || !req->newptr)
1497                 return (error);
1498
1499         if (!arg1)
1500                 error = EPERM;
1501         else
1502                 error = SYSCTL_IN(req, arg1, sizeof(int));
1503         return (error);
1504 }
1505
1506 /*
1507  * Based on on sysctl_handle_int() convert milliseconds into ticks.
1508  * Note: this is used by TCP.
1509  */
1510
1511 int
1512 sysctl_msec_to_ticks(SYSCTL_HANDLER_ARGS)
1513 {
1514         int error, s, tt;
1515
1516         tt = *(int *)arg1;
1517         s = (int)((int64_t)tt * 1000 / hz);
1518
1519         error = sysctl_handle_int(oidp, &s, 0, req);
1520         if (error || !req->newptr)
1521                 return (error);
1522
1523         tt = (int)((int64_t)s * hz / 1000);
1524         if (tt < 1)
1525                 return (EINVAL);
1526
1527         *(int *)arg1 = tt;
1528         return (0);
1529 }
1530
1531
1532 /*
1533  * Handle a long, signed or unsigned.
1534  * Two cases:
1535  *     a variable:  point arg1 at it.
1536  *     a constant:  pass it in arg2.
1537  */
1538
1539 int
1540 sysctl_handle_long(SYSCTL_HANDLER_ARGS)
1541 {
1542         int error = 0;
1543         long tmplong;
1544 #ifdef SCTL_MASK32
1545         int tmpint;
1546 #endif
1547
1548         /*
1549          * Attempt to get a coherent snapshot by making a copy of the data.
1550          */
1551         if (arg1)
1552                 tmplong = *(long *)arg1;
1553         else
1554                 tmplong = arg2;
1555 #ifdef SCTL_MASK32
1556         if (req->flags & SCTL_MASK32) {
1557                 tmpint = tmplong;
1558                 error = SYSCTL_OUT(req, &tmpint, sizeof(int));
1559         } else
1560 #endif
1561                 error = SYSCTL_OUT(req, &tmplong, sizeof(long));
1562
1563         if (error || !req->newptr)
1564                 return (error);
1565
1566         if (!arg1)
1567                 error = EPERM;
1568 #ifdef SCTL_MASK32
1569         else if (req->flags & SCTL_MASK32) {
1570                 error = SYSCTL_IN(req, &tmpint, sizeof(int));
1571                 *(long *)arg1 = (long)tmpint;
1572         }
1573 #endif
1574         else
1575                 error = SYSCTL_IN(req, arg1, sizeof(long));
1576         return (error);
1577 }
1578
1579 /*
1580  * Handle a 64 bit int, signed or unsigned.
1581  * Two cases:
1582  *     a variable:  point arg1 at it.
1583  *     a constant:  pass it in arg2.
1584  */
1585 int
1586 sysctl_handle_64(SYSCTL_HANDLER_ARGS)
1587 {
1588         int error = 0;
1589         uint64_t tmpout;
1590
1591         /*
1592          * Attempt to get a coherent snapshot by making a copy of the data.
1593          */
1594         if (arg1)
1595                 tmpout = *(uint64_t *)arg1;
1596         else
1597                 tmpout = arg2;
1598         error = SYSCTL_OUT(req, &tmpout, sizeof(uint64_t));
1599
1600         if (error || !req->newptr)
1601                 return (error);
1602
1603         if (!arg1)
1604                 error = EPERM;
1605         else
1606                 error = SYSCTL_IN(req, arg1, sizeof(uint64_t));
1607         return (error);
1608 }
1609
1610 /*
1611  * Handle our generic '\0' terminated 'C' string.
1612  * Two cases:
1613  *      a variable string:  point arg1 at it, arg2 is max length.
1614  *      a constant string:  point arg1 at it, arg2 is zero.
1615  */
1616
1617 int
1618 sysctl_handle_string(SYSCTL_HANDLER_ARGS)
1619 {
1620         size_t outlen;
1621         int error = 0, ro_string = 0;
1622
1623         /*
1624          * A zero-length buffer indicates a fixed size read-only
1625          * string.  In ddb, don't worry about trying to make a malloced
1626          * snapshot.
1627          */
1628         if (arg2 == 0 || kdb_active) {
1629                 arg2 = strlen((char *)arg1) + 1;
1630                 ro_string = 1;
1631         }
1632
1633         if (req->oldptr != NULL) {
1634                 char *tmparg;
1635
1636                 if (ro_string) {
1637                         tmparg = arg1;
1638                 } else {
1639                         /* try to make a coherent snapshot of the string */
1640                         tmparg = malloc(arg2, M_SYSCTLTMP, M_WAITOK);
1641                         memcpy(tmparg, arg1, arg2);
1642                 }
1643
1644                 outlen = strnlen(tmparg, arg2 - 1) + 1;
1645                 error = SYSCTL_OUT(req, tmparg, outlen);
1646
1647                 if (!ro_string)
1648                         free(tmparg, M_SYSCTLTMP);
1649         } else {
1650                 outlen = strnlen((char *)arg1, arg2 - 1) + 1;
1651                 error = SYSCTL_OUT(req, NULL, outlen);
1652         }
1653         if (error || !req->newptr)
1654                 return (error);
1655
1656         if ((req->newlen - req->newidx) >= arg2) {
1657                 error = EINVAL;
1658         } else {
1659                 arg2 = (req->newlen - req->newidx);
1660                 error = SYSCTL_IN(req, arg1, arg2);
1661                 ((char *)arg1)[arg2] = '\0';
1662         }
1663         return (error);
1664 }
1665
1666 /*
1667  * Handle any kind of opaque data.
1668  * arg1 points to it, arg2 is the size.
1669  */
1670
1671 int
1672 sysctl_handle_opaque(SYSCTL_HANDLER_ARGS)
1673 {
1674         int error, tries;
1675         u_int generation;
1676         struct sysctl_req req2;
1677
1678         /*
1679          * Attempt to get a coherent snapshot, by using the thread
1680          * pre-emption counter updated from within mi_switch() to
1681          * determine if we were pre-empted during a bcopy() or
1682          * copyout(). Make 3 attempts at doing this before giving up.
1683          * If we encounter an error, stop immediately.
1684          */
1685         tries = 0;
1686         req2 = *req;
1687 retry:
1688         generation = curthread->td_generation;
1689         error = SYSCTL_OUT(req, arg1, arg2);
1690         if (error)
1691                 return (error);
1692         tries++;
1693         if (generation != curthread->td_generation && tries < 3) {
1694                 *req = req2;
1695                 goto retry;
1696         }
1697
1698         error = SYSCTL_IN(req, arg1, arg2);
1699
1700         return (error);
1701 }
1702
1703 /*
1704  * Based on on sysctl_handle_int() convert microseconds to a sbintime.
1705  */
1706 int
1707 sysctl_usec_to_sbintime(SYSCTL_HANDLER_ARGS)
1708 {
1709         int error;
1710         int64_t tt;
1711         sbintime_t sb;
1712
1713         tt = *(int64_t *)arg1;
1714         sb = sbttous(tt);
1715
1716         error = sysctl_handle_64(oidp, &sb, 0, req);
1717         if (error || !req->newptr)
1718                 return (error);
1719
1720         tt = ustosbt(sb);
1721         *(int64_t *)arg1 = tt;
1722
1723         return (0);
1724 }
1725
1726 /*
1727  * Based on on sysctl_handle_int() convert milliseconds to a sbintime.
1728  */
1729 int
1730 sysctl_msec_to_sbintime(SYSCTL_HANDLER_ARGS)
1731 {
1732         int error;
1733         int64_t tt;
1734         sbintime_t sb;
1735
1736         tt = *(int64_t *)arg1;
1737         sb = sbttoms(tt);
1738
1739         error = sysctl_handle_64(oidp, &sb, 0, req);
1740         if (error || !req->newptr)
1741                 return (error);
1742
1743         tt = mstosbt(sb);
1744         *(int64_t *)arg1 = tt;
1745
1746         return (0);
1747 }
1748
1749 /*
1750  * Convert seconds to a struct timeval.  Intended for use with
1751  * intervals and thus does not permit negative seconds.
1752  */
1753 int
1754 sysctl_sec_to_timeval(SYSCTL_HANDLER_ARGS)
1755 {
1756         struct timeval *tv;
1757         int error, secs;
1758
1759         tv = arg1;
1760         secs = tv->tv_sec;
1761
1762         error = sysctl_handle_int(oidp, &secs, 0, req);
1763         if (error || req->newptr == NULL)
1764                 return (error);
1765
1766         if (secs < 0)
1767                 return (EINVAL);
1768         tv->tv_sec = secs;
1769
1770         return (0);
1771 }
1772
1773 /*
1774  * Transfer functions to/from kernel space.
1775  * XXX: rather untested at this point
1776  */
1777 static int
1778 sysctl_old_kernel(struct sysctl_req *req, const void *p, size_t l)
1779 {
1780         size_t i = 0;
1781
1782         if (req->oldptr) {
1783                 i = l;
1784                 if (req->oldlen <= req->oldidx)
1785                         i = 0;
1786                 else
1787                         if (i > req->oldlen - req->oldidx)
1788                                 i = req->oldlen - req->oldidx;
1789                 if (i > 0)
1790                         bcopy(p, (char *)req->oldptr + req->oldidx, i);
1791         }
1792         req->oldidx += l;
1793         if (req->oldptr && i != l)
1794                 return (ENOMEM);
1795         return (0);
1796 }
1797
1798 static int
1799 sysctl_new_kernel(struct sysctl_req *req, void *p, size_t l)
1800 {
1801         if (!req->newptr)
1802                 return (0);
1803         if (req->newlen - req->newidx < l)
1804                 return (EINVAL);
1805         bcopy((const char *)req->newptr + req->newidx, p, l);
1806         req->newidx += l;
1807         return (0);
1808 }
1809
1810 int
1811 kernel_sysctl(struct thread *td, int *name, u_int namelen, void *old,
1812     size_t *oldlenp, void *new, size_t newlen, size_t *retval, int flags)
1813 {
1814         int error = 0;
1815         struct sysctl_req req;
1816
1817         bzero(&req, sizeof req);
1818
1819         req.td = td;
1820         req.flags = flags;
1821
1822         if (oldlenp) {
1823                 req.oldlen = *oldlenp;
1824         }
1825         req.validlen = req.oldlen;
1826
1827         if (old) {
1828                 req.oldptr= old;
1829         }
1830
1831         if (new != NULL) {
1832                 req.newlen = newlen;
1833                 req.newptr = new;
1834         }
1835
1836         req.oldfunc = sysctl_old_kernel;
1837         req.newfunc = sysctl_new_kernel;
1838         req.lock = REQ_UNWIRED;
1839
1840         error = sysctl_root(0, name, namelen, &req);
1841
1842         if (req.lock == REQ_WIRED && req.validlen > 0)
1843                 vsunlock(req.oldptr, req.validlen);
1844
1845         if (error && error != ENOMEM)
1846                 return (error);
1847
1848         if (retval) {
1849                 if (req.oldptr && req.oldidx > req.validlen)
1850                         *retval = req.validlen;
1851                 else
1852                         *retval = req.oldidx;
1853         }
1854         return (error);
1855 }
1856
1857 int
1858 kernel_sysctlbyname(struct thread *td, char *name, void *old, size_t *oldlenp,
1859     void *new, size_t newlen, size_t *retval, int flags)
1860 {
1861         int oid[CTL_MAXNAME];
1862         size_t oidlen, plen;
1863         int error;
1864
1865         oid[0] = CTL_SYSCTL;
1866         oid[1] = CTL_SYSCTL_NAME2OID;
1867         oidlen = sizeof(oid);
1868
1869         error = kernel_sysctl(td, oid, 2, oid, &oidlen,
1870             (void *)name, strlen(name), &plen, flags);
1871         if (error)
1872                 return (error);
1873
1874         error = kernel_sysctl(td, oid, plen / sizeof(int), old, oldlenp,
1875             new, newlen, retval, flags);
1876         return (error);
1877 }
1878
1879 /*
1880  * Transfer function to/from user space.
1881  */
1882 static int
1883 sysctl_old_user(struct sysctl_req *req, const void *p, size_t l)
1884 {
1885         size_t i, len, origidx;
1886         int error;
1887
1888         origidx = req->oldidx;
1889         req->oldidx += l;
1890         if (req->oldptr == NULL)
1891                 return (0);
1892         /*
1893          * If we have not wired the user supplied buffer and we are currently
1894          * holding locks, drop a witness warning, as it's possible that
1895          * write operations to the user page can sleep.
1896          */
1897         if (req->lock != REQ_WIRED)
1898                 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
1899                     "sysctl_old_user()");
1900         i = l;
1901         len = req->validlen;
1902         if (len <= origidx)
1903                 i = 0;
1904         else {
1905                 if (i > len - origidx)
1906                         i = len - origidx;
1907                 if (req->lock == REQ_WIRED) {
1908                         error = copyout_nofault(p, (char *)req->oldptr +
1909                             origidx, i);
1910                 } else
1911                         error = copyout(p, (char *)req->oldptr + origidx, i);
1912                 if (error != 0)
1913                         return (error);
1914         }
1915         if (i < l)
1916                 return (ENOMEM);
1917         return (0);
1918 }
1919
1920 static int
1921 sysctl_new_user(struct sysctl_req *req, void *p, size_t l)
1922 {
1923         int error;
1924
1925         if (!req->newptr)
1926                 return (0);
1927         if (req->newlen - req->newidx < l)
1928                 return (EINVAL);
1929         WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
1930             "sysctl_new_user()");
1931         error = copyin((const char *)req->newptr + req->newidx, p, l);
1932         req->newidx += l;
1933         return (error);
1934 }
1935
1936 /*
1937  * Wire the user space destination buffer.  If set to a value greater than
1938  * zero, the len parameter limits the maximum amount of wired memory.
1939  */
1940 int
1941 sysctl_wire_old_buffer(struct sysctl_req *req, size_t len)
1942 {
1943         int ret;
1944         size_t wiredlen;
1945
1946         wiredlen = (len > 0 && len < req->oldlen) ? len : req->oldlen;
1947         ret = 0;
1948         if (req->lock != REQ_WIRED && req->oldptr &&
1949             req->oldfunc == sysctl_old_user) {
1950                 if (wiredlen != 0) {
1951                         ret = vslock(req->oldptr, wiredlen);
1952                         if (ret != 0) {
1953                                 if (ret != ENOMEM)
1954                                         return (ret);
1955                                 wiredlen = 0;
1956                         }
1957                 }
1958                 req->lock = REQ_WIRED;
1959                 req->validlen = wiredlen;
1960         }
1961         return (0);
1962 }
1963
1964 int
1965 sysctl_find_oid(int *name, u_int namelen, struct sysctl_oid **noid,
1966     int *nindx, struct sysctl_req *req)
1967 {
1968         struct sysctl_oid_list *lsp;
1969         struct sysctl_oid *oid;
1970         int indx;
1971
1972         SYSCTL_ASSERT_LOCKED();
1973         lsp = &sysctl__children;
1974         indx = 0;
1975         while (indx < CTL_MAXNAME) {
1976                 SLIST_FOREACH(oid, lsp, oid_link) {
1977                         if (oid->oid_number == name[indx])
1978                                 break;
1979                 }
1980                 if (oid == NULL)
1981                         return (ENOENT);
1982
1983                 indx++;
1984                 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
1985                         if (oid->oid_handler != NULL || indx == namelen) {
1986                                 *noid = oid;
1987                                 if (nindx != NULL)
1988                                         *nindx = indx;
1989                                 KASSERT((oid->oid_kind & CTLFLAG_DYING) == 0,
1990                                     ("%s found DYING node %p", __func__, oid));
1991                                 return (0);
1992                         }
1993                         lsp = SYSCTL_CHILDREN(oid);
1994                 } else if (indx == namelen) {
1995                         if ((oid->oid_kind & CTLFLAG_DORMANT) != 0)
1996                                 return (ENOENT);
1997                         *noid = oid;
1998                         if (nindx != NULL)
1999                                 *nindx = indx;
2000                         KASSERT((oid->oid_kind & CTLFLAG_DYING) == 0,
2001                             ("%s found DYING node %p", __func__, oid));
2002                         return (0);
2003                 } else {
2004                         return (ENOTDIR);
2005                 }
2006         }
2007         return (ENOENT);
2008 }
2009
2010 /*
2011  * Traverse our tree, and find the right node, execute whatever it points
2012  * to, and return the resulting error code.
2013  */
2014
2015 static int
2016 sysctl_root(SYSCTL_HANDLER_ARGS)
2017 {
2018         struct sysctl_oid *oid;
2019         struct rm_priotracker tracker;
2020         int error, indx, lvl;
2021
2022         SYSCTL_RLOCK(&tracker);
2023
2024         error = sysctl_find_oid(arg1, arg2, &oid, &indx, req);
2025         if (error)
2026                 goto out;
2027
2028         if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
2029                 /*
2030                  * You can't call a sysctl when it's a node, but has
2031                  * no handler.  Inform the user that it's a node.
2032                  * The indx may or may not be the same as namelen.
2033                  */
2034                 if (oid->oid_handler == NULL) {
2035                         error = EISDIR;
2036                         goto out;
2037                 }
2038         }
2039
2040         /* Is this sysctl writable? */
2041         if (req->newptr && !(oid->oid_kind & CTLFLAG_WR)) {
2042                 error = EPERM;
2043                 goto out;
2044         }
2045
2046         KASSERT(req->td != NULL, ("sysctl_root(): req->td == NULL"));
2047
2048 #ifdef CAPABILITY_MODE
2049         /*
2050          * If the process is in capability mode, then don't permit reading or
2051          * writing unless specifically granted for the node.
2052          */
2053         if (IN_CAPABILITY_MODE(req->td)) {
2054                 if ((req->oldptr && !(oid->oid_kind & CTLFLAG_CAPRD)) ||
2055                     (req->newptr && !(oid->oid_kind & CTLFLAG_CAPWR))) {
2056                         error = EPERM;
2057                         goto out;
2058                 }
2059         }
2060 #endif
2061
2062         /* Is this sysctl sensitive to securelevels? */
2063         if (req->newptr && (oid->oid_kind & CTLFLAG_SECURE)) {
2064                 lvl = (oid->oid_kind & CTLMASK_SECURE) >> CTLSHIFT_SECURE;
2065                 error = securelevel_gt(req->td->td_ucred, lvl);
2066                 if (error)
2067                         goto out;
2068         }
2069
2070         /* Is this sysctl writable by only privileged users? */
2071         if (req->newptr && !(oid->oid_kind & CTLFLAG_ANYBODY)) {
2072                 int priv;
2073
2074                 if (oid->oid_kind & CTLFLAG_PRISON)
2075                         priv = PRIV_SYSCTL_WRITEJAIL;
2076 #ifdef VIMAGE
2077                 else if ((oid->oid_kind & CTLFLAG_VNET) &&
2078                      prison_owns_vnet(req->td->td_ucred))
2079                         priv = PRIV_SYSCTL_WRITEJAIL;
2080 #endif
2081                 else
2082                         priv = PRIV_SYSCTL_WRITE;
2083                 error = priv_check(req->td, priv);
2084                 if (error)
2085                         goto out;
2086         }
2087
2088         if (!oid->oid_handler) {
2089                 error = EINVAL;
2090                 goto out;
2091         }
2092
2093         if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
2094                 arg1 = (int *)arg1 + indx;
2095                 arg2 -= indx;
2096         } else {
2097                 arg1 = oid->oid_arg1;
2098                 arg2 = oid->oid_arg2;
2099         }
2100 #ifdef MAC
2101         error = mac_system_check_sysctl(req->td->td_ucred, oid, arg1, arg2,
2102             req);
2103         if (error != 0)
2104                 goto out;
2105 #endif
2106 #ifdef VIMAGE
2107         if ((oid->oid_kind & CTLFLAG_VNET) && arg1 != NULL)
2108                 arg1 = (void *)(curvnet->vnet_data_base + (uintptr_t)arg1);
2109 #endif
2110         error = sysctl_root_handler_locked(oid, arg1, arg2, req, &tracker);
2111
2112 out:
2113         SYSCTL_RUNLOCK(&tracker);
2114         return (error);
2115 }
2116
2117 #ifndef _SYS_SYSPROTO_H_
2118 struct sysctl_args {
2119         int     *name;
2120         u_int   namelen;
2121         void    *old;
2122         size_t  *oldlenp;
2123         void    *new;
2124         size_t  newlen;
2125 };
2126 #endif
2127 int
2128 sys___sysctl(struct thread *td, struct sysctl_args *uap)
2129 {
2130         int error, i, name[CTL_MAXNAME];
2131         size_t j;
2132
2133         if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
2134                 return (EINVAL);
2135
2136         error = copyin(uap->name, &name, uap->namelen * sizeof(int));
2137         if (error)
2138                 return (error);
2139
2140         error = userland_sysctl(td, name, uap->namelen,
2141                 uap->old, uap->oldlenp, 0,
2142                 uap->new, uap->newlen, &j, 0);
2143         if (error && error != ENOMEM)
2144                 return (error);
2145         if (uap->oldlenp) {
2146                 i = copyout(&j, uap->oldlenp, sizeof(j));
2147                 if (i)
2148                         return (i);
2149         }
2150         return (error);
2151 }
2152
2153 int
2154 kern___sysctlbyname(struct thread *td, const char *oname, size_t namelen,
2155     void *old, size_t *oldlenp, void *new, size_t newlen, size_t *retval,
2156     int flags, bool inkernel)
2157 {
2158         int oid[CTL_MAXNAME];
2159         char namebuf[16];
2160         char *name;
2161         size_t oidlen;
2162         int error;
2163
2164         if (namelen > MAXPATHLEN || namelen == 0)
2165                 return (EINVAL);
2166         name = namebuf;
2167         if (namelen > sizeof(namebuf))
2168                 name = malloc(namelen, M_SYSCTL, M_WAITOK);
2169         error = copyin(oname, name, namelen);
2170         if (error != 0)
2171                 goto out;
2172
2173         oid[0] = CTL_SYSCTL;
2174         oid[1] = CTL_SYSCTL_NAME2OID;
2175         oidlen = sizeof(oid);
2176         error = kernel_sysctl(td, oid, 2, oid, &oidlen, (void *)name, namelen,
2177             retval, flags);
2178         if (error != 0)
2179                 goto out;
2180         error = userland_sysctl(td, oid, *retval / sizeof(int), old, oldlenp,
2181             inkernel, new, newlen, retval, flags);
2182
2183 out:
2184         if (namelen > sizeof(namebuf))
2185                 free(name, M_SYSCTL);
2186         return (error);
2187 }
2188
2189 #ifndef _SYS_SYSPROTO_H_
2190 struct __sysctlbyname_args {
2191         const char      *name;
2192         size_t  namelen;
2193         void    *old;
2194         size_t  *oldlenp;
2195         void    *new;
2196         size_t  newlen;
2197 };
2198 #endif
2199 int
2200 sys___sysctlbyname(struct thread *td, struct __sysctlbyname_args *uap)
2201 {
2202         size_t rv;
2203         int error;
2204
2205         error = kern___sysctlbyname(td, uap->name, uap->namelen, uap->old,
2206             uap->oldlenp, uap->new, uap->newlen, &rv, 0, 0);
2207         if (error != 0)
2208                 return (error);
2209         if (uap->oldlenp != NULL)
2210                 error = copyout(&rv, uap->oldlenp, sizeof(rv));
2211
2212         return (error);
2213 }
2214
2215 /*
2216  * This is used from various compatibility syscalls too.  That's why name
2217  * must be in kernel space.
2218  */
2219 int
2220 userland_sysctl(struct thread *td, int *name, u_int namelen, void *old,
2221     size_t *oldlenp, int inkernel, const void *new, size_t newlen,
2222     size_t *retval, int flags)
2223 {
2224         int error = 0, memlocked;
2225         struct sysctl_req req;
2226
2227         bzero(&req, sizeof req);
2228
2229         req.td = td;
2230         req.flags = flags;
2231
2232         if (oldlenp) {
2233                 if (inkernel) {
2234                         req.oldlen = *oldlenp;
2235                 } else {
2236                         error = copyin(oldlenp, &req.oldlen, sizeof(*oldlenp));
2237                         if (error)
2238                                 return (error);
2239                 }
2240         }
2241         req.validlen = req.oldlen;
2242         req.oldptr = old;
2243
2244         if (new != NULL) {
2245                 req.newlen = newlen;
2246                 req.newptr = new;
2247         }
2248
2249         req.oldfunc = sysctl_old_user;
2250         req.newfunc = sysctl_new_user;
2251         req.lock = REQ_UNWIRED;
2252
2253 #ifdef KTRACE
2254         if (KTRPOINT(curthread, KTR_SYSCTL))
2255                 ktrsysctl(name, namelen);
2256 #endif
2257         memlocked = 0;
2258         if (req.oldptr && req.oldlen > 4 * PAGE_SIZE) {
2259                 memlocked = 1;
2260                 sx_xlock(&sysctlmemlock);
2261         }
2262         CURVNET_SET(TD_TO_VNET(td));
2263
2264         for (;;) {
2265                 req.oldidx = 0;
2266                 req.newidx = 0;
2267                 error = sysctl_root(0, name, namelen, &req);
2268                 if (error != EAGAIN)
2269                         break;
2270                 kern_yield(PRI_USER);
2271         }
2272
2273         CURVNET_RESTORE();
2274
2275         if (req.lock == REQ_WIRED && req.validlen > 0)
2276                 vsunlock(req.oldptr, req.validlen);
2277         if (memlocked)
2278                 sx_xunlock(&sysctlmemlock);
2279
2280         if (error && error != ENOMEM)
2281                 return (error);
2282
2283         if (retval) {
2284                 if (req.oldptr && req.oldidx > req.validlen)
2285                         *retval = req.validlen;
2286                 else
2287                         *retval = req.oldidx;
2288         }
2289         return (error);
2290 }
2291
2292 /*
2293  * Drain into a sysctl struct.  The user buffer should be wired if a page
2294  * fault would cause issue.
2295  */
2296 static int
2297 sbuf_sysctl_drain(void *arg, const char *data, int len)
2298 {
2299         struct sysctl_req *req = arg;
2300         int error;
2301
2302         error = SYSCTL_OUT(req, data, len);
2303         KASSERT(error >= 0, ("Got unexpected negative value %d", error));
2304         return (error == 0 ? len : -error);
2305 }
2306
2307 struct sbuf *
2308 sbuf_new_for_sysctl(struct sbuf *s, char *buf, int length,
2309     struct sysctl_req *req)
2310 {
2311
2312         /* Supply a default buffer size if none given. */
2313         if (buf == NULL && length == 0)
2314                 length = 64;
2315         s = sbuf_new(s, buf, length, SBUF_FIXEDLEN | SBUF_INCLUDENUL);
2316         sbuf_set_drain(s, sbuf_sysctl_drain, req);
2317         return (s);
2318 }
2319
2320 #ifdef DDB
2321
2322 /* The current OID the debugger is working with */
2323 static struct sysctl_oid *g_ddb_oid;
2324
2325 /* The current flags specified by the user */
2326 static int g_ddb_sysctl_flags;
2327
2328 /* Check to see if the last sysctl printed */
2329 static int g_ddb_sysctl_printed;
2330
2331 static const int ctl_sign[CTLTYPE+1] = {
2332         [CTLTYPE_INT] = 1,
2333         [CTLTYPE_LONG] = 1,
2334         [CTLTYPE_S8] = 1,
2335         [CTLTYPE_S16] = 1,
2336         [CTLTYPE_S32] = 1,
2337         [CTLTYPE_S64] = 1,
2338 };
2339
2340 static const int ctl_size[CTLTYPE+1] = {
2341         [CTLTYPE_INT] = sizeof(int),
2342         [CTLTYPE_UINT] = sizeof(u_int),
2343         [CTLTYPE_LONG] = sizeof(long),
2344         [CTLTYPE_ULONG] = sizeof(u_long),
2345         [CTLTYPE_S8] = sizeof(int8_t),
2346         [CTLTYPE_S16] = sizeof(int16_t),
2347         [CTLTYPE_S32] = sizeof(int32_t),
2348         [CTLTYPE_S64] = sizeof(int64_t),
2349         [CTLTYPE_U8] = sizeof(uint8_t),
2350         [CTLTYPE_U16] = sizeof(uint16_t),
2351         [CTLTYPE_U32] = sizeof(uint32_t),
2352         [CTLTYPE_U64] = sizeof(uint64_t),
2353 };
2354
2355 #define DB_SYSCTL_NAME_ONLY     0x001   /* Compare with -N */
2356 #define DB_SYSCTL_VALUE_ONLY    0x002   /* Compare with -n */
2357 #define DB_SYSCTL_OPAQUE        0x004   /* Compare with -o */
2358 #define DB_SYSCTL_HEX           0x008   /* Compare with -x */
2359
2360 #define DB_SYSCTL_SAFE_ONLY     0x100   /* Only simple types */
2361
2362 static const char db_sysctl_modifs[] = {
2363         'N', 'n', 'o', 'x',
2364 };
2365
2366 static const int db_sysctl_modif_values[] = {
2367         DB_SYSCTL_NAME_ONLY, DB_SYSCTL_VALUE_ONLY,
2368         DB_SYSCTL_OPAQUE, DB_SYSCTL_HEX,
2369 };
2370
2371 /* Handlers considered safe to print while recursing */
2372 static int (* const db_safe_handlers[])(SYSCTL_HANDLER_ARGS) = {
2373         sysctl_handle_bool,
2374         sysctl_handle_8,
2375         sysctl_handle_16,
2376         sysctl_handle_32,
2377         sysctl_handle_64,
2378         sysctl_handle_int,
2379         sysctl_handle_long,
2380         sysctl_handle_string,
2381         sysctl_handle_opaque,
2382 };
2383
2384 /*
2385  * Use in place of sysctl_old_kernel to print sysctl values.
2386  *
2387  * Compare to the output handling in show_var from sbin/sysctl/sysctl.c
2388  */
2389 static int
2390 sysctl_old_ddb(struct sysctl_req *req, const void *ptr, size_t len)
2391 {
2392         const u_char *val, *p;
2393         const char *sep1;
2394         size_t intlen, slen;
2395         uintmax_t umv;
2396         intmax_t mv;
2397         int sign, ctltype, hexlen, xflag, error;
2398
2399         /* Suppress false-positive GCC uninitialized variable warnings */
2400         mv = 0;
2401         umv = 0;
2402
2403         slen = len;
2404         val = p = ptr;
2405
2406         if (ptr == NULL) {
2407                 error = 0;
2408                 goto out;
2409         }
2410
2411         /* We are going to print */
2412         g_ddb_sysctl_printed = 1;
2413
2414         xflag = g_ddb_sysctl_flags & DB_SYSCTL_HEX;
2415
2416         ctltype = (g_ddb_oid->oid_kind & CTLTYPE);
2417         sign = ctl_sign[ctltype];
2418         intlen = ctl_size[ctltype];
2419
2420         switch (ctltype) {
2421         case CTLTYPE_NODE:
2422         case CTLTYPE_STRING:
2423                 db_printf("%.*s", (int) len, (const char *) p);
2424                 error = 0;
2425                 goto out;
2426
2427         case CTLTYPE_INT:
2428         case CTLTYPE_UINT:
2429         case CTLTYPE_LONG:
2430         case CTLTYPE_ULONG:
2431         case CTLTYPE_S8:
2432         case CTLTYPE_S16:
2433         case CTLTYPE_S32:
2434         case CTLTYPE_S64:
2435         case CTLTYPE_U8:
2436         case CTLTYPE_U16:
2437         case CTLTYPE_U32:
2438         case CTLTYPE_U64:
2439                 hexlen = 2 + (intlen * CHAR_BIT + 3) / 4;
2440                 sep1 = "";
2441                 while (len >= intlen) {
2442                         switch (ctltype) {
2443                         case CTLTYPE_INT:
2444                         case CTLTYPE_UINT:
2445                                 umv = *(const u_int *)p;
2446                                 mv = *(const int *)p;
2447                                 break;
2448                         case CTLTYPE_LONG:
2449                         case CTLTYPE_ULONG:
2450                                 umv = *(const u_long *)p;
2451                                 mv = *(const long *)p;
2452                                 break;
2453                         case CTLTYPE_S8:
2454                         case CTLTYPE_U8:
2455                                 umv = *(const uint8_t *)p;
2456                                 mv = *(const int8_t *)p;
2457                                 break;
2458                         case CTLTYPE_S16:
2459                         case CTLTYPE_U16:
2460                                 umv = *(const uint16_t *)p;
2461                                 mv = *(const int16_t *)p;
2462                                 break;
2463                         case CTLTYPE_S32:
2464                         case CTLTYPE_U32:
2465                                 umv = *(const uint32_t *)p;
2466                                 mv = *(const int32_t *)p;
2467                                 break;
2468                         case CTLTYPE_S64:
2469                         case CTLTYPE_U64:
2470                                 umv = *(const uint64_t *)p;
2471                                 mv = *(const int64_t *)p;
2472                                 break;
2473                         }
2474
2475                         db_printf("%s", sep1);
2476                         if (xflag)
2477                                 db_printf("%#0*jx", hexlen, umv);
2478                         else if (!sign)
2479                                 db_printf("%ju", umv);
2480                         else if (g_ddb_oid->oid_fmt[1] == 'K') {
2481                                 /* Kelvins are currently unsupported. */
2482                                 error = EOPNOTSUPP;
2483                                 goto out;
2484                         } else
2485                                 db_printf("%jd", mv);
2486
2487                         sep1 = " ";
2488                         len -= intlen;
2489                         p += intlen;
2490                 }
2491                 error = 0;
2492                 goto out;
2493
2494         case CTLTYPE_OPAQUE:
2495                 /* TODO: Support struct functions. */
2496
2497                 /* FALLTHROUGH */
2498         default:
2499                 db_printf("Format:%s Length:%zu Dump:0x",
2500                     g_ddb_oid->oid_fmt, len);
2501                 while (len-- && (xflag || p < val + 16))
2502                         db_printf("%02x", *p++);
2503                 if (!xflag && len > 16)
2504                         db_printf("...");
2505                 error = 0;
2506                 goto out;
2507         }
2508
2509 out:
2510         req->oldidx += slen;
2511         return (error);
2512 }
2513
2514 /*
2515  * Avoid setting new sysctl values from the debugger
2516  */
2517 static int
2518 sysctl_new_ddb(struct sysctl_req *req, void *p, size_t l)
2519 {
2520
2521         if (!req->newptr)
2522                 return (0);
2523
2524         /* Changing sysctls from the debugger is currently unsupported */
2525         return (EPERM);
2526 }
2527
2528 /*
2529  * Run a sysctl handler with the DDB oldfunc and newfunc attached.
2530  * Instead of copying any output to a buffer we'll dump it right to
2531  * the console.
2532  */
2533 static int
2534 db_sysctl(struct sysctl_oid *oidp, int *name, u_int namelen,
2535     void *old, size_t *oldlenp, size_t *retval, int flags)
2536 {
2537         struct sysctl_req req;
2538         int error;
2539
2540         /* Setup the request */
2541         bzero(&req, sizeof req);
2542         req.td = kdb_thread;
2543         req.oldfunc = sysctl_old_ddb;
2544         req.newfunc = sysctl_new_ddb;
2545         req.lock = REQ_UNWIRED;
2546         if (oldlenp) {
2547                 req.oldlen = *oldlenp;
2548         }
2549         req.validlen = req.oldlen;
2550         if (old) {
2551                 req.oldptr = old;
2552         }
2553
2554         /* Setup our globals for sysctl_old_ddb */
2555         g_ddb_oid = oidp;
2556         g_ddb_sysctl_flags = flags;
2557         g_ddb_sysctl_printed = 0;
2558
2559         error = sysctl_root(0, name, namelen, &req);
2560
2561         /* Reset globals */
2562         g_ddb_oid = NULL;
2563         g_ddb_sysctl_flags = 0;
2564
2565         if (retval) {
2566                 if (req.oldptr && req.oldidx > req.validlen)
2567                         *retval = req.validlen;
2568                 else
2569                         *retval = req.oldidx;
2570         }
2571         return (error);
2572 }
2573
2574 /*
2575  * Show a sysctl's name
2576  */
2577 static void
2578 db_show_oid_name(int *oid, size_t nlen)
2579 {
2580         struct sysctl_oid *oidp;
2581         int qoid[CTL_MAXNAME+2];
2582         int error;
2583
2584         qoid[0] = 0;
2585         memcpy(qoid + 2, oid, nlen * sizeof(int));
2586         qoid[1] = 1;
2587
2588         error = sysctl_find_oid(qoid, nlen + 2, &oidp, NULL, NULL);
2589         if (error)
2590                 db_error("sysctl name oid");
2591
2592         error = db_sysctl(oidp, qoid, nlen + 2, NULL, NULL, NULL, 0);
2593         if (error)
2594                 db_error("sysctl name");
2595 }
2596
2597 /*
2598  * Check to see if an OID is safe to print from ddb.
2599  */
2600 static bool
2601 db_oid_safe(const struct sysctl_oid *oidp)
2602 {
2603         for (unsigned int i = 0; i < nitems(db_safe_handlers); ++i) {
2604                 if (oidp->oid_handler == db_safe_handlers[i])
2605                         return (true);
2606         }
2607
2608         return (false);
2609 }
2610
2611 /*
2612  * Show a sysctl at a specific OID
2613  * Compare to the input handling in show_var from sbin/sysctl/sysctl.c
2614  */
2615 static int
2616 db_show_oid(struct sysctl_oid *oidp, int *oid, size_t nlen, int flags)
2617 {
2618         int error, xflag, oflag, Nflag, nflag;
2619         size_t len;
2620
2621         xflag = flags & DB_SYSCTL_HEX;
2622         oflag = flags & DB_SYSCTL_OPAQUE;
2623         nflag = flags & DB_SYSCTL_VALUE_ONLY;
2624         Nflag = flags & DB_SYSCTL_NAME_ONLY;
2625
2626         if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_OPAQUE &&
2627             (!xflag && !oflag))
2628                 return (0);
2629
2630         if (Nflag) {
2631                 db_show_oid_name(oid, nlen);
2632                 error = 0;
2633                 goto out;
2634         }
2635
2636         if (!nflag) {
2637                 db_show_oid_name(oid, nlen);
2638                 db_printf(": ");
2639         }
2640
2641         if ((flags & DB_SYSCTL_SAFE_ONLY) && !db_oid_safe(oidp)) {
2642                 db_printf("Skipping, unsafe to print while recursing.");
2643                 error = 0;
2644                 goto out;
2645         }
2646
2647         /* Try once, and ask about the size */
2648         len = 0;
2649         error = db_sysctl(oidp, oid, nlen,
2650             NULL, NULL, &len, flags);
2651         if (error)
2652                 goto out;
2653
2654         if (!g_ddb_sysctl_printed)
2655                 /* Lie about the size */
2656                 error = db_sysctl(oidp, oid, nlen,
2657                     (void *) 1, &len, NULL, flags);
2658
2659 out:
2660         db_printf("\n");
2661         return (error);
2662 }
2663
2664 /*
2665  * Show all sysctls under a specific OID
2666  * Compare to sysctl_all from sbin/sysctl/sysctl.c
2667  */
2668 static int
2669 db_show_sysctl_all(int *oid, size_t len, int flags)
2670 {
2671         struct sysctl_oid *oidp;
2672         int name1[CTL_MAXNAME + 2], name2[CTL_MAXNAME + 2];
2673         size_t l1, l2;
2674
2675         name1[0] = CTL_SYSCTL;
2676         name1[1] = CTL_SYSCTL_NEXT;
2677         l1 = 2;
2678         if (len) {
2679                 memcpy(name1+2, oid, len * sizeof(int));
2680                 l1 +=len;
2681         } else {
2682                 name1[2] = 1;
2683                 l1++;
2684         }
2685         for (;;) {
2686                 int i, error;
2687
2688                 l2 = sizeof(name2);
2689                 error = kernel_sysctl(kdb_thread, name1, l1,
2690                     name2, &l2, NULL, 0, &l2, 0);
2691                 if (error != 0) {
2692                         if (error == ENOENT)
2693                                 return (0);
2694                         else
2695                                 db_error("sysctl(getnext)");
2696                 }
2697
2698                 l2 /= sizeof(int);
2699
2700                 if (l2 < (unsigned int)len)
2701                         return (0);
2702
2703                 for (i = 0; i < len; i++)
2704                         if (name2[i] != oid[i])
2705                                 return (0);
2706
2707                 /* Find the OID in question */
2708                 error = sysctl_find_oid(name2, l2, &oidp, NULL, NULL);
2709                 if (error)
2710                         return (error);
2711
2712                 i = db_show_oid(oidp, name2, l2, flags | DB_SYSCTL_SAFE_ONLY);
2713
2714                 if (db_pager_quit)
2715                         return (0);
2716
2717                 memcpy(name1+2, name2, l2 * sizeof(int));
2718                 l1 = 2 + l2;
2719         }
2720 }
2721
2722 /*
2723  * Show a sysctl by its user facing string
2724  */
2725 static int
2726 db_sysctlbyname(char *name, int flags)
2727 {
2728         struct sysctl_oid *oidp;
2729         int oid[CTL_MAXNAME];
2730         int error, nlen;
2731
2732         error = name2oid(name, oid, &nlen, &oidp);
2733         if (error) {
2734                 return (error);
2735         }
2736
2737         if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
2738                 db_show_sysctl_all(oid, nlen, flags);
2739         } else {
2740                 error = db_show_oid(oidp, oid, nlen, flags);
2741         }
2742
2743         return (error);
2744 }
2745
2746 static void
2747 db_sysctl_cmd_usage(void)
2748 {
2749         db_printf(
2750             " sysctl [/Nnox] <sysctl>                                       \n"
2751             "                                                               \n"
2752             " <sysctl> The name of the sysctl to show.                      \n"
2753             "                                                               \n"
2754             " Show a sysctl by hooking into SYSCTL_IN and SYSCTL_OUT.       \n"
2755             " This will work for most sysctls, but should not be used       \n"
2756             " with sysctls that are known to malloc.                        \n"
2757             "                                                               \n"
2758             " While recursing any \"unsafe\" sysctls will be skipped.       \n"
2759             " Call sysctl directly on the sysctl to try printing the        \n"
2760             " skipped sysctl. This is unsafe and may make the ddb           \n"
2761             " session unusable.                                             \n"
2762             "                                                               \n"
2763             " Arguments:                                                    \n"
2764             "   /N      Display only the name of the sysctl.                \n"
2765             "   /n      Display only the value of the sysctl.               \n"
2766             "   /o      Display opaque values.                              \n"
2767             "   /x      Display the sysctl in hex.                          \n"
2768             "                                                               \n"
2769             "For example:                                                   \n"
2770             "sysctl vm.v_free_min                                           \n"
2771             "vn.v_free_min: 12669                                           \n"
2772             );
2773 }
2774
2775 /*
2776  * Show a specific sysctl similar to sysctl (8).
2777  */
2778 DB_FUNC(sysctl, db_sysctl_cmd, db_cmd_table, CS_OWN, NULL)
2779 {
2780         char name[TOK_STRING_SIZE];
2781         int error, i, t, flags;
2782
2783         /* Parse the modifiers */
2784         t = db_read_token();
2785         if (t == tSLASH || t == tMINUS) {
2786                 t = db_read_token();
2787                 if (t != tIDENT) {
2788                         db_printf("Bad modifier\n");
2789                         error = EINVAL;
2790                         goto out;
2791                 }
2792                 db_strcpy(modif, db_tok_string);
2793         }
2794         else {
2795                 db_unread_token(t);
2796                 modif[0] = '\0';
2797         }
2798
2799         flags = 0;
2800         for (i = 0; i < nitems(db_sysctl_modifs); i++) {
2801                 if (strchr(modif, db_sysctl_modifs[i])) {
2802                         flags |= db_sysctl_modif_values[i];
2803                 }
2804         }
2805
2806         /* Parse the sysctl names */
2807         t = db_read_token();
2808         if (t != tIDENT) {
2809                 db_printf("Need sysctl name\n");
2810                 error = EINVAL;
2811                 goto out;
2812         }
2813
2814         /* Copy the name into a temporary buffer */
2815         db_strcpy(name, db_tok_string);
2816
2817         /* Ensure there is no trailing cruft */
2818         t = db_read_token();
2819         if (t != tEOL) {
2820                 db_printf("Unexpected sysctl argument\n");
2821                 error = EINVAL;
2822                 goto out;
2823         }
2824
2825         error = db_sysctlbyname(name, flags);
2826         if (error == ENOENT) {
2827                 db_printf("unknown oid: '%s'\n", db_tok_string);
2828                 goto out;
2829         } else if (error) {
2830                 db_printf("%s: error: %d\n", db_tok_string, error);
2831                 goto out;
2832         }
2833
2834 out:
2835         /* Ensure we eat all of our text */
2836         db_flush_lex();
2837
2838         if (error == EINVAL) {
2839                 db_sysctl_cmd_usage();
2840         }
2841 }
2842
2843 #endif /* DDB */