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