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