sysctl.c revision 1.43
1/* $OpenBSD: sysctl.c,v 1.43 1999/12/10 10:12:56 itojun 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.43 1999/12/10 10:12:56 itojun 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 <vm/vm_param.h> 58#include <machine/cpu.h> 59#include <net/route.h> 60 61#include <netinet/in.h> 62#include <netinet/in_systm.h> 63#include <netinet/ip.h> 64#include <netinet/in_pcb.h> 65#include <netinet/ip_icmp.h> 66#include <netinet/ip_ip4.h> 67#include <netinet/ip_ether.h> 68#include <netinet/ip_ah.h> 69#include <netinet/ip_esp.h> 70#include <netinet/icmp_var.h> 71#include <netinet/ip_var.h> 72#include <netinet/udp.h> 73#include <netinet/udp_var.h> 74#include <netinet/tcp.h> 75#include <netinet/tcp_timer.h> 76#include <netinet/tcp_var.h> 77 78#ifdef INET6 79#include <netinet6/ip6.h> 80#include <netinet6/icmp6.h> 81#include <netinet6/ip6_var.h> 82#include <netinet6/pim6_var.h> 83#endif 84 85#include <netipx/ipx.h> 86#include <netipx/ipx_var.h> 87#include <netipx/spx_var.h> 88#include <ddb/db_var.h> 89#include <dev/rndvar.h> 90 91#include <err.h> 92#include <errno.h> 93#include <stdio.h> 94#include <stdlib.h> 95#include <string.h> 96#include <ctype.h> 97 98#ifdef CPU_BIOS 99#include <machine/biosvar.h> 100#endif 101 102struct ctlname topname[] = CTL_NAMES; 103struct ctlname kernname[] = CTL_KERN_NAMES; 104struct ctlname vmname[] = CTL_VM_NAMES; 105struct ctlname fsname[] = CTL_FS_NAMES; 106struct ctlname netname[] = CTL_NET_NAMES; 107struct ctlname hwname[] = CTL_HW_NAMES; 108struct ctlname username[] = CTL_USER_NAMES; 109struct ctlname debugname[CTL_DEBUG_MAXID]; 110struct ctlname *vfsname; 111#ifdef CTL_MACHDEP_NAMES 112struct ctlname machdepname[] = CTL_MACHDEP_NAMES; 113#endif 114struct ctlname ddbname[] = CTL_DDB_NAMES; 115char names[BUFSIZ]; 116int lastused; 117 118struct list { 119 struct ctlname *list; 120 int size; 121}; 122struct list toplist = { topname, CTL_MAXID }; 123struct list secondlevel[] = { 124 { 0, 0 }, /* CTL_UNSPEC */ 125 { kernname, KERN_MAXID }, /* CTL_KERN */ 126 { vmname, VM_MAXID }, /* CTL_VM */ 127 { fsname, FS_MAXID }, /* CTL_FS */ 128 { netname, NET_MAXID }, /* CTL_NET */ 129 { 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */ 130 { hwname, HW_MAXID }, /* CTL_HW */ 131#ifdef CTL_MACHDEP_NAMES 132 { machdepname, CPU_MAXID }, /* CTL_MACHDEP */ 133#else 134 { 0, 0 }, /* CTL_MACHDEP */ 135#endif 136 { username, USER_MAXID }, /* CTL_USER_NAMES */ 137 { ddbname, DBCTL_MAXID }, /* CTL_DDB_NAMES */ 138 { 0, 0 }, /* CTL_VFS */ 139}; 140 141int Aflag, aflag, nflag, wflag; 142 143/* 144 * Variables requiring special processing. 145 */ 146#define CLOCK 0x00000001 147#define BOOTTIME 0x00000002 148#define CHRDEV 0x00000004 149#define BLKDEV 0x00000008 150#define RNDSTATS 0x00000010 151#define BADDYNAMIC 0x00000020 152#define BIOSGEO 0x00000040 153#define BIOSDEV 0x00000080 154#define MAJ2DEV 0x00000100 155#define UNSIGNED 0x00000200 156 157/* prototypes */ 158void debuginit __P((void)); 159void listall __P((char *, struct list *)); 160void parse __P((char *, int)); 161void parse_baddynamic __P((int *, size_t, char *, void **, size_t *, int, int)); 162void usage __P((void)); 163int findname __P((char *, char *, char **, struct list *)); 164int sysctl_inet __P((char *, char **, int *, int, int *)); 165#ifdef INET6 166int sysctl_inet6 __P((char *, char **, int *, int, int *)); 167#endif 168int sysctl_ipx __P((char *, char **, int *, int, int *)); 169int sysctl_fs __P((char *, char **, int *, int, int *)); 170int sysctl_bios __P((char *, char **, int *, int, int *)); 171void vfsinit __P((void)); 172 173int 174main(argc, argv) 175 int argc; 176 char *argv[]; 177{ 178 int ch, lvl1; 179 180 while ((ch = getopt(argc, argv, "Aanw")) != -1) { 181 switch (ch) { 182 183 case 'A': 184 Aflag = 1; 185 break; 186 187 case 'a': 188 aflag = 1; 189 break; 190 191 case 'n': 192 nflag = 1; 193 break; 194 195 case 'w': 196 wflag = 1; 197 break; 198 199 default: 200 usage(); 201 } 202 } 203 argc -= optind; 204 argv += optind; 205 206 if (argc == 0 && (Aflag || aflag)) { 207 debuginit(); 208 vfsinit(); 209 for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++) 210 listall(topname[lvl1].ctl_name, &secondlevel[lvl1]); 211 exit(0); 212 } 213 if (argc == 0) 214 usage(); 215 for (; *argv != NULL; ++argv) 216 parse(*argv, 1); 217 exit(0); 218} 219 220/* 221 * List all variables known to the system. 222 */ 223void 224listall(prefix, lp) 225 char *prefix; 226 struct list *lp; 227{ 228 int lvl2; 229 char *cp, name[BUFSIZ]; 230 231 if (lp->list == NULL) 232 return; 233 (void)strncpy(name, prefix, BUFSIZ-1); 234 name[BUFSIZ-1] = '\0'; 235 cp = &name[strlen(name)]; 236 *cp++ = '.'; 237 for (lvl2 = 0; lvl2 < lp->size; lvl2++) { 238 if (lp->list[lvl2].ctl_name == NULL) 239 continue; 240 (void)strcpy(cp, lp->list[lvl2].ctl_name); 241 parse(name, Aflag); 242 } 243} 244 245/* 246 * Parse a name into a MIB entry. 247 * Lookup and print out the MIB entry if it exists. 248 * Set a new value if requested. 249 */ 250void 251parse(string, flags) 252 char *string; 253 int flags; 254{ 255 int indx, type, state, intval; 256 size_t size, len, newsize = 0; 257 int special = 0; 258 void *newval = 0; 259 quad_t quadval; 260 struct list *lp; 261 struct vfsconf vfc; 262 int mib[CTL_MAXNAME]; 263 char *cp, *bufp, buf[BUFSIZ]; 264 265 (void)strncpy(buf, string, sizeof(buf) - 1); 266 buf[sizeof(buf) - 1] = '\0'; 267 bufp = buf; 268 if ((cp = strchr(string, '=')) != NULL) { 269 if (!wflag) 270 errx(2, "must specify -w to set variables"); 271 *strchr(buf, '=') = '\0'; 272 *cp++ = '\0'; 273 while (isspace(*cp)) 274 cp++; 275 newval = cp; 276 newsize = strlen(cp); 277 } 278 if ((indx = findname(string, "top", &bufp, &toplist)) == -1) 279 return; 280 mib[0] = indx; 281 if (indx == CTL_VFS) 282 vfsinit(); 283 if (indx == CTL_DEBUG) 284 debuginit(); 285 lp = &secondlevel[indx]; 286 if (lp->list == 0) { 287 warnx("%s: class is not implemented", topname[indx].ctl_name); 288 return; 289 } 290 if (bufp == NULL) { 291 listall(topname[indx].ctl_name, lp); 292 return; 293 } 294 if ((indx = findname(string, "second", &bufp, lp)) == -1) 295 return; 296 mib[1] = indx; 297 type = lp->list[indx].ctl_type; 298 len = 2; 299 switch (mib[0]) { 300 301 case CTL_KERN: 302 switch (mib[1]) { 303 case KERN_PROF: 304 mib[2] = GPROF_STATE; 305 size = sizeof(state); 306 if (sysctl(mib, 3, &state, &size, NULL, 0) == -1) { 307 if (flags == 0) 308 return; 309 if (!nflag) 310 (void)printf("%s: ", string); 311 (void)puts("kernel is not compiled for profiling"); 312 return; 313 } 314 if (!nflag) 315 (void)printf("%s = %s\n", string, 316 state == GMON_PROF_OFF ? "off" : "running"); 317 return; 318 case KERN_VNODE: 319 case KERN_FILE: 320 if (flags == 0) 321 return; 322 warnx("use pstat to view %s information", string); 323 return; 324 case KERN_PROC: 325 if (flags == 0) 326 return; 327 warnx("use ps to view %s information", string); 328 return; 329 case KERN_NTPTIME: 330 if (flags == 0) 331 return; 332 warnx("use xntpdc to view %s information", string); 333 return; 334 case KERN_CLOCKRATE: 335 special |= CLOCK; 336 break; 337 case KERN_BOOTTIME: 338 special |= BOOTTIME; 339 break; 340 case KERN_RND: 341 special |= RNDSTATS; 342 break; 343 case KERN_HOSTID: 344 case KERN_ARND: 345 special |= UNSIGNED; 346 break; 347 } 348 break; 349 350 case CTL_HW: 351 break; 352 353 case CTL_VM: 354 if (mib[1] == VM_LOADAVG) { 355 double loads[3]; 356 357 getloadavg(loads, 3); 358 if (!nflag) 359 (void)printf("%s = ", string); 360 (void)printf("%.2f %.2f %.2f\n", loads[0], 361 loads[1], loads[2]); 362 return; 363 } else if (mib[1] == VM_PSSTRINGS) { 364 struct _ps_strings _ps; 365 366 len = sizeof(_ps); 367 if (sysctl(mib, 2, &_ps, &len, NULL, 0) == -1) { 368 if (flags == 0) 369 return; 370 if (!nflag) 371 (void)printf("%s: ", string); 372 (void)puts("can't find ps strings"); 373 return; 374 } 375 if (!nflag) 376 (void)printf("%s = ", string); 377 (void)printf("%p\n", _ps.val); 378 return; 379 } 380 if (flags == 0) 381 return; 382 warnx("use vmstat or systat to view %s information", string); 383 return; 384 385 case CTL_NET: 386 if (mib[1] == PF_INET) { 387 len = sysctl_inet(string, &bufp, mib, flags, &type); 388 if (len < 0) 389 return; 390 391 if ((mib[2] == IPPROTO_TCP && 392 mib[3] == TCPCTL_BADDYNAMIC) || 393 (mib[2] == IPPROTO_UDP && 394 mib[3] == UDPCTL_BADDYNAMIC)) { 395 396 special |= BADDYNAMIC; 397 398 if (newval != NULL) 399 parse_baddynamic(mib, len, string, 400 &newval, &newsize, flags, nflag); 401 } 402 break; 403 } 404#ifdef INET6 405 if (mib[1] == PF_INET6) { 406 len = sysctl_inet6(string, &bufp, mib, flags, &type); 407 if (len < 0) 408 return; 409 410 break; 411 } 412#endif 413 if (mib[1] == PF_IPX) { 414 len = sysctl_ipx(string, &bufp, mib, flags, &type); 415 if (len >= 0) 416 break; 417 return; 418 } 419 if (flags == 0) 420 return; 421 warnx("use netstat to view %s information", string); 422 return; 423 424 case CTL_DEBUG: 425 mib[2] = CTL_DEBUG_VALUE; 426 len = 3; 427 break; 428 429 case CTL_MACHDEP: 430#ifdef CPU_CONSDEV 431 if (mib[1] == CPU_CONSDEV) 432 special |= CHRDEV; 433#endif 434#ifdef CPU_BLK2CHR 435 if (mib[1] == CPU_BLK2CHR) { 436 if (bufp == NULL) 437 return; 438 mib[2] = makedev(atoi(bufp),0); 439 bufp = NULL; 440 len = 3; 441 special |= CHRDEV; 442 break; 443 } 444#endif 445#ifdef CPU_CHR2BLK 446 if (mib[1] == CPU_CHR2BLK) { 447 if (bufp == NULL) 448 return; 449 mib[2] = makedev(atoi(bufp),0); 450 bufp = NULL; 451 len = 3; 452 special |= BLKDEV; 453 break; 454 } 455#endif 456#ifdef CPU_BIOS 457 if (mib[1] == CPU_BIOS) { 458 len = sysctl_bios(string, &bufp, mib, flags, &type); 459 if (len < 0) 460 return; 461 if (mib[2] == BIOS_DEV) 462 special |= BIOSDEV; 463 if (mib[2] == BIOS_DISKINFO) 464 special |= BIOSGEO; 465 break; 466 } 467#endif 468 break; 469 470 case CTL_FS: 471 len = sysctl_fs(string, &bufp, mib, flags, &type); 472 if (len >= 0) 473 break; 474 return; 475 476 case CTL_VFS: 477 mib[3] = mib[1]; 478 mib[1] = VFS_GENERIC; 479 mib[2] = VFS_CONF; 480 len = 4; 481 size = sizeof vfc; 482 if (sysctl(mib, 4, &vfc, &size, (void *)0, (size_t)0) < 0) { 483 if (errno != EOPNOTSUPP) 484 perror("vfs print"); 485 return; 486 } 487 if (flags == 0 && vfc.vfc_refcount == 0) 488 return; 489 if (!nflag) 490 fprintf(stdout, "%s has %d mounted instance%s\n", 491 string, vfc.vfc_refcount, 492 vfc.vfc_refcount != 1 ? "s" : ""); 493 else 494 fprintf(stdout, "%d\n", vfc.vfc_refcount); 495 return; 496 497 case CTL_USER: 498 case CTL_DDB: 499 break; 500 501 default: 502 warnx("illegal top level value: %d", mib[0]); 503 return; 504 505 } 506 if (bufp) { 507 warnx("name %s in %s is unknown", bufp, string); 508 return; 509 } 510 if (newsize > 0) { 511 switch (type) { 512 case CTLTYPE_INT: 513 errno = 0; 514 if (special & UNSIGNED) 515 intval = strtoul(newval, &cp, 10); 516 else 517 intval = strtol(newval, &cp, 10); 518 if (*cp != '\0') { 519 warnx("%s: illegal value: %s", string, 520 (char *)newval); 521 return; 522 } 523 if (errno == ERANGE) { 524 warnx("%s: value %s out of range", string, 525 (char *)newval); 526 return; 527 } 528 newval = &intval; 529 newsize = sizeof(intval); 530 break; 531 532 case CTLTYPE_QUAD: 533 (void)sscanf(newval, "%qd", &quadval); 534 newval = &quadval; 535 newsize = sizeof(quadval); 536 break; 537 } 538 } 539 size = BUFSIZ; 540 if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) { 541 if (flags == 0) 542 return; 543 switch (errno) { 544 case EOPNOTSUPP: 545 warnx("%s: value is not available", string); 546 return; 547 case ENOTDIR: 548 warnx("%s: specification is incomplete", string); 549 return; 550 case ENOMEM: 551 warnx("%s: type is unknown to this program", string); 552 return; 553 case ENXIO: 554 if (special & BIOSGEO) 555 return; 556 default: 557 warn(string); 558 return; 559 } 560 } 561 if (special & CLOCK) { 562 struct clockinfo *clkp = (struct clockinfo *)buf; 563 564 if (!nflag) 565 (void)printf("%s = ", string); 566 (void)printf( 567 "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n", 568 clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz); 569 return; 570 } 571 if (special & BOOTTIME) { 572 struct timeval *btp = (struct timeval *)buf; 573 time_t boottime; 574 575 if (!nflag) { 576 boottime = btp->tv_sec; 577 (void)printf("%s = %s", string, ctime(&boottime)); 578 } else 579 (void)printf("%ld\n", btp->tv_sec); 580 return; 581 } 582 if (special & BLKDEV) { 583 dev_t dev = *(dev_t *)buf; 584 585 if (!nflag) 586 (void)printf("%s = %s\n", string, 587 devname(dev, S_IFBLK)); 588 else 589 (void)printf("0x%x\n", dev); 590 return; 591 } 592 if (special & CHRDEV) { 593 dev_t dev = *(dev_t *)buf; 594 595 if (!nflag) 596 (void)printf("%s = %s\n", string, 597 devname(dev, S_IFCHR)); 598 else 599 (void)printf("0x%x\n", dev); 600 return; 601 } 602#ifdef CPU_BIOS 603 if (special & BIOSGEO) { 604 bios_diskinfo_t *pdi = (bios_diskinfo_t *)buf; 605 606 if (!nflag) 607 (void)printf("%s = ", string); 608 (void)printf("bootdev = 0x%x, " 609 "cylinders = %u, heads = %u, sectors = %u\n", 610 pdi->bsd_dev, pdi->bios_cylinders, pdi->bios_heads, 611 pdi->bios_sectors); 612 return; 613 } 614 if (special & BIOSDEV) { 615 int dev = *(int*)buf; 616 617 if (!nflag) 618 (void)printf("%s = ", string); 619 (void) printf("0x%02x\n", dev); 620 return; 621 } 622#endif 623 if (special & UNSIGNED) { 624 if (newsize == 0) { 625 if (!nflag) 626 (void)printf("%s = ", string); 627 (void)printf("%u\n", *(u_int *)buf); 628 } else { 629 if (!nflag) 630 (void)printf("%s: %u -> ", string, 631 *(u_int *)buf); 632 (void)printf("%u\n", *(u_int *)newval); 633 } 634 return; 635 } 636 if (special & RNDSTATS) { 637 struct rndstats *rndstats = (struct rndstats *)buf; 638 639 if (!nflag) 640 (void)printf("%s = ", string); 641 (void)printf( 642 "%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u\n", 643 rndstats->rnd_total, rndstats->rnd_used, 644 rndstats->arc4_reads, rndstats->rnd_timer, 645 rndstats->rnd_mouse, rndstats->rnd_tty, 646 rndstats->rnd_disk, rndstats->rnd_net, 647 rndstats->rnd_reads, rndstats->rnd_waits, 648 rndstats->rnd_enqs, rndstats->rnd_deqs, 649 rndstats->rnd_drops, rndstats->rnd_drople, 650 rndstats->rnd_asleep, rndstats->rnd_queued); 651 return; 652 } 653 if (special & BADDYNAMIC) { 654 in_port_t port, lastport; 655 u_int32_t *baddynamic = (u_int32_t *)buf; 656 657 if (!nflag) 658 (void)printf("%s%s", string, newsize ? ": " : " = "); 659 lastport = 0; 660 for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED; port++) 661 if (DP_ISSET(baddynamic, port)) { 662 (void)printf("%s%hd", lastport ? "," : "", 663 port); 664 lastport = port; 665 } 666 if (newsize != 0) { 667 if (!nflag) 668 fputs(" -> ", stdout); 669 baddynamic = (u_int32_t *)newval; 670 lastport = 0; 671 for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED; 672 port++) 673 if (DP_ISSET(baddynamic, port)) { 674 (void)printf("%s%hd", 675 lastport ? "," : "", port); 676 lastport = port; 677 } 678 } 679 (void)putchar('\n'); 680 return; 681 } 682 switch (type) { 683 case CTLTYPE_INT: 684 if (newsize == 0) { 685 if (!nflag) 686 (void)printf("%s = ", string); 687 (void)printf("%d\n", *(int *)buf); 688 } else { 689 if (!nflag) 690 (void)printf("%s: %d -> ", string, 691 *(int *)buf); 692 (void)printf("%d\n", *(int *)newval); 693 } 694 return; 695 696 case CTLTYPE_STRING: 697 if (newsize == 0) { 698 if (!nflag) 699 (void)printf("%s = ", string); 700 (void)puts(buf); 701 } else { 702 if (!nflag) 703 (void)printf("%s: %s -> ", string, buf); 704 (void)puts((char *)newval); 705 } 706 return; 707 708 case CTLTYPE_QUAD: 709 if (newsize == 0) { 710 if (!nflag) 711 (void)printf("%s = ", string); 712 (void)printf("%qd\n", *(quad_t *)buf); 713 } else { 714 if (!nflag) 715 (void)printf("%s: %qd -> ", string, 716 *(quad_t *)buf); 717 (void)printf("%qd\n", *(quad_t *)newval); 718 } 719 return; 720 721 case CTLTYPE_STRUCT: 722 warnx("%s: unknown structure returned", string); 723 return; 724 725 default: 726 case CTLTYPE_NODE: 727 warnx("%s: unknown type returned", string); 728 return; 729 } 730} 731 732void 733parse_baddynamic(mib, len, string, newvalp, newsizep, flags, nflag) 734 int mib[]; 735 size_t len; 736 char *string; 737 void **newvalp; 738 size_t *newsizep; 739 int flags; 740 int nflag; 741{ 742 static u_int32_t newbaddynamic[DP_MAPSIZE]; 743 in_port_t port; 744 size_t size; 745 char action, *cp; 746 747 if (strchr((char *)*newvalp, '+') || strchr((char *)*newvalp, '-')) { 748 size = sizeof(newbaddynamic); 749 if (sysctl(mib, len, newbaddynamic, &size, 0, 0) == -1) { 750 if (flags == 0) 751 return; 752 if (!nflag) 753 (void)printf("%s: ", string); 754 (void)puts("kernel does contain bad dynamic port tables"); 755 return; 756 } 757 758 while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) { 759 if (*cp != '+' && *cp != '-') 760 errx(1, "cannot mix +/- with full list"); 761 action = *cp++; 762 port = atoi(cp); 763 if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED) 764 errx(1, "invalid port, range is %d to %d", 765 IPPORT_RESERVED/2, IPPORT_RESERVED-1); 766 if (action == '+') 767 DP_SET(newbaddynamic, port); 768 else 769 DP_CLR(newbaddynamic, port); 770 } 771 } else { 772 (void)memset((void *)newbaddynamic, 0, sizeof(newbaddynamic)); 773 while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) { 774 port = atoi(cp); 775 if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED) 776 errx(1, "invalid port, range is %d to %d", 777 IPPORT_RESERVED/2, IPPORT_RESERVED-1); 778 DP_SET(newbaddynamic, port); 779 } 780 } 781 782 *newvalp = (void *)newbaddynamic; 783 *newsizep = sizeof(newbaddynamic); 784} 785 786/* 787 * Initialize the set of debugging names 788 */ 789void 790debuginit() 791{ 792 int mib[3], loc, i; 793 size_t size; 794 795 if (secondlevel[CTL_DEBUG].list != 0) 796 return; 797 secondlevel[CTL_DEBUG].list = debugname; 798 mib[0] = CTL_DEBUG; 799 mib[2] = CTL_DEBUG_NAME; 800 for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) { 801 mib[1] = i; 802 size = BUFSIZ - loc; 803 if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1) 804 continue; 805 debugname[i].ctl_name = &names[loc]; 806 debugname[i].ctl_type = CTLTYPE_INT; 807 loc += size; 808 } 809 lastused = loc; 810} 811 812/* 813 * Initialize the set of filesystem names 814 */ 815void 816vfsinit() 817{ 818 int mib[4], maxtypenum, cnt, loc, size; 819 struct vfsconf vfc; 820 size_t buflen; 821 822 if (secondlevel[CTL_VFS].list != 0) 823 return; 824 mib[0] = CTL_VFS; 825 mib[1] = VFS_GENERIC; 826 mib[2] = VFS_MAXTYPENUM; 827 buflen = 4; 828 if (sysctl(mib, 3, &maxtypenum, &buflen, (void *)0, (size_t)0) < 0) 829 return; 830 if ((vfsname = malloc(maxtypenum * sizeof(*vfsname))) == 0) 831 return; 832 memset(vfsname, 0, maxtypenum * sizeof(*vfsname)); 833 mib[2] = VFS_CONF; 834 buflen = sizeof vfc; 835 for (loc = lastused, cnt = 0; cnt < maxtypenum; cnt++) { 836 mib[3] = cnt; 837 if (sysctl(mib, 4, &vfc, &buflen, (void *)0, (size_t)0) < 0) { 838 if (errno == EOPNOTSUPP) 839 continue; 840 perror("vfsinit"); 841 free(vfsname); 842 return; 843 } 844 strcat(&names[loc], vfc.vfc_name); 845 vfsname[cnt].ctl_name = &names[loc]; 846 vfsname[cnt].ctl_type = CTLTYPE_INT; 847 size = strlen(vfc.vfc_name) + 1; 848 loc += size; 849 } 850 lastused = loc; 851 secondlevel[CTL_VFS].list = vfsname; 852 secondlevel[CTL_VFS].size = maxtypenum; 853 return; 854} 855 856struct ctlname posixname[] = CTL_FS_POSIX_NAMES; 857struct list fslist = { posixname, FS_POSIX_MAXID }; 858 859/* 860 * handle file system requests 861 */ 862int 863sysctl_fs(string, bufpp, mib, flags, typep) 864 char *string; 865 char **bufpp; 866 int mib[]; 867 int flags; 868 int *typep; 869{ 870 int indx; 871 872 if (*bufpp == NULL) { 873 listall(string, &fslist); 874 return(-1); 875 } 876 if ((indx = findname(string, "third", bufpp, &fslist)) == -1) 877 return(-1); 878 mib[2] = indx; 879 *typep = fslist.list[indx].ctl_type; 880 return(3); 881} 882 883#ifdef CPU_BIOS 884struct ctlname biosname[] = CTL_BIOS_NAMES; 885struct list bioslist = { biosname, BIOS_MAXID }; 886 887/* 888 * handle BIOS requests 889 */ 890int 891sysctl_bios(string, bufpp, mib, flags, typep) 892 char *string; 893 char **bufpp; 894 int mib[]; 895 int flags; 896 int *typep; 897{ 898 char *name; 899 int indx; 900 901 if (*bufpp == NULL) { 902 listall(string, &bioslist); 903 return(-1); 904 } 905 if ((indx = findname(string, "third", bufpp, &bioslist)) == -1) 906 return(-1); 907 mib[2] = indx; 908 if (indx == BIOS_DISKINFO) { 909 if (*bufpp == NULL) { 910 char name[BUFSIZ]; 911 912 /* scan all the bios devices */ 913 for (indx = 0; indx < 256; indx++) { 914 snprintf(name, sizeof(name), "%s.%u", 915 string, indx); 916 parse(name, 1); 917 } 918 return(-1); 919 } 920 if ((name = strsep(bufpp, ".")) == NULL) { 921 warnx("%s: incomplete specification", string); 922 return(-1); 923 } 924 mib[3] = atoi(name); 925 *typep = CTLTYPE_STRUCT; 926 return 4; 927 } else { 928 *typep = bioslist.list[indx].ctl_type; 929 return(3); 930 } 931} 932#endif 933 934struct ctlname inetname[] = CTL_IPPROTO_NAMES; 935struct ctlname ipname[] = IPCTL_NAMES; 936struct ctlname icmpname[] = ICMPCTL_NAMES; 937struct ctlname ip4name[] = IP4CTL_NAMES; 938struct ctlname tcpname[] = TCPCTL_NAMES; 939struct ctlname udpname[] = UDPCTL_NAMES; 940struct ctlname espname[] = ESPCTL_NAMES; 941struct ctlname ahname[] = AHCTL_NAMES; 942struct ctlname etheripname[] = ETHERIPCTL_NAMES; 943struct list inetlist = { inetname, IPPROTO_MAXID }; 944struct list inetvars[] = { 945 { ipname, IPCTL_MAXID }, /* ip */ 946 { icmpname, ICMPCTL_MAXID }, /* icmp */ 947 { 0, 0 }, /* igmp */ 948 { 0, 0 }, /* ggmp */ 949 { ip4name, IP4CTL_MAXID }, /* ipencap */ 950 { 0, 0 }, 951 { tcpname, TCPCTL_MAXID }, /* tcp */ 952 { 0, 0 }, 953 { 0, 0 }, /* egp */ 954 { 0, 0 }, 955 { 0, 0 }, 956 { 0, 0 }, 957 { 0, 0 }, /* pup */ 958 { 0, 0 }, 959 { 0, 0 }, 960 { 0, 0 }, 961 { 0, 0 }, 962 { udpname, UDPCTL_MAXID }, /* udp */ 963 { 0, 0 }, 964 { 0, 0 }, 965 { 0, 0 }, 966 { 0, 0 }, 967 { 0, 0 }, 968 { 0, 0 }, 969 { 0, 0 }, 970 { 0, 0 }, 971 { 0, 0 }, 972 { 0, 0 }, 973 { 0, 0 }, 974 { 0, 0 }, 975 { 0, 0 }, 976 { 0, 0 }, 977 { 0, 0 }, 978 { 0, 0 }, 979 { 0, 0 }, 980 { 0, 0 }, 981 { 0, 0 }, 982 { 0, 0 }, 983 { 0, 0 }, 984 { 0, 0 }, 985 { 0, 0 }, 986 { 0, 0 }, 987 { 0, 0 }, 988 { 0, 0 }, 989 { 0, 0 }, 990 { 0, 0 }, 991 { 0, 0 }, 992 { 0, 0 }, 993 { 0, 0 }, 994 { 0, 0 }, 995 { espname, ESPCTL_MAXID }, /* esp */ 996 { ahname, AHCTL_MAXID }, /* ah */ 997 { 0, 0 }, 998 { 0, 0 }, 999 { 0, 0 }, 1000 { 0, 0 }, 1001 { 0, 0 }, 1002 { 0, 0 }, 1003 { 0, 0 }, 1004 { 0, 0 }, 1005 { 0, 0 }, 1006 { 0, 0 }, 1007 { 0, 0 }, 1008 { 0, 0 }, 1009 { 0, 0 }, 1010 { 0, 0 }, 1011 { 0, 0 }, 1012 { 0, 0 }, 1013 { 0, 0 }, 1014 { 0, 0 }, 1015 { 0, 0 }, 1016 { 0, 0 }, 1017 { 0, 0 }, 1018 { 0, 0 }, 1019 { 0, 0 }, 1020 { 0, 0 }, 1021 { 0, 0 }, 1022 { 0, 0 }, 1023 { 0, 0 }, 1024 { 0, 0 }, 1025 { 0, 0 }, 1026 { 0, 0 }, 1027 { 0, 0 }, 1028 { 0, 0 }, 1029 { 0, 0 }, 1030 { 0, 0 }, 1031 { 0, 0 }, 1032 { 0, 0 }, 1033 { 0, 0 }, 1034 { 0, 0 }, 1035 { 0, 0 }, 1036 { 0, 0 }, 1037 { 0, 0 }, 1038 { 0, 0 }, 1039 { 0, 0 }, 1040 { 0, 0 }, 1041 { 0, 0 }, 1042 { etheripname, ETHERIPCTL_MAXID }, 1043}; 1044 1045/* 1046 * handle internet requests 1047 */ 1048int 1049sysctl_inet(string, bufpp, mib, flags, typep) 1050 char *string; 1051 char **bufpp; 1052 int mib[]; 1053 int flags; 1054 int *typep; 1055{ 1056 struct list *lp; 1057 int indx; 1058 1059 if (*bufpp == NULL) { 1060 listall(string, &inetlist); 1061 return(-1); 1062 } 1063 if ((indx = findname(string, "third", bufpp, &inetlist)) == -1) 1064 return(-1); 1065 mib[2] = indx; 1066 if (indx < IPPROTO_MAXID && inetvars[indx].list != NULL) 1067 lp = &inetvars[indx]; 1068 else if (!flags) 1069 return(-1); 1070 else { 1071 warnx("%s: no variables defined for this protocol", string); 1072 return(-1); 1073 } 1074 if (*bufpp == NULL) { 1075 listall(string, lp); 1076 return(-1); 1077 } 1078 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 1079 return(-1); 1080 mib[3] = indx; 1081 *typep = lp->list[indx].ctl_type; 1082 return(4); 1083} 1084 1085#ifdef INET6 1086struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES; 1087struct ctlname ip6name[] = IPV6CTL_NAMES; 1088struct ctlname icmp6name[] = ICMPV6CTL_NAMES; 1089struct ctlname pim6name[] = PIMCTL_NAMES; 1090struct list inet6list = { inet6name, IPV6PROTO_MAXID }; 1091struct list inet6vars[] = { 1092/*0*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1093 { 0, 0 }, 1094 { 0, 0 }, 1095 { 0, 0 }, 1096 { 0, 0 }, 1097 { 0, 0 }, 1098/*10*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1099 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1100/*20*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1101 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1102/*30*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1103 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1104/*40*/ { 0, 0 }, 1105 { ip6name, IPV6CTL_MAXID }, /* ipv6 */ 1106 { 0, 0 }, 1107 { 0, 0 }, 1108 { 0, 0 }, 1109 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1110/*50*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1111 { 0, 0 }, 1112 { 0, 0 }, 1113 { 0, 0 }, 1114 { icmp6name, ICMPV6CTL_MAXID }, /* icmp6 */ 1115 { 0, 0 }, 1116/*60*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1117 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1118/*70*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1119 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1120/*80*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1121 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1122/*90*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1123 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 1124/*100*/ { 0, 0 }, 1125 { 0, 0 }, 1126 { 0, 0 }, 1127 { pim6name, PIMCTL_MAXID }, /* pim6 */ 1128}; 1129 1130/* 1131 * handle internet6 requests 1132 */ 1133int 1134sysctl_inet6(string, bufpp, mib, flags, typep) 1135 char *string; 1136 char **bufpp; 1137 int mib[]; 1138 int flags; 1139 int *typep; 1140{ 1141 struct list *lp; 1142 int indx; 1143 1144 if (*bufpp == NULL) { 1145 listall(string, &inet6list); 1146 return(-1); 1147 } 1148 if ((indx = findname(string, "third", bufpp, &inet6list)) == -1) 1149 return(-1); 1150 mib[2] = indx; 1151 if (indx < IPV6PROTO_MAXID && inet6vars[indx].list != NULL) 1152 lp = &inet6vars[indx]; 1153 else if (!flags) 1154 return(-1); 1155 else { 1156 warnx("%s: no variables defined for this protocol", string); 1157 return(-1); 1158 } 1159 if (*bufpp == NULL) { 1160 listall(string, lp); 1161 return(-1); 1162 } 1163 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 1164 return(-1); 1165 mib[3] = indx; 1166 *typep = lp->list[indx].ctl_type; 1167 return(4); 1168} 1169#endif 1170 1171struct ctlname ipxname[] = CTL_IPXPROTO_NAMES; 1172struct ctlname ipxpname[] = IPXCTL_NAMES; 1173struct ctlname spxpname[] = SPXCTL_NAMES; 1174struct list ipxlist = { ipxname, IPXCTL_MAXID }; 1175struct list ipxvars[] = { 1176 { ipxpname, IPXCTL_MAXID }, /* ipx */ 1177 { 0, 0 }, 1178 { 0, 0 }, 1179 { 0, 0 }, 1180 { 0, 0 }, 1181 { spxpname, SPXCTL_MAXID }, 1182}; 1183 1184/* 1185 * Handle internet requests 1186 */ 1187int 1188sysctl_ipx(string, bufpp, mib, flags, typep) 1189 char *string; 1190 char **bufpp; 1191 int mib[]; 1192 int flags; 1193 int *typep; 1194{ 1195 struct list *lp; 1196 int indx; 1197 1198 if (*bufpp == NULL) { 1199 listall(string, &ipxlist); 1200 return(-1); 1201 } 1202 if ((indx = findname(string, "third", bufpp, &ipxlist)) == -1) 1203 return(-1); 1204 mib[2] = indx; 1205 if (indx <= IPXPROTO_SPX && ipxvars[indx].list != NULL) 1206 lp = &ipxvars[indx]; 1207 else if (!flags) 1208 return(-1); 1209 else { 1210 warnx("%s: no variables defined for this protocol", string); 1211 return(-1); 1212 } 1213 if (*bufpp == NULL) { 1214 listall(string, lp); 1215 return(-1); 1216 } 1217 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 1218 return(-1); 1219 mib[3] = indx; 1220 *typep = lp->list[indx].ctl_type; 1221 return(4); 1222} 1223 1224/* 1225 * Scan a list of names searching for a particular name. 1226 */ 1227int 1228findname(string, level, bufp, namelist) 1229 char *string; 1230 char *level; 1231 char **bufp; 1232 struct list *namelist; 1233{ 1234 char *name; 1235 int i; 1236 1237 if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { 1238 warnx("%s: incomplete specification", string); 1239 return(-1); 1240 } 1241 for (i = 0; i < namelist->size; i++) 1242 if (namelist->list[i].ctl_name != NULL && 1243 strcmp(name, namelist->list[i].ctl_name) == 0) 1244 break; 1245 if (i == namelist->size) { 1246 warnx("%s level name %s in %s is invalid", level, name, string); 1247 return(-1); 1248 } 1249 return(i); 1250} 1251 1252void 1253usage() 1254{ 1255 1256 (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n", 1257 "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...", 1258 "sysctl [-n] -a", "sysctl [-n] -A"); 1259 exit(1); 1260} 1261