sysctl.c revision 1.78
1/* $OpenBSD: sysctl.c,v 1.78 2001/12/04 14:57:27 art Exp $ */ 2/* $NetBSD: sysctl.c,v 1.9 1995/09/30 07:12:50 thorpej Exp $ */ 3 4/* 5 * Copyright (c) 1993 6 * The Regents of the University of California. All rights reserved. 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 37#ifndef lint 38static char copyright[] = 39"@(#) Copyright (c) 1993\n\ 40 The Regents of the University of California. All rights reserved.\n"; 41#endif /* not lint */ 42 43#ifndef lint 44#if 0 45static char sccsid[] = "@(#)sysctl.c 8.5 (Berkeley) 5/9/95"; 46#else 47static char *rcsid = "$OpenBSD: sysctl.c,v 1.78 2001/12/04 14:57:27 art Exp $"; 48#endif 49#endif /* not lint */ 50 51#include <sys/param.h> 52#include <sys/gmon.h> 53#include <sys/mount.h> 54#include <sys/stat.h> 55#include <sys/sysctl.h> 56#include <sys/socket.h> 57#include <sys/malloc.h> 58#include <sys/dkstat.h> 59#include <sys/uio.h> 60#include <sys/tty.h> 61#include <sys/namei.h> 62#include <machine/cpu.h> 63#include <net/route.h> 64 65#include <netinet/in.h> 66#include <netinet/in_systm.h> 67#include <netinet/ip.h> 68#include <netinet/in_pcb.h> 69#include <netinet/ip_icmp.h> 70#include <netinet/ip_ipip.h> 71#include <netinet/ip_ether.h> 72#include <netinet/ip_ah.h> 73#include <netinet/ip_esp.h> 74#include <netinet/icmp_var.h> 75#include <netinet/ip_var.h> 76#include <netinet/udp.h> 77#include <netinet/udp_var.h> 78#include <netinet/tcp.h> 79#include <netinet/tcp_timer.h> 80#include <netinet/tcp_var.h> 81#include <netinet/ip_gre.h> 82#include <netinet/ip_ipcomp.h> 83 84#ifdef INET6 85#include <netinet/ip6.h> 86#include <netinet/icmp6.h> 87#include <netinet6/ip6_var.h> 88#include <netinet6/pim6_var.h> 89#endif 90 91#include <uvm/uvm_swap_encrypt.h> 92 93#include <ufs/ufs/quota.h> 94#include <ufs/ufs/inode.h> 95#include <ufs/ffs/fs.h> 96#include <ufs/ffs/ffs_extern.h> 97 98#include <nfs/rpcv2.h> 99#include <nfs/nfsproto.h> 100#include <nfs/nfs.h> 101 102#include <netipx/ipx.h> 103#include <netipx/ipx_var.h> 104#include <netipx/spx_var.h> 105#include <ddb/db_var.h> 106#include <dev/rndvar.h> 107 108#include <err.h> 109#include <errno.h> 110#include <stdio.h> 111#include <stdlib.h> 112#include <string.h> 113#include <ctype.h> 114 115#ifdef CPU_BIOS 116#include <machine/biosvar.h> 117#endif 118 119struct ctlname topname[] = CTL_NAMES; 120struct ctlname kernname[] = CTL_KERN_NAMES; 121struct ctlname vmname[] = CTL_VM_NAMES; 122struct ctlname fsname[] = CTL_FS_NAMES; 123struct ctlname netname[] = CTL_NET_NAMES; 124struct ctlname hwname[] = CTL_HW_NAMES; 125struct ctlname username[] = CTL_USER_NAMES; 126struct ctlname debugname[CTL_DEBUG_MAXID]; 127struct ctlname kernmallocname[] = CTL_KERN_MALLOC_NAMES; 128struct ctlname forkstatname[] = CTL_KERN_FORKSTAT_NAMES; 129struct ctlname nchstatsname[] = CTL_KERN_NCHSTATS_NAMES; 130struct ctlname ttyname[] = CTL_KERN_TTY_NAMES; 131struct ctlname *vfsname; 132#ifdef CTL_MACHDEP_NAMES 133struct ctlname machdepname[] = CTL_MACHDEP_NAMES; 134#endif 135struct ctlname ddbname[] = CTL_DDB_NAMES; 136char names[BUFSIZ]; 137int lastused; 138 139struct list { 140 struct ctlname *list; 141 int size; 142}; 143struct list toplist = { topname, CTL_MAXID }; 144struct list secondlevel[] = { 145 { 0, 0 }, /* CTL_UNSPEC */ 146 { kernname, KERN_MAXID }, /* CTL_KERN */ 147 { vmname, VM_MAXID }, /* CTL_VM */ 148 { fsname, FS_MAXID }, /* CTL_FS */ 149 { netname, NET_MAXID }, /* CTL_NET */ 150 { 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */ 151 { hwname, HW_MAXID }, /* CTL_HW */ 152#ifdef CTL_MACHDEP_NAMES 153 { machdepname, CPU_MAXID }, /* CTL_MACHDEP */ 154#else 155 { 0, 0 }, /* CTL_MACHDEP */ 156#endif 157 { username, USER_MAXID }, /* CTL_USER_NAMES */ 158 { ddbname, DBCTL_MAXID }, /* CTL_DDB_NAMES */ 159 { 0, 0 }, /* CTL_VFS */ 160}; 161 162int Aflag, aflag, nflag, wflag; 163 164/* 165 * Variables requiring special processing. 166 */ 167#define CLOCK 0x00000001 168#define BOOTTIME 0x00000002 169#define CHRDEV 0x00000004 170#define BLKDEV 0x00000008 171#define RNDSTATS 0x00000010 172#define BADDYNAMIC 0x00000020 173#define BIOSGEO 0x00000040 174#define BIOSDEV 0x00000080 175#define MAJ2DEV 0x00000100 176#define UNSIGNED 0x00000200 177#define KMEMBUCKETS 0x00000400 178#define LONGARRAY 0x00000800 179#define KMEMSTATS 0x00001000 180 181/* prototypes */ 182void debuginit __P((void)); 183void listall __P((char *, struct list *)); 184void parse __P((char *, int)); 185void parse_baddynamic __P((int *, size_t, char *, void **, size_t *, int, int)); 186void usage __P((void)); 187int findname __P((char *, char *, char **, struct list *)); 188int sysctl_inet __P((char *, char **, int *, int, int *)); 189#ifdef INET6 190int sysctl_inet6 __P((char *, char **, int *, int, int *)); 191#endif 192int sysctl_ipx __P((char *, char **, int *, int, int *)); 193int sysctl_fs __P((char *, char **, int *, int, int *)); 194static int sysctl_vfs __P((char *, char **, int[], int, int *)); 195static int sysctl_vfsgen __P((char *, char **, int[], int, int *)); 196int sysctl_bios __P((char *, char **, int *, int, int *)); 197int sysctl_swpenc __P((char *, char **, int *, int, int *)); 198int sysctl_forkstat __P((char *, char **, int *, int, int *)); 199int sysctl_tty __P((char *, char **, int *, int, int *)); 200int sysctl_nchstats __P((char *, char **, int *, int, int *)); 201int sysctl_malloc __P((char *, char **, int *, int, int *)); 202void vfsinit __P((void)); 203 204int 205main(argc, argv) 206 int argc; 207 char *argv[]; 208{ 209 int ch, lvl1; 210 211 while ((ch = getopt(argc, argv, "Aanw")) != -1) { 212 switch (ch) { 213 214 case 'A': 215 Aflag = 1; 216 break; 217 218 case 'a': 219 aflag = 1; 220 break; 221 222 case 'n': 223 nflag = 1; 224 break; 225 226 case 'w': 227 wflag = 1; 228 break; 229 230 default: 231 usage(); 232 } 233 } 234 argc -= optind; 235 argv += optind; 236 237 if (argc == 0 && (Aflag || aflag)) { 238 debuginit(); 239 vfsinit(); 240 for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++) 241 listall(topname[lvl1].ctl_name, &secondlevel[lvl1]); 242 return (0); 243 } 244 if (argc == 0) 245 usage(); 246 for (; *argv != NULL; ++argv) 247 parse(*argv, 1); 248 return (0); 249} 250 251/* 252 * List all variables known to the system. 253 */ 254void 255listall(prefix, lp) 256 char *prefix; 257 struct list *lp; 258{ 259 char *cp, name[BUFSIZ]; 260 int lvl2, len; 261 262 if (lp->list == NULL) 263 return; 264 if ((len = strlcpy(name, prefix, sizeof(name))) >= sizeof(name)) 265 warn("%s: name too long", prefix); 266 cp = name + len++; 267 *cp++ = '.'; 268 for (lvl2 = 0; lvl2 < lp->size; lvl2++) { 269 if (lp->list[lvl2].ctl_name == NULL) 270 continue; 271 if (strlcpy(cp, lp->list[lvl2].ctl_name, 272 sizeof(name) - len) >= sizeof(name) - len) 273 warn("%s: name too long", lp->list[lvl2].ctl_name); 274 parse(name, Aflag); 275 } 276} 277 278/* 279 * Parse a name into a MIB entry. 280 * Lookup and print out the MIB entry if it exists. 281 * Set a new value if requested. 282 */ 283void 284parse(string, flags) 285 char *string; 286 int flags; 287{ 288 int indx, type, state, intval, len; 289 size_t size, newsize = 0; 290 int lal = 0, special = 0; 291 void *newval = 0; 292 int64_t quadval; 293 struct list *lp; 294 int mib[CTL_MAXNAME]; 295 char *cp, *bufp, buf[BUFSIZ]; 296 297 (void)strlcpy(buf, string, sizeof(buf)); 298 bufp = buf; 299 if ((cp = strchr(string, '=')) != NULL) { 300 if (!wflag) 301 errx(2, "must specify -w to set variables"); 302 *strchr(buf, '=') = '\0'; 303 *cp++ = '\0'; 304 while (isspace(*cp)) 305 cp++; 306 newval = cp; 307 newsize = strlen(cp); 308 } 309 if ((indx = findname(string, "top", &bufp, &toplist)) == -1) 310 return; 311 mib[0] = indx; 312 if (indx == CTL_VFS) 313 vfsinit(); 314 if (indx == CTL_DEBUG) 315 debuginit(); 316 lp = &secondlevel[indx]; 317 if (lp->list == 0) { 318 warnx("%s: class is not implemented", topname[indx].ctl_name); 319 return; 320 } 321 if (bufp == NULL) { 322 listall(topname[indx].ctl_name, lp); 323 return; 324 } 325 if ((indx = findname(string, "second", &bufp, lp)) == -1) 326 return; 327 mib[1] = indx; 328 type = lp->list[indx].ctl_type; 329 len = 2; 330 switch (mib[0]) { 331 332 case CTL_KERN: 333 switch (mib[1]) { 334 case KERN_PROF: 335 mib[2] = GPROF_STATE; 336 size = sizeof(state); 337 if (sysctl(mib, 3, &state, &size, NULL, 0) == -1) { 338 if (flags == 0) 339 return; 340 if (!nflag) 341 (void)printf("%s: ", string); 342 (void)puts("kernel is not compiled for profiling"); 343 return; 344 } 345 if (!nflag) 346 (void)printf("%s = %s\n", string, 347 state == GMON_PROF_OFF ? "off" : "running"); 348 return; 349 case KERN_FORKSTAT: 350 sysctl_forkstat(string, &bufp, mib, flags, &type); 351 return; 352 case KERN_TTY: 353 len = sysctl_tty(string, &bufp, mib, flags, &type); 354 if (len < 0) 355 return; 356 newsize = 0; 357 break; 358 case KERN_NCHSTATS: 359 sysctl_nchstats(string, &bufp, mib, flags, &type); 360 return; 361 case KERN_MALLOCSTATS: 362 len = sysctl_malloc(string, &bufp, mib, flags, &type); 363 if (len < 0) 364 return; 365 if (mib[2] == KERN_MALLOC_BUCKET) 366 special |= KMEMBUCKETS; 367 if (mib[2] == KERN_MALLOC_KMEMSTATS) 368 special |= KMEMSTATS; 369 newsize = 0; 370 break; 371 case KERN_MSGBUF: 372 if (flags == 0) 373 return; 374 warnx("use dmesg to view %s", string); 375 return; 376 case KERN_VNODE: 377 case KERN_FILE: 378 if (flags == 0) 379 return; 380 warnx("use pstat to view %s information", string); 381 return; 382 case KERN_PROC: 383 if (flags == 0) 384 return; 385 warnx("use ps to view %s information", string); 386 return; 387 case KERN_NTPTIME: 388 if (flags == 0) 389 return; 390 warnx("use xntpdc to view %s information", string); 391 return; 392 case KERN_CLOCKRATE: 393 special |= CLOCK; 394 break; 395 case KERN_BOOTTIME: 396 special |= BOOTTIME; 397 break; 398 case KERN_RND: 399 special |= RNDSTATS; 400 break; 401 case KERN_HOSTID: 402 case KERN_ARND: 403 special |= UNSIGNED; 404 break; 405 case KERN_CPTIME: 406 special |= LONGARRAY; 407 lal = CPUSTATES; 408 break; 409 } 410 break; 411 412 case CTL_HW: 413 switch (mib[1]) { 414 case HW_DISKSTATS: 415 /* 416 * Only complain if someone asks explicitly for this, 417 * otherwise "fail" silently. 418 */ 419 if (flags) 420 warnx("use vmstat to view %s information", 421 string); 422 return; 423 } 424 break; 425 426 case CTL_VM: 427 if (mib[1] == VM_LOADAVG) { 428 double loads[3]; 429 430 getloadavg(loads, 3); 431 if (!nflag) 432 (void)printf("%s = ", string); 433 (void)printf("%.2f %.2f %.2f\n", loads[0], 434 loads[1], loads[2]); 435 return; 436 } else if (mib[1] == VM_PSSTRINGS) { 437 struct _ps_strings _ps; 438 439 size = sizeof(_ps); 440 if (sysctl(mib, 2, &_ps, &size, NULL, 0) == -1) { 441 if (flags == 0) 442 return; 443 if (!nflag) 444 (void)printf("%s: ", string); 445 (void)puts("can't find ps strings"); 446 return; 447 } 448 if (!nflag) 449 (void)printf("%s = ", string); 450 (void)printf("%p\n", _ps.val); 451 return; 452 } else if (mib[1] == VM_SWAPENCRYPT) { 453 len = sysctl_swpenc(string, &bufp, mib, flags, &type); 454 if (len < 0) 455 return; 456 457 break; 458 } else if (mib[1] == VM_NKMEMPAGES || 459 mib[1] == VM_ANONMIN || 460 mib[1] == VM_VTEXTMIN || 461 mib[1] == VM_VNODEMIN) { 462 break; 463 } 464 if (flags == 0) 465 return; 466 warnx("use vmstat or systat to view %s information", string); 467 return; 468 469 break; 470 471 case CTL_NET: 472 if (mib[1] == PF_INET) { 473 len = sysctl_inet(string, &bufp, mib, flags, &type); 474 if (len < 0) 475 return; 476 477 if ((mib[2] == IPPROTO_TCP && 478 mib[3] == TCPCTL_BADDYNAMIC) || 479 (mib[2] == IPPROTO_UDP && 480 mib[3] == UDPCTL_BADDYNAMIC)) { 481 482 special |= BADDYNAMIC; 483 484 if (newval != NULL) 485 parse_baddynamic(mib, len, string, 486 &newval, &newsize, flags, nflag); 487 } 488 break; 489 } 490#ifdef INET6 491 if (mib[1] == PF_INET6) { 492 len = sysctl_inet6(string, &bufp, mib, flags, &type); 493 if (len < 0) 494 return; 495 496 break; 497 } 498#endif 499 if (mib[1] == PF_IPX) { 500 len = sysctl_ipx(string, &bufp, mib, flags, &type); 501 if (len >= 0) 502 break; 503 return; 504 } 505 if (flags == 0) 506 return; 507 warnx("use netstat to view %s information", string); 508 return; 509 510 case CTL_DEBUG: 511 mib[2] = CTL_DEBUG_VALUE; 512 len = 3; 513 break; 514 515 case CTL_MACHDEP: 516#ifdef CPU_CONSDEV 517 if (mib[1] == CPU_CONSDEV) 518 special |= CHRDEV; 519#endif 520#ifdef CPU_BLK2CHR 521 if (mib[1] == CPU_BLK2CHR) { 522 if (bufp == NULL) 523 return; 524 mib[2] = makedev(atoi(bufp),0); 525 bufp = NULL; 526 len = 3; 527 special |= CHRDEV; 528 break; 529 } 530#endif 531#ifdef CPU_CHR2BLK 532 if (mib[1] == CPU_CHR2BLK) { 533 if (bufp == NULL) 534 return; 535 mib[2] = makedev(atoi(bufp),0); 536 bufp = NULL; 537 len = 3; 538 special |= BLKDEV; 539 break; 540 } 541#endif 542#ifdef CPU_BIOS 543 if (mib[1] == CPU_BIOS) { 544 len = sysctl_bios(string, &bufp, mib, flags, &type); 545 if (len < 0) 546 return; 547 if (mib[2] == BIOS_DEV) 548 special |= BIOSDEV; 549 if (mib[2] == BIOS_DISKINFO) 550 special |= BIOSGEO; 551 break; 552 } 553#endif 554 break; 555 556 case CTL_FS: 557 len = sysctl_fs(string, &bufp, mib, flags, &type); 558 if (len >= 0) 559 break; 560 return; 561 562 case CTL_VFS: 563 if (mib[1]) 564 len = sysctl_vfs(string, &bufp, mib, flags, &type); 565 else 566 len = sysctl_vfsgen(string, &bufp, mib, flags, &type); 567 if (len >= 0) { 568 if (type == CTLTYPE_STRUCT) { 569 if (flags) 570 warnx("use nfsstat to view %s information", 571 MOUNT_NFS); 572 return; 573 } else 574 break; 575 } 576 return; 577 578 case CTL_USER: 579 case CTL_DDB: 580 break; 581 582 default: 583 warnx("illegal top level value: %d", mib[0]); 584 return; 585 586 } 587 if (bufp) { 588 warnx("name %s in %s is unknown", bufp, string); 589 return; 590 } 591 if (newsize > 0) { 592 switch (type) { 593 case CTLTYPE_INT: 594 errno = 0; 595 if (special & UNSIGNED) 596 intval = strtoul(newval, &cp, 10); 597 else 598 intval = strtol(newval, &cp, 10); 599 if (*cp != '\0') { 600 warnx("%s: illegal value: %s", string, 601 (char *)newval); 602 return; 603 } 604 if (errno == ERANGE) { 605 warnx("%s: value %s out of range", string, 606 (char *)newval); 607 return; 608 } 609 newval = &intval; 610 newsize = sizeof(intval); 611 break; 612 613 case CTLTYPE_QUAD: 614 /* XXX - assumes sizeof(long long) == sizeof(quad_t) */ 615 (void)sscanf(newval, "%lld", (long long *)&quadval); 616 newval = &quadval; 617 newsize = sizeof(quadval); 618 break; 619 } 620 } 621 size = BUFSIZ; 622 if (sysctl(mib, len, buf, &size, newval, newsize) == -1) { 623 if (flags == 0) 624 return; 625 switch (errno) { 626 case EOPNOTSUPP: 627 warnx("%s: value is not available", string); 628 return; 629 case ENOTDIR: 630 warnx("%s: specification is incomplete", string); 631 return; 632 case ENOMEM: 633 warnx("%s: type is unknown to this program", string); 634 return; 635 case ENXIO: 636 if (special & BIOSGEO) 637 return; 638 default: 639 warn("%s", string); 640 return; 641 } 642 } 643 if (special & KMEMBUCKETS) { 644 struct kmembuckets *kb = (struct kmembuckets *)buf; 645 if (!nflag) 646 (void)printf("%s = ", string); 647 printf("("); 648 printf("calls = %llu ", (long long)kb->kb_calls); 649 printf("total_allocated = %llu ", (long long)kb->kb_total); 650 printf("total_free = %lld ", (long long)kb->kb_totalfree); 651 printf("elements = %lld ", (long long)kb->kb_elmpercl); 652 printf("high watermark = %lld ", (long long)kb->kb_highwat); 653 printf("could_free = %lld", (long long)kb->kb_couldfree); 654 printf(")\n"); 655 return; 656 } 657 if (special & KMEMSTATS) { 658 struct kmemstats *km = (struct kmemstats *)buf; 659 int j, first = 1; 660 661 if (!nflag) 662 (void)printf("%s = ", string); 663 (void)printf("(inuse = %ld, calls = %ld, memuse = %ldK, limblocks = %d, mapblocks = %d, maxused = %ldK, limit = %ldK, spare = %ld, sizes = (", km->ks_inuse, km->ks_calls, (km->ks_memuse + 1023) / 1024, km->ks_limblocks, km->ks_mapblocks, (km->ks_maxused + 1023) / 1024, (km->ks_limit + 1023) / 1024, km->ks_spare); 664 for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) { 665 if ((km->ks_size & j ) == 0) 666 continue; 667 if (first) 668 (void)printf("%d", j); 669 else 670 (void)printf(",%d", j); 671 first = 0; 672 } 673 if (first) 674 (void)printf("none"); 675 (void)printf("))\n"); 676 return; 677 } 678 if (special & CLOCK) { 679 struct clockinfo *clkp = (struct clockinfo *)buf; 680 681 if (!nflag) 682 (void)printf("%s = ", string); 683 (void)printf( 684 "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n", 685 clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz); 686 return; 687 } 688 if (special & BOOTTIME) { 689 struct timeval *btp = (struct timeval *)buf; 690 time_t boottime; 691 692 if (!nflag) { 693 boottime = btp->tv_sec; 694 (void)printf("%s = %s", string, ctime(&boottime)); 695 } else 696 (void)printf("%ld\n", btp->tv_sec); 697 return; 698 } 699 if (special & BLKDEV) { 700 dev_t dev = *(dev_t *)buf; 701 702 if (!nflag) 703 (void)printf("%s = %s\n", string, 704 devname(dev, S_IFBLK)); 705 else 706 (void)printf("0x%x\n", dev); 707 return; 708 } 709 if (special & CHRDEV) { 710 dev_t dev = *(dev_t *)buf; 711 712 if (!nflag) 713 (void)printf("%s = %s\n", string, 714 devname(dev, S_IFCHR)); 715 else 716 (void)printf("0x%x\n", dev); 717 return; 718 } 719#ifdef CPU_BIOS 720 if (special & BIOSGEO) { 721 bios_diskinfo_t *pdi = (bios_diskinfo_t *)buf; 722 723 if (!nflag) 724 (void)printf("%s = ", string); 725 (void)printf("bootdev = 0x%x, " 726 "cylinders = %u, heads = %u, sectors = %u\n", 727 pdi->bsd_dev, pdi->bios_cylinders, 728 pdi->bios_heads, pdi->bios_sectors); 729 return; 730 } 731 if (special & BIOSDEV) { 732 int dev = *(int*)buf; 733 734 if (!nflag) 735 (void)printf("%s = ", string); 736 (void) printf("0x%02x\n", dev); 737 return; 738 } 739#endif 740 if (special & UNSIGNED) { 741 if (newsize == 0) { 742 if (!nflag) 743 (void)printf("%s = ", string); 744 (void)printf("%u\n", *(u_int *)buf); 745 } else { 746 if (!nflag) 747 (void)printf("%s: %u -> ", string, 748 *(u_int *)buf); 749 (void)printf("%u\n", *(u_int *)newval); 750 } 751 return; 752 } 753 if (special & RNDSTATS) { 754 struct rndstats *rndstats = (struct rndstats *)buf; 755 int i; 756 757 if (!nflag) 758 (void)printf("%s = ", string); 759 (void)printf( 760 "%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu", 761 (unsigned long long)rndstats->rnd_total, 762 (unsigned long long)rndstats->rnd_used, 763 (unsigned long long)rndstats->rnd_reads, 764 (unsigned long long)rndstats->arc4_reads, 765 (unsigned long long)rndstats->arc4_nstirs, 766 (unsigned long long)rndstats->arc4_stirs, 767 (unsigned long long)rndstats->rnd_pad[0], 768 (unsigned long long)rndstats->rnd_pad[1], 769 (unsigned long long)rndstats->rnd_pad[2], 770 (unsigned long long)rndstats->rnd_pad[3], 771 (unsigned long long)rndstats->rnd_pad[4], 772 (unsigned long long)rndstats->rnd_waits, 773 (unsigned long long)rndstats->rnd_enqs, 774 (unsigned long long)rndstats->rnd_deqs, 775 (unsigned long long)rndstats->rnd_drops, 776 (unsigned long long)rndstats->rnd_drople); 777 for (i = 0; i < sizeof(rndstats->rnd_ed)/sizeof(rndstats->rnd_ed[0]); i++) 778 (void)printf(" %llu", (unsigned long long)rndstats->rnd_ed[i]); 779 for (i = 0; i < sizeof(rndstats->rnd_sc)/sizeof(rndstats->rnd_sc[0]); i++) 780 (void)printf(" %llu", (unsigned long long)rndstats->rnd_sc[i]); 781 for (i = 0; i < sizeof(rndstats->rnd_sb)/sizeof(rndstats->rnd_sb[0]); i++) 782 (void)printf(" %llu", (unsigned long long)rndstats->rnd_sb[i]); 783 printf("\n"); 784 return; 785 } 786 if (special & BADDYNAMIC) { 787 in_port_t port, lastport; 788 u_int32_t *baddynamic = (u_int32_t *)buf; 789 790 if (!nflag) 791 (void)printf("%s%s", string, newsize ? ": " : " = "); 792 lastport = 0; 793 for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED; port++) 794 if (DP_ISSET(baddynamic, port)) { 795 (void)printf("%s%hd", lastport ? "," : "", 796 port); 797 lastport = port; 798 } 799 if (newsize != 0) { 800 if (!nflag) 801 fputs(" -> ", stdout); 802 baddynamic = (u_int32_t *)newval; 803 lastport = 0; 804 for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED; 805 port++) 806 if (DP_ISSET(baddynamic, port)) { 807 (void)printf("%s%hd", 808 lastport ? "," : "", port); 809 lastport = port; 810 } 811 } 812 (void)putchar('\n'); 813 return; 814 } 815 if (special & LONGARRAY) { 816 long *la = (long *)buf; 817 if (!nflag) 818 printf("%s = ", string); 819 while (lal--) 820 printf("%ld%s", *la++, lal? ",":""); 821 putchar('\n'); 822 return; 823 } 824 switch (type) { 825 case CTLTYPE_INT: 826 if (newsize == 0) { 827 if (!nflag) 828 (void)printf("%s = ", string); 829 (void)printf("%d\n", *(int *)buf); 830 } else { 831 if (!nflag) 832 (void)printf("%s: %d -> ", string, 833 *(int *)buf); 834 (void)printf("%d\n", *(int *)newval); 835 } 836 return; 837 838 case CTLTYPE_STRING: 839 if (newval == NULL) { 840 if (!nflag) 841 (void)printf("%s = ", string); 842 (void)puts(buf); 843 } else { 844 if (!nflag) 845 (void)printf("%s: %s -> ", string, buf); 846 (void)puts((char *)newval); 847 } 848 return; 849 850 case CTLTYPE_QUAD: 851 if (newsize == 0) { 852 long long tmp = *(quad_t *)buf; 853 854 if (!nflag) 855 (void)printf("%s = ", string); 856 (void)printf("%lld\n", tmp); 857 } else { 858 long long tmp = *(quad_t *)buf; 859 860 if (!nflag) 861 (void)printf("%s: %lld -> ", string, tmp); 862 tmp = *(quad_t *)newval; 863 (void)printf("%qd\n", tmp); 864 } 865 return; 866 867 case CTLTYPE_STRUCT: 868 warnx("%s: unknown structure returned", string); 869 return; 870 871 default: 872 case CTLTYPE_NODE: 873 warnx("%s: unknown type returned", string); 874 return; 875 } 876} 877 878void 879parse_baddynamic(mib, len, string, newvalp, newsizep, flags, nflag) 880 int mib[]; 881 size_t len; 882 char *string; 883 void **newvalp; 884 size_t *newsizep; 885 int flags; 886 int nflag; 887{ 888 static u_int32_t newbaddynamic[DP_MAPSIZE]; 889 in_port_t port; 890 size_t size; 891 char action, *cp; 892 893 if (strchr((char *)*newvalp, '+') || strchr((char *)*newvalp, '-')) { 894 size = sizeof(newbaddynamic); 895 if (sysctl(mib, len, newbaddynamic, &size, 0, 0) == -1) { 896 if (flags == 0) 897 return; 898 if (!nflag) 899 (void)printf("%s: ", string); 900 (void)puts("kernel does contain bad dynamic port tables"); 901 return; 902 } 903 904 while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) { 905 if (*cp != '+' && *cp != '-') 906 errx(1, "cannot mix +/- with full list"); 907 action = *cp++; 908 port = atoi(cp); 909 if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED) 910 errx(1, "invalid port, range is %d to %d", 911 IPPORT_RESERVED/2, IPPORT_RESERVED-1); 912 if (action == '+') 913 DP_SET(newbaddynamic, port); 914 else 915 DP_CLR(newbaddynamic, port); 916 } 917 } else { 918 (void)memset((void *)newbaddynamic, 0, sizeof(newbaddynamic)); 919 while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) { 920 port = atoi(cp); 921 if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED) 922 errx(1, "invalid port, range is %d to %d", 923 IPPORT_RESERVED/2, IPPORT_RESERVED-1); 924 DP_SET(newbaddynamic, port); 925 } 926 } 927 928 *newvalp = (void *)newbaddynamic; 929 *newsizep = sizeof(newbaddynamic); 930} 931 932/* 933 * Initialize the set of debugging names 934 */ 935void 936debuginit() 937{ 938 int mib[3], loc, i; 939 size_t size; 940 941 if (secondlevel[CTL_DEBUG].list != 0) 942 return; 943 secondlevel[CTL_DEBUG].list = debugname; 944 mib[0] = CTL_DEBUG; 945 mib[2] = CTL_DEBUG_NAME; 946 for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) { 947 mib[1] = i; 948 size = BUFSIZ - loc; 949 if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1) 950 continue; 951 debugname[i].ctl_name = &names[loc]; 952 debugname[i].ctl_type = CTLTYPE_INT; 953 loc += size; 954 } 955 lastused = loc; 956} 957 958struct ctlname vfsgennames[] = CTL_VFSGENCTL_NAMES; 959struct ctlname ffsname[] = FFS_NAMES; 960struct ctlname nfsname[] = FS_NFS_NAMES; 961struct list *vfsvars; 962int *vfs_typenums; 963 964/* 965 * Initialize the set of filesystem names 966 */ 967void 968vfsinit() 969{ 970 int mib[4], maxtypenum, cnt, loc, size; 971 struct vfsconf vfc; 972 size_t buflen; 973 974 if (secondlevel[CTL_VFS].list != 0) 975 return; 976 mib[0] = CTL_VFS; 977 mib[1] = VFS_GENERIC; 978 mib[2] = VFS_MAXTYPENUM; 979 buflen = 4; 980 if (sysctl(mib, 3, &maxtypenum, &buflen, (void *)0, (size_t)0) < 0) 981 return; 982 maxtypenum++; /* + generic */ 983 if ((vfs_typenums = malloc(maxtypenum * sizeof(int))) == NULL) 984 return; 985 memset(vfs_typenums, 0, maxtypenum * sizeof(int)); 986 if ((vfsvars = malloc(maxtypenum * sizeof(*vfsvars))) == NULL) { 987 free(vfs_typenums); 988 return; 989 } 990 memset(vfsvars, 0, maxtypenum * sizeof(*vfsvars)); 991 if ((vfsname = malloc(maxtypenum * sizeof(*vfsname))) == NULL) { 992 free(vfs_typenums); 993 free(vfsvars); 994 return; 995 } 996 memset(vfsname, 0, maxtypenum * sizeof(*vfsname)); 997 mib[2] = VFS_CONF; 998 buflen = sizeof vfc; 999 for (loc = lastused, cnt = 1; cnt < maxtypenum; cnt++) { 1000 mib[3] = cnt - 1; 1001 if (sysctl(mib, 4, &vfc, &buflen, (void *)0, (size_t)0) < 0) { 1002 if (errno == EOPNOTSUPP) 1003 continue; 1004 warn("vfsinit"); 1005 free(vfsname); 1006 return; 1007 } 1008 if (!strcmp(vfc.vfc_name, MOUNT_FFS)) { 1009 vfsvars[cnt].list = ffsname; 1010 vfsvars[cnt].size = FFS_MAXID; 1011 } 1012 if (!strcmp(vfc.vfc_name, MOUNT_NFS)) { 1013 vfsvars[cnt].list = nfsname; 1014 vfsvars[cnt].size = NFS_MAXID; 1015 } 1016 vfs_typenums[cnt] = vfc.vfc_typenum; 1017 strcat(&names[loc], vfc.vfc_name); 1018 vfsname[cnt].ctl_name = &names[loc]; 1019 vfsname[cnt].ctl_type = CTLTYPE_NODE; 1020 size = strlen(vfc.vfc_name) + 1; 1021 loc += size; 1022 } 1023 lastused = loc; 1024 1025 vfsname[0].ctl_name = "mounts"; 1026 vfsname[0].ctl_type = CTLTYPE_NODE; 1027 vfsvars[0].list = vfsname + 1; 1028 vfsvars[0].size = maxtypenum - 1; 1029 1030 secondlevel[CTL_VFS].list = vfsname; 1031 secondlevel[CTL_VFS].size = maxtypenum; 1032 return; 1033} 1034 1035int 1036sysctl_vfsgen(string, bufpp, mib, flags, typep) 1037 char *string; 1038 char **bufpp; 1039 int mib[]; 1040 int flags; 1041 int *typep; 1042{ 1043 int indx; 1044 size_t size; 1045 struct vfsconf vfc; 1046 1047 if (*bufpp == NULL) { 1048 listall(string, vfsvars); 1049 return (-1); 1050 } 1051 1052 if ((indx = findname(string, "third", bufpp, vfsvars)) == -1) 1053 return (-1); 1054 1055 mib[1] = VFS_GENERIC; 1056 mib[2] = VFS_CONF; 1057 mib[3] = indx; 1058 size = sizeof vfc; 1059 if (sysctl(mib, 4, &vfc, &size, (void *)0, (size_t)0) < 0) { 1060 if (errno != EOPNOTSUPP) 1061 warn("vfs print"); 1062 return -1; 1063 } 1064 if (flags == 0 && vfc.vfc_refcount == 0) 1065 return -1; 1066 if (!nflag) 1067 fprintf(stdout, "%s has %d mounted instance%s\n", 1068 string, vfc.vfc_refcount, 1069 vfc.vfc_refcount != 1 ? "s" : ""); 1070 else 1071 fprintf(stdout, "%d\n", vfc.vfc_refcount); 1072 1073 return -1; 1074} 1075 1076int 1077sysctl_vfs(string, bufpp, mib, flags, typep) 1078 char *string; 1079 char **bufpp; 1080 int mib[]; 1081 int flags; 1082 int *typep; 1083{ 1084 struct list *lp = &vfsvars[mib[1]]; 1085 int indx; 1086 1087 if (lp->list == NULL) { 1088 if (flags) 1089 warnx("No variables defined for file system %s", string); 1090 return(-1); 1091 } 1092 if (*bufpp == NULL) { 1093 listall(string, lp); 1094 return (-1); 1095 } 1096 if ((indx = findname(string, "third", bufpp, lp)) == -1) 1097 return (-1); 1098 1099 mib[1] = vfs_typenums[mib[1]]; 1100 mib[2] = indx; 1101 *typep = lp->list[indx].ctl_type; 1102 return (3); 1103} 1104 1105struct ctlname posixname[] = CTL_FS_POSIX_NAMES; 1106struct list fslist = { posixname, FS_POSIX_MAXID }; 1107 1108/* 1109 * handle file system requests 1110 */ 1111int 1112sysctl_fs(string, bufpp, mib, flags, typep) 1113 char *string; 1114 char **bufpp; 1115 int mib[]; 1116 int flags; 1117 int *typep; 1118{ 1119 int indx; 1120 1121 if (*bufpp == NULL) { 1122 listall(string, &fslist); 1123 return(-1); 1124 } 1125 if ((indx = findname(string, "third", bufpp, &fslist)) == -1) 1126 return(-1); 1127 mib[2] = indx; 1128 *typep = fslist.list[indx].ctl_type; 1129 return(3); 1130} 1131 1132#ifdef CPU_BIOS 1133struct ctlname biosname[] = CTL_BIOS_NAMES; 1134struct list bioslist = { biosname, BIOS_MAXID }; 1135 1136/* 1137 * handle BIOS requests 1138 */ 1139int 1140sysctl_bios(string, bufpp, mib, flags, typep) 1141 char *string; 1142 char **bufpp; 1143 int mib[]; 1144 int flags; 1145 int *typep; 1146{ 1147 char *name; 1148 int indx; 1149 1150 if (*bufpp == NULL) { 1151 listall(string, &bioslist); 1152 return(-1); 1153 } 1154 if ((indx = findname(string, "third", bufpp, &bioslist)) == -1) 1155 return(-1); 1156 mib[2] = indx; 1157 if (indx == BIOS_DISKINFO) { 1158 if (*bufpp == NULL) { 1159 char name[BUFSIZ]; 1160 1161 /* scan all the bios devices */ 1162 for (indx = 0; indx < 256; indx++) { 1163 snprintf(name, sizeof(name), "%s.%u", 1164 string, indx); 1165 parse(name, 1); 1166 } 1167 return(-1); 1168 } 1169 if ((name = strsep(bufpp, ".")) == NULL) { 1170 warnx("%s: incomplete specification", string); 1171 return(-1); 1172 } 1173 mib[3] = atoi(name); 1174 *typep = CTLTYPE_STRUCT; 1175 return(4); 1176 } else { 1177 *typep = bioslist.list[indx].ctl_type; 1178 return(3); 1179 } 1180} 1181#endif 1182 1183struct ctlname swpencname[] = CTL_SWPENC_NAMES; 1184struct list swpenclist = { swpencname, SWPENC_MAXID }; 1185 1186/* 1187 * handle swap encrypt requests 1188 */ 1189int 1190sysctl_swpenc(string, bufpp, mib, flags, typep) 1191 char *string; 1192 char **bufpp; 1193 int mib[]; 1194 int flags; 1195 int *typep; 1196{ 1197 int indx; 1198 1199 if (*bufpp == NULL) { 1200 listall(string, &swpenclist); 1201 return(-1); 1202 } 1203 if ((indx = findname(string, "third", bufpp, &swpenclist)) == -1) 1204 return(-1); 1205 mib[2] = indx; 1206 *typep = swpenclist.list[indx].ctl_type; 1207 return(3); 1208} 1209 1210struct ctlname inetname[] = CTL_IPPROTO_NAMES; 1211struct ctlname ipname[] = IPCTL_NAMES; 1212struct ctlname icmpname[] = ICMPCTL_NAMES; 1213struct ctlname ipipname[] = IPIPCTL_NAMES; 1214struct ctlname tcpname[] = TCPCTL_NAMES; 1215struct ctlname udpname[] = UDPCTL_NAMES; 1216struct ctlname espname[] = ESPCTL_NAMES; 1217struct ctlname ahname[] = AHCTL_NAMES; 1218struct ctlname etheripname[] = ETHERIPCTL_NAMES; 1219struct ctlname grename[] = GRECTL_NAMES; 1220struct ctlname mobileipname[] = MOBILEIPCTL_NAMES; 1221struct ctlname ipcompname[] = IPCOMPCTL_NAMES; 1222struct list inetlist = { inetname, IPPROTO_MAXID }; 1223struct list inetvars[] = { 1224 { ipname, IPCTL_MAXID }, /* ip */ 1225 { icmpname, ICMPCTL_MAXID }, /* icmp */ 1226 { 0, 0 }, /* igmp */ 1227 { 0, 0 }, /* ggmp */ 1228 { ipipname, IPIPCTL_MAXID }, /* ipencap */ 1229 { 0, 0 }, 1230 { tcpname, TCPCTL_MAXID }, /* tcp */ 1231 { 0, 0 }, 1232 { 0, 0 }, /* egp */ 1233 { 0, 0 }, 1234 { 0, 0 }, 1235 { 0, 0 }, 1236 { 0, 0 }, /* pup */ 1237 { 0, 0 }, 1238 { 0, 0 }, 1239 { 0, 0 }, 1240 { 0, 0 }, 1241 { udpname, UDPCTL_MAXID }, /* udp */ 1242 { 0, 0 }, 1243 { 0, 0 }, 1244 { 0, 0 }, 1245 { 0, 0 }, 1246 { 0, 0 }, 1247 { 0, 0 }, 1248 { 0, 0 }, 1249 { 0, 0 }, 1250 { 0, 0 }, 1251 { 0, 0 }, 1252 { 0, 0 }, 1253 { 0, 0 }, 1254 { 0, 0 }, 1255 { 0, 0 }, 1256 { 0, 0 }, 1257 { 0, 0 }, 1258 { 0, 0 }, 1259 { 0, 0 }, 1260 { 0, 0 }, 1261 { 0, 0 }, 1262 { 0, 0 }, 1263 { 0, 0 }, 1264 { 0, 0 }, 1265 { 0, 0 }, 1266 { 0, 0 }, 1267 { 0, 0 }, 1268 { 0, 0 }, 1269 { 0, 0 }, 1270 { 0, 0 }, 1271 { grename, GRECTL_MAXID }, /* GRE */ 1272 { 0, 0 }, 1273 { 0, 0 }, 1274 { espname, ESPCTL_MAXID }, /* esp */ 1275 { ahname, AHCTL_MAXID }, /* ah */ 1276 { 0, 0 }, 1277 { 0, 0 }, 1278 { 0, 0 }, 1279 { mobileipname, MOBILEIPCTL_MAXID }, /* mobileip */ 1280 { 0, 0 }, 1281 { 0, 0 }, 1282 { 0, 0 }, 1283 { 0, 0 }, 1284 { 0, 0 }, 1285 { 0, 0 }, 1286 { 0, 0 }, 1287 { 0, 0 }, 1288 { 0, 0 }, 1289 { 0, 0 }, 1290 { 0, 0 }, 1291 { 0, 0 }, 1292 { 0, 0 }, 1293 { 0, 0 }, 1294 { 0, 0 }, 1295 { 0, 0 }, 1296 { 0, 0 }, 1297 { 0, 0 }, 1298 { 0, 0 }, 1299 { 0, 0 }, 1300 { 0, 0 }, 1301 { 0, 0 }, 1302 { 0, 0 }, 1303 { 0, 0 }, 1304 { 0, 0 }, 1305 { 0, 0 }, 1306 { 0, 0 }, 1307 { 0, 0 }, 1308 { 0, 0 }, 1309 { 0, 0 }, 1310 { 0, 0 }, 1311 { 0, 0 }, 1312 { 0, 0 }, 1313 { 0, 0 }, 1314 { 0, 0 }, 1315 { 0, 0 }, 1316 { 0, 0 }, 1317 { 0, 0 }, 1318 { 0, 0 }, 1319 { 0, 0 }, 1320 { 0, 0 }, 1321 { etheripname, ETHERIPCTL_MAXID }, 1322 { 0, 0 }, 1323 { 0, 0 }, 1324 { 0, 0 }, 1325 { 0, 0 }, 1326 { 0, 0 }, 1327 { 0, 0 }, 1328 { 0, 0 }, 1329 { 0, 0 }, 1330 { 0, 0 }, 1331 { 0, 0 }, 1332 { ipcompname, IPCOMPCTL_MAXID }, 1333}; 1334 1335struct list kernmalloclist = { kernmallocname, KERN_MALLOC_MAXID }; 1336struct list forkstatlist = { forkstatname, KERN_FORKSTAT_MAXID }; 1337struct list nchstatslist = { nchstatsname, KERN_NCHSTATS_MAXID }; 1338struct list ttylist = { ttyname, KERN_TTY_MAXID }; 1339 1340/* 1341 * handle vfs namei cache statistics 1342 */ 1343int 1344sysctl_nchstats(string, bufpp, mib, flags, typep) 1345 char *string; 1346 char **bufpp; 1347 int mib[]; 1348 int flags; 1349 int *typep; 1350{ 1351 static struct nchstats nch; 1352 int indx; 1353 size_t size; 1354 static int keepvalue = 0; 1355 1356 if (*bufpp == NULL) { 1357 bzero(&nch, sizeof(struct nchstats)); 1358 listall(string, &nchstatslist); 1359 return(-1); 1360 } 1361 if ((indx = findname(string, "third", bufpp, &nchstatslist)) == -1) 1362 return(-1); 1363 mib[2] = indx; 1364 if (*bufpp != NULL) { 1365 warnx("fourth level name in %s is invalid", string); 1366 return(-1); 1367 } 1368 if (keepvalue == 0) { 1369 size = sizeof(struct nchstats); 1370 if (sysctl(mib, 2, &nch, &size, NULL, 0) < 0) 1371 return(-1); 1372 keepvalue = 1; 1373 } 1374 if (!nflag) 1375 (void)printf("%s = ", string); 1376 switch (indx) { 1377 case KERN_NCHSTATS_GOODHITS: 1378 (void)printf("%ld\n", nch.ncs_goodhits); 1379 break; 1380 case KERN_NCHSTATS_NEGHITS: 1381 (void)printf("%ld\n", nch.ncs_neghits); 1382 break; 1383 case KERN_NCHSTATS_BADHITS: 1384 (void)printf("%ld\n", nch.ncs_badhits); 1385 break; 1386 case KERN_NCHSTATS_FALSEHITS: 1387 (void)printf("%ld\n", nch.ncs_falsehits); 1388 break; 1389 case KERN_NCHSTATS_MISS: 1390 (void)printf("%ld\n", nch.ncs_miss); 1391 break; 1392 case KERN_NCHSTATS_LONG: 1393 (void)printf("%ld\n", nch.ncs_long); 1394 break; 1395 case KERN_NCHSTATS_PASS2: 1396 (void)printf("%ld\n", nch.ncs_pass2); 1397 break; 1398 case KERN_NCHSTATS_2PASSES: 1399 (void)printf("%ld\n", nch.ncs_2passes); 1400 break; 1401 } 1402 return(-1); 1403} 1404 1405/* 1406 * handle tty statistics 1407 */ 1408int 1409sysctl_tty(string, bufpp, mib, flags, typep) 1410 char *string; 1411 char **bufpp; 1412 int mib[]; 1413 int flags; 1414 int *typep; 1415{ 1416 int indx; 1417 1418 if (*bufpp == NULL) { 1419 listall(string, &ttylist); 1420 return(-1); 1421 } 1422 if ((indx = findname(string, "third", bufpp, &ttylist)) == -1) 1423 return(-1); 1424 mib[2] = indx; 1425 *typep = CTLTYPE_QUAD; 1426 return(3); 1427} 1428 1429/* 1430 * handle fork statistics 1431 */ 1432int 1433sysctl_forkstat(string, bufpp, mib, flags, typep) 1434 char *string; 1435 char **bufpp; 1436 int mib[]; 1437 int flags; 1438 int *typep; 1439{ 1440 static struct forkstat fks; 1441 static int keepvalue = 0; 1442 int indx; 1443 size_t size; 1444 1445 if (*bufpp == NULL) { 1446 bzero(&fks, sizeof(struct forkstat)); 1447 listall(string, &forkstatlist); 1448 return(-1); 1449 } 1450 if ((indx = findname(string, "third", bufpp, &forkstatlist)) == -1) 1451 return(-1); 1452 if (*bufpp != NULL) { 1453 warnx("fourth level name in %s is invalid", string); 1454 return(-1); 1455 } 1456 if (keepvalue == 0) { 1457 size = sizeof(struct forkstat); 1458 if (sysctl(mib, 2, &fks, &size, NULL, 0) < 0) 1459 return(-1); 1460 keepvalue = 1; 1461 } 1462 if (!nflag) 1463 (void)printf("%s = ", string); 1464 switch (indx) { 1465 case KERN_FORKSTAT_FORK: 1466 (void)printf("%d\n", fks.cntfork); 1467 break; 1468 case KERN_FORKSTAT_VFORK: 1469 (void)printf("%d\n", fks.cntvfork); 1470 break; 1471 case KERN_FORKSTAT_RFORK: 1472 (void)printf("%d\n", fks.cntrfork); 1473 break; 1474 case KERN_FORKSTAT_KTHREAD: 1475 (void)printf("%d\n", fks.cntkthread); 1476 break; 1477 case KERN_FORKSTAT_SIZFORK: 1478 (void)printf("%d\n", fks.sizfork); 1479 break; 1480 case KERN_FORKSTAT_SIZVFORK: 1481 (void)printf("%d\n", fks.sizvfork); 1482 break; 1483 case KERN_FORKSTAT_SIZRFORK: 1484 (void)printf("%d\n", fks.sizrfork); 1485 break; 1486 case KERN_FORKSTAT_SIZKTHREAD: 1487 (void)printf("%d\n", fks.sizkthread); 1488 break; 1489 } 1490 return(-1); 1491} 1492 1493/* 1494 * handle malloc statistics 1495 */ 1496int 1497sysctl_malloc(string, bufpp, mib, flags, typep) 1498 char *string; 1499 char **bufpp; 1500 int mib[]; 1501 int flags; 1502 int *typep; 1503{ 1504 int indx, stor, i; 1505 char *name, bufp[BUFSIZ], *buf, *ptr; 1506 struct list lp; 1507 size_t size; 1508 1509 if (*bufpp == NULL) { 1510 listall(string, &kernmalloclist); 1511 return(-1); 1512 } 1513 if ((indx = findname(string, "third", bufpp, &kernmalloclist)) == -1) 1514 return(-1); 1515 mib[2] = indx; 1516 if (mib[2] == KERN_MALLOC_BUCKET) { 1517 if ((name = strsep(bufpp, ".")) == NULL) { 1518 size = BUFSIZ; 1519 stor = mib[2]; 1520 mib[2] = KERN_MALLOC_BUCKETS; 1521 buf = bufp; 1522 if (sysctl(mib, 3, buf, &size, NULL, 0) < 0) 1523 return(-1); 1524 mib[2] = stor; 1525 for (stor = 0, i = 0; i < size; i++) 1526 if (buf[i] == ',') 1527 stor++; 1528 lp.list = calloc(stor + 2, sizeof(struct ctlname)); 1529 if (lp.list == NULL) 1530 return(-1); 1531 lp.size = stor + 2; 1532 for (i = 1; 1533 (lp.list[i].ctl_name = strsep(&buf, ",")) != NULL; 1534 i++) { 1535 lp.list[i].ctl_type = CTLTYPE_STRUCT; 1536 } 1537 lp.list[i].ctl_name = buf; 1538 lp.list[i].ctl_type = CTLTYPE_STRUCT; 1539 listall(string, &lp); 1540 free(lp.list); 1541 return(-1); 1542 } 1543 mib[3] = atoi(name); 1544 return(4); 1545 } else if (mib[2] == KERN_MALLOC_BUCKETS) { 1546 *typep = CTLTYPE_STRING; 1547 return(3); 1548 } else if (mib[2] == KERN_MALLOC_KMEMSTATS) { 1549 size = BUFSIZ; 1550 stor = mib[2]; 1551 mib[2] = KERN_MALLOC_KMEMNAMES; 1552 buf = bufp; 1553 if (sysctl(mib, 3, buf, &size, NULL, 0) < 0) 1554 return(-1); 1555 mib[2] = stor; 1556 if ((name = strsep(bufpp, ".")) == NULL) { 1557 for (stor = 0, i = 0; i < size; i++) 1558 if (buf[i] == ',') 1559 stor++; 1560 lp.list = calloc(stor + 2, sizeof(struct ctlname)); 1561 if (lp.list == NULL) 1562 return(-1); 1563 lp.size = stor + 2; 1564 for (i = 1; (lp.list[i].ctl_name = strsep(&buf, ",")) != NULL; i++) { 1565 if (lp.list[i].ctl_name[0] == '\0') { 1566 i--; 1567 continue; 1568 } 1569 lp.list[i].ctl_type = CTLTYPE_STRUCT; 1570 } 1571 lp.list[i].ctl_name = buf; 1572 lp.list[i].ctl_type = CTLTYPE_STRUCT; 1573 listall(string, &lp); 1574 free(lp.list); 1575 return(-1); 1576 } 1577 ptr = strstr(buf, name); 1578 tryagain: 1579 if (ptr == NULL) { 1580 warnx("fourth level name %s in %s is invalid", name, 1581 string); 1582 return(-1); 1583 } 1584 if ((*(ptr + strlen(name)) != ',') && 1585 (*(ptr + strlen(name)) != '\0')) { 1586 ptr = strstr(ptr + 1, name); /* retry */ 1587 goto tryagain; 1588 } 1589 if ((ptr != buf) && (*(ptr - 1) != ',')) { 1590 ptr = strstr(ptr + 1, name); /* retry */ 1591 goto tryagain; 1592 } 1593 for (i = 0, stor = 0; buf + i < ptr; i++) 1594 if (buf[i] == ',') 1595 stor++; 1596 mib[3] = stor; 1597 return(4); 1598 } else if (mib[2] == KERN_MALLOC_KMEMNAMES) { 1599 *typep = CTLTYPE_STRING; 1600 return(3); 1601 } 1602 return(-1); 1603} 1604 1605/* 1606 * handle internet requests 1607 */ 1608int 1609sysctl_inet(string, bufpp, mib, flags, typep) 1610 char *string; 1611 char **bufpp; 1612 int mib[]; 1613 int flags; 1614 int *typep; 1615{ 1616 struct list *lp; 1617 int indx; 1618 1619 if (*bufpp == NULL) { 1620 listall(string, &inetlist); 1621 return(-1); 1622 } 1623 if ((indx = findname(string, "third", bufpp, &inetlist)) == -1) 1624 return(-1); 1625 mib[2] = indx; 1626 if (indx < IPPROTO_MAXID && inetvars[indx].list != NULL) 1627 lp = &inetvars[indx]; 1628 else if (!flags) 1629 return(-1); 1630 else { 1631 warnx("%s: no variables defined for this protocol", string); 1632 return(-1); 1633 } 1634 if (*bufpp == NULL) { 1635 listall(string, lp); 1636 return(-1); 1637 } 1638 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 1639 return(-1); 1640 mib[3] = indx; 1641 *typep = lp->list[indx].ctl_type; 1642 return(4); 1643} 1644 1645#ifdef INET6 1646struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES; 1647struct ctlname ip6name[] = IPV6CTL_NAMES; 1648struct ctlname icmp6name[] = ICMPV6CTL_NAMES; 1649struct ctlname pim6name[] = PIM6CTL_NAMES; 1650struct list inet6list = { inet6name, IPV6PROTO_MAXID }; 1651struct list inet6vars[] = { 1652/*0*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1653 { 0, 0 }, 1654 { 0, 0 }, 1655 { 0, 0 }, 1656 { 0, 0 }, 1657 { 0, 0 }, 1658/*10*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1659 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1660/*20*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1661 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1662/*30*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1663 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1664/*40*/ { 0, 0 }, 1665 { ip6name, IPV6CTL_MAXID }, /* ipv6 */ 1666 { 0, 0 }, 1667 { 0, 0 }, 1668 { 0, 0 }, 1669 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1670/*50*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1671 { 0, 0 }, 1672 { 0, 0 }, 1673 { 0, 0 }, 1674 { icmp6name, ICMPV6CTL_MAXID }, /* icmp6 */ 1675 { 0, 0 }, 1676/*60*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1677 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1678/*70*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1679 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1680/*80*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1681 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1682/*90*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1683 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1684/*100*/ { 0, 0 }, 1685 { 0, 0 }, 1686 { 0, 0 }, 1687 { pim6name, PIM6CTL_MAXID }, /* pim6 */ 1688}; 1689 1690/* 1691 * handle internet6 requests 1692 */ 1693int 1694sysctl_inet6(string, bufpp, mib, flags, typep) 1695 char *string; 1696 char **bufpp; 1697 int mib[]; 1698 int flags; 1699 int *typep; 1700{ 1701 struct list *lp; 1702 int indx; 1703 1704 if (*bufpp == NULL) { 1705 listall(string, &inet6list); 1706 return(-1); 1707 } 1708 if ((indx = findname(string, "third", bufpp, &inet6list)) == -1) 1709 return(-1); 1710 mib[2] = indx; 1711 if (indx < IPV6PROTO_MAXID && inet6vars[indx].list != NULL) 1712 lp = &inet6vars[indx]; 1713 else if (!flags) 1714 return(-1); 1715 else { 1716 warnx("%s: no variables defined for this protocol", string); 1717 return(-1); 1718 } 1719 if (*bufpp == NULL) { 1720 listall(string, lp); 1721 return(-1); 1722 } 1723 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 1724 return(-1); 1725 mib[3] = indx; 1726 *typep = lp->list[indx].ctl_type; 1727 return(4); 1728} 1729#endif 1730 1731struct ctlname ipxname[] = CTL_IPXPROTO_NAMES; 1732struct ctlname ipxpname[] = IPXCTL_NAMES; 1733struct ctlname spxpname[] = SPXCTL_NAMES; 1734struct list ipxlist = { ipxname, IPXCTL_MAXID }; 1735struct list ipxvars[] = { 1736 { ipxpname, IPXCTL_MAXID }, /* ipx */ 1737 { 0, 0 }, 1738 { 0, 0 }, 1739 { 0, 0 }, 1740 { 0, 0 }, 1741 { spxpname, SPXCTL_MAXID }, 1742}; 1743 1744/* 1745 * Handle internet requests 1746 */ 1747int 1748sysctl_ipx(string, bufpp, mib, flags, typep) 1749 char *string; 1750 char **bufpp; 1751 int mib[]; 1752 int flags; 1753 int *typep; 1754{ 1755 struct list *lp; 1756 int indx; 1757 1758 if (*bufpp == NULL) { 1759 listall(string, &ipxlist); 1760 return(-1); 1761 } 1762 if ((indx = findname(string, "third", bufpp, &ipxlist)) == -1) 1763 return(-1); 1764 mib[2] = indx; 1765 if (indx <= IPXPROTO_SPX && ipxvars[indx].list != NULL) 1766 lp = &ipxvars[indx]; 1767 else if (!flags) 1768 return(-1); 1769 else { 1770 warnx("%s: no variables defined for this protocol", string); 1771 return(-1); 1772 } 1773 if (*bufpp == NULL) { 1774 listall(string, lp); 1775 return(-1); 1776 } 1777 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 1778 return(-1); 1779 mib[3] = indx; 1780 *typep = lp->list[indx].ctl_type; 1781 return(4); 1782} 1783 1784/* 1785 * Scan a list of names searching for a particular name. 1786 */ 1787int 1788findname(string, level, bufp, namelist) 1789 char *string; 1790 char *level; 1791 char **bufp; 1792 struct list *namelist; 1793{ 1794 char *name; 1795 int i; 1796 1797 if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { 1798 warnx("%s: incomplete specification", string); 1799 return(-1); 1800 } 1801 for (i = 0; i < namelist->size; i++) 1802 if (namelist->list[i].ctl_name != NULL && 1803 strcmp(name, namelist->list[i].ctl_name) == 0) 1804 break; 1805 if (i == namelist->size) { 1806 warnx("%s level name %s in %s is invalid", level, name, string); 1807 return(-1); 1808 } 1809 return(i); 1810} 1811 1812void 1813usage() 1814{ 1815 1816 (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n", 1817 "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...", 1818 "sysctl [-n] -a", "sysctl [-n] -A"); 1819 exit(1); 1820} 1821