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