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