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