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