kern_sysctl.c revision 1541
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