kern_sysctl.c revision 1549
1/*-
2 * Copyright (c) 1982, 1986, 1989, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Mike Karels at Berkeley Software Design, Inc.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by the University of
19 *	California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 *	@(#)kern_sysctl.c	8.4 (Berkeley) 4/14/94
37 */
38
39/*
40 * sysctl system call.
41 */
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/kernel.h>
46#include <sys/malloc.h>
47#include <sys/proc.h>
48#include <sys/file.h>
49#include <sys/vnode.h>
50#include <sys/unistd.h>
51#include <sys/buf.h>
52#include <sys/ioctl.h>
53#include <sys/tty.h>
54#include <vm/vm.h>
55#include <sys/sysctl.h>
56
57sysctlfn kern_sysctl;
58sysctlfn hw_sysctl;
59#ifdef DEBUG
60sysctlfn debug_sysctl;
61#endif
62extern sysctlfn vm_sysctl;
63extern sysctlfn fs_sysctl;
64extern sysctlfn net_sysctl;
65extern sysctlfn cpu_sysctl;
66
67/*
68 * Locking and stats
69 */
70static struct sysctl_lock {
71	int	sl_lock;
72	int	sl_want;
73	int	sl_locked;
74} memlock;
75
76struct sysctl_args {
77	int	*name;
78	u_int	namelen;
79	void	*old;
80	size_t	*oldlenp;
81	void	*new;
82	size_t	newlen;
83};
84
85int
86__sysctl(p, uap, retval)
87	struct proc *p;
88	register struct sysctl_args *uap;
89	int *retval;
90{
91	int error, dolock = 1;
92	u_int savelen = 0, oldlen = 0;
93	sysctlfn *fn;
94	int name[CTL_MAXNAME];
95
96	if (uap->new != NULL && (error = suser(p->p_ucred, &p->p_acflag)))
97		return (error);
98	/*
99	 * all top-level sysctl names are non-terminal
100	 */
101	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
102		return (EINVAL);
103	if (error = copyin(uap->name, &name, uap->namelen * sizeof(int)))
104		return (error);
105
106	switch (name[0]) {
107	case CTL_KERN:
108		fn = kern_sysctl;
109		if (name[2] != KERN_VNODE)	/* XXX */
110			dolock = 0;
111		break;
112	case CTL_HW:
113		fn = hw_sysctl;
114		break;
115	case CTL_VM:
116		fn = vm_sysctl;
117		break;
118	case CTL_NET:
119		fn = net_sysctl;
120		break;
121#ifdef notyet
122	case CTL_FS:
123		fn = fs_sysctl;
124		break;
125#endif
126	case CTL_MACHDEP:
127		fn = cpu_sysctl;
128		break;
129#ifdef DEBUG
130	case CTL_DEBUG:
131		fn = debug_sysctl;
132		break;
133#endif
134	default:
135		return (EOPNOTSUPP);
136	}
137
138	if (uap->oldlenp &&
139	    (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen))))
140		return (error);
141	if (uap->old != NULL) {
142		if (!useracc(uap->old, oldlen, B_WRITE))
143			return (EFAULT);
144		while (memlock.sl_lock) {
145			memlock.sl_want = 1;
146			sleep((caddr_t)&memlock, PRIBIO+1);
147			memlock.sl_locked++;
148		}
149		memlock.sl_lock = 1;
150		if (dolock)
151			vslock(uap->old, oldlen);
152		savelen = oldlen;
153	}
154	error = (*fn)(name + 1, uap->namelen - 1, uap->old, &oldlen,
155	    uap->new, uap->newlen, p);
156	if (uap->old != NULL) {
157		if (dolock)
158			vsunlock(uap->old, savelen, B_WRITE);
159		memlock.sl_lock = 0;
160		if (memlock.sl_want) {
161			memlock.sl_want = 0;
162			wakeup((caddr_t)&memlock);
163		}
164	}
165	if (error)
166		return (error);
167	if (uap->oldlenp)
168		error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen));
169	*retval = oldlen;
170	return (0);
171}
172
173/*
174 * Attributes stored in the kernel.
175 */
176char hostname[MAXHOSTNAMELEN];
177int hostnamelen;
178long hostid;
179int securelevel;
180
181/*
182 * kernel related system variables.
183 */
184int
185kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
186	int *name;
187	u_int namelen;
188	void *oldp;
189	size_t *oldlenp;
190	void *newp;
191	size_t newlen;
192	struct proc *p;
193{
194	int error, level, inthostid;
195	extern char ostype[], osrelease[], version[];
196
197	/* all sysctl names at this level are terminal */
198	if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF))
199		return (ENOTDIR);		/* overloaded */
200
201	switch (name[0]) {
202	case KERN_OSTYPE:
203		return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
204	case KERN_OSRELEASE:
205		return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
206	case KERN_OSREV:
207		return (sysctl_rdint(oldp, oldlenp, newp, BSD));
208	case KERN_VERSION:
209		return (sysctl_rdstring(oldp, oldlenp, newp, version));
210	case KERN_MAXVNODES:
211		return(sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes));
212	case KERN_MAXPROC:
213		return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc));
214	case KERN_MAXFILES:
215		return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
216	case KERN_ARGMAX:
217		return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
218	case KERN_SECURELVL:
219		level = securelevel;
220		if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
221		    newp == NULL)
222			return (error);
223		if (level < securelevel && p->p_pid != 1)
224			return (EPERM);
225		securelevel = level;
226		return (0);
227	case KERN_HOSTNAME:
228		error = sysctl_string(oldp, oldlenp, newp, newlen,
229		    hostname, sizeof(hostname));
230		if (newp && !error)
231			hostnamelen = newlen;
232		return (error);
233	case KERN_HOSTID:
234		inthostid = hostid;  /* XXX assumes sizeof long <= sizeof int */
235		error =  sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
236		hostid = inthostid;
237		return (error);
238	case KERN_CLOCKRATE:
239		return (sysctl_clockrate(oldp, oldlenp));
240	case KERN_BOOTTIME:
241		return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime,
242		    sizeof(struct timeval)));
243	case KERN_VNODE:
244		return (sysctl_vnode(oldp, oldlenp));
245	case KERN_PROC:
246		return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
247	case KERN_FILE:
248		return (sysctl_file(oldp, oldlenp));
249#ifdef GPROF
250	case KERN_PROF:
251		return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp,
252		    newp, newlen));
253#endif
254	case KERN_POSIX1:
255		return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION));
256	case KERN_NGROUPS:
257		return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX));
258	case KERN_JOB_CONTROL:
259		return (sysctl_rdint(oldp, oldlenp, newp, 1));
260	case KERN_SAVED_IDS:
261#ifdef _POSIX_SAVED_IDS
262		return (sysctl_rdint(oldp, oldlenp, newp, 1));
263#else
264		return (sysctl_rdint(oldp, oldlenp, newp, 0));
265#endif
266	default:
267		return (EOPNOTSUPP);
268	}
269	/* NOTREACHED */
270}
271
272/*
273 * hardware related system variables.
274 */
275int
276hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
277	int *name;
278	u_int namelen;
279	void *oldp;
280	size_t *oldlenp;
281	void *newp;
282	size_t newlen;
283	struct proc *p;
284{
285	extern char machine[], cpu_model[];
286
287	/* all sysctl names at this level are terminal */
288	if (namelen != 1)
289		return (ENOTDIR);		/* overloaded */
290
291	switch (name[0]) {
292	case HW_MACHINE:
293		return (sysctl_rdstring(oldp, oldlenp, newp, machine));
294	case HW_MODEL:
295		return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model));
296	case HW_NCPU:
297		return (sysctl_rdint(oldp, oldlenp, newp, 1));	/* XXX */
298	case HW_BYTEORDER:
299		return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER));
300	case HW_PHYSMEM:
301		return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem)));
302	case HW_USERMEM:
303		return (sysctl_rdint(oldp, oldlenp, newp,
304		    ctob(physmem - cnt.v_wire_count)));
305	case HW_PAGESIZE:
306		return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE));
307	default:
308		return (EOPNOTSUPP);
309	}
310	/* NOTREACHED */
311}
312
313#ifdef DEBUG
314/*
315 * Debugging related system variables.
316 */
317struct ctldebug debug0, debug1, debug2, debug3, debug4;
318struct ctldebug debug5, debug6, debug7, debug8, debug9;
319struct ctldebug debug10, debug11, debug12, debug13, debug14;
320struct ctldebug debug15, debug16, debug17, debug18, debug19;
321static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
322	&debug0, &debug1, &debug2, &debug3, &debug4,
323	&debug5, &debug6, &debug7, &debug8, &debug9,
324	&debug10, &debug11, &debug12, &debug13, &debug14,
325	&debug15, &debug16, &debug17, &debug18, &debug19,
326};
327int
328debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
329	int *name;
330	u_int namelen;
331	void *oldp;
332	size_t *oldlenp;
333	void *newp;
334	size_t newlen;
335	struct proc *p;
336{
337	struct ctldebug *cdp;
338
339	/* all sysctl names at this level are name and field */
340	if (namelen != 2)
341		return (ENOTDIR);		/* overloaded */
342	cdp = debugvars[name[0]];
343	if (cdp->debugname == 0)
344		return (EOPNOTSUPP);
345	switch (name[1]) {
346	case CTL_DEBUG_NAME:
347		return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
348	case CTL_DEBUG_VALUE:
349		return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
350	default:
351		return (EOPNOTSUPP);
352	}
353	/* NOTREACHED */
354}
355#endif /* DEBUG */
356
357/*
358 * Validate parameters and get old / set new parameters
359 * for an integer-valued sysctl function.
360 */
361int
362sysctl_int(oldp, oldlenp, newp, newlen, valp)
363	void *oldp;
364	size_t *oldlenp;
365	void *newp;
366	size_t newlen;
367	int *valp;
368{
369	int error = 0;
370
371	if (oldp && *oldlenp < sizeof(int))
372		return (ENOMEM);
373	if (newp && newlen != sizeof(int))
374		return (EINVAL);
375	*oldlenp = sizeof(int);
376	if (oldp)
377		error = copyout(valp, oldp, sizeof(int));
378	if (error == 0 && newp)
379		error = copyin(newp, valp, sizeof(int));
380	return (error);
381}
382
383/*
384 * As above, but read-only.
385 */
386int
387sysctl_rdint(oldp, oldlenp, newp, val)
388	void *oldp;
389	size_t *oldlenp;
390	void *newp;
391	int val;
392{
393	int error = 0;
394
395	if (oldp && *oldlenp < sizeof(int))
396		return (ENOMEM);
397	if (newp)
398		return (EPERM);
399	*oldlenp = sizeof(int);
400	if (oldp)
401		error = copyout((caddr_t)&val, oldp, sizeof(int));
402	return (error);
403}
404
405/*
406 * Validate parameters and get old / set new parameters
407 * for a string-valued sysctl function.
408 */
409int
410sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
411	void *oldp;
412	size_t *oldlenp;
413	void *newp;
414	size_t newlen;
415	char *str;
416	int maxlen;
417{
418	int len, error = 0;
419
420	len = strlen(str) + 1;
421	if (oldp && *oldlenp < len)
422		return (ENOMEM);
423	if (newp && newlen >= maxlen)
424		return (EINVAL);
425	if (oldp) {
426		*oldlenp = len;
427		error = copyout(str, oldp, len);
428	}
429	if (error == 0 && newp) {
430		error = copyin(newp, str, newlen);
431		str[newlen] = 0;
432	}
433	return (error);
434}
435
436/*
437 * As above, but read-only.
438 */
439int
440sysctl_rdstring(oldp, oldlenp, newp, str)
441	void *oldp;
442	size_t *oldlenp;
443	void *newp;
444	char *str;
445{
446	int len, error = 0;
447
448	len = strlen(str) + 1;
449	if (oldp && *oldlenp < len)
450		return (ENOMEM);
451	if (newp)
452		return (EPERM);
453	*oldlenp = len;
454	if (oldp)
455		error = copyout(str, oldp, len);
456	return (error);
457}
458
459/*
460 * Validate parameters and get old / set new parameters
461 * for a structure oriented sysctl function.
462 */
463int
464sysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
465	void *oldp;
466	size_t *oldlenp;
467	void *newp;
468	size_t newlen;
469	void *sp;
470	int len;
471{
472	int error = 0;
473
474	if (oldp && *oldlenp < len)
475		return (ENOMEM);
476	if (newp && newlen > len)
477		return (EINVAL);
478	if (oldp) {
479		*oldlenp = len;
480		error = copyout(sp, oldp, len);
481	}
482	if (error == 0 && newp)
483		error = copyin(newp, sp, len);
484	return (error);
485}
486
487/*
488 * Validate parameters and get old parameters
489 * for a structure oriented sysctl function.
490 */
491int
492sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
493	void *oldp;
494	size_t *oldlenp;
495	void *newp, *sp;
496	int len;
497{
498	int error = 0;
499
500	if (oldp && *oldlenp < len)
501		return (ENOMEM);
502	if (newp)
503		return (EPERM);
504	*oldlenp = len;
505	if (oldp)
506		error = copyout(sp, oldp, len);
507	return (error);
508}
509
510/*
511 * Get file structures.
512 */
513int
514sysctl_file(where, sizep)
515	char *where;
516	size_t *sizep;
517{
518	int buflen, error;
519	struct file *fp;
520	char *start = where;
521
522	buflen = *sizep;
523	if (where == NULL) {
524		/*
525		 * overestimate by 10 files
526		 */
527		*sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
528		return (0);
529	}
530
531	/*
532	 * first copyout filehead
533	 */
534	if (buflen < sizeof(filehead)) {
535		*sizep = 0;
536		return (0);
537	}
538	if (error = copyout((caddr_t)&filehead, where, sizeof(filehead)))
539		return (error);
540	buflen -= sizeof(filehead);
541	where += sizeof(filehead);
542
543	/*
544	 * followed by an array of file structures
545	 */
546	for (fp = filehead; fp != NULL; fp = fp->f_filef) {
547		if (buflen < sizeof(struct file)) {
548			*sizep = where - start;
549			return (ENOMEM);
550		}
551		if (error = copyout((caddr_t)fp, where, sizeof (struct file)))
552			return (error);
553		buflen -= sizeof(struct file);
554		where += sizeof(struct file);
555	}
556	*sizep = where - start;
557	return (0);
558}
559
560/*
561 * try over estimating by 5 procs
562 */
563#define KERN_PROCSLOP	(5 * sizeof (struct kinfo_proc))
564
565int
566sysctl_doproc(name, namelen, where, sizep)
567	int *name;
568	u_int namelen;
569	char *where;
570	size_t *sizep;
571{
572	register struct proc *p;
573	register struct kinfo_proc *dp = (struct kinfo_proc *)where;
574	register int needed = 0;
575	int buflen = where != NULL ? *sizep : 0;
576	int doingzomb;
577	struct eproc eproc;
578	int error = 0;
579
580	if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
581		return (EINVAL);
582	p = (struct proc *)allproc;
583	doingzomb = 0;
584again:
585	for (; p != NULL; p = p->p_next) {
586		/*
587		 * Skip embryonic processes.
588		 */
589		if (p->p_stat == SIDL)
590			continue;
591		/*
592		 * TODO - make more efficient (see notes below).
593		 * do by session.
594		 */
595		switch (name[0]) {
596
597		case KERN_PROC_PID:
598			/* could do this with just a lookup */
599			if (p->p_pid != (pid_t)name[1])
600				continue;
601			break;
602
603		case KERN_PROC_PGRP:
604			/* could do this by traversing pgrp */
605			if (p->p_pgrp->pg_id != (pid_t)name[1])
606				continue;
607			break;
608
609		case KERN_PROC_TTY:
610			if ((p->p_flag & P_CONTROLT) == 0 ||
611			    p->p_session->s_ttyp == NULL ||
612			    p->p_session->s_ttyp->t_dev != (dev_t)name[1])
613				continue;
614			break;
615
616		case KERN_PROC_UID:
617			if (p->p_ucred->cr_uid != (uid_t)name[1])
618				continue;
619			break;
620
621		case KERN_PROC_RUID:
622			if (p->p_cred->p_ruid != (uid_t)name[1])
623				continue;
624			break;
625		}
626		if (buflen >= sizeof(struct kinfo_proc)) {
627			fill_eproc(p, &eproc);
628			if (error = copyout((caddr_t)p, &dp->kp_proc,
629			    sizeof(struct proc)))
630				return (error);
631			if (error = copyout((caddr_t)&eproc, &dp->kp_eproc,
632			    sizeof(eproc)))
633				return (error);
634			dp++;
635			buflen -= sizeof(struct kinfo_proc);
636		}
637		needed += sizeof(struct kinfo_proc);
638	}
639	if (doingzomb == 0) {
640		p = zombproc;
641		doingzomb++;
642		goto again;
643	}
644	if (where != NULL) {
645		*sizep = (caddr_t)dp - where;
646		if (needed > *sizep)
647			return (ENOMEM);
648	} else {
649		needed += KERN_PROCSLOP;
650		*sizep = needed;
651	}
652	return (0);
653}
654
655/*
656 * Fill in an eproc structure for the specified process.
657 */
658void
659fill_eproc(p, ep)
660	register struct proc *p;
661	register struct eproc *ep;
662{
663	register struct tty *tp;
664
665	ep->e_paddr = p;
666	ep->e_sess = p->p_pgrp->pg_session;
667	ep->e_pcred = *p->p_cred;
668	ep->e_ucred = *p->p_ucred;
669	if (p->p_stat == SIDL || p->p_stat == SZOMB) {
670		ep->e_vm.vm_rssize = 0;
671		ep->e_vm.vm_tsize = 0;
672		ep->e_vm.vm_dsize = 0;
673		ep->e_vm.vm_ssize = 0;
674#ifndef sparc
675		/* ep->e_vm.vm_pmap = XXX; */
676#endif
677	} else {
678		register struct vmspace *vm = p->p_vmspace;
679
680#ifdef pmap_resident_count
681		ep->e_vm.vm_rssize = pmap_resident_count(&vm->vm_pmap); /*XXX*/
682#else
683		ep->e_vm.vm_rssize = vm->vm_rssize;
684#endif
685		ep->e_vm.vm_tsize = vm->vm_tsize;
686		ep->e_vm.vm_dsize = vm->vm_dsize;
687		ep->e_vm.vm_ssize = vm->vm_ssize;
688#ifndef sparc
689		ep->e_vm.vm_pmap = vm->vm_pmap;
690#endif
691	}
692	if (p->p_pptr)
693		ep->e_ppid = p->p_pptr->p_pid;
694	else
695		ep->e_ppid = 0;
696	ep->e_pgid = p->p_pgrp->pg_id;
697	ep->e_jobc = p->p_pgrp->pg_jobc;
698	if ((p->p_flag & P_CONTROLT) &&
699	     (tp = ep->e_sess->s_ttyp)) {
700		ep->e_tdev = tp->t_dev;
701		ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
702		ep->e_tsess = tp->t_session;
703	} else
704		ep->e_tdev = NODEV;
705	ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
706	if (SESS_LEADER(p))
707		ep->e_flag |= EPROC_SLEADER;
708	if (p->p_wmesg)
709		strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
710	ep->e_xsize = ep->e_xrssize = 0;
711	ep->e_xccount = ep->e_xswrss = 0;
712}
713
714#ifdef COMPAT_43
715#include <sys/socket.h>
716#define	KINFO_PROC		(0<<8)
717#define	KINFO_RT		(1<<8)
718#define	KINFO_VNODE		(2<<8)
719#define	KINFO_FILE		(3<<8)
720#define	KINFO_METER		(4<<8)
721#define	KINFO_LOADAVG		(5<<8)
722#define	KINFO_CLOCKRATE		(6<<8)
723
724struct getkerninfo_args {
725	int	op;
726	char	*where;
727	int	*size;
728	int	arg;
729};
730
731int
732ogetkerninfo(p, uap, retval)
733	struct proc *p;
734	register struct getkerninfo_args *uap;
735	int *retval;
736{
737	int error, name[5];
738	u_int size;
739
740	if (uap->size &&
741	    (error = copyin((caddr_t)uap->size, (caddr_t)&size, sizeof(size))))
742		return (error);
743
744	switch (uap->op & 0xff00) {
745
746	case KINFO_RT:
747		name[0] = PF_ROUTE;
748		name[1] = 0;
749		name[2] = (uap->op & 0xff0000) >> 16;
750		name[3] = uap->op & 0xff;
751		name[4] = uap->arg;
752		error = net_sysctl(name, 5, uap->where, &size, NULL, 0, p);
753		break;
754
755	case KINFO_VNODE:
756		name[0] = KERN_VNODE;
757		error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p);
758		break;
759
760	case KINFO_PROC:
761		name[0] = KERN_PROC;
762		name[1] = uap->op & 0xff;
763		name[2] = uap->arg;
764		error = kern_sysctl(name, 3, uap->where, &size, NULL, 0, p);
765		break;
766
767	case KINFO_FILE:
768		name[0] = KERN_FILE;
769		error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p);
770		break;
771
772	case KINFO_METER:
773		name[0] = VM_METER;
774		error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p);
775		break;
776
777	case KINFO_LOADAVG:
778		name[0] = VM_LOADAVG;
779		error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p);
780		break;
781
782	case KINFO_CLOCKRATE:
783		name[0] = KERN_CLOCKRATE;
784		error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p);
785		break;
786
787	default:
788		return (EOPNOTSUPP);
789	}
790	if (error)
791		return (error);
792	*retval = size;
793	if (uap->size)
794		error = copyout((caddr_t)&size, (caddr_t)uap->size,
795		    sizeof(size));
796	return (error);
797}
798#endif /* COMPAT_43 */
799