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