sysctl.c revision 1.29
1/* $OpenBSD: sysctl.c,v 1.29 1997/10/15 19:30:55 kstailey 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.29 1997/10/15 19:30:55 kstailey 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 CONSDEV 0x00000004 137#define RNDSTATS 0x00000008 138#define BADDYNAMIC 0x00000010 139#define BIOSGEO 0x00000020 140#define BIOSDEV 0x00000040 141 142/* prototypes */ 143void debuginit __P((void)); 144void listall __P((char *, struct list *)); 145void parse __P((char *, int)); 146void parse_baddynamic __P((int *, size_t, char *, void **, size_t *, int, int)); 147void usage __P((void)); 148int findname __P((char *, char *, char **, struct list *)); 149int sysctl_inet __P((char *, char **, int *, int, int *)); 150int sysctl_ipsec __P((char *, char **, int *, int, int *)); 151int sysctl_ipx __P((char *, char **, int *, int, int *)); 152int sysctl_fs __P((char *, char **, int *, int, int *)); 153int sysctl_bios __P((char *, char **, int *, int, int *)); 154 155int 156main(argc, argv) 157 int argc; 158 char *argv[]; 159{ 160 int ch, lvl1; 161 162 while ((ch = getopt(argc, argv, "Aanw")) != -1) { 163 switch (ch) { 164 165 case 'A': 166 Aflag = 1; 167 break; 168 169 case 'a': 170 aflag = 1; 171 break; 172 173 case 'n': 174 nflag = 1; 175 break; 176 177 case 'w': 178 wflag = 1; 179 break; 180 181 default: 182 usage(); 183 } 184 } 185 argc -= optind; 186 argv += optind; 187 188 if (Aflag || aflag) { 189 debuginit(); 190 for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++) 191 listall(topname[lvl1].ctl_name, &secondlevel[lvl1]); 192 exit(0); 193 } 194 if (argc == 0) 195 usage(); 196 while (argc-- > 0) 197 parse(*argv++, 1); 198 exit(0); 199} 200 201/* 202 * List all variables known to the system. 203 */ 204void 205listall(prefix, lp) 206 char *prefix; 207 struct list *lp; 208{ 209 int lvl2; 210 char *cp, name[BUFSIZ]; 211 212 if (lp->list == NULL) 213 return; 214 (void)strncpy(name, prefix, BUFSIZ-1); 215 cp = &name[strlen(name)]; 216 *cp++ = '.'; 217 for (lvl2 = 0; lvl2 < lp->size; lvl2++) { 218 if (lp->list[lvl2].ctl_name == NULL) 219 continue; 220 (void)strcpy(cp, lp->list[lvl2].ctl_name); 221 parse(name, Aflag); 222 } 223} 224 225/* 226 * Parse a name into a MIB entry. 227 * Lookup and print out the MIB entry if it exists. 228 * Set a new value if requested. 229 */ 230void 231parse(string, flags) 232 char *string; 233 int flags; 234{ 235 int indx, type, state; 236 int special = 0; 237 void *newval = 0; 238 int intval, newsize = 0; 239 quad_t quadval; 240 size_t size, len; 241 struct list *lp; 242 int mib[CTL_MAXNAME]; 243 char *cp, *bufp, buf[BUFSIZ]; 244 245 (void)strncpy(buf, string, sizeof(buf) - 1); 246 buf[sizeof(buf) - 1] = '\0'; 247 bufp = buf; 248 if ((cp = strchr(string, '=')) != NULL) { 249 if (!wflag) 250 errx(2, "must specify -w to set variables"); 251 *strchr(buf, '=') = '\0'; 252 *cp++ = '\0'; 253 while (isspace(*cp)) 254 cp++; 255 newval = cp; 256 newsize = strlen(cp); 257 } 258 if ((indx = findname(string, "top", &bufp, &toplist)) == -1) 259 return; 260 mib[0] = indx; 261 if (indx == CTL_DEBUG) 262 debuginit(); 263 lp = &secondlevel[indx]; 264 if (lp->list == 0) { 265 warnx("%s: class is not implemented", topname[indx].ctl_name); 266 return; 267 } 268 if (bufp == NULL) { 269 listall(topname[indx].ctl_name, lp); 270 return; 271 } 272 if ((indx = findname(string, "second", &bufp, lp)) == -1) 273 return; 274 mib[1] = indx; 275 type = lp->list[indx].ctl_type; 276 len = 2; 277 switch (mib[0]) { 278 279 case CTL_KERN: 280 switch (mib[1]) { 281 case KERN_PROF: 282 mib[2] = GPROF_STATE; 283 size = sizeof(state); 284 if (sysctl(mib, 3, &state, &size, NULL, 0) == -1) { 285 if (flags == 0) 286 return; 287 if (!nflag) 288 (void)printf("%s: ", string); 289 (void)puts("kernel is not compiled for profiling"); 290 return; 291 } 292 if (!nflag) 293 (void)printf("%s = %s\n", string, 294 state == GMON_PROF_OFF ? "off" : "running"); 295 return; 296 case KERN_VNODE: 297 case KERN_FILE: 298 if (flags == 0) 299 return; 300 warnx("use pstat to view %s information", string); 301 return; 302 case KERN_PROC: 303 if (flags == 0) 304 return; 305 warnx("use ps to view %s information", string); 306 return; 307 case KERN_NTPTIME: 308 if (flags == 0) 309 return; 310 warnx("use xntpdc to view %s information", string); 311 return; 312 case KERN_CLOCKRATE: 313 special |= CLOCK; 314 break; 315 case KERN_BOOTTIME: 316 special |= BOOTTIME; 317 break; 318 case KERN_RND: 319 special |= RNDSTATS; 320 break; 321 } 322 break; 323 324 case CTL_HW: 325 break; 326 327 case CTL_VM: 328 if (mib[1] == VM_LOADAVG) { 329 double loads[3]; 330 331 getloadavg(loads, 3); 332 if (!nflag) 333 (void)printf("%s = ", string); 334 (void)printf("%.2f %.2f %.2f\n", loads[0], 335 loads[1], loads[2]); 336 return; 337 } else if (mib[1] == VM_PSSTRINGS) { 338 struct _ps_strings _ps; 339 340 len = sizeof(_ps); 341 if (sysctl(mib, 2, &_ps, &len, NULL, 0) == -1) { 342 if (flags == 0) 343 return; 344 if (!nflag) 345 (void)printf("%s: ", string); 346 (void)puts("can't find ps strings"); 347 return; 348 } 349 if (!nflag) 350 (void)printf("%s = ", string); 351 (void)printf("%p\n", _ps.val); 352 return; 353 } 354 if (flags == 0) 355 return; 356 warnx("use vmstat or systat to view %s information", string); 357 return; 358 359 case CTL_NET: 360 if (mib[1] == PF_INET) { 361 len = sysctl_inet(string, &bufp, mib, flags, &type); 362 if (len < 0) 363 return; 364 365 if ((mib[2] == IPPROTO_TCP && 366 mib[3] == TCPCTL_BADDYNAMIC) || 367 (mib[2] == IPPROTO_UDP && 368 mib[3] == UDPCTL_BADDYNAMIC)) { 369 370 special |= BADDYNAMIC; 371 372 if (newval != NULL) 373 parse_baddynamic(mib, len, string, 374 &newval, &newsize, flags, nflag); 375 } 376 break; 377 } 378 if (mib[1] == PF_IPX) { 379 len = sysctl_ipx(string, &bufp, mib, flags, &type); 380 if (len >= 0) 381 break; 382 return; 383 } 384 if (mib[1] == PF_ENCAP) { 385 len = sysctl_ipsec(string, &bufp, mib, flags, &type); 386 if (len >= 0) 387 break; 388 return; 389 } 390 if (flags == 0) 391 return; 392 warnx("use netstat to view %s information", string); 393 return; 394 395 case CTL_DEBUG: 396 mib[2] = CTL_DEBUG_VALUE; 397 len = 3; 398 break; 399 400 case CTL_MACHDEP: 401#ifdef CPU_CONSDEV 402 if (mib[1] == CPU_CONSDEV) 403 special |= CONSDEV; 404#endif 405#ifdef CPU_BIOS 406 if (mib[1] == CPU_BIOS) { 407 len = sysctl_bios(string, &bufp, mib, flags, &type); 408 if (mib[2] == BIOS_GEOMETRY) 409 special |= BIOSGEO; 410 if (mib[2] == BIOS_DEV) 411 special |= BIOSDEV; 412 if (len >= 0) 413 break; 414 return; 415 } 416#endif 417 break; 418 419 case CTL_FS: 420 len = sysctl_fs(string, &bufp, mib, flags, &type); 421 if (len >= 0) 422 break; 423 return; 424 425 case CTL_USER: 426 case CTL_DDB: 427 break; 428 429 default: 430 warnx("illegal top level value: %d", mib[0]); 431 return; 432 433 } 434 if (bufp) { 435 warnx("name %s in %s is unknown", bufp, string); 436 return; 437 } 438 if (newsize > 0) { 439 switch (type) { 440 case CTLTYPE_INT: 441 intval = atoi(newval); 442 newval = &intval; 443 newsize = sizeof(intval); 444 break; 445 446 case CTLTYPE_QUAD: 447 (void)sscanf(newval, "%qd", &quadval); 448 newval = &quadval; 449 newsize = sizeof(quadval); 450 break; 451 } 452 } 453 size = BUFSIZ; 454 if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) { 455 if (flags == 0) 456 return; 457 switch (errno) { 458 case EOPNOTSUPP: 459 warnx("%s: value is not available", string); 460 return; 461 case ENOTDIR: 462 warnx("%s: specification is incomplete", string); 463 return; 464 case ENOMEM: 465 warnx("%s: type is unknown to this program", string); 466 return; 467 default: 468 warnx(string); 469 return; 470 } 471 } 472 if (special & CLOCK) { 473 struct clockinfo *clkp = (struct clockinfo *)buf; 474 475 if (!nflag) 476 (void)printf("%s = ", string); 477 (void)printf( 478 "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n", 479 clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz); 480 return; 481 } 482 if (special & BOOTTIME) { 483 struct timeval *btp = (struct timeval *)buf; 484 time_t boottime; 485 486 if (!nflag) { 487 boottime = btp->tv_sec; 488 (void)printf("%s = %s", string, ctime(&boottime)); 489 } else 490 (void)printf("%ld\n", btp->tv_sec); 491 return; 492 } 493 if (special & CONSDEV) { 494 dev_t dev = *(dev_t *)buf; 495 496 if (!nflag) 497 (void)printf("%s = %s\n", string, 498 devname(dev, S_IFCHR)); 499 else 500 (void)printf("0x%x\n", dev); 501 return; 502 } 503#ifdef CPU_BIOS 504 if (special & BIOSGEO) { 505 u_int geo = *(int *)buf; 506 507 if (!nflag) 508 (void)printf("%s = ", string); 509 printf("Cylinders=%d Tracks=%d Sectors=%d (%08x)\n", 510 BIOSNTRACKS(geo), BIOSNHEADS(geo), BIOSNSECTS(geo), geo); 511 return; 512 } 513 if (special & BIOSDEV) { 514 int dev = *(int*)buf; 515 516 if (!nflag) 517 (void)printf("%s = ", string); 518 if (dev & 0x80) 519 dev = ('c' + dev) & 0x7f; 520 else 521 dev += 'a'; 522 (void) printf("%c:\n", dev); 523 return; 524 } 525#endif 526 if (special & RNDSTATS) { 527 struct rndstats *rndstats = (struct rndstats *)buf; 528 529 if (!nflag) 530 (void)printf("%s = ", string); 531 (void)printf( 532 "%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u\n", 533 rndstats->rnd_total, rndstats->rnd_used, 534 rndstats->arc4_reads, rndstats->rnd_timer, 535 rndstats->rnd_mouse, rndstats->rnd_tty, 536 rndstats->rnd_disk, rndstats->rnd_net, 537 rndstats->rnd_reads, rndstats->rnd_waits, 538 rndstats->rnd_enqs, rndstats->rnd_deqs, 539 rndstats->rnd_drops, rndstats->rnd_drople, 540 rndstats->rnd_asleep, rndstats->rnd_queued); 541 return; 542 } 543 if (special & BADDYNAMIC) { 544 in_port_t port, lastport; 545 u_int32_t *baddynamic = (u_int32_t *)buf; 546 547 if (!nflag) 548 (void)printf("%s%s", string, newsize ? ": " : " = "); 549 lastport = 0; 550 for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED; port++) 551 if (DP_ISSET(baddynamic, port)) { 552 (void)printf("%s%hd", lastport ? "," : "", 553 port); 554 lastport = port; 555 } 556 if (newsize != 0) { 557 if (!nflag) 558 fputs(" -> ", stdout); 559 baddynamic = (u_int32_t *)newval; 560 lastport = 0; 561 for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED; 562 port++) 563 if (DP_ISSET(baddynamic, port)) { 564 (void)printf("%s%hd", 565 lastport ? "," : "", port); 566 lastport = port; 567 } 568 } 569 (void)putchar('\n'); 570 return; 571 } 572 switch (type) { 573 case CTLTYPE_INT: 574 if (newsize == 0) { 575 if (!nflag) 576 (void)printf("%s = ", string); 577 (void)printf("%d\n", *(int *)buf); 578 } else { 579 if (!nflag) 580 (void)printf("%s: %d -> ", string, 581 *(int *)buf); 582 (void)printf("%d\n", *(int *)newval); 583 } 584 return; 585 586 case CTLTYPE_STRING: 587 if (newsize == 0) { 588 if (!nflag) 589 (void)printf("%s = ", string); 590 (void)puts(buf); 591 } else { 592 if (!nflag) 593 (void)printf("%s: %s -> ", string, buf); 594 (void)puts((char *)newval); 595 } 596 return; 597 598 case CTLTYPE_QUAD: 599 if (newsize == 0) { 600 if (!nflag) 601 (void)printf("%s = ", string); 602 (void)printf("%qd\n", *(quad_t *)buf); 603 } else { 604 if (!nflag) 605 (void)printf("%s: %qd -> ", string, 606 *(quad_t *)buf); 607 (void)printf("%qd\n", *(quad_t *)newval); 608 } 609 return; 610 611 case CTLTYPE_STRUCT: 612 warnx("%s: unknown structure returned", string); 613 return; 614 615 default: 616 case CTLTYPE_NODE: 617 warnx("%s: unknown type returned", string); 618 return; 619 } 620} 621 622void 623parse_baddynamic(mib, len, string, newvalp, newsizep, flags, nflag) 624 int mib[]; 625 size_t len; 626 char *string; 627 void **newvalp; 628 size_t *newsizep; 629 int flags; 630 int nflag; 631{ 632 static u_int32_t newbaddynamic[DP_MAPSIZE]; 633 in_port_t port; 634 size_t size; 635 char action, *cp; 636 637 if (strchr((char *)*newvalp, '+') || strchr((char *)*newvalp, '-')) { 638 size = sizeof(newbaddynamic); 639 if (sysctl(mib, len, newbaddynamic, &size, 0, 0) == -1) { 640 if (flags == 0) 641 return; 642 if (!nflag) 643 (void)printf("%s: ", string); 644 (void)puts("kernel does contain bad dynamic port tables"); 645 return; 646 } 647 648 while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) { 649 if (*cp != '+' && *cp != '-') 650 errx(1, "cannot mix +/- with full list"); 651 action = *cp++; 652 port = atoi(cp); 653 if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED) 654 errx(1, "invalid port, range is %d to %d", 655 IPPORT_RESERVED/2, IPPORT_RESERVED-1); 656 if (action == '+') 657 DP_SET(newbaddynamic, port); 658 else 659 DP_CLR(newbaddynamic, port); 660 } 661 } else { 662 (void)memset((void *)newbaddynamic, 0, sizeof(newbaddynamic)); 663 while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) { 664 port = atoi(cp); 665 if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED) 666 errx(1, "invalid port, range is %d to %d", 667 IPPORT_RESERVED/2, IPPORT_RESERVED-1); 668 DP_SET(newbaddynamic, port); 669 } 670 } 671 672 *newvalp = (void *)newbaddynamic; 673 *newsizep = sizeof(newbaddynamic); 674} 675 676/* 677 * Initialize the set of debugging names 678 */ 679void 680debuginit() 681{ 682 int mib[3], loc, i; 683 size_t size; 684 685 if (secondlevel[CTL_DEBUG].list != 0) 686 return; 687 secondlevel[CTL_DEBUG].list = debugname; 688 mib[0] = CTL_DEBUG; 689 mib[2] = CTL_DEBUG_NAME; 690 for (loc = 0, i = 0; i < CTL_DEBUG_MAXID; i++) { 691 mib[1] = i; 692 size = BUFSIZ - loc; 693 if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1) 694 continue; 695 debugname[i].ctl_name = &names[loc]; 696 debugname[i].ctl_type = CTLTYPE_INT; 697 loc += size; 698 } 699} 700 701struct ctlname posixname[] = CTL_FS_POSIX_NAMES; 702struct list fslist = { posixname, FS_POSIX_MAXID }; 703 704/* 705 * handle file system requests 706 */ 707int 708sysctl_fs(string, bufpp, mib, flags, typep) 709 char *string; 710 char **bufpp; 711 int mib[]; 712 int flags; 713 int *typep; 714{ 715 int indx; 716 717 if (*bufpp == NULL) { 718 listall(string, &fslist); 719 return(-1); 720 } 721 if ((indx = findname(string, "third", bufpp, &fslist)) == -1) 722 return(-1); 723 mib[2] = indx; 724 *typep = fslist.list[indx].ctl_type; 725 return(3); 726} 727 728#ifdef CPU_BIOS 729struct ctlname biosname[] = CTL_BIOS_NAMES; 730struct list bioslist = { biosname, BIOS_MAXID }; 731 732/* 733 * handle BIOS requests 734 */ 735int 736sysctl_bios(string, bufpp, mib, flags, typep) 737 char *string; 738 char **bufpp; 739 int mib[]; 740 int flags; 741 int *typep; 742{ 743 int indx; 744 745 if (*bufpp == NULL) { 746 listall(string, &bioslist); 747 return(-1); 748 } 749 if ((indx = findname(string, "third", bufpp, &bioslist)) == -1) 750 return(-1); 751 mib[2] = indx; 752 *typep = bioslist.list[indx].ctl_type; 753 return(3); 754} 755#endif 756 757struct ctlname encapname[] = ENCAPCTL_NAMES; 758struct ctlname ipsecname[] = CTL_IPSEC_NAMES; 759struct list ipseclist = { ipsecname, IPSECCTL_MAXID }; 760struct list ipsecvars[] = { 761 { encapname, ENCAPCTL_MAXID }, 762}; 763 764/* 765 * handle ipsec requests 766 */ 767int 768sysctl_ipsec(string, bufpp, mib, flags, typep) 769 char *string; 770 char **bufpp; 771 int mib[]; 772 int flags; 773 int *typep; 774{ 775 struct list *lp; 776 int indx; 777 778 if (*bufpp == NULL) { 779 listall(string, &ipseclist); 780 return(-1); 781 } 782 if ((indx = findname(string, "third", bufpp, &ipseclist)) == -1) 783 return(-1); 784 mib[2] = indx; 785 if (indx <= IPSECCTL_MAXID && ipsecvars[indx].list != NULL) 786 lp = &ipsecvars[indx]; 787 else if (!flags) 788 return(-1); 789 else { 790 warnx("%s: no variables defined for this protocol", string); 791 return(-1); 792 } 793 if (*bufpp == NULL) { 794 listall(string, lp); 795 return(-1); 796 } 797 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 798 return(-1); 799 mib[3] = indx; 800 *typep = lp->list[indx].ctl_type; 801 return(4); 802} 803 804struct ctlname inetname[] = CTL_IPPROTO_NAMES; 805struct ctlname ipname[] = IPCTL_NAMES; 806struct ctlname icmpname[] = ICMPCTL_NAMES; 807struct ctlname tcpname[] = TCPCTL_NAMES; 808struct ctlname udpname[] = UDPCTL_NAMES; 809struct list inetlist = { inetname, IPPROTO_MAXID }; 810struct list inetvars[] = { 811 { 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 { 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}; 830 831/* 832 * handle internet requests 833 */ 834int 835sysctl_inet(string, bufpp, mib, flags, typep) 836 char *string; 837 char **bufpp; 838 int mib[]; 839 int flags; 840 int *typep; 841{ 842 struct list *lp; 843 int indx; 844 845 if (*bufpp == NULL) { 846 listall(string, &inetlist); 847 return(-1); 848 } 849 if ((indx = findname(string, "third", bufpp, &inetlist)) == -1) 850 return(-1); 851 mib[2] = indx; 852 if (indx <= IPPROTO_UDP && inetvars[indx].list != NULL) 853 lp = &inetvars[indx]; 854 else if (!flags) 855 return(-1); 856 else { 857 warnx("%s: no variables defined for this protocol", string); 858 return(-1); 859 } 860 if (*bufpp == NULL) { 861 listall(string, lp); 862 return(-1); 863 } 864 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 865 return(-1); 866 mib[3] = indx; 867 *typep = lp->list[indx].ctl_type; 868 return(4); 869} 870 871struct ctlname ipxname[] = CTL_IPXPROTO_NAMES; 872struct ctlname ipxpname[] = IPXCTL_NAMES; 873struct ctlname spxpname[] = SPXCTL_NAMES; 874struct list ipxlist = { ipxname, IPXCTL_MAXID }; 875struct list ipxvars[] = { 876 { ipxpname, IPXCTL_MAXID }, /* ipx */ 877 { 0, 0 }, 878 { 0, 0 }, 879 { 0, 0 }, 880 { 0, 0 }, 881 { spxpname, SPXCTL_MAXID }, 882}; 883 884/* 885 * Handle internet requests 886 */ 887int 888sysctl_ipx(string, bufpp, mib, flags, typep) 889 char *string; 890 char **bufpp; 891 int mib[]; 892 int flags; 893 int *typep; 894{ 895 struct list *lp; 896 int indx; 897 898 if (*bufpp == NULL) { 899 listall(string, &ipxlist); 900 return(-1); 901 } 902 if ((indx = findname(string, "third", bufpp, &ipxlist)) == -1) 903 return(-1); 904 mib[2] = indx; 905 if (indx <= IPXPROTO_SPX && ipxvars[indx].list != NULL) 906 lp = &ipxvars[indx]; 907 else if (!flags) 908 return(-1); 909 else { 910 warnx("%s: no variables defined for this protocol", string); 911 return(-1); 912 } 913 if (*bufpp == NULL) { 914 listall(string, lp); 915 return(-1); 916 } 917 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 918 return(-1); 919 mib[3] = indx; 920 *typep = lp->list[indx].ctl_type; 921 return(4); 922} 923 924/* 925 * Scan a list of names searching for a particular name. 926 */ 927int 928findname(string, level, bufp, namelist) 929 char *string; 930 char *level; 931 char **bufp; 932 struct list *namelist; 933{ 934 char *name; 935 int i; 936 937 if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { 938 warnx("%s: incomplete specification", string); 939 return(-1); 940 } 941 for (i = 0; i < namelist->size; i++) 942 if (namelist->list[i].ctl_name != NULL && 943 strcmp(name, namelist->list[i].ctl_name) == 0) 944 break; 945 if (i == namelist->size) { 946 warnx("%s level name %s in %s is invalid", level, name, string); 947 return(-1); 948 } 949 return(i); 950} 951 952void 953usage() 954{ 955 956 (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n", 957 "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...", 958 "sysctl [-n] -a", "sysctl [-n] -A"); 959 exit(1); 960} 961