xref: /freebsd/sys/kern/kern_sysctl.c (revision 4b2af45f4ba1f8d8d5a56c4b18f29da6d08146e9)
1df8bae1dSRodney W. Grimes /*-
2df8bae1dSRodney W. Grimes  * Copyright (c) 1982, 1986, 1989, 1993
3df8bae1dSRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
4df8bae1dSRodney W. Grimes  *
5df8bae1dSRodney W. Grimes  * This code is derived from software contributed to Berkeley by
6df8bae1dSRodney W. Grimes  * Mike Karels at Berkeley Software Design, Inc.
7df8bae1dSRodney W. Grimes  *
8df8bae1dSRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
9df8bae1dSRodney W. Grimes  * modification, are permitted provided that the following conditions
10df8bae1dSRodney W. Grimes  * are met:
11df8bae1dSRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
12df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
13df8bae1dSRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
14df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
15df8bae1dSRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
16df8bae1dSRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
17df8bae1dSRodney W. Grimes  *    must display the following acknowledgement:
18df8bae1dSRodney W. Grimes  *	This product includes software developed by the University of
19df8bae1dSRodney W. Grimes  *	California, Berkeley and its contributors.
20df8bae1dSRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
21df8bae1dSRodney W. Grimes  *    may be used to endorse or promote products derived from this software
22df8bae1dSRodney W. Grimes  *    without specific prior written permission.
23df8bae1dSRodney W. Grimes  *
24df8bae1dSRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25df8bae1dSRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26df8bae1dSRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27df8bae1dSRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28df8bae1dSRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29df8bae1dSRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30df8bae1dSRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31df8bae1dSRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32df8bae1dSRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33df8bae1dSRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34df8bae1dSRodney W. Grimes  * SUCH DAMAGE.
35df8bae1dSRodney W. Grimes  *
36df8bae1dSRodney W. Grimes  *	@(#)kern_sysctl.c	8.4 (Berkeley) 4/14/94
374b2af45fSPoul-Henning Kamp  * $Id: kern_sysctl.c,v 1.51 1995/11/16 18:59:49 phk Exp $
38df8bae1dSRodney W. Grimes  */
39df8bae1dSRodney W. Grimes 
40df8bae1dSRodney W. Grimes /*
41df8bae1dSRodney W. Grimes  * sysctl system call.
42df8bae1dSRodney W. Grimes  */
43df8bae1dSRodney W. Grimes 
44df8bae1dSRodney W. Grimes #include <sys/param.h>
45df8bae1dSRodney W. Grimes #include <sys/systm.h>
46d2d3e875SBruce Evans #include <sys/sysproto.h>
47df8bae1dSRodney W. Grimes #include <sys/kernel.h>
48df8bae1dSRodney W. Grimes #include <sys/vnode.h>
49df8bae1dSRodney W. Grimes #include <sys/unistd.h>
505bb4f738SGarrett Wollman #include <sys/conf.h>
51df8bae1dSRodney W. Grimes #include <sys/sysctl.h>
52df8bae1dSRodney W. Grimes 
534b2af45fSPoul-Henning Kamp /*
544b2af45fSPoul-Henning Kamp  * Locking and stats
554b2af45fSPoul-Henning Kamp  */
564b2af45fSPoul-Henning Kamp static struct sysctl_lock {
574b2af45fSPoul-Henning Kamp 	int	sl_lock;
584b2af45fSPoul-Henning Kamp 	int	sl_want;
594b2af45fSPoul-Henning Kamp 	int	sl_locked;
604b2af45fSPoul-Henning Kamp } memlock;
614b2af45fSPoul-Henning Kamp 
624b2af45fSPoul-Henning Kamp static int sysctl_root SYSCTL_HANDLER_ARGS;
634b2af45fSPoul-Henning Kamp 
64787d58f2SPoul-Henning Kamp extern struct linker_set sysctl_;
65787d58f2SPoul-Henning Kamp 
66b396cd83SPoul-Henning Kamp /* BEGIN_MIB */
67787d58f2SPoul-Henning Kamp SYSCTL_NODE(, 0,	  sysctl, CTLFLAG_RW, 0,
68787d58f2SPoul-Henning Kamp 	"Sysctl internal magic");
692e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_KERN,	  kern,   CTLFLAG_RW, 0,
702e210993SPoul-Henning Kamp 	"High kernel, proc, limits &c");
712e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_VM,	  vm,     CTLFLAG_RW, 0,
722e210993SPoul-Henning Kamp 	"Virtual memory");
732e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_FS,	  fs,     CTLFLAG_RW, 0,
742e210993SPoul-Henning Kamp 	"File system");
752e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_NET,	  net,    CTLFLAG_RW, 0,
762e210993SPoul-Henning Kamp 	"Network, (see socket.h)");
772e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_DEBUG,  debug,  CTLFLAG_RW, 0,
782e210993SPoul-Henning Kamp 	"Debugging");
792e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_HW,	  hw,     CTLFLAG_RW, 0,
802e210993SPoul-Henning Kamp 	"hardware");
812e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_MACHDEP, machdep, CTLFLAG_RW, 0,
822e210993SPoul-Henning Kamp 	"machine dependent");
832e210993SPoul-Henning Kamp SYSCTL_NODE(, CTL_USER,	  user,   CTLFLAG_RW, 0,
842e210993SPoul-Henning Kamp 	"user-level");
85b396cd83SPoul-Henning Kamp 
862e210993SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_OSRELEASE, osrelease, CTLFLAG_RD, osrelease, 0, "");
87b396cd83SPoul-Henning Kamp 
882e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_OSREV, osrevision, CTLFLAG_RD, 0, BSD, "");
89b396cd83SPoul-Henning Kamp 
902e210993SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_VERSION, version, CTLFLAG_RD, version, 0, "");
91b396cd83SPoul-Henning Kamp 
922e210993SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_OSTYPE, ostype, CTLFLAG_RD, ostype, 0, "");
93b396cd83SPoul-Henning Kamp 
94b396cd83SPoul-Henning Kamp extern int osreldate;
952e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_OSRELDATE, osreldate, CTLFLAG_RD, &osreldate, 0, "");
96b396cd83SPoul-Henning Kamp 
972e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXVNODES, maxvnodes, CTLFLAG_RD, &desiredvnodes, 0, "");
98b396cd83SPoul-Henning Kamp 
992e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXPROC, maxproc, CTLFLAG_RD, &maxproc, 0, "");
100b396cd83SPoul-Henning Kamp 
101b396cd83SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_MAXPROCPERUID, maxprocperuid,
1023a34a5c3SPoul-Henning Kamp 	CTLFLAG_RD, &maxprocperuid, 0, "");
103b396cd83SPoul-Henning Kamp 
1042e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_ARGMAX, argmax, CTLFLAG_RD, 0, ARG_MAX, "");
105b396cd83SPoul-Henning Kamp 
1062e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_POSIX1, posix1version, CTLFLAG_RD, 0, _POSIX_VERSION, "");
107b396cd83SPoul-Henning Kamp 
1082e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_NGROUPS, ngroups, CTLFLAG_RD, 0, NGROUPS_MAX, "");
109b396cd83SPoul-Henning Kamp 
1102e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_JOB_CONTROL, job_control, CTLFLAG_RD, 0, 1, "");
111b396cd83SPoul-Henning Kamp 
112b396cd83SPoul-Henning Kamp #ifdef _POSIX_SAVED_IDS
1132e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD, 0, 1, "");
114b396cd83SPoul-Henning Kamp #else
1152e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD, 0, 0, "");
116b396cd83SPoul-Henning Kamp #endif
117b396cd83SPoul-Henning Kamp 
118b396cd83SPoul-Henning Kamp char kernelname[MAXPATHLEN] = "/kernel";	/* XXX bloat */
119b396cd83SPoul-Henning Kamp 
120b396cd83SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_BOOTFILE, bootfile,
1213a34a5c3SPoul-Henning Kamp 	CTLFLAG_RW, kernelname, sizeof kernelname, "");
122b396cd83SPoul-Henning Kamp 
123b396cd83SPoul-Henning Kamp SYSCTL_STRUCT(_kern, KERN_BOOTTIME, boottime,
1243a34a5c3SPoul-Henning Kamp 	CTLFLAG_RW, &boottime, timeval, "");
125b396cd83SPoul-Henning Kamp 
1262e210993SPoul-Henning Kamp SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
127b396cd83SPoul-Henning Kamp 
128787d58f2SPoul-Henning Kamp SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, "");
129b396cd83SPoul-Henning Kamp 
1302e210993SPoul-Henning Kamp SYSCTL_INT(_hw, HW_NCPU, ncpu, CTLFLAG_RD, 0, 1, "");
131b396cd83SPoul-Henning Kamp 
1322e210993SPoul-Henning Kamp SYSCTL_INT(_hw, HW_BYTEORDER, byteorder, CTLFLAG_RD, 0, BYTE_ORDER, "");
133b396cd83SPoul-Henning Kamp 
1342e210993SPoul-Henning Kamp SYSCTL_INT(_hw, HW_PAGESIZE, pagesize, CTLFLAG_RD, 0, PAGE_SIZE, "");
135b396cd83SPoul-Henning Kamp 
136b396cd83SPoul-Henning Kamp /* END_MIB */
137b396cd83SPoul-Henning Kamp 
138b396cd83SPoul-Henning Kamp extern int vfs_update_wakeup;
139b396cd83SPoul-Henning Kamp extern int vfs_update_interval;
140b396cd83SPoul-Henning Kamp static int
1413a34a5c3SPoul-Henning Kamp sysctl_kern_updateinterval SYSCTL_HANDLER_ARGS
142b396cd83SPoul-Henning Kamp {
1433a34a5c3SPoul-Henning Kamp 	int error = sysctl_handle_int(oidp,
144ae0eb976SPoul-Henning Kamp 		oidp->oid_arg1, oidp->oid_arg2, req);
1453a34a5c3SPoul-Henning Kamp 	if (!error)
146b396cd83SPoul-Henning Kamp 		wakeup(&vfs_update_wakeup);
1473a34a5c3SPoul-Henning Kamp 	return error;
148b396cd83SPoul-Henning Kamp }
149b396cd83SPoul-Henning Kamp 
1502e210993SPoul-Henning Kamp SYSCTL_PROC(_kern, KERN_UPDATEINTERVAL, update, CTLTYPE_INT|CTLFLAG_RW,
1513a34a5c3SPoul-Henning Kamp 	&vfs_update_interval, 0, sysctl_kern_updateinterval, "");
152b396cd83SPoul-Henning Kamp 
1532e210993SPoul-Henning Kamp 
1542e210993SPoul-Henning Kamp char hostname[MAXHOSTNAMELEN];
1552e210993SPoul-Henning Kamp 
1569565c0e6SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_HOSTNAME, hostname, CTLFLAG_RW,
1579565c0e6SPoul-Henning Kamp 	hostname, sizeof(hostname), "");
1582e210993SPoul-Henning Kamp 
1594b2af45fSPoul-Henning Kamp int securelevel = -1;
1604b2af45fSPoul-Henning Kamp 
1614b2af45fSPoul-Henning Kamp static int
1624b2af45fSPoul-Henning Kamp sysctl_kern_securelvl SYSCTL_HANDLER_ARGS
1634b2af45fSPoul-Henning Kamp {
1644b2af45fSPoul-Henning Kamp 		int error, level;
1654b2af45fSPoul-Henning Kamp 
1664b2af45fSPoul-Henning Kamp 		level = securelevel;
1674b2af45fSPoul-Henning Kamp 		error = sysctl_handle_int(oidp, &level, 0, req);
1684b2af45fSPoul-Henning Kamp 		if (error || !req->newptr)
1694b2af45fSPoul-Henning Kamp 			return (error);
1704b2af45fSPoul-Henning Kamp 		if (level < securelevel && req->p->p_pid != 1)
1714b2af45fSPoul-Henning Kamp 			return (EPERM);
1724b2af45fSPoul-Henning Kamp 		securelevel = level;
1734b2af45fSPoul-Henning Kamp 		return (error);
1744b2af45fSPoul-Henning Kamp }
1754b2af45fSPoul-Henning Kamp 
1764b2af45fSPoul-Henning Kamp SYSCTL_PROC(_kern, KERN_SECURELVL, securelevel, CTLTYPE_INT|CTLFLAG_RW,
1774b2af45fSPoul-Henning Kamp 	0, 0, sysctl_kern_securelvl, "");
1784b2af45fSPoul-Henning Kamp 
1794b2af45fSPoul-Henning Kamp static int
1804b2af45fSPoul-Henning Kamp sysctl_kern_dumpdev SYSCTL_HANDLER_ARGS
1814b2af45fSPoul-Henning Kamp {
1824b2af45fSPoul-Henning Kamp 	int error;
1834b2af45fSPoul-Henning Kamp 	dev_t ndumpdev;
1844b2af45fSPoul-Henning Kamp 
1854b2af45fSPoul-Henning Kamp 	ndumpdev = dumpdev;
1864b2af45fSPoul-Henning Kamp 	error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req);
1874b2af45fSPoul-Henning Kamp 	if (!error && ndumpdev != dumpdev) {
1884b2af45fSPoul-Henning Kamp 		error = setdumpdev(ndumpdev);
1894b2af45fSPoul-Henning Kamp 	}
1904b2af45fSPoul-Henning Kamp 	return (error);
1914b2af45fSPoul-Henning Kamp }
1924b2af45fSPoul-Henning Kamp 
1934b2af45fSPoul-Henning Kamp SYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW,
1944b2af45fSPoul-Henning Kamp 	0, sizeof dumpdev, sysctl_kern_dumpdev, "");
1954b2af45fSPoul-Henning Kamp 
1964b2af45fSPoul-Henning Kamp static int
1974b2af45fSPoul-Henning Kamp sysctl_hw_physmem SYSCTL_HANDLER_ARGS
1984b2af45fSPoul-Henning Kamp {
1994b2af45fSPoul-Henning Kamp 	int error = sysctl_handle_int(oidp, 0, ctob(physmem), req);
2004b2af45fSPoul-Henning Kamp 	return (error);
2014b2af45fSPoul-Henning Kamp }
2024b2af45fSPoul-Henning Kamp 
2034b2af45fSPoul-Henning Kamp SYSCTL_PROC(_hw, HW_PHYSMEM, physmem, CTLTYPE_INT|CTLFLAG_RD,
2044b2af45fSPoul-Henning Kamp 	0, 0, sysctl_hw_physmem, "");
2054b2af45fSPoul-Henning Kamp 
2064b2af45fSPoul-Henning Kamp static int
2074b2af45fSPoul-Henning Kamp sysctl_hw_usermem SYSCTL_HANDLER_ARGS
2084b2af45fSPoul-Henning Kamp {
2094b2af45fSPoul-Henning Kamp 	int error = sysctl_handle_int(oidp, 0,
2104b2af45fSPoul-Henning Kamp 		ctob(physmem - cnt.v_wire_count), req);
2114b2af45fSPoul-Henning Kamp 	return (error);
2124b2af45fSPoul-Henning Kamp }
2134b2af45fSPoul-Henning Kamp 
2144b2af45fSPoul-Henning Kamp SYSCTL_PROC(_hw, HW_USERMEM, usermem, CTLTYPE_INT|CTLFLAG_RD,
2154b2af45fSPoul-Henning Kamp 	0, 0, sysctl_hw_usermem, "");
2164b2af45fSPoul-Henning Kamp 
2174b2af45fSPoul-Henning Kamp /* END_MIB */
2184b2af45fSPoul-Henning Kamp 
219787d58f2SPoul-Henning Kamp static int
2203c8e79ddSBruce Evans sysctl_order_cmp(const void *a, const void *b)
221787d58f2SPoul-Henning Kamp {
2223c8e79ddSBruce Evans 	const struct sysctl_oid **pa, **pb;
2233c8e79ddSBruce Evans 
2243c8e79ddSBruce Evans 	pa = (const struct sysctl_oid **)a;
2253c8e79ddSBruce Evans 	pb = (const struct sysctl_oid **)b;
2263c8e79ddSBruce Evans 	if (*pa == NULL)
2273c8e79ddSBruce Evans 		return (1);
2283c8e79ddSBruce Evans 	if (*pb == NULL)
2293c8e79ddSBruce Evans 		return (-1);
230787d58f2SPoul-Henning Kamp 	return ((*pa)->oid_number - (*pb)->oid_number);
231787d58f2SPoul-Henning Kamp }
232787d58f2SPoul-Henning Kamp 
233787d58f2SPoul-Henning Kamp static void
234787d58f2SPoul-Henning Kamp sysctl_order(void *arg)
235787d58f2SPoul-Henning Kamp {
236b8da2396SPoul-Henning Kamp 	int j;
237787d58f2SPoul-Henning Kamp 	struct linker_set *l = (struct linker_set *) arg;
238787d58f2SPoul-Henning Kamp 	struct sysctl_oid **oidpp;
239787d58f2SPoul-Henning Kamp 
240787d58f2SPoul-Henning Kamp 	j = l->ls_length;
241787d58f2SPoul-Henning Kamp 	oidpp = (struct sysctl_oid **) l->ls_items;
242787d58f2SPoul-Henning Kamp 	for (; j--; oidpp++) {
243787d58f2SPoul-Henning Kamp 		if (!*oidpp)
244787d58f2SPoul-Henning Kamp 			continue;
245787d58f2SPoul-Henning Kamp 		if ((*oidpp)->oid_arg1 == arg) {
246787d58f2SPoul-Henning Kamp 			*oidpp = 0;
247787d58f2SPoul-Henning Kamp 			continue;
248787d58f2SPoul-Henning Kamp 		}
249787d58f2SPoul-Henning Kamp 		if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE)
250787d58f2SPoul-Henning Kamp 			if (!(*oidpp)->oid_handler)
251787d58f2SPoul-Henning Kamp 				sysctl_order((*oidpp)->oid_arg1);
252787d58f2SPoul-Henning Kamp 	}
253787d58f2SPoul-Henning Kamp 	qsort(l->ls_items, l->ls_length, sizeof l->ls_items[0],
254787d58f2SPoul-Henning Kamp 		sysctl_order_cmp);
255787d58f2SPoul-Henning Kamp }
256787d58f2SPoul-Henning Kamp 
257787d58f2SPoul-Henning Kamp SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_order, &sysctl_);
258787d58f2SPoul-Henning Kamp 
259787d58f2SPoul-Henning Kamp static void
260787d58f2SPoul-Henning Kamp sysctl_sysctl_debug_dump_node(struct linker_set *l, int i)
261787d58f2SPoul-Henning Kamp {
262787d58f2SPoul-Henning Kamp 	int j, k;
263787d58f2SPoul-Henning Kamp 	struct sysctl_oid **oidpp;
264787d58f2SPoul-Henning Kamp 
265787d58f2SPoul-Henning Kamp 	j = l->ls_length;
266787d58f2SPoul-Henning Kamp 	oidpp = (struct sysctl_oid **) l->ls_items;
267787d58f2SPoul-Henning Kamp 	for (; j--; oidpp++) {
268787d58f2SPoul-Henning Kamp 
269787d58f2SPoul-Henning Kamp 		if (!*oidpp)
270787d58f2SPoul-Henning Kamp 			continue;
271787d58f2SPoul-Henning Kamp 
272787d58f2SPoul-Henning Kamp 		for (k=0; k<i; k++)
273787d58f2SPoul-Henning Kamp 			printf(" ");
274787d58f2SPoul-Henning Kamp 
275787d58f2SPoul-Henning Kamp 		if ((*oidpp)->oid_number > 100) {
276b8da2396SPoul-Henning Kamp 			printf("Junk! %p  # %d  %s  k %x  a1 %p  a2 %x  h %p\n",
277787d58f2SPoul-Henning Kamp 				*oidpp,
278787d58f2SPoul-Henning Kamp 		 		(*oidpp)->oid_number, (*oidpp)->oid_name,
279787d58f2SPoul-Henning Kamp 		 		(*oidpp)->oid_kind, (*oidpp)->oid_arg1,
280787d58f2SPoul-Henning Kamp 		 		(*oidpp)->oid_arg2, (*oidpp)->oid_handler);
281787d58f2SPoul-Henning Kamp 			continue;
282787d58f2SPoul-Henning Kamp 		}
283787d58f2SPoul-Henning Kamp 		printf("%d %s ", (*oidpp)->oid_number, (*oidpp)->oid_name);
284787d58f2SPoul-Henning Kamp 
285787d58f2SPoul-Henning Kamp 		printf("%c%c",
286787d58f2SPoul-Henning Kamp 			(*oidpp)->oid_kind & CTLFLAG_RD ? 'R':' ',
287787d58f2SPoul-Henning Kamp 			(*oidpp)->oid_kind & CTLFLAG_WR ? 'W':' ');
288787d58f2SPoul-Henning Kamp 
289787d58f2SPoul-Henning Kamp 		switch ((*oidpp)->oid_kind & CTLTYPE) {
290787d58f2SPoul-Henning Kamp 			case CTLTYPE_NODE:
291787d58f2SPoul-Henning Kamp 				if ((*oidpp)->oid_handler) {
292787d58f2SPoul-Henning Kamp 					printf(" Node(proc)\n");
293787d58f2SPoul-Henning Kamp 				} else {
294787d58f2SPoul-Henning Kamp 					printf(" Node\n");
295787d58f2SPoul-Henning Kamp 					sysctl_sysctl_debug_dump_node(
296787d58f2SPoul-Henning Kamp 						(*oidpp)->oid_arg1, i+2);
297787d58f2SPoul-Henning Kamp 				}
298787d58f2SPoul-Henning Kamp 				break;
299787d58f2SPoul-Henning Kamp 			case CTLTYPE_INT:    printf(" Int\n"); break;
300787d58f2SPoul-Henning Kamp 			case CTLTYPE_STRING: printf(" String\n"); break;
301787d58f2SPoul-Henning Kamp 			case CTLTYPE_QUAD:   printf(" Quad\n"); break;
302787d58f2SPoul-Henning Kamp 			case CTLTYPE_OPAQUE: printf(" Opaque/struct\n"); break;
303787d58f2SPoul-Henning Kamp 			default:	     printf("\n");
304787d58f2SPoul-Henning Kamp 		}
305787d58f2SPoul-Henning Kamp 
306787d58f2SPoul-Henning Kamp 	}
307787d58f2SPoul-Henning Kamp }
308787d58f2SPoul-Henning Kamp 
309787d58f2SPoul-Henning Kamp 
310787d58f2SPoul-Henning Kamp static int
311787d58f2SPoul-Henning Kamp sysctl_sysctl_debug SYSCTL_HANDLER_ARGS
312787d58f2SPoul-Henning Kamp {
313787d58f2SPoul-Henning Kamp 	sysctl_sysctl_debug_dump_node(&sysctl_, 0);
314787d58f2SPoul-Henning Kamp 	return ENOENT;
315787d58f2SPoul-Henning Kamp }
316787d58f2SPoul-Henning Kamp 
317787d58f2SPoul-Henning Kamp SYSCTL_PROC(_sysctl, 0, debug, CTLTYPE_STRING|CTLFLAG_RD,
318787d58f2SPoul-Henning Kamp 	0, 0, sysctl_sysctl_debug, "");
3192e210993SPoul-Henning Kamp 
3202e210993SPoul-Henning Kamp char domainname[MAXHOSTNAMELEN];
32127aef046SPoul-Henning Kamp SYSCTL_STRING(_kern, KERN_DOMAINNAME, domainname, CTLFLAG_RW,
32227aef046SPoul-Henning Kamp 	&domainname, sizeof(domainname), "");
3232e210993SPoul-Henning Kamp 
3242e210993SPoul-Henning Kamp long hostid;
3252e210993SPoul-Henning Kamp /* Some trouble here, if sizeof (int) != sizeof (long) */
3262e210993SPoul-Henning Kamp SYSCTL_INT(_kern, KERN_HOSTID, hostid, CTLFLAG_RW, &hostid, 0, "");
3272e210993SPoul-Henning Kamp 
328ae0eb976SPoul-Henning Kamp /*
329ae0eb976SPoul-Henning Kamp  * Handle an integer, signed or unsigned.
330ae0eb976SPoul-Henning Kamp  * Two cases:
331ae0eb976SPoul-Henning Kamp  *     a variable:  point arg1 at it.
332ae0eb976SPoul-Henning Kamp  *     a constant:  pass it in arg2.
333ae0eb976SPoul-Henning Kamp  */
334ae0eb976SPoul-Henning Kamp 
3353a34a5c3SPoul-Henning Kamp int
3363a34a5c3SPoul-Henning Kamp sysctl_handle_int SYSCTL_HANDLER_ARGS
337b396cd83SPoul-Henning Kamp {
338ae0eb976SPoul-Henning Kamp 	int error = 0;
339b396cd83SPoul-Henning Kamp 
340ae0eb976SPoul-Henning Kamp 	if (arg1)
341ae0eb976SPoul-Henning Kamp 		error = SYSCTL_OUT(req, arg1, sizeof(int));
342ae0eb976SPoul-Henning Kamp 	else if (arg2)
343ae0eb976SPoul-Henning Kamp 		error = SYSCTL_OUT(req, &arg2, sizeof(int));
344b396cd83SPoul-Henning Kamp 
345ae0eb976SPoul-Henning Kamp 	if (error || !req->newptr)
346ae0eb976SPoul-Henning Kamp 		return (error);
347b396cd83SPoul-Henning Kamp 
348ae0eb976SPoul-Henning Kamp 	if (!arg1)
349ae0eb976SPoul-Henning Kamp 		error = EPERM;
350ae0eb976SPoul-Henning Kamp 	else
351ae0eb976SPoul-Henning Kamp 		error = SYSCTL_IN(req, arg1, sizeof(int));
352ae0eb976SPoul-Henning Kamp 	return (error);
353b396cd83SPoul-Henning Kamp }
354b396cd83SPoul-Henning Kamp 
355ae0eb976SPoul-Henning Kamp /*
356ae0eb976SPoul-Henning Kamp  * Handle our generic '\0' terminated 'C' string.
357ae0eb976SPoul-Henning Kamp  * Two cases:
358ae0eb976SPoul-Henning Kamp  * 	a variable string:  point arg1 at it, arg2 is max length.
359ae0eb976SPoul-Henning Kamp  * 	a constant string:  point arg1 at it, arg2 is zero.
360ae0eb976SPoul-Henning Kamp  */
361ae0eb976SPoul-Henning Kamp 
3623a34a5c3SPoul-Henning Kamp int
3633a34a5c3SPoul-Henning Kamp sysctl_handle_string SYSCTL_HANDLER_ARGS
364b396cd83SPoul-Henning Kamp {
365ae0eb976SPoul-Henning Kamp 	int error=0;
366b396cd83SPoul-Henning Kamp 
367ae0eb976SPoul-Henning Kamp 	error = SYSCTL_OUT(req, arg1, strlen((char *)arg1)+1);
368b396cd83SPoul-Henning Kamp 
369deae269aSPoul-Henning Kamp 	if (error || !req->newptr || !arg2)
370ae0eb976SPoul-Henning Kamp 		return (error);
371ae0eb976SPoul-Henning Kamp 
372ae0eb976SPoul-Henning Kamp 	if ((req->newlen - req->newidx) > arg2) {
373ae0eb976SPoul-Henning Kamp 		error = E2BIG;
374ae0eb976SPoul-Henning Kamp 	} else {
375ae0eb976SPoul-Henning Kamp 		arg2 = (req->newlen - req->newidx);
376ae0eb976SPoul-Henning Kamp 		error = SYSCTL_IN(req, arg1, arg2);
377ae0eb976SPoul-Henning Kamp 		((char *)arg1)[arg2] = '\0';
378b396cd83SPoul-Henning Kamp 	}
379b396cd83SPoul-Henning Kamp 
3802e210993SPoul-Henning Kamp 	return (error);
381b396cd83SPoul-Henning Kamp }
382b396cd83SPoul-Henning Kamp 
383ae0eb976SPoul-Henning Kamp /*
384ae0eb976SPoul-Henning Kamp  * Handle any kind of opaque data.
385ae0eb976SPoul-Henning Kamp  * arg1 points to it, arg2 is the size.
386ae0eb976SPoul-Henning Kamp  */
387ae0eb976SPoul-Henning Kamp 
3883a34a5c3SPoul-Henning Kamp int
3893a34a5c3SPoul-Henning Kamp sysctl_handle_opaque SYSCTL_HANDLER_ARGS
390b396cd83SPoul-Henning Kamp {
391ae0eb976SPoul-Henning Kamp 	int error;
392b396cd83SPoul-Henning Kamp 
393ae0eb976SPoul-Henning Kamp 	error = SYSCTL_OUT(req, arg1, arg2);
394b396cd83SPoul-Henning Kamp 
395ae0eb976SPoul-Henning Kamp 	if (error || !req->newptr)
396ae0eb976SPoul-Henning Kamp 		return (error);
397ae0eb976SPoul-Henning Kamp 
398ae0eb976SPoul-Henning Kamp 	error = SYSCTL_IN(req, arg1, arg2);
399ae0eb976SPoul-Henning Kamp 
400ae0eb976SPoul-Henning Kamp 	return (error);
401b396cd83SPoul-Henning Kamp }
402ae0eb976SPoul-Henning Kamp 
403deae269aSPoul-Henning Kamp /*
404deae269aSPoul-Henning Kamp  * Transfer functions to/from kernel space.
405deae269aSPoul-Henning Kamp  * XXX: rather untested at this point
406deae269aSPoul-Henning Kamp  */
407deae269aSPoul-Henning Kamp static int
408ae0eb976SPoul-Henning Kamp sysctl_old_kernel(struct sysctl_req *req, void *p, int l)
409ae0eb976SPoul-Henning Kamp {
410deae269aSPoul-Henning Kamp 	int i = 0;
411deae269aSPoul-Henning Kamp 
412deae269aSPoul-Henning Kamp 	if (req->oldptr) {
413deae269aSPoul-Henning Kamp 		i = min(req->oldlen - req->oldidx, l);
414deae269aSPoul-Henning Kamp 		if (i > 0)
415ae0eb976SPoul-Henning Kamp 			bcopy(p, req->oldptr + req->oldidx, i);
416ae0eb976SPoul-Henning Kamp 	}
417deae269aSPoul-Henning Kamp 	req->oldidx += l;
418ae0eb976SPoul-Henning Kamp 	if (i != l)
419ae0eb976SPoul-Henning Kamp 		return (ENOMEM);
4202e210993SPoul-Henning Kamp 	return (0);
421ae0eb976SPoul-Henning Kamp 
422ae0eb976SPoul-Henning Kamp }
423ae0eb976SPoul-Henning Kamp 
424deae269aSPoul-Henning Kamp static int
425ae0eb976SPoul-Henning Kamp sysctl_new_kernel(struct sysctl_req *req, void *p, int l)
426ae0eb976SPoul-Henning Kamp {
427deae269aSPoul-Henning Kamp 	if (!req->newptr)
428deae269aSPoul-Henning Kamp 		return 0;
429deae269aSPoul-Henning Kamp 	if (req->newlen - req->newidx < l)
430ae0eb976SPoul-Henning Kamp 		return (EINVAL);
431ae0eb976SPoul-Henning Kamp 	bcopy(req->newptr + req->newidx, p, l);
432ae0eb976SPoul-Henning Kamp 	req->newidx += l;
433ae0eb976SPoul-Henning Kamp 	return (0);
434ae0eb976SPoul-Henning Kamp }
435ae0eb976SPoul-Henning Kamp 
436deae269aSPoul-Henning Kamp /*
437deae269aSPoul-Henning Kamp  * Transfer function to/from user space.
438deae269aSPoul-Henning Kamp  */
439deae269aSPoul-Henning Kamp static int
440ae0eb976SPoul-Henning Kamp sysctl_old_user(struct sysctl_req *req, void *p, int l)
441ae0eb976SPoul-Henning Kamp {
442deae269aSPoul-Henning Kamp 	int error = 0, i = 0;
443ae0eb976SPoul-Henning Kamp 
4444b2af45fSPoul-Henning Kamp 	if (req->lock == 1 && req->oldptr) {
4454b2af45fSPoul-Henning Kamp 		vslock(req->oldptr, req->oldlen);
4464b2af45fSPoul-Henning Kamp 		req->lock = 2;
4474b2af45fSPoul-Henning Kamp 	}
448deae269aSPoul-Henning Kamp 	if (req->oldptr) {
449deae269aSPoul-Henning Kamp 		i = min(req->oldlen - req->oldidx, l);
450deae269aSPoul-Henning Kamp 		if (i > 0)
451ae0eb976SPoul-Henning Kamp 			error  = copyout(p, req->oldptr + req->oldidx, i);
452deae269aSPoul-Henning Kamp 	}
453deae269aSPoul-Henning Kamp 	req->oldidx += l;
454ae0eb976SPoul-Henning Kamp 	if (error)
455ae0eb976SPoul-Henning Kamp 		return (error);
456deae269aSPoul-Henning Kamp 	if (req->oldptr && i < l)
457ae0eb976SPoul-Henning Kamp 		return (ENOMEM);
458deae269aSPoul-Henning Kamp 	return (0);
459ae0eb976SPoul-Henning Kamp }
460ae0eb976SPoul-Henning Kamp 
461deae269aSPoul-Henning Kamp static int
462ae0eb976SPoul-Henning Kamp sysctl_new_user(struct sysctl_req *req, void *p, int l)
463ae0eb976SPoul-Henning Kamp {
46416cd04a3SPoul-Henning Kamp 	int error;
465deae269aSPoul-Henning Kamp 
466deae269aSPoul-Henning Kamp 	if (!req->newptr)
467deae269aSPoul-Henning Kamp 		return 0;
468deae269aSPoul-Henning Kamp 	if (req->newlen - req->newidx < l)
469ae0eb976SPoul-Henning Kamp 		return (EINVAL);
470ae0eb976SPoul-Henning Kamp 	error = copyin(req->newptr + req->newidx, p, l);
471ae0eb976SPoul-Henning Kamp 	req->newidx += l;
472ae0eb976SPoul-Henning Kamp 	return (error);
473b396cd83SPoul-Henning Kamp }
474b396cd83SPoul-Henning Kamp 
475df8bae1dSRodney W. Grimes /*
4762e210993SPoul-Henning Kamp  * Traverse our tree, and find the right node, execute whatever it points
4772e210993SPoul-Henning Kamp  * at, and return the resulting error code.
4782e210993SPoul-Henning Kamp  */
4792e210993SPoul-Henning Kamp 
4802e210993SPoul-Henning Kamp int
4812e210993SPoul-Henning Kamp sysctl_root SYSCTL_HANDLER_ARGS
4822e210993SPoul-Henning Kamp {
4832e210993SPoul-Henning Kamp 	int *name = (int *) arg1;
4842e210993SPoul-Henning Kamp 	int namelen = arg2;
4852e210993SPoul-Henning Kamp 	int indx, i, j;
4862e210993SPoul-Henning Kamp 	struct sysctl_oid **oidpp;
4872e210993SPoul-Henning Kamp 	struct linker_set *lsp = &sysctl_;
4882e210993SPoul-Henning Kamp 
4892e210993SPoul-Henning Kamp 	j = lsp->ls_length;
4902e210993SPoul-Henning Kamp 	oidpp = (struct sysctl_oid **) lsp->ls_items;
4912e210993SPoul-Henning Kamp 
4922e210993SPoul-Henning Kamp 	indx = 0;
4932e210993SPoul-Henning Kamp 	while (j-- && indx < CTL_MAXNAME) {
494787d58f2SPoul-Henning Kamp 		if (*oidpp && ((*oidpp)->oid_number == name[indx])) {
4952e210993SPoul-Henning Kamp 			indx++;
4964b2af45fSPoul-Henning Kamp 			if ((*oidpp)->oid_kind & CTLFLAG_NOLOCK)
4974b2af45fSPoul-Henning Kamp 				req->lock = 0;
4982e210993SPoul-Henning Kamp 			if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
4992e210993SPoul-Henning Kamp 				if ((*oidpp)->oid_handler)
5002e210993SPoul-Henning Kamp 					goto found;
5012e210993SPoul-Henning Kamp 				if (indx == namelen)
5022e210993SPoul-Henning Kamp 					return ENOENT;
5032e210993SPoul-Henning Kamp 				lsp = (struct linker_set*)(*oidpp)->oid_arg1;
5042e210993SPoul-Henning Kamp 				j = lsp->ls_length;
5052e210993SPoul-Henning Kamp 				oidpp = (struct sysctl_oid **)lsp->ls_items;
5062e210993SPoul-Henning Kamp 			} else {
5072e210993SPoul-Henning Kamp 				if (indx != namelen)
5082e210993SPoul-Henning Kamp 					return EISDIR;
5092e210993SPoul-Henning Kamp 				goto found;
5102e210993SPoul-Henning Kamp 			}
5112e210993SPoul-Henning Kamp 		} else {
5122e210993SPoul-Henning Kamp 			oidpp++;
5132e210993SPoul-Henning Kamp 		}
5142e210993SPoul-Henning Kamp 	}
515deae269aSPoul-Henning Kamp 	return ENOENT;
5162e210993SPoul-Henning Kamp found:
5172e210993SPoul-Henning Kamp 
5182e210993SPoul-Henning Kamp 	/* If writing isn't allowed */
519ae0eb976SPoul-Henning Kamp 	if (req->newptr && !((*oidpp)->oid_kind & CTLFLAG_WR))
5202e210993SPoul-Henning Kamp 		return (EPERM);
5212e210993SPoul-Henning Kamp 
5222e210993SPoul-Henning Kamp 	if (!(*oidpp)->oid_handler)
5232e210993SPoul-Henning Kamp 		return EINVAL;
5242e210993SPoul-Henning Kamp 
5252e210993SPoul-Henning Kamp 	if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
5262e210993SPoul-Henning Kamp 		i = ((*oidpp)->oid_handler) (*oidpp,
5272e210993SPoul-Henning Kamp 					name + indx, namelen - indx,
528ae0eb976SPoul-Henning Kamp 					req);
5292e210993SPoul-Henning Kamp 	} else {
5302e210993SPoul-Henning Kamp 		i = ((*oidpp)->oid_handler) (*oidpp,
5312e210993SPoul-Henning Kamp 					(*oidpp)->oid_arg1, (*oidpp)->oid_arg2,
532ae0eb976SPoul-Henning Kamp 					req);
5332e210993SPoul-Henning Kamp 	}
5342e210993SPoul-Henning Kamp 	return (i);
5352e210993SPoul-Henning Kamp }
5362e210993SPoul-Henning Kamp 
537d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
538b8da2396SPoul-Henning Kamp struct sysctl_args {
539b8da2396SPoul-Henning Kamp 	int	*name;
540b8da2396SPoul-Henning Kamp 	u_int	namelen;
541b8da2396SPoul-Henning Kamp 	void	*old;
542b8da2396SPoul-Henning Kamp 	size_t	*oldlenp;
543b8da2396SPoul-Henning Kamp 	void	*new;
544b8da2396SPoul-Henning Kamp 	size_t	newlen;
545b8da2396SPoul-Henning Kamp };
546d2d3e875SBruce Evans #endif
547b8da2396SPoul-Henning Kamp 
548df8bae1dSRodney W. Grimes int
5494b2af45fSPoul-Henning Kamp __sysctl(struct proc *p, struct sysctl_args *uap, int *retval)
550df8bae1dSRodney W. Grimes {
551deae269aSPoul-Henning Kamp 	int error, i, j, name[CTL_MAXNAME];
552b396cd83SPoul-Henning Kamp 
553df8bae1dSRodney W. Grimes 	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
554df8bae1dSRodney W. Grimes 		return (EINVAL);
555b396cd83SPoul-Henning Kamp 
556797f2d22SPoul-Henning Kamp  	error = copyin(uap->name, &name, uap->namelen * sizeof(int));
557797f2d22SPoul-Henning Kamp  	if (error)
558df8bae1dSRodney W. Grimes 		return (error);
559df8bae1dSRodney W. Grimes 
560deae269aSPoul-Henning Kamp 	error = userland_sysctl(p, name, uap->namelen,
561b8da2396SPoul-Henning Kamp 		uap->old, uap->oldlenp, 0,
562deae269aSPoul-Henning Kamp 		uap->new, uap->newlen, &j);
563deae269aSPoul-Henning Kamp 	if (error && error != ENOMEM)
564deae269aSPoul-Henning Kamp 		return (error);
565deae269aSPoul-Henning Kamp 	if (uap->oldlenp) {
566deae269aSPoul-Henning Kamp 		i = copyout(&j, uap->oldlenp, sizeof(j));
567deae269aSPoul-Henning Kamp 		if (i)
568deae269aSPoul-Henning Kamp 			return (i);
569deae269aSPoul-Henning Kamp 	}
570deae269aSPoul-Henning Kamp 	return (error);
571b8da2396SPoul-Henning Kamp }
572b8da2396SPoul-Henning Kamp 
573b8da2396SPoul-Henning Kamp /*
574b8da2396SPoul-Henning Kamp  * This is used from various compatibility syscalls too.  That's why name
575b8da2396SPoul-Henning Kamp  * must be in kernel space.
576b8da2396SPoul-Henning Kamp  */
577b8da2396SPoul-Henning Kamp int
578b8da2396SPoul-Henning Kamp userland_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen, int *retval)
579b8da2396SPoul-Henning Kamp {
5804b2af45fSPoul-Henning Kamp 	int error = 0;
581ae0eb976SPoul-Henning Kamp 	struct sysctl_req req;
582ae0eb976SPoul-Henning Kamp 
583ae0eb976SPoul-Henning Kamp 	bzero(&req, sizeof req);
584b8da2396SPoul-Henning Kamp 
58516cd04a3SPoul-Henning Kamp 	req.p = p;
58616cd04a3SPoul-Henning Kamp 
587b8da2396SPoul-Henning Kamp 	if (new != NULL && (error = suser(p->p_ucred, &p->p_acflag)))
588b396cd83SPoul-Henning Kamp 		return (error);
589b396cd83SPoul-Henning Kamp 
590b8da2396SPoul-Henning Kamp 	if (oldlenp) {
591b8da2396SPoul-Henning Kamp 		if (inkernel) {
592ae0eb976SPoul-Henning Kamp 			req.oldlen = *oldlenp;
593b8da2396SPoul-Henning Kamp 		} else {
594deae269aSPoul-Henning Kamp 			error = copyin(oldlenp, &req.oldlen, sizeof(*oldlenp));
595b8da2396SPoul-Henning Kamp 			if (error)
596b8da2396SPoul-Henning Kamp 				return (error);
597b8da2396SPoul-Henning Kamp 		}
598b8da2396SPoul-Henning Kamp 	}
599b8da2396SPoul-Henning Kamp 
600ae0eb976SPoul-Henning Kamp 	if (old) {
601ae0eb976SPoul-Henning Kamp 		if (!useracc(old, req.oldlen, B_WRITE))
602ae0eb976SPoul-Henning Kamp 			return (EFAULT);
603ae0eb976SPoul-Henning Kamp 		req.oldptr= old;
604ae0eb976SPoul-Henning Kamp 	}
6052e210993SPoul-Henning Kamp 
606b8da2396SPoul-Henning Kamp 	if (newlen) {
607ae0eb976SPoul-Henning Kamp 		if (!useracc(new, req.newlen, B_READ))
608ae0eb976SPoul-Henning Kamp 			return (EFAULT);
609ae0eb976SPoul-Henning Kamp 		req.newlen = newlen;
610ae0eb976SPoul-Henning Kamp 		req.newptr = new;
611b396cd83SPoul-Henning Kamp 	}
612b396cd83SPoul-Henning Kamp 
613ae0eb976SPoul-Henning Kamp 	req.oldfunc = sysctl_old_user;
614ae0eb976SPoul-Henning Kamp 	req.newfunc = sysctl_new_user;
6154b2af45fSPoul-Henning Kamp 	req.lock = 1;
6164b2af45fSPoul-Henning Kamp 
6174b2af45fSPoul-Henning Kamp 	/* XXX this should probably be done in a general way */
6184b2af45fSPoul-Henning Kamp 	while (memlock.sl_lock) {
6194b2af45fSPoul-Henning Kamp 		memlock.sl_want = 1;
6204b2af45fSPoul-Henning Kamp 		(void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0);
6214b2af45fSPoul-Henning Kamp 		memlock.sl_locked++;
6224b2af45fSPoul-Henning Kamp 	}
6234b2af45fSPoul-Henning Kamp 	memlock.sl_lock = 1;
624ae0eb976SPoul-Henning Kamp 
625ae0eb976SPoul-Henning Kamp 	error = sysctl_root(0, name, namelen, &req);
626b396cd83SPoul-Henning Kamp 
6274b2af45fSPoul-Henning Kamp 	if (req.lock == 2)
6284b2af45fSPoul-Henning Kamp 		vsunlock(req.oldptr, req.oldlen, B_WRITE);
6294b2af45fSPoul-Henning Kamp 
6304b2af45fSPoul-Henning Kamp 	memlock.sl_lock = 0;
6314b2af45fSPoul-Henning Kamp 
6324b2af45fSPoul-Henning Kamp 	if (memlock.sl_want) {
6334b2af45fSPoul-Henning Kamp 		memlock.sl_want = 0;
6344b2af45fSPoul-Henning Kamp 		wakeup((caddr_t)&memlock);
6354b2af45fSPoul-Henning Kamp 	}
6364b2af45fSPoul-Henning Kamp 
637deae269aSPoul-Henning Kamp 	if (error && error != ENOMEM)
638deae269aSPoul-Henning Kamp 		return (error);
639deae269aSPoul-Henning Kamp 
640deae269aSPoul-Henning Kamp 	if (retval) {
641deae269aSPoul-Henning Kamp 		if (req.oldptr && req.oldidx > req.oldlen)
642ae0eb976SPoul-Henning Kamp 			*retval = req.oldlen;
643deae269aSPoul-Henning Kamp 		else
644deae269aSPoul-Henning Kamp 			*retval = req.oldidx;
645b8da2396SPoul-Henning Kamp 	}
6462e210993SPoul-Henning Kamp 	return (error);
647df8bae1dSRodney W. Grimes }
648df8bae1dSRodney W. Grimes 
649df8bae1dSRodney W. Grimes #ifdef COMPAT_43
650df8bae1dSRodney W. Grimes #include <sys/socket.h>
651df8bae1dSRodney W. Grimes #define	KINFO_PROC		(0<<8)
652df8bae1dSRodney W. Grimes #define	KINFO_RT		(1<<8)
653df8bae1dSRodney W. Grimes #define	KINFO_VNODE		(2<<8)
654df8bae1dSRodney W. Grimes #define	KINFO_FILE		(3<<8)
655df8bae1dSRodney W. Grimes #define	KINFO_METER		(4<<8)
656df8bae1dSRodney W. Grimes #define	KINFO_LOADAVG		(5<<8)
657df8bae1dSRodney W. Grimes #define	KINFO_CLOCKRATE		(6<<8)
658df8bae1dSRodney W. Grimes 
6596ece4a51SPeter Wemm /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */
6606ece4a51SPeter Wemm #define	KINFO_BSDI_SYSINFO	(101<<8)
6616ece4a51SPeter Wemm 
6626ece4a51SPeter Wemm /*
6636ece4a51SPeter Wemm  * XXX this is bloat, but I hope it's better here than on the potentially
6646ece4a51SPeter Wemm  * limited kernel stack...  -Peter
6656ece4a51SPeter Wemm  */
6666ece4a51SPeter Wemm 
6676ece4a51SPeter Wemm struct {
6686ece4a51SPeter Wemm 	int	bsdi_machine;		/* "i386" on BSD/386 */
6696ece4a51SPeter Wemm /*      ^^^ this is an offset to the string, relative to the struct start */
6706ece4a51SPeter Wemm 	char	*pad0;
6716ece4a51SPeter Wemm 	long	pad1;
6726ece4a51SPeter Wemm 	long	pad2;
6736ece4a51SPeter Wemm 	long	pad3;
6746ece4a51SPeter Wemm 	u_long	pad4;
6756ece4a51SPeter Wemm 	u_long	pad5;
6766ece4a51SPeter Wemm 	u_long	pad6;
6776ece4a51SPeter Wemm 
6786ece4a51SPeter Wemm 	int	bsdi_ostype;		/* "BSD/386" on BSD/386 */
6796ece4a51SPeter Wemm 	int	bsdi_osrelease;		/* "1.1" on BSD/386 */
6806ece4a51SPeter Wemm 	long	pad7;
6816ece4a51SPeter Wemm 	long	pad8;
6826ece4a51SPeter Wemm 	char	*pad9;
6836ece4a51SPeter Wemm 
6846ece4a51SPeter Wemm 	long	pad10;
6856ece4a51SPeter Wemm 	long	pad11;
6866ece4a51SPeter Wemm 	int	pad12;
6876ece4a51SPeter Wemm 	long	pad13;
6886ece4a51SPeter Wemm 	quad_t	pad14;
6896ece4a51SPeter Wemm 	long	pad15;
6906ece4a51SPeter Wemm 
6916ece4a51SPeter Wemm 	struct	timeval pad16;
6926ece4a51SPeter Wemm 	/* we dont set this, because BSDI's uname used gethostname() instead */
6936ece4a51SPeter Wemm 	int	bsdi_hostname;		/* hostname on BSD/386 */
6946ece4a51SPeter Wemm 
6956ece4a51SPeter Wemm 	/* the actual string data is appended here */
6966ece4a51SPeter Wemm 
6976ece4a51SPeter Wemm } bsdi_si;
6986ece4a51SPeter Wemm /*
6996ece4a51SPeter Wemm  * this data is appended to the end of the bsdi_si structure during copyout.
7006ece4a51SPeter Wemm  * The "char *" offsets are relative to the base of the bsdi_si struct.
7016ece4a51SPeter Wemm  * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings
7026ece4a51SPeter Wemm  * should not exceed the length of the buffer here... (or else!! :-)
7036ece4a51SPeter Wemm  */
7046ece4a51SPeter Wemm char bsdi_strings[80];	/* It had better be less than this! */
7056ece4a51SPeter Wemm 
706d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
707df8bae1dSRodney W. Grimes struct getkerninfo_args {
708df8bae1dSRodney W. Grimes 	int	op;
709df8bae1dSRodney W. Grimes 	char	*where;
710df8bae1dSRodney W. Grimes 	int	*size;
711df8bae1dSRodney W. Grimes 	int	arg;
712df8bae1dSRodney W. Grimes };
713d2d3e875SBruce Evans #endif
714df8bae1dSRodney W. Grimes 
71526f9a767SRodney W. Grimes int
7164b2af45fSPoul-Henning Kamp ogetkerninfo(struct proc *p, struct getkerninfo_args *uap, int *retval)
717df8bae1dSRodney W. Grimes {
718b8da2396SPoul-Henning Kamp 	int error, name[6];
719df8bae1dSRodney W. Grimes 	u_int size;
720df8bae1dSRodney W. Grimes 
721df8bae1dSRodney W. Grimes 	switch (uap->op & 0xff00) {
722df8bae1dSRodney W. Grimes 
723df8bae1dSRodney W. Grimes 	case KINFO_RT:
724b8da2396SPoul-Henning Kamp 		name[0] = CTL_NET;
725b8da2396SPoul-Henning Kamp 		name[1] = PF_ROUTE;
726b8da2396SPoul-Henning Kamp 		name[2] = 0;
727b8da2396SPoul-Henning Kamp 		name[3] = (uap->op & 0xff0000) >> 16;
728b8da2396SPoul-Henning Kamp 		name[4] = uap->op & 0xff;
729b8da2396SPoul-Henning Kamp 		name[5] = uap->arg;
730b8da2396SPoul-Henning Kamp 		error = userland_sysctl(p, name, 6, uap->where, uap->size,
7314b2af45fSPoul-Henning Kamp 			0, 0, 0, &size);
732df8bae1dSRodney W. Grimes 		break;
733df8bae1dSRodney W. Grimes 
734df8bae1dSRodney W. Grimes 	case KINFO_VNODE:
735b8da2396SPoul-Henning Kamp 		name[0] = CTL_KERN;
736b8da2396SPoul-Henning Kamp 		name[1] = KERN_VNODE;
737b8da2396SPoul-Henning Kamp 		error = userland_sysctl(p, name, 2, uap->where, uap->size,
7384b2af45fSPoul-Henning Kamp 			0, 0, 0, &size);
739df8bae1dSRodney W. Grimes 		break;
740df8bae1dSRodney W. Grimes 
741df8bae1dSRodney W. Grimes 	case KINFO_PROC:
742b8da2396SPoul-Henning Kamp 		name[0] = CTL_KERN;
743b8da2396SPoul-Henning Kamp 		name[1] = KERN_PROC;
744b8da2396SPoul-Henning Kamp 		name[2] = uap->op & 0xff;
745b8da2396SPoul-Henning Kamp 		name[3] = uap->arg;
746b8da2396SPoul-Henning Kamp 		error = userland_sysctl(p, name, 4, uap->where, uap->size,
7474b2af45fSPoul-Henning Kamp 			0, 0, 0, &size);
748df8bae1dSRodney W. Grimes 		break;
749df8bae1dSRodney W. Grimes 
750df8bae1dSRodney W. Grimes 	case KINFO_FILE:
751b8da2396SPoul-Henning Kamp 		name[0] = CTL_KERN;
752b8da2396SPoul-Henning Kamp 		name[1] = KERN_FILE;
753b8da2396SPoul-Henning Kamp 		error = userland_sysctl(p, name, 2, uap->where, uap->size,
7544b2af45fSPoul-Henning Kamp 			0, 0, 0, &size);
755df8bae1dSRodney W. Grimes 		break;
756df8bae1dSRodney W. Grimes 
757df8bae1dSRodney W. Grimes 	case KINFO_METER:
758b8da2396SPoul-Henning Kamp 		name[0] = CTL_VM;
759b8da2396SPoul-Henning Kamp 		name[1] = VM_METER;
760b8da2396SPoul-Henning Kamp 		error = userland_sysctl(p, name, 2, uap->where, uap->size,
7614b2af45fSPoul-Henning Kamp 			0, 0, 0, &size);
762df8bae1dSRodney W. Grimes 		break;
763df8bae1dSRodney W. Grimes 
764df8bae1dSRodney W. Grimes 	case KINFO_LOADAVG:
765b8da2396SPoul-Henning Kamp 		name[0] = CTL_VM;
766b8da2396SPoul-Henning Kamp 		name[1] = VM_LOADAVG;
767b8da2396SPoul-Henning Kamp 		error = userland_sysctl(p, name, 2, uap->where, uap->size,
7684b2af45fSPoul-Henning Kamp 			0, 0, 0, &size);
769df8bae1dSRodney W. Grimes 		break;
770df8bae1dSRodney W. Grimes 
771df8bae1dSRodney W. Grimes 	case KINFO_CLOCKRATE:
772b8da2396SPoul-Henning Kamp 		name[0] = CTL_KERN;
773b8da2396SPoul-Henning Kamp 		name[1] = KERN_CLOCKRATE;
774b8da2396SPoul-Henning Kamp 		error = userland_sysctl(p, name, 2, uap->where, uap->size,
7754b2af45fSPoul-Henning Kamp 			0, 0, 0, &size);
776df8bae1dSRodney W. Grimes 		break;
777df8bae1dSRodney W. Grimes 
7786ece4a51SPeter Wemm 	case KINFO_BSDI_SYSINFO: {
7796ece4a51SPeter Wemm 		/*
7806ece4a51SPeter Wemm 		 * this is pretty crude, but it's just enough for uname()
7816ece4a51SPeter Wemm 		 * from BSDI's 1.x libc to work.
7826ece4a51SPeter Wemm 		 *
7836ece4a51SPeter Wemm 		 * In particular, it doesn't return the same results when
7846ece4a51SPeter Wemm 		 * the supplied buffer is too small.  BSDI's version apparently
7856ece4a51SPeter Wemm 		 * will return the amount copied, and set the *size to how
7866ece4a51SPeter Wemm 		 * much was needed.  The emulation framework here isn't capable
7876ece4a51SPeter Wemm 		 * of that, so we just set both to the amount copied.
7886ece4a51SPeter Wemm 		 * BSDI's 2.x product apparently fails with ENOMEM in this
7896ece4a51SPeter Wemm 		 * scenario.
7906ece4a51SPeter Wemm 		 */
7916ece4a51SPeter Wemm 
7926ece4a51SPeter Wemm 		u_int needed;
7936ece4a51SPeter Wemm 		u_int left;
7946ece4a51SPeter Wemm 		char *s;
7956ece4a51SPeter Wemm 
7966ece4a51SPeter Wemm 		bzero((char *)&bsdi_si, sizeof(bsdi_si));
7976ece4a51SPeter Wemm 		bzero(bsdi_strings, sizeof(bsdi_strings));
7986ece4a51SPeter Wemm 
7996ece4a51SPeter Wemm 		s = bsdi_strings;
8006ece4a51SPeter Wemm 
8016ece4a51SPeter Wemm 		bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si);
8026ece4a51SPeter Wemm 		strcpy(s, ostype);
8036ece4a51SPeter Wemm 		s += strlen(s) + 1;
8046ece4a51SPeter Wemm 
8056ece4a51SPeter Wemm 		bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si);
8066ece4a51SPeter Wemm 		strcpy(s, osrelease);
8076ece4a51SPeter Wemm 		s += strlen(s) + 1;
8086ece4a51SPeter Wemm 
8096ece4a51SPeter Wemm 		bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si);
8106ece4a51SPeter Wemm 		strcpy(s, machine);
8116ece4a51SPeter Wemm 		s += strlen(s) + 1;
8126ece4a51SPeter Wemm 
8136ece4a51SPeter Wemm 		needed = sizeof(bsdi_si) + (s - bsdi_strings);
8146ece4a51SPeter Wemm 
8156ece4a51SPeter Wemm 		if (uap->where == NULL) {
8166ece4a51SPeter Wemm 			/* process is asking how much buffer to supply.. */
8176ece4a51SPeter Wemm 			size = needed;
8186ece4a51SPeter Wemm 			error = 0;
8196ece4a51SPeter Wemm 			break;
8206ece4a51SPeter Wemm 		}
8216ece4a51SPeter Wemm 
8226ece4a51SPeter Wemm 
8236ece4a51SPeter Wemm 		/* if too much buffer supplied, trim it down */
8246ece4a51SPeter Wemm 		if (size > needed)
8256ece4a51SPeter Wemm 			size = needed;
8266ece4a51SPeter Wemm 
8276ece4a51SPeter Wemm 		/* how much of the buffer is remaining */
8286ece4a51SPeter Wemm 		left = size;
8296ece4a51SPeter Wemm 
8306ece4a51SPeter Wemm 		if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0)
8316ece4a51SPeter Wemm 			break;
8326ece4a51SPeter Wemm 
8336ece4a51SPeter Wemm 		/* is there any point in continuing? */
8346ece4a51SPeter Wemm 		if (left > sizeof(bsdi_si)) {
8356ece4a51SPeter Wemm 			left -= sizeof(bsdi_si);
8366ece4a51SPeter Wemm 			error = copyout(&bsdi_strings,
8376ece4a51SPeter Wemm 					uap->where + sizeof(bsdi_si), left);
8386ece4a51SPeter Wemm 		}
8396ece4a51SPeter Wemm 		break;
8406ece4a51SPeter Wemm 	}
8416ece4a51SPeter Wemm 
842df8bae1dSRodney W. Grimes 	default:
843df8bae1dSRodney W. Grimes 		return (EOPNOTSUPP);
844df8bae1dSRodney W. Grimes 	}
845df8bae1dSRodney W. Grimes 	if (error)
846df8bae1dSRodney W. Grimes 		return (error);
847df8bae1dSRodney W. Grimes 	*retval = size;
848df8bae1dSRodney W. Grimes 	if (uap->size)
849df8bae1dSRodney W. Grimes 		error = copyout((caddr_t)&size, (caddr_t)uap->size,
850df8bae1dSRodney W. Grimes 		    sizeof(size));
851df8bae1dSRodney W. Grimes 	return (error);
852df8bae1dSRodney W. Grimes }
853df8bae1dSRodney W. Grimes #endif /* COMPAT_43 */
854