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