158888Smckusick /* 258888Smckusick * Copyright (c) 1993 The Regents of the University of California. 358888Smckusick * All rights reserved. 458888Smckusick * 558888Smckusick * %sccs.include.redist.c% 658888Smckusick */ 758888Smckusick 858888Smckusick #ifndef lint 958888Smckusick char copyright[] = 1058888Smckusick "@(#) Copyright (c) 1993 The Regents of the University of California.\n\ 1158888Smckusick All rights reserved.\n"; 1258888Smckusick #endif /* not lint */ 1358888Smckusick 1458888Smckusick #ifndef lint 15*59140Smckusick static char sccsid[] = "@(#)sysctl.c 5.4 (Berkeley) 04/18/93"; 1658888Smckusick #endif /* not lint */ 1758888Smckusick 1858888Smckusick #include <sys/types.h> 1958888Smckusick #include <sys/stat.h> 2058888Smckusick #include <sys/sysctl.h> 2158888Smckusick #include <sys/socket.h> 2258888Smckusick #include <vm/vm_param.h> 23*59140Smckusick #include <netinet/in.h> 24*59140Smckusick #include <netinet/in_systm.h> 25*59140Smckusick #include <netinet/ip.h> 26*59140Smckusick #include <netinet/ip_icmp.h> 27*59140Smckusick #include <netinet/icmp_var.h> 2858888Smckusick #include <errno.h> 2958888Smckusick #include <stdlib.h> 3058888Smckusick #include <string.h> 3158888Smckusick #include <stdio.h> 3258888Smckusick 33*59140Smckusick struct ctlname topname[] = CTL_NAMES; 34*59140Smckusick struct ctlname kernname[] = CTL_KERN_NAMES; 35*59140Smckusick struct ctlname vmname[] = CTL_VM_NAMES; 36*59140Smckusick struct ctlname netname[] = CTL_NET_NAMES; 37*59140Smckusick struct ctlname hwname[] = CTL_HW_NAMES; 3858888Smckusick 3958888Smckusick struct list { 40*59140Smckusick struct ctlname *list; 4158888Smckusick int size; 42*59140Smckusick }; 43*59140Smckusick struct list toplist = { topname, CTL_MAXID }; 44*59140Smckusick struct list secondlevel[] = { 4558888Smckusick { 0, 0 }, /* CTL_UNSPEC */ 4658888Smckusick { kernname, KERN_MAXID }, /* CTL_KERN */ 4758888Smckusick { vmname, VM_MAXID }, /* CTL_VM */ 4858888Smckusick { 0, 0 }, /* CTL_FS */ 4958888Smckusick { netname, NET_MAXID }, /* CTL_NET */ 5058888Smckusick { 0, 0 }, /* CTL_DEBUG */ 5158888Smckusick { hwname, HW_MAXID }, /* CTL_HW */ 5258888Smckusick { 0, 0 }, /* CTL_MACHDEP */ 5358888Smckusick }; 5458888Smckusick 5558910Smckusick int Aflag, aflag, nflag, wflag; 5658888Smckusick 5758888Smckusick int 5858888Smckusick main(argc, argv) 5958888Smckusick int argc; 6058888Smckusick char *argv[]; 6158888Smckusick { 6258888Smckusick extern char *optarg; 6358888Smckusick extern int optind; 6458910Smckusick int ch, lvl1; 6558888Smckusick 6658910Smckusick while ((ch = getopt(argc, argv, "Aanw")) != EOF) { 6758888Smckusick switch (ch) { 6858888Smckusick 6958888Smckusick case 'A': 7058888Smckusick Aflag = 1; 7158888Smckusick break; 7258888Smckusick 7358888Smckusick case 'a': 7458888Smckusick aflag = 1; 7558888Smckusick break; 7658888Smckusick 7758910Smckusick case 'n': 7858910Smckusick nflag = 1; 7958910Smckusick break; 8058910Smckusick 8158888Smckusick case 'w': 8258888Smckusick wflag = 1; 8358888Smckusick break; 8458888Smckusick 8558888Smckusick default: 8658888Smckusick usage(); 8758888Smckusick } 8858888Smckusick } 8958888Smckusick argc -= optind; 9058888Smckusick argv += optind; 9158888Smckusick 9258888Smckusick if (Aflag || aflag) { 9358910Smckusick for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++) 94*59140Smckusick listall(topname[lvl1].ctl_name, &secondlevel[lvl1]); 9558888Smckusick exit(0); 9658888Smckusick } 9758888Smckusick if (argc == 0) 9858888Smckusick usage(); 9958888Smckusick while (argc-- > 0) 10058888Smckusick parse(*argv, 1); 10158888Smckusick exit(0); 10258888Smckusick } 10358888Smckusick 10458888Smckusick /* 10558888Smckusick * List all variables known to the system. 10658888Smckusick */ 107*59140Smckusick listall(prefix, lp) 108*59140Smckusick char *prefix; 109*59140Smckusick struct list *lp; 11058888Smckusick { 11158910Smckusick int lvl2; 11258888Smckusick char *cp, name[BUFSIZ]; 11358888Smckusick 11458910Smckusick if (lp->list == 0) 11558910Smckusick return; 116*59140Smckusick strcpy(name, prefix); 11758910Smckusick cp = &name[strlen(name)]; 11858910Smckusick *cp++ = '.'; 119*59140Smckusick for (lvl2 = 0; lvl2 < lp->size; lvl2++) { 120*59140Smckusick if (lp->list[lvl2].ctl_name == 0) 121*59140Smckusick continue; 122*59140Smckusick strcpy(cp, lp->list[lvl2].ctl_name); 12358910Smckusick parse(name, Aflag); 12458888Smckusick } 12558888Smckusick } 12658888Smckusick 12758888Smckusick /* 12858888Smckusick * Parse a name into a MIB entry. 12958888Smckusick * Lookup and print out the MIB entry if it exists. 13058888Smckusick * Set a new value if requested. 13158888Smckusick */ 13258888Smckusick parse(string, flags) 13358888Smckusick char *string; 13458888Smckusick int flags; 13558888Smckusick { 136*59140Smckusick int indx, type, size, len; 13758888Smckusick int isclockrate = 0; 13858888Smckusick void *newval = 0; 13958888Smckusick int intval, newsize = 0; 140*59140Smckusick quad_t quadval; 141*59140Smckusick struct list *lp; 14258888Smckusick int mib[CTL_MAXNAME]; 14358888Smckusick char *cp, *bufp, buf[BUFSIZ], strval[BUFSIZ]; 14458888Smckusick 14558888Smckusick bufp = buf; 14658888Smckusick snprintf(buf, BUFSIZ, "%s", string); 14758888Smckusick if ((cp = strchr(string, '=')) != NULL) { 14858888Smckusick if (!wflag) { 14958888Smckusick fprintf(stderr, "Must specify -w to set variables\n"); 15058888Smckusick exit(2); 15158888Smckusick } 15258888Smckusick *strchr(buf, '=') = '\0'; 15358888Smckusick *cp++ = '\0'; 15458888Smckusick while (isspace(*cp)) 15558888Smckusick cp++; 156*59140Smckusick newval = cp; 157*59140Smckusick newsize = strlen(cp); 15858888Smckusick } 159*59140Smckusick if ((indx = findname(string, "top", &bufp, &toplist)) == -1) 16058888Smckusick return; 16158888Smckusick mib[0] = indx; 16258888Smckusick lp = &secondlevel[indx]; 16358888Smckusick if (lp->list == 0) { 16458888Smckusick fprintf(stderr, "%s: class is not implemented\n", 16558888Smckusick topname[indx]); 16658888Smckusick return; 16758888Smckusick } 16858910Smckusick if (bufp == NULL) { 169*59140Smckusick listall(topname[indx].ctl_name, lp); 17058910Smckusick return; 17158910Smckusick } 17258888Smckusick if ((indx = findname(string, "second", &bufp, lp)) == -1) 17358888Smckusick return; 17458888Smckusick mib[1] = indx; 175*59140Smckusick type = lp->list[indx].ctl_type; 176*59140Smckusick len = 2; 17758888Smckusick switch (mib[0]) { 17858888Smckusick 17958888Smckusick case CTL_KERN: 18058888Smckusick switch (mib[1]) { 18158888Smckusick case KERN_VNODE: 18258888Smckusick case KERN_FILE: 18358888Smckusick if (flags == 0) 18458888Smckusick return; 18558888Smckusick fprintf(stderr, 18658888Smckusick "Use pstat to view %s information\n", string); 18758888Smckusick return; 18858888Smckusick case KERN_PROC: 18958888Smckusick if (flags == 0) 19058888Smckusick return; 19158888Smckusick fprintf(stderr, 19258888Smckusick "Use ps to view %s information\n", string); 19358888Smckusick return; 19458888Smckusick case KERN_CLOCKRATE: 19558888Smckusick isclockrate = 1; 19658888Smckusick break; 19758888Smckusick } 19858888Smckusick break; 19958888Smckusick 20058888Smckusick case CTL_HW: 20158888Smckusick break; 20258888Smckusick 20358888Smckusick case CTL_VM: 20458888Smckusick if (mib[1] == VM_LOADAVG) { 20558888Smckusick double loads[3]; 20658888Smckusick 20758888Smckusick getloadavg(loads, 3); 20858910Smckusick if (!nflag) 20958910Smckusick fprintf(stdout, "%s: ", string); 21058910Smckusick fprintf(stdout, "%.2f %.2f %.2f\n", 21158888Smckusick loads[0], loads[1], loads[2]); 21258888Smckusick return; 21358888Smckusick } 21458888Smckusick if (flags == 0) 21558888Smckusick return; 21658888Smckusick fprintf(stderr, 21758888Smckusick "Use vmstat or systat to view %s information\n", string); 21858888Smckusick return; 21958888Smckusick 22058888Smckusick case CTL_NET: 221*59140Smckusick if (mib[1] == PF_INET) { 222*59140Smckusick len = sysctl_inet(string, &bufp, mib, flags, &type); 223*59140Smckusick if (len >= 0) 224*59140Smckusick break; 225*59140Smckusick return; 226*59140Smckusick } 22758888Smckusick if (flags == 0) 22858888Smckusick return; 22958888Smckusick fprintf(stderr, "Use netstat to view %s information\n", string); 23058888Smckusick return; 23158888Smckusick 23258888Smckusick case CTL_FS: 23358888Smckusick case CTL_DEBUG: 23458888Smckusick case CTL_MACHDEP: 23558888Smckusick break; 23658888Smckusick 23758888Smckusick default: 23858888Smckusick fprintf(stderr, "Illegal top level value: %d\n", mib[0]); 23958888Smckusick return; 24058888Smckusick 24158888Smckusick } 242*59140Smckusick if (bufp) { 243*59140Smckusick fprintf(stderr, "name %s in %s is unknown\n", *bufp, string); 244*59140Smckusick return; 245*59140Smckusick } 246*59140Smckusick if (newsize > 0) { 247*59140Smckusick switch (type) { 248*59140Smckusick case CTLTYPE_INT: 249*59140Smckusick intval = atoi(newval); 250*59140Smckusick newval = &intval; 251*59140Smckusick newsize = sizeof intval; 252*59140Smckusick break; 25358888Smckusick 254*59140Smckusick case CTLTYPE_QUAD: 255*59140Smckusick sscanf(newval, "%qd", &quadval); 256*59140Smckusick newval = &quadval; 257*59140Smckusick newsize = sizeof quadval; 258*59140Smckusick break; 259*59140Smckusick } 260*59140Smckusick } 26158888Smckusick size = BUFSIZ; 262*59140Smckusick if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) { 26358888Smckusick if (flags == 0) 26458888Smckusick return; 26558888Smckusick switch (errno) { 26658888Smckusick case EOPNOTSUPP: 26758888Smckusick fprintf(stderr, "%s: value is not available\n", string); 26858888Smckusick return; 26958888Smckusick case ENOTDIR: 27058888Smckusick fprintf(stderr, "%s: specification is incomplete\n", 27158888Smckusick string); 27258888Smckusick return; 27358888Smckusick case ENOMEM: 27458888Smckusick fprintf(stderr, "%s: type is unknown to this program\n", 27558888Smckusick string); 27658888Smckusick return; 27758888Smckusick default: 27858888Smckusick perror(string); 27958888Smckusick return; 28058888Smckusick } 28158888Smckusick } 28258888Smckusick if (isclockrate) { 28358888Smckusick struct clockinfo *clkp = (struct clockinfo *)buf; 28458888Smckusick 28558910Smckusick if (!nflag) 28658910Smckusick fprintf(stdout, "%s: ", string); 28758888Smckusick fprintf(stdout, 28858910Smckusick "hz = %d, tick = %d, profhz = %d, stathz = %d\n", 28958910Smckusick clkp->hz, clkp->tick, clkp->profhz, clkp->stathz); 29058888Smckusick return; 29158888Smckusick } 292*59140Smckusick switch (type) { 293*59140Smckusick case CTLTYPE_INT: 29458910Smckusick if (newsize == 0) { 29558910Smckusick if (!nflag) 29658910Smckusick fprintf(stdout, "%s = ", string); 29758910Smckusick fprintf(stdout, "%d\n", *(int *)buf); 29858910Smckusick } else { 29958910Smckusick if (!nflag) 30058910Smckusick fprintf(stdout, "%s: %d -> ", string, 30158910Smckusick *(int *)buf); 30258910Smckusick fprintf(stdout, "%d\n", *(int *)newval); 30358910Smckusick } 304*59140Smckusick return; 305*59140Smckusick 306*59140Smckusick case CTLTYPE_STRING: 30758910Smckusick if (newsize == 0) { 30858910Smckusick if (!nflag) 30958910Smckusick fprintf(stdout, "%s = ", string); 31058910Smckusick fprintf(stdout, "%s\n", buf); 31158910Smckusick } else { 31258910Smckusick if (!nflag) 31358910Smckusick fprintf(stdout, "%s: %s -> ", string, buf); 31458910Smckusick fprintf(stdout, "%s\n", newval); 31558910Smckusick } 316*59140Smckusick return; 317*59140Smckusick 318*59140Smckusick case CTLTYPE_QUAD: 319*59140Smckusick if (newsize == 0) { 320*59140Smckusick if (!nflag) 321*59140Smckusick fprintf(stdout, "%s = ", string); 322*59140Smckusick fprintf(stdout, "%qd\n", *(quad_t *)buf); 323*59140Smckusick } else { 324*59140Smckusick if (!nflag) 325*59140Smckusick fprintf(stdout, "%s: %qd -> ", string, 326*59140Smckusick *(quad_t *)buf); 327*59140Smckusick fprintf(stdout, "%qd\n", *(quad_t *)newval); 328*59140Smckusick } 329*59140Smckusick return; 330*59140Smckusick 331*59140Smckusick case CTLTYPE_STRUCT: 332*59140Smckusick fprintf(stderr, "%s: unknown structure returned\n", 333*59140Smckusick string); 334*59140Smckusick return; 335*59140Smckusick 336*59140Smckusick default: 337*59140Smckusick case CTLTYPE_NODE: 338*59140Smckusick fprintf(stderr, "%s: unknown type returned\n", 339*59140Smckusick string); 340*59140Smckusick return; 341*59140Smckusick } 34258888Smckusick } 34358888Smckusick 344*59140Smckusick struct ctlname inetname[] = CTL_IPPROTO_NAMES; 345*59140Smckusick struct ctlname ipname[] = IPCTL_NAMES; 346*59140Smckusick struct ctlname icmpname[] = ICMPCTL_NAMES; 347*59140Smckusick struct list inetlist = { inetname, IPPROTO_MAXID }; 348*59140Smckusick struct list inetvars[] = { 349*59140Smckusick { ipname, IPCTL_MAXID }, 350*59140Smckusick { icmpname, ICMPCTL_MAXID }, 351*59140Smckusick }; 352*59140Smckusick 35358888Smckusick /* 354*59140Smckusick * handle internet requests 355*59140Smckusick */ 356*59140Smckusick sysctl_inet(string, bufpp, mib, flags, typep) 357*59140Smckusick char *string; 358*59140Smckusick char **bufpp; 359*59140Smckusick int mib[]; 360*59140Smckusick int flags; 361*59140Smckusick int *typep; 362*59140Smckusick { 363*59140Smckusick struct list *lp; 364*59140Smckusick int indx; 365*59140Smckusick 366*59140Smckusick if (*bufpp == NULL) { 367*59140Smckusick listall(string, &inetlist); 368*59140Smckusick return (-1); 369*59140Smckusick } 370*59140Smckusick if ((indx = findname(string, "third", bufpp, &inetlist)) == -1) 371*59140Smckusick return (-1); 372*59140Smckusick mib[2] = indx; 373*59140Smckusick if (indx < 2) 374*59140Smckusick lp = &inetvars[indx]; 375*59140Smckusick else if (!flags) 376*59140Smckusick return (-1); 377*59140Smckusick else { 378*59140Smckusick fprintf(stderr, "%s: no variables defined for this protocol\n", 379*59140Smckusick string); 380*59140Smckusick return (-1); 381*59140Smckusick } 382*59140Smckusick if (*bufpp == NULL) { 383*59140Smckusick listall(string, lp); 384*59140Smckusick return (-1); 385*59140Smckusick } 386*59140Smckusick if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 387*59140Smckusick return (-1); 388*59140Smckusick mib[3] = indx; 389*59140Smckusick *typep = lp->list[indx].ctl_type; 390*59140Smckusick return (4); 391*59140Smckusick } 392*59140Smckusick 393*59140Smckusick /* 39458888Smckusick * Scan a list of names searching for a particular name. 39558888Smckusick */ 39658888Smckusick findname(string, level, bufp, namelist) 39758888Smckusick char *string; 39858888Smckusick char *level; 39958888Smckusick char **bufp; 40058888Smckusick struct list *namelist; 40158888Smckusick { 40258888Smckusick char *name; 40358888Smckusick int i; 40458888Smckusick 40558888Smckusick if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { 40658888Smckusick fprintf(stderr, "%s: incomplete specification\n", string); 40758888Smckusick return (-1); 40858888Smckusick } 40958888Smckusick for (i = 0; i < namelist->size; i++) 410*59140Smckusick if (!strcmp(name, namelist->list[i].ctl_name)) 41158888Smckusick break; 41258888Smckusick if (i == namelist->size) { 41358888Smckusick fprintf(stderr, "%s level name %s in %s is invalid\n", 41458888Smckusick level, name, string); 41558888Smckusick return (-1); 41658888Smckusick } 41758888Smckusick return (i); 41858888Smckusick } 41958888Smckusick 42058888Smckusick usage() 42158888Smckusick { 42258888Smckusick 42358911Smckusick (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n", 42458911Smckusick "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...", 42558911Smckusick "sysctl [-n] -a", "sysctl [-n] -A"); 42658888Smckusick exit(1); 42758888Smckusick } 428