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