sysctl.c revision 1.33
1/* $OpenBSD: sysctl.c,v 1.33 1998/02/17 20:51:24 matthieu Exp $ */ 2/* $NetBSD: sysctl.c,v 1.9 1995/09/30 07:12:50 thorpej Exp $ */ 3 4/* 5 * Copyright (c) 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37#ifndef lint 38static char 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 45static char sccsid[] = "@(#)sysctl.c 8.1 (Berkeley) 6/6/93"; 46#else 47static char *rcsid = "$OpenBSD: sysctl.c,v 1.33 1998/02/17 20:51:24 matthieu 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 <vm/vm_param.h> 57#include <machine/cpu.h> 58 59#include <net/route.h> 60 61#include <netinet/in.h> 62#include <netinet/in_systm.h> 63#include <netinet/ip.h> 64#include <netinet/in_pcb.h> 65#include <netinet/ip_icmp.h> 66#include <netinet/icmp_var.h> 67#include <netinet/ip_var.h> 68#include <netinet/udp.h> 69#include <netinet/udp_var.h> 70#include <netinet/tcp.h> 71#include <netinet/tcp_timer.h> 72#include <netinet/tcp_var.h> 73 74#include <netipx/ipx.h> 75#include <netipx/ipx_var.h> 76#include <netipx/spx_var.h> 77#include <ddb/db_var.h> 78#include <dev/rndvar.h> 79#include <net/encap.h> 80#include <netinet/ip_ipsp.h> 81 82#include <err.h> 83#include <errno.h> 84#include <stdio.h> 85#include <stdlib.h> 86#include <string.h> 87#include <ctype.h> 88 89#ifdef CPU_BIOS 90#include <machine/biosvar.h> 91#endif 92 93struct ctlname topname[] = CTL_NAMES; 94struct ctlname kernname[] = CTL_KERN_NAMES; 95struct ctlname vmname[] = CTL_VM_NAMES; 96struct ctlname fsname[] = CTL_FS_NAMES; 97struct ctlname netname[] = CTL_NET_NAMES; 98struct ctlname hwname[] = CTL_HW_NAMES; 99struct ctlname username[] = CTL_USER_NAMES; 100struct ctlname debugname[CTL_DEBUG_MAXID]; 101#ifdef CTL_MACHDEP_NAMES 102struct ctlname machdepname[] = CTL_MACHDEP_NAMES; 103#endif 104struct ctlname ddbname[] = CTL_DDB_NAMES; 105char names[BUFSIZ]; 106 107struct list { 108 struct ctlname *list; 109 int size; 110}; 111struct list toplist = { topname, CTL_MAXID }; 112struct list secondlevel[] = { 113 { 0, 0 }, /* CTL_UNSPEC */ 114 { kernname, KERN_MAXID }, /* CTL_KERN */ 115 { vmname, VM_MAXID }, /* CTL_VM */ 116 { fsname, FS_MAXID }, /* CTL_FS */ 117 { netname, NET_MAXID }, /* CTL_NET */ 118 { 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */ 119 { hwname, HW_MAXID }, /* CTL_HW */ 120#ifdef CTL_MACHDEP_NAMES 121 { machdepname, CPU_MAXID }, /* CTL_MACHDEP */ 122#else 123 { 0, 0 }, /* CTL_MACHDEP */ 124#endif 125 { username, USER_MAXID }, /* CTL_USER_NAMES */ 126 { ddbname, DBCTL_MAXID }, /* CTL_DDB_NAMES */ 127}; 128 129int Aflag, aflag, nflag, wflag; 130 131/* 132 * Variables requiring special processing. 133 */ 134#define CLOCK 0x00000001 135#define BOOTTIME 0x00000002 136#define CHRDEV 0x00000004 137#define BLKDEV 0x00000008 138#define RNDSTATS 0x00000010 139#define BADDYNAMIC 0x00000020 140#define BIOSGEO 0x00000040 141#define BIOSDEV 0x00000080 142#define MAJ2DEV 0x00000100 143 144/* prototypes */ 145void debuginit __P((void)); 146void listall __P((char *, struct list *)); 147void parse __P((char *, int)); 148void parse_baddynamic __P((int *, size_t, char *, void **, size_t *, int, int)); 149void usage __P((void)); 150int findname __P((char *, char *, char **, struct list *)); 151int sysctl_inet __P((char *, char **, int *, int, int *)); 152int sysctl_ipsec __P((char *, char **, int *, int, int *)); 153int sysctl_ipx __P((char *, char **, int *, int, int *)); 154int sysctl_fs __P((char *, char **, int *, int, int *)); 155int sysctl_bios __P((char *, char **, int *, int, int *)); 156 157int 158main(argc, argv) 159 int argc; 160 char *argv[]; 161{ 162 int ch, lvl1; 163 164 while ((ch = getopt(argc, argv, "Aanw")) != -1) { 165 switch (ch) { 166 167 case 'A': 168 Aflag = 1; 169 break; 170 171 case 'a': 172 aflag = 1; 173 break; 174 175 case 'n': 176 nflag = 1; 177 break; 178 179 case 'w': 180 wflag = 1; 181 break; 182 183 default: 184 usage(); 185 } 186 } 187 argc -= optind; 188 argv += optind; 189 190 if (Aflag || aflag) { 191 debuginit(); 192 for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++) 193 listall(topname[lvl1].ctl_name, &secondlevel[lvl1]); 194 exit(0); 195 } 196 if (argc == 0) 197 usage(); 198 while (argc-- > 0) 199 parse(*argv++, 1); 200 exit(0); 201} 202 203/* 204 * List all variables known to the system. 205 */ 206void 207listall(prefix, lp) 208 char *prefix; 209 struct list *lp; 210{ 211 int lvl2; 212 char *cp, name[BUFSIZ]; 213 214 if (lp->list == NULL) 215 return; 216 (void)strncpy(name, prefix, BUFSIZ-1); 217 name[BUFSIZ-1] = '\0'; 218 cp = &name[strlen(name)]; 219 *cp++ = '.'; 220 for (lvl2 = 0; lvl2 < lp->size; lvl2++) { 221 if (lp->list[lvl2].ctl_name == NULL) 222 continue; 223 (void)strcpy(cp, lp->list[lvl2].ctl_name); 224 parse(name, Aflag); 225 } 226} 227 228/* 229 * Parse a name into a MIB entry. 230 * Lookup and print out the MIB entry if it exists. 231 * Set a new value if requested. 232 */ 233void 234parse(string, flags) 235 char *string; 236 int flags; 237{ 238 int indx, type, state, len; 239 int special = 0; 240 void *newval = 0; 241 int intval, newsize = 0; 242 quad_t quadval; 243 size_t size; 244 struct list *lp; 245 int mib[CTL_MAXNAME]; 246 char *cp, *bufp, buf[BUFSIZ]; 247 248 (void)strncpy(buf, string, sizeof(buf) - 1); 249 buf[sizeof(buf) - 1] = '\0'; 250 bufp = buf; 251 if ((cp = strchr(string, '=')) != NULL) { 252 if (!wflag) 253 errx(2, "must specify -w to set variables"); 254 *strchr(buf, '=') = '\0'; 255 *cp++ = '\0'; 256 while (isspace(*cp)) 257 cp++; 258 newval = cp; 259 newsize = strlen(cp); 260 } 261 if ((indx = findname(string, "top", &bufp, &toplist)) == -1) 262 return; 263 mib[0] = indx; 264 if (indx == CTL_DEBUG) 265 debuginit(); 266 lp = &secondlevel[indx]; 267 if (lp->list == 0) { 268 warnx("%s: class is not implemented", topname[indx].ctl_name); 269 return; 270 } 271 if (bufp == NULL) { 272 listall(topname[indx].ctl_name, lp); 273 return; 274 } 275 if ((indx = findname(string, "second", &bufp, lp)) == -1) 276 return; 277 mib[1] = indx; 278 type = lp->list[indx].ctl_type; 279 len = 2; 280 switch (mib[0]) { 281 282 case CTL_KERN: 283 switch (mib[1]) { 284 case KERN_PROF: 285 mib[2] = GPROF_STATE; 286 size = sizeof(state); 287 if (sysctl(mib, 3, &state, &size, NULL, 0) == -1) { 288 if (flags == 0) 289 return; 290 if (!nflag) 291 (void)printf("%s: ", string); 292 (void)puts("kernel is not compiled for profiling"); 293 return; 294 } 295 if (!nflag) 296 (void)printf("%s = %s\n", string, 297 state == GMON_PROF_OFF ? "off" : "running"); 298 return; 299 case KERN_VNODE: 300 case KERN_FILE: 301 if (flags == 0) 302 return; 303 warnx("use pstat to view %s information", string); 304 return; 305 case KERN_PROC: 306 if (flags == 0) 307 return; 308 warnx("use ps to view %s information", string); 309 return; 310 case KERN_NTPTIME: 311 if (flags == 0) 312 return; 313 warnx("use xntpdc to view %s information", string); 314 return; 315 case KERN_CLOCKRATE: 316 special |= CLOCK; 317 break; 318 case KERN_BOOTTIME: 319 special |= BOOTTIME; 320 break; 321 case KERN_RND: 322 special |= RNDSTATS; 323 break; 324 } 325 break; 326 327 case CTL_HW: 328 break; 329 330 case CTL_VM: 331 if (mib[1] == VM_LOADAVG) { 332 double loads[3]; 333 334 getloadavg(loads, 3); 335 if (!nflag) 336 (void)printf("%s = ", string); 337 (void)printf("%.2f %.2f %.2f\n", loads[0], 338 loads[1], loads[2]); 339 return; 340 } else if (mib[1] == VM_PSSTRINGS) { 341 struct _ps_strings _ps; 342 343 len = sizeof(_ps); 344 if (sysctl(mib, 2, &_ps, &len, NULL, 0) == -1) { 345 if (flags == 0) 346 return; 347 if (!nflag) 348 (void)printf("%s: ", string); 349 (void)puts("can't find ps strings"); 350 return; 351 } 352 if (!nflag) 353 (void)printf("%s = ", string); 354 (void)printf("%p\n", _ps.val); 355 return; 356 } 357 if (flags == 0) 358 return; 359 warnx("use vmstat or systat to view %s information", string); 360 return; 361 362 case CTL_NET: 363 if (mib[1] == PF_INET) { 364 len = sysctl_inet(string, &bufp, mib, flags, &type); 365 if (len < 0) 366 return; 367 368 if ((mib[2] == IPPROTO_TCP && 369 mib[3] == TCPCTL_BADDYNAMIC) || 370 (mib[2] == IPPROTO_UDP && 371 mib[3] == UDPCTL_BADDYNAMIC)) { 372 373 special |= BADDYNAMIC; 374 375 if (newval != NULL) 376 parse_baddynamic(mib, len, string, 377 &newval, &newsize, flags, nflag); 378 } 379 break; 380 } 381 if (mib[1] == PF_IPX) { 382 len = sysctl_ipx(string, &bufp, mib, flags, &type); 383 if (len >= 0) 384 break; 385 return; 386 } 387 if (mib[1] == PF_ENCAP) { 388 len = sysctl_ipsec(string, &bufp, mib, flags, &type); 389 if (len >= 0) 390 break; 391 return; 392 } 393 if (flags == 0) 394 return; 395 warnx("use netstat to view %s information", string); 396 return; 397 398 case CTL_DEBUG: 399 mib[2] = CTL_DEBUG_VALUE; 400 len = 3; 401 break; 402 403 case CTL_MACHDEP: 404#ifdef CPU_CONSDEV 405 if (mib[1] == CPU_CONSDEV) 406 special |= CHRDEV; 407#endif 408#ifdef CPU_BLK2CHR 409 if (mib[1] == CPU_BLK2CHR) { 410 if (bufp == NULL) 411 return; 412 mib[2] = makedev(atoi(bufp),0); 413 bufp = NULL; 414 len = 3; 415 special |= CHRDEV; 416 break; 417 } 418#endif 419#ifdef CPU_CHR2BLK 420 if (mib[1] == CPU_CHR2BLK) { 421 if (bufp == NULL) 422 return; 423 mib[2] = makedev(atoi(bufp),0); 424 bufp = NULL; 425 len = 3; 426 special |= BLKDEV; 427 break; 428 } 429#endif 430#ifdef CPU_BIOS 431 if (mib[1] == CPU_BIOS) { 432 len = sysctl_bios(string, &bufp, mib, flags, &type); 433 if (len < 0) 434 return; 435 if (mib[2] == BIOS_DEV) 436 special |= BIOSDEV; 437 if (mib[2] == BIOS_DISKINFO) 438 special |= BIOSGEO; 439 break; 440 } 441#endif 442 break; 443 444 case CTL_FS: 445 len = sysctl_fs(string, &bufp, mib, flags, &type); 446 if (len >= 0) 447 break; 448 return; 449 450 case CTL_USER: 451 case CTL_DDB: 452 break; 453 454 default: 455 warnx("illegal top level value: %d", mib[0]); 456 return; 457 458 } 459 if (bufp) { 460 warnx("name %s in %s is unknown", bufp, string); 461 return; 462 } 463 if (newsize > 0) { 464 switch (type) { 465 case CTLTYPE_INT: 466 intval = atoi(newval); 467 newval = &intval; 468 newsize = sizeof(intval); 469 break; 470 471 case CTLTYPE_QUAD: 472 (void)sscanf(newval, "%qd", &quadval); 473 newval = &quadval; 474 newsize = sizeof(quadval); 475 break; 476 } 477 } 478 size = BUFSIZ; 479 if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) { 480 if (flags == 0) 481 return; 482 switch (errno) { 483 case EOPNOTSUPP: 484 warnx("%s: value is not available", string); 485 return; 486 case ENOTDIR: 487 warnx("%s: specification is incomplete", string); 488 return; 489 case ENOMEM: 490 warnx("%s: type is unknown to this program", string); 491 return; 492 case ENXIO: 493 if (special & BIOSGEO) 494 return; 495 default: 496 warn(string); 497 return; 498 } 499 } 500 if (special & CLOCK) { 501 struct clockinfo *clkp = (struct clockinfo *)buf; 502 503 if (!nflag) 504 (void)printf("%s = ", string); 505 (void)printf( 506 "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n", 507 clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz); 508 return; 509 } 510 if (special & BOOTTIME) { 511 struct timeval *btp = (struct timeval *)buf; 512 time_t boottime; 513 514 if (!nflag) { 515 boottime = btp->tv_sec; 516 (void)printf("%s = %s", string, ctime(&boottime)); 517 } else 518 (void)printf("%ld\n", btp->tv_sec); 519 return; 520 } 521 if (special & BLKDEV) { 522 dev_t dev = *(dev_t *)buf; 523 524 if (!nflag) 525 (void)printf("%s = %s\n", string, 526 devname(dev, S_IFBLK)); 527 else 528 (void)printf("0x%x\n", dev); 529 return; 530 } 531 if (special & CHRDEV) { 532 dev_t dev = *(dev_t *)buf; 533 534 if (!nflag) 535 (void)printf("%s = %s\n", string, 536 devname(dev, S_IFCHR)); 537 else 538 (void)printf("0x%x\n", dev); 539 return; 540 } 541#ifdef CPU_BIOS 542 if (special & BIOSGEO) { 543 bios_diskinfo_t *pdi = (bios_diskinfo_t *)buf; 544 545 if (!nflag) 546 (void)printf("%s = ", string); 547 (void)printf("bootdev = 0x%x, " 548 "cylinders = %u, heads = %u, sectors = %u\n", 549 pdi->bsd_dev, pdi->bios_cylinders, pdi->bios_heads, 550 pdi->bios_sectors); 551 return; 552 } 553 if (special & BIOSDEV) { 554 int dev = *(int*)buf; 555 556 if (!nflag) 557 (void)printf("%s = ", string); 558 (void) printf("0x%02x\n", dev); 559 return; 560 } 561#endif 562 if (special & RNDSTATS) { 563 struct rndstats *rndstats = (struct rndstats *)buf; 564 565 if (!nflag) 566 (void)printf("%s = ", string); 567 (void)printf( 568 "%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u\n", 569 rndstats->rnd_total, rndstats->rnd_used, 570 rndstats->arc4_reads, rndstats->rnd_timer, 571 rndstats->rnd_mouse, rndstats->rnd_tty, 572 rndstats->rnd_disk, rndstats->rnd_net, 573 rndstats->rnd_reads, rndstats->rnd_waits, 574 rndstats->rnd_enqs, rndstats->rnd_deqs, 575 rndstats->rnd_drops, rndstats->rnd_drople, 576 rndstats->rnd_asleep, rndstats->rnd_queued); 577 return; 578 } 579 if (special & BADDYNAMIC) { 580 in_port_t port, lastport; 581 u_int32_t *baddynamic = (u_int32_t *)buf; 582 583 if (!nflag) 584 (void)printf("%s%s", string, newsize ? ": " : " = "); 585 lastport = 0; 586 for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED; port++) 587 if (DP_ISSET(baddynamic, port)) { 588 (void)printf("%s%hd", lastport ? "," : "", 589 port); 590 lastport = port; 591 } 592 if (newsize != 0) { 593 if (!nflag) 594 fputs(" -> ", stdout); 595 baddynamic = (u_int32_t *)newval; 596 lastport = 0; 597 for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED; 598 port++) 599 if (DP_ISSET(baddynamic, port)) { 600 (void)printf("%s%hd", 601 lastport ? "," : "", port); 602 lastport = port; 603 } 604 } 605 (void)putchar('\n'); 606 return; 607 } 608 switch (type) { 609 case CTLTYPE_INT: 610 if (newsize == 0) { 611 if (!nflag) 612 (void)printf("%s = ", string); 613 (void)printf("%d\n", *(int *)buf); 614 } else { 615 if (!nflag) 616 (void)printf("%s: %d -> ", string, 617 *(int *)buf); 618 (void)printf("%d\n", *(int *)newval); 619 } 620 return; 621 622 case CTLTYPE_STRING: 623 if (newsize == 0) { 624 if (!nflag) 625 (void)printf("%s = ", string); 626 (void)puts(buf); 627 } else { 628 if (!nflag) 629 (void)printf("%s: %s -> ", string, buf); 630 (void)puts((char *)newval); 631 } 632 return; 633 634 case CTLTYPE_QUAD: 635 if (newsize == 0) { 636 if (!nflag) 637 (void)printf("%s = ", string); 638 (void)printf("%qd\n", *(quad_t *)buf); 639 } else { 640 if (!nflag) 641 (void)printf("%s: %qd -> ", string, 642 *(quad_t *)buf); 643 (void)printf("%qd\n", *(quad_t *)newval); 644 } 645 return; 646 647 case CTLTYPE_STRUCT: 648 warnx("%s: unknown structure returned", string); 649 return; 650 651 default: 652 case CTLTYPE_NODE: 653 warnx("%s: unknown type returned", string); 654 return; 655 } 656} 657 658void 659parse_baddynamic(mib, len, string, newvalp, newsizep, flags, nflag) 660 int mib[]; 661 size_t len; 662 char *string; 663 void **newvalp; 664 size_t *newsizep; 665 int flags; 666 int nflag; 667{ 668 static u_int32_t newbaddynamic[DP_MAPSIZE]; 669 in_port_t port; 670 size_t size; 671 char action, *cp; 672 673 if (strchr((char *)*newvalp, '+') || strchr((char *)*newvalp, '-')) { 674 size = sizeof(newbaddynamic); 675 if (sysctl(mib, len, newbaddynamic, &size, 0, 0) == -1) { 676 if (flags == 0) 677 return; 678 if (!nflag) 679 (void)printf("%s: ", string); 680 (void)puts("kernel does contain bad dynamic port tables"); 681 return; 682 } 683 684 while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) { 685 if (*cp != '+' && *cp != '-') 686 errx(1, "cannot mix +/- with full list"); 687 action = *cp++; 688 port = atoi(cp); 689 if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED) 690 errx(1, "invalid port, range is %d to %d", 691 IPPORT_RESERVED/2, IPPORT_RESERVED-1); 692 if (action == '+') 693 DP_SET(newbaddynamic, port); 694 else 695 DP_CLR(newbaddynamic, port); 696 } 697 } else { 698 (void)memset((void *)newbaddynamic, 0, sizeof(newbaddynamic)); 699 while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) { 700 port = atoi(cp); 701 if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED) 702 errx(1, "invalid port, range is %d to %d", 703 IPPORT_RESERVED/2, IPPORT_RESERVED-1); 704 DP_SET(newbaddynamic, port); 705 } 706 } 707 708 *newvalp = (void *)newbaddynamic; 709 *newsizep = sizeof(newbaddynamic); 710} 711 712/* 713 * Initialize the set of debugging names 714 */ 715void 716debuginit() 717{ 718 int mib[3], loc, i; 719 size_t size; 720 721 if (secondlevel[CTL_DEBUG].list != 0) 722 return; 723 secondlevel[CTL_DEBUG].list = debugname; 724 mib[0] = CTL_DEBUG; 725 mib[2] = CTL_DEBUG_NAME; 726 for (loc = 0, i = 0; i < CTL_DEBUG_MAXID; i++) { 727 mib[1] = i; 728 size = BUFSIZ - loc; 729 if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1) 730 continue; 731 debugname[i].ctl_name = &names[loc]; 732 debugname[i].ctl_type = CTLTYPE_INT; 733 loc += size; 734 } 735} 736 737struct ctlname posixname[] = CTL_FS_POSIX_NAMES; 738struct list fslist = { posixname, FS_POSIX_MAXID }; 739 740/* 741 * handle file system requests 742 */ 743int 744sysctl_fs(string, bufpp, mib, flags, typep) 745 char *string; 746 char **bufpp; 747 int mib[]; 748 int flags; 749 int *typep; 750{ 751 int indx; 752 753 if (*bufpp == NULL) { 754 listall(string, &fslist); 755 return(-1); 756 } 757 if ((indx = findname(string, "third", bufpp, &fslist)) == -1) 758 return(-1); 759 mib[2] = indx; 760 *typep = fslist.list[indx].ctl_type; 761 return(3); 762} 763 764#ifdef CPU_BIOS 765struct ctlname biosname[] = CTL_BIOS_NAMES; 766struct list bioslist = { biosname, BIOS_MAXID }; 767 768/* 769 * handle BIOS requests 770 */ 771int 772sysctl_bios(string, bufpp, mib, flags, typep) 773 char *string; 774 char **bufpp; 775 int mib[]; 776 int flags; 777 int *typep; 778{ 779 char *name; 780 int indx; 781 782 if (*bufpp == NULL) { 783 listall(string, &bioslist); 784 return(-1); 785 } 786 if ((indx = findname(string, "third", bufpp, &bioslist)) == -1) 787 return(-1); 788 mib[2] = indx; 789 if (indx == BIOS_DISKINFO) { 790 if (*bufpp == NULL) { 791 char name[BUFSIZ]; 792 793 /* scan all the bios devices */ 794 for (indx = 0; indx < 256; indx++) { 795 snprintf(name, sizeof(name), "%s.%u", 796 string, indx); 797 parse(name, 1); 798 } 799 return(-1); 800 } 801 if ((name = strsep(bufpp, ".")) == NULL) { 802 warnx("%s: incomplete specification", string); 803 return(-1); 804 } 805 mib[3] = atoi(name); 806 *typep = CTLTYPE_STRUCT; 807 return 4; 808 } else { 809 *typep = bioslist.list[indx].ctl_type; 810 return(3); 811 } 812} 813#endif 814 815struct ctlname encapname[] = ENCAPCTL_NAMES; 816struct ctlname ipsecname[] = CTL_IPSEC_NAMES; 817struct list ipseclist = { ipsecname, IPSECCTL_MAXID }; 818struct list ipsecvars[] = { 819 { encapname, ENCAPCTL_MAXID }, 820}; 821 822/* 823 * handle ipsec requests 824 */ 825int 826sysctl_ipsec(string, bufpp, mib, flags, typep) 827 char *string; 828 char **bufpp; 829 int mib[]; 830 int flags; 831 int *typep; 832{ 833 struct list *lp; 834 int indx; 835 836 if (*bufpp == NULL) { 837 listall(string, &ipseclist); 838 return(-1); 839 } 840 if ((indx = findname(string, "third", bufpp, &ipseclist)) == -1) 841 return(-1); 842 mib[2] = indx; 843 if (indx <= IPSECCTL_MAXID && ipsecvars[indx].list != NULL) 844 lp = &ipsecvars[indx]; 845 else if (!flags) 846 return(-1); 847 else { 848 warnx("%s: no variables defined for this protocol", string); 849 return(-1); 850 } 851 if (*bufpp == NULL) { 852 listall(string, lp); 853 return(-1); 854 } 855 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 856 return(-1); 857 mib[3] = indx; 858 *typep = lp->list[indx].ctl_type; 859 return(4); 860} 861 862struct ctlname inetname[] = CTL_IPPROTO_NAMES; 863struct ctlname ipname[] = IPCTL_NAMES; 864struct ctlname icmpname[] = ICMPCTL_NAMES; 865struct ctlname tcpname[] = TCPCTL_NAMES; 866struct ctlname udpname[] = UDPCTL_NAMES; 867struct list inetlist = { inetname, IPPROTO_MAXID }; 868struct list inetvars[] = { 869 { ipname, IPCTL_MAXID }, /* ip */ 870 { icmpname, ICMPCTL_MAXID }, /* icmp */ 871 { 0, 0 }, /* igmp */ 872 { 0, 0 }, /* ggmp */ 873 { 0, 0 }, 874 { 0, 0 }, 875 { tcpname, TCPCTL_MAXID }, /* tcp */ 876 { 0, 0 }, 877 { 0, 0 }, /* egp */ 878 { 0, 0 }, 879 { 0, 0 }, 880 { 0, 0 }, 881 { 0, 0 }, /* pup */ 882 { 0, 0 }, 883 { 0, 0 }, 884 { 0, 0 }, 885 { 0, 0 }, 886 { udpname, UDPCTL_MAXID }, /* udp */ 887}; 888 889/* 890 * handle internet requests 891 */ 892int 893sysctl_inet(string, bufpp, mib, flags, typep) 894 char *string; 895 char **bufpp; 896 int mib[]; 897 int flags; 898 int *typep; 899{ 900 struct list *lp; 901 int indx; 902 903 if (*bufpp == NULL) { 904 listall(string, &inetlist); 905 return(-1); 906 } 907 if ((indx = findname(string, "third", bufpp, &inetlist)) == -1) 908 return(-1); 909 mib[2] = indx; 910 if (indx <= IPPROTO_UDP && inetvars[indx].list != NULL) 911 lp = &inetvars[indx]; 912 else if (!flags) 913 return(-1); 914 else { 915 warnx("%s: no variables defined for this protocol", string); 916 return(-1); 917 } 918 if (*bufpp == NULL) { 919 listall(string, lp); 920 return(-1); 921 } 922 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 923 return(-1); 924 mib[3] = indx; 925 *typep = lp->list[indx].ctl_type; 926 return(4); 927} 928 929struct ctlname ipxname[] = CTL_IPXPROTO_NAMES; 930struct ctlname ipxpname[] = IPXCTL_NAMES; 931struct ctlname spxpname[] = SPXCTL_NAMES; 932struct list ipxlist = { ipxname, IPXCTL_MAXID }; 933struct list ipxvars[] = { 934 { ipxpname, IPXCTL_MAXID }, /* ipx */ 935 { 0, 0 }, 936 { 0, 0 }, 937 { 0, 0 }, 938 { 0, 0 }, 939 { spxpname, SPXCTL_MAXID }, 940}; 941 942/* 943 * Handle internet requests 944 */ 945int 946sysctl_ipx(string, bufpp, mib, flags, typep) 947 char *string; 948 char **bufpp; 949 int mib[]; 950 int flags; 951 int *typep; 952{ 953 struct list *lp; 954 int indx; 955 956 if (*bufpp == NULL) { 957 listall(string, &ipxlist); 958 return(-1); 959 } 960 if ((indx = findname(string, "third", bufpp, &ipxlist)) == -1) 961 return(-1); 962 mib[2] = indx; 963 if (indx <= IPXPROTO_SPX && ipxvars[indx].list != NULL) 964 lp = &ipxvars[indx]; 965 else if (!flags) 966 return(-1); 967 else { 968 warnx("%s: no variables defined for this protocol", string); 969 return(-1); 970 } 971 if (*bufpp == NULL) { 972 listall(string, lp); 973 return(-1); 974 } 975 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 976 return(-1); 977 mib[3] = indx; 978 *typep = lp->list[indx].ctl_type; 979 return(4); 980} 981 982/* 983 * Scan a list of names searching for a particular name. 984 */ 985int 986findname(string, level, bufp, namelist) 987 char *string; 988 char *level; 989 char **bufp; 990 struct list *namelist; 991{ 992 char *name; 993 int i; 994 995 if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { 996 warnx("%s: incomplete specification", string); 997 return(-1); 998 } 999 for (i = 0; i < namelist->size; i++) 1000 if (namelist->list[i].ctl_name != NULL && 1001 strcmp(name, namelist->list[i].ctl_name) == 0) 1002 break; 1003 if (i == namelist->size) { 1004 warnx("%s level name %s in %s is invalid", level, name, string); 1005 return(-1); 1006 } 1007 return(i); 1008} 1009 1010void 1011usage() 1012{ 1013 1014 (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n", 1015 "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...", 1016 "sysctl [-n] -a", "sysctl [-n] -A"); 1017 exit(1); 1018} 1019