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