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