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