sysctl.c revision 1.13
1126557Snjl/* $OpenBSD: sysctl.c,v 1.13 1997/07/22 14:43:19 kstailey Exp $ */ 2126557Snjl/* $NetBSD: sysctl.c,v 1.9 1995/09/30 07:12:50 thorpej Exp $ */ 3126557Snjl 4126557Snjl/* 5126557Snjl * Copyright (c) 1993 6126557Snjl * The Regents of the University of California. All rights reserved. 7126557Snjl * 8126557Snjl * Redistribution and use in source and binary forms, with or without 9126557Snjl * modification, are permitted provided that the following conditions 10126557Snjl * are met: 11126557Snjl * 1. Redistributions of source code must retain the above copyright 12126557Snjl * notice, this list of conditions and the following disclaimer. 13126557Snjl * 2. Redistributions in binary form must reproduce the above copyright 14126557Snjl * notice, this list of conditions and the following disclaimer in the 15126557Snjl * documentation and/or other materials provided with the distribution. 16126557Snjl * 3. All advertising materials mentioning features or use of this software 17126557Snjl * must display the following acknowledgement: 18126557Snjl * This product includes software developed by the University of 19126557Snjl * California, Berkeley and its contributors. 20126557Snjl * 4. Neither the name of the University nor the names of its contributors 21126557Snjl * may be used to endorse or promote products derived from this software 22126557Snjl * without specific prior written permission. 23126557Snjl * 24126557Snjl * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25126557Snjl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26126557Snjl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27126557Snjl * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28137439Snjl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29126557Snjl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30126557Snjl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31126557Snjl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32126557Snjl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33126557Snjl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34126557Snjl * SUCH DAMAGE. 35126557Snjl */ 36126557Snjl 37126557Snjl#ifndef lint 38126557Snjlstatic char copyright[] = 39126557Snjl"@(#) Copyright (c) 1993\n\ 40126557Snjl The Regents of the University of California. All rights reserved.\n"; 41130650Sru#endif /* not lint */ 42148066Shrs 43126557Snjl#ifndef lint 44130650Sru#if 0 45130650Srustatic char sccsid[] = "@(#)sysctl.c 8.1 (Berkeley) 6/6/93"; 46130650Sru#else 47130650Srustatic char *rcsid = "$OpenBSD: sysctl.c,v 1.13 1997/07/22 14:43:19 kstailey Exp $"; 48130650Sru#endif 49130650Sru#endif /* not lint */ 50126557Snjl 51130650Sru#include <sys/param.h> 52137439Snjl#include <sys/gmon.h> 53130650Sru#include <sys/stat.h> 54126557Snjl#include <sys/sysctl.h> 55130650Sru#include <sys/socket.h> 56126557Snjl#include <vm/vm_param.h> 57130650Sru#include <machine/cpu.h> 58126557Snjl 59130650Sru#include <netinet/in.h> 60126557Snjl#include <netinet/in_systm.h> 61126557Snjl#include <netinet/ip.h> 62126557Snjl#include <netinet/ip_icmp.h> 63126557Snjl#include <netinet/icmp_var.h> 64126557Snjl#include <netinet/ip_var.h> 65126557Snjl#include <netinet/udp.h> 66126557Snjl#include <netinet/udp_var.h> 67126557Snjl#include <netinet/tcp.h> 68126557Snjl#include <netinet/tcp_timer.h> 69126557Snjl#include <netinet/tcp_var.h> 70126557Snjl 71126557Snjl#include <netipx/ipx.h> 72126557Snjl#include <netipx/ipx_var.h> 73126557Snjl#include <netipx/spx_var.h> 74126557Snjl#include <ddb/db_var.h> 75126557Snjl#include <dev/rndvar.h> 76126557Snjl#include <net/encap.h> 77126557Snjl#include <netinet/ip_ipsp.h> 78126557Snjl 79126557Snjl#include <errno.h> 80126557Snjl#include <stdio.h> 81267938Sbapt#include <stdlib.h> 82126557Snjl#include <string.h> 83267938Sbapt#include <ctype.h> 84137439Snjl 85137439Snjlstruct ctlname topname[] = CTL_NAMES; 86137439Snjlstruct ctlname kernname[] = CTL_KERN_NAMES; 87137439Snjlstruct ctlname vmname[] = CTL_VM_NAMES; 88137439Snjlstruct ctlname fsname[] = CTL_FS_NAMES; 89137439Snjlstruct ctlname netname[] = CTL_NET_NAMES; 90struct ctlname hwname[] = CTL_HW_NAMES; 91struct ctlname username[] = CTL_USER_NAMES; 92struct ctlname debugname[CTL_DEBUG_MAXID]; 93#ifdef CTL_MACHDEP_NAMES 94struct ctlname machdepname[] = CTL_MACHDEP_NAMES; 95#endif 96struct ctlname ddbname[] = CTL_DDB_NAMES; 97char names[BUFSIZ]; 98 99struct list { 100 struct ctlname *list; 101 int size; 102}; 103struct list toplist = { topname, CTL_MAXID }; 104struct list secondlevel[] = { 105 { 0, 0 }, /* CTL_UNSPEC */ 106 { kernname, KERN_MAXID }, /* CTL_KERN */ 107 { vmname, VM_MAXID }, /* CTL_VM */ 108 { fsname, FS_MAXID }, /* CTL_FS */ 109 { netname, NET_MAXID }, /* CTL_NET */ 110 { 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */ 111 { hwname, HW_MAXID }, /* CTL_HW */ 112#ifdef CTL_MACHDEP_NAMES 113 { machdepname, CPU_MAXID }, /* CTL_MACHDEP */ 114#else 115 { 0, 0 }, /* CTL_MACHDEP */ 116#endif 117 { username, USER_MAXID }, /* CTL_USER_NAMES */ 118 { ddbname, DBCTL_MAXID }, /* CTL_DDB_NAMES */ 119}; 120 121int Aflag, aflag, nflag, wflag; 122 123/* 124 * Variables requiring special processing. 125 */ 126#define CLOCK 0x00000001 127#define BOOTTIME 0x00000002 128#define CONSDEV 0x00000004 129#define RNDSTATS 0x00000008 130 131/* prototypes */ 132void usage(); 133void debuginit(); 134void parse __P(( char *string, int flags)); 135void listall __P((char *prefix, struct list *lp)); 136int findname __P((char *string, char *level, char **bufp, struct list *namelist)); 137int sysctl_inet __P((char *string, char **bufpp, int mib[], int flags, int *typep)); 138int sysctl_ipsec __P((char *string, char **bufpp, int mib[], int flags, int *typep)); 139int sysctl_ipx __P((char *string, char **bufpp, int mib[], int flags, int *typep)); 140int sysctl_fs __P((char *string, char **bufpp, int mib[], int flags, int *typep)); 141 142int 143main(argc, argv) 144 int argc; 145 char *argv[]; 146{ 147 extern char *optarg; 148 extern int optind; 149 int ch, lvl1; 150 151 while ((ch = getopt(argc, argv, "Aanw")) != -1) { 152 switch (ch) { 153 154 case 'A': 155 Aflag = 1; 156 break; 157 158 case 'a': 159 aflag = 1; 160 break; 161 162 case 'n': 163 nflag = 1; 164 break; 165 166 case 'w': 167 wflag = 1; 168 break; 169 170 default: 171 usage(); 172 } 173 } 174 argc -= optind; 175 argv += optind; 176 177 if (Aflag || aflag) { 178 debuginit(); 179 for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++) 180 listall(topname[lvl1].ctl_name, &secondlevel[lvl1]); 181 exit(0); 182 } 183 if (argc == 0) 184 usage(); 185 while (argc-- > 0) 186 parse(*argv++, 1); 187 exit(0); 188} 189 190/* 191 * List all variables known to the system. 192 */ 193void 194listall(prefix, lp) 195 char *prefix; 196 struct list *lp; 197{ 198 int lvl2; 199 char *cp, name[BUFSIZ]; 200 201 if (lp->list == 0) 202 return; 203 strncpy(name, prefix, BUFSIZ-1); 204 cp = &name[strlen(name)]; 205 *cp++ = '.'; 206 for (lvl2 = 0; lvl2 < lp->size; lvl2++) { 207 if (lp->list[lvl2].ctl_name == 0) 208 continue; 209 strcpy(cp, lp->list[lvl2].ctl_name); 210 parse(name, Aflag); 211 } 212} 213 214/* 215 * Parse a name into a MIB entry. 216 * Lookup and print out the MIB entry if it exists. 217 * Set a new value if requested. 218 */ 219void 220parse(string, flags) 221 char *string; 222 int flags; 223{ 224 int indx, type, state; 225 int special = 0; 226 void *newval = 0; 227 int intval, newsize = 0; 228 quad_t quadval; 229 size_t size, len; 230 struct list *lp; 231 int mib[CTL_MAXNAME]; 232 char *cp, *bufp, buf[BUFSIZ]; 233 234 bufp = buf; 235 snprintf(buf, BUFSIZ, "%s", string); 236 if ((cp = strchr(string, '=')) != NULL) { 237 if (!wflag) { 238 fprintf(stderr, "Must specify -w to set variables\n"); 239 exit(2); 240 } 241 *strchr(buf, '=') = '\0'; 242 *cp++ = '\0'; 243 while (isspace(*cp)) 244 cp++; 245 newval = cp; 246 newsize = strlen(cp); 247 } 248 if ((indx = findname(string, "top", &bufp, &toplist)) == -1) 249 return; 250 mib[0] = indx; 251 if (indx == CTL_DEBUG) 252 debuginit(); 253 lp = &secondlevel[indx]; 254 if (lp->list == 0) { 255 fprintf(stderr, "%s: class is not implemented\n", 256 topname[indx].ctl_name); 257 return; 258 } 259 if (bufp == NULL) { 260 listall(topname[indx].ctl_name, lp); 261 return; 262 } 263 if ((indx = findname(string, "second", &bufp, lp)) == -1) 264 return; 265 mib[1] = indx; 266 type = lp->list[indx].ctl_type; 267 len = 2; 268 switch (mib[0]) { 269 270 case CTL_KERN: 271 switch (mib[1]) { 272 case KERN_PROF: 273 mib[2] = GPROF_STATE; 274 size = sizeof state; 275 if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) { 276 if (flags == 0) 277 return; 278 if (!nflag) 279 fprintf(stdout, "%s: ", string); 280 fprintf(stdout, 281 "kernel is not compiled for profiling\n"); 282 return; 283 } 284 if (!nflag) 285 fprintf(stdout, "%s = %s\n", string, 286 state == GMON_PROF_OFF ? "off" : "running"); 287 return; 288 case KERN_VNODE: 289 case KERN_FILE: 290 if (flags == 0) 291 return; 292 fprintf(stderr, 293 "Use pstat to view %s information\n", string); 294 return; 295 case KERN_PROC: 296 if (flags == 0) 297 return; 298 fprintf(stderr, 299 "Use ps to view %s information\n", string); 300 return; 301 case KERN_NTPTIME: 302 if (flags == 0) 303 return; 304 fprintf(stderr, 305 "Use xntpd to view %s information\n", string); 306 return; 307 case KERN_CLOCKRATE: 308 special |= CLOCK; 309 break; 310 case KERN_BOOTTIME: 311 special |= BOOTTIME; 312 break; 313 case KERN_RND: 314 special |= RNDSTATS; 315 break; 316 } 317 break; 318 319 case CTL_HW: 320 break; 321 322 case CTL_VM: 323 if (mib[1] == VM_LOADAVG) { 324 double loads[3]; 325 326 getloadavg(loads, 3); 327 if (!nflag) 328 fprintf(stdout, "%s = ", string); 329 fprintf(stdout, "%.2f %.2f %.2f\n", 330 loads[0], loads[1], loads[2]); 331 return; 332 } else if (mib[1] == VM_PSSTRINGS) { 333 struct _ps_strings _ps; 334 335 len = sizeof(_ps); 336 sysctl(mib, 2, &_ps, &len, NULL, 0); 337 if (!nflag) 338 fprintf(stdout, "%s = ", string); 339 fprintf(stdout, "%ld\n", _ps.val); 340 return; 341 } 342 if (flags == 0) 343 return; 344 fprintf(stderr, 345 "Use vmstat or systat to view %s information\n", string); 346 return; 347 348 case CTL_NET: 349 if (mib[1] == PF_INET) { 350 len = sysctl_inet(string, &bufp, mib, flags, &type); 351 if (len >= 0) 352 break; 353 return; 354 } 355 if (mib[1] == PF_IPX) { 356 len = sysctl_ipx(string, &bufp, mib, flags, &type); 357 if (len >= 0) 358 break; 359 return; 360 } 361 if (mib[1] == PF_ENCAP) { 362 len = sysctl_ipsec(string, &bufp, mib, flags, &type); 363 if (len >= 0) 364 break; 365 return; 366 } 367 if (flags == 0) 368 return; 369 fprintf(stderr, "Use netstat to view %s information\n", string); 370 return; 371 372 case CTL_DEBUG: 373 mib[2] = CTL_DEBUG_VALUE; 374 len = 3; 375 break; 376 377 case CTL_MACHDEP: 378#ifdef CPU_CONSDEV 379 if (mib[1] == CPU_CONSDEV) 380 special |= CONSDEV; 381#endif 382 break; 383 384 case CTL_FS: 385 len = sysctl_fs(string, &bufp, mib, flags, &type); 386 if (len >= 0) 387 break; 388 return; 389 390 case CTL_USER: 391 case CTL_DDB: 392 break; 393 394 default: 395 fprintf(stderr, "Illegal top level value: %d\n", mib[0]); 396 return; 397 398 } 399 if (bufp) { 400 fprintf(stderr, "name %s in %s is unknown\n", bufp, string); 401 return; 402 } 403 if (newsize > 0) { 404 switch (type) { 405 case CTLTYPE_INT: 406 intval = atoi(newval); 407 newval = &intval; 408 newsize = sizeof intval; 409 break; 410 411 case CTLTYPE_QUAD: 412 sscanf(newval, "%qd", &quadval); 413 newval = &quadval; 414 newsize = sizeof quadval; 415 break; 416 } 417 } 418 size = BUFSIZ; 419 if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) { 420 if (flags == 0) 421 return; 422 switch (errno) { 423 case EOPNOTSUPP: 424 fprintf(stderr, "%s: value is not available\n", string); 425 return; 426 case ENOTDIR: 427 fprintf(stderr, "%s: specification is incomplete\n", 428 string); 429 return; 430 case ENOMEM: 431 fprintf(stderr, "%s: type is unknown to this program\n", 432 string); 433 return; 434 default: 435 perror(string); 436 return; 437 } 438 } 439 if (special & CLOCK) { 440 struct clockinfo *clkp = (struct clockinfo *)buf; 441 442 if (!nflag) 443 fprintf(stdout, "%s = ", string); 444 fprintf(stdout, 445 "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n", 446 clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz); 447 return; 448 } 449 if (special & BOOTTIME) { 450 struct timeval *btp = (struct timeval *)buf; 451 time_t boottime; 452 453 if (!nflag) { 454 boottime = btp->tv_sec; 455 fprintf(stdout, "%s = %s\n", string, ctime(&boottime)); 456 } else 457 fprintf(stdout, "%ld\n", btp->tv_sec); 458 return; 459 } 460 if (special & CONSDEV) { 461 dev_t dev = *(dev_t *)buf; 462 463 if (!nflag) 464 fprintf(stdout, "%s = %s\n", string, 465 devname(dev, S_IFCHR)); 466 else 467 fprintf(stdout, "0x%x\n", dev); 468 return; 469 } 470 if (special & RNDSTATS) { 471 struct rndstats *rndstats = (struct rndstats *)buf; 472 if (!nflag) 473 fprintf(stdout, "%s = ", string); 474 fprintf(stdout, 475 "%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u\n", 476 rndstats->rnd_total, rndstats->rnd_used, 477 rndstats->arc4_reads, rndstats->rnd_timer, 478 rndstats->rnd_mouse, rndstats->rnd_tty, 479 rndstats->rnd_disk, rndstats->rnd_net, 480 rndstats->rnd_reads, rndstats->rnd_waits, 481 rndstats->rnd_enqs, rndstats->rnd_deqs, 482 rndstats->rnd_drops, rndstats->rnd_drople, 483 rndstats->rnd_asleep, rndstats->rnd_queued); 484 return; 485 } 486 switch (type) { 487 case CTLTYPE_INT: 488 if (newsize == 0) { 489 if (!nflag) 490 fprintf(stdout, "%s = ", string); 491 fprintf(stdout, "%d\n", *(int *)buf); 492 } else { 493 if (!nflag) 494 fprintf(stdout, "%s: %d -> ", string, 495 *(int *)buf); 496 fprintf(stdout, "%d\n", *(int *)newval); 497 } 498 return; 499 500 case CTLTYPE_STRING: 501 if (newsize == 0) { 502 if (!nflag) 503 fprintf(stdout, "%s = ", string); 504 fprintf(stdout, "%s\n", buf); 505 } else { 506 if (!nflag) 507 fprintf(stdout, "%s: %s -> ", string, buf); 508 fprintf(stdout, "%s\n", (char *)newval); 509 } 510 return; 511 512 case CTLTYPE_QUAD: 513 if (newsize == 0) { 514 if (!nflag) 515 fprintf(stdout, "%s = ", string); 516 fprintf(stdout, "%qd\n", *(quad_t *)buf); 517 } else { 518 if (!nflag) 519 fprintf(stdout, "%s: %qd -> ", string, 520 *(quad_t *)buf); 521 fprintf(stdout, "%qd\n", *(quad_t *)newval); 522 } 523 return; 524 525 case CTLTYPE_STRUCT: 526 fprintf(stderr, "%s: unknown structure returned\n", 527 string); 528 return; 529 530 default: 531 case CTLTYPE_NODE: 532 fprintf(stderr, "%s: unknown type returned\n", 533 string); 534 return; 535 } 536} 537 538/* 539 * Initialize the set of debugging names 540 */ 541void 542debuginit() 543{ 544 int mib[3], loc, i; 545 size_t size; 546 547 if (secondlevel[CTL_DEBUG].list != 0) 548 return; 549 secondlevel[CTL_DEBUG].list = debugname; 550 mib[0] = CTL_DEBUG; 551 mib[2] = CTL_DEBUG_NAME; 552 for (loc = 0, i = 0; i < CTL_DEBUG_MAXID; i++) { 553 mib[1] = i; 554 size = BUFSIZ - loc; 555 if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1) 556 continue; 557 debugname[i].ctl_name = &names[loc]; 558 debugname[i].ctl_type = CTLTYPE_INT; 559 loc += size; 560 } 561} 562 563struct ctlname posixname[] = CTL_FS_POSIX_NAMES; 564struct list fslist = { posixname, FS_POSIX_MAXID }; 565 566/* 567 * handle file system requests 568 */ 569int 570sysctl_fs(string, bufpp, mib, flags, typep) 571 char *string; 572 char **bufpp; 573 int mib[]; 574 int flags; 575 int *typep; 576{ 577 int indx; 578 579 if (*bufpp == NULL) { 580 listall(string, &fslist); 581 return (-1); 582 } 583 if ((indx = findname(string, "third", bufpp, &fslist)) == -1) 584 return (-1); 585 mib[2] = indx; 586 *typep = fslist.list[indx].ctl_type; 587 return (3); 588} 589 590struct ctlname encapname[] = ENCAPCTL_NAMES; 591struct ctlname ipsecname[] = CTL_IPSEC_NAMES; 592struct list ipseclist = { ipsecname, IPSECCTL_MAXID }; 593struct list ipsecvars[] = { 594 { encapname, ENCAPCTL_MAXID }, 595}; 596 597/* 598 * handle ipsec requests 599 */ 600int 601sysctl_ipsec(string, bufpp, mib, flags, typep) 602 char *string; 603 char **bufpp; 604 int mib[]; 605 int flags; 606 int *typep; 607{ 608 struct list *lp; 609 int indx; 610 611 if (*bufpp == NULL) { 612 listall(string, &ipseclist); 613 return (-1); 614 } 615 if ((indx = findname(string, "third", bufpp, &ipseclist)) == -1) 616 return (-1); 617 mib[2] = indx; 618 if (indx <= IPSECCTL_MAXID && ipsecvars[indx].list != NULL) 619 lp = &ipsecvars[indx]; 620 else if (!flags) 621 return (-1); 622 else { 623 fprintf(stderr, "%s: no variables defined for this protocol\n", 624 string); 625 return (-1); 626 } 627 if (*bufpp == NULL) { 628 listall(string, lp); 629 return (-1); 630 } 631 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 632 return (-1); 633 mib[3] = indx; 634 *typep = lp->list[indx].ctl_type; 635 return (4); 636} 637 638struct ctlname inetname[] = CTL_IPPROTO_NAMES; 639struct ctlname ipname[] = IPCTL_NAMES; 640struct ctlname icmpname[] = ICMPCTL_NAMES; 641struct ctlname tcpname[] = TCPCTL_NAMES; 642struct ctlname udpname[] = UDPCTL_NAMES; 643struct list inetlist = { inetname, IPPROTO_MAXID }; 644struct list inetvars[] = { 645 { ipname, IPCTL_MAXID }, /* ip */ 646 { icmpname, ICMPCTL_MAXID }, /* icmp */ 647 { 0, 0 }, /* igmp */ 648 { 0, 0 }, /* ggmp */ 649 { 0, 0 }, 650 { 0, 0 }, 651 { tcpname, TCPCTL_MAXID }, /* tcp */ 652 { 0, 0 }, 653 { 0, 0 }, /* egp */ 654 { 0, 0 }, 655 { 0, 0 }, 656 { 0, 0 }, 657 { 0, 0 }, /* pup */ 658 { 0, 0 }, 659 { 0, 0 }, 660 { 0, 0 }, 661 { 0, 0 }, 662 { udpname, UDPCTL_MAXID }, /* udp */ 663}; 664 665/* 666 * handle internet requests 667 */ 668int 669sysctl_inet(string, bufpp, mib, flags, typep) 670 char *string; 671 char **bufpp; 672 int mib[]; 673 int flags; 674 int *typep; 675{ 676 struct list *lp; 677 int indx; 678 679 if (*bufpp == NULL) { 680 listall(string, &inetlist); 681 return (-1); 682 } 683 if ((indx = findname(string, "third", bufpp, &inetlist)) == -1) 684 return (-1); 685 mib[2] = indx; 686 if (indx <= IPPROTO_UDP && inetvars[indx].list != NULL) 687 lp = &inetvars[indx]; 688 else if (!flags) 689 return (-1); 690 else { 691 fprintf(stderr, "%s: no variables defined for this protocol\n", 692 string); 693 return (-1); 694 } 695 if (*bufpp == NULL) { 696 listall(string, lp); 697 return (-1); 698 } 699 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 700 return (-1); 701 mib[3] = indx; 702 *typep = lp->list[indx].ctl_type; 703 return (4); 704} 705 706struct ctlname ipxname[] = CTL_IPXPROTO_NAMES; 707struct ctlname ipxpname[] = IPXCTL_NAMES; 708struct ctlname spxpname[] = SPXCTL_NAMES; 709struct list ipxlist = { ipxname, IPXCTL_MAXID }; 710struct list ipxvars[] = { 711 { ipxpname, IPXCTL_MAXID }, /* ipx */ 712 { 0, 0 }, 713 { 0, 0 }, 714 { 0, 0 }, 715 { 0, 0 }, 716 { spxpname, SPXCTL_MAXID }, 717}; 718 719/* 720 * handle internet requests 721 */ 722int 723sysctl_ipx(string, bufpp, mib, flags, typep) 724 char *string; 725 char **bufpp; 726 int mib[]; 727 int flags; 728 int *typep; 729{ 730 struct list *lp; 731 int indx; 732 733 if (*bufpp == NULL) { 734 listall(string, &ipxlist); 735 return (-1); 736 } 737 if ((indx = findname(string, "third", bufpp, &ipxlist)) == -1) 738 return (-1); 739 mib[2] = indx; 740 if (indx <= IPXPROTO_SPX && ipxvars[indx].list != NULL) 741 lp = &ipxvars[indx]; 742 else if (!flags) 743 return (-1); 744 else { 745 fprintf(stderr, "%s: no variables defined for this protocol\n", 746 string); 747 return (-1); 748 } 749 if (*bufpp == NULL) { 750 listall(string, lp); 751 return (-1); 752 } 753 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 754 return (-1); 755 mib[3] = indx; 756 *typep = lp->list[indx].ctl_type; 757 return (4); 758} 759 760/* 761 * Scan a list of names searching for a particular name. 762 */ 763int 764findname(string, level, bufp, namelist) 765 char *string; 766 char *level; 767 char **bufp; 768 struct list *namelist; 769{ 770 char *name; 771 int i; 772 773 if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { 774 fprintf(stderr, "%s: incomplete specification\n", string); 775 return (-1); 776 } 777 for (i = 0; i < namelist->size; i++) 778 if (namelist->list[i].ctl_name != NULL && 779 strcmp(name, namelist->list[i].ctl_name) == 0) 780 break; 781 if (i == namelist->size) { 782 fprintf(stderr, "%s level name %s in %s is invalid\n", 783 level, name, string); 784 return (-1); 785 } 786 return (i); 787} 788 789void 790usage() 791{ 792 793 (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n", 794 "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...", 795 "sysctl [-n] -a", "sysctl [-n] -A"); 796 exit(1); 797} 798