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