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