init_sysctl.c revision 1.30
1/*	$NetBSD: init_sysctl.c,v 1.30 2004/05/26 16:28:05 christos Exp $ */
2
3/*-
4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Brown.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *      This product includes software developed by the NetBSD
21 *      Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 *    contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39#include <sys/cdefs.h>
40__KERNEL_RCSID(0, "$NetBSD: init_sysctl.c,v 1.30 2004/05/26 16:28:05 christos Exp $");
41
42#include "opt_sysv.h"
43#include "opt_multiprocessor.h"
44#include "opt_posix.h"
45#include "pty.h"
46#include "rnd.h"
47
48#include <sys/types.h>
49#include <sys/param.h>
50#include <sys/sysctl.h>
51#include <sys/errno.h>
52#include <sys/systm.h>
53#include <sys/kernel.h>
54#include <sys/unistd.h>
55#include <sys/disklabel.h>
56#include <sys/rnd.h>
57#include <sys/vnode.h>
58#include <sys/mount.h>
59#include <sys/namei.h>
60#include <sys/msgbuf.h>
61#include <dev/cons.h>
62#include <sys/socketvar.h>
63#include <sys/file.h>
64#include <sys/tty.h>
65#include <sys/malloc.h>
66#include <sys/resource.h>
67#include <sys/resourcevar.h>
68#include <sys/exec.h>
69#include <sys/conf.h>
70#include <sys/device.h>
71
72#if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
73#include <sys/ipc.h>
74#endif
75#ifdef SYSVMSG
76#include <sys/msg.h>
77#endif
78#ifdef SYSVSEM
79#include <sys/sem.h>
80#endif
81#ifdef SYSVSHM
82#include <sys/shm.h>
83#endif
84
85#include <machine/cpu.h>
86
87/*
88 * try over estimating by 5 procs/lwps
89 */
90#define KERN_PROCSLOP	(5 * sizeof(struct kinfo_proc))
91#define KERN_LWPSLOP	(5 * sizeof(struct kinfo_lwp))
92
93#ifndef MULTIPROCESSOR
94#define	sysctl_ncpus()	(1)
95#else /* MULTIPROCESSOR */
96#ifndef CPU_INFO_FOREACH
97#define CPU_INFO_ITERATOR int
98#define CPU_INFO_FOREACH(cii, ci) cii = 0, ci = curcpu(); ci != NULL; ci = NULL
99#endif
100static int
101sysctl_ncpus(void)
102{
103	struct cpu_info *ci;
104	CPU_INFO_ITERATOR cii;
105
106	int ncpus = 0;
107	for (CPU_INFO_FOREACH(cii, ci))
108		ncpus++;
109	return (ncpus);
110}
111#endif /* MULTIPROCESSOR */
112
113static int sysctl_kern_maxvnodes(SYSCTLFN_PROTO);
114static int sysctl_kern_rtc_offset(SYSCTLFN_PROTO);
115static int sysctl_kern_maxproc(SYSCTLFN_PROTO);
116static int sysctl_kern_securelevel(SYSCTLFN_PROTO);
117static int sysctl_kern_hostid(SYSCTLFN_PROTO);
118static int sysctl_setlen(SYSCTLFN_PROTO);
119static int sysctl_kern_clockrate(SYSCTLFN_PROTO);
120static int sysctl_kern_file(SYSCTLFN_PROTO);
121static int sysctl_kern_autonice(SYSCTLFN_PROTO);
122static int sysctl_msgbuf(SYSCTLFN_PROTO);
123static int sysctl_kern_defcorename(SYSCTLFN_PROTO);
124static int sysctl_kern_cptime(SYSCTLFN_PROTO);
125#if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
126static int sysctl_kern_sysvipc(SYSCTLFN_PROTO);
127#endif /* defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) */
128#if NPTY > 0
129static int sysctl_kern_maxptys(SYSCTLFN_PROTO);
130#endif /* NPTY > 0 */
131static int sysctl_kern_sbmax(SYSCTLFN_PROTO);
132static int sysctl_kern_urnd(SYSCTLFN_PROTO);
133static int sysctl_kern_lwp(SYSCTLFN_PROTO);
134static int sysctl_kern_forkfsleep(SYSCTLFN_PROTO);
135static int sysctl_kern_root_partition(SYSCTLFN_PROTO);
136static int sysctl_kern_drivers(SYSCTLFN_PROTO);
137static int sysctl_doeproc(SYSCTLFN_PROTO);
138static int sysctl_kern_proc_args(SYSCTLFN_PROTO);
139static int sysctl_hw_usermem(SYSCTLFN_PROTO);
140static int sysctl_hw_cnmagic(SYSCTLFN_PROTO);
141static int sysctl_hw_ncpu(SYSCTLFN_PROTO);
142
143static void fill_kproc2(struct proc *, struct kinfo_proc2 *);
144static void fill_lwp(struct lwp *l, struct kinfo_lwp *kl);
145
146/*
147 * ********************************************************************
148 * section 1: setup routines
149 * ********************************************************************
150 * these functions are stuffed into a link set for sysctl setup
151 * functions.  they're never called or referenced from anywhere else.
152 * ********************************************************************
153 */
154
155/*
156 * sets up the base nodes...
157 */
158SYSCTL_SETUP(sysctl_root_setup, "sysctl base setup")
159{
160
161	sysctl_createv(clog, 0, NULL, NULL,
162		       CTLFLAG_PERMANENT,
163		       CTLTYPE_NODE, "kern",
164		       SYSCTL_DESCR("High kernel"),
165		       NULL, 0, NULL, 0,
166		       CTL_KERN, CTL_EOL);
167	sysctl_createv(clog, 0, NULL, NULL,
168		       CTLFLAG_PERMANENT,
169		       CTLTYPE_NODE, "vm",
170		       SYSCTL_DESCR("Virtual memory"),
171		       NULL, 0, NULL, 0,
172		       CTL_VM, CTL_EOL);
173	sysctl_createv(clog, 0, NULL, NULL,
174		       CTLFLAG_PERMANENT,
175		       CTLTYPE_NODE, "vfs",
176		       SYSCTL_DESCR("Filesystem"),
177		       NULL, 0, NULL, 0,
178		       CTL_VFS, CTL_EOL);
179	sysctl_createv(clog, 0, NULL, NULL,
180		       CTLFLAG_PERMANENT,
181		       CTLTYPE_NODE, "net",
182		       SYSCTL_DESCR("Networking"),
183		       NULL, 0, NULL, 0,
184		       CTL_NET, CTL_EOL);
185	sysctl_createv(clog, 0, NULL, NULL,
186		       CTLFLAG_PERMANENT,
187		       CTLTYPE_NODE, "debug",
188		       SYSCTL_DESCR("Debugging"),
189		       NULL, 0, NULL, 0,
190		       CTL_DEBUG, CTL_EOL);
191	sysctl_createv(clog, 0, NULL, NULL,
192		       CTLFLAG_PERMANENT,
193		       CTLTYPE_NODE, "hw",
194		       SYSCTL_DESCR("Generic CPU, I/O"),
195		       NULL, 0, NULL, 0,
196		       CTL_HW, CTL_EOL);
197	sysctl_createv(clog, 0, NULL, NULL,
198		       CTLFLAG_PERMANENT,
199		       CTLTYPE_NODE, "machdep",
200		       SYSCTL_DESCR("Machine dependent"),
201		       NULL, 0, NULL, 0,
202		       CTL_MACHDEP, CTL_EOL);
203	/*
204	 * this node is inserted so that the sysctl nodes in libc can
205	 * operate.
206	 */
207	sysctl_createv(clog, 0, NULL, NULL,
208		       CTLFLAG_PERMANENT,
209		       CTLTYPE_NODE, "user",
210		       SYSCTL_DESCR("User-level"),
211		       NULL, 0, NULL, 0,
212		       CTL_USER, CTL_EOL);
213	sysctl_createv(clog, 0, NULL, NULL,
214		       CTLFLAG_PERMANENT,
215		       CTLTYPE_NODE, "ddb",
216		       SYSCTL_DESCR("In-kernel debugger"),
217		       NULL, 0, NULL, 0,
218		       CTL_DDB, CTL_EOL);
219	sysctl_createv(clog, 0, NULL, NULL,
220		       CTLFLAG_PERMANENT,
221		       CTLTYPE_NODE, "proc",
222		       SYSCTL_DESCR("Per-process"),
223		       NULL, 0, NULL, 0,
224		       CTL_PROC, CTL_EOL);
225	sysctl_createv(clog, 0, NULL, NULL,
226		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
227		       CTLTYPE_NODE, "vendor",
228		       SYSCTL_DESCR("Vendor specific"),
229		       NULL, 0, NULL, 0,
230		       CTL_VENDOR, CTL_EOL);
231	sysctl_createv(clog, 0, NULL, NULL,
232		       CTLFLAG_PERMANENT,
233		       CTLTYPE_NODE, "emul",
234		       SYSCTL_DESCR("Emulation settings"),
235		       NULL, 0, NULL, 0,
236		       CTL_EMUL, CTL_EOL);
237}
238
239/*
240 * this setup routine is a replacement for kern_sysctl()
241 */
242SYSCTL_SETUP(sysctl_kern_setup, "sysctl kern subtree setup")
243{
244	extern int kern_logsigexit;	/* defined in kern/kern_sig.c */
245	extern fixpt_t ccpu;		/* defined in kern/kern_synch.c */
246	extern int dumponpanic;		/* defined in kern/subr_prf.c */
247
248	sysctl_createv(clog, 0, NULL, NULL,
249		       CTLFLAG_PERMANENT,
250		       CTLTYPE_NODE, "kern", NULL,
251		       NULL, 0, NULL, 0,
252		       CTL_KERN, CTL_EOL);
253
254	sysctl_createv(clog, 0, NULL, NULL,
255		       CTLFLAG_PERMANENT,
256		       CTLTYPE_STRING, "ostype",
257		       SYSCTL_DESCR("Operating system type"),
258		       NULL, 0, &ostype, 0,
259		       CTL_KERN, KERN_OSTYPE, CTL_EOL);
260	sysctl_createv(clog, 0, NULL, NULL,
261		       CTLFLAG_PERMANENT,
262		       CTLTYPE_STRING, "osrelease",
263		       SYSCTL_DESCR("Operating system release"),
264		       NULL, 0, &osrelease, 0,
265		       CTL_KERN, KERN_OSRELEASE, CTL_EOL);
266	sysctl_createv(clog, 0, NULL, NULL,
267		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
268		       CTLTYPE_INT, "osrevision",
269		       SYSCTL_DESCR("Operating system revision"),
270		       NULL, __NetBSD_Version__, NULL, 0,
271		       CTL_KERN, KERN_OSREV, CTL_EOL);
272	sysctl_createv(clog, 0, NULL, NULL,
273		       CTLFLAG_PERMANENT,
274		       CTLTYPE_STRING, "version",
275		       SYSCTL_DESCR("Kernel version"),
276		       NULL, 0, &version, 0,
277		       CTL_KERN, KERN_VERSION, CTL_EOL);
278	sysctl_createv(clog, 0, NULL, NULL,
279		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
280		       CTLTYPE_INT, "maxvnodes",
281		       SYSCTL_DESCR("Maximum number of vnodes"),
282		       sysctl_kern_maxvnodes, 0, NULL, 0,
283		       CTL_KERN, KERN_MAXVNODES, CTL_EOL);
284	sysctl_createv(clog, 0, NULL, NULL,
285		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
286		       CTLTYPE_INT, "maxproc",
287		       SYSCTL_DESCR("Maximum number of simultaneous processes"),
288		       sysctl_kern_maxproc, 0, NULL, 0,
289		       CTL_KERN, KERN_MAXPROC, CTL_EOL);
290	sysctl_createv(clog, 0, NULL, NULL,
291		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
292		       CTLTYPE_INT, "maxfiles",
293		       SYSCTL_DESCR("Maximum number of open files"),
294		       NULL, 0, &maxfiles, 0,
295		       CTL_KERN, KERN_MAXFILES, CTL_EOL);
296	sysctl_createv(clog, 0, NULL, NULL,
297		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
298		       CTLTYPE_INT, "argmax",
299		       SYSCTL_DESCR("Maximum number of bytes of arguments to "
300				    "execve(2)"),
301		       NULL, ARG_MAX, NULL, 0,
302		       CTL_KERN, KERN_ARGMAX, CTL_EOL);
303	sysctl_createv(clog, 0, NULL, NULL,
304		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
305		       CTLTYPE_INT, "securelevel",
306		       SYSCTL_DESCR("System security level"),
307		       sysctl_kern_securelevel, 0, &securelevel, 0,
308		       CTL_KERN, KERN_SECURELVL, CTL_EOL);
309	sysctl_createv(clog, 0, NULL, NULL,
310		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
311		       CTLTYPE_STRING, "hostname",
312		       SYSCTL_DESCR("System hostname"),
313		       sysctl_setlen, 0, &hostname, MAXHOSTNAMELEN,
314		       CTL_KERN, KERN_HOSTNAME, CTL_EOL);
315	sysctl_createv(clog, 0, NULL, NULL,
316		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_HEX,
317		       CTLTYPE_INT, "hostid",
318		       SYSCTL_DESCR("System host ID number"),
319		       sysctl_kern_hostid, 0, NULL, 0,
320		       CTL_KERN, KERN_HOSTID, CTL_EOL);
321	sysctl_createv(clog, 0, NULL, NULL,
322		       CTLFLAG_PERMANENT,
323		       CTLTYPE_STRUCT, "clockrate",
324		       SYSCTL_DESCR("Kernel clock rates"),
325		       sysctl_kern_clockrate, 0, NULL,
326		       sizeof(struct clockinfo),
327		       CTL_KERN, KERN_CLOCKRATE, CTL_EOL);
328	sysctl_createv(clog, 0, NULL, NULL,
329		       CTLFLAG_PERMANENT,
330		       CTLTYPE_STRUCT, "vnode",
331		       SYSCTL_DESCR("System vnode table"),
332		       sysctl_kern_vnode, 0, NULL, 0,
333		       CTL_KERN, KERN_VNODE, CTL_EOL);
334	sysctl_createv(clog, 0, NULL, NULL,
335		       CTLFLAG_PERMANENT,
336		       CTLTYPE_STRUCT, "file",
337		       SYSCTL_DESCR("System open file table"),
338		       sysctl_kern_file, 0, NULL, 0,
339		       CTL_KERN, KERN_FILE, CTL_EOL);
340#ifndef GPROF
341	sysctl_createv(clog, 0, NULL, NULL,
342		       CTLFLAG_PERMANENT,
343		       CTLTYPE_NODE, "profiling",
344		       SYSCTL_DESCR("Profiling information (not available)"),
345		       sysctl_notavail, 0, NULL, 0,
346		       CTL_KERN, KERN_PROF, CTL_EOL);
347#endif
348	sysctl_createv(clog, 0, NULL, NULL,
349		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
350		       CTLTYPE_INT, "posix1version",
351		       SYSCTL_DESCR("Version of ISO/IEC 9945 (POSIX 1003.1) "
352				    "with which the operating system attempts "
353				    "to comply"),
354		       NULL, _POSIX_VERSION, NULL, 0,
355		       CTL_KERN, KERN_POSIX1, CTL_EOL);
356	sysctl_createv(clog, 0, NULL, NULL,
357		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
358		       CTLTYPE_INT, "ngroups",
359		       SYSCTL_DESCR("Maximum number of supplemental groups"),
360		       NULL, NGROUPS_MAX, NULL, 0,
361		       CTL_KERN, KERN_NGROUPS, CTL_EOL);
362	sysctl_createv(clog, 0, NULL, NULL,
363		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
364		       CTLTYPE_INT, "job_control",
365		       SYSCTL_DESCR("Whether job control is available"),
366		       NULL, 1, NULL, 0,
367		       CTL_KERN, KERN_JOB_CONTROL, CTL_EOL);
368	sysctl_createv(clog, 0, NULL, NULL,
369		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
370		       CTLTYPE_INT, "saved_ids",
371		       SYSCTL_DESCR("Whether saved set-group/user ID is "
372				    "available"), NULL,
373#ifdef _POSIX_SAVED_IDS
374		       1,
375#else /* _POSIX_SAVED_IDS */
376		       0,
377#endif /* _POSIX_SAVED_IDS */
378		       NULL, 0, CTL_KERN, KERN_SAVED_IDS, CTL_EOL);
379	sysctl_createv(clog, 0, NULL, NULL,
380		       CTLFLAG_PERMANENT,
381		       CTLTYPE_STRUCT, "boottime",
382		       SYSCTL_DESCR("System boot time"),
383		       NULL, 0, &boottime, sizeof(boottime),
384		       CTL_KERN, KERN_BOOTTIME, CTL_EOL);
385	sysctl_createv(clog, 0, NULL, NULL,
386		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
387		       CTLTYPE_STRING, "domainname",
388		       SYSCTL_DESCR("YP domain name"),
389		       sysctl_setlen, 0, &domainname, MAXHOSTNAMELEN,
390		       CTL_KERN, KERN_DOMAINNAME, CTL_EOL);
391	sysctl_createv(clog, 0, NULL, NULL,
392		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
393		       CTLTYPE_INT, "maxpartitions",
394		       SYSCTL_DESCR("Maximum number of partitions allowed per "
395				    "disk"),
396		       NULL, MAXPARTITIONS, NULL, 0,
397		       CTL_KERN, KERN_MAXPARTITIONS, CTL_EOL);
398	sysctl_createv(clog, 0, NULL, NULL,
399		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
400		       CTLTYPE_INT, "rawpartition",
401		       SYSCTL_DESCR("Raw partition of a disk"),
402		       NULL, RAW_PART, NULL, 0,
403		       CTL_KERN, KERN_RAWPARTITION, CTL_EOL);
404	sysctl_createv(clog, 0, NULL, NULL,
405		       CTLFLAG_PERMANENT,
406		       CTLTYPE_STRUCT, "timex", NULL,
407		       sysctl_notavail, 0, NULL, 0,
408		       CTL_KERN, KERN_TIMEX, CTL_EOL);
409	sysctl_createv(clog, 0, NULL, NULL,
410		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
411		       CTLTYPE_INT, "autonicetime",
412		       SYSCTL_DESCR("CPU clock seconds before non-root "
413				    "process priority is lowered"),
414		       sysctl_kern_autonice, 0, &autonicetime, 0,
415		       CTL_KERN, KERN_AUTONICETIME, CTL_EOL);
416	sysctl_createv(clog, 0, NULL, NULL,
417		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
418		       CTLTYPE_INT, "autoniceval",
419		       SYSCTL_DESCR("Automatic reniced non-root process "
420				    "priority"),
421		       sysctl_kern_autonice, 0, &autoniceval, 0,
422		       CTL_KERN, KERN_AUTONICEVAL, CTL_EOL);
423	sysctl_createv(clog, 0, NULL, NULL,
424		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
425		       CTLTYPE_INT, "rtc_offset",
426		       SYSCTL_DESCR("Offset of real time clock from UTC in "
427				    "minutes"),
428		       sysctl_kern_rtc_offset, 0, &rtc_offset, 0,
429		       CTL_KERN, KERN_RTC_OFFSET, CTL_EOL);
430	sysctl_createv(clog, 0, NULL, NULL,
431		       CTLFLAG_PERMANENT,
432		       CTLTYPE_STRING, "root_device",
433		       SYSCTL_DESCR("Name of the root device"),
434		       sysctl_root_device, 0, NULL, 0,
435		       CTL_KERN, KERN_ROOT_DEVICE, CTL_EOL);
436	sysctl_createv(clog, 0, NULL, NULL,
437		       CTLFLAG_PERMANENT,
438		       CTLTYPE_INT, "msgbufsize",
439		       SYSCTL_DESCR("Size of the kernel message buffer"),
440		       sysctl_msgbuf, 0, &msgbufp->msg_bufs, 0,
441		       CTL_KERN, KERN_MSGBUFSIZE, CTL_EOL);
442	sysctl_createv(clog, 0, NULL, NULL,
443		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
444		       CTLTYPE_INT, "fsync",
445		       SYSCTL_DESCR("Whether the POSIX 1003.1b File "
446				    "Synchronization Option is available on "
447				    "this system"),
448		       NULL, 1, NULL, 0,
449		       CTL_KERN, KERN_FSYNC, CTL_EOL);
450	sysctl_createv(clog, 0, NULL, NULL,
451		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
452		       CTLTYPE_INT, "sysvmsg",
453		       SYSCTL_DESCR("System V style message support available"),
454		       NULL,
455#ifdef SYSVMSG
456		       1,
457#else /* SYSVMSG */
458		       0,
459#endif /* SYSVMSG */
460		       NULL, 0, CTL_KERN, KERN_SYSVMSG, CTL_EOL);
461	sysctl_createv(clog, 0, NULL, NULL,
462		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
463		       CTLTYPE_INT, "sysvsem",
464		       SYSCTL_DESCR("System V style semaphore support "
465				    "available"), NULL,
466#ifdef SYSVSEM
467		       1,
468#else /* SYSVSEM */
469		       0,
470#endif /* SYSVSEM */
471		       NULL, 0, CTL_KERN, KERN_SYSVSEM, CTL_EOL);
472	sysctl_createv(clog, 0, NULL, NULL,
473		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
474		       CTLTYPE_INT, "sysvshm",
475		       SYSCTL_DESCR("System V style shared memory support "
476				    "available"), NULL,
477#ifdef SYSVSHM
478		       1,
479#else /* SYSVSHM */
480		       0,
481#endif /* SYSVSHM */
482		       NULL, 0, CTL_KERN, KERN_SYSVSHM, CTL_EOL);
483	sysctl_createv(clog, 0, NULL, NULL,
484		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
485		       CTLTYPE_INT, "synchronized_io",
486		       SYSCTL_DESCR("Whether the POSIX 1003.1b Synchronized "
487				    "I/O Option is available on this system"),
488		       NULL, 1, NULL, 0,
489		       CTL_KERN, KERN_SYNCHRONIZED_IO, CTL_EOL);
490	sysctl_createv(clog, 0, NULL, NULL,
491		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
492		       CTLTYPE_INT, "iov_max",
493		       SYSCTL_DESCR("Maximum number of iovec structures per "
494				    "process"),
495		       NULL, IOV_MAX, NULL, 0,
496		       CTL_KERN, KERN_IOV_MAX, CTL_EOL);
497	sysctl_createv(clog, 0, NULL, NULL,
498		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
499		       CTLTYPE_INT, "mapped_files",
500		       SYSCTL_DESCR("Whether the POSIX 1003.1b Memory Mapped "
501				    "Files Option is available on this system"),
502		       NULL, 1, NULL, 0,
503		       CTL_KERN, KERN_MAPPED_FILES, CTL_EOL);
504	sysctl_createv(clog, 0, NULL, NULL,
505		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
506		       CTLTYPE_INT, "memlock",
507		       SYSCTL_DESCR("Whether the POSIX 1003.1b Process Memory "
508				    "Locking Option is available on this "
509				    "system"),
510		       NULL, 1, NULL, 0,
511		       CTL_KERN, KERN_MEMLOCK, CTL_EOL);
512	sysctl_createv(clog, 0, NULL, NULL,
513		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
514		       CTLTYPE_INT, "memlock_range",
515		       SYSCTL_DESCR("Whether the POSIX 1003.1b Range Memory "
516				    "Locking Option is available on this "
517				    "system"),
518		       NULL, 1, NULL, 0,
519		       CTL_KERN, KERN_MEMLOCK_RANGE, CTL_EOL);
520	sysctl_createv(clog, 0, NULL, NULL,
521		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
522		       CTLTYPE_INT, "memory_protection",
523		       SYSCTL_DESCR("Whether the POSIX 1003.1b Memory "
524				    "Protection Option is available on this "
525				    "system"),
526		       NULL, 1, NULL, 0,
527		       CTL_KERN, KERN_MEMORY_PROTECTION, CTL_EOL);
528	sysctl_createv(clog, 0, NULL, NULL,
529		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
530		       CTLTYPE_INT, "login_name_max",
531		       SYSCTL_DESCR("Maximum login name length"),
532		       NULL, LOGIN_NAME_MAX, NULL, 0,
533		       CTL_KERN, KERN_LOGIN_NAME_MAX, CTL_EOL);
534	sysctl_createv(clog, 0, NULL, NULL,
535		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
536		       CTLTYPE_STRING, "defcorename",
537		       SYSCTL_DESCR("Default core file name"),
538		       sysctl_kern_defcorename, 0, defcorename, MAXPATHLEN,
539		       CTL_KERN, KERN_DEFCORENAME, CTL_EOL);
540	sysctl_createv(clog, 0, NULL, NULL,
541		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
542		       CTLTYPE_INT, "logsigexit",
543		       SYSCTL_DESCR("Log process exit when caused by signals"),
544		       NULL, 0, &kern_logsigexit, 0,
545		       CTL_KERN, KERN_LOGSIGEXIT, CTL_EOL);
546	sysctl_createv(clog, 0, NULL, NULL,
547		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
548		       CTLTYPE_INT, "fscale",
549		       SYSCTL_DESCR("Kernel fixed-point scale factor"),
550		       NULL, FSCALE, NULL, 0,
551		       CTL_KERN, KERN_FSCALE, CTL_EOL);
552	sysctl_createv(clog, 0, NULL, NULL,
553		       CTLFLAG_PERMANENT,
554		       CTLTYPE_INT, "ccpu",
555		       SYSCTL_DESCR("Scheduler exponential decay value"),
556		       NULL, 0, &ccpu, 0,
557		       CTL_KERN, KERN_CCPU, CTL_EOL);
558	sysctl_createv(clog, 0, NULL, NULL,
559		       CTLFLAG_PERMANENT,
560		       CTLTYPE_STRUCT, "cp_time",
561		       SYSCTL_DESCR("Clock ticks spent in different CPU states"),
562		       sysctl_kern_cptime, 0, NULL, 0,
563		       CTL_KERN, KERN_CP_TIME, CTL_EOL);
564#if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
565	sysctl_createv(clog, 0, NULL, NULL,
566		       CTLFLAG_PERMANENT,
567		       CTLTYPE_STRUCT, "sysvipc_info",
568		       SYSCTL_DESCR("System V style IPC information"),
569		       sysctl_kern_sysvipc, 0, NULL, 0,
570		       CTL_KERN, KERN_SYSVIPC_INFO, CTL_EOL);
571#endif /* SYSVMSG || SYSVSEM || SYSVSHM */
572	sysctl_createv(clog, 0, NULL, NULL,
573		       CTLFLAG_PERMANENT,
574		       CTLTYPE_INT, "msgbuf",
575		       SYSCTL_DESCR("Kernel message buffer"),
576		       sysctl_msgbuf, 0, NULL, 0,
577		       CTL_KERN, KERN_MSGBUF, CTL_EOL);
578	sysctl_createv(clog, 0, NULL, NULL,
579		       CTLFLAG_PERMANENT,
580		       CTLTYPE_STRUCT, "consdev",
581		       SYSCTL_DESCR("Console device"),
582		       sysctl_consdev, 0, NULL, sizeof(dev_t),
583		       CTL_KERN, KERN_CONSDEV, CTL_EOL);
584#if NPTY > 0
585	sysctl_createv(clog, 0, NULL, NULL,
586		       CTLFLAG_PERMANENT,
587		       CTLTYPE_INT, "maxptys",
588		       SYSCTL_DESCR("Maximum number of pseudo-ttys"),
589		       sysctl_kern_maxptys, 0, NULL, 0,
590		       CTL_KERN, KERN_MAXPTYS, CTL_EOL);
591#endif /* NPTY > 0 */
592	sysctl_createv(clog, 0, NULL, NULL,
593		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
594		       CTLTYPE_INT, "maxphys",
595		       SYSCTL_DESCR("Maximum raw I/O transfer size"),
596		       NULL, MAXPHYS, NULL, 0,
597		       CTL_KERN, KERN_MAXPHYS, CTL_EOL);
598	sysctl_createv(clog, 0, NULL, NULL,
599		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
600		       CTLTYPE_INT, "sbmax",
601		       SYSCTL_DESCR("Maximum socket buffer size"),
602		       sysctl_kern_sbmax, 0, NULL, 0,
603		       CTL_KERN, KERN_SBMAX, CTL_EOL);
604	sysctl_createv(clog, 0, NULL, NULL,
605		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
606		       CTLTYPE_INT, "monotonic_clock",
607		       SYSCTL_DESCR("Implementation version of the POSIX "
608				    "1003.1b Monotonic Clock Option"),
609		       /* XXX _POSIX_VERSION */
610		       NULL, _POSIX_MONOTONIC_CLOCK, NULL, 0,
611		       CTL_KERN, KERN_MONOTONIC_CLOCK, CTL_EOL);
612	sysctl_createv(clog, 0, NULL, NULL,
613		       CTLFLAG_PERMANENT,
614		       CTLTYPE_INT, "urandom",
615		       SYSCTL_DESCR("Random integer value"),
616		       sysctl_kern_urnd, 0, NULL, 0,
617		       CTL_KERN, KERN_URND, CTL_EOL);
618	sysctl_createv(clog, 0, NULL, NULL,
619		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
620		       CTLTYPE_INT, "labelsector",
621		       SYSCTL_DESCR("Sector number containing the disklabel"),
622		       NULL, LABELSECTOR, NULL, 0,
623		       CTL_KERN, KERN_LABELSECTOR, CTL_EOL);
624	sysctl_createv(clog, 0, NULL, NULL,
625		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
626		       CTLTYPE_INT, "labeloffset",
627		       SYSCTL_DESCR("Offset of the disklabel within the "
628				    "sector"),
629		       NULL, LABELOFFSET, NULL, 0,
630		       CTL_KERN, KERN_LABELOFFSET, CTL_EOL);
631	sysctl_createv(clog, 0, NULL, NULL,
632		       CTLFLAG_PERMANENT,
633		       CTLTYPE_NODE, "lwp",
634		       SYSCTL_DESCR("System-wide LWP information"),
635		       sysctl_kern_lwp, 0, NULL, 0,
636		       CTL_KERN, KERN_LWP, CTL_EOL);
637	sysctl_createv(clog, 0, NULL, NULL,
638		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
639		       CTLTYPE_INT, "forkfsleep",
640		       SYSCTL_DESCR("Milliseconds to sleep on fork failure due "
641				    "to process limits"),
642		       sysctl_kern_forkfsleep, 0, NULL, 0,
643		       CTL_KERN, KERN_FORKFSLEEP, CTL_EOL);
644	sysctl_createv(clog, 0, NULL, NULL,
645		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
646		       CTLTYPE_INT, "posix_threads",
647		       SYSCTL_DESCR("Version of IEEE Std 1003.1 and its "
648				    "Threads option to which the system "
649				    "attempts to conform"),
650		       /* XXX _POSIX_VERSION */
651		       NULL, _POSIX_THREADS, NULL, 0,
652		       CTL_KERN, KERN_POSIX_THREADS, CTL_EOL);
653	sysctl_createv(clog, 0, NULL, NULL,
654		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
655		       CTLTYPE_INT, "posix_semaphores",
656		       SYSCTL_DESCR("Version of IEEE Std 1003.1 and its "
657				    "Semaphores option to which the system "
658				    "attempts to conform"), NULL,
659#ifdef P1003_1B_SEMAPHORE
660		       200112,
661#else /* P1003_1B_SEMAPHORE */
662		       0,
663#endif /* P1003_1B_SEMAPHORE */
664		       NULL, 0, CTL_KERN, KERN_POSIX_SEMAPHORES, CTL_EOL);
665	sysctl_createv(clog, 0, NULL, NULL,
666		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
667		       CTLTYPE_INT, "posix_barriers",
668		       SYSCTL_DESCR("Version of IEEE Std 1003.1 and its "
669				    "Barriers option to which the system "
670				    "attempts to conform"),
671		       /* XXX _POSIX_VERSION */
672		       NULL, _POSIX_BARRIERS, NULL, 0,
673		       CTL_KERN, KERN_POSIX_BARRIERS, CTL_EOL);
674	sysctl_createv(clog, 0, NULL, NULL,
675		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
676		       CTLTYPE_INT, "posix_timers",
677		       SYSCTL_DESCR("Version of IEEE Std 1003.1 and its "
678				    "Timers option to which the system "
679				    "attempts to conform"),
680		       /* XXX _POSIX_VERSION */
681		       NULL, _POSIX_TIMERS, NULL, 0,
682		       CTL_KERN, KERN_POSIX_TIMERS, CTL_EOL);
683	sysctl_createv(clog, 0, NULL, NULL,
684		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
685		       CTLTYPE_INT, "posix_spin_locks",
686		       SYSCTL_DESCR("Version of IEEE Std 1003.1 and its Spin "
687				    "Locks option to which the system attempts "
688				    "to conform"),
689		       /* XXX _POSIX_VERSION */
690		       NULL, _POSIX_SPIN_LOCKS, NULL, 0,
691		       CTL_KERN, KERN_POSIX_SPIN_LOCKS, CTL_EOL);
692	sysctl_createv(clog, 0, NULL, NULL,
693		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
694		       CTLTYPE_INT, "posix_reader_writer_locks",
695		       SYSCTL_DESCR("Version of IEEE Std 1003.1 and its "
696				    "Read-Write Locks option to which the "
697				    "system attempts to conform"),
698		       /* XXX _POSIX_VERSION */
699		       NULL, _POSIX_READER_WRITER_LOCKS, NULL, 0,
700		       CTL_KERN, KERN_POSIX_READER_WRITER_LOCKS, CTL_EOL);
701	sysctl_createv(clog, 0, NULL, NULL,
702		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
703		       CTLTYPE_INT, "dump_on_panic",
704		       SYSCTL_DESCR("Perform a crash dump on system panic"),
705		       NULL, 0, &dumponpanic, 0,
706		       CTL_KERN, KERN_DUMP_ON_PANIC, CTL_EOL);
707	sysctl_createv(clog, 0, NULL, NULL,
708		       CTLFLAG_PERMANENT,
709		       CTLTYPE_INT, "root_partition",
710		       SYSCTL_DESCR("Root partition on the root device"),
711		       sysctl_kern_root_partition, 0, NULL, 0,
712		       CTL_KERN, KERN_ROOT_PARTITION, CTL_EOL);
713	sysctl_createv(clog, 0, NULL, NULL,
714		       CTLFLAG_PERMANENT,
715		       CTLTYPE_STRUCT, "drivers",
716		       SYSCTL_DESCR("List of all drivers with block and "
717				    "character device numbers"),
718		       sysctl_kern_drivers, 0, NULL, 0,
719		       CTL_KERN, KERN_DRIVERS, CTL_EOL);
720}
721
722SYSCTL_SETUP(sysctl_kern_proc_setup,
723	     "sysctl kern.proc/proc2/proc_args subtree setup")
724{
725
726	sysctl_createv(clog, 0, NULL, NULL,
727		       CTLFLAG_PERMANENT,
728		       CTLTYPE_NODE, "kern", NULL,
729		       NULL, 0, NULL, 0,
730		       CTL_KERN, CTL_EOL);
731
732	sysctl_createv(clog, 0, NULL, NULL,
733		       CTLFLAG_PERMANENT,
734		       CTLTYPE_NODE, "proc",
735		       SYSCTL_DESCR("System-wide process information"),
736		       sysctl_doeproc, 0, NULL, 0,
737		       CTL_KERN, KERN_PROC, CTL_EOL);
738	sysctl_createv(clog, 0, NULL, NULL,
739		       CTLFLAG_PERMANENT,
740		       CTLTYPE_NODE, "proc2",
741		       SYSCTL_DESCR("Machine-independent process information"),
742		       sysctl_doeproc, 0, NULL, 0,
743		       CTL_KERN, KERN_PROC2, CTL_EOL);
744	sysctl_createv(clog, 0, NULL, NULL,
745		       CTLFLAG_PERMANENT,
746		       CTLTYPE_NODE, "proc_args",
747		       SYSCTL_DESCR("Process argument information"),
748		       sysctl_kern_proc_args, 0, NULL, 0,
749		       CTL_KERN, KERN_PROC_ARGS, CTL_EOL);
750
751	/*
752	  "nodes" under these:
753
754	  KERN_PROC_ALL
755	  KERN_PROC_PID pid
756	  KERN_PROC_PGRP pgrp
757	  KERN_PROC_SESSION sess
758	  KERN_PROC_TTY tty
759	  KERN_PROC_UID uid
760	  KERN_PROC_RUID uid
761	  KERN_PROC_GID gid
762	  KERN_PROC_RGID gid
763
764	  all in all, probably not worth the effort...
765	*/
766}
767
768SYSCTL_SETUP(sysctl_hw_setup, "sysctl hw subtree setup")
769{
770	u_int u;
771	u_quad_t q;
772
773	sysctl_createv(clog, 0, NULL, NULL,
774		       CTLFLAG_PERMANENT,
775		       CTLTYPE_NODE, "hw", NULL,
776		       NULL, 0, NULL, 0,
777		       CTL_HW, CTL_EOL);
778
779	sysctl_createv(clog, 0, NULL, NULL,
780		       CTLFLAG_PERMANENT,
781		       CTLTYPE_STRING, "machine",
782		       SYSCTL_DESCR("Machine class"),
783		       NULL, 0, machine, 0,
784		       CTL_HW, HW_MACHINE, CTL_EOL);
785	sysctl_createv(clog, 0, NULL, NULL,
786		       CTLFLAG_PERMANENT,
787		       CTLTYPE_STRING, "model",
788		       SYSCTL_DESCR("Machine model"),
789		       NULL, 0, cpu_model, 0,
790		       CTL_HW, HW_MODEL, CTL_EOL);
791	sysctl_createv(clog, 0, NULL, NULL,
792		       CTLFLAG_PERMANENT,
793		       CTLTYPE_INT, "ncpu",
794		       SYSCTL_DESCR("Number of active CPUs"),
795		       sysctl_hw_ncpu, 0, NULL, 0,
796		       CTL_HW, HW_NCPU, CTL_EOL);
797	sysctl_createv(clog, 0, NULL, NULL,
798		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
799		       CTLTYPE_INT, "byteorder",
800		       SYSCTL_DESCR("System byte order"),
801		       NULL, BYTE_ORDER, NULL, 0,
802		       CTL_HW, HW_BYTEORDER, CTL_EOL);
803	u = ((u_int)physmem > (UINT_MAX / PAGE_SIZE)) ?
804		UINT_MAX : physmem * PAGE_SIZE;
805	sysctl_createv(clog, 0, NULL, NULL,
806		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
807		       CTLTYPE_INT, "physmem",
808		       SYSCTL_DESCR("Bytes of physical memory"),
809		       NULL, u, NULL, 0,
810		       CTL_HW, HW_PHYSMEM, CTL_EOL);
811	sysctl_createv(clog, 0, NULL, NULL,
812		       CTLFLAG_PERMANENT,
813		       CTLTYPE_INT, "usermem",
814		       SYSCTL_DESCR("Bytes of non-kernel memory"),
815		       sysctl_hw_usermem, 0, NULL, 0,
816		       CTL_HW, HW_USERMEM, CTL_EOL);
817	sysctl_createv(clog, 0, NULL, NULL,
818		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
819		       CTLTYPE_INT, "pagesize",
820		       SYSCTL_DESCR("Software page size"),
821		       NULL, PAGE_SIZE, NULL, 0,
822		       CTL_HW, HW_PAGESIZE, CTL_EOL);
823	sysctl_createv(clog, 0, NULL, NULL,
824		       CTLFLAG_PERMANENT,
825		       CTLTYPE_STRING, "disknames",
826		       SYSCTL_DESCR("List of disk devices present"),
827		       sysctl_hw_disknames, 0, NULL, 0,
828		       CTL_HW, HW_DISKNAMES, CTL_EOL);
829	sysctl_createv(clog, 0, NULL, NULL,
830		       CTLFLAG_PERMANENT,
831		       CTLTYPE_STRUCT, "diskstats",
832		       SYSCTL_DESCR("Statistics on disk operation"),
833		       sysctl_hw_diskstats, 0, NULL, 0,
834		       CTL_HW, HW_DISKSTATS, CTL_EOL);
835	sysctl_createv(clog, 0, NULL, NULL,
836		       CTLFLAG_PERMANENT,
837		       CTLTYPE_STRING, "machine_arch",
838		       SYSCTL_DESCR("Machine CPU class"),
839		       NULL, 0, machine_arch, 0,
840		       CTL_HW, HW_MACHINE_ARCH, CTL_EOL);
841	sysctl_createv(clog, 0, NULL, NULL,
842		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
843		       CTLTYPE_INT, "alignbytes",
844		       SYSCTL_DESCR("Alignment constraint for all possible "
845				    "data types"),
846		       NULL, ALIGNBYTES, NULL, 0,
847		       CTL_HW, HW_ALIGNBYTES, CTL_EOL);
848	sysctl_createv(clog, 0, NULL, NULL,
849		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_HEX,
850		       CTLTYPE_STRING, "cnmagic",
851		       SYSCTL_DESCR("Console magic key sequence"),
852		       sysctl_hw_cnmagic, 0, NULL, CNS_LEN,
853		       CTL_HW, HW_CNMAGIC, CTL_EOL);
854	q = (u_quad_t)physmem * PAGE_SIZE;
855	sysctl_createv(clog, 0, NULL, NULL,
856		       CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
857		       CTLTYPE_QUAD, "physmem64",
858		       SYSCTL_DESCR("Bytes of physical memory"),
859		       NULL, q, NULL, 0,
860		       CTL_HW, HW_PHYSMEM64, CTL_EOL);
861	sysctl_createv(clog, 0, NULL, NULL,
862		       CTLFLAG_PERMANENT,
863		       CTLTYPE_QUAD, "usermem64",
864		       SYSCTL_DESCR("Bytes of non-kernel memory"),
865		       sysctl_hw_usermem, 0, NULL, 0,
866		       CTL_HW, HW_USERMEM64, CTL_EOL);
867}
868
869#ifdef DEBUG
870/*
871 * Debugging related system variables.
872 */
873struct ctldebug /* debug0, */ /* debug1, */ debug2, debug3, debug4;
874struct ctldebug debug5, debug6, debug7, debug8, debug9;
875struct ctldebug debug10, debug11, debug12, debug13, debug14;
876struct ctldebug debug15, debug16, debug17, debug18, debug19;
877static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
878	&debug0, &debug1, &debug2, &debug3, &debug4,
879	&debug5, &debug6, &debug7, &debug8, &debug9,
880	&debug10, &debug11, &debug12, &debug13, &debug14,
881	&debug15, &debug16, &debug17, &debug18, &debug19,
882};
883
884/*
885 * this setup routine is a replacement for debug_sysctl()
886 *
887 * note that it creates several nodes per defined debug variable
888 */
889SYSCTL_SETUP(sysctl_debug_setup, "sysctl debug subtree setup")
890{
891	struct ctldebug *cdp;
892	char nodename[20];
893	int i;
894
895	/*
896	 * two ways here:
897	 *
898	 * the "old" way (debug.name -> value) which was emulated by
899	 * the sysctl(8) binary
900	 *
901	 * the new way, which the sysctl(8) binary was actually using
902
903	 node	debug
904	 node	debug.0
905	 string	debug.0.name
906	 int	debug.0.value
907	 int	debug.name
908
909	 */
910
911	sysctl_createv(clog, 0, NULL, NULL,
912		       CTLFLAG_PERMANENT,
913		       CTLTYPE_NODE, "debug", NULL,
914		       NULL, 0, NULL, 0,
915		       CTL_DEBUG, CTL_EOL);
916
917	for (i = 0; i < CTL_DEBUG_MAXID; i++) {
918		cdp = debugvars[i];
919		if (cdp->debugname == NULL || cdp->debugvar == NULL)
920			continue;
921
922		snprintf(nodename, sizeof(nodename), "debug%d", i);
923		sysctl_createv(clog, 0, NULL, NULL,
924			       CTLFLAG_PERMANENT|CTLFLAG_HIDDEN,
925			       CTLTYPE_NODE, nodename, NULL,
926			       NULL, 0, NULL, 0,
927			       CTL_DEBUG, i, CTL_EOL);
928		sysctl_createv(clog, 0, NULL, NULL,
929			       CTLFLAG_PERMANENT|CTLFLAG_HIDDEN,
930			       CTLTYPE_STRING, "name", NULL,
931			       NULL, 0, cdp->debugname, 0,
932			       CTL_DEBUG, i, CTL_DEBUG_NAME, CTL_EOL);
933		sysctl_createv(clog, 0, NULL, NULL,
934			       CTLFLAG_PERMANENT|CTLFLAG_HIDDEN,
935			       CTLTYPE_INT, "value", NULL,
936			       NULL, 0, cdp->debugvar, 0,
937			       CTL_DEBUG, i, CTL_DEBUG_VALUE, CTL_EOL);
938		sysctl_createv(clog, 0, NULL, NULL,
939			       CTLFLAG_PERMANENT,
940			       CTLTYPE_INT, cdp->debugname, NULL,
941			       NULL, 0, cdp->debugvar, 0,
942			       CTL_DEBUG, CTL_CREATE, CTL_EOL);
943	}
944}
945#endif /* DEBUG */
946
947/*
948 * ********************************************************************
949 * section 2: private node-specific helper routines.
950 * ********************************************************************
951 */
952
953/*
954 * sysctl helper routine for kern.maxvnodes.  drain vnodes if
955 * new value is lower than desiredvnodes and then calls reinit
956 * routines that needs to adjust to the new value.
957 */
958static int
959sysctl_kern_maxvnodes(SYSCTLFN_ARGS)
960{
961	int error, new_vnodes, old_vnodes;
962	struct sysctlnode node;
963
964	new_vnodes = desiredvnodes;
965	node = *rnode;
966	node.sysctl_data = &new_vnodes;
967	error = sysctl_lookup(SYSCTLFN_CALL(&node));
968	if (error || newp == NULL)
969		return (error);
970
971	old_vnodes = desiredvnodes;
972	desiredvnodes = new_vnodes;
973	if (new_vnodes < old_vnodes) {
974		error = vfs_drainvnodes(new_vnodes, l->l_proc);
975		if (error) {
976			desiredvnodes = old_vnodes;
977			return (error);
978		}
979	}
980	vfs_reinit();
981	nchreinit();
982
983	return (0);
984}
985
986/*
987 * sysctl helper routine for rtc_offset - set time after changes
988 */
989static int
990sysctl_kern_rtc_offset(SYSCTLFN_ARGS)
991{
992	struct timeval tv, delta;
993	int s, error, new_rtc_offset;
994	struct sysctlnode node;
995
996	new_rtc_offset = rtc_offset;
997	node = *rnode;
998	node.sysctl_data = &new_rtc_offset;
999	error = sysctl_lookup(SYSCTLFN_CALL(&node));
1000	if (error || newp == NULL)
1001		return (error);
1002
1003	if (securelevel > 0)
1004		return (EPERM);
1005	if (rtc_offset == new_rtc_offset)
1006		return (0);
1007
1008	/* if we change the offset, adjust the time */
1009	s = splclock();
1010	tv = time;
1011	splx(s);
1012	delta.tv_sec = 60*(new_rtc_offset - rtc_offset);
1013	delta.tv_usec = 0;
1014	timeradd(&tv, &delta, &tv);
1015	rtc_offset = new_rtc_offset;
1016	settime(&tv);
1017
1018	return (0);
1019}
1020
1021/*
1022 * sysctl helper routine for kern.maxvnodes.  ensures that the new
1023 * values are not too low or too high.
1024 */
1025static int
1026sysctl_kern_maxproc(SYSCTLFN_ARGS)
1027{
1028	int error, nmaxproc;
1029	struct sysctlnode node;
1030
1031	nmaxproc = maxproc;
1032	node = *rnode;
1033	node.sysctl_data = &nmaxproc;
1034	error = sysctl_lookup(SYSCTLFN_CALL(&node));
1035	if (error || newp == NULL)
1036		return (error);
1037
1038	if (nmaxproc < 0 || nmaxproc >= PID_MAX)
1039		return (EINVAL);
1040#ifdef __HAVE_CPU_MAXPROC
1041	if (nmaxproc > cpu_maxproc())
1042		return (EINVAL);
1043#endif
1044	maxproc = nmaxproc;
1045
1046	return (0);
1047}
1048
1049/*
1050 * sysctl helper routine for kern.securelevel.  ensures that the value
1051 * only rises unless the caller has pid 1 (assumed to be init).
1052 */
1053static int
1054sysctl_kern_securelevel(SYSCTLFN_ARGS)
1055{
1056	int newsecurelevel, error;
1057	struct sysctlnode node;
1058
1059	newsecurelevel = securelevel;
1060	node = *rnode;
1061	node.sysctl_data = &newsecurelevel;
1062	error = sysctl_lookup(SYSCTLFN_CALL(&node));
1063	if (error || newp == NULL)
1064		return (error);
1065
1066	if (newsecurelevel < securelevel && l && l->l_proc->p_pid != 1)
1067		return (EPERM);
1068	securelevel = newsecurelevel;
1069
1070	return (error);
1071}
1072
1073/*
1074 * sysctl helper function for kern.hostid.  the hostid is a long, but
1075 * we export it as an int, so we need to give it a little help.
1076 */
1077static int
1078sysctl_kern_hostid(SYSCTLFN_ARGS)
1079{
1080	int error, inthostid;
1081	struct sysctlnode node;
1082
1083	inthostid = hostid;  /* XXX assumes sizeof int <= sizeof long */
1084	node = *rnode;
1085	node.sysctl_data = &inthostid;
1086	error = sysctl_lookup(SYSCTLFN_CALL(&node));
1087	if (error || newp == NULL)
1088		return (error);
1089
1090	hostid = (unsigned)inthostid;
1091
1092	return (0);
1093}
1094
1095/*
1096 * sysctl helper function for kern.hostname and kern.domainnname.
1097 * resets the relevant recorded length when the underlying name is
1098 * changed.
1099 */
1100static int
1101sysctl_setlen(SYSCTLFN_ARGS)
1102{
1103	int error;
1104
1105	error = sysctl_lookup(SYSCTLFN_CALL(rnode));
1106	if (error || newp == NULL)
1107		return (error);
1108
1109	switch (rnode->sysctl_num) {
1110	case KERN_HOSTNAME:
1111		hostnamelen = strlen((const char*)rnode->sysctl_data);
1112		break;
1113	case KERN_DOMAINNAME:
1114		domainnamelen = strlen((const char*)rnode->sysctl_data);
1115		break;
1116	}
1117
1118	return (0);
1119}
1120
1121/*
1122 * sysctl helper routine for kern.clockrate.  assembles a struct on
1123 * the fly to be returned to the caller.
1124 */
1125static int
1126sysctl_kern_clockrate(SYSCTLFN_ARGS)
1127{
1128	struct clockinfo clkinfo;
1129	struct sysctlnode node;
1130
1131	clkinfo.tick = tick;
1132	clkinfo.tickadj = tickadj;
1133	clkinfo.hz = hz;
1134	clkinfo.profhz = profhz;
1135	clkinfo.stathz = stathz ? stathz : hz;
1136
1137	node = *rnode;
1138	node.sysctl_data = &clkinfo;
1139	return (sysctl_lookup(SYSCTLFN_CALL(&node)));
1140}
1141
1142
1143/*
1144 * sysctl helper routine for kern.file pseudo-subtree.
1145 */
1146static int
1147sysctl_kern_file(SYSCTLFN_ARGS)
1148{
1149	int error;
1150	size_t buflen;
1151	struct file *fp;
1152	char *start, *where;
1153
1154	start = where = oldp;
1155	buflen = *oldlenp;
1156	if (where == NULL) {
1157		/*
1158		 * overestimate by 10 files
1159		 */
1160		*oldlenp = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
1161		return (0);
1162	}
1163
1164	/*
1165	 * first copyout filehead
1166	 */
1167	if (buflen < sizeof(filehead)) {
1168		*oldlenp = 0;
1169		return (0);
1170	}
1171	error = copyout(&filehead, where, sizeof(filehead));
1172	if (error)
1173		return (error);
1174	buflen -= sizeof(filehead);
1175	where += sizeof(filehead);
1176
1177	/*
1178	 * followed by an array of file structures
1179	 */
1180	LIST_FOREACH(fp, &filehead, f_list) {
1181		if (buflen < sizeof(struct file)) {
1182			*oldlenp = where - start;
1183			return (ENOMEM);
1184		}
1185		error = copyout(fp, where, sizeof(struct file));
1186		if (error)
1187			return (error);
1188		buflen -= sizeof(struct file);
1189		where += sizeof(struct file);
1190	}
1191	*oldlenp = where - start;
1192	return (0);
1193}
1194
1195/*
1196 * sysctl helper routine for kern.autonicetime and kern.autoniceval.
1197 * asserts that the assigned value is in the correct range.
1198 */
1199static int
1200sysctl_kern_autonice(SYSCTLFN_ARGS)
1201{
1202	int error, t = 0;
1203	struct sysctlnode node;
1204
1205	node = *rnode;
1206	t = *(int*)node.sysctl_data;
1207	node.sysctl_data = &t;
1208	error = sysctl_lookup(SYSCTLFN_CALL(&node));
1209	if (error || newp == NULL)
1210		return (error);
1211
1212	switch (node.sysctl_num) {
1213	case KERN_AUTONICETIME:
1214		if (t >= 0)
1215			autonicetime = t;
1216		break;
1217	case KERN_AUTONICEVAL:
1218		if (t < PRIO_MIN)
1219			t = PRIO_MIN;
1220		else if (t > PRIO_MAX)
1221			t = PRIO_MAX;
1222		autoniceval = t;
1223		break;
1224	}
1225
1226	return (0);
1227}
1228
1229/*
1230 * sysctl helper routine for kern.msgbufsize and kern.msgbuf.  for the
1231 * former it merely checks the message buffer is set up.  for the latter,
1232 * it also copies out the data if necessary.
1233 */
1234static int
1235sysctl_msgbuf(SYSCTLFN_ARGS)
1236{
1237	char *where = oldp;
1238	size_t len, maxlen;
1239	long beg, end;
1240	int error;
1241
1242	if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
1243		msgbufenabled = 0;
1244		return (ENXIO);
1245	}
1246
1247	switch (rnode->sysctl_num) {
1248	case KERN_MSGBUFSIZE:
1249		return (sysctl_lookup(SYSCTLFN_CALL(rnode)));
1250	case KERN_MSGBUF:
1251		break;
1252	default:
1253		return (EOPNOTSUPP);
1254	}
1255
1256	if (newp != NULL)
1257		return (EPERM);
1258
1259        if (oldp == NULL) {
1260		/* always return full buffer size */
1261		*oldlenp = msgbufp->msg_bufs;
1262		return (0);
1263        }
1264
1265	error = 0;
1266	maxlen = MIN(msgbufp->msg_bufs, *oldlenp);
1267
1268	/*
1269	 * First, copy from the write pointer to the end of
1270	 * message buffer.
1271	 */
1272	beg = msgbufp->msg_bufx;
1273	end = msgbufp->msg_bufs;
1274	while (maxlen > 0) {
1275		len = MIN(end - beg, maxlen);
1276		if (len == 0)
1277			break;
1278		error = copyout(&msgbufp->msg_bufc[beg], where, len);
1279		if (error)
1280			break;
1281		where += len;
1282		maxlen -= len;
1283
1284		/*
1285		 * ... then, copy from the beginning of message buffer to
1286		 * the write pointer.
1287		 */
1288		beg = 0;
1289		end = msgbufp->msg_bufx;
1290	}
1291
1292	return (error);
1293}
1294
1295/*
1296 * sysctl helper routine for kern.defcorename.  in the case of a new
1297 * string being assigned, check that it's not a zero-length string.
1298 * (XXX the check in -current doesn't work, but do we really care?)
1299 */
1300static int
1301sysctl_kern_defcorename(SYSCTLFN_ARGS)
1302{
1303	int error;
1304	char newcorename[MAXPATHLEN];
1305	struct sysctlnode node;
1306
1307	node = *rnode;
1308	node.sysctl_data = &newcorename[0];
1309	memcpy(node.sysctl_data, rnode->sysctl_data, MAXPATHLEN);
1310	error = sysctl_lookup(SYSCTLFN_CALL(&node));
1311	if (error || newp == NULL)
1312		return (error);
1313
1314	/*
1315	 * when sysctl_lookup() deals with a string, it's guaranteed
1316	 * to come back nul terminated.  so there.  :)
1317	 */
1318	if (strlen(newcorename) == 0)
1319		return (EINVAL);
1320
1321	memcpy(rnode->sysctl_data, node.sysctl_data, MAXPATHLEN);
1322
1323	return (0);
1324}
1325
1326/*
1327 * sysctl helper routine for kern.cp_time node.  adds up cpu time
1328 * across all cpus.
1329 */
1330static int
1331sysctl_kern_cptime(SYSCTLFN_ARGS)
1332{
1333	struct sysctlnode node = *rnode;
1334
1335#ifndef MULTIPROCESSOR
1336
1337	if (namelen == 1) {
1338		if (name[0] != 0)
1339			return (ENOENT);
1340		/*
1341		 * you're allowed to ask for the zero'th processor
1342		 */
1343		name++;
1344		namelen--;
1345	}
1346	node.sysctl_data = curcpu()->ci_schedstate.spc_cp_time;
1347	node.sysctl_size = sizeof(curcpu()->ci_schedstate.spc_cp_time);
1348	return (sysctl_lookup(SYSCTLFN_CALL(&node)));
1349
1350#else /* MULTIPROCESSOR */
1351
1352	u_int64_t *cp_time = NULL;
1353	int error, n = sysctl_ncpus(), i;
1354	struct cpu_info *ci;
1355	CPU_INFO_ITERATOR cii;
1356
1357	/*
1358	 * if you specifically pass a buffer that is the size of the
1359	 * sum, or if you are probing for the size, you get the "sum"
1360	 * of cp_time (and the size thereof) across all processors.
1361	 *
1362	 * alternately, you can pass an additional mib number and get
1363	 * cp_time for that particular processor.
1364	 */
1365	switch (namelen) {
1366	case 0:
1367	    	if (*oldlenp == sizeof(u_int64_t) * CPUSTATES || oldp == NULL) {
1368			node.sysctl_size = sizeof(u_int64_t) * CPUSTATES;
1369			n = -1; /* SUM */
1370		}
1371		else {
1372			node.sysctl_size = n * sizeof(u_int64_t) * CPUSTATES;
1373			n = -2; /* ALL */
1374		}
1375		break;
1376	case 1:
1377		if (name[0] < 0 || name[0] >= n)
1378			return (ENOENT); /* ENOSUCHPROCESSOR */
1379		node.sysctl_size = sizeof(u_int64_t) * CPUSTATES;
1380		n = name[0];
1381		/*
1382		 * adjust these so that sysctl_lookup() will be happy
1383		 */
1384		name++;
1385		namelen--;
1386		break;
1387	default:
1388		return (EINVAL);
1389	}
1390
1391	cp_time = malloc(node.sysctl_size, M_TEMP, M_WAITOK|M_CANFAIL);
1392	if (cp_time == NULL)
1393		return (ENOMEM);
1394	node.sysctl_data = cp_time;
1395	memset(cp_time, 0, node.sysctl_size);
1396
1397	for (CPU_INFO_FOREACH(cii, ci)) {
1398		if (n <= 0)
1399			for (i = 0; i < CPUSTATES; i++)
1400				cp_time[i] += ci->ci_schedstate.spc_cp_time[i];
1401		/*
1402		 * if a specific processor was requested and we just
1403		 * did it, we're done here
1404		 */
1405		if (n == 0)
1406			break;
1407		/*
1408		 * if doing "all", skip to next cp_time set for next processor
1409		 */
1410		if (n == -2)
1411			cp_time += CPUSTATES;
1412		/*
1413		 * if we're doing a specific processor, we're one
1414		 * processor closer
1415		 */
1416		if (n > 0)
1417			n--;
1418	}
1419
1420	error = sysctl_lookup(SYSCTLFN_CALL(&node));
1421	free(node.sysctl_data, M_TEMP);
1422	return (error);
1423
1424#endif /* MULTIPROCESSOR */
1425}
1426
1427#if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
1428/*
1429 * sysctl helper routine for kern.sysvipc_info subtree.
1430 */
1431
1432#define	FILL_PERM(src, dst) do { \
1433	(dst)._key = (src)._key; \
1434	(dst).uid = (src).uid; \
1435	(dst).gid = (src).gid; \
1436	(dst).cuid = (src).cuid; \
1437	(dst).cgid = (src).cgid; \
1438	(dst).mode = (src).mode; \
1439	(dst)._seq = (src)._seq; \
1440} while (/*CONSTCOND*/ 0);
1441#define	FILL_MSG(src, dst) do { \
1442	FILL_PERM((src).msg_perm, (dst).msg_perm); \
1443	(dst).msg_qnum = (src).msg_qnum; \
1444	(dst).msg_qbytes = (src).msg_qbytes; \
1445	(dst)._msg_cbytes = (src)._msg_cbytes; \
1446	(dst).msg_lspid = (src).msg_lspid; \
1447	(dst).msg_lrpid = (src).msg_lrpid; \
1448	(dst).msg_stime = (src).msg_stime; \
1449	(dst).msg_rtime = (src).msg_rtime; \
1450	(dst).msg_ctime = (src).msg_ctime; \
1451} while (/*CONSTCOND*/ 0)
1452#define	FILL_SEM(src, dst) do { \
1453	FILL_PERM((src).sem_perm, (dst).sem_perm); \
1454	(dst).sem_nsems = (src).sem_nsems; \
1455	(dst).sem_otime = (src).sem_otime; \
1456	(dst).sem_ctime = (src).sem_ctime; \
1457} while (/*CONSTCOND*/ 0)
1458#define	FILL_SHM(src, dst) do { \
1459	FILL_PERM((src).shm_perm, (dst).shm_perm); \
1460	(dst).shm_segsz = (src).shm_segsz; \
1461	(dst).shm_lpid = (src).shm_lpid; \
1462	(dst).shm_cpid = (src).shm_cpid; \
1463	(dst).shm_atime = (src).shm_atime; \
1464	(dst).shm_dtime = (src).shm_dtime; \
1465	(dst).shm_ctime = (src).shm_ctime; \
1466	(dst).shm_nattch = (src).shm_nattch; \
1467} while (/*CONSTCOND*/ 0)
1468
1469static int
1470sysctl_kern_sysvipc(SYSCTLFN_ARGS)
1471{
1472	void *where = oldp;
1473	size_t *sizep = oldlenp;
1474#ifdef SYSVMSG
1475	struct msg_sysctl_info *msgsi = NULL;
1476#endif
1477#ifdef SYSVSEM
1478	struct sem_sysctl_info *semsi = NULL;
1479#endif
1480#ifdef SYSVSHM
1481	struct shm_sysctl_info *shmsi = NULL;
1482#endif
1483	size_t infosize, dssize, tsize, buflen;
1484	void *buf = NULL;
1485	char *start;
1486	int32_t nds;
1487	int i, error, ret;
1488
1489	if (namelen != 1)
1490		return (EINVAL);
1491
1492	start = where;
1493	buflen = *sizep;
1494
1495	switch (*name) {
1496	case KERN_SYSVIPC_MSG_INFO:
1497#ifdef SYSVMSG
1498		infosize = sizeof(msgsi->msginfo);
1499		nds = msginfo.msgmni;
1500		dssize = sizeof(msgsi->msgids[0]);
1501		break;
1502#else
1503		return (EINVAL);
1504#endif
1505	case KERN_SYSVIPC_SEM_INFO:
1506#ifdef SYSVSEM
1507		infosize = sizeof(semsi->seminfo);
1508		nds = seminfo.semmni;
1509		dssize = sizeof(semsi->semids[0]);
1510		break;
1511#else
1512		return (EINVAL);
1513#endif
1514	case KERN_SYSVIPC_SHM_INFO:
1515#ifdef SYSVSHM
1516		infosize = sizeof(shmsi->shminfo);
1517		nds = shminfo.shmmni;
1518		dssize = sizeof(shmsi->shmids[0]);
1519		break;
1520#else
1521		return (EINVAL);
1522#endif
1523	default:
1524		return (EINVAL);
1525	}
1526	/*
1527	 * Round infosize to 64 bit boundary if requesting more than just
1528	 * the info structure or getting the total data size.
1529	 */
1530	if (where == NULL || *sizep > infosize)
1531		infosize = ((infosize + 7) / 8) * 8;
1532	tsize = infosize + nds * dssize;
1533
1534	/* Return just the total size required. */
1535	if (where == NULL) {
1536		*sizep = tsize;
1537		return (0);
1538	}
1539
1540	/* Not enough room for even the info struct. */
1541	if (buflen < infosize) {
1542		*sizep = 0;
1543		return (ENOMEM);
1544	}
1545	buf = malloc(min(tsize, buflen), M_TEMP, M_WAITOK);
1546	memset(buf, 0, min(tsize, buflen));
1547
1548	switch (*name) {
1549#ifdef SYSVMSG
1550	case KERN_SYSVIPC_MSG_INFO:
1551		msgsi = (struct msg_sysctl_info *)buf;
1552		msgsi->msginfo = msginfo;
1553		break;
1554#endif
1555#ifdef SYSVSEM
1556	case KERN_SYSVIPC_SEM_INFO:
1557		semsi = (struct sem_sysctl_info *)buf;
1558		semsi->seminfo = seminfo;
1559		break;
1560#endif
1561#ifdef SYSVSHM
1562	case KERN_SYSVIPC_SHM_INFO:
1563		shmsi = (struct shm_sysctl_info *)buf;
1564		shmsi->shminfo = shminfo;
1565		break;
1566#endif
1567	}
1568	buflen -= infosize;
1569
1570	ret = 0;
1571	if (buflen > 0) {
1572		/* Fill in the IPC data structures.  */
1573		for (i = 0; i < nds; i++) {
1574			if (buflen < dssize) {
1575				ret = ENOMEM;
1576				break;
1577			}
1578			switch (*name) {
1579#ifdef SYSVMSG
1580			case KERN_SYSVIPC_MSG_INFO:
1581				FILL_MSG(msqids[i], msgsi->msgids[i]);
1582				break;
1583#endif
1584#ifdef SYSVSEM
1585			case KERN_SYSVIPC_SEM_INFO:
1586				FILL_SEM(sema[i], semsi->semids[i]);
1587				break;
1588#endif
1589#ifdef SYSVSHM
1590			case KERN_SYSVIPC_SHM_INFO:
1591				FILL_SHM(shmsegs[i], shmsi->shmids[i]);
1592				break;
1593#endif
1594			}
1595			buflen -= dssize;
1596		}
1597	}
1598	*sizep -= buflen;
1599	error = copyout(buf, start, *sizep);
1600	/* If copyout succeeded, use return code set earlier. */
1601	if (error == 0)
1602		error = ret;
1603	if (buf)
1604		free(buf, M_TEMP);
1605	return (error);
1606}
1607
1608#undef FILL_PERM
1609#undef FILL_MSG
1610#undef FILL_SEM
1611#undef FILL_SHM
1612
1613#endif /* defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) */
1614
1615#if NPTY > 0
1616/*
1617 * sysctl helper routine for kern.maxptys.  ensures that any new value
1618 * is acceptable to the pty subsystem.
1619 */
1620static int
1621sysctl_kern_maxptys(SYSCTLFN_ARGS)
1622{
1623	int pty_maxptys(int, int);		/* defined in kern/tty_pty.c */
1624	int error, max;
1625	struct sysctlnode node;
1626
1627	/* get current value of maxptys */
1628	max = pty_maxptys(0, 0);
1629
1630	node = *rnode;
1631	node.sysctl_data = &max;
1632	error = sysctl_lookup(SYSCTLFN_CALL(&node));
1633	if (error || newp == NULL)
1634		return (error);
1635
1636	if (max != pty_maxptys(max, 1))
1637		return (EINVAL);
1638
1639	return (0);
1640}
1641#endif /* NPTY > 0 */
1642
1643/*
1644 * sysctl helper routine for kern.sbmax.  basically just ensures that
1645 * any new value is not too small.
1646 */
1647static int
1648sysctl_kern_sbmax(SYSCTLFN_ARGS)
1649{
1650	int error, new_sbmax;
1651	struct sysctlnode node;
1652
1653	new_sbmax = sb_max;
1654	node = *rnode;
1655	node.sysctl_data = &new_sbmax;
1656	error = sysctl_lookup(SYSCTLFN_CALL(&node));
1657	if (error || newp == NULL)
1658		return (error);
1659
1660	error = sb_max_set(new_sbmax);
1661
1662	return (error);
1663}
1664
1665/*
1666 * sysctl helper routine for kern.urandom node.  picks a random number
1667 * for you.
1668 */
1669static int
1670sysctl_kern_urnd(SYSCTLFN_ARGS)
1671{
1672#if NRND > 0
1673	int v;
1674
1675	if (rnd_extract_data(&v, sizeof(v), RND_EXTRACT_ANY) == sizeof(v)) {
1676		struct sysctlnode node = *rnode;
1677		node.sysctl_data = &v;
1678		return (sysctl_lookup(SYSCTLFN_CALL(&node)));
1679	}
1680	else
1681		return (EIO);	/*XXX*/
1682#else
1683	return (EOPNOTSUPP);
1684#endif
1685}
1686
1687/*
1688 * sysctl helper routine to do kern.lwp.* work.
1689 */
1690static int
1691sysctl_kern_lwp(SYSCTLFN_ARGS)
1692{
1693	struct kinfo_lwp klwp;
1694	struct proc *p;
1695	struct lwp *l2;
1696	char *where, *dp;
1697	int pid, elem_size, elem_count;
1698	int buflen, needed, error;
1699
1700	if (namelen == 1 && name[0] == CTL_QUERY)
1701		return (sysctl_query(SYSCTLFN_CALL(rnode)));
1702
1703	dp = where = oldp;
1704	buflen = where != NULL ? *oldlenp : 0;
1705	error = needed = 0;
1706
1707	if (newp != NULL || namelen != 3)
1708		return (EINVAL);
1709	pid = name[0];
1710	elem_size = name[1];
1711	elem_count = name[2];
1712
1713	p = pfind(pid);
1714	if (p == NULL)
1715		return (ESRCH);
1716	LIST_FOREACH(l2, &p->p_lwps, l_sibling) {
1717		if (buflen >= elem_size && elem_count > 0) {
1718			fill_lwp(l2, &klwp);
1719			/*
1720			 * Copy out elem_size, but not larger than
1721			 * the size of a struct kinfo_proc2.
1722			 */
1723			error = copyout(&klwp, dp,
1724			    min(sizeof(klwp), elem_size));
1725			if (error)
1726				goto cleanup;
1727			dp += elem_size;
1728			buflen -= elem_size;
1729			elem_count--;
1730		}
1731		needed += elem_size;
1732	}
1733
1734	if (where != NULL) {
1735		*oldlenp = dp - where;
1736		if (needed > *oldlenp)
1737			return (ENOMEM);
1738	} else {
1739		needed += KERN_LWPSLOP;
1740		*oldlenp = needed;
1741	}
1742	return (0);
1743 cleanup:
1744	return (error);
1745}
1746
1747/*
1748 * sysctl helper routine for kern.forkfsleep node.  ensures that the
1749 * given value is not too large or two small, and is at least one
1750 * timer tick if not zero.
1751 */
1752static int
1753sysctl_kern_forkfsleep(SYSCTLFN_ARGS)
1754{
1755	/* userland sees value in ms, internally is in ticks */
1756	extern int forkfsleep;		/* defined in kern/kern_fork.c */
1757	int error, timo, lsleep;
1758	struct sysctlnode node;
1759
1760	lsleep = forkfsleep * 1000 / hz;
1761	node = *rnode;
1762	node.sysctl_data = &lsleep;
1763	error = sysctl_lookup(SYSCTLFN_CALL(&node));
1764	if (error || newp == NULL)
1765		return (error);
1766
1767	/* refuse negative values, and overly 'long time' */
1768	if (lsleep < 0 || lsleep > MAXSLP * 1000)
1769		return (EINVAL);
1770
1771	timo = mstohz(lsleep);
1772
1773	/* if the interval is >0 ms && <1 tick, use 1 tick */
1774	if (lsleep != 0 && timo == 0)
1775		forkfsleep = 1;
1776	else
1777		forkfsleep = timo;
1778
1779	return (0);
1780}
1781
1782/*
1783 * sysctl helper routine for kern.root_partition
1784 */
1785static int
1786sysctl_kern_root_partition(SYSCTLFN_ARGS)
1787{
1788	int rootpart = DISKPART(rootdev);
1789	struct sysctlnode node = *rnode;
1790
1791	node.sysctl_data = &rootpart;
1792	return (sysctl_lookup(SYSCTLFN_CALL(&node)));
1793}
1794
1795/*
1796 * sysctl helper function for kern.drivers
1797 */
1798static int
1799sysctl_kern_drivers(SYSCTLFN_ARGS)
1800{
1801	int error;
1802	size_t buflen;
1803	struct kinfo_drivers kd;
1804	char *start, *where;
1805	const char *dname;
1806	int i;
1807	extern struct devsw_conv *devsw_conv;
1808	extern int max_devsw_convs;
1809
1810	if (newp != NULL || namelen != 0)
1811		return (EINVAL);
1812
1813	start = where = oldp;
1814	buflen = *oldlenp;
1815	if (where == NULL) {
1816		*oldlenp = max_devsw_convs * sizeof kd;
1817		return 0;
1818	}
1819
1820	/*
1821	 * An array of kinfo_drivers structures
1822	 */
1823	error = 0;
1824	for (i = 0; i < max_devsw_convs; i++) {
1825		dname = devsw_conv[i].d_name;
1826		if (dname == NULL)
1827			continue;
1828		if (buflen < sizeof kd) {
1829			error = ENOMEM;
1830			break;
1831		}
1832		memset(&kd, 0, sizeof(kd));
1833		kd.d_bmajor = devsw_conv[i].d_bmajor;
1834		kd.d_cmajor = devsw_conv[i].d_cmajor;
1835		strlcpy(kd.d_name, dname, sizeof kd.d_name);
1836		error = copyout(&kd, where, sizeof kd);
1837		if (error != 0)
1838			break;
1839		buflen -= sizeof kd;
1840		where += sizeof kd;
1841	}
1842	*oldlenp = where - start;
1843	return error;
1844}
1845
1846static int
1847sysctl_doeproc(SYSCTLFN_ARGS)
1848{
1849	struct eproc eproc;
1850	struct kinfo_proc2 kproc2;
1851	struct kinfo_proc *dp;
1852	struct proc *p;
1853	const struct proclist_desc *pd;
1854	char *where, *dp2;
1855	int type, op, arg;
1856	u_int elem_size, elem_count;
1857	size_t buflen, needed;
1858	int error;
1859
1860	if (namelen == 1 && name[0] == CTL_QUERY)
1861		return (sysctl_query(SYSCTLFN_CALL(rnode)));
1862
1863	dp = oldp;
1864	dp2 = where = oldp;
1865	buflen = where != NULL ? *oldlenp : 0;
1866	error = 0;
1867	needed = 0;
1868	type = rnode->sysctl_num;
1869
1870	if (type == KERN_PROC) {
1871		if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
1872			return (EINVAL);
1873		op = name[0];
1874		if (op != KERN_PROC_ALL)
1875			arg = name[1];
1876		else
1877			arg = 0;		/* Quell compiler warning */
1878		elem_size = elem_count = 0;	/* Ditto */
1879	} else {
1880		if (namelen != 4)
1881			return (EINVAL);
1882		op = name[0];
1883		arg = name[1];
1884		elem_size = name[2];
1885		elem_count = name[3];
1886	}
1887
1888	proclist_lock_read();
1889
1890	pd = proclists;
1891again:
1892	for (p = LIST_FIRST(pd->pd_list); p != NULL; p = LIST_NEXT(p, p_list)) {
1893		/*
1894		 * Skip embryonic processes.
1895		 */
1896		if (p->p_stat == SIDL)
1897			continue;
1898		/*
1899		 * TODO - make more efficient (see notes below).
1900		 * do by session.
1901		 */
1902		switch (op) {
1903
1904		case KERN_PROC_PID:
1905			/* could do this with just a lookup */
1906			if (p->p_pid != (pid_t)arg)
1907				continue;
1908			break;
1909
1910		case KERN_PROC_PGRP:
1911			/* could do this by traversing pgrp */
1912			if (p->p_pgrp->pg_id != (pid_t)arg)
1913				continue;
1914			break;
1915
1916		case KERN_PROC_SESSION:
1917			if (p->p_session->s_sid != (pid_t)arg)
1918				continue;
1919			break;
1920
1921		case KERN_PROC_TTY:
1922			if (arg == (int) KERN_PROC_TTY_REVOKE) {
1923				if ((p->p_flag & P_CONTROLT) == 0 ||
1924				    p->p_session->s_ttyp == NULL ||
1925				    p->p_session->s_ttyvp != NULL)
1926					continue;
1927			} else if ((p->p_flag & P_CONTROLT) == 0 ||
1928			    p->p_session->s_ttyp == NULL) {
1929				if ((dev_t)arg != KERN_PROC_TTY_NODEV)
1930					continue;
1931			} else if (p->p_session->s_ttyp->t_dev != (dev_t)arg)
1932				continue;
1933			break;
1934
1935		case KERN_PROC_UID:
1936			if (p->p_ucred->cr_uid != (uid_t)arg)
1937				continue;
1938			break;
1939
1940		case KERN_PROC_RUID:
1941			if (p->p_cred->p_ruid != (uid_t)arg)
1942				continue;
1943			break;
1944
1945		case KERN_PROC_GID:
1946			if (p->p_ucred->cr_gid != (uid_t)arg)
1947				continue;
1948			break;
1949
1950		case KERN_PROC_RGID:
1951			if (p->p_cred->p_rgid != (uid_t)arg)
1952				continue;
1953			break;
1954
1955		case KERN_PROC_ALL:
1956			/* allow everything */
1957			break;
1958
1959		default:
1960			error = EINVAL;
1961			goto cleanup;
1962		}
1963		if (type == KERN_PROC) {
1964			if (buflen >= sizeof(struct kinfo_proc)) {
1965				fill_eproc(p, &eproc);
1966				error = copyout(p, &dp->kp_proc,
1967				    sizeof(struct proc));
1968				if (error)
1969					goto cleanup;
1970				error = copyout(&eproc, &dp->kp_eproc,
1971				    sizeof(eproc));
1972				if (error)
1973					goto cleanup;
1974				dp++;
1975				buflen -= sizeof(struct kinfo_proc);
1976			}
1977			needed += sizeof(struct kinfo_proc);
1978		} else { /* KERN_PROC2 */
1979			if (buflen >= elem_size && elem_count > 0) {
1980				fill_kproc2(p, &kproc2);
1981				/*
1982				 * Copy out elem_size, but not larger than
1983				 * the size of a struct kinfo_proc2.
1984				 */
1985				error = copyout(&kproc2, dp2,
1986				    min(sizeof(kproc2), elem_size));
1987				if (error)
1988					goto cleanup;
1989				dp2 += elem_size;
1990				buflen -= elem_size;
1991				elem_count--;
1992			}
1993			needed += elem_size;
1994		}
1995	}
1996	pd++;
1997	if (pd->pd_list != NULL)
1998		goto again;
1999	proclist_unlock_read();
2000
2001	if (where != NULL) {
2002		if (type == KERN_PROC)
2003			*oldlenp = (char *)dp - where;
2004		else
2005			*oldlenp = dp2 - where;
2006		if (needed > *oldlenp)
2007			return (ENOMEM);
2008	} else {
2009		needed += KERN_PROCSLOP;
2010		*oldlenp = needed;
2011	}
2012	return (0);
2013 cleanup:
2014	proclist_unlock_read();
2015	return (error);
2016}
2017
2018/*
2019 * sysctl helper routine for kern.proc_args pseudo-subtree.
2020 */
2021static int
2022sysctl_kern_proc_args(SYSCTLFN_ARGS)
2023{
2024	struct ps_strings pss;
2025	struct proc *p, *up = l->l_proc;
2026	size_t len, upper_bound, xlen, i;
2027	struct uio auio;
2028	struct iovec aiov;
2029	vaddr_t argv;
2030	pid_t pid;
2031	int nargv, type, error;
2032	char *arg;
2033	char *tmp;
2034
2035	if (namelen == 1 && name[0] == CTL_QUERY)
2036		return (sysctl_query(SYSCTLFN_CALL(rnode)));
2037
2038	if (newp != NULL || namelen != 2)
2039		return (EINVAL);
2040	pid = name[0];
2041	type = name[1];
2042
2043	switch (type) {
2044	case KERN_PROC_ARGV:
2045	case KERN_PROC_NARGV:
2046	case KERN_PROC_ENV:
2047	case KERN_PROC_NENV:
2048		/* ok */
2049		break;
2050	default:
2051		return (EINVAL);
2052	}
2053
2054	/* check pid */
2055	if ((p = pfind(pid)) == NULL)
2056		return (EINVAL);
2057
2058	/* only root or same user change look at the environment */
2059	if (type == KERN_PROC_ENV || type == KERN_PROC_NENV) {
2060		if (up->p_ucred->cr_uid != 0) {
2061			if (up->p_cred->p_ruid != p->p_cred->p_ruid ||
2062			    up->p_cred->p_ruid != p->p_cred->p_svuid)
2063				return (EPERM);
2064		}
2065	}
2066
2067	if (oldp == NULL) {
2068		if (type == KERN_PROC_NARGV || type == KERN_PROC_NENV)
2069			*oldlenp = sizeof (int);
2070		else
2071			*oldlenp = ARG_MAX;	/* XXX XXX XXX */
2072		return (0);
2073	}
2074
2075	/*
2076	 * Zombies don't have a stack, so we can't read their psstrings.
2077	 * System processes also don't have a user stack.
2078	 */
2079	if (P_ZOMBIE(p) || (p->p_flag & P_SYSTEM) != 0)
2080		return (EINVAL);
2081
2082	/*
2083	 * Lock the process down in memory.
2084	 */
2085	/* XXXCDC: how should locking work here? */
2086	if ((p->p_flag & P_WEXIT) || (p->p_vmspace->vm_refcnt < 1))
2087		return (EFAULT);
2088
2089	p->p_vmspace->vm_refcnt++;	/* XXX */
2090
2091	/*
2092	 * Allocate a temporary buffer to hold the arguments.
2093	 */
2094	arg = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
2095
2096	/*
2097	 * Read in the ps_strings structure.
2098	 */
2099	aiov.iov_base = &pss;
2100	aiov.iov_len = sizeof(pss);
2101	auio.uio_iov = &aiov;
2102	auio.uio_iovcnt = 1;
2103	auio.uio_offset = (vaddr_t)p->p_psstr;
2104	auio.uio_resid = sizeof(pss);
2105	auio.uio_segflg = UIO_SYSSPACE;
2106	auio.uio_rw = UIO_READ;
2107	auio.uio_procp = NULL;
2108	error = uvm_io(&p->p_vmspace->vm_map, &auio);
2109	if (error)
2110		goto done;
2111
2112	if (type == KERN_PROC_ARGV || type == KERN_PROC_NARGV)
2113		memcpy(&nargv, (char *)&pss + p->p_psnargv, sizeof(nargv));
2114	else
2115		memcpy(&nargv, (char *)&pss + p->p_psnenv, sizeof(nargv));
2116	if (type == KERN_PROC_NARGV || type == KERN_PROC_NENV) {
2117		error = copyout(&nargv, oldp, sizeof(nargv));
2118		*oldlenp = sizeof(nargv);
2119		goto done;
2120	}
2121	/*
2122	 * Now read the address of the argument vector.
2123	 */
2124	switch (type) {
2125	case KERN_PROC_ARGV:
2126		/* XXX compat32 stuff here */
2127		memcpy(&tmp, (char *)&pss + p->p_psargv, sizeof(tmp));
2128		break;
2129	case KERN_PROC_ENV:
2130		memcpy(&tmp, (char *)&pss + p->p_psenv, sizeof(tmp));
2131		break;
2132	default:
2133		return (EINVAL);
2134	}
2135	auio.uio_offset = (off_t)(unsigned long)tmp;
2136	aiov.iov_base = &argv;
2137	aiov.iov_len = sizeof(argv);
2138	auio.uio_iov = &aiov;
2139	auio.uio_iovcnt = 1;
2140	auio.uio_resid = sizeof(argv);
2141	auio.uio_segflg = UIO_SYSSPACE;
2142	auio.uio_rw = UIO_READ;
2143	auio.uio_procp = NULL;
2144	error = uvm_io(&p->p_vmspace->vm_map, &auio);
2145	if (error)
2146		goto done;
2147
2148	/*
2149	 * Now copy in the actual argument vector, one page at a time,
2150	 * since we don't know how long the vector is (though, we do
2151	 * know how many NUL-terminated strings are in the vector).
2152	 */
2153	len = 0;
2154	upper_bound = *oldlenp;
2155	for (; nargv != 0 && len < upper_bound; len += xlen) {
2156		aiov.iov_base = arg;
2157		aiov.iov_len = PAGE_SIZE;
2158		auio.uio_iov = &aiov;
2159		auio.uio_iovcnt = 1;
2160		auio.uio_offset = argv + len;
2161		xlen = PAGE_SIZE - ((argv + len) & PAGE_MASK);
2162		auio.uio_resid = xlen;
2163		auio.uio_segflg = UIO_SYSSPACE;
2164		auio.uio_rw = UIO_READ;
2165		auio.uio_procp = NULL;
2166		error = uvm_io(&p->p_vmspace->vm_map, &auio);
2167		if (error)
2168			goto done;
2169
2170		for (i = 0; i < xlen && nargv != 0; i++) {
2171			if (arg[i] == '\0')
2172				nargv--;	/* one full string */
2173		}
2174
2175		/*
2176		 * Make sure we don't copyout past the end of the user's
2177		 * buffer.
2178		 */
2179		if (len + i > upper_bound)
2180			i = upper_bound - len;
2181
2182		error = copyout(arg, (char *)oldp + len, i);
2183		if (error)
2184			break;
2185
2186		if (nargv == 0) {
2187			len += i;
2188			break;
2189		}
2190	}
2191	*oldlenp = len;
2192
2193done:
2194	uvmspace_free(p->p_vmspace);
2195
2196	free(arg, M_TEMP);
2197	return (error);
2198}
2199
2200/*
2201 * sysctl helper routine for hw.usermem and hw.usermem64.  values are
2202 * calculate on the fly taking into account integer overflow and the
2203 * current wired count.
2204 */
2205static int
2206sysctl_hw_usermem(SYSCTLFN_ARGS)
2207{
2208	u_int ui;
2209	u_quad_t uq;
2210	struct sysctlnode node;
2211
2212	node = *rnode;
2213	switch (rnode->sysctl_num) {
2214	    case HW_USERMEM:
2215		if ((ui = physmem - uvmexp.wired) > (UINT_MAX / PAGE_SIZE))
2216			ui = UINT_MAX;
2217		else
2218			ui *= PAGE_SIZE;
2219		node.sysctl_data = &ui;
2220		break;
2221	case HW_USERMEM64:
2222		uq = (u_quad_t)(physmem - uvmexp.wired) * PAGE_SIZE;
2223		node.sysctl_data = &uq;
2224		break;
2225	default:
2226		return (EINVAL);
2227	}
2228
2229	return (sysctl_lookup(SYSCTLFN_CALL(&node)));
2230}
2231
2232/*
2233 * sysctl helper routine for kern.cnmagic node.  pulls the old value
2234 * out, encoded, and stuffs the new value in for decoding.
2235 */
2236static int
2237sysctl_hw_cnmagic(SYSCTLFN_ARGS)
2238{
2239	char magic[CNS_LEN];
2240	int error;
2241	struct sysctlnode node;
2242
2243	if (oldp)
2244		cn_get_magic(magic, CNS_LEN);
2245	node = *rnode;
2246	node.sysctl_data = &magic[0];
2247	error = sysctl_lookup(SYSCTLFN_CALL(&node));
2248	if (error || newp == NULL)
2249		return (error);
2250
2251	return (cn_set_magic(magic));
2252}
2253
2254static int
2255sysctl_hw_ncpu(SYSCTLFN_ARGS)
2256{
2257	int ncpu;
2258	struct sysctlnode node;
2259
2260	ncpu = sysctl_ncpus();
2261	node = *rnode;
2262	node.sysctl_data = &ncpu;
2263
2264	return (sysctl_lookup(SYSCTLFN_CALL(&node)));
2265}
2266
2267
2268/*
2269 * ********************************************************************
2270 * section 3: public helper routines that are used for more than one
2271 * node
2272 * ********************************************************************
2273 */
2274
2275/*
2276 * sysctl helper routine for the kern.root_device node and some ports'
2277 * machdep.root_device nodes.
2278 */
2279int
2280sysctl_root_device(SYSCTLFN_ARGS)
2281{
2282	struct sysctlnode node;
2283
2284	node = *rnode;
2285	node.sysctl_data = root_device->dv_xname;
2286	node.sysctl_size = strlen(root_device->dv_xname) + 1;
2287	return (sysctl_lookup(SYSCTLFN_CALL(&node)));
2288}
2289
2290/*
2291 * sysctl helper routine for kern.consdev, dependent on the current
2292 * state of the console.  also used for machdep.console_device on some
2293 * ports.
2294 */
2295int
2296sysctl_consdev(SYSCTLFN_ARGS)
2297{
2298	dev_t consdev;
2299	struct sysctlnode node;
2300
2301	if (cn_tab != NULL)
2302		consdev = cn_tab->cn_dev;
2303	else
2304		consdev = NODEV;
2305	node = *rnode;
2306	node.sysctl_data = &consdev;
2307	node.sysctl_size = sizeof(consdev);
2308	return (sysctl_lookup(SYSCTLFN_CALL(&node)));
2309}
2310
2311/*
2312 * ********************************************************************
2313 * section 4: support for some helpers
2314 * ********************************************************************
2315 */
2316
2317/*
2318 * Fill in a kinfo_proc2 structure for the specified process.
2319 */
2320static void
2321fill_kproc2(struct proc *p, struct kinfo_proc2 *ki)
2322{
2323	struct tty *tp;
2324	struct lwp *l;
2325	struct timeval ut, st;
2326
2327	memset(ki, 0, sizeof(*ki));
2328
2329	ki->p_paddr = PTRTOUINT64(p);
2330	ki->p_fd = PTRTOUINT64(p->p_fd);
2331	ki->p_cwdi = PTRTOUINT64(p->p_cwdi);
2332	ki->p_stats = PTRTOUINT64(p->p_stats);
2333	ki->p_limit = PTRTOUINT64(p->p_limit);
2334	ki->p_vmspace = PTRTOUINT64(p->p_vmspace);
2335	ki->p_sigacts = PTRTOUINT64(p->p_sigacts);
2336	ki->p_sess = PTRTOUINT64(p->p_session);
2337	ki->p_tsess = 0;	/* may be changed if controlling tty below */
2338	ki->p_ru = PTRTOUINT64(p->p_ru);
2339
2340	ki->p_eflag = 0;
2341	ki->p_exitsig = p->p_exitsig;
2342	ki->p_flag = p->p_flag;
2343
2344	ki->p_pid = p->p_pid;
2345	if (p->p_pptr)
2346		ki->p_ppid = p->p_pptr->p_pid;
2347	else
2348		ki->p_ppid = 0;
2349	ki->p_sid = p->p_session->s_sid;
2350	ki->p__pgid = p->p_pgrp->pg_id;
2351
2352	ki->p_tpgid = NO_PGID;	/* may be changed if controlling tty below */
2353
2354	ki->p_uid = p->p_ucred->cr_uid;
2355	ki->p_ruid = p->p_cred->p_ruid;
2356	ki->p_gid = p->p_ucred->cr_gid;
2357	ki->p_rgid = p->p_cred->p_rgid;
2358	ki->p_svuid = p->p_cred->p_svuid;
2359	ki->p_svgid = p->p_cred->p_svgid;
2360
2361	memcpy(ki->p_groups, p->p_cred->pc_ucred->cr_groups,
2362	    min(sizeof(ki->p_groups), sizeof(p->p_cred->pc_ucred->cr_groups)));
2363	ki->p_ngroups = p->p_cred->pc_ucred->cr_ngroups;
2364
2365	ki->p_jobc = p->p_pgrp->pg_jobc;
2366	if ((p->p_flag & P_CONTROLT) && (tp = p->p_session->s_ttyp)) {
2367		ki->p_tdev = tp->t_dev;
2368		ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID;
2369		ki->p_tsess = PTRTOUINT64(tp->t_session);
2370	} else {
2371		ki->p_tdev = NODEV;
2372	}
2373
2374	ki->p_estcpu = p->p_estcpu;
2375	ki->p_rtime_sec = p->p_rtime.tv_sec;
2376	ki->p_rtime_usec = p->p_rtime.tv_usec;
2377	ki->p_cpticks = p->p_cpticks;
2378	ki->p_pctcpu = p->p_pctcpu;
2379
2380	ki->p_uticks = p->p_uticks;
2381	ki->p_sticks = p->p_sticks;
2382	ki->p_iticks = p->p_iticks;
2383
2384	ki->p_tracep = PTRTOUINT64(p->p_tracep);
2385	ki->p_traceflag = p->p_traceflag;
2386
2387
2388	memcpy(&ki->p_siglist, &p->p_sigctx.ps_siglist, sizeof(ki_sigset_t));
2389	memcpy(&ki->p_sigmask, &p->p_sigctx.ps_sigmask, sizeof(ki_sigset_t));
2390	memcpy(&ki->p_sigignore, &p->p_sigctx.ps_sigignore,sizeof(ki_sigset_t));
2391	memcpy(&ki->p_sigcatch, &p->p_sigctx.ps_sigcatch, sizeof(ki_sigset_t));
2392
2393	ki->p_stat = p->p_stat; /* Will likely be overridden by LWP status */
2394	ki->p_realstat = p->p_stat;
2395	ki->p_nice = p->p_nice;
2396
2397	ki->p_xstat = p->p_xstat;
2398	ki->p_acflag = p->p_acflag;
2399
2400	strncpy(ki->p_comm, p->p_comm,
2401	    min(sizeof(ki->p_comm), sizeof(p->p_comm)));
2402
2403	strncpy(ki->p_login, p->p_session->s_login,
2404	    min(sizeof ki->p_login - 1, sizeof p->p_session->s_login));
2405
2406	ki->p_nlwps = p->p_nlwps;
2407	ki->p_nrlwps = p->p_nrlwps;
2408	ki->p_realflag = p->p_flag;
2409
2410	if (p->p_stat == SIDL || P_ZOMBIE(p)) {
2411		ki->p_vm_rssize = 0;
2412		ki->p_vm_tsize = 0;
2413		ki->p_vm_dsize = 0;
2414		ki->p_vm_ssize = 0;
2415		l = NULL;
2416	} else {
2417		struct vmspace *vm = p->p_vmspace;
2418
2419		ki->p_vm_rssize = vm_resident_count(vm);
2420		ki->p_vm_tsize = vm->vm_tsize;
2421		ki->p_vm_dsize = vm->vm_dsize;
2422		ki->p_vm_ssize = vm->vm_ssize;
2423
2424		/* Pick a "representative" LWP */
2425		l = proc_representative_lwp(p);
2426		ki->p_forw = PTRTOUINT64(l->l_forw);
2427		ki->p_back = PTRTOUINT64(l->l_back);
2428		ki->p_addr = PTRTOUINT64(l->l_addr);
2429		ki->p_stat = l->l_stat;
2430		ki->p_flag |= l->l_flag;
2431		ki->p_swtime = l->l_swtime;
2432		ki->p_slptime = l->l_slptime;
2433		if (l->l_stat == LSONPROC) {
2434			KDASSERT(l->l_cpu != NULL);
2435			ki->p_schedflags = l->l_cpu->ci_schedstate.spc_flags;
2436		} else
2437			ki->p_schedflags = 0;
2438		ki->p_holdcnt = l->l_holdcnt;
2439		ki->p_priority = l->l_priority;
2440		ki->p_usrpri = l->l_usrpri;
2441		if (l->l_wmesg)
2442			strncpy(ki->p_wmesg, l->l_wmesg, sizeof(ki->p_wmesg));
2443		ki->p_wchan = PTRTOUINT64(l->l_wchan);
2444
2445	}
2446
2447	if (p->p_session->s_ttyvp)
2448		ki->p_eflag |= EPROC_CTTY;
2449	if (SESS_LEADER(p))
2450		ki->p_eflag |= EPROC_SLEADER;
2451
2452	/* XXX Is this double check necessary? */
2453	if (P_ZOMBIE(p)) {
2454		ki->p_uvalid = 0;
2455	} else {
2456		ki->p_uvalid = 1;
2457
2458		ki->p_ustart_sec = p->p_stats->p_start.tv_sec;
2459		ki->p_ustart_usec = p->p_stats->p_start.tv_usec;
2460
2461		calcru(p, &ut, &st, 0);
2462		ki->p_uutime_sec = ut.tv_sec;
2463		ki->p_uutime_usec = ut.tv_usec;
2464		ki->p_ustime_sec = st.tv_sec;
2465		ki->p_ustime_usec = st.tv_usec;
2466
2467		ki->p_uru_maxrss = p->p_stats->p_ru.ru_maxrss;
2468		ki->p_uru_ixrss = p->p_stats->p_ru.ru_ixrss;
2469		ki->p_uru_idrss = p->p_stats->p_ru.ru_idrss;
2470		ki->p_uru_isrss = p->p_stats->p_ru.ru_isrss;
2471		ki->p_uru_minflt = p->p_stats->p_ru.ru_minflt;
2472		ki->p_uru_majflt = p->p_stats->p_ru.ru_majflt;
2473		ki->p_uru_nswap = p->p_stats->p_ru.ru_nswap;
2474		ki->p_uru_inblock = p->p_stats->p_ru.ru_inblock;
2475		ki->p_uru_oublock = p->p_stats->p_ru.ru_oublock;
2476		ki->p_uru_msgsnd = p->p_stats->p_ru.ru_msgsnd;
2477		ki->p_uru_msgrcv = p->p_stats->p_ru.ru_msgrcv;
2478		ki->p_uru_nsignals = p->p_stats->p_ru.ru_nsignals;
2479		ki->p_uru_nvcsw = p->p_stats->p_ru.ru_nvcsw;
2480		ki->p_uru_nivcsw = p->p_stats->p_ru.ru_nivcsw;
2481
2482		timeradd(&p->p_stats->p_cru.ru_utime,
2483			 &p->p_stats->p_cru.ru_stime, &ut);
2484		ki->p_uctime_sec = ut.tv_sec;
2485		ki->p_uctime_usec = ut.tv_usec;
2486	}
2487#ifdef MULTIPROCESSOR
2488	if (l && l->l_cpu != NULL)
2489		ki->p_cpuid = l->l_cpu->ci_cpuid;
2490	else
2491#endif
2492		ki->p_cpuid = KI_NOCPU;
2493}
2494
2495/*
2496 * Fill in a kinfo_lwp structure for the specified lwp.
2497 */
2498static void
2499fill_lwp(struct lwp *l, struct kinfo_lwp *kl)
2500{
2501
2502	kl->l_forw = PTRTOUINT64(l->l_forw);
2503	kl->l_back = PTRTOUINT64(l->l_back);
2504	kl->l_laddr = PTRTOUINT64(l);
2505	kl->l_addr = PTRTOUINT64(l->l_addr);
2506	kl->l_stat = l->l_stat;
2507	kl->l_lid = l->l_lid;
2508	kl->l_flag = l->l_flag;
2509
2510	kl->l_swtime = l->l_swtime;
2511	kl->l_slptime = l->l_slptime;
2512	if (l->l_stat == LSONPROC) {
2513		KDASSERT(l->l_cpu != NULL);
2514		kl->l_schedflags = l->l_cpu->ci_schedstate.spc_flags;
2515	} else
2516		kl->l_schedflags = 0;
2517	kl->l_holdcnt = l->l_holdcnt;
2518	kl->l_priority = l->l_priority;
2519	kl->l_usrpri = l->l_usrpri;
2520	if (l->l_wmesg)
2521		strncpy(kl->l_wmesg, l->l_wmesg, sizeof(kl->l_wmesg));
2522	kl->l_wchan = PTRTOUINT64(l->l_wchan);
2523#ifdef MULTIPROCESSOR
2524	if (l->l_cpu != NULL)
2525		kl->l_cpuid = l->l_cpu->ci_cpuid;
2526	else
2527#endif
2528		kl->l_cpuid = KI_NOCPU;
2529}
2530
2531/*
2532 * Fill in an eproc structure for the specified process.
2533 */
2534void
2535fill_eproc(struct proc *p, struct eproc *ep)
2536{
2537	struct tty *tp;
2538	struct lwp *l;
2539
2540	ep->e_paddr = p;
2541	ep->e_sess = p->p_session;
2542	ep->e_pcred = *p->p_cred;
2543	ep->e_ucred = *p->p_ucred;
2544	if (p->p_stat == SIDL || P_ZOMBIE(p)) {
2545		ep->e_vm.vm_rssize = 0;
2546		ep->e_vm.vm_tsize = 0;
2547		ep->e_vm.vm_dsize = 0;
2548		ep->e_vm.vm_ssize = 0;
2549		/* ep->e_vm.vm_pmap = XXX; */
2550	} else {
2551		struct vmspace *vm = p->p_vmspace;
2552
2553		ep->e_vm.vm_rssize = vm_resident_count(vm);
2554		ep->e_vm.vm_tsize = vm->vm_tsize;
2555		ep->e_vm.vm_dsize = vm->vm_dsize;
2556		ep->e_vm.vm_ssize = vm->vm_ssize;
2557
2558		/* Pick a "representative" LWP */
2559		l = proc_representative_lwp(p);
2560
2561		if (l->l_wmesg)
2562			strncpy(ep->e_wmesg, l->l_wmesg, WMESGLEN);
2563	}
2564	if (p->p_pptr)
2565		ep->e_ppid = p->p_pptr->p_pid;
2566	else
2567		ep->e_ppid = 0;
2568	ep->e_pgid = p->p_pgrp->pg_id;
2569	ep->e_sid = ep->e_sess->s_sid;
2570	ep->e_jobc = p->p_pgrp->pg_jobc;
2571	if ((p->p_flag & P_CONTROLT) &&
2572	    (tp = ep->e_sess->s_ttyp)) {
2573		ep->e_tdev = tp->t_dev;
2574		ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID;
2575		ep->e_tsess = tp->t_session;
2576	} else
2577		ep->e_tdev = NODEV;
2578
2579	ep->e_xsize = ep->e_xrssize = 0;
2580	ep->e_xccount = ep->e_xswrss = 0;
2581	ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
2582	if (SESS_LEADER(p))
2583		ep->e_flag |= EPROC_SLEADER;
2584	strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME);
2585}
2586