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