1 /* $NetBSD: sysctl.c,v 1.43 2001/01/09 21:31:02 fvdl 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.43 2001/01/09 21:31:02 fvdl 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 302 bufp = buf; 303 snprintf(buf, BUFSIZ, "%s", string); 304 if ((cp = strchr(string, '=')) != NULL) { 305 if (!wflag) 306 errx(2, "Must specify -w to set variables"); 307 *strchr(buf, '=') = '\0'; 308 *cp++ = '\0'; 309 while (isspace((unsigned char) *cp)) 310 cp++; 311 newval = cp; 312 newsize = strlen(cp); 313 } 314 if ((indx = findname(string, "top", &bufp, &toplist)) == -1) 315 return; 316 mib[0] = indx; 317 if (indx == CTL_DEBUG) 318 debuginit(); 319 if (mib[0] == CTL_PROC) { 320 type = CTLTYPE_NODE; 321 len = 1; 322 } else { 323 lp = &secondlevel[indx]; 324 if (lp->list == 0) { 325 warnx("Class `%s' is not implemented", 326 topname[indx].ctl_name); 327 return; 328 } 329 if (bufp == NULL) { 330 listall(topname[indx].ctl_name, lp); 331 return; 332 } 333 if ((indx = findname(string, "second", &bufp, lp)) == -1) 334 return; 335 mib[1] = indx; 336 type = lp->list[indx].ctl_type; 337 len = 2; 338 } 339 switch (mib[0]) { 340 341 case CTL_KERN: 342 switch (mib[1]) { 343 case KERN_PROF: 344 mib[2] = GPROF_STATE; 345 size = sizeof state; 346 if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) { 347 if (flags == 0) 348 return; 349 if (!nflag) 350 printf("%s: ", string); 351 warnx("Kernel is not compiled for profiling"); 352 return; 353 } 354 if (!nflag) 355 printf("%s: %s\n", string, 356 state == GMON_PROF_OFF ? "off" : "running"); 357 return; 358 case KERN_VNODE: 359 case KERN_FILE: 360 if (flags == 0) 361 return; 362 warnx("Use pstat to view %s information", string); 363 return; 364 case KERN_PROC: 365 case KERN_PROC2: 366 case KERN_PROC_ARGS: 367 if (flags == 0) 368 return; 369 warnx("Use ps to view %s information", string); 370 return; 371 case KERN_CLOCKRATE: 372 special |= CLOCK; 373 break; 374 case KERN_BOOTTIME: 375 special |= BOOTTIME; 376 break; 377 case KERN_NTPTIME: 378 if (flags == 0) 379 return; 380 warnx("Use xntpdc -c kerninfo to view %s information", 381 string); 382 return; 383 case KERN_MBUF: 384 len = sysctl_mbuf(string, &bufp, mib, flags, &type); 385 if (len < 0) 386 return; 387 break; 388 case KERN_CP_TIME: 389 special |= CPTIME; 390 break; 391 case KERN_MSGBUF: 392 if (flags == 0) 393 return; 394 warnx("Use dmesg to view %s information", string); 395 return; 396 case KERN_CONSDEV: 397 special |= CONSDEV; 398 break; 399 } 400 break; 401 402 case CTL_HW: 403 break; 404 405 case CTL_VM: 406 if (mib[1] == VM_LOADAVG) { 407 double loads[3]; 408 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 if (mib[1] == VM_NKMEMPAGES) { 417 size_t nkmempages_len; 418 int nkmempages; 419 420 nkmempages_len = sizeof(nkmempages); 421 422 if (sysctl(mib, 2, &nkmempages, &nkmempages_len, 423 NULL, 0)) { 424 warn("unable to get %s", string); 425 return; 426 } 427 if (!nflag) 428 printf("%s: ", string); 429 printf("%d\n", nkmempages); 430 } 431 if (flags == 0) 432 return; 433 warnx("Use vmstat or systat to view %s information", string); 434 return; 435 436 case CTL_NET: 437 if (mib[1] == PF_INET) { 438 len = sysctl_inet(string, &bufp, mib, flags, &type); 439 if (len >= 0) 440 break; 441 return; 442 } 443 #ifdef INET6 444 else if (mib[1] == PF_INET6) { 445 len = sysctl_inet6(string, &bufp, mib, flags, &type); 446 if (len >= 0) 447 break; 448 return; 449 } 450 #endif /* INET6 */ 451 #ifdef IPSEC 452 else if (mib[1] == PF_KEY) { 453 len = sysctl_key(string, &bufp, mib, flags, &type); 454 if (len >= 0) 455 break; 456 return; 457 } 458 #endif /* IPSEC */ 459 if (flags == 0) 460 return; 461 warnx("Use netstat to view %s information", string); 462 return; 463 464 case CTL_DEBUG: 465 mib[2] = CTL_DEBUG_VALUE; 466 len = 3; 467 break; 468 469 case CTL_MACHDEP: 470 #ifdef CPU_CONSDEV 471 if (mib[1] == CPU_CONSDEV) 472 special |= CONSDEV; 473 #endif 474 #ifdef CPU_DISKINFO 475 if (mib[1] == CPU_DISKINFO) 476 special |= DISKINFO; 477 #endif 478 break; 479 480 case CTL_VFS: 481 if (mib[1] == VFS_GENERIC) 482 len = sysctl_vfsgen(string, &bufp, mib, flags, &type); 483 else 484 len = sysctl_vfs(string, &bufp, mib, flags, &type); 485 if (len < 0) 486 return; 487 488 /* XXX Special-case for NFS stats. */ 489 if (mib[1] == 2 && mib[2] == NFS_NFSSTATS) { 490 if (flags == 0) 491 return; 492 warnx("Use nfsstat to view %s information", string); 493 return; 494 } 495 break; 496 497 case CTL_VENDOR: 498 case CTL_USER: 499 case CTL_DDB: 500 break; 501 case CTL_PROC: 502 len = sysctl_proc(string, &bufp, mib, flags, &type); 503 if (len < 0) 504 return; 505 break; 506 default: 507 warnx("Illegal top level value: %d", mib[0]); 508 return; 509 510 } 511 if (bufp) { 512 warnx("Name %s in %s is unknown", bufp, string); 513 return; 514 } 515 if (newsize > 0) { 516 switch (type) { 517 case CTLTYPE_INT: 518 intval = atoi(newval); 519 newval = &intval; 520 newsize = sizeof intval; 521 break; 522 523 case CTLTYPE_LIMIT: 524 if (strcmp(newval, "unlimited") == 0) { 525 quadval = RLIM_INFINITY; 526 newval = &quadval; 527 newsize = sizeof quadval; 528 break; 529 } 530 /* FALLTHROUGH */ 531 case CTLTYPE_QUAD: 532 sscanf(newval, "%lld", (long long *)&quadval); 533 newval = &quadval; 534 newsize = sizeof quadval; 535 break; 536 } 537 } 538 size = BUFSIZ; 539 if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) { 540 if (flags == 0) 541 return; 542 switch (errno) { 543 case EOPNOTSUPP: 544 warnx("The value of %s is not available", string); 545 return; 546 case ENOTDIR: 547 warnx("The specification of %s is incomplete", 548 string); 549 return; 550 case ENOMEM: 551 warnx("The type %s is unknown to this program", 552 string); 553 return; 554 default: 555 warn("sysctl() for %s failed", string); 556 return; 557 } 558 } 559 if (special & CLOCK) { 560 struct clockinfo *clkp = (struct clockinfo *)buf; 561 562 if (!nflag) 563 printf("%s: ", string); 564 printf( 565 "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n", 566 clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz); 567 return; 568 } 569 if (special & BOOTTIME) { 570 struct timeval *btp = (struct timeval *)buf; 571 time_t boottime; 572 573 if (!nflag) { 574 boottime = btp->tv_sec; 575 /* ctime() provides the trailing newline */ 576 printf("%s = %s", string, ctime(&boottime)); 577 } else 578 printf("%ld\n", (long) btp->tv_sec); 579 return; 580 } 581 if (special & CONSDEV) { 582 dev_t dev = *(dev_t *)buf; 583 584 if (!nflag) 585 printf("%s = %s\n", string, devname(dev, S_IFCHR)); 586 else 587 printf("0x%x\n", dev); 588 return; 589 } 590 if (special & DISKINFO) { 591 /* Don't know a good way to deal with this i386 specific one */ 592 return; 593 } 594 if (special & CPTIME) { 595 u_int64_t *cp_time = (u_int64_t *)buf; 596 597 if (!nflag) 598 printf("%s: ", string); 599 printf("user = %llu, nice = %llu, sys = %llu, intr = %llu, " 600 "idle = %llu\n", (unsigned long long) cp_time[0], 601 (unsigned long long) cp_time[1], 602 (unsigned long long) cp_time[2], 603 (unsigned long long) cp_time[3], 604 (unsigned long long) cp_time[4]); 605 return; 606 } 607 608 switch (type) { 609 case CTLTYPE_INT: 610 if (newsize == 0) { 611 if (!nflag) 612 printf("%s = ", string); 613 printf("%d\n", *(int *)buf); 614 } else { 615 if (!nflag) 616 printf("%s: %d -> ", string, *(int *)buf); 617 printf("%d\n", *(int *)newval); 618 } 619 return; 620 621 case CTLTYPE_STRING: 622 if (newsize == 0) { 623 if (!nflag) 624 printf("%s = ", string); 625 printf("%s\n", buf); 626 } else { 627 if (!nflag) 628 printf("%s: %s -> ", string, buf); 629 printf("%s\n", (char *) newval); 630 } 631 return; 632 633 case CTLTYPE_LIMIT: 634 #define PRINTF_LIMIT(lim) { \ 635 if ((lim) == RLIM_INFINITY) \ 636 printf("unlimited");\ 637 else \ 638 printf("%lld", (long long)(lim)); \ 639 } 640 641 if (newsize == 0) { 642 if (!nflag) 643 printf("%s = ", string); 644 PRINTF_LIMIT((long long)(*(quad_t *)buf)); 645 } else { 646 if (!nflag) { 647 printf("%s: ", string); 648 PRINTF_LIMIT((long long)(*(quad_t *)buf)); 649 printf(" -> "); 650 } 651 PRINTF_LIMIT((long long)(*(quad_t *)newval)); 652 } 653 printf("\n"); 654 return; 655 #undef PRINTF_LIMIT 656 657 case CTLTYPE_QUAD: 658 if (newsize == 0) { 659 if (!nflag) 660 printf("%s = ", string); 661 printf("%lld\n", (long long)(*(quad_t *)buf)); 662 } else { 663 if (!nflag) 664 printf("%s: %lld -> ", string, 665 (long long)(*(quad_t *)buf)); 666 printf("%lld\n", (long long)(*(quad_t *)newval)); 667 } 668 return; 669 670 case CTLTYPE_STRUCT: 671 warnx("%s: unknown structure returned", string); 672 return; 673 674 default: 675 case CTLTYPE_NODE: 676 warnx("%s: unknown type returned", string); 677 return; 678 } 679 } 680 681 /* 682 * Initialize the set of debugging names 683 */ 684 static void 685 debuginit() 686 { 687 int mib[3], loc, i; 688 size_t size; 689 690 if (secondlevel[CTL_DEBUG].list != 0) 691 return; 692 secondlevel[CTL_DEBUG].list = debugname; 693 mib[0] = CTL_DEBUG; 694 mib[2] = CTL_DEBUG_NAME; 695 for (loc = 0, i = 0; i < CTL_DEBUG_MAXID; i++) { 696 mib[1] = i; 697 size = BUFSIZ - loc; 698 if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1) 699 continue; 700 debugname[i].ctl_name = &names[loc]; 701 debugname[i].ctl_type = CTLTYPE_INT; 702 loc += size; 703 } 704 } 705 706 struct ctlname inetname[] = CTL_IPPROTO_NAMES; 707 struct ctlname ipname[] = IPCTL_NAMES; 708 struct ctlname icmpname[] = ICMPCTL_NAMES; 709 struct ctlname tcpname[] = TCPCTL_NAMES; 710 struct ctlname udpname[] = UDPCTL_NAMES; 711 #ifdef IPSEC 712 struct ctlname ipsecname[] = IPSECCTL_NAMES; 713 #endif 714 struct list inetlist = { inetname, IPPROTO_MAXID }; 715 struct list inetvars[] = { 716 /*0*/ { ipname, IPCTL_MAXID }, /* ip */ 717 { icmpname, ICMPCTL_MAXID }, /* icmp */ 718 { 0, 0 }, /* igmp */ 719 { 0, 0 }, /* ggmp */ 720 { 0, 0 }, 721 { 0, 0 }, 722 { tcpname, TCPCTL_MAXID }, /* tcp */ 723 { 0, 0 }, 724 { 0, 0 }, /* egp */ 725 { 0, 0 }, 726 /*10*/ { 0, 0 }, 727 { 0, 0 }, 728 { 0, 0 }, /* pup */ 729 { 0, 0 }, 730 { 0, 0 }, 731 { 0, 0 }, 732 { 0, 0 }, 733 { udpname, UDPCTL_MAXID }, /* udp */ 734 { 0, 0 }, 735 { 0, 0 }, 736 /*20*/ { 0, 0 }, 737 { 0, 0 }, 738 { 0, 0 }, /* idp */ 739 { 0, 0 }, 740 { 0, 0 }, 741 { 0, 0 }, 742 { 0, 0 }, 743 { 0, 0 }, 744 { 0, 0 }, 745 { 0, 0 }, 746 /*30*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 747 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 748 /*40*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 749 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 750 #ifdef IPSEC 751 { ipsecname, IPSECCTL_MAXID }, /* esp - for backward compatibility */ 752 { ipsecname, IPSECCTL_MAXID }, /* ah */ 753 #else 754 { 0, 0 }, 755 { 0, 0 }, 756 #endif 757 }; 758 759 /* 760 * handle internet requests 761 */ 762 static int 763 sysctl_inet(string, bufpp, mib, flags, typep) 764 char *string; 765 char **bufpp; 766 int mib[]; 767 int flags; 768 int *typep; 769 { 770 struct list *lp; 771 int indx; 772 773 if (*bufpp == NULL) { 774 listall(string, &inetlist); 775 return (-1); 776 } 777 if ((indx = findname(string, "third", bufpp, &inetlist)) == -1) 778 return (-1); 779 mib[2] = indx; 780 if (indx <= IPPROTO_MAXID && inetvars[indx].list != NULL) 781 lp = &inetvars[indx]; 782 else if (!flags) 783 return (-1); 784 else { 785 warnx("No variables defined for protocol %s", string); 786 return (-1); 787 } 788 if (*bufpp == NULL) { 789 listall(string, lp); 790 return (-1); 791 } 792 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 793 return (-1); 794 mib[3] = indx; 795 *typep = lp->list[indx].ctl_type; 796 return (4); 797 } 798 799 #ifdef INET6 800 struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES; 801 struct ctlname ip6name[] = IPV6CTL_NAMES; 802 struct ctlname icmp6name[] = ICMPV6CTL_NAMES; 803 #ifdef TCP6 804 struct ctlname tcp6name[] = TCP6CTL_NAMES; 805 #endif 806 struct ctlname udp6name[] = UDP6CTL_NAMES; 807 struct ctlname pim6name[] = PIM6CTL_NAMES; 808 struct ctlname ipsec6name[] = IPSEC6CTL_NAMES; 809 struct list inet6list = { inet6name, IPV6PROTO_MAXID }; 810 struct list inet6vars[] = { 811 /*0*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 812 { 0, 0 }, 813 #ifdef TCP6 814 { tcp6name, TCP6CTL_MAXID }, /* tcp6 */ 815 #else 816 { 0, 0 }, 817 #endif 818 { 0, 0 }, 819 { 0, 0 }, 820 { 0, 0 }, 821 /*10*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 822 { 0, 0 }, 823 { 0, 0 }, 824 { udp6name, UDP6CTL_MAXID }, /* udp6 */ 825 { 0, 0 }, 826 { 0, 0 }, 827 /*20*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 828 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 829 /*30*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 830 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 831 /*40*/ { 0, 0 }, 832 { ip6name, IPV6CTL_MAXID }, /* ipv6 */ 833 { 0, 0 }, 834 { 0, 0 }, 835 { 0, 0 }, 836 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 837 #ifdef IPSEC 838 /*50*/ { ipsec6name, IPSECCTL_MAXID }, /* esp6 - for backward compatibility */ 839 { ipsec6name, IPSECCTL_MAXID }, /* ah6 */ 840 #else 841 { 0, 0 }, 842 { 0, 0 }, 843 #endif 844 { 0, 0 }, 845 { 0, 0 }, 846 { 0, 0 }, 847 { 0, 0 }, 848 { 0, 0 }, 849 { 0, 0 }, 850 { icmp6name, ICMPV6CTL_MAXID }, /* icmp6 */ 851 { 0, 0 }, 852 /*60*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 853 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 854 /*70*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 855 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 856 /*80*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 857 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 858 /*90*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 859 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 860 /*100*/ { 0, 0 }, 861 { 0, 0 }, 862 { 0, 0 }, 863 { pim6name, PIM6CTL_MAXID }, /* pim6 */ 864 }; 865 866 /* 867 * handle internet6 requests 868 */ 869 static int 870 sysctl_inet6(string, bufpp, mib, flags, typep) 871 char *string; 872 char **bufpp; 873 int mib[]; 874 int flags; 875 int *typep; 876 { 877 struct list *lp; 878 int indx; 879 880 if (*bufpp == NULL) { 881 listall(string, &inet6list); 882 return (-1); 883 } 884 if ((indx = findname(string, "third", bufpp, &inet6list)) == -1) 885 return (-1); 886 mib[2] = indx; 887 if (indx <= sizeof(inet6vars)/sizeof(inet6vars[0]) 888 && inet6vars[indx].list != NULL) { 889 lp = &inet6vars[indx]; 890 } else if (!flags) { 891 return (-1); 892 } else { 893 fprintf(stderr, "%s: no variables defined for this protocol\n", 894 string); 895 return (-1); 896 } 897 if (*bufpp == NULL) { 898 listall(string, lp); 899 return (-1); 900 } 901 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 902 return (-1); 903 mib[3] = indx; 904 *typep = lp->list[indx].ctl_type; 905 return (4); 906 } 907 #endif /* INET6 */ 908 909 #ifdef IPSEC 910 struct ctlname keynames[] = KEYCTL_NAMES; 911 struct list keylist = { keynames, KEYCTL_MAXID }; 912 913 /* 914 * handle key requests 915 */ 916 static int 917 sysctl_key(string, bufpp, mib, flags, typep) 918 char *string; 919 char **bufpp; 920 int mib[]; 921 int flags; 922 int *typep; 923 { 924 struct list *lp; 925 int indx; 926 927 if (*bufpp == NULL) { 928 listall(string, &keylist); 929 return (-1); 930 } 931 if ((indx = findname(string, "third", bufpp, &keylist)) == -1) 932 return (-1); 933 mib[2] = indx; 934 lp = &keylist; 935 *typep = lp->list[indx].ctl_type; 936 return 3; 937 } 938 #endif /*IPSEC*/ 939 940 struct ctlname ffsname[] = FFS_NAMES; 941 struct ctlname nfsname[] = NFS_NAMES; 942 struct list vfsvars[] = { 943 { 0, 0 }, /* generic */ 944 { ffsname, FFS_MAXID }, /* FFS */ 945 { nfsname, NFS_MAXID }, /* NFS */ 946 { 0, 0 }, /* MFS */ 947 { 0, 0 }, /* MSDOS */ 948 { 0, 0 }, /* LFS */ 949 { 0, 0 }, /* old LOFS */ 950 { 0, 0 }, /* FDESC */ 951 { 0, 0 }, /* PORTAL */ 952 { 0, 0 }, /* NULL */ 953 { 0, 0 }, /* UMAP */ 954 { 0, 0 }, /* KERNFS */ 955 { 0, 0 }, /* PROCFS */ 956 { 0, 0 }, /* AFS */ 957 { 0, 0 }, /* CD9660 */ 958 { 0, 0 }, /* UNION */ 959 { 0, 0 }, /* ADOSFS */ 960 { 0, 0 }, /* EXT2FS */ 961 { 0, 0 }, /* CODA */ 962 { 0, 0 }, /* FILECORE */ 963 }; 964 965 /* 966 * handle vfs requests 967 */ 968 static int 969 sysctl_vfs(string, bufpp, mib, flags, typep) 970 char *string; 971 char **bufpp; 972 int mib[]; 973 int flags; 974 int *typep; 975 { 976 struct list *lp = &vfsvars[mib[1]]; 977 int indx; 978 979 if (lp->list == NULL) { 980 if (flags) 981 warnx("No variables defined for file system %s", 982 string); 983 return (-1); 984 } 985 if (*bufpp == NULL) { 986 listall(string, lp); 987 return (-1); 988 } 989 if ((indx = findname(string, "third", bufpp, lp)) == -1) 990 return (-1); 991 mib[2] = indx; 992 *typep = lp->list[indx].ctl_type; 993 return (3); 994 } 995 996 struct ctlname vfsgenname[] = CTL_VFSGENCTL_NAMES; 997 struct list vfsgenvars = { vfsgenname, VFSGEN_MAXID }; 998 999 /* 1000 * handle vfs.generic requests 1001 */ 1002 static int 1003 sysctl_vfsgen(string, bufpp, mib, flags, typep) 1004 char *string; 1005 char **bufpp; 1006 int mib[]; 1007 int flags; 1008 int *typep; 1009 { 1010 struct list *lp = &vfsgenvars; 1011 int indx; 1012 1013 if (*bufpp == NULL) { 1014 listall(string, lp); 1015 return (-1); 1016 } 1017 if ((indx = findname(string, "third", bufpp, lp)) == -1) 1018 return (-1); 1019 /* Don't bother with VFS_CONF. */ 1020 if (indx == VFS_CONF) 1021 return (-1); 1022 mib[2] = indx; 1023 *typep = lp->list[indx].ctl_type; 1024 return (3); 1025 } 1026 1027 struct ctlname procnames[] = PROC_PID_NAMES; 1028 struct list procvars = {procnames, PROC_PID_MAXID}; 1029 struct ctlname proclimitnames[] = PROC_PID_LIMIT_NAMES; 1030 struct list proclimitvars = {proclimitnames, PROC_PID_LIMIT_MAXID}; 1031 struct ctlname proclimittypenames[] = PROC_PID_LIMIT_TYPE_NAMES; 1032 struct list proclimittypevars = {proclimittypenames, 1033 PROC_PID_LIMIT_TYPE_MAXID}; 1034 /* 1035 * handle kern.proc requests 1036 */ 1037 static int 1038 sysctl_proc(string, bufpp, mib, flags, typep) 1039 char *string; 1040 char **bufpp; 1041 int mib[]; 1042 int flags; 1043 int *typep; 1044 { 1045 char *cp, name[BUFSIZ]; 1046 struct list *lp; 1047 int indx; 1048 1049 if (*bufpp == NULL) { 1050 strcpy(name, string); 1051 cp = &name[strlen(name)]; 1052 *cp++ = '.'; 1053 strcpy(cp, "curproc"); 1054 parse (name, Aflag); 1055 return (-1); 1056 } 1057 cp = strsep(bufpp, "."); 1058 if (cp == NULL) { 1059 warnx("%s: incomplete specification", string); 1060 return (-1); 1061 } 1062 if (strcmp(cp, "curproc") == 0) { 1063 mib[1] = PROC_CURPROC; 1064 } else { 1065 mib[1] = atoi(cp); 1066 if (mib[1] == 0) { 1067 warnx("second level name %s in %s is invalid", cp, 1068 string); 1069 return (-1); 1070 } 1071 } 1072 *typep = CTLTYPE_NODE; 1073 lp = &procvars; 1074 if (*bufpp == NULL) { 1075 listall(string, lp); 1076 return (-1); 1077 } 1078 if ((indx = findname(string, "third", bufpp, lp)) == -1) 1079 return (-1); 1080 mib[2] = indx; 1081 *typep = lp->list[indx].ctl_type; 1082 if (*typep != CTLTYPE_NODE) 1083 return(3); 1084 lp = &proclimitvars; 1085 if (*bufpp == NULL) { 1086 listall(string, lp); 1087 return (-1); 1088 } 1089 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 1090 return (-1); 1091 mib[3] = indx; 1092 lp = &proclimittypevars; 1093 if (*bufpp == NULL) { 1094 listall(string, lp); 1095 return (-1); 1096 } 1097 if ((indx = findname(string, "fifth", bufpp, lp)) == -1) 1098 return (-1); 1099 mib[4] = indx; 1100 *typep = CTLTYPE_LIMIT; 1101 return(5); 1102 } 1103 1104 struct ctlname mbufnames[] = CTL_MBUF_NAMES; 1105 struct list mbufvars = { mbufnames, MBUF_MAXID }; 1106 /* 1107 * handle kern.mbuf requests 1108 */ 1109 static int 1110 sysctl_mbuf(string, bufpp, mib, flags, typep) 1111 char *string; 1112 char **bufpp; 1113 int mib[]; 1114 int flags; 1115 int *typep; 1116 { 1117 struct list *lp = &mbufvars; 1118 int indx; 1119 1120 if (*bufpp == NULL) { 1121 listall(string, lp); 1122 return (-1); 1123 } 1124 if ((indx = findname(string, "third", bufpp, lp)) == -1) 1125 return (-1); 1126 mib[2] = indx; 1127 *typep = lp->list[indx].ctl_type; 1128 return (3); 1129 } 1130 1131 /* 1132 * Scan a list of names searching for a particular name. 1133 */ 1134 static int 1135 findname(string, level, bufp, namelist) 1136 char *string; 1137 char *level; 1138 char **bufp; 1139 struct list *namelist; 1140 { 1141 char *name; 1142 int i; 1143 1144 if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { 1145 warnx("%s: incomplete specification", string); 1146 return (-1); 1147 } 1148 for (i = 0; i < namelist->size; i++) 1149 if (namelist->list[i].ctl_name != NULL && 1150 strcmp(name, namelist->list[i].ctl_name) == 0) 1151 break; 1152 if (i == namelist->size) { 1153 warnx("%s level name %s in %s is invalid", 1154 level, name, string); 1155 return (-1); 1156 } 1157 return (i); 1158 } 1159 1160 static void 1161 usage() 1162 { 1163 extern char *__progname; 1164 1165 (void)fprintf(stderr, "Usage:\t%s %s\n\t%s %s\n\t%s %s\n\t%s %s\n\t%s %s\n", 1166 __progname, "[-n] variable ...", 1167 __progname, "[-n] -w variable=value ...", 1168 __progname, "[-n] -a", 1169 __progname, "[-n] -A", 1170 __progname, "[-n] -f file"); 1171 exit(1); 1172 } 1173