kern_sysctl.c revision 1542
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, 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 */
184kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
185	int *name;
186	u_int namelen;
187	void *oldp;
188	size_t *oldlenp;
189	void *newp;
190	size_t newlen;
191	struct proc *p;
192{
193	int error, level, inthostid;
194	extern char ostype[], osrelease[], version[];
195
196	/* all sysctl names at this level are terminal */
197	if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF))
198		return (ENOTDIR);		/* overloaded */
199
200	switch (name[0]) {
201	case KERN_OSTYPE:
202		return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
203	case KERN_OSRELEASE:
204		return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
205	case KERN_OSREV:
206		return (sysctl_rdint(oldp, oldlenp, newp, BSD));
207	case KERN_VERSION:
208		return (sysctl_rdstring(oldp, oldlenp, newp, version));
209	case KERN_MAXVNODES:
210		return(sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes));
211	case KERN_MAXPROC:
212		return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc));
213	case KERN_MAXFILES:
214		return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
215	case KERN_ARGMAX:
216		return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
217	case KERN_SECURELVL:
218		level = securelevel;
219		if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
220		    newp == NULL)
221			return (error);
222		if (level < securelevel && p->p_pid != 1)
223			return (EPERM);
224		securelevel = level;
225		return (0);
226	case KERN_HOSTNAME:
227		error = sysctl_string(oldp, oldlenp, newp, newlen,
228		    hostname, sizeof(hostname));
229		if (newp && !error)
230			hostnamelen = newlen;
231		return (error);
232	case KERN_HOSTID:
233		inthostid = hostid;  /* XXX assumes sizeof long <= sizeof int */
234		error =  sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
235		hostid = inthostid;
236		return (error);
237	case KERN_CLOCKRATE:
238		return (sysctl_clockrate(oldp, oldlenp));
239	case KERN_BOOTTIME:
240		return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime,
241		    sizeof(struct timeval)));
242	case KERN_VNODE:
243		return (sysctl_vnode(oldp, oldlenp));
244	case KERN_PROC:
245		return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
246	case KERN_FILE:
247		return (sysctl_file(oldp, oldlenp));
248#ifdef GPROF
249	case KERN_PROF:
250		return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp,
251		    newp, newlen));
252#endif
253	case KERN_POSIX1:
254		return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION));
255	case KERN_NGROUPS:
256		return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX));
257	case KERN_JOB_CONTROL:
258		return (sysctl_rdint(oldp, oldlenp, newp, 1));
259	case KERN_SAVED_IDS:
260#ifdef _POSIX_SAVED_IDS
261		return (sysctl_rdint(oldp, oldlenp, newp, 1));
262#else
263		return (sysctl_rdint(oldp, oldlenp, newp, 0));
264#endif
265	default:
266		return (EOPNOTSUPP);
267	}
268	/* NOTREACHED */
269}
270
271/*
272 * hardware related system variables.
273 */
274hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
275	int *name;
276	u_int namelen;
277	void *oldp;
278	size_t *oldlenp;
279	void *newp;
280	size_t newlen;
281	struct proc *p;
282{
283	extern char machine[], cpu_model[];
284
285	/* all sysctl names at this level are terminal */
286	if (namelen != 1)
287		return (ENOTDIR);		/* overloaded */
288
289	switch (name[0]) {
290	case HW_MACHINE:
291		return (sysctl_rdstring(oldp, oldlenp, newp, machine));
292	case HW_MODEL:
293		return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model));
294	case HW_NCPU:
295		return (sysctl_rdint(oldp, oldlenp, newp, 1));	/* XXX */
296	case HW_BYTEORDER:
297		return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER));
298	case HW_PHYSMEM:
299		return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem)));
300	case HW_USERMEM:
301		return (sysctl_rdint(oldp, oldlenp, newp,
302		    ctob(physmem - cnt.v_wire_count)));
303	case HW_PAGESIZE:
304		return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE));
305	default:
306		return (EOPNOTSUPP);
307	}
308	/* NOTREACHED */
309}
310
311#ifdef DEBUG
312/*
313 * Debugging related system variables.
314 */
315struct ctldebug debug0, debug1, debug2, debug3, debug4;
316struct ctldebug debug5, debug6, debug7, debug8, debug9;
317struct ctldebug debug10, debug11, debug12, debug13, debug14;
318struct ctldebug debug15, debug16, debug17, debug18, debug19;
319static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
320	&debug0, &debug1, &debug2, &debug3, &debug4,
321	&debug5, &debug6, &debug7, &debug8, &debug9,
322	&debug10, &debug11, &debug12, &debug13, &debug14,
323	&debug15, &debug16, &debug17, &debug18, &debug19,
324};
325int
326debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
327	int *name;
328	u_int namelen;
329	void *oldp;
330	size_t *oldlenp;
331	void *newp;
332	size_t newlen;
333	struct proc *p;
334{
335	struct ctldebug *cdp;
336
337	/* all sysctl names at this level are name and field */
338	if (namelen != 2)
339		return (ENOTDIR);		/* overloaded */
340	cdp = debugvars[name[0]];
341	if (cdp->debugname == 0)
342		return (EOPNOTSUPP);
343	switch (name[1]) {
344	case CTL_DEBUG_NAME:
345		return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
346	case CTL_DEBUG_VALUE:
347		return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
348	default:
349		return (EOPNOTSUPP);
350	}
351	/* NOTREACHED */
352}
353#endif /* DEBUG */
354
355/*
356 * Validate parameters and get old / set new parameters
357 * for an integer-valued sysctl function.
358 */
359sysctl_int(oldp, oldlenp, newp, newlen, valp)
360	void *oldp;
361	size_t *oldlenp;
362	void *newp;
363	size_t newlen;
364	int *valp;
365{
366	int error = 0;
367
368	if (oldp && *oldlenp < sizeof(int))
369		return (ENOMEM);
370	if (newp && newlen != sizeof(int))
371		return (EINVAL);
372	*oldlenp = sizeof(int);
373	if (oldp)
374		error = copyout(valp, oldp, sizeof(int));
375	if (error == 0 && newp)
376		error = copyin(newp, valp, sizeof(int));
377	return (error);
378}
379
380/*
381 * As above, but read-only.
382 */
383sysctl_rdint(oldp, oldlenp, newp, val)
384	void *oldp;
385	size_t *oldlenp;
386	void *newp;
387	int val;
388{
389	int error = 0;
390
391	if (oldp && *oldlenp < sizeof(int))
392		return (ENOMEM);
393	if (newp)
394		return (EPERM);
395	*oldlenp = sizeof(int);
396	if (oldp)
397		error = copyout((caddr_t)&val, oldp, sizeof(int));
398	return (error);
399}
400
401/*
402 * Validate parameters and get old / set new parameters
403 * for a string-valued sysctl function.
404 */
405sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
406	void *oldp;
407	size_t *oldlenp;
408	void *newp;
409	size_t newlen;
410	char *str;
411	int maxlen;
412{
413	int len, error = 0;
414
415	len = strlen(str) + 1;
416	if (oldp && *oldlenp < len)
417		return (ENOMEM);
418	if (newp && newlen >= maxlen)
419		return (EINVAL);
420	if (oldp) {
421		*oldlenp = len;
422		error = copyout(str, oldp, len);
423	}
424	if (error == 0 && newp) {
425		error = copyin(newp, str, newlen);
426		str[newlen] = 0;
427	}
428	return (error);
429}
430
431/*
432 * As above, but read-only.
433 */
434sysctl_rdstring(oldp, oldlenp, newp, str)
435	void *oldp;
436	size_t *oldlenp;
437	void *newp;
438	char *str;
439{
440	int len, error = 0;
441
442	len = strlen(str) + 1;
443	if (oldp && *oldlenp < len)
444		return (ENOMEM);
445	if (newp)
446		return (EPERM);
447	*oldlenp = len;
448	if (oldp)
449		error = copyout(str, oldp, len);
450	return (error);
451}
452
453/*
454 * Validate parameters and get old / set new parameters
455 * for a structure oriented sysctl function.
456 */
457sysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
458	void *oldp;
459	size_t *oldlenp;
460	void *newp;
461	size_t newlen;
462	void *sp;
463	int len;
464{
465	int error = 0;
466
467	if (oldp && *oldlenp < len)
468		return (ENOMEM);
469	if (newp && newlen > len)
470		return (EINVAL);
471	if (oldp) {
472		*oldlenp = len;
473		error = copyout(sp, oldp, len);
474	}
475	if (error == 0 && newp)
476		error = copyin(newp, sp, len);
477	return (error);
478}
479
480/*
481 * Validate parameters and get old parameters
482 * for a structure oriented sysctl function.
483 */
484sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
485	void *oldp;
486	size_t *oldlenp;
487	void *newp, *sp;
488	int len;
489{
490	int error = 0;
491
492	if (oldp && *oldlenp < len)
493		return (ENOMEM);
494	if (newp)
495		return (EPERM);
496	*oldlenp = len;
497	if (oldp)
498		error = copyout(sp, oldp, len);
499	return (error);
500}
501
502/*
503 * Get file structures.
504 */
505sysctl_file(where, sizep)
506	char *where;
507	size_t *sizep;
508{
509	int buflen, error;
510	struct file *fp;
511	char *start = where;
512
513	buflen = *sizep;
514	if (where == NULL) {
515		/*
516		 * overestimate by 10 files
517		 */
518		*sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
519		return (0);
520	}
521
522	/*
523	 * first copyout filehead
524	 */
525	if (buflen < sizeof(filehead)) {
526		*sizep = 0;
527		return (0);
528	}
529	if (error = copyout((caddr_t)&filehead, where, sizeof(filehead)))
530		return (error);
531	buflen -= sizeof(filehead);
532	where += sizeof(filehead);
533
534	/*
535	 * followed by an array of file structures
536	 */
537	for (fp = filehead; fp != NULL; fp = fp->f_filef) {
538		if (buflen < sizeof(struct file)) {
539			*sizep = where - start;
540			return (ENOMEM);
541		}
542		if (error = copyout((caddr_t)fp, where, sizeof (struct file)))
543			return (error);
544		buflen -= sizeof(struct file);
545		where += sizeof(struct file);
546	}
547	*sizep = where - start;
548	return (0);
549}
550
551/*
552 * try over estimating by 5 procs
553 */
554#define KERN_PROCSLOP	(5 * sizeof (struct kinfo_proc))
555
556sysctl_doproc(name, namelen, where, sizep)
557	int *name;
558	u_int namelen;
559	char *where;
560	size_t *sizep;
561{
562	register struct proc *p;
563	register struct kinfo_proc *dp = (struct kinfo_proc *)where;
564	register int needed = 0;
565	int buflen = where != NULL ? *sizep : 0;
566	int doingzomb;
567	struct eproc eproc;
568	int error = 0;
569
570	if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
571		return (EINVAL);
572	p = (struct proc *)allproc;
573	doingzomb = 0;
574again:
575	for (; p != NULL; p = p->p_next) {
576		/*
577		 * Skip embryonic processes.
578		 */
579		if (p->p_stat == SIDL)
580			continue;
581		/*
582		 * TODO - make more efficient (see notes below).
583		 * do by session.
584		 */
585		switch (name[0]) {
586
587		case KERN_PROC_PID:
588			/* could do this with just a lookup */
589			if (p->p_pid != (pid_t)name[1])
590				continue;
591			break;
592
593		case KERN_PROC_PGRP:
594			/* could do this by traversing pgrp */
595			if (p->p_pgrp->pg_id != (pid_t)name[1])
596				continue;
597			break;
598
599		case KERN_PROC_TTY:
600			if ((p->p_flag & P_CONTROLT) == 0 ||
601			    p->p_session->s_ttyp == NULL ||
602			    p->p_session->s_ttyp->t_dev != (dev_t)name[1])
603				continue;
604			break;
605
606		case KERN_PROC_UID:
607			if (p->p_ucred->cr_uid != (uid_t)name[1])
608				continue;
609			break;
610
611		case KERN_PROC_RUID:
612			if (p->p_cred->p_ruid != (uid_t)name[1])
613				continue;
614			break;
615		}
616		if (buflen >= sizeof(struct kinfo_proc)) {
617			fill_eproc(p, &eproc);
618			if (error = copyout((caddr_t)p, &dp->kp_proc,
619			    sizeof(struct proc)))
620				return (error);
621			if (error = copyout((caddr_t)&eproc, &dp->kp_eproc,
622			    sizeof(eproc)))
623				return (error);
624			dp++;
625			buflen -= sizeof(struct kinfo_proc);
626		}
627		needed += sizeof(struct kinfo_proc);
628	}
629	if (doingzomb == 0) {
630		p = zombproc;
631		doingzomb++;
632		goto again;
633	}
634	if (where != NULL) {
635		*sizep = (caddr_t)dp - where;
636		if (needed > *sizep)
637			return (ENOMEM);
638	} else {
639		needed += KERN_PROCSLOP;
640		*sizep = needed;
641	}
642	return (0);
643}
644
645/*
646 * Fill in an eproc structure for the specified process.
647 */
648void
649fill_eproc(p, ep)
650	register struct proc *p;
651	register struct eproc *ep;
652{
653	register struct tty *tp;
654
655	ep->e_paddr = p;
656	ep->e_sess = p->p_pgrp->pg_session;
657	ep->e_pcred = *p->p_cred;
658	ep->e_ucred = *p->p_ucred;
659	if (p->p_stat == SIDL || p->p_stat == SZOMB) {
660		ep->e_vm.vm_rssize = 0;
661		ep->e_vm.vm_tsize = 0;
662		ep->e_vm.vm_dsize = 0;
663		ep->e_vm.vm_ssize = 0;
664#ifndef sparc
665		/* ep->e_vm.vm_pmap = XXX; */
666#endif
667	} else {
668		register struct vmspace *vm = p->p_vmspace;
669
670#ifdef pmap_resident_count
671		ep->e_vm.vm_rssize = pmap_resident_count(&vm->vm_pmap); /*XXX*/
672#else
673		ep->e_vm.vm_rssize = vm->vm_rssize;
674#endif
675		ep->e_vm.vm_tsize = vm->vm_tsize;
676		ep->e_vm.vm_dsize = vm->vm_dsize;
677		ep->e_vm.vm_ssize = vm->vm_ssize;
678#ifndef sparc
679		ep->e_vm.vm_pmap = vm->vm_pmap;
680#endif
681	}
682	if (p->p_pptr)
683		ep->e_ppid = p->p_pptr->p_pid;
684	else
685		ep->e_ppid = 0;
686	ep->e_pgid = p->p_pgrp->pg_id;
687	ep->e_jobc = p->p_pgrp->pg_jobc;
688	if ((p->p_flag & P_CONTROLT) &&
689	     (tp = ep->e_sess->s_ttyp)) {
690		ep->e_tdev = tp->t_dev;
691		ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
692		ep->e_tsess = tp->t_session;
693	} else
694		ep->e_tdev = NODEV;
695	ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
696	if (SESS_LEADER(p))
697		ep->e_flag |= EPROC_SLEADER;
698	if (p->p_wmesg)
699		strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
700	ep->e_xsize = ep->e_xrssize = 0;
701	ep->e_xccount = ep->e_xswrss = 0;
702}
703
704#ifdef COMPAT_43
705#include <sys/socket.h>
706#define	KINFO_PROC		(0<<8)
707#define	KINFO_RT		(1<<8)
708#define	KINFO_VNODE		(2<<8)
709#define	KINFO_FILE		(3<<8)
710#define	KINFO_METER		(4<<8)
711#define	KINFO_LOADAVG		(5<<8)
712#define	KINFO_CLOCKRATE		(6<<8)
713
714struct getkerninfo_args {
715	int	op;
716	char	*where;
717	int	*size;
718	int	arg;
719};
720
721ogetkerninfo(p, uap, retval)
722	struct proc *p;
723	register struct getkerninfo_args *uap;
724	int *retval;
725{
726	int error, name[5];
727	u_int size;
728
729	if (uap->size &&
730	    (error = copyin((caddr_t)uap->size, (caddr_t)&size, sizeof(size))))
731		return (error);
732
733	switch (uap->op & 0xff00) {
734
735	case KINFO_RT:
736		name[0] = PF_ROUTE;
737		name[1] = 0;
738		name[2] = (uap->op & 0xff0000) >> 16;
739		name[3] = uap->op & 0xff;
740		name[4] = uap->arg;
741		error = net_sysctl(name, 5, uap->where, &size, NULL, 0, p);
742		break;
743
744	case KINFO_VNODE:
745		name[0] = KERN_VNODE;
746		error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p);
747		break;
748
749	case KINFO_PROC:
750		name[0] = KERN_PROC;
751		name[1] = uap->op & 0xff;
752		name[2] = uap->arg;
753		error = kern_sysctl(name, 3, uap->where, &size, NULL, 0, p);
754		break;
755
756	case KINFO_FILE:
757		name[0] = KERN_FILE;
758		error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p);
759		break;
760
761	case KINFO_METER:
762		name[0] = VM_METER;
763		error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p);
764		break;
765
766	case KINFO_LOADAVG:
767		name[0] = VM_LOADAVG;
768		error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p);
769		break;
770
771	case KINFO_CLOCKRATE:
772		name[0] = KERN_CLOCKRATE;
773		error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p);
774		break;
775
776	default:
777		return (EOPNOTSUPP);
778	}
779	if (error)
780		return (error);
781	*retval = size;
782	if (uap->size)
783		error = copyout((caddr_t)&size, (caddr_t)uap->size,
784		    sizeof(size));
785	return (error);
786}
787#endif /* COMPAT_43 */
788