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