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