1 /* $NetBSD: sysctl.c,v 1.61 2002/11/30 03:10:54 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 #ifndef lint 38 __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 45 static char sccsid[] = "@(#)sysctl.c 8.1 (Berkeley) 6/6/93"; 46 #else 47 __RCSID("$NetBSD: sysctl.c,v 1.61 2002/11/30 03:10:54 lukem Exp $"); 48 #endif 49 #endif /* not lint */ 50 51 #include <sys/param.h> 52 #include <sys/gmon.h> 53 #include <sys/stat.h> 54 #include <sys/sysctl.h> 55 #include <sys/socket.h> 56 #include <sys/mount.h> 57 #include <sys/mbuf.h> 58 #include <sys/resource.h> 59 #include <uvm/uvm_param.h> 60 #include <machine/cpu.h> 61 62 #include <ufs/ufs/dinode.h> 63 #include <ufs/ufs/dir.h> 64 #include <ufs/ffs/fs.h> 65 #include <ufs/ffs/ffs_extern.h> 66 67 #include <nfs/rpcv2.h> 68 #include <nfs/nfsproto.h> 69 #include <nfs/nfs.h> 70 71 #include <netinet/in.h> 72 #include <netinet/in_systm.h> 73 #include <netinet/ip.h> 74 #include <netinet/ip_icmp.h> 75 #include <netinet/icmp_var.h> 76 #include <netinet/ip_var.h> 77 #include <netinet/udp.h> 78 #include <netinet/udp_var.h> 79 #include <netinet/tcp.h> 80 #include <netinet/tcp_timer.h> 81 #include <netinet/tcp_var.h> 82 83 #ifdef INET6 84 #include <netinet/ip6.h> 85 #include <netinet/icmp6.h> 86 #include <netinet6/ip6_var.h> 87 #include <netinet6/udp6.h> 88 #include <netinet6/udp6_var.h> 89 #ifdef TCP6 90 #include <netinet6/tcp6.h> 91 #include <netinet6/tcp6_timer.h> 92 #include <netinet6/tcp6_var.h> 93 #endif 94 #include <netinet6/pim6_var.h> 95 #endif /* INET6 */ 96 97 #include "../../sys/compat/linux/common/linux_exec.h" 98 #include "../../sys/compat/irix/irix_sysctl.h" 99 100 #ifdef IPSEC 101 #include <net/route.h> 102 #include <netinet6/ipsec.h> 103 #include <netkey/key_var.h> 104 #endif /* IPSEC */ 105 106 #include <sys/pipe.h> 107 108 #include <err.h> 109 #include <ctype.h> 110 #include <errno.h> 111 #include <stdio.h> 112 #include <stdlib.h> 113 #include <string.h> 114 #include <unistd.h> 115 116 struct ctlname topname[] = CTL_NAMES; 117 struct ctlname kernname[] = CTL_KERN_NAMES; 118 struct ctlname vmname[] = CTL_VM_NAMES; 119 struct ctlname vfsname[] = CTL_VFS_NAMES; 120 struct ctlname netname[] = CTL_NET_NAMES; 121 struct ctlname hwname[] = CTL_HW_NAMES; 122 struct ctlname username[] = CTL_USER_NAMES; 123 struct ctlname ddbname[] = CTL_DDB_NAMES; 124 struct ctlname debugname[CTL_DEBUG_MAXID]; 125 #ifdef CTL_MACHDEP_NAMES 126 struct ctlname machdepname[] = CTL_MACHDEP_NAMES; 127 #endif 128 struct ctlname emulname[] = CTL_EMUL_NAMES; 129 struct ctlname vendorname[] = { { 0, 0 } }; 130 131 /* this one is dummy, it's used only for '-a' or '-A' */ 132 struct ctlname procname[] = { {0, 0}, {"curproc", CTLTYPE_NODE} }; 133 134 char names[BUFSIZ]; 135 136 struct list { 137 struct ctlname *list; 138 int size; 139 }; 140 struct list toplist = { topname, CTL_MAXID }; 141 struct list secondlevel[] = { 142 { 0, 0 }, /* CTL_UNSPEC */ 143 { kernname, KERN_MAXID }, /* CTL_KERN */ 144 { vmname, VM_MAXID }, /* CTL_VM */ 145 { vfsname, VFS_MAXID }, /* CTL_VFS */ 146 { netname, NET_MAXID }, /* CTL_NET */ 147 { 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */ 148 { hwname, HW_MAXID }, /* CTL_HW */ 149 #ifdef CTL_MACHDEP_NAMES 150 { machdepname, CPU_MAXID }, /* CTL_MACHDEP */ 151 #else 152 { 0, 0 }, /* CTL_MACHDEP */ 153 #endif 154 { username, USER_MAXID }, /* CTL_USER_NAMES */ 155 { ddbname, DDBCTL_MAXID }, /* CTL_DDB_NAMES */ 156 { procname, 2 }, /* dummy name */ 157 { vendorname, 0 }, /* CTL_VENDOR_NAMES */ 158 { emulname, EMUL_MAXID }, /* CTL_EMUL_NAMES */ 159 160 { 0, 0}, 161 }; 162 163 int Aflag, aflag, nflag, qflag, wflag; 164 165 /* 166 * Variables requiring special processing. 167 */ 168 #define CLOCK 0x00000001 169 #define BOOTTIME 0x00000002 170 #define CONSDEV 0x00000004 171 #define DISKINFO 0x00000008 172 #define CPTIME 0x00000010 173 174 /* 175 * A dummy type for limits, which requires special parsing 176 */ 177 #define CTLTYPE_LIMIT ((~0x1) << 31) 178 179 int main(int, char *[]); 180 181 static void listall(const char *, struct list *); 182 static void parse(char *, int); 183 static void debuginit(void); 184 static int sysctl_inet(char *, char **, int[], int, int *); 185 #ifdef INET6 186 static int sysctl_inet6(char *, char **, int[], int, int *); 187 #endif 188 static int sysctl_vfs(char *, char **, int[], int, int *); 189 static int sysctl_proc(char *, char **, int[], int, int *); 190 static int sysctl_3rd(struct list *, char *, char **, int[], int, int *); 191 192 #ifdef IPSEC 193 struct ctlname keynames[] = KEYCTL_NAMES; 194 struct list keyvars = { keynames, KEYCTL_MAXID }; 195 #endif /*IPSEC*/ 196 struct ctlname vfsgenname[] = CTL_VFSGENCTL_NAMES; 197 struct list vfsgenvars = { vfsgenname, VFSGEN_MAXID }; 198 struct ctlname mbufnames[] = CTL_MBUF_NAMES; 199 struct list mbufvars = { mbufnames, MBUF_MAXID }; 200 struct ctlname pipenames[] = CTL_PIPE_NAMES; 201 struct list pipevars = { pipenames, KERN_PIPE_MAXID }; 202 struct ctlname tkstatnames[] = KERN_TKSTAT_NAMES; 203 struct list tkstatvars = { tkstatnames, KERN_TKSTAT_MAXID }; 204 205 static int sysctl_linux(char *, char **, int[], int, int *); 206 static int sysctl_irix(char *, char **, int[], int, int *); 207 static int findname(char *, char *, char **, struct list *); 208 static void usage(void); 209 210 #define USEAPP(s, a) \ 211 if (flags) printf("%s: use '%s' to view this information\n", s, a) 212 213 214 int 215 main(int argc, char *argv[]) 216 { 217 char *fn = NULL; 218 int ch, lvl1; 219 220 while ((ch = getopt(argc, argv, "Aaf:nqw")) != -1) { 221 switch (ch) { 222 223 case 'A': 224 Aflag = 1; 225 break; 226 227 case 'a': 228 aflag = 1; 229 break; 230 231 case 'f': 232 fn = optarg; 233 wflag = 1; 234 break; 235 236 case 'n': 237 nflag = 1; 238 break; 239 240 case 'q': 241 qflag = 1; 242 break; 243 244 case 'w': 245 wflag = 1; 246 break; 247 248 default: 249 usage(); 250 } 251 } 252 253 if (qflag && !wflag) 254 usage(); 255 256 argc -= optind; 257 argv += optind; 258 259 if (Aflag || aflag) { 260 debuginit(); 261 for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++) 262 listall(topname[lvl1].ctl_name, &secondlevel[lvl1]); 263 return 0; 264 } 265 266 if (fn) { 267 FILE *fp; 268 char *l; 269 270 fp = fopen(fn, "r"); 271 if (fp == NULL) { 272 err(1, "%s", fn); 273 } else { 274 for (; (l = fparseln(fp, NULL, NULL, NULL, 0)) != NULL; 275 free(l)) { 276 if (*l) 277 parse(l, 1); 278 } 279 fclose(fp); 280 } 281 } else { 282 if (argc == 0) 283 usage(); 284 while (argc-- > 0) 285 parse(*argv++, 1); 286 } 287 return 0; 288 } 289 290 /* 291 * List all variables known to the system. 292 */ 293 static void 294 listall(const char *prefix, struct list *lp) 295 { 296 int lvl2; 297 char *cp, name[BUFSIZ]; 298 299 if (lp->list == 0) 300 return; 301 strcpy(name, prefix); 302 cp = &name[strlen(name)]; 303 *cp++ = '.'; 304 for (lvl2 = 0; lvl2 < lp->size; lvl2++) { 305 if (lp->list[lvl2].ctl_name == 0) 306 continue; 307 strcpy(cp, lp->list[lvl2].ctl_name); 308 parse(name, Aflag); 309 } 310 } 311 312 /* 313 * Parse a name into a MIB entry. 314 * Lookup and print out the MIB entry if it exists. 315 * Set a new value if requested. 316 */ 317 static void 318 parse(char *string, int flags) 319 { 320 int indx, type, state, len; 321 int special = 0; 322 void *newval = 0; 323 int intval, newsize = 0; 324 quad_t quadval; 325 size_t size; 326 struct list *lp; 327 int mib[CTL_MAXNAME]; 328 char *cp, *bufp, buf[BUFSIZ]; 329 double loads[3]; 330 331 bufp = buf; 332 snprintf(buf, BUFSIZ, "%s", string); 333 if ((cp = strchr(string, '=')) != NULL) { 334 if (!wflag) 335 errx(2, "Must specify -w to set variables"); 336 *strchr(buf, '=') = '\0'; 337 *cp++ = '\0'; 338 while (isspace((unsigned char) *cp)) 339 cp++; 340 newval = cp; 341 newsize = strlen(cp); 342 } 343 if ((indx = findname(string, "top", &bufp, &toplist)) == -1) 344 return; 345 mib[0] = indx; 346 if (indx == CTL_DEBUG) 347 debuginit(); 348 if (mib[0] == CTL_PROC) { 349 type = CTLTYPE_NODE; 350 len = 1; 351 } else { 352 lp = &secondlevel[indx]; 353 if (lp->list == 0) { 354 warnx("Class `%s' is not implemented", 355 topname[indx].ctl_name); 356 return; 357 } 358 if (bufp == NULL) { 359 listall(topname[indx].ctl_name, lp); 360 return; 361 } 362 if ((indx = findname(string, "second", &bufp, lp)) == -1) 363 return; 364 mib[1] = indx; 365 type = lp->list[indx].ctl_type; 366 len = 2; 367 } 368 switch (mib[0]) { 369 370 case CTL_KERN: 371 switch (mib[1]) { 372 case KERN_PROF: 373 mib[2] = GPROF_STATE; 374 size = sizeof state; 375 if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) { 376 if (flags == 0) 377 return; 378 if (!nflag) 379 printf("%s: ", string); 380 printf( 381 "kernel is not compiled for profiling\n"); 382 return; 383 } 384 if (!nflag) 385 printf("%s: %s\n", string, 386 state == GMON_PROF_OFF ? "off" : "running"); 387 return; 388 case KERN_VNODE: 389 case KERN_FILE: 390 USEAPP(string, "pstat"); 391 return; 392 case KERN_PROC: 393 case KERN_PROC2: 394 case KERN_PROC_ARGS: 395 USEAPP(string, "ps"); 396 return; 397 case KERN_CLOCKRATE: 398 special |= CLOCK; 399 break; 400 case KERN_BOOTTIME: 401 special |= BOOTTIME; 402 break; 403 case KERN_NTPTIME: 404 USEAPP(string, "ntpdc -c kerninfo"); 405 return; 406 case KERN_MBUF: 407 len = sysctl_3rd(&mbufvars, string, &bufp, mib, flags, 408 &type); 409 if (len < 0) 410 return; 411 break; 412 case KERN_CP_TIME: 413 special |= CPTIME; 414 break; 415 case KERN_MSGBUF: 416 USEAPP(string, "dmesg"); 417 return; 418 case KERN_CONSDEV: 419 special |= CONSDEV; 420 break; 421 case KERN_PIPE: 422 len = sysctl_3rd(&pipevars, string, &bufp, mib, flags, 423 &type); 424 if (len < 0) 425 return; 426 break; 427 case KERN_TKSTAT: 428 len = sysctl_3rd(&tkstatvars, string, &bufp, mib, flags, 429 &type); 430 if (len < 0) 431 return; 432 break; 433 } 434 break; 435 436 case CTL_HW: 437 switch (mib[1]) { 438 case HW_DISKSTATS: 439 USEAPP(string, "iostat"); 440 return; 441 } 442 break; 443 444 case CTL_VM: 445 switch (mib[1]) { 446 case VM_LOADAVG: 447 getloadavg(loads, 3); 448 if (!nflag) 449 printf("%s: ", string); 450 printf("%.2f %.2f %.2f\n", loads[0], loads[1], 451 loads[2]); 452 return; 453 454 case VM_METER: 455 case VM_UVMEXP: 456 case VM_UVMEXP2: 457 USEAPP(string, "vmstat' or 'systat"); 458 return; 459 } 460 break; 461 462 case CTL_NET: 463 if (mib[1] == PF_INET) { 464 len = sysctl_inet(string, &bufp, mib, flags, &type); 465 if (len >= 0) 466 break; 467 return; 468 } 469 #ifdef INET6 470 else if (mib[1] == PF_INET6) { 471 len = sysctl_inet6(string, &bufp, mib, flags, &type); 472 if (len >= 0) 473 break; 474 return; 475 } 476 #endif /* INET6 */ 477 #ifdef IPSEC 478 else if (mib[1] == PF_KEY) { 479 len = sysctl_3rd(&keyvars, string, &bufp, mib, flags, 480 &type); 481 if (len >= 0) 482 break; 483 return; 484 } 485 #endif /* IPSEC */ 486 if (flags == 0) 487 return; 488 USEAPP(string, "netstat"); 489 return; 490 491 case CTL_DEBUG: 492 mib[2] = CTL_DEBUG_VALUE; 493 len = 3; 494 break; 495 496 case CTL_MACHDEP: 497 #ifdef CPU_CONSDEV 498 if (mib[1] == CPU_CONSDEV) 499 special |= CONSDEV; 500 #endif 501 #ifdef CPU_DISKINFO 502 if (mib[1] == CPU_DISKINFO) 503 special |= DISKINFO; 504 #endif 505 break; 506 507 case CTL_VFS: 508 if (mib[1] == VFS_GENERIC) { 509 len = sysctl_3rd(&vfsgenvars, string, &bufp, mib, flags, 510 &type); 511 /* Don't bother with VFS_CONF. */ 512 if (mib[2] == VFS_CONF) 513 len = -1; 514 } else 515 len = sysctl_vfs(string, &bufp, mib, flags, &type); 516 if (len < 0) 517 return; 518 519 /* XXX Special-case for NFS stats. */ 520 if (mib[1] == 2 && mib[2] == NFS_NFSSTATS) { 521 USEAPP(string, "nfsstat"); 522 return; 523 } 524 break; 525 526 case CTL_VENDOR: 527 case CTL_USER: 528 case CTL_DDB: 529 break; 530 case CTL_PROC: 531 len = sysctl_proc(string, &bufp, mib, flags, &type); 532 if (len < 0) 533 return; 534 break; 535 case CTL_EMUL: 536 switch (mib[1]) { 537 case EMUL_IRIX: 538 len = sysctl_irix(string, &bufp, mib, flags, &type); 539 break; 540 case EMUL_LINUX: 541 len = sysctl_linux(string, &bufp, mib, flags, &type); 542 break; 543 default: 544 warnx("Illegal emul level value: %d", mib[0]); 545 break; 546 } 547 if (len < 0) 548 return; 549 break; 550 default: 551 warnx("Illegal top level value: %d", mib[0]); 552 return; 553 554 } 555 if (bufp) { 556 warnx("Name %s in %s is unknown", bufp, string); 557 return; 558 } 559 if (newsize > 0) { 560 switch (type) { 561 case CTLTYPE_INT: 562 intval = atoi(newval); 563 newval = &intval; 564 newsize = sizeof intval; 565 break; 566 567 case CTLTYPE_LIMIT: 568 if (strcmp(newval, "unlimited") == 0) { 569 quadval = RLIM_INFINITY; 570 newval = &quadval; 571 newsize = sizeof quadval; 572 break; 573 } 574 /* FALLTHROUGH */ 575 case CTLTYPE_QUAD: 576 sscanf(newval, "%lld", (long long *)&quadval); 577 newval = &quadval; 578 newsize = sizeof quadval; 579 break; 580 } 581 } 582 size = BUFSIZ; 583 if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) { 584 if (flags == 0) 585 return; 586 switch (errno) { 587 case EOPNOTSUPP: 588 printf("%s: the value is not available\n", string); 589 return; 590 case ENOTDIR: 591 printf("%s: the specification is incomplete\n", string); 592 return; 593 case ENOMEM: 594 printf("%s: this type is unknown to this program\n", 595 string); 596 return; 597 default: 598 printf("%s: sysctl() failed with %s\n", 599 string, strerror(errno)); 600 return; 601 } 602 } 603 if (qflag && (newsize > 0)) 604 return; 605 if (special & CLOCK) { 606 struct clockinfo *clkp = (struct clockinfo *)buf; 607 608 if (!nflag) 609 printf("%s: ", string); 610 printf( 611 "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n", 612 clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz); 613 return; 614 } 615 if (special & BOOTTIME) { 616 struct timeval *btp = (struct timeval *)buf; 617 time_t boottime; 618 619 if (!nflag) { 620 boottime = btp->tv_sec; 621 /* ctime() provides the trailing newline */ 622 printf("%s = %s", string, ctime(&boottime)); 623 } else 624 printf("%ld\n", (long) btp->tv_sec); 625 return; 626 } 627 if (special & CONSDEV) { 628 dev_t dev = *(dev_t *)buf; 629 630 if (!nflag) 631 printf("%s = %s\n", string, devname(dev, S_IFCHR)); 632 else 633 printf("0x%x\n", dev); 634 return; 635 } 636 if (special & DISKINFO) { 637 /* Don't know a good way to deal with this i386 specific one */ 638 return; 639 } 640 if (special & CPTIME) { 641 u_int64_t *cp_time = (u_int64_t *)buf; 642 643 if (!nflag) 644 printf("%s: ", string); 645 printf("user = %llu, nice = %llu, sys = %llu, intr = %llu, " 646 "idle = %llu\n", (unsigned long long) cp_time[0], 647 (unsigned long long) cp_time[1], 648 (unsigned long long) cp_time[2], 649 (unsigned long long) cp_time[3], 650 (unsigned long long) cp_time[4]); 651 return; 652 } 653 654 switch (type) { 655 case CTLTYPE_INT: 656 if (newsize == 0) { 657 if (!nflag) 658 printf("%s = ", string); 659 printf("%d\n", *(int *)buf); 660 } else { 661 if (!nflag) 662 printf("%s: %d -> ", string, *(int *)buf); 663 printf("%d\n", *(int *)newval); 664 } 665 return; 666 667 case CTLTYPE_STRING: 668 /* If sysctl() didn't return any data, don't print a string. */ 669 if (size == 0) 670 buf[0] = '\0'; 671 if (newsize == 0) { 672 if (!nflag) 673 printf("%s = ", string); 674 printf("%s\n", buf); 675 } else { 676 if (!nflag) 677 printf("%s: %s -> ", string, buf); 678 printf("%s\n", (char *) newval); 679 } 680 return; 681 682 case CTLTYPE_LIMIT: 683 #define PRINTF_LIMIT(lim) { \ 684 if ((lim) == RLIM_INFINITY) \ 685 printf("unlimited");\ 686 else \ 687 printf("%lld", (long long)(lim)); \ 688 } 689 690 if (newsize == 0) { 691 if (!nflag) 692 printf("%s = ", string); 693 PRINTF_LIMIT((long long)(*(quad_t *)buf)); 694 } else { 695 if (!nflag) { 696 printf("%s: ", string); 697 PRINTF_LIMIT((long long)(*(quad_t *)buf)); 698 printf(" -> "); 699 } 700 PRINTF_LIMIT((long long)(*(quad_t *)newval)); 701 } 702 printf("\n"); 703 return; 704 #undef PRINTF_LIMIT 705 706 case CTLTYPE_QUAD: 707 if (newsize == 0) { 708 if (!nflag) 709 printf("%s = ", string); 710 printf("%lld\n", (long long)(*(quad_t *)buf)); 711 } else { 712 if (!nflag) 713 printf("%s: %lld -> ", string, 714 (long long)(*(quad_t *)buf)); 715 printf("%lld\n", (long long)(*(quad_t *)newval)); 716 } 717 return; 718 719 case CTLTYPE_STRUCT: 720 warnx("%s: unknown structure returned", string); 721 return; 722 723 default: 724 case CTLTYPE_NODE: 725 warnx("%s: unknown type returned", string); 726 return; 727 } 728 } 729 730 /* 731 * Initialize the set of debugging names 732 */ 733 static void 734 debuginit(void) 735 { 736 int mib[3], loc, i; 737 size_t size; 738 739 if (secondlevel[CTL_DEBUG].list != 0) 740 return; 741 secondlevel[CTL_DEBUG].list = debugname; 742 mib[0] = CTL_DEBUG; 743 mib[2] = CTL_DEBUG_NAME; 744 for (loc = 0, i = 0; i < CTL_DEBUG_MAXID; i++) { 745 mib[1] = i; 746 size = BUFSIZ - loc; 747 if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1) 748 continue; 749 debugname[i].ctl_name = &names[loc]; 750 debugname[i].ctl_type = CTLTYPE_INT; 751 loc += size; 752 } 753 } 754 755 struct ctlname inetname[] = CTL_IPPROTO_NAMES; 756 struct ctlname ipname[] = IPCTL_NAMES; 757 struct ctlname icmpname[] = ICMPCTL_NAMES; 758 struct ctlname tcpname[] = TCPCTL_NAMES; 759 struct ctlname udpname[] = UDPCTL_NAMES; 760 #ifdef IPSEC 761 struct ctlname ipsecname[] = IPSECCTL_NAMES; 762 #endif 763 struct list inetlist = { inetname, IPPROTO_MAXID }; 764 struct list inetvars[] = { 765 /*0*/ { ipname, IPCTL_MAXID }, /* ip */ 766 { icmpname, ICMPCTL_MAXID }, /* icmp */ 767 { 0, 0 }, /* igmp */ 768 { 0, 0 }, /* ggmp */ 769 { 0, 0 }, 770 { 0, 0 }, 771 { tcpname, TCPCTL_MAXID }, /* tcp */ 772 { 0, 0 }, 773 { 0, 0 }, /* egp */ 774 { 0, 0 }, 775 /*10*/ { 0, 0 }, 776 { 0, 0 }, 777 { 0, 0 }, /* pup */ 778 { 0, 0 }, 779 { 0, 0 }, 780 { 0, 0 }, 781 { 0, 0 }, 782 { udpname, UDPCTL_MAXID }, /* udp */ 783 { 0, 0 }, 784 { 0, 0 }, 785 /*20*/ { 0, 0 }, 786 { 0, 0 }, 787 { 0, 0 }, /* idp */ 788 { 0, 0 }, 789 { 0, 0 }, 790 { 0, 0 }, 791 { 0, 0 }, 792 { 0, 0 }, 793 { 0, 0 }, 794 { 0, 0 }, 795 /*30*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 796 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 797 /*40*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 798 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 799 #ifdef IPSEC 800 { ipsecname, IPSECCTL_MAXID }, /* esp - for backward compatibility */ 801 { ipsecname, IPSECCTL_MAXID }, /* ah */ 802 #else 803 { 0, 0 }, 804 { 0, 0 }, 805 #endif 806 }; 807 808 /* 809 * handle internet requests 810 */ 811 static int 812 sysctl_inet(char *string, char **bufpp, int mib[], int flags, int *typep) 813 { 814 struct list *lp; 815 int indx; 816 817 if (*bufpp == NULL) { 818 listall(string, &inetlist); 819 return (-1); 820 } 821 if ((indx = findname(string, "third", bufpp, &inetlist)) == -1) 822 return (-1); 823 mib[2] = indx; 824 if (indx <= IPPROTO_MAXID && inetvars[indx].list != NULL) 825 lp = &inetvars[indx]; 826 else if (!flags) 827 return (-1); 828 else { 829 printf("%s: no variables defined for protocol\n", string); 830 return (-1); 831 } 832 if (*bufpp == NULL) { 833 listall(string, lp); 834 return (-1); 835 } 836 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 837 return (-1); 838 mib[3] = indx; 839 *typep = lp->list[indx].ctl_type; 840 return (4); 841 } 842 843 #ifdef INET6 844 struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES; 845 struct ctlname ip6name[] = IPV6CTL_NAMES; 846 struct ctlname icmp6name[] = ICMPV6CTL_NAMES; 847 struct ctlname udp6name[] = UDP6CTL_NAMES; 848 struct ctlname pim6name[] = PIM6CTL_NAMES; 849 struct ctlname ipsec6name[] = IPSEC6CTL_NAMES; 850 struct list inet6list = { inet6name, IPV6PROTO_MAXID }; 851 struct list inet6vars[] = { 852 /*0*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 853 { 0, 0 }, 854 { tcpname, TCPCTL_MAXID }, /* tcp6 */ 855 { 0, 0 }, 856 { 0, 0 }, 857 { 0, 0 }, 858 /*10*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 859 { 0, 0 }, 860 { 0, 0 }, 861 { udp6name, UDP6CTL_MAXID }, /* udp6 */ 862 { 0, 0 }, 863 { 0, 0 }, 864 /*20*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 865 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 866 /*30*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 867 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 868 /*40*/ { 0, 0 }, 869 { ip6name, IPV6CTL_MAXID }, /* ipv6 */ 870 { 0, 0 }, 871 { 0, 0 }, 872 { 0, 0 }, 873 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 874 #ifdef IPSEC 875 /*50*/ { ipsec6name, IPSECCTL_MAXID }, /* esp6 - for backward compatibility */ 876 { ipsec6name, IPSECCTL_MAXID }, /* ah6 */ 877 #else 878 { 0, 0 }, 879 { 0, 0 }, 880 #endif 881 { 0, 0 }, 882 { 0, 0 }, 883 { 0, 0 }, 884 { 0, 0 }, 885 { 0, 0 }, 886 { 0, 0 }, 887 { icmp6name, ICMPV6CTL_MAXID }, /* icmp6 */ 888 { 0, 0 }, 889 /*60*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 890 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 891 /*70*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 892 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 893 /*80*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 894 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 895 /*90*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 896 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 897 /*100*/ { 0, 0 }, 898 { 0, 0 }, 899 { 0, 0 }, 900 { pim6name, PIM6CTL_MAXID }, /* pim6 */ 901 }; 902 903 /* 904 * handle internet6 requests 905 */ 906 static int 907 sysctl_inet6(char *string, char **bufpp, int mib[], int flags, int *typep) 908 { 909 struct list *lp; 910 int indx; 911 912 if (*bufpp == NULL) { 913 listall(string, &inet6list); 914 return (-1); 915 } 916 if ((indx = findname(string, "third", bufpp, &inet6list)) == -1) 917 return (-1); 918 mib[2] = indx; 919 if (indx <= sizeof(inet6vars)/sizeof(inet6vars[0]) 920 && inet6vars[indx].list != NULL) { 921 lp = &inet6vars[indx]; 922 } else if (!flags) { 923 return (-1); 924 } else { 925 fprintf(stderr, "%s: no variables defined for this protocol\n", 926 string); 927 return (-1); 928 } 929 if (*bufpp == NULL) { 930 listall(string, lp); 931 return (-1); 932 } 933 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 934 return (-1); 935 mib[3] = indx; 936 *typep = lp->list[indx].ctl_type; 937 return (4); 938 } 939 #endif /* INET6 */ 940 941 struct ctlname ffsname[] = FFS_NAMES; 942 struct ctlname nfsname[] = NFS_NAMES; 943 struct list vfsvars[] = { 944 { 0, 0 }, /* generic */ 945 { ffsname, FFS_MAXID }, /* FFS */ 946 { nfsname, NFS_MAXID }, /* NFS */ 947 { 0, 0 }, /* MFS */ 948 { 0, 0 }, /* MSDOS */ 949 { 0, 0 }, /* LFS */ 950 { 0, 0 }, /* old LOFS */ 951 { 0, 0 }, /* FDESC */ 952 { 0, 0 }, /* PORTAL */ 953 { 0, 0 }, /* NULL */ 954 { 0, 0 }, /* UMAP */ 955 { 0, 0 }, /* KERNFS */ 956 { 0, 0 }, /* PROCFS */ 957 { 0, 0 }, /* AFS */ 958 { 0, 0 }, /* CD9660 */ 959 { 0, 0 }, /* UNION */ 960 { 0, 0 }, /* ADOSFS */ 961 { 0, 0 }, /* EXT2FS */ 962 { 0, 0 }, /* CODA */ 963 { 0, 0 }, /* FILECORE */ 964 }; 965 966 /* 967 * handle vfs requests 968 */ 969 static int 970 sysctl_vfs(char *string, char **bufpp, int mib[], int flags, int *typep) 971 { 972 struct list *lp = &vfsvars[mib[1]]; 973 int indx; 974 975 if (lp->list == NULL) { 976 if (flags) 977 printf("%s: no variables defined for file system\n", 978 string); 979 return (-1); 980 } 981 if (*bufpp == NULL) { 982 listall(string, lp); 983 return (-1); 984 } 985 if ((indx = findname(string, "third", bufpp, lp)) == -1) 986 return (-1); 987 mib[2] = indx; 988 *typep = lp->list[indx].ctl_type; 989 return (3); 990 } 991 992 /* 993 * handle 3rd level requests. 994 */ 995 static int 996 sysctl_3rd(struct list *lp, char *string, char **bufpp, int mib[], int flags, 997 int *typep) 998 { 999 int indx; 1000 1001 if (*bufpp == NULL) { 1002 listall(string, lp); 1003 return (-1); 1004 } 1005 if ((indx = findname(string, "third", bufpp, lp)) == -1) 1006 return (-1); 1007 mib[2] = indx; 1008 *typep = lp->list[indx].ctl_type; 1009 return (3); 1010 } 1011 1012 struct ctlname procnames[] = PROC_PID_NAMES; 1013 struct list procvars = {procnames, PROC_PID_MAXID}; 1014 struct ctlname proclimitnames[] = PROC_PID_LIMIT_NAMES; 1015 struct list proclimitvars = {proclimitnames, PROC_PID_LIMIT_MAXID}; 1016 struct ctlname proclimittypenames[] = PROC_PID_LIMIT_TYPE_NAMES; 1017 struct list proclimittypevars = {proclimittypenames, 1018 PROC_PID_LIMIT_TYPE_MAXID}; 1019 /* 1020 * handle kern.proc requests 1021 */ 1022 static int 1023 sysctl_proc(char *string, char **bufpp, int mib[], int flags, int *typep) 1024 { 1025 char *cp, name[BUFSIZ]; 1026 struct list *lp; 1027 int indx; 1028 1029 if (*bufpp == NULL) { 1030 strcpy(name, string); 1031 cp = &name[strlen(name)]; 1032 *cp++ = '.'; 1033 strcpy(cp, "curproc"); 1034 parse(name, Aflag); 1035 return (-1); 1036 } 1037 cp = strsep(bufpp, "."); 1038 if (cp == NULL) { 1039 warnx("%s: incomplete specification", string); 1040 return (-1); 1041 } 1042 if (strcmp(cp, "curproc") == 0) { 1043 mib[1] = PROC_CURPROC; 1044 } else { 1045 mib[1] = atoi(cp); 1046 if (mib[1] == 0) { 1047 warnx("second level name %s in %s is invalid", cp, 1048 string); 1049 return (-1); 1050 } 1051 } 1052 *typep = CTLTYPE_NODE; 1053 lp = &procvars; 1054 if (*bufpp == NULL) { 1055 listall(string, lp); 1056 return (-1); 1057 } 1058 if ((indx = findname(string, "third", bufpp, lp)) == -1) 1059 return (-1); 1060 mib[2] = indx; 1061 *typep = lp->list[indx].ctl_type; 1062 if (*typep != CTLTYPE_NODE) 1063 return(3); 1064 lp = &proclimitvars; 1065 if (*bufpp == NULL) { 1066 listall(string, lp); 1067 return (-1); 1068 } 1069 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 1070 return (-1); 1071 mib[3] = indx; 1072 lp = &proclimittypevars; 1073 if (*bufpp == NULL) { 1074 listall(string, lp); 1075 return (-1); 1076 } 1077 if ((indx = findname(string, "fifth", bufpp, lp)) == -1) 1078 return (-1); 1079 mib[4] = indx; 1080 *typep = CTLTYPE_LIMIT; 1081 return(5); 1082 } 1083 1084 struct ctlname linuxnames[] = EMUL_LINUX_NAMES; 1085 struct list linuxvars = { linuxnames, EMUL_LINUX_MAXID }; 1086 struct ctlname linuxkernnames[] = EMUL_LINUX_KERN_NAMES; 1087 struct list linuxkernvars = { linuxkernnames, EMUL_LINUX_KERN_MAXID }; 1088 1089 static int 1090 sysctl_linux(char *string, char **bufpp, int mib[], int flags, int *typep) 1091 { 1092 struct list *lp = &linuxvars; 1093 int indx; 1094 char name[BUFSIZ], *cp; 1095 1096 if (*bufpp == NULL) { 1097 (void)strcpy(name, string); 1098 cp = &name[strlen(name)]; 1099 *cp++ = '.'; 1100 (void)strcpy(cp, "kern"); 1101 listall(name, &linuxkernvars); 1102 return (-1); 1103 } 1104 if ((indx = findname(string, "third", bufpp, lp)) == -1) 1105 return (-1); 1106 mib[2] = indx; 1107 lp = &linuxkernvars; 1108 *typep = lp->list[indx].ctl_type; 1109 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 1110 return (-1); 1111 mib[3] = indx; 1112 *typep = lp->list[indx].ctl_type; 1113 return (4); 1114 } 1115 1116 struct ctlname irixnames[] = EMUL_IRIX_NAMES; 1117 struct list irixvars = { irixnames, EMUL_IRIX_MAXID }; 1118 struct ctlname irixkernnames[] = EMUL_IRIX_KERN_NAMES; 1119 struct list irixkernvars = { irixkernnames, EMUL_IRIX_KERN_MAXID }; 1120 1121 static int 1122 sysctl_irix(char *string, char **bufpp, int mib[], int flags, int *typep) 1123 { 1124 struct list *lp = &irixvars; 1125 int indx; 1126 char name[BUFSIZ], *cp; 1127 1128 if (*bufpp == NULL) { 1129 (void)strcpy(name, string); 1130 cp = &name[strlen(name)]; 1131 *cp++ = '.'; 1132 (void)strcpy(cp, "kern"); 1133 listall(name, &irixkernvars); 1134 return (-1); 1135 } 1136 if ((indx = findname(string, "third", bufpp, lp)) == -1) 1137 return (-1); 1138 mib[2] = indx; 1139 lp = &irixkernvars; 1140 *typep = lp->list[indx].ctl_type; 1141 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 1142 return (-1); 1143 mib[3] = indx; 1144 *typep = lp->list[indx].ctl_type; 1145 return (4); 1146 } 1147 1148 /* 1149 * Scan a list of names searching for a particular name. 1150 */ 1151 static int 1152 findname(char *string, char *level, char **bufp, struct list *namelist) 1153 { 1154 char *name; 1155 int i; 1156 1157 if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { 1158 warnx("%s: incomplete specification", string); 1159 return (-1); 1160 } 1161 for (i = 0; i < namelist->size; i++) 1162 if (namelist->list[i].ctl_name != NULL && 1163 strcmp(name, namelist->list[i].ctl_name) == 0) 1164 break; 1165 if (i == namelist->size) { 1166 warnx("%s level name %s in %s is invalid", 1167 level, name, string); 1168 return (-1); 1169 } 1170 return (i); 1171 } 1172 1173 static void 1174 usage(void) 1175 { 1176 const char *progname = getprogname(); 1177 1178 (void)fprintf(stderr, 1179 "Usage:\t%s %s\n\t%s %s\n\t%s %s\n\t%s %s\n\t%s %s\n", 1180 progname, "[-n] variable ...", 1181 progname, "[-n] [-q] -w variable=value ...", 1182 progname, "[-n] -a", 1183 progname, "[-n] -A", 1184 progname, "[-n] [-q] -f file"); 1185 exit(1); 1186 } 1187