1 /* $NetBSD: kern_sysctl.c,v 1.3 1994/08/30 03:05:46 mycroft Exp $ */ 2 3 /*- 4 * Copyright (c) 1982, 1986, 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Mike Karels at Berkeley Software Design, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94 39 */ 40 41 /* 42 * sysctl system call. 43 */ 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/kernel.h> 48 #include <sys/malloc.h> 49 #include <sys/proc.h> 50 #include <sys/file.h> 51 #include <sys/vnode.h> 52 #include <sys/unistd.h> 53 #include <sys/buf.h> 54 #include <sys/ioctl.h> 55 #include <sys/tty.h> 56 #include <vm/vm.h> 57 #include <sys/sysctl.h> 58 59 sysctlfn kern_sysctl; 60 sysctlfn hw_sysctl; 61 #ifdef DEBUG 62 sysctlfn debug_sysctl; 63 #endif 64 extern sysctlfn vm_sysctl; 65 extern sysctlfn fs_sysctl; 66 extern sysctlfn net_sysctl; 67 extern sysctlfn cpu_sysctl; 68 69 /* 70 * Locking and stats 71 */ 72 static struct sysctl_lock { 73 int sl_lock; 74 int sl_want; 75 int sl_locked; 76 } memlock; 77 78 struct sysctl_args { 79 int *name; 80 u_int namelen; 81 void *old; 82 size_t *oldlenp; 83 void *new; 84 size_t newlen; 85 }; 86 87 int 88 __sysctl(p, uap, retval) 89 struct proc *p; 90 register struct sysctl_args *uap; 91 int *retval; 92 { 93 int error, dolock = 1; 94 u_int savelen, oldlen = 0; 95 sysctlfn *fn; 96 int name[CTL_MAXNAME]; 97 98 if (uap->new != NULL && (error = suser(p->p_ucred, &p->p_acflag))) 99 return (error); 100 /* 101 * all top-level sysctl names are non-terminal 102 */ 103 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 104 return (EINVAL); 105 if (error = copyin(uap->name, &name, uap->namelen * sizeof(int))) 106 return (error); 107 108 switch (name[0]) { 109 case CTL_KERN: 110 fn = kern_sysctl; 111 if (name[2] != KERN_VNODE) /* XXX */ 112 dolock = 0; 113 break; 114 case CTL_HW: 115 fn = hw_sysctl; 116 break; 117 case CTL_VM: 118 fn = vm_sysctl; 119 break; 120 case CTL_NET: 121 fn = net_sysctl; 122 break; 123 #ifdef notyet 124 case CTL_FS: 125 fn = fs_sysctl; 126 break; 127 #endif 128 case CTL_MACHDEP: 129 fn = cpu_sysctl; 130 break; 131 #ifdef DEBUG 132 case CTL_DEBUG: 133 fn = debug_sysctl; 134 break; 135 #endif 136 default: 137 return (EOPNOTSUPP); 138 } 139 140 if (uap->oldlenp && 141 (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen)))) 142 return (error); 143 if (uap->old != NULL) { 144 if (!useracc(uap->old, oldlen, B_WRITE)) 145 return (EFAULT); 146 while (memlock.sl_lock) { 147 memlock.sl_want = 1; 148 sleep((caddr_t)&memlock, PRIBIO+1); 149 memlock.sl_locked++; 150 } 151 memlock.sl_lock = 1; 152 if (dolock) 153 vslock(uap->old, oldlen); 154 savelen = oldlen; 155 } 156 error = (*fn)(name + 1, uap->namelen - 1, uap->old, &oldlen, 157 uap->new, uap->newlen, p); 158 if (uap->old != NULL) { 159 if (dolock) 160 vsunlock(uap->old, savelen, B_WRITE); 161 memlock.sl_lock = 0; 162 if (memlock.sl_want) { 163 memlock.sl_want = 0; 164 wakeup((caddr_t)&memlock); 165 } 166 } 167 if (error) 168 return (error); 169 if (uap->oldlenp) 170 error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen)); 171 *retval = oldlen; 172 return (0); 173 } 174 175 /* 176 * Attributes stored in the kernel. 177 */ 178 char hostname[MAXHOSTNAMELEN]; 179 int hostnamelen; 180 char domainname[MAXHOSTNAMELEN]; 181 int domainnamelen; 182 long hostid; 183 int securelevel; 184 185 /* 186 * kernel related system variables. 187 */ 188 kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 189 int *name; 190 u_int namelen; 191 void *oldp; 192 size_t *oldlenp; 193 void *newp; 194 size_t newlen; 195 struct proc *p; 196 { 197 int error, level, inthostid; 198 extern char ostype[], osrelease[], version[]; 199 200 /* all sysctl names at this level are terminal */ 201 if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF)) 202 return (ENOTDIR); /* overloaded */ 203 204 switch (name[0]) { 205 case KERN_OSTYPE: 206 return (sysctl_rdstring(oldp, oldlenp, newp, ostype)); 207 case KERN_OSRELEASE: 208 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease)); 209 case KERN_OSREV: 210 return (sysctl_rdint(oldp, oldlenp, newp, BSD)); 211 case KERN_VERSION: 212 return (sysctl_rdstring(oldp, oldlenp, newp, version)); 213 case KERN_MAXVNODES: 214 return(sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes)); 215 case KERN_MAXPROC: 216 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc)); 217 case KERN_MAXFILES: 218 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles)); 219 case KERN_ARGMAX: 220 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX)); 221 case KERN_SECURELVL: 222 level = securelevel; 223 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || 224 newp == NULL) 225 return (error); 226 if (level < securelevel && p->p_pid != 1) 227 return (EPERM); 228 securelevel = level; 229 return (0); 230 case KERN_HOSTNAME: 231 error = sysctl_string(oldp, oldlenp, newp, newlen, 232 hostname, sizeof(hostname)); 233 if (newp && !error) 234 hostnamelen = newlen; 235 return (error); 236 case KERN_DOMAINNAME: 237 error = sysctl_string(oldp, oldlenp, newp, newlen, 238 domainname, sizeof(domainname)); 239 if (newp && !error) 240 domainnamelen = newlen; 241 return (error); 242 case KERN_HOSTID: 243 inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */ 244 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid); 245 hostid = inthostid; 246 return (error); 247 case KERN_CLOCKRATE: 248 return (sysctl_clockrate(oldp, oldlenp)); 249 case KERN_BOOTTIME: 250 return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime, 251 sizeof(struct timeval))); 252 case KERN_VNODE: 253 return (sysctl_vnode(oldp, oldlenp)); 254 case KERN_PROC: 255 return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); 256 case KERN_FILE: 257 return (sysctl_file(oldp, oldlenp)); 258 #ifdef GPROF 259 case KERN_PROF: 260 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, 261 newp, newlen)); 262 #endif 263 case KERN_POSIX1: 264 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION)); 265 case KERN_NGROUPS: 266 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX)); 267 case KERN_JOB_CONTROL: 268 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 269 case KERN_SAVED_IDS: 270 #ifdef _POSIX_SAVED_IDS 271 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 272 #else 273 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 274 #endif 275 default: 276 return (EOPNOTSUPP); 277 } 278 /* NOTREACHED */ 279 } 280 281 /* 282 * hardware related system variables. 283 */ 284 hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 285 int *name; 286 u_int namelen; 287 void *oldp; 288 size_t *oldlenp; 289 void *newp; 290 size_t newlen; 291 struct proc *p; 292 { 293 extern char machine[], cpu_model[]; 294 295 /* all sysctl names at this level are terminal */ 296 if (namelen != 1) 297 return (ENOTDIR); /* overloaded */ 298 299 switch (name[0]) { 300 case HW_MACHINE: 301 return (sysctl_rdstring(oldp, oldlenp, newp, machine)); 302 case HW_MODEL: 303 return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); 304 case HW_NCPU: 305 return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */ 306 case HW_BYTEORDER: 307 return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER)); 308 case HW_PHYSMEM: 309 return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); 310 case HW_USERMEM: 311 return (sysctl_rdint(oldp, oldlenp, newp, 312 ctob(physmem - cnt.v_wire_count))); 313 case HW_PAGESIZE: 314 return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE)); 315 default: 316 return (EOPNOTSUPP); 317 } 318 /* NOTREACHED */ 319 } 320 321 #ifdef DEBUG 322 /* 323 * Debugging related system variables. 324 */ 325 struct ctldebug debug0, debug1, debug2, debug3, debug4; 326 struct ctldebug debug5, debug6, debug7, debug8, debug9; 327 struct ctldebug debug10, debug11, debug12, debug13, debug14; 328 struct ctldebug debug15, debug16, debug17, debug18, debug19; 329 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 330 &debug0, &debug1, &debug2, &debug3, &debug4, 331 &debug5, &debug6, &debug7, &debug8, &debug9, 332 &debug10, &debug11, &debug12, &debug13, &debug14, 333 &debug15, &debug16, &debug17, &debug18, &debug19, 334 }; 335 int 336 debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 337 int *name; 338 u_int namelen; 339 void *oldp; 340 size_t *oldlenp; 341 void *newp; 342 size_t newlen; 343 struct proc *p; 344 { 345 struct ctldebug *cdp; 346 347 /* all sysctl names at this level are name and field */ 348 if (namelen != 2) 349 return (ENOTDIR); /* overloaded */ 350 cdp = debugvars[name[0]]; 351 if (cdp->debugname == 0) 352 return (EOPNOTSUPP); 353 switch (name[1]) { 354 case CTL_DEBUG_NAME: 355 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 356 case CTL_DEBUG_VALUE: 357 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 358 default: 359 return (EOPNOTSUPP); 360 } 361 /* NOTREACHED */ 362 } 363 #endif /* DEBUG */ 364 365 /* 366 * Validate parameters and get old / set new parameters 367 * for an integer-valued sysctl function. 368 */ 369 sysctl_int(oldp, oldlenp, newp, newlen, valp) 370 void *oldp; 371 size_t *oldlenp; 372 void *newp; 373 size_t newlen; 374 int *valp; 375 { 376 int error = 0; 377 378 if (oldp && *oldlenp < sizeof(int)) 379 return (ENOMEM); 380 if (newp && newlen != sizeof(int)) 381 return (EINVAL); 382 *oldlenp = sizeof(int); 383 if (oldp) 384 error = copyout(valp, oldp, sizeof(int)); 385 if (error == 0 && newp) 386 error = copyin(newp, valp, sizeof(int)); 387 return (error); 388 } 389 390 /* 391 * As above, but read-only. 392 */ 393 sysctl_rdint(oldp, oldlenp, newp, val) 394 void *oldp; 395 size_t *oldlenp; 396 void *newp; 397 int val; 398 { 399 int error = 0; 400 401 if (oldp && *oldlenp < sizeof(int)) 402 return (ENOMEM); 403 if (newp) 404 return (EPERM); 405 *oldlenp = sizeof(int); 406 if (oldp) 407 error = copyout((caddr_t)&val, oldp, sizeof(int)); 408 return (error); 409 } 410 411 /* 412 * Validate parameters and get old / set new parameters 413 * for a string-valued sysctl function. 414 */ 415 sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) 416 void *oldp; 417 size_t *oldlenp; 418 void *newp; 419 size_t newlen; 420 char *str; 421 int maxlen; 422 { 423 int len, error = 0; 424 425 len = strlen(str) + 1; 426 if (oldp && *oldlenp < len) 427 return (ENOMEM); 428 if (newp && newlen >= maxlen) 429 return (EINVAL); 430 if (oldp) { 431 *oldlenp = len; 432 error = copyout(str, oldp, len); 433 } 434 if (error == 0 && newp) { 435 error = copyin(newp, str, newlen); 436 str[newlen] = 0; 437 } 438 return (error); 439 } 440 441 /* 442 * As above, but read-only. 443 */ 444 sysctl_rdstring(oldp, oldlenp, newp, str) 445 void *oldp; 446 size_t *oldlenp; 447 void *newp; 448 char *str; 449 { 450 int len, error = 0; 451 452 len = strlen(str) + 1; 453 if (oldp && *oldlenp < len) 454 return (ENOMEM); 455 if (newp) 456 return (EPERM); 457 *oldlenp = len; 458 if (oldp) 459 error = copyout(str, oldp, len); 460 return (error); 461 } 462 463 /* 464 * Validate parameters and get old / set new parameters 465 * for a structure oriented sysctl function. 466 */ 467 sysctl_struct(oldp, oldlenp, newp, newlen, sp, len) 468 void *oldp; 469 size_t *oldlenp; 470 void *newp; 471 size_t newlen; 472 void *sp; 473 int len; 474 { 475 int error = 0; 476 477 if (oldp && *oldlenp < len) 478 return (ENOMEM); 479 if (newp && newlen > len) 480 return (EINVAL); 481 if (oldp) { 482 *oldlenp = len; 483 error = copyout(sp, oldp, len); 484 } 485 if (error == 0 && newp) 486 error = copyin(newp, sp, len); 487 return (error); 488 } 489 490 /* 491 * Validate parameters and get old parameters 492 * for a structure oriented sysctl function. 493 */ 494 sysctl_rdstruct(oldp, oldlenp, newp, sp, len) 495 void *oldp; 496 size_t *oldlenp; 497 void *newp, *sp; 498 int len; 499 { 500 int error = 0; 501 502 if (oldp && *oldlenp < len) 503 return (ENOMEM); 504 if (newp) 505 return (EPERM); 506 *oldlenp = len; 507 if (oldp) 508 error = copyout(sp, oldp, len); 509 return (error); 510 } 511 512 /* 513 * Get file structures. 514 */ 515 sysctl_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.lh_first; fp != 0; fp = fp->f_list.le_next) { 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 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 = allproc.lh_first; 583 doingzomb = 0; 584 again: 585 for (; p != 0; p = p->p_list.le_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.lh_first; 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 ogetkerninfo(p, uap, retval) 732 struct proc *p; 733 register struct getkerninfo_args *uap; 734 int *retval; 735 { 736 int error, name[5]; 737 u_int size; 738 739 if (uap->size && 740 (error = copyin((caddr_t)uap->size, (caddr_t)&size, sizeof(size)))) 741 return (error); 742 743 switch (uap->op & 0xff00) { 744 745 case KINFO_RT: 746 name[0] = PF_ROUTE; 747 name[1] = 0; 748 name[2] = (uap->op & 0xff0000) >> 16; 749 name[3] = uap->op & 0xff; 750 name[4] = uap->arg; 751 error = net_sysctl(name, 5, uap->where, &size, NULL, 0, p); 752 break; 753 754 case KINFO_VNODE: 755 name[0] = KERN_VNODE; 756 error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 757 break; 758 759 case KINFO_PROC: 760 name[0] = KERN_PROC; 761 name[1] = uap->op & 0xff; 762 name[2] = uap->arg; 763 error = kern_sysctl(name, 3, uap->where, &size, NULL, 0, p); 764 break; 765 766 case KINFO_FILE: 767 name[0] = KERN_FILE; 768 error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 769 break; 770 771 case KINFO_METER: 772 name[0] = VM_METER; 773 error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 774 break; 775 776 case KINFO_LOADAVG: 777 name[0] = VM_LOADAVG; 778 error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); 779 break; 780 781 case KINFO_CLOCKRATE: 782 name[0] = KERN_CLOCKRATE; 783 error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); 784 break; 785 786 default: 787 return (EOPNOTSUPP); 788 } 789 if (error) 790 return (error); 791 *retval = size; 792 if (uap->size) 793 error = copyout((caddr_t)&size, (caddr_t)uap->size, 794 sizeof(size)); 795 return (error); 796 } 797 #endif /* COMPAT_43 */ 798