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