kern_sysctl.c revision 12243
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: kern_sysctl.c,v 1.37 1995/11/12 06:43:01 bde Exp $ 38 */ 39 40/* 41 * sysctl system call. 42 */ 43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/sysproto.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 <sys/conf.h> 57#include <vm/vm.h> 58#include <sys/sysctl.h> 59#include <sys/user.h> 60 61extern struct linker_set sysctl_; 62 63/* BEGIN_MIB */ 64SYSCTL_NODE(, 0, sysctl, CTLFLAG_RW, 0, 65 "Sysctl internal magic"); 66SYSCTL_NODE(, CTL_KERN, kern, CTLFLAG_RW, 0, 67 "High kernel, proc, limits &c"); 68SYSCTL_NODE(, CTL_VM, vm, CTLFLAG_RW, 0, 69 "Virtual memory"); 70SYSCTL_NODE(, CTL_FS, fs, CTLFLAG_RW, 0, 71 "File system"); 72SYSCTL_NODE(, CTL_NET, net, CTLFLAG_RW, 0, 73 "Network, (see socket.h)"); 74SYSCTL_NODE(, CTL_DEBUG, debug, CTLFLAG_RW, 0, 75 "Debugging"); 76SYSCTL_NODE(, CTL_HW, hw, CTLFLAG_RW, 0, 77 "hardware"); 78SYSCTL_NODE(, CTL_MACHDEP, machdep, CTLFLAG_RW, 0, 79 "machine dependent"); 80SYSCTL_NODE(, CTL_USER, user, CTLFLAG_RW, 0, 81 "user-level"); 82 83SYSCTL_STRING(_kern, KERN_OSRELEASE, osrelease, CTLFLAG_RD, osrelease, 0, ""); 84 85SYSCTL_INT(_kern, KERN_OSREV, osrevision, CTLFLAG_RD, 0, BSD, ""); 86 87SYSCTL_STRING(_kern, KERN_VERSION, version, CTLFLAG_RD, version, 0, ""); 88 89SYSCTL_STRING(_kern, KERN_OSTYPE, ostype, CTLFLAG_RD, ostype, 0, ""); 90 91extern int osreldate; 92SYSCTL_INT(_kern, KERN_OSRELDATE, osreldate, CTLFLAG_RD, &osreldate, 0, ""); 93 94SYSCTL_INT(_kern, KERN_MAXVNODES, maxvnodes, CTLFLAG_RD, &desiredvnodes, 0, ""); 95 96SYSCTL_INT(_kern, KERN_MAXPROC, maxproc, CTLFLAG_RD, &maxproc, 0, ""); 97 98SYSCTL_INT(_kern, KERN_MAXPROCPERUID, maxprocperuid, 99 CTLFLAG_RD, &maxprocperuid, 0, ""); 100 101SYSCTL_INT(_kern, KERN_MAXFILESPERPROC, maxfilesperproc, 102 CTLFLAG_RD, &maxfilesperproc, 0, ""); 103 104SYSCTL_INT(_kern, KERN_ARGMAX, argmax, CTLFLAG_RD, 0, ARG_MAX, ""); 105 106SYSCTL_INT(_kern, KERN_POSIX1, posix1version, CTLFLAG_RD, 0, _POSIX_VERSION, ""); 107 108SYSCTL_INT(_kern, KERN_NGROUPS, ngroups, CTLFLAG_RD, 0, NGROUPS_MAX, ""); 109 110SYSCTL_INT(_kern, KERN_JOB_CONTROL, job_control, CTLFLAG_RD, 0, 1, ""); 111 112SYSCTL_INT(_kern, KERN_MAXFILES, maxfiles, CTLFLAG_RW, &maxfiles, 0, ""); 113 114#ifdef _POSIX_SAVED_IDS 115SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD, 0, 1, ""); 116#else 117SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD, 0, 0, ""); 118#endif 119 120char kernelname[MAXPATHLEN] = "/kernel"; /* XXX bloat */ 121 122SYSCTL_STRING(_kern, KERN_BOOTFILE, bootfile, 123 CTLFLAG_RW, kernelname, sizeof kernelname, ""); 124 125SYSCTL_STRUCT(_kern, KERN_BOOTTIME, boottime, 126 CTLFLAG_RW, &boottime, timeval, ""); 127 128SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); 129 130SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, ""); 131 132SYSCTL_INT(_hw, HW_NCPU, ncpu, CTLFLAG_RD, 0, 1, ""); 133 134SYSCTL_INT(_hw, HW_BYTEORDER, byteorder, CTLFLAG_RD, 0, BYTE_ORDER, ""); 135 136SYSCTL_INT(_hw, HW_PAGESIZE, pagesize, CTLFLAG_RD, 0, PAGE_SIZE, ""); 137 138/* END_MIB */ 139 140extern int vfs_update_wakeup; 141extern int vfs_update_interval; 142static int 143sysctl_kern_updateinterval SYSCTL_HANDLER_ARGS 144{ 145 int error = sysctl_handle_int(oidp, 146 oidp->oid_arg1, oidp->oid_arg2, req); 147 if (!error) 148 wakeup(&vfs_update_wakeup); 149 return error; 150} 151 152SYSCTL_PROC(_kern, KERN_UPDATEINTERVAL, update, CTLTYPE_INT|CTLFLAG_RW, 153 &vfs_update_interval, 0, sysctl_kern_updateinterval, ""); 154 155 156char hostname[MAXHOSTNAMELEN]; 157int hostnamelen; 158static int 159sysctl_kern_hostname SYSCTL_HANDLER_ARGS 160{ 161 int error = sysctl_handle_string(oidp, 162 oidp->oid_arg1, oidp->oid_arg2, req); 163 if (req->newptr && (error == 0 || error == ENOMEM)) 164 hostnamelen = req->newlen; 165 return error; 166} 167 168SYSCTL_PROC(_kern, KERN_HOSTNAME, hostname, CTLTYPE_STRING|CTLFLAG_RW, 169 &hostname, sizeof(hostname), sysctl_kern_hostname, ""); 170 171static int 172sysctl_order_cmp(const void *a, const void *b) 173{ 174 const struct sysctl_oid **pa, **pb; 175 176 pa = (const struct sysctl_oid **)a; 177 pb = (const struct sysctl_oid **)b; 178 if (*pa == NULL) 179 return (1); 180 if (*pb == NULL) 181 return (-1); 182 return ((*pa)->oid_number - (*pb)->oid_number); 183} 184 185static void 186sysctl_order(void *arg) 187{ 188 int j; 189 struct linker_set *l = (struct linker_set *) arg; 190 struct sysctl_oid **oidpp; 191 192 j = l->ls_length; 193 oidpp = (struct sysctl_oid **) l->ls_items; 194 for (; j--; oidpp++) { 195 if (!*oidpp) 196 continue; 197 if ((*oidpp)->oid_arg1 == arg) { 198 *oidpp = 0; 199 continue; 200 } 201 if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) 202 if (!(*oidpp)->oid_handler) 203 sysctl_order((*oidpp)->oid_arg1); 204 } 205 qsort(l->ls_items, l->ls_length, sizeof l->ls_items[0], 206 sysctl_order_cmp); 207} 208 209SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_order, &sysctl_); 210 211static void 212sysctl_sysctl_debug_dump_node(struct linker_set *l, int i) 213{ 214 int j, k; 215 struct sysctl_oid **oidpp; 216 217 j = l->ls_length; 218 oidpp = (struct sysctl_oid **) l->ls_items; 219 for (; j--; oidpp++) { 220 221 if (!*oidpp) 222 continue; 223 224 for (k=0; k<i; k++) 225 printf(" "); 226 227 if ((*oidpp)->oid_number > 100) { 228 printf("Junk! %p # %d %s k %x a1 %p a2 %x h %p\n", 229 *oidpp, 230 (*oidpp)->oid_number, (*oidpp)->oid_name, 231 (*oidpp)->oid_kind, (*oidpp)->oid_arg1, 232 (*oidpp)->oid_arg2, (*oidpp)->oid_handler); 233 continue; 234 } 235 printf("%d %s ", (*oidpp)->oid_number, (*oidpp)->oid_name); 236 237 printf("%c%c", 238 (*oidpp)->oid_kind & CTLFLAG_RD ? 'R':' ', 239 (*oidpp)->oid_kind & CTLFLAG_WR ? 'W':' '); 240 241 switch ((*oidpp)->oid_kind & CTLTYPE) { 242 case CTLTYPE_NODE: 243 if ((*oidpp)->oid_handler) { 244 printf(" Node(proc)\n"); 245 } else { 246 printf(" Node\n"); 247 sysctl_sysctl_debug_dump_node( 248 (*oidpp)->oid_arg1, i+2); 249 } 250 break; 251 case CTLTYPE_INT: printf(" Int\n"); break; 252 case CTLTYPE_STRING: printf(" String\n"); break; 253 case CTLTYPE_QUAD: printf(" Quad\n"); break; 254 case CTLTYPE_OPAQUE: printf(" Opaque/struct\n"); break; 255 default: printf("\n"); 256 } 257 258 } 259} 260 261 262static int 263sysctl_sysctl_debug SYSCTL_HANDLER_ARGS 264{ 265 sysctl_sysctl_debug_dump_node(&sysctl_, 0); 266 return ENOENT; 267} 268 269SYSCTL_PROC(_sysctl, 0, debug, CTLTYPE_STRING|CTLFLAG_RD, 270 0, 0, sysctl_sysctl_debug, ""); 271 272char domainname[MAXHOSTNAMELEN]; 273int domainnamelen; 274static int 275sysctl_kern_domainname SYSCTL_HANDLER_ARGS 276{ 277 int error = sysctl_handle_string(oidp, 278 oidp->oid_arg1, oidp->oid_arg2, req); 279 if (req->newptr && (error == 0 || error == ENOMEM)) 280 domainnamelen = req->newlen; 281 return error; 282} 283 284SYSCTL_PROC(_kern, KERN_DOMAINNAME, domainname, CTLTYPE_STRING|CTLFLAG_RW, 285 &domainname, sizeof(domainname), sysctl_kern_domainname, ""); 286 287long hostid; 288/* Some trouble here, if sizeof (int) != sizeof (long) */ 289SYSCTL_INT(_kern, KERN_HOSTID, hostid, CTLFLAG_RW, &hostid, 0, ""); 290 291/* 292 * Handle an integer, signed or unsigned. 293 * Two cases: 294 * a variable: point arg1 at it. 295 * a constant: pass it in arg2. 296 */ 297 298int 299sysctl_handle_int SYSCTL_HANDLER_ARGS 300{ 301 int error = 0; 302 303 if (arg1) 304 error = SYSCTL_OUT(req, arg1, sizeof(int)); 305 else if (arg2) 306 error = SYSCTL_OUT(req, &arg2, sizeof(int)); 307 308 if (error || !req->newptr) 309 return (error); 310 311 if (!arg1) 312 error = EPERM; 313 else 314 error = SYSCTL_IN(req, arg1, sizeof(int)); 315 return (error); 316} 317 318/* 319 * Handle our generic '\0' terminated 'C' string. 320 * Two cases: 321 * a variable string: point arg1 at it, arg2 is max length. 322 * a constant string: point arg1 at it, arg2 is zero. 323 */ 324 325int 326sysctl_handle_string SYSCTL_HANDLER_ARGS 327{ 328 int error=0; 329 330 if (arg2) 331 error = SYSCTL_OUT(req, arg1, arg2); 332 else 333 error = SYSCTL_OUT(req, arg1, strlen((char *)arg1)+1); 334 335 if (error || !req->newptr) 336 return (error); 337 338 if ((req->newlen - req->newidx) > arg2) { 339 error = E2BIG; 340 } else { 341 arg2 = (req->newlen - req->newidx); 342 error = SYSCTL_IN(req, arg1, arg2); 343 ((char *)arg1)[arg2] = '\0'; 344 } 345 346 return (error); 347} 348 349/* 350 * Handle any kind of opaque data. 351 * arg1 points to it, arg2 is the size. 352 */ 353 354int 355sysctl_handle_opaque SYSCTL_HANDLER_ARGS 356{ 357 int error; 358 359 error = SYSCTL_OUT(req, arg1, arg2); 360 361 if (error || !req->newptr) 362 return (error); 363 364 error = SYSCTL_IN(req, arg1, arg2); 365 366 return (error); 367} 368 369int 370sysctl_old_kernel(struct sysctl_req *req, void *p, int l) 371{ 372 int i = min(req->oldlen - req->oldidx, l); 373 if (i) { 374 bcopy(p, req->oldptr + req->oldidx, i); 375 req->oldidx += i; 376 } 377 if (i != l) 378 return (ENOMEM); 379 else 380 return (0); 381 382} 383 384int 385sysctl_new_kernel(struct sysctl_req *req, void *p, int l) 386{ 387 int i = req->newlen - req->newidx; 388 if (i < l) 389 return (EINVAL); 390 bcopy(req->newptr + req->newidx, p, l); 391 req->newidx += l; 392 return (0); 393} 394 395int 396sysctl_old_user(struct sysctl_req *req, void *p, int l) 397{ 398 int error , i = min(req->oldlen - req->oldidx, l); 399 400 error = copyout(p, req->oldptr + req->oldidx, i); 401 req->oldidx += i; 402 if (error) 403 return (error); 404 if (i < l) 405 return (ENOMEM); 406 return (error); 407} 408 409int 410sysctl_new_user(struct sysctl_req *req, void *p, int l) 411{ 412 int error, i = req->newlen - req->newidx; 413 if (i < l) 414 return (EINVAL); 415 error = copyin(req->newptr + req->newidx, p, l); 416 req->newidx += l; 417 return (error); 418} 419 420#ifdef DEBUG 421static sysctlfn debug_sysctl; 422#endif 423 424/* 425 * Locking and stats 426 */ 427static struct sysctl_lock { 428 int sl_lock; 429 int sl_want; 430 int sl_locked; 431} memlock; 432 433 434 435/* 436 * Traverse our tree, and find the right node, execute whatever it points 437 * at, and return the resulting error code. 438 * We work entirely in kernel-space at this time. 439 */ 440 441 442int 443sysctl_root SYSCTL_HANDLER_ARGS 444{ 445 int *name = (int *) arg1; 446 int namelen = arg2; 447 int indx, i, j; 448 struct sysctl_oid **oidpp; 449 struct linker_set *lsp = &sysctl_; 450 451 j = lsp->ls_length; 452 oidpp = (struct sysctl_oid **) lsp->ls_items; 453 454 indx = 0; 455 while (j-- && indx < CTL_MAXNAME) { 456 if (*oidpp && ((*oidpp)->oid_number == name[indx])) { 457 indx++; 458 if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 459 if ((*oidpp)->oid_handler) 460 goto found; 461 if (indx == namelen) 462 return ENOENT; 463 lsp = (struct linker_set*)(*oidpp)->oid_arg1; 464 j = lsp->ls_length; 465 oidpp = (struct sysctl_oid **)lsp->ls_items; 466 } else { 467 if (indx != namelen) 468 return EISDIR; 469 goto found; 470 } 471 } else { 472 oidpp++; 473 } 474 } 475 return EJUSTRETURN; 476found: 477 478 /* If writing isn't allowed */ 479 if (req->newptr && !((*oidpp)->oid_kind & CTLFLAG_WR)) 480 return (EPERM); 481 482 if (!(*oidpp)->oid_handler) 483 return EINVAL; 484 485 if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 486 i = ((*oidpp)->oid_handler) (*oidpp, 487 name + indx, namelen - indx, 488 req); 489 } else { 490 i = ((*oidpp)->oid_handler) (*oidpp, 491 (*oidpp)->oid_arg1, (*oidpp)->oid_arg2, 492 req); 493 } 494 return (i); 495} 496 497#ifndef _SYS_SYSPROTO_H_ 498struct sysctl_args { 499 int *name; 500 u_int namelen; 501 void *old; 502 size_t *oldlenp; 503 void *new; 504 size_t newlen; 505}; 506#endif 507 508int 509__sysctl(p, uap, retval) 510 struct proc *p; 511 register struct sysctl_args *uap; 512 int *retval; 513{ 514 int error, name[CTL_MAXNAME]; 515 516 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 517 return (EINVAL); 518 519 error = copyin(uap->name, &name, uap->namelen * sizeof(int)); 520 if (error) 521 return (error); 522 523 return (userland_sysctl(p, name, uap->namelen, 524 uap->old, uap->oldlenp, 0, 525 uap->new, uap->newlen, retval)); 526} 527 528static sysctlfn kern_sysctl; 529 530/* 531 * This is used from various compatibility syscalls too. That's why name 532 * must be in kernel space. 533 */ 534int 535userland_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen, int *retval) 536{ 537 int error = 0, dolock = 1, i, oldlen = 0; 538 u_int savelen = 0; 539 sysctlfn *fn; 540 struct sysctl_req req; 541 542 bzero(&req, sizeof req); 543 544 if (new != NULL && (error = suser(p->p_ucred, &p->p_acflag))) 545 return (error); 546 547 if (oldlenp) { 548 if (inkernel) { 549 req.oldlen = *oldlenp; 550 } else { 551 error = copyin(oldlenp, &req.oldlen, 552 sizeof(req.oldlen)); 553 if (error) 554 return (error); 555 } 556 oldlen = req.oldlen; 557 } 558 559 if (old) { 560 if (!useracc(old, req.oldlen, B_WRITE)) 561 return (EFAULT); 562 req.oldptr= old; 563 } 564 565 if (newlen) { 566 if (!useracc(new, req.newlen, B_READ)) 567 return (EFAULT); 568 req.newlen = newlen; 569 req.newptr = new; 570 } 571 572 req.oldfunc = sysctl_old_user; 573 req.newfunc = sysctl_new_user; 574 575 error = sysctl_root(0, name, namelen, &req); 576 577 if (!error || error == ENOMEM) { 578 if (retval) 579 *retval = req.oldlen; 580 if (oldlenp) { 581 if (inkernel) { 582 *oldlenp = req.oldlen; 583 } else { 584 i = copyout(&req.oldlen, oldlenp, 585 sizeof(req.oldlen)); 586 if (i) 587 error = i; 588 } 589 } 590 return (error); 591 } 592 593 switch (name[0]) { 594 case CTL_KERN: 595 fn = kern_sysctl; 596 if (name[1] != KERN_VNODE) /* XXX */ 597 dolock = 0; 598 break; 599 case CTL_HW: 600 fn = hw_sysctl; 601 break; 602 case CTL_VM: 603 fn = vm_sysctl; 604 break; 605 case CTL_NET: 606 fn = net_sysctl; 607 break; 608 case CTL_FS: 609 fn = fs_sysctl; 610 break; 611#ifdef DEBUG 612 case CTL_DEBUG: 613 fn = debug_sysctl; 614 break; 615#endif 616 default: 617 return (EOPNOTSUPP); 618 } 619 if (old != NULL) { 620 if (!useracc(old, oldlen, B_WRITE)) 621 return (EFAULT); 622 while (memlock.sl_lock) { 623 memlock.sl_want = 1; 624 (void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0); 625 memlock.sl_locked++; 626 } 627 memlock.sl_lock = 1; 628 if (dolock) 629 vslock(old, oldlen); 630 savelen = oldlen; 631 } 632 633 634 error = (*fn)(name + 1, namelen - 1, old, &oldlen, 635 new, newlen, p); 636 637 638 if (old != NULL) { 639 if (dolock) 640 vsunlock(old, savelen, B_WRITE); 641 memlock.sl_lock = 0; 642 if (memlock.sl_want) { 643 memlock.sl_want = 0; 644 wakeup((caddr_t)&memlock); 645 } 646 } 647#if 0 648 if (error) { 649 printf("SYSCTL_ERROR: "); 650 for(i=0;i<namelen;i++) 651 printf("%d ", name[i]); 652 printf("= %d\n", error); 653 } 654#endif 655 if (error) 656 return (error); 657 if (retval) 658 *retval = oldlen; 659 if (oldlenp) { 660 if (inkernel) { 661 *oldlenp = oldlen; 662 } else { 663 error = copyout(&oldlen, oldlenp, sizeof(oldlen)); 664 } 665 } 666 return (error); 667} 668 669/* 670 * Attributes stored in the kernel. 671 */ 672int securelevel = -1; 673 674/* 675 * kernel related system variables. 676 */ 677static int 678kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 679 int *name; 680 u_int namelen; 681 void *oldp; 682 size_t *oldlenp; 683 void *newp; 684 size_t newlen; 685 struct proc *p; 686{ 687 int error, level; 688 dev_t ndumpdev; 689 690 /* all sysctl names at this level are terminal */ 691 if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF 692 || name[0] == KERN_NTP_PLL)) 693 return (ENOTDIR); /* overloaded */ 694 695 switch (name[0]) { 696 697 case KERN_SECURELVL: 698 level = securelevel; 699 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || 700 newp == NULL) 701 return (error); 702 if (level < securelevel && p->p_pid != 1) 703 return (EPERM); 704 securelevel = level; 705 return (0); 706 case KERN_VNODE: 707 return (sysctl_vnode(oldp, oldlenp)); 708 case KERN_PROC: 709 return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); 710 case KERN_FILE: 711 return (sysctl_file(oldp, oldlenp)); 712#ifdef GPROF 713 case KERN_PROF: 714 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, 715 newp, newlen)); 716#endif 717 case KERN_NTP_PLL: 718 return (ntp_sysctl(name + 1, namelen - 1, oldp, oldlenp, 719 newp, newlen, p)); 720 case KERN_DUMPDEV: 721 ndumpdev = dumpdev; 722 error = sysctl_struct(oldp, oldlenp, newp, newlen, &ndumpdev, 723 sizeof ndumpdev); 724 if (!error && ndumpdev != dumpdev) { 725 error = setdumpdev(ndumpdev); 726 } 727 return error; 728 default: 729 return (EOPNOTSUPP); 730 } 731 /* NOTREACHED */ 732} 733 734/* 735 * hardware related system variables. 736 */ 737int 738hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 739 int *name; 740 u_int namelen; 741 void *oldp; 742 size_t *oldlenp; 743 void *newp; 744 size_t newlen; 745 struct proc *p; 746{ 747 /* almost all sysctl names at this level are terminal */ 748 if (namelen != 1 && name[0] != HW_DEVCONF) 749 return (ENOTDIR); /* overloaded */ 750 751 switch (name[0]) { 752 case HW_PHYSMEM: 753 return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); 754 case HW_USERMEM: 755 return (sysctl_rdint(oldp, oldlenp, newp, 756 ctob(physmem - cnt.v_wire_count))); 757 case HW_DEVCONF: 758 return (dev_sysctl(name + 1, namelen - 1, oldp, oldlenp, 759 newp, newlen, p)); 760 default: 761 return (EOPNOTSUPP); 762 } 763 /* NOTREACHED */ 764} 765 766#ifdef DEBUG 767/* 768 * Debugging related system variables. 769 */ 770struct ctldebug debug0, debug1, debug2, debug3, debug4; 771struct ctldebug debug5, debug6, debug7, debug8, debug9; 772struct ctldebug debug10, debug11, debug12, debug13, debug14; 773struct ctldebug debug15, debug16, debug17, debug18, debug19; 774static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 775 &debug0, &debug1, &debug2, &debug3, &debug4, 776 &debug5, &debug6, &debug7, &debug8, &debug9, 777 &debug10, &debug11, &debug12, &debug13, &debug14, 778 &debug15, &debug16, &debug17, &debug18, &debug19, 779}; 780static int 781debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 782 int *name; 783 u_int namelen; 784 void *oldp; 785 size_t *oldlenp; 786 void *newp; 787 size_t newlen; 788 struct proc *p; 789{ 790 struct ctldebug *cdp; 791 792 /* all sysctl names at this level are name and field */ 793 if (namelen != 2) 794 return (ENOTDIR); /* overloaded */ 795 cdp = debugvars[name[0]]; 796 if (cdp->debugname == 0) 797 return (EOPNOTSUPP); 798 switch (name[1]) { 799 case CTL_DEBUG_NAME: 800 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 801 case CTL_DEBUG_VALUE: 802 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 803 default: 804 return (EOPNOTSUPP); 805 } 806 /* NOTREACHED */ 807} 808#endif /* DEBUG */ 809 810/* 811 * Validate parameters and get old / set new parameters 812 * for an integer-valued sysctl function. 813 */ 814int 815sysctl_int(oldp, oldlenp, newp, newlen, valp) 816 void *oldp; 817 size_t *oldlenp; 818 void *newp; 819 size_t newlen; 820 int *valp; 821{ 822 int error = 0; 823 824 if (oldp && *oldlenp < sizeof(int)) 825 return (ENOMEM); 826 if (newp && newlen != sizeof(int)) 827 return (EINVAL); 828 *oldlenp = sizeof(int); 829 if (oldp) 830 error = copyout(valp, oldp, sizeof(int)); 831 if (error == 0 && newp) 832 error = copyin(newp, valp, sizeof(int)); 833 return (error); 834} 835 836/* 837 * As above, but read-only. 838 */ 839int 840sysctl_rdint(oldp, oldlenp, newp, val) 841 void *oldp; 842 size_t *oldlenp; 843 void *newp; 844 int val; 845{ 846 int error = 0; 847 848 if (oldp && *oldlenp < sizeof(int)) 849 return (ENOMEM); 850 if (newp) 851 return (EPERM); 852 *oldlenp = sizeof(int); 853 if (oldp) 854 error = copyout((caddr_t)&val, oldp, sizeof(int)); 855 return (error); 856} 857 858/* 859 * Validate parameters and get old / set new parameters 860 * for a string-valued sysctl function. 861 */ 862int 863sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen) 864 void *oldp; 865 size_t *oldlenp; 866 void *newp; 867 size_t newlen; 868 char *str; 869 int maxlen; 870{ 871 int len, error = 0, rval = 0; 872 873 len = strlen(str) + 1; 874 if (oldp && *oldlenp < len) { 875 len = *oldlenp; 876 rval = ENOMEM; 877 } 878 if (newp && newlen >= maxlen) 879 return (EINVAL); 880 if (oldp) { 881 *oldlenp = len; 882 error = copyout(str, oldp, len); 883 if (error) 884 rval = error; 885 } 886 if ((error == 0 || error == ENOMEM) && newp) { 887 error = copyin(newp, str, newlen); 888 if (error) 889 rval = error; 890 str[newlen] = 0; 891 } 892 return (rval); 893} 894 895/* 896 * As above, but read-only. 897 */ 898int 899sysctl_rdstring(oldp, oldlenp, newp, str) 900 void *oldp; 901 size_t *oldlenp; 902 void *newp; 903 char *str; 904{ 905 int len, error = 0, rval = 0; 906 907 len = strlen(str) + 1; 908 if (oldp && *oldlenp < len) { 909 len = *oldlenp; 910 rval = ENOMEM; 911 } 912 if (newp) 913 return (EPERM); 914 *oldlenp = len; 915 if (oldp) 916 error = copyout(str, oldp, len); 917 if (error) 918 rval = error; 919 return (rval); 920} 921 922/* 923 * Validate parameters and get old / set new parameters 924 * for a structure oriented sysctl function. 925 */ 926int 927sysctl_struct(oldp, oldlenp, newp, newlen, sp, len) 928 void *oldp; 929 size_t *oldlenp; 930 void *newp; 931 size_t newlen; 932 void *sp; 933 int len; 934{ 935 int error = 0; 936 937 if (oldp && *oldlenp < len) 938 return (ENOMEM); 939 if (newp && newlen > len) 940 return (EINVAL); 941 if (oldp) { 942 *oldlenp = len; 943 error = copyout(sp, oldp, len); 944 } 945 if (error == 0 && newp) 946 error = copyin(newp, sp, len); 947 return (error); 948} 949 950/* 951 * Validate parameters and get old parameters 952 * for a structure oriented sysctl function. 953 */ 954int 955sysctl_rdstruct(oldp, oldlenp, newp, sp, len) 956 void *oldp; 957 size_t *oldlenp; 958 void *newp, *sp; 959 int len; 960{ 961 int error = 0; 962 963 if (oldp && *oldlenp < len) 964 return (ENOMEM); 965 if (newp) 966 return (EPERM); 967 *oldlenp = len; 968 if (oldp) 969 error = copyout(sp, oldp, len); 970 return (error); 971} 972 973/* 974 * Get file structures. 975 */ 976int 977sysctl_file(where, sizep) 978 char *where; 979 size_t *sizep; 980{ 981 int buflen, error; 982 struct file *fp; 983 char *start = where; 984 985 buflen = *sizep; 986 if (where == NULL) { 987 /* 988 * overestimate by 10 files 989 */ 990 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 991 return (0); 992 } 993 994 /* 995 * first copyout filehead 996 */ 997 if (buflen < sizeof(filehead)) { 998 *sizep = 0; 999 return (0); 1000 } 1001 error = copyout((caddr_t)&filehead, where, sizeof(filehead)); 1002 if (error) 1003 return (error); 1004 buflen -= sizeof(filehead); 1005 where += sizeof(filehead); 1006 1007 /* 1008 * followed by an array of file structures 1009 */ 1010 for (fp = filehead; fp != NULL; fp = fp->f_filef) { 1011 if (buflen < sizeof(struct file)) { 1012 *sizep = where - start; 1013 return (ENOMEM); 1014 } 1015 error = copyout((caddr_t)fp, where, sizeof (struct file)); 1016 if (error) 1017 return (error); 1018 buflen -= sizeof(struct file); 1019 where += sizeof(struct file); 1020 } 1021 *sizep = where - start; 1022 return (0); 1023} 1024 1025/* 1026 * try over estimating by 5 procs 1027 */ 1028#define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc)) 1029 1030int 1031sysctl_doproc(name, namelen, where, sizep) 1032 int *name; 1033 u_int namelen; 1034 char *where; 1035 size_t *sizep; 1036{ 1037 register struct proc *p; 1038 register struct kinfo_proc *dp = (struct kinfo_proc *)where; 1039 register int needed = 0; 1040 int buflen = where != NULL ? *sizep : 0; 1041 int doingzomb; 1042 struct eproc eproc; 1043 int error = 0; 1044 1045 if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL)) 1046 return (EINVAL); 1047 p = (struct proc *)allproc; 1048 doingzomb = 0; 1049again: 1050 for (; p != NULL; p = p->p_next) { 1051 /* 1052 * Skip embryonic processes. 1053 */ 1054 if (p->p_stat == SIDL) 1055 continue; 1056 /* 1057 * TODO - make more efficient (see notes below). 1058 * do by session. 1059 */ 1060 switch (name[0]) { 1061 1062 case KERN_PROC_PID: 1063 /* could do this with just a lookup */ 1064 if (p->p_pid != (pid_t)name[1]) 1065 continue; 1066 break; 1067 1068 case KERN_PROC_PGRP: 1069 /* could do this by traversing pgrp */ 1070 if (p->p_pgrp == NULL || p->p_pgrp->pg_id != (pid_t)name[1]) 1071 continue; 1072 break; 1073 1074 case KERN_PROC_TTY: 1075 if ((p->p_flag & P_CONTROLT) == 0 || 1076 p->p_session == NULL || 1077 p->p_session->s_ttyp == NULL || 1078 p->p_session->s_ttyp->t_dev != (dev_t)name[1]) 1079 continue; 1080 break; 1081 1082 case KERN_PROC_UID: 1083 if (p->p_ucred == NULL || p->p_ucred->cr_uid != (uid_t)name[1]) 1084 continue; 1085 break; 1086 1087 case KERN_PROC_RUID: 1088 if (p->p_ucred == NULL || p->p_cred->p_ruid != (uid_t)name[1]) 1089 continue; 1090 break; 1091 } 1092 if (buflen >= sizeof(struct kinfo_proc)) { 1093 fill_eproc(p, &eproc); 1094 error = copyout((caddr_t)p, &dp->kp_proc, 1095 sizeof(struct proc)); 1096 if (error) 1097 return (error); 1098 error = copyout((caddr_t)&eproc, &dp->kp_eproc, 1099 sizeof(eproc)); 1100 if (error) 1101 return (error); 1102 dp++; 1103 buflen -= sizeof(struct kinfo_proc); 1104 } 1105 needed += sizeof(struct kinfo_proc); 1106 } 1107 if (doingzomb == 0) { 1108 p = zombproc; 1109 doingzomb++; 1110 goto again; 1111 } 1112 if (where != NULL) { 1113 *sizep = (caddr_t)dp - where; 1114 if (needed > *sizep) 1115 return (ENOMEM); 1116 } else { 1117 needed += KERN_PROCSLOP; 1118 *sizep = needed; 1119 } 1120 return (0); 1121} 1122 1123/* 1124 * Fill in an eproc structure for the specified process. 1125 */ 1126void 1127fill_eproc(p, ep) 1128 register struct proc *p; 1129 register struct eproc *ep; 1130{ 1131 register struct tty *tp; 1132 1133 bzero(ep, sizeof(*ep)); 1134 1135 ep->e_paddr = p; 1136 if (p->p_cred) { 1137 ep->e_pcred = *p->p_cred; 1138 if (p->p_ucred) 1139 ep->e_ucred = *p->p_ucred; 1140 } 1141 if (p->p_stat != SIDL && p->p_stat != SZOMB && p->p_vmspace != NULL) { 1142 register struct vmspace *vm = p->p_vmspace; 1143 1144#ifdef pmap_resident_count 1145 ep->e_vm.vm_rssize = pmap_resident_count(&vm->vm_pmap); /*XXX*/ 1146#else 1147 ep->e_vm.vm_rssize = vm->vm_rssize; 1148#endif 1149 ep->e_vm.vm_tsize = vm->vm_tsize; 1150 ep->e_vm.vm_dsize = vm->vm_dsize; 1151 ep->e_vm.vm_ssize = vm->vm_ssize; 1152#ifndef sparc 1153 ep->e_vm.vm_pmap = vm->vm_pmap; 1154#endif 1155 } 1156 if (p->p_pptr) 1157 ep->e_ppid = p->p_pptr->p_pid; 1158 if (p->p_pgrp) { 1159 ep->e_sess = p->p_pgrp->pg_session; 1160 ep->e_pgid = p->p_pgrp->pg_id; 1161 ep->e_jobc = p->p_pgrp->pg_jobc; 1162 } 1163 if ((p->p_flag & P_CONTROLT) && 1164 (ep->e_sess != NULL) && 1165 ((tp = ep->e_sess->s_ttyp) != NULL)) { 1166 ep->e_tdev = tp->t_dev; 1167 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 1168 ep->e_tsess = tp->t_session; 1169 } else 1170 ep->e_tdev = NODEV; 1171 if (ep->e_sess && ep->e_sess->s_ttyvp) 1172 ep->e_flag = EPROC_CTTY; 1173 if (SESS_LEADER(p)) 1174 ep->e_flag |= EPROC_SLEADER; 1175 if (p->p_wmesg) { 1176 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN); 1177 ep->e_wmesg[WMESGLEN] = 0; 1178 } 1179} 1180 1181#ifdef COMPAT_43 1182#include <sys/socket.h> 1183#define KINFO_PROC (0<<8) 1184#define KINFO_RT (1<<8) 1185#define KINFO_VNODE (2<<8) 1186#define KINFO_FILE (3<<8) 1187#define KINFO_METER (4<<8) 1188#define KINFO_LOADAVG (5<<8) 1189#define KINFO_CLOCKRATE (6<<8) 1190 1191/* Non-standard BSDI extension - only present on their 4.3 net-2 releases */ 1192#define KINFO_BSDI_SYSINFO (101<<8) 1193 1194/* 1195 * XXX this is bloat, but I hope it's better here than on the potentially 1196 * limited kernel stack... -Peter 1197 */ 1198 1199struct { 1200 int bsdi_machine; /* "i386" on BSD/386 */ 1201/* ^^^ this is an offset to the string, relative to the struct start */ 1202 char *pad0; 1203 long pad1; 1204 long pad2; 1205 long pad3; 1206 u_long pad4; 1207 u_long pad5; 1208 u_long pad6; 1209 1210 int bsdi_ostype; /* "BSD/386" on BSD/386 */ 1211 int bsdi_osrelease; /* "1.1" on BSD/386 */ 1212 long pad7; 1213 long pad8; 1214 char *pad9; 1215 1216 long pad10; 1217 long pad11; 1218 int pad12; 1219 long pad13; 1220 quad_t pad14; 1221 long pad15; 1222 1223 struct timeval pad16; 1224 /* we dont set this, because BSDI's uname used gethostname() instead */ 1225 int bsdi_hostname; /* hostname on BSD/386 */ 1226 1227 /* the actual string data is appended here */ 1228 1229} bsdi_si; 1230/* 1231 * this data is appended to the end of the bsdi_si structure during copyout. 1232 * The "char *" offsets are relative to the base of the bsdi_si struct. 1233 * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings 1234 * should not exceed the length of the buffer here... (or else!! :-) 1235 */ 1236char bsdi_strings[80]; /* It had better be less than this! */ 1237 1238#ifndef _SYS_SYSPROTO_H_ 1239struct getkerninfo_args { 1240 int op; 1241 char *where; 1242 int *size; 1243 int arg; 1244}; 1245#endif 1246 1247int 1248ogetkerninfo(p, uap, retval) 1249 struct proc *p; 1250 register struct getkerninfo_args *uap; 1251 int *retval; 1252{ 1253 int error, name[6]; 1254 u_int size; 1255 1256 switch (uap->op & 0xff00) { 1257 1258 case KINFO_RT: 1259 name[0] = CTL_NET; 1260 name[1] = PF_ROUTE; 1261 name[2] = 0; 1262 name[3] = (uap->op & 0xff0000) >> 16; 1263 name[4] = uap->op & 0xff; 1264 name[5] = uap->arg; 1265 error = userland_sysctl(p, name, 6, uap->where, uap->size, 1266 0, 0, 0, 0); 1267 break; 1268 1269 case KINFO_VNODE: 1270 name[0] = CTL_KERN; 1271 name[1] = KERN_VNODE; 1272 error = userland_sysctl(p, name, 2, uap->where, uap->size, 1273 0, 0, 0, 0); 1274 break; 1275 1276 case KINFO_PROC: 1277 name[0] = CTL_KERN; 1278 name[1] = KERN_PROC; 1279 name[2] = uap->op & 0xff; 1280 name[3] = uap->arg; 1281 error = userland_sysctl(p, name, 4, uap->where, uap->size, 1282 0, 0, 0, 0); 1283 break; 1284 1285 case KINFO_FILE: 1286 name[0] = CTL_KERN; 1287 name[1] = KERN_FILE; 1288 error = userland_sysctl(p, name, 2, uap->where, uap->size, 1289 0, 0, 0, 0); 1290 break; 1291 1292 case KINFO_METER: 1293 name[0] = CTL_VM; 1294 name[1] = VM_METER; 1295 error = userland_sysctl(p, name, 2, uap->where, uap->size, 1296 0, 0, 0, 0); 1297 break; 1298 1299 case KINFO_LOADAVG: 1300 name[0] = CTL_VM; 1301 name[1] = VM_LOADAVG; 1302 error = userland_sysctl(p, name, 2, uap->where, uap->size, 1303 0, 0, 0, 0); 1304 break; 1305 1306 case KINFO_CLOCKRATE: 1307 name[0] = CTL_KERN; 1308 name[1] = KERN_CLOCKRATE; 1309 error = userland_sysctl(p, name, 2, uap->where, uap->size, 1310 0, 0, 0, 0); 1311 break; 1312 1313 case KINFO_BSDI_SYSINFO: { 1314 /* 1315 * this is pretty crude, but it's just enough for uname() 1316 * from BSDI's 1.x libc to work. 1317 * 1318 * In particular, it doesn't return the same results when 1319 * the supplied buffer is too small. BSDI's version apparently 1320 * will return the amount copied, and set the *size to how 1321 * much was needed. The emulation framework here isn't capable 1322 * of that, so we just set both to the amount copied. 1323 * BSDI's 2.x product apparently fails with ENOMEM in this 1324 * scenario. 1325 */ 1326 1327 u_int needed; 1328 u_int left; 1329 char *s; 1330 1331 bzero((char *)&bsdi_si, sizeof(bsdi_si)); 1332 bzero(bsdi_strings, sizeof(bsdi_strings)); 1333 1334 s = bsdi_strings; 1335 1336 bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si); 1337 strcpy(s, ostype); 1338 s += strlen(s) + 1; 1339 1340 bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si); 1341 strcpy(s, osrelease); 1342 s += strlen(s) + 1; 1343 1344 bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si); 1345 strcpy(s, machine); 1346 s += strlen(s) + 1; 1347 1348 needed = sizeof(bsdi_si) + (s - bsdi_strings); 1349 1350 if (uap->where == NULL) { 1351 /* process is asking how much buffer to supply.. */ 1352 size = needed; 1353 error = 0; 1354 break; 1355 } 1356 1357 1358 /* if too much buffer supplied, trim it down */ 1359 if (size > needed) 1360 size = needed; 1361 1362 /* how much of the buffer is remaining */ 1363 left = size; 1364 1365 if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0) 1366 break; 1367 1368 /* is there any point in continuing? */ 1369 if (left > sizeof(bsdi_si)) { 1370 left -= sizeof(bsdi_si); 1371 error = copyout(&bsdi_strings, 1372 uap->where + sizeof(bsdi_si), left); 1373 } 1374 break; 1375 } 1376 1377 default: 1378 return (EOPNOTSUPP); 1379 } 1380 if (error) 1381 return (error); 1382 *retval = size; 1383 if (uap->size) 1384 error = copyout((caddr_t)&size, (caddr_t)uap->size, 1385 sizeof(size)); 1386 return (error); 1387} 1388#endif /* COMPAT_43 */ 1389