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