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