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