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