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