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