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