xref: /dragonfly/sys/kern/kern_sysctl.c (revision 926deccb)
1 /*-
2  * Copyright (c) 1982, 1986, 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Mike Karels at Berkeley Software Design, Inc.
7  *
8  * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD
9  * project, to make these variables more userfriendly.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  *	@(#)kern_sysctl.c	8.4 (Berkeley) 4/14/94
36  * $FreeBSD: src/sys/kern/kern_sysctl.c,v 1.92.2.9 2003/05/01 22:48:09 trhodes Exp $
37  */
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/buf.h>
43 #include <sys/sysctl.h>
44 #include <sys/malloc.h>
45 #include <sys/proc.h>
46 #include <sys/priv.h>
47 #include <sys/sysproto.h>
48 #include <sys/lock.h>
49 
50 #include <sys/mplock2.h>
51 
52 #include <vm/vm.h>
53 #include <vm/vm_extern.h>
54 
55 static MALLOC_DEFINE(M_SYSCTL, "sysctl", "sysctl internal magic");
56 static MALLOC_DEFINE(M_SYSCTLOID, "sysctloid", "sysctl dynamic oids");
57 
58 static struct lock sysctl_lkp;
59 static struct lock sysctl_ctx_lkp;
60 
61 static void	sysctl_lock(int type);
62 static void	sysctl_unlock(void);
63 static void	sysctl_ctx_lock(int type);
64 static void	sysctl_ctx_unlock(void);
65 
66 static int	sysctl_root(SYSCTL_HANDLER_ARGS);
67 static void	sysctl_register_oid_int(struct sysctl_oid *oipd);
68 static void	sysctl_unregister_oid_int(struct sysctl_oid *oipd);
69 static struct sysctl_ctx_entry* sysctl_ctx_entry_find_int
70 	(struct sysctl_ctx_list *, struct sysctl_oid *oidp);
71 
72 struct sysctl_oid_list sysctl__children; /* root list */
73 
74 static struct sysctl_oid *
75 sysctl_find_oidname(const char *name, struct sysctl_oid_list *list, int lock)
76 {
77 	struct sysctl_oid *oidp;
78 
79 	SLIST_FOREACH(oidp, list, oid_link) {
80 		if (strcmp(oidp->oid_name, name) == 0) {
81 			break;
82 		}
83 	}
84 	return (oidp);
85 }
86 
87 /*
88  * Initialization of the MIB tree.
89  *
90  * Order by number in each list.
91  */
92 
93 void
94 sysctl_register_oid(struct sysctl_oid *oidp)
95 {
96 	sysctl_lock(LK_EXCLUSIVE);
97 	sysctl_register_oid_int(oidp);
98 	sysctl_unlock();
99 }
100 
101 static void
102 sysctl_register_oid_int(struct sysctl_oid *oidp)
103 {
104 	struct sysctl_oid_list *parent = oidp->oid_parent;
105 	struct sysctl_oid *p;
106 	struct sysctl_oid *q;
107 
108 	/*
109 	 * First check if another oid with the same name already
110 	 * exists in the parent's list.
111 	 */
112 	p = sysctl_find_oidname(oidp->oid_name, parent, 0);
113 	if (p != NULL) {
114 		if ((p->oid_kind & CTLTYPE) == CTLTYPE_NODE)
115 			p->oid_refcnt++;
116 		else
117 			kprintf("can't re-use a leaf (%s)!\n", p->oid_name);
118 		return;
119 	}
120 
121 	/*
122 	 * If this oid has a number OID_AUTO, give it a number which
123 	 * is greater than any current oid.  Make sure it is at least
124 	 * 256 to leave space for pre-assigned oid numbers.
125 	 */
126 	if (oidp->oid_number == OID_AUTO) {
127 		int newoid = 0x100;	/* minimum AUTO oid */
128 
129 		/*
130 		 * Adjust based on highest oid in parent list
131 		 */
132 		SLIST_FOREACH(p, parent, oid_link) {
133 			if (newoid <= p->oid_number)
134 				newoid = p->oid_number + 1;
135 		}
136 		oidp->oid_number = newoid;
137 	}
138 
139 	/*
140 	 * Insert the oid into the parent's list in order.
141 	 */
142 	q = NULL;
143 	SLIST_FOREACH(p, parent, oid_link) {
144 		if (oidp->oid_number < p->oid_number)
145 			break;
146 		q = p;
147 	}
148 	if (q)
149 		SLIST_INSERT_AFTER(q, oidp, oid_link);
150 	else
151 		SLIST_INSERT_HEAD(parent, oidp, oid_link);
152 }
153 
154 void
155 sysctl_unregister_oid(struct sysctl_oid *oidp)
156 {
157 	sysctl_lock(LK_EXCLUSIVE);
158 	sysctl_unregister_oid_int(oidp);
159 	sysctl_unlock();
160 }
161 
162 static void
163 sysctl_unregister_oid_int(struct sysctl_oid *oidp)
164 {
165 	struct sysctl_oid *p;
166 
167 	if (oidp->oid_number == OID_AUTO)
168 		panic("Trying to unregister OID_AUTO entry: %p", oidp);
169 
170 	SLIST_FOREACH(p, oidp->oid_parent, oid_link) {
171 		if (p != oidp)
172 			continue;
173 		SLIST_REMOVE(oidp->oid_parent, oidp, sysctl_oid, oid_link);
174 		return;
175 	}
176 
177 	/*
178 	 * This can happen when a module fails to register and is
179 	 * being unloaded afterwards.  It should not be a panic()
180 	 * for normal use.
181 	 */
182 	kprintf("%s: failed to unregister sysctl\n", __func__);
183 }
184 
185 /* Initialize a new context to keep track of dynamically added sysctls. */
186 int
187 sysctl_ctx_init(struct sysctl_ctx_list *c)
188 {
189 	if (c == NULL)
190 		return(EINVAL);
191 	TAILQ_INIT(c);
192 	return(0);
193 }
194 
195 /* Free the context, and destroy all dynamic oids registered in this context */
196 int
197 sysctl_ctx_free(struct sysctl_ctx_list *clist)
198 {
199 	struct sysctl_ctx_entry *e, *e1;
200 	int error;
201 
202 	error = 0;
203 	sysctl_ctx_lock(LK_EXCLUSIVE);
204 	/*
205 	 * First perform a "dry run" to check if it's ok to remove oids.
206 	 * XXX FIXME
207 	 * XXX This algorithm is a hack. But I don't know any
208 	 * XXX better solution for now...
209 	 */
210 	TAILQ_FOREACH(e, clist, link) {
211 		error = sysctl_remove_oid(e->entry, 0, 0);
212 		if (error)
213 			break;
214 	}
215 	/*
216 	 * Restore deregistered entries, either from the end,
217 	 * or from the place where error occured.
218 	 * e contains the entry that was not unregistered
219 	 */
220 	if (error)
221 		e1 = TAILQ_PREV(e, sysctl_ctx_list, link);
222 	else
223 		e1 = TAILQ_LAST(clist, sysctl_ctx_list);
224 	while (e1 != NULL) {
225 		sysctl_register_oid(e1->entry);
226 		e1 = TAILQ_PREV(e1, sysctl_ctx_list, link);
227 	}
228 	if (error) {
229 		sysctl_ctx_unlock();
230 		return(EBUSY);
231 	}
232 	/* Now really delete the entries */
233 	e = TAILQ_FIRST(clist);
234 	while (e != NULL) {
235 		e1 = TAILQ_NEXT(e, link);
236 		error = sysctl_remove_oid(e->entry, 1, 0);
237 		if (error)
238 			panic("sysctl_remove_oid: corrupt tree, entry: %s",
239 			    e->entry->oid_name);
240 		kfree(e, M_SYSCTLOID);
241 		e = e1;
242 	}
243 	sysctl_ctx_unlock();
244 	return (error);
245 }
246 
247 /* Add an entry to the context */
248 struct sysctl_ctx_entry *
249 sysctl_ctx_entry_add(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
250 {
251 	struct sysctl_ctx_entry *e;
252 
253 	if (clist == NULL || oidp == NULL)
254 		return(NULL);
255 	e = kmalloc(sizeof(struct sysctl_ctx_entry), M_SYSCTLOID, M_WAITOK);
256 	e->entry = oidp;
257 	sysctl_ctx_lock(LK_EXCLUSIVE);
258 	TAILQ_INSERT_HEAD(clist, e, link);
259 	sysctl_ctx_unlock();
260 	return (e);
261 }
262 
263 /* Find an entry in the context */
264 struct sysctl_ctx_entry *
265 sysctl_ctx_entry_find(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
266 {
267 	struct sysctl_ctx_entry *e;
268 
269 	if (clist == NULL || oidp == NULL)
270 		return(NULL);
271 
272 	sysctl_ctx_lock(LK_SHARED);
273 	e = sysctl_ctx_entry_find_int(clist, oidp);
274 	sysctl_ctx_unlock();
275 
276 	return(e);
277 }
278 
279 struct sysctl_ctx_entry *
280 sysctl_ctx_entry_find_int(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
281 {
282 	struct sysctl_ctx_entry *e;
283 
284 	KKASSERT(clist != NULL && oidp != NULL);
285 
286 	for (e = TAILQ_FIRST(clist); e != NULL; e = TAILQ_NEXT(e, link)) {
287 		if(e->entry == oidp)
288 			break;
289 	}
290 
291 	return (e);
292 }
293 
294 /*
295  * Delete an entry from the context.
296  * NOTE: this function doesn't free oidp! You have to remove it
297  * with sysctl_remove_oid().
298  */
299 int
300 sysctl_ctx_entry_del(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
301 {
302 	struct sysctl_ctx_entry *e;
303 
304 	if (clist == NULL || oidp == NULL)
305 		return (EINVAL);
306 
307 	sysctl_ctx_lock(LK_EXCLUSIVE);
308 	e = sysctl_ctx_entry_find_int(clist, oidp);
309 	if (e == NULL) {
310 		sysctl_ctx_unlock();
311 		return (ENOENT);
312 	}
313 	TAILQ_REMOVE(clist, e, link);
314 	kfree(e, M_SYSCTLOID);
315 	sysctl_ctx_unlock();
316 
317 	return(0);
318 }
319 
320 /*
321  * Remove dynamically created sysctl trees.
322  * oidp - top of the tree to be removed
323  * del - if 0 - just deregister, otherwise free up entries as well
324  * recurse - if != 0 traverse the subtree to be deleted
325  */
326 int
327 sysctl_remove_oid(struct sysctl_oid *oidp, int del, int recurse)
328 {
329 	struct sysctl_oid *p;
330 	int error;
331 
332 	if (oidp == NULL)
333 		return(EINVAL);
334 	if ((oidp->oid_kind & CTLFLAG_DYN) == 0) {
335 		kprintf("can't remove non-dynamic nodes!\n");
336 		return (EINVAL);
337 	}
338 	sysctl_lock(LK_EXCLUSIVE | LK_CANRECURSE);
339 	/*
340 	 * WARNING: normal method to do this should be through
341 	 * sysctl_ctx_free(). Use recursing as the last resort
342 	 * method to purge your sysctl tree of leftovers...
343 	 * However, if some other code still references these nodes,
344 	 * it will panic.
345 	 */
346 	if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
347 		if (oidp->oid_refcnt == 1) {
348 			SLIST_FOREACH(p, SYSCTL_CHILDREN(oidp), oid_link) {
349 				if (!recurse) {
350 					sysctl_unlock();
351 					return(ENOTEMPTY);
352 				}
353 				error = sysctl_remove_oid(p, del, recurse);
354 				if (error) {
355 					sysctl_unlock();
356 					return(error);
357 				}
358 			}
359 			if (del)
360 				kfree(SYSCTL_CHILDREN(oidp), M_SYSCTLOID);
361 		}
362 	}
363 	if (oidp->oid_refcnt > 1 ) {
364 		oidp->oid_refcnt--;
365 	} else {
366 		if (oidp->oid_refcnt == 0) {
367 			kprintf("Warning: bad oid_refcnt=%u (%s)!\n",
368 			       oidp->oid_refcnt, oidp->oid_name);
369 			sysctl_unlock();
370 			return(EINVAL);
371 		}
372 		sysctl_unregister_oid_int(oidp);
373 		if (del) {
374 			if (oidp->oid_descr)
375 				kfree(__DECONST(char *,oidp->oid_descr),
376 				     M_SYSCTLOID);
377 			kfree(__DECONST(char *, oidp->oid_name), M_SYSCTLOID);
378 			kfree(oidp, M_SYSCTLOID);
379 		}
380 	}
381 	sysctl_unlock();
382 	return(0);
383 }
384 
385 /*
386  * Create new sysctls at run time.
387  * clist may point to a valid context initialized with sysctl_ctx_init().
388  */
389 struct sysctl_oid *
390 sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
391 	int number, const char *name, int kind, void *arg1, int arg2,
392 	int (*handler)(SYSCTL_HANDLER_ARGS), const char *fmt, const char *descr)
393 {
394 	struct sysctl_oid *oidp;
395 	ssize_t len;
396 	char *newname;
397 
398 	/* You have to hook up somewhere.. */
399 	if (parent == NULL)
400 		return(NULL);
401 	sysctl_lock(LK_EXCLUSIVE);
402 	/* Check if the node already exists, otherwise create it */
403 	oidp = sysctl_find_oidname(name, parent, 0);
404 	if (oidp != NULL) {
405 		if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
406 			oidp->oid_refcnt++;
407 			/* Update the context */
408 			if (clist != NULL)
409 				sysctl_ctx_entry_add(clist, oidp);
410 			sysctl_unlock();
411 			return (oidp);
412 		} else {
413 			kprintf("can't re-use a leaf (%s)!\n", name);
414 			sysctl_unlock();
415 			return (NULL);
416 		}
417 	}
418 	oidp = kmalloc(sizeof(struct sysctl_oid), M_SYSCTLOID, M_WAITOK | M_ZERO);
419 	oidp->oid_parent = parent;
420 	SLIST_NEXT(oidp, oid_link) = NULL;
421 	oidp->oid_number = number;
422 	oidp->oid_refcnt = 1;
423 	len = strlen(name);
424 	newname = kmalloc(len + 1, M_SYSCTLOID, M_WAITOK);
425 	bcopy(name, newname, len + 1);
426 	newname[len] = '\0';
427 	oidp->oid_name = newname;
428 	oidp->oid_handler = handler;
429 	oidp->oid_kind = CTLFLAG_DYN | kind;
430 	if ((kind & CTLTYPE) == CTLTYPE_NODE) {
431 		struct sysctl_oid_list *children;
432 
433 		/* Allocate space for children */
434 		children = kmalloc(sizeof(*children), M_SYSCTLOID, M_WAITOK);
435 		SYSCTL_SET_CHILDREN(oidp, children);
436 		SLIST_INIT(children);
437 	} else {
438 		oidp->oid_arg1 = arg1;
439 		oidp->oid_arg2 = arg2;
440 	}
441 	oidp->oid_fmt = fmt;
442 	if (descr) {
443 		int len = strlen(descr) + 1;
444 		oidp->oid_descr = kmalloc(len, M_SYSCTLOID, M_WAITOK);
445 		strcpy((char *)(uintptr_t)(const void *)oidp->oid_descr, descr);
446 	};
447 	/* Update the context, if used */
448 	if (clist != NULL)
449 		sysctl_ctx_entry_add(clist, oidp);
450 	/* Register this oid */
451 	sysctl_register_oid_int(oidp);
452 	sysctl_unlock();
453 	return (oidp);
454 }
455 
456 /*
457  * Register the kernel's oids on startup.
458  */
459 SET_DECLARE(sysctl_set, struct sysctl_oid);
460 
461 static void
462 sysctl_register_all(void *arg)
463 {
464 	struct sysctl_oid **oidp;
465 
466 	lockinit(&sysctl_lkp, "sysctl", 0, 0);
467 	lockinit(&sysctl_ctx_lkp, "sysctl ctx", 0, 0);
468 	SET_FOREACH(oidp, sysctl_set)
469 		sysctl_register_oid_int(*oidp);
470 }
471 
472 SYSINIT(sysctl, SI_BOOT1_POST, SI_ORDER_ANY, sysctl_register_all, 0);
473 
474 /*
475  * "Staff-functions"
476  *
477  * These functions implement a presently undocumented interface
478  * used by the sysctl program to walk the tree, and get the type
479  * so it can print the value.
480  * This interface is under work and consideration, and should probably
481  * be killed with a big axe by the first person who can find the time.
482  * (be aware though, that the proper interface isn't as obvious as it
483  * may seem, there are various conflicting requirements.
484  *
485  * {0,0}	kprintf the entire MIB-tree.
486  * {0,1,...}	return the name of the "..." OID.
487  * {0,2,...}	return the next OID.
488  * {0,3}	return the OID of the name in "new"
489  * {0,4,...}	return the kind & format info for the "..." OID.
490  */
491 
492 static void
493 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list *l, int i)
494 {
495 	int k;
496 	struct sysctl_oid *oidp;
497 
498 	sysctl_lock(LK_SHARED);
499 	SLIST_FOREACH(oidp, l, oid_link) {
500 
501 		for (k=0; k<i; k++)
502 			kprintf(" ");
503 
504 		kprintf("%d %s ", oidp->oid_number, oidp->oid_name);
505 
506 		kprintf("%c%c",
507 			oidp->oid_kind & CTLFLAG_RD ? 'R':' ',
508 			oidp->oid_kind & CTLFLAG_WR ? 'W':' ');
509 
510 		if (oidp->oid_handler)
511 			kprintf(" *Handler");
512 
513 		switch (oidp->oid_kind & CTLTYPE) {
514 			case CTLTYPE_NODE:
515 				kprintf(" Node\n");
516 				if (!oidp->oid_handler) {
517 					sysctl_sysctl_debug_dump_node(
518 						oidp->oid_arg1, i+2);
519 				}
520 				break;
521 			case CTLTYPE_INT:    kprintf(" Int\n"); break;
522 			case CTLTYPE_STRING: kprintf(" String\n"); break;
523 			case CTLTYPE_QUAD:   kprintf(" Quad\n"); break;
524 			case CTLTYPE_OPAQUE: kprintf(" Opaque/struct\n"); break;
525 			default:	     kprintf("\n");
526 		}
527 
528 	}
529 	sysctl_unlock();
530 }
531 
532 static int
533 sysctl_sysctl_debug(SYSCTL_HANDLER_ARGS)
534 {
535 	int error;
536 
537 	error = priv_check(req->td, PRIV_SYSCTL_DEBUG);
538 	if (error)
539 		return error;
540 	sysctl_sysctl_debug_dump_node(&sysctl__children, 0);
541 	return ENOENT;
542 }
543 
544 SYSCTL_PROC(_sysctl, 0, debug, CTLTYPE_STRING|CTLFLAG_RD,
545 	0, 0, sysctl_sysctl_debug, "-", "");
546 
547 static int
548 sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
549 {
550 	int *name = (int *) arg1;
551 	u_int namelen = arg2;
552 	int error = 0;
553 	struct sysctl_oid *oid;
554 	struct sysctl_oid_list *lsp = &sysctl__children, *lsp2;
555 	char buf[16];
556 
557 	sysctl_lock(LK_SHARED);
558 	while (namelen) {
559 		if (!lsp) {
560 			ksnprintf(buf, sizeof(buf), "%d", *name);
561 			if (req->oldidx)
562 				error = SYSCTL_OUT(req, ".", 1);
563 			if (!error)
564 				error = SYSCTL_OUT(req, buf, strlen(buf));
565 			if (error) {
566 				sysctl_unlock();
567 				return (error);
568 			}
569 			namelen--;
570 			name++;
571 			continue;
572 		}
573 		lsp2 = NULL;
574 		SLIST_FOREACH(oid, lsp, oid_link) {
575 			if (oid->oid_number != *name)
576 				continue;
577 
578 			if (req->oldidx)
579 				error = SYSCTL_OUT(req, ".", 1);
580 			if (!error)
581 				error = SYSCTL_OUT(req, oid->oid_name,
582 					strlen(oid->oid_name));
583 			if (error) {
584 				sysctl_unlock();
585 				return (error);
586 			}
587 
588 			namelen--;
589 			name++;
590 
591 			if ((oid->oid_kind & CTLTYPE) != CTLTYPE_NODE)
592 				break;
593 
594 			if (oid->oid_handler)
595 				break;
596 
597 			lsp2 = (struct sysctl_oid_list *)oid->oid_arg1;
598 			break;
599 		}
600 		lsp = lsp2;
601 	}
602 	sysctl_unlock();
603 	return (SYSCTL_OUT(req, "", 1));
604 }
605 
606 SYSCTL_NODE(_sysctl, 1, name, CTLFLAG_RD, sysctl_sysctl_name, "");
607 
608 static int
609 sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen,
610 	int *next, int *len, int level, struct sysctl_oid **oidpp)
611 {
612 	struct sysctl_oid *oidp;
613 
614 	*len = level;
615 	sysctl_lock(LK_SHARED);
616 	SLIST_FOREACH(oidp, lsp, oid_link) {
617 		*next = oidp->oid_number;
618 		*oidpp = oidp;
619 
620 		if (!namelen) {
621 			if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) {
622 				sysctl_unlock();
623 				return 0;
624 			}
625 			if (oidp->oid_handler) {
626 				/* We really should call the handler here...*/
627 				sysctl_unlock();
628 				return 0;
629 			}
630 			lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
631 			if (!sysctl_sysctl_next_ls(lsp, 0, 0, next+1,
632 				len, level+1, oidpp)) {
633 				sysctl_unlock();
634 				return 0;
635 			}
636 			goto emptynode;
637 		}
638 
639 		if (oidp->oid_number < *name)
640 			continue;
641 
642 		if (oidp->oid_number > *name) {
643 			if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) {
644 				sysctl_unlock();
645 				return 0;
646 			}
647 			if (oidp->oid_handler) {
648 				sysctl_unlock();
649 				return 0;
650 			}
651 			lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
652 			if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1,
653 				next+1, len, level+1, oidpp)) {
654 				sysctl_unlock();
655 				return (0);
656 			}
657 			goto next;
658 		}
659 		if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
660 			continue;
661 
662 		if (oidp->oid_handler)
663 			continue;
664 
665 		lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
666 		if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, next+1,
667 			len, level+1, oidpp)) {
668 			sysctl_unlock();
669 			return (0);
670 		}
671 	next:
672 		namelen = 1;
673 		*len = level;
674 	emptynode:
675 		*len = level;
676 	}
677 	sysctl_unlock();
678 	return 1;
679 }
680 
681 static int
682 sysctl_sysctl_next(SYSCTL_HANDLER_ARGS)
683 {
684 	int *name = (int *) arg1;
685 	u_int namelen = arg2;
686 	int i, j, error;
687 	struct sysctl_oid *oid;
688 	struct sysctl_oid_list *lsp = &sysctl__children;
689 	int newoid[CTL_MAXNAME];
690 
691 	i = sysctl_sysctl_next_ls(lsp, name, namelen, newoid, &j, 1, &oid);
692 	if (i)
693 		return ENOENT;
694 	error = SYSCTL_OUT(req, newoid, j * sizeof (int));
695 	return (error);
696 }
697 
698 SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD, sysctl_sysctl_next, "");
699 
700 static int
701 name2oid (char *name, int *oid, int *len, struct sysctl_oid **oidpp)
702 {
703 	int i;
704 	struct sysctl_oid *oidp;
705 	struct sysctl_oid_list *lsp = &sysctl__children;
706 	char *p;
707 
708 	if (!*name)
709 		return ENOENT;
710 
711 	p = name + strlen(name) - 1 ;
712 	if (*p == '.')
713 		*p = '\0';
714 
715 	*len = 0;
716 
717 	for (p = name; *p && *p != '.'; p++)
718 		;
719 	i = *p;
720 	if (i == '.')
721 		*p = '\0';
722 
723 	sysctl_lock(LK_SHARED);
724 	oidp = SLIST_FIRST(lsp);
725 
726 	while (oidp && *len < CTL_MAXNAME) {
727 		if (strcmp(name, oidp->oid_name)) {
728 			oidp = SLIST_NEXT(oidp, oid_link);
729 			continue;
730 		}
731 		*oid++ = oidp->oid_number;
732 		(*len)++;
733 
734 		if (!i) {
735 			if (oidpp)
736 				*oidpp = oidp;
737 			sysctl_unlock();
738 			return (0);
739 		}
740 
741 		if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
742 			break;
743 
744 		if (oidp->oid_handler)
745 			break;
746 
747 		lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
748 		oidp = SLIST_FIRST(lsp);
749 		name = p+1;
750 		for (p = name; *p && *p != '.'; p++)
751 				;
752 		i = *p;
753 		if (i == '.')
754 			*p = '\0';
755 	}
756 	sysctl_unlock();
757 	return ENOENT;
758 }
759 
760 static int
761 sysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS)
762 {
763 	char *p;
764 	int error, oid[CTL_MAXNAME], len;
765 	struct sysctl_oid *op = NULL;
766 
767 	if (!req->newlen)
768 		return ENOENT;
769 	if (req->newlen >= MAXPATHLEN)	/* XXX arbitrary, undocumented */
770 		return (ENAMETOOLONG);
771 
772 	p = kmalloc(req->newlen+1, M_SYSCTL, M_WAITOK);
773 
774 	error = SYSCTL_IN(req, p, req->newlen);
775 	if (error) {
776 		kfree(p, M_SYSCTL);
777 		return (error);
778 	}
779 
780 	p [req->newlen] = '\0';
781 
782 	error = name2oid(p, oid, &len, &op);
783 
784 	kfree(p, M_SYSCTL);
785 
786 	if (error)
787 		return (error);
788 
789 	error = SYSCTL_OUT(req, oid, len * sizeof *oid);
790 	return (error);
791 }
792 
793 SYSCTL_PROC(_sysctl, 3, name2oid, CTLFLAG_RW|CTLFLAG_ANYBODY, 0, 0,
794 	sysctl_sysctl_name2oid, "I", "");
795 
796 static int
797 sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS)
798 {
799 	struct sysctl_oid *oid;
800 	int error;
801 
802 	error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
803 	if (error)
804 		return (error);
805 
806 	if (!oid->oid_fmt)
807 		return (ENOENT);
808 	error = SYSCTL_OUT(req, &oid->oid_kind, sizeof(oid->oid_kind));
809 	if (error)
810 		return (error);
811 	error = SYSCTL_OUT(req, oid->oid_fmt, strlen(oid->oid_fmt) + 1);
812 	return (error);
813 }
814 
815 
816 SYSCTL_NODE(_sysctl, 4, oidfmt, CTLFLAG_RD, sysctl_sysctl_oidfmt, "");
817 
818 static int
819 sysctl_sysctl_oiddescr(SYSCTL_HANDLER_ARGS)
820 {
821 	struct sysctl_oid *oid;
822 	int error;
823 
824 	error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
825 	if (error)
826 		return (error);
827 
828 	if (!oid->oid_descr)
829 		return (ENOENT);
830 	error = SYSCTL_OUT(req, oid->oid_descr, strlen(oid->oid_descr) + 1);
831 	return (error);
832 }
833 
834 SYSCTL_NODE(_sysctl, 5, oiddescr, CTLFLAG_RD, sysctl_sysctl_oiddescr, "");
835 
836 /*
837  * Default "handler" functions.
838  */
839 
840 /*
841  * Handle an int, signed or unsigned.
842  * Two cases:
843  *     a variable:  point arg1 at it.
844  *     a constant:  pass it in arg2.
845  */
846 
847 int
848 sysctl_handle_int(SYSCTL_HANDLER_ARGS)
849 {
850 	int error = 0;
851 
852 	if (arg1)
853 		error = SYSCTL_OUT(req, arg1, sizeof(int));
854 	else
855 		error = SYSCTL_OUT(req, &arg2, sizeof(int));
856 
857 	if (error || !req->newptr)
858 		return (error);
859 
860 	if (!arg1)
861 		error = EPERM;
862 	else
863 		error = SYSCTL_IN(req, arg1, sizeof(int));
864 	return (error);
865 }
866 
867 /*
868  * Handle a long, signed or unsigned.  arg1 points to it.
869  */
870 
871 int
872 sysctl_handle_long(SYSCTL_HANDLER_ARGS)
873 {
874 	int error = 0;
875 
876 	if (!arg1)
877 		return (EINVAL);
878 	error = SYSCTL_OUT(req, arg1, sizeof(long));
879 
880 	if (error || !req->newptr)
881 		return (error);
882 
883 	error = SYSCTL_IN(req, arg1, sizeof(long));
884 	return (error);
885 }
886 
887 /*
888  * Handle a quad, signed or unsigned.  arg1 points to it.
889  */
890 
891 int
892 sysctl_handle_quad(SYSCTL_HANDLER_ARGS)
893 {
894 	int error = 0;
895 
896 	if (!arg1)
897 		return (EINVAL);
898 	error = SYSCTL_OUT(req, arg1, sizeof(quad_t));
899 
900 	if (error || !req->newptr)
901 		return (error);
902 
903 	error = SYSCTL_IN(req, arg1, sizeof(quad_t));
904 	return (error);
905 }
906 
907 /*
908  * Handle our generic '\0' terminated 'C' string.
909  * Two cases:
910  * 	a variable string:  point arg1 at it, arg2 is max length.
911  * 	a constant string:  point arg1 at it, arg2 is zero.
912  */
913 
914 int
915 sysctl_handle_string(SYSCTL_HANDLER_ARGS)
916 {
917 	int error=0;
918 
919 	error = SYSCTL_OUT(req, arg1, strlen((char *)arg1)+1);
920 
921 	if (error || !req->newptr)
922 		return (error);
923 
924 	if ((req->newlen - req->newidx) >= arg2) {
925 		error = EINVAL;
926 	} else {
927 		arg2 = (req->newlen - req->newidx);
928 		error = SYSCTL_IN(req, arg1, arg2);
929 		((char *)arg1)[arg2] = '\0';
930 	}
931 
932 	return (error);
933 }
934 
935 /*
936  * Handle any kind of opaque data.
937  * arg1 points to it, arg2 is the size.
938  */
939 
940 int
941 sysctl_handle_opaque(SYSCTL_HANDLER_ARGS)
942 {
943 	int error;
944 
945 	error = SYSCTL_OUT(req, arg1, arg2);
946 
947 	if (error || !req->newptr)
948 		return (error);
949 
950 	error = SYSCTL_IN(req, arg1, arg2);
951 
952 	return (error);
953 }
954 
955 /*
956  * Transfer functions to/from kernel space.
957  * XXX: rather untested at this point
958  */
959 static int
960 sysctl_old_kernel(struct sysctl_req *req, const void *p, size_t l)
961 {
962 	size_t i = 0;
963 
964 	if (req->oldptr) {
965 		i = l;
966 		if (i > req->oldlen - req->oldidx)
967 			i = req->oldlen - req->oldidx;
968 		if (i > 0)
969 			bcopy(p, (char *)req->oldptr + req->oldidx, i);
970 	}
971 	req->oldidx += l;
972 	if (req->oldptr && i != l)
973 		return (ENOMEM);
974 	return (0);
975 }
976 
977 static int
978 sysctl_new_kernel(struct sysctl_req *req, void *p, size_t l)
979 {
980 
981 	if (!req->newptr)
982 		return 0;
983 	if (req->newlen - req->newidx < l)
984 		return (EINVAL);
985 	bcopy((char *)req->newptr + req->newidx, p, l);
986 	req->newidx += l;
987 	return (0);
988 }
989 
990 int
991 kernel_sysctl(int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen, size_t *retval)
992 {
993 	int error = 0;
994 	struct sysctl_req req;
995 
996 	bzero(&req, sizeof req);
997 
998 	req.td = curthread;
999 
1000 	if (oldlenp) {
1001 		req.oldlen = *oldlenp;
1002 	}
1003 
1004 	if (old) {
1005 		req.oldptr = old;
1006 	}
1007 
1008 	if (new != NULL) {
1009 		req.newlen = newlen;
1010 		req.newptr = new;
1011 	}
1012 
1013 	req.oldfunc = sysctl_old_kernel;
1014 	req.newfunc = sysctl_new_kernel;
1015 #if 0
1016 	req.lock = 1;
1017 #endif
1018 
1019 	sysctl_lock(LK_SHARED);
1020 
1021 	error = sysctl_root(0, name, namelen, &req);
1022 
1023 #if 0
1024 	if (req.lock == 2)
1025 		vsunlock(req.oldptr, req.oldlen);
1026 #endif
1027 
1028 	sysctl_unlock();
1029 
1030 	if (error && error != ENOMEM)
1031 		return (error);
1032 
1033 	if (retval) {
1034 		if (req.oldptr && req.oldidx > req.oldlen)
1035 			*retval = req.oldlen;
1036 		else
1037 			*retval = req.oldidx;
1038 	}
1039 	return (error);
1040 }
1041 
1042 int
1043 kernel_sysctlbyname(char *name, void *old, size_t *oldlenp,
1044     void *new, size_t newlen, size_t *retval)
1045 {
1046         int oid[CTL_MAXNAME];
1047         size_t oidlen, plen;
1048 	int error;
1049 
1050 	oid[0] = 0;		/* sysctl internal magic */
1051 	oid[1] = 3;		/* name2oid */
1052 	oidlen = sizeof(oid);
1053 
1054 	error = kernel_sysctl(oid, 2, oid, &oidlen, name, strlen(name), &plen);
1055 	if (error)
1056 		return (error);
1057 
1058 	error = kernel_sysctl(oid, plen / sizeof(int), old, oldlenp,
1059 	    new, newlen, retval);
1060 	return (error);
1061 }
1062 
1063 /*
1064  * Transfer function to/from user space.
1065  */
1066 static int
1067 sysctl_old_user(struct sysctl_req *req, const void *p, size_t l)
1068 {
1069 	int error = 0;
1070 	size_t i = 0;
1071 
1072 #if 0
1073 	if (req->lock == 1 && req->oldptr) {
1074 		vslock(req->oldptr, req->oldlen);
1075 		req->lock = 2;
1076 	}
1077 #endif
1078 	if (req->oldptr) {
1079 		i = l;
1080 		if (i > req->oldlen - req->oldidx)
1081 			i = req->oldlen - req->oldidx;
1082 		if (i > 0)
1083 			error = copyout(p, (char *)req->oldptr + req->oldidx,
1084 					i);
1085 	}
1086 	req->oldidx += l;
1087 	if (error)
1088 		return (error);
1089 	if (req->oldptr && i < l)
1090 		return (ENOMEM);
1091 	return (0);
1092 }
1093 
1094 static int
1095 sysctl_new_user(struct sysctl_req *req, void *p, size_t l)
1096 {
1097 	int error;
1098 
1099 	if (!req->newptr)
1100 		return 0;
1101 	if (req->newlen - req->newidx < l)
1102 		return (EINVAL);
1103 	error = copyin((char *)req->newptr + req->newidx, p, l);
1104 	req->newidx += l;
1105 	return (error);
1106 }
1107 
1108 int
1109 sysctl_find_oid(int *name, u_int namelen, struct sysctl_oid **noid,
1110     int *nindx, struct sysctl_req *req)
1111 {
1112 	struct sysctl_oid *oid;
1113 	int indx;
1114 
1115 	sysctl_lock(LK_SHARED);
1116 	oid = SLIST_FIRST(&sysctl__children);
1117 	indx = 0;
1118 	while (oid && indx < CTL_MAXNAME) {
1119 		if (oid->oid_number == name[indx]) {
1120 			indx++;
1121 			if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
1122 				if (oid->oid_handler != NULL ||
1123 				    indx == namelen) {
1124 					*noid = oid;
1125 					if (nindx != NULL)
1126 						*nindx = indx;
1127 					sysctl_unlock();
1128 					return (0);
1129 				}
1130 				oid = SLIST_FIRST(
1131 				    (struct sysctl_oid_list *)oid->oid_arg1);
1132 			} else if (indx == namelen) {
1133 				*noid = oid;
1134 				if (nindx != NULL)
1135 					*nindx = indx;
1136 				sysctl_unlock();
1137 				return (0);
1138 			} else {
1139 				sysctl_unlock();
1140 				return (ENOTDIR);
1141 			}
1142 		} else {
1143 			oid = SLIST_NEXT(oid, oid_link);
1144 		}
1145 	}
1146 	sysctl_unlock();
1147 	return (ENOENT);
1148 }
1149 
1150 /*
1151  * Traverse our tree, and find the right node, execute whatever it points
1152  * to, and return the resulting error code.
1153  */
1154 
1155 int
1156 sysctl_root(SYSCTL_HANDLER_ARGS)
1157 {
1158 	struct thread *td = req->td;
1159 	struct proc *p = td ? td->td_proc : NULL;
1160 	struct sysctl_oid *oid;
1161 	int error, indx;
1162 
1163 	error = sysctl_find_oid(arg1, arg2, &oid, &indx, req);
1164 	if (error)
1165 		return (error);
1166 
1167 	if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
1168 		/*
1169 		 * You can't call a sysctl when it's a node, but has
1170 		 * no handler.  Inform the user that it's a node.
1171 		 * The indx may or may not be the same as namelen.
1172 		 */
1173 		if (oid->oid_handler == NULL)
1174 			return (EISDIR);
1175 	}
1176 
1177 	/* If writing isn't allowed */
1178 	if (req->newptr && (!(oid->oid_kind & CTLFLAG_WR) ||
1179 	    ((oid->oid_kind & CTLFLAG_SECURE) && securelevel > 0)))
1180 		return (EPERM);
1181 
1182 	/* Most likely only root can write */
1183 	if (!(oid->oid_kind & CTLFLAG_ANYBODY) && req->newptr && p &&
1184 	    (error = priv_check_cred(td->td_ucred,
1185 	     (oid->oid_kind & CTLFLAG_PRISON) ? PRIV_SYSCTL_WRITEJAIL :
1186 	                                        PRIV_SYSCTL_WRITE, 0)))
1187 		return (error);
1188 
1189 	if (!oid->oid_handler)
1190 		return EINVAL;
1191 
1192 	if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE)
1193 		error = oid->oid_handler(oid, (int *)arg1 + indx, arg2 - indx,
1194 		    req);
1195 	else
1196 		error = oid->oid_handler(oid, oid->oid_arg1, oid->oid_arg2,
1197 		    req);
1198 	return (error);
1199 }
1200 
1201 /*
1202  * MPALMOSTSAFE
1203  */
1204 int
1205 sys___sysctl(struct sysctl_args *uap)
1206 {
1207 	int error, i, name[CTL_MAXNAME];
1208 	size_t j;
1209 
1210 	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1211 		return (EINVAL);
1212 
1213 	error = copyin(uap->name, &name, uap->namelen * sizeof(int));
1214  	if (error)
1215 		return (error);
1216 
1217 	error = userland_sysctl(name, uap->namelen,
1218 		uap->old, uap->oldlenp, 0,
1219 		uap->new, uap->newlen, &j);
1220 	if (error && error != ENOMEM)
1221 		return (error);
1222 	if (uap->oldlenp) {
1223 		i = copyout(&j, uap->oldlenp, sizeof(j));
1224 		if (i)
1225 			return (i);
1226 	}
1227 	return (error);
1228 }
1229 
1230 /*
1231  * This is used from various compatibility syscalls too.  That's why name
1232  * must be in kernel space.
1233  */
1234 int
1235 userland_sysctl(int *name, u_int namelen, void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen, size_t *retval)
1236 {
1237 	int error = 0;
1238 	struct sysctl_req req, req2;
1239 
1240 	bzero(&req, sizeof req);
1241 
1242 	if (oldlenp) {
1243 		if (inkernel) {
1244 			req.oldlen = *oldlenp;
1245 		} else {
1246 			error = copyin(oldlenp, &req.oldlen, sizeof(*oldlenp));
1247 			if (error)
1248 				return (error);
1249 		}
1250 	}
1251 
1252 	if (old) {
1253 		if (!useracc(old, req.oldlen, VM_PROT_WRITE))
1254 			return (EFAULT);
1255 		req.oldptr= old;
1256 	}
1257 
1258 	if (new != NULL) {
1259 		if (!useracc(new, newlen, VM_PROT_READ))
1260 			return (EFAULT);
1261 		req.newlen = newlen;
1262 		req.newptr = new;
1263 	}
1264 
1265 	req.oldfunc = sysctl_old_user;
1266 	req.newfunc = sysctl_new_user;
1267 #if 0
1268 	req.lock = 1;
1269 #endif
1270 	req.td = curthread;
1271 
1272 	sysctl_lock(LK_SHARED);
1273 
1274 	do {
1275 	    req2 = req;
1276 	    error = sysctl_root(0, name, namelen, &req2);
1277 	} while (error == EAGAIN);
1278 
1279 	req = req2;
1280 #if 0
1281 	if (req.lock == 2)
1282 		vsunlock(req.oldptr, req.oldlen);
1283 #endif
1284 
1285 	sysctl_unlock();
1286 
1287 	if (error && error != ENOMEM)
1288 		return (error);
1289 
1290 	if (retval) {
1291 		if (req.oldptr && req.oldidx > req.oldlen)
1292 			*retval = req.oldlen;
1293 		else
1294 			*retval = req.oldidx;
1295 	}
1296 	return (error);
1297 }
1298 
1299 static void
1300 sysctl_lock(int flag)
1301 {
1302 	lockmgr(&sysctl_lkp, flag);
1303 }
1304 
1305 static void
1306 sysctl_unlock(void)
1307 {
1308 	lockmgr(&sysctl_lkp, LK_RELEASE);
1309 }
1310 
1311 static void
1312 sysctl_ctx_lock(int flag)
1313 {
1314 	lockmgr(&sysctl_ctx_lkp, flag);
1315 }
1316 
1317 static void
1318 sysctl_ctx_unlock(void)
1319 {
1320 	lockmgr(&sysctl_ctx_lkp, LK_RELEASE);
1321 }
1322 
1323 int
1324 sysctl_int_range(SYSCTL_HANDLER_ARGS, int low, int high)
1325 {
1326 	int error, value;
1327 
1328 	value = *(int *)arg1;
1329 	error = sysctl_handle_int(oidp, &value, 0, req);
1330 	if (error || !req->newptr)
1331 		return (error);
1332 	if (value < low || value > high)
1333 		return (EINVAL);
1334 	*(int *)arg1 = value;
1335 	return (0);
1336 }
1337