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.51 1995/11/16 18:59:49 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/vnode.h> 49 #include <sys/unistd.h> 50 #include <sys/conf.h> 51 #include <sys/sysctl.h> 52 53 /* 54 * Locking and stats 55 */ 56 static struct sysctl_lock { 57 int sl_lock; 58 int sl_want; 59 int sl_locked; 60 } memlock; 61 62 static int sysctl_root SYSCTL_HANDLER_ARGS; 63 64 extern struct linker_set sysctl_; 65 66 /* BEGIN_MIB */ 67 SYSCTL_NODE(, 0, sysctl, CTLFLAG_RW, 0, 68 "Sysctl internal magic"); 69 SYSCTL_NODE(, CTL_KERN, kern, CTLFLAG_RW, 0, 70 "High kernel, proc, limits &c"); 71 SYSCTL_NODE(, CTL_VM, vm, CTLFLAG_RW, 0, 72 "Virtual memory"); 73 SYSCTL_NODE(, CTL_FS, fs, CTLFLAG_RW, 0, 74 "File system"); 75 SYSCTL_NODE(, CTL_NET, net, CTLFLAG_RW, 0, 76 "Network, (see socket.h)"); 77 SYSCTL_NODE(, CTL_DEBUG, debug, CTLFLAG_RW, 0, 78 "Debugging"); 79 SYSCTL_NODE(, CTL_HW, hw, CTLFLAG_RW, 0, 80 "hardware"); 81 SYSCTL_NODE(, CTL_MACHDEP, machdep, CTLFLAG_RW, 0, 82 "machine dependent"); 83 SYSCTL_NODE(, CTL_USER, user, CTLFLAG_RW, 0, 84 "user-level"); 85 86 SYSCTL_STRING(_kern, KERN_OSRELEASE, osrelease, CTLFLAG_RD, osrelease, 0, ""); 87 88 SYSCTL_INT(_kern, KERN_OSREV, osrevision, CTLFLAG_RD, 0, BSD, ""); 89 90 SYSCTL_STRING(_kern, KERN_VERSION, version, CTLFLAG_RD, version, 0, ""); 91 92 SYSCTL_STRING(_kern, KERN_OSTYPE, ostype, CTLFLAG_RD, ostype, 0, ""); 93 94 extern int osreldate; 95 SYSCTL_INT(_kern, KERN_OSRELDATE, osreldate, CTLFLAG_RD, &osreldate, 0, ""); 96 97 SYSCTL_INT(_kern, KERN_MAXVNODES, maxvnodes, CTLFLAG_RD, &desiredvnodes, 0, ""); 98 99 SYSCTL_INT(_kern, KERN_MAXPROC, maxproc, CTLFLAG_RD, &maxproc, 0, ""); 100 101 SYSCTL_INT(_kern, KERN_MAXPROCPERUID, maxprocperuid, 102 CTLFLAG_RD, &maxprocperuid, 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 #ifdef _POSIX_SAVED_IDS 113 SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD, 0, 1, ""); 114 #else 115 SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD, 0, 0, ""); 116 #endif 117 118 char kernelname[MAXPATHLEN] = "/kernel"; /* XXX bloat */ 119 120 SYSCTL_STRING(_kern, KERN_BOOTFILE, bootfile, 121 CTLFLAG_RW, kernelname, sizeof kernelname, ""); 122 123 SYSCTL_STRUCT(_kern, KERN_BOOTTIME, boottime, 124 CTLFLAG_RW, &boottime, timeval, ""); 125 126 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); 127 128 SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, ""); 129 130 SYSCTL_INT(_hw, HW_NCPU, ncpu, CTLFLAG_RD, 0, 1, ""); 131 132 SYSCTL_INT(_hw, HW_BYTEORDER, byteorder, CTLFLAG_RD, 0, BYTE_ORDER, ""); 133 134 SYSCTL_INT(_hw, HW_PAGESIZE, pagesize, CTLFLAG_RD, 0, PAGE_SIZE, ""); 135 136 /* END_MIB */ 137 138 extern int vfs_update_wakeup; 139 extern int vfs_update_interval; 140 static int 141 sysctl_kern_updateinterval SYSCTL_HANDLER_ARGS 142 { 143 int error = sysctl_handle_int(oidp, 144 oidp->oid_arg1, oidp->oid_arg2, req); 145 if (!error) 146 wakeup(&vfs_update_wakeup); 147 return error; 148 } 149 150 SYSCTL_PROC(_kern, KERN_UPDATEINTERVAL, update, CTLTYPE_INT|CTLFLAG_RW, 151 &vfs_update_interval, 0, sysctl_kern_updateinterval, ""); 152 153 154 char hostname[MAXHOSTNAMELEN]; 155 156 SYSCTL_STRING(_kern, KERN_HOSTNAME, hostname, CTLFLAG_RW, 157 hostname, sizeof(hostname), ""); 158 159 int securelevel = -1; 160 161 static int 162 sysctl_kern_securelvl SYSCTL_HANDLER_ARGS 163 { 164 int error, level; 165 166 level = securelevel; 167 error = sysctl_handle_int(oidp, &level, 0, req); 168 if (error || !req->newptr) 169 return (error); 170 if (level < securelevel && req->p->p_pid != 1) 171 return (EPERM); 172 securelevel = level; 173 return (error); 174 } 175 176 SYSCTL_PROC(_kern, KERN_SECURELVL, securelevel, CTLTYPE_INT|CTLFLAG_RW, 177 0, 0, sysctl_kern_securelvl, ""); 178 179 static int 180 sysctl_kern_dumpdev SYSCTL_HANDLER_ARGS 181 { 182 int error; 183 dev_t ndumpdev; 184 185 ndumpdev = dumpdev; 186 error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req); 187 if (!error && ndumpdev != dumpdev) { 188 error = setdumpdev(ndumpdev); 189 } 190 return (error); 191 } 192 193 SYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW, 194 0, sizeof dumpdev, sysctl_kern_dumpdev, ""); 195 196 static int 197 sysctl_hw_physmem SYSCTL_HANDLER_ARGS 198 { 199 int error = sysctl_handle_int(oidp, 0, ctob(physmem), req); 200 return (error); 201 } 202 203 SYSCTL_PROC(_hw, HW_PHYSMEM, physmem, CTLTYPE_INT|CTLFLAG_RD, 204 0, 0, sysctl_hw_physmem, ""); 205 206 static int 207 sysctl_hw_usermem SYSCTL_HANDLER_ARGS 208 { 209 int error = sysctl_handle_int(oidp, 0, 210 ctob(physmem - cnt.v_wire_count), req); 211 return (error); 212 } 213 214 SYSCTL_PROC(_hw, HW_USERMEM, usermem, CTLTYPE_INT|CTLFLAG_RD, 215 0, 0, sysctl_hw_usermem, ""); 216 217 /* END_MIB */ 218 219 static int 220 sysctl_order_cmp(const void *a, const void *b) 221 { 222 const struct sysctl_oid **pa, **pb; 223 224 pa = (const struct sysctl_oid **)a; 225 pb = (const struct sysctl_oid **)b; 226 if (*pa == NULL) 227 return (1); 228 if (*pb == NULL) 229 return (-1); 230 return ((*pa)->oid_number - (*pb)->oid_number); 231 } 232 233 static void 234 sysctl_order(void *arg) 235 { 236 int j; 237 struct linker_set *l = (struct linker_set *) arg; 238 struct sysctl_oid **oidpp; 239 240 j = l->ls_length; 241 oidpp = (struct sysctl_oid **) l->ls_items; 242 for (; j--; oidpp++) { 243 if (!*oidpp) 244 continue; 245 if ((*oidpp)->oid_arg1 == arg) { 246 *oidpp = 0; 247 continue; 248 } 249 if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) 250 if (!(*oidpp)->oid_handler) 251 sysctl_order((*oidpp)->oid_arg1); 252 } 253 qsort(l->ls_items, l->ls_length, sizeof l->ls_items[0], 254 sysctl_order_cmp); 255 } 256 257 SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_order, &sysctl_); 258 259 static void 260 sysctl_sysctl_debug_dump_node(struct linker_set *l, int i) 261 { 262 int j, k; 263 struct sysctl_oid **oidpp; 264 265 j = l->ls_length; 266 oidpp = (struct sysctl_oid **) l->ls_items; 267 for (; j--; oidpp++) { 268 269 if (!*oidpp) 270 continue; 271 272 for (k=0; k<i; k++) 273 printf(" "); 274 275 if ((*oidpp)->oid_number > 100) { 276 printf("Junk! %p # %d %s k %x a1 %p a2 %x h %p\n", 277 *oidpp, 278 (*oidpp)->oid_number, (*oidpp)->oid_name, 279 (*oidpp)->oid_kind, (*oidpp)->oid_arg1, 280 (*oidpp)->oid_arg2, (*oidpp)->oid_handler); 281 continue; 282 } 283 printf("%d %s ", (*oidpp)->oid_number, (*oidpp)->oid_name); 284 285 printf("%c%c", 286 (*oidpp)->oid_kind & CTLFLAG_RD ? 'R':' ', 287 (*oidpp)->oid_kind & CTLFLAG_WR ? 'W':' '); 288 289 switch ((*oidpp)->oid_kind & CTLTYPE) { 290 case CTLTYPE_NODE: 291 if ((*oidpp)->oid_handler) { 292 printf(" Node(proc)\n"); 293 } else { 294 printf(" Node\n"); 295 sysctl_sysctl_debug_dump_node( 296 (*oidpp)->oid_arg1, i+2); 297 } 298 break; 299 case CTLTYPE_INT: printf(" Int\n"); break; 300 case CTLTYPE_STRING: printf(" String\n"); break; 301 case CTLTYPE_QUAD: printf(" Quad\n"); break; 302 case CTLTYPE_OPAQUE: printf(" Opaque/struct\n"); break; 303 default: printf("\n"); 304 } 305 306 } 307 } 308 309 310 static int 311 sysctl_sysctl_debug SYSCTL_HANDLER_ARGS 312 { 313 sysctl_sysctl_debug_dump_node(&sysctl_, 0); 314 return ENOENT; 315 } 316 317 SYSCTL_PROC(_sysctl, 0, debug, CTLTYPE_STRING|CTLFLAG_RD, 318 0, 0, sysctl_sysctl_debug, ""); 319 320 char domainname[MAXHOSTNAMELEN]; 321 SYSCTL_STRING(_kern, KERN_DOMAINNAME, domainname, CTLFLAG_RW, 322 &domainname, sizeof(domainname), ""); 323 324 long hostid; 325 /* Some trouble here, if sizeof (int) != sizeof (long) */ 326 SYSCTL_INT(_kern, KERN_HOSTID, hostid, CTLFLAG_RW, &hostid, 0, ""); 327 328 /* 329 * Handle an integer, signed or unsigned. 330 * Two cases: 331 * a variable: point arg1 at it. 332 * a constant: pass it in arg2. 333 */ 334 335 int 336 sysctl_handle_int SYSCTL_HANDLER_ARGS 337 { 338 int error = 0; 339 340 if (arg1) 341 error = SYSCTL_OUT(req, arg1, sizeof(int)); 342 else if (arg2) 343 error = SYSCTL_OUT(req, &arg2, sizeof(int)); 344 345 if (error || !req->newptr) 346 return (error); 347 348 if (!arg1) 349 error = EPERM; 350 else 351 error = SYSCTL_IN(req, arg1, sizeof(int)); 352 return (error); 353 } 354 355 /* 356 * Handle our generic '\0' terminated 'C' string. 357 * Two cases: 358 * a variable string: point arg1 at it, arg2 is max length. 359 * a constant string: point arg1 at it, arg2 is zero. 360 */ 361 362 int 363 sysctl_handle_string SYSCTL_HANDLER_ARGS 364 { 365 int error=0; 366 367 error = SYSCTL_OUT(req, arg1, strlen((char *)arg1)+1); 368 369 if (error || !req->newptr || !arg2) 370 return (error); 371 372 if ((req->newlen - req->newidx) > arg2) { 373 error = E2BIG; 374 } else { 375 arg2 = (req->newlen - req->newidx); 376 error = SYSCTL_IN(req, arg1, arg2); 377 ((char *)arg1)[arg2] = '\0'; 378 } 379 380 return (error); 381 } 382 383 /* 384 * Handle any kind of opaque data. 385 * arg1 points to it, arg2 is the size. 386 */ 387 388 int 389 sysctl_handle_opaque SYSCTL_HANDLER_ARGS 390 { 391 int error; 392 393 error = SYSCTL_OUT(req, arg1, arg2); 394 395 if (error || !req->newptr) 396 return (error); 397 398 error = SYSCTL_IN(req, arg1, arg2); 399 400 return (error); 401 } 402 403 /* 404 * Transfer functions to/from kernel space. 405 * XXX: rather untested at this point 406 */ 407 static int 408 sysctl_old_kernel(struct sysctl_req *req, void *p, int l) 409 { 410 int i = 0; 411 412 if (req->oldptr) { 413 i = min(req->oldlen - req->oldidx, l); 414 if (i > 0) 415 bcopy(p, req->oldptr + req->oldidx, i); 416 } 417 req->oldidx += l; 418 if (i != l) 419 return (ENOMEM); 420 return (0); 421 422 } 423 424 static int 425 sysctl_new_kernel(struct sysctl_req *req, void *p, int l) 426 { 427 if (!req->newptr) 428 return 0; 429 if (req->newlen - req->newidx < l) 430 return (EINVAL); 431 bcopy(req->newptr + req->newidx, p, l); 432 req->newidx += l; 433 return (0); 434 } 435 436 /* 437 * Transfer function to/from user space. 438 */ 439 static int 440 sysctl_old_user(struct sysctl_req *req, void *p, int l) 441 { 442 int error = 0, i = 0; 443 444 if (req->lock == 1 && req->oldptr) { 445 vslock(req->oldptr, req->oldlen); 446 req->lock = 2; 447 } 448 if (req->oldptr) { 449 i = min(req->oldlen - req->oldidx, l); 450 if (i > 0) 451 error = copyout(p, req->oldptr + req->oldidx, i); 452 } 453 req->oldidx += l; 454 if (error) 455 return (error); 456 if (req->oldptr && i < l) 457 return (ENOMEM); 458 return (0); 459 } 460 461 static int 462 sysctl_new_user(struct sysctl_req *req, void *p, int l) 463 { 464 int error; 465 466 if (!req->newptr) 467 return 0; 468 if (req->newlen - req->newidx < l) 469 return (EINVAL); 470 error = copyin(req->newptr + req->newidx, p, l); 471 req->newidx += l; 472 return (error); 473 } 474 475 /* 476 * Traverse our tree, and find the right node, execute whatever it points 477 * at, and return the resulting error code. 478 */ 479 480 int 481 sysctl_root SYSCTL_HANDLER_ARGS 482 { 483 int *name = (int *) arg1; 484 int namelen = arg2; 485 int indx, i, j; 486 struct sysctl_oid **oidpp; 487 struct linker_set *lsp = &sysctl_; 488 489 j = lsp->ls_length; 490 oidpp = (struct sysctl_oid **) lsp->ls_items; 491 492 indx = 0; 493 while (j-- && indx < CTL_MAXNAME) { 494 if (*oidpp && ((*oidpp)->oid_number == name[indx])) { 495 indx++; 496 if ((*oidpp)->oid_kind & CTLFLAG_NOLOCK) 497 req->lock = 0; 498 if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 499 if ((*oidpp)->oid_handler) 500 goto found; 501 if (indx == namelen) 502 return ENOENT; 503 lsp = (struct linker_set*)(*oidpp)->oid_arg1; 504 j = lsp->ls_length; 505 oidpp = (struct sysctl_oid **)lsp->ls_items; 506 } else { 507 if (indx != namelen) 508 return EISDIR; 509 goto found; 510 } 511 } else { 512 oidpp++; 513 } 514 } 515 return ENOENT; 516 found: 517 518 /* If writing isn't allowed */ 519 if (req->newptr && !((*oidpp)->oid_kind & CTLFLAG_WR)) 520 return (EPERM); 521 522 if (!(*oidpp)->oid_handler) 523 return EINVAL; 524 525 if (((*oidpp)->oid_kind & CTLTYPE) == CTLTYPE_NODE) { 526 i = ((*oidpp)->oid_handler) (*oidpp, 527 name + indx, namelen - indx, 528 req); 529 } else { 530 i = ((*oidpp)->oid_handler) (*oidpp, 531 (*oidpp)->oid_arg1, (*oidpp)->oid_arg2, 532 req); 533 } 534 return (i); 535 } 536 537 #ifndef _SYS_SYSPROTO_H_ 538 struct sysctl_args { 539 int *name; 540 u_int namelen; 541 void *old; 542 size_t *oldlenp; 543 void *new; 544 size_t newlen; 545 }; 546 #endif 547 548 int 549 __sysctl(struct proc *p, struct sysctl_args *uap, int *retval) 550 { 551 int error, i, j, name[CTL_MAXNAME]; 552 553 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 554 return (EINVAL); 555 556 error = copyin(uap->name, &name, uap->namelen * sizeof(int)); 557 if (error) 558 return (error); 559 560 error = userland_sysctl(p, name, uap->namelen, 561 uap->old, uap->oldlenp, 0, 562 uap->new, uap->newlen, &j); 563 if (error && error != ENOMEM) 564 return (error); 565 if (uap->oldlenp) { 566 i = copyout(&j, uap->oldlenp, sizeof(j)); 567 if (i) 568 return (i); 569 } 570 return (error); 571 } 572 573 /* 574 * This is used from various compatibility syscalls too. That's why name 575 * must be in kernel space. 576 */ 577 int 578 userland_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen, int *retval) 579 { 580 int error = 0; 581 struct sysctl_req req; 582 583 bzero(&req, sizeof req); 584 585 req.p = p; 586 587 if (new != NULL && (error = suser(p->p_ucred, &p->p_acflag))) 588 return (error); 589 590 if (oldlenp) { 591 if (inkernel) { 592 req.oldlen = *oldlenp; 593 } else { 594 error = copyin(oldlenp, &req.oldlen, sizeof(*oldlenp)); 595 if (error) 596 return (error); 597 } 598 } 599 600 if (old) { 601 if (!useracc(old, req.oldlen, B_WRITE)) 602 return (EFAULT); 603 req.oldptr= old; 604 } 605 606 if (newlen) { 607 if (!useracc(new, req.newlen, B_READ)) 608 return (EFAULT); 609 req.newlen = newlen; 610 req.newptr = new; 611 } 612 613 req.oldfunc = sysctl_old_user; 614 req.newfunc = sysctl_new_user; 615 req.lock = 1; 616 617 /* XXX this should probably be done in a general way */ 618 while (memlock.sl_lock) { 619 memlock.sl_want = 1; 620 (void) tsleep((caddr_t)&memlock, PRIBIO+1, "sysctl", 0); 621 memlock.sl_locked++; 622 } 623 memlock.sl_lock = 1; 624 625 error = sysctl_root(0, name, namelen, &req); 626 627 if (req.lock == 2) 628 vsunlock(req.oldptr, req.oldlen, B_WRITE); 629 630 memlock.sl_lock = 0; 631 632 if (memlock.sl_want) { 633 memlock.sl_want = 0; 634 wakeup((caddr_t)&memlock); 635 } 636 637 if (error && error != ENOMEM) 638 return (error); 639 640 if (retval) { 641 if (req.oldptr && req.oldidx > req.oldlen) 642 *retval = req.oldlen; 643 else 644 *retval = req.oldidx; 645 } 646 return (error); 647 } 648 649 #ifdef COMPAT_43 650 #include <sys/socket.h> 651 #define KINFO_PROC (0<<8) 652 #define KINFO_RT (1<<8) 653 #define KINFO_VNODE (2<<8) 654 #define KINFO_FILE (3<<8) 655 #define KINFO_METER (4<<8) 656 #define KINFO_LOADAVG (5<<8) 657 #define KINFO_CLOCKRATE (6<<8) 658 659 /* Non-standard BSDI extension - only present on their 4.3 net-2 releases */ 660 #define KINFO_BSDI_SYSINFO (101<<8) 661 662 /* 663 * XXX this is bloat, but I hope it's better here than on the potentially 664 * limited kernel stack... -Peter 665 */ 666 667 struct { 668 int bsdi_machine; /* "i386" on BSD/386 */ 669 /* ^^^ this is an offset to the string, relative to the struct start */ 670 char *pad0; 671 long pad1; 672 long pad2; 673 long pad3; 674 u_long pad4; 675 u_long pad5; 676 u_long pad6; 677 678 int bsdi_ostype; /* "BSD/386" on BSD/386 */ 679 int bsdi_osrelease; /* "1.1" on BSD/386 */ 680 long pad7; 681 long pad8; 682 char *pad9; 683 684 long pad10; 685 long pad11; 686 int pad12; 687 long pad13; 688 quad_t pad14; 689 long pad15; 690 691 struct timeval pad16; 692 /* we dont set this, because BSDI's uname used gethostname() instead */ 693 int bsdi_hostname; /* hostname on BSD/386 */ 694 695 /* the actual string data is appended here */ 696 697 } bsdi_si; 698 /* 699 * this data is appended to the end of the bsdi_si structure during copyout. 700 * The "char *" offsets are relative to the base of the bsdi_si struct. 701 * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings 702 * should not exceed the length of the buffer here... (or else!! :-) 703 */ 704 char bsdi_strings[80]; /* It had better be less than this! */ 705 706 #ifndef _SYS_SYSPROTO_H_ 707 struct getkerninfo_args { 708 int op; 709 char *where; 710 int *size; 711 int arg; 712 }; 713 #endif 714 715 int 716 ogetkerninfo(struct proc *p, struct getkerninfo_args *uap, int *retval) 717 { 718 int error, name[6]; 719 u_int size; 720 721 switch (uap->op & 0xff00) { 722 723 case KINFO_RT: 724 name[0] = CTL_NET; 725 name[1] = PF_ROUTE; 726 name[2] = 0; 727 name[3] = (uap->op & 0xff0000) >> 16; 728 name[4] = uap->op & 0xff; 729 name[5] = uap->arg; 730 error = userland_sysctl(p, name, 6, uap->where, uap->size, 731 0, 0, 0, &size); 732 break; 733 734 case KINFO_VNODE: 735 name[0] = CTL_KERN; 736 name[1] = KERN_VNODE; 737 error = userland_sysctl(p, name, 2, uap->where, uap->size, 738 0, 0, 0, &size); 739 break; 740 741 case KINFO_PROC: 742 name[0] = CTL_KERN; 743 name[1] = KERN_PROC; 744 name[2] = uap->op & 0xff; 745 name[3] = uap->arg; 746 error = userland_sysctl(p, name, 4, uap->where, uap->size, 747 0, 0, 0, &size); 748 break; 749 750 case KINFO_FILE: 751 name[0] = CTL_KERN; 752 name[1] = KERN_FILE; 753 error = userland_sysctl(p, name, 2, uap->where, uap->size, 754 0, 0, 0, &size); 755 break; 756 757 case KINFO_METER: 758 name[0] = CTL_VM; 759 name[1] = VM_METER; 760 error = userland_sysctl(p, name, 2, uap->where, uap->size, 761 0, 0, 0, &size); 762 break; 763 764 case KINFO_LOADAVG: 765 name[0] = CTL_VM; 766 name[1] = VM_LOADAVG; 767 error = userland_sysctl(p, name, 2, uap->where, uap->size, 768 0, 0, 0, &size); 769 break; 770 771 case KINFO_CLOCKRATE: 772 name[0] = CTL_KERN; 773 name[1] = KERN_CLOCKRATE; 774 error = userland_sysctl(p, name, 2, uap->where, uap->size, 775 0, 0, 0, &size); 776 break; 777 778 case KINFO_BSDI_SYSINFO: { 779 /* 780 * this is pretty crude, but it's just enough for uname() 781 * from BSDI's 1.x libc to work. 782 * 783 * In particular, it doesn't return the same results when 784 * the supplied buffer is too small. BSDI's version apparently 785 * will return the amount copied, and set the *size to how 786 * much was needed. The emulation framework here isn't capable 787 * of that, so we just set both to the amount copied. 788 * BSDI's 2.x product apparently fails with ENOMEM in this 789 * scenario. 790 */ 791 792 u_int needed; 793 u_int left; 794 char *s; 795 796 bzero((char *)&bsdi_si, sizeof(bsdi_si)); 797 bzero(bsdi_strings, sizeof(bsdi_strings)); 798 799 s = bsdi_strings; 800 801 bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si); 802 strcpy(s, ostype); 803 s += strlen(s) + 1; 804 805 bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si); 806 strcpy(s, osrelease); 807 s += strlen(s) + 1; 808 809 bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si); 810 strcpy(s, machine); 811 s += strlen(s) + 1; 812 813 needed = sizeof(bsdi_si) + (s - bsdi_strings); 814 815 if (uap->where == NULL) { 816 /* process is asking how much buffer to supply.. */ 817 size = needed; 818 error = 0; 819 break; 820 } 821 822 823 /* if too much buffer supplied, trim it down */ 824 if (size > needed) 825 size = needed; 826 827 /* how much of the buffer is remaining */ 828 left = size; 829 830 if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0) 831 break; 832 833 /* is there any point in continuing? */ 834 if (left > sizeof(bsdi_si)) { 835 left -= sizeof(bsdi_si); 836 error = copyout(&bsdi_strings, 837 uap->where + sizeof(bsdi_si), left); 838 } 839 break; 840 } 841 842 default: 843 return (EOPNOTSUPP); 844 } 845 if (error) 846 return (error); 847 *retval = size; 848 if (uap->size) 849 error = copyout((caddr_t)&size, (caddr_t)uap->size, 850 sizeof(size)); 851 return (error); 852 } 853 #endif /* COMPAT_43 */ 854