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