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*59159Smckusick static char sccsid[] = "@(#)sysctl.c 5.5 (Berkeley) 04/19/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> 2359140Smckusick #include <netinet/in.h> 2459140Smckusick #include <netinet/in_systm.h> 2559140Smckusick #include <netinet/ip.h> 2659140Smckusick #include <netinet/ip_icmp.h> 2759140Smckusick #include <netinet/icmp_var.h> 2858888Smckusick #include <errno.h> 2958888Smckusick #include <stdlib.h> 3058888Smckusick #include <string.h> 3158888Smckusick #include <stdio.h> 3258888Smckusick 3359140Smckusick struct ctlname topname[] = CTL_NAMES; 3459140Smckusick struct ctlname kernname[] = CTL_KERN_NAMES; 3559140Smckusick struct ctlname vmname[] = CTL_VM_NAMES; 3659140Smckusick struct ctlname netname[] = CTL_NET_NAMES; 3759140Smckusick struct ctlname hwname[] = CTL_HW_NAMES; 38*59159Smckusick struct ctlname debugname[CTL_DEBUG_MAXID]; 39*59159Smckusick char names[BUFSIZ]; 4058888Smckusick 4158888Smckusick struct list { 4259140Smckusick struct ctlname *list; 4358888Smckusick int size; 4459140Smckusick }; 4559140Smckusick struct list toplist = { topname, CTL_MAXID }; 4659140Smckusick struct list secondlevel[] = { 4758888Smckusick { 0, 0 }, /* CTL_UNSPEC */ 4858888Smckusick { kernname, KERN_MAXID }, /* CTL_KERN */ 4958888Smckusick { vmname, VM_MAXID }, /* CTL_VM */ 5058888Smckusick { 0, 0 }, /* CTL_FS */ 5158888Smckusick { netname, NET_MAXID }, /* CTL_NET */ 52*59159Smckusick { 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */ 5358888Smckusick { hwname, HW_MAXID }, /* CTL_HW */ 5458888Smckusick { 0, 0 }, /* CTL_MACHDEP */ 5558888Smckusick }; 5658888Smckusick 5758910Smckusick int Aflag, aflag, nflag, wflag; 5858888Smckusick 5958888Smckusick int 6058888Smckusick main(argc, argv) 6158888Smckusick int argc; 6258888Smckusick char *argv[]; 6358888Smckusick { 6458888Smckusick extern char *optarg; 6558888Smckusick extern int optind; 6658910Smckusick int ch, lvl1; 6758888Smckusick 6858910Smckusick while ((ch = getopt(argc, argv, "Aanw")) != EOF) { 6958888Smckusick switch (ch) { 7058888Smckusick 7158888Smckusick case 'A': 7258888Smckusick Aflag = 1; 7358888Smckusick break; 7458888Smckusick 7558888Smckusick case 'a': 7658888Smckusick aflag = 1; 7758888Smckusick break; 7858888Smckusick 7958910Smckusick case 'n': 8058910Smckusick nflag = 1; 8158910Smckusick break; 8258910Smckusick 8358888Smckusick case 'w': 8458888Smckusick wflag = 1; 8558888Smckusick break; 8658888Smckusick 8758888Smckusick default: 8858888Smckusick usage(); 8958888Smckusick } 9058888Smckusick } 9158888Smckusick argc -= optind; 9258888Smckusick argv += optind; 9358888Smckusick 9458888Smckusick if (Aflag || aflag) { 95*59159Smckusick debuginit(); 9658910Smckusick for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++) 9759140Smckusick listall(topname[lvl1].ctl_name, &secondlevel[lvl1]); 9858888Smckusick exit(0); 9958888Smckusick } 10058888Smckusick if (argc == 0) 10158888Smckusick usage(); 10258888Smckusick while (argc-- > 0) 10358888Smckusick parse(*argv, 1); 10458888Smckusick exit(0); 10558888Smckusick } 10658888Smckusick 10758888Smckusick /* 10858888Smckusick * List all variables known to the system. 10958888Smckusick */ 11059140Smckusick listall(prefix, lp) 11159140Smckusick char *prefix; 11259140Smckusick struct list *lp; 11358888Smckusick { 11458910Smckusick int lvl2; 11558888Smckusick char *cp, name[BUFSIZ]; 11658888Smckusick 11758910Smckusick if (lp->list == 0) 11858910Smckusick return; 11959140Smckusick strcpy(name, prefix); 12058910Smckusick cp = &name[strlen(name)]; 12158910Smckusick *cp++ = '.'; 12259140Smckusick for (lvl2 = 0; lvl2 < lp->size; lvl2++) { 12359140Smckusick if (lp->list[lvl2].ctl_name == 0) 12459140Smckusick continue; 12559140Smckusick strcpy(cp, lp->list[lvl2].ctl_name); 12658910Smckusick parse(name, Aflag); 12758888Smckusick } 12858888Smckusick } 12958888Smckusick 13058888Smckusick /* 13158888Smckusick * Parse a name into a MIB entry. 13258888Smckusick * Lookup and print out the MIB entry if it exists. 13358888Smckusick * Set a new value if requested. 13458888Smckusick */ 13558888Smckusick parse(string, flags) 13658888Smckusick char *string; 13758888Smckusick int flags; 13858888Smckusick { 13959140Smckusick int indx, type, size, len; 14058888Smckusick int isclockrate = 0; 14158888Smckusick void *newval = 0; 14258888Smckusick int intval, newsize = 0; 14359140Smckusick quad_t quadval; 14459140Smckusick struct list *lp; 14558888Smckusick int mib[CTL_MAXNAME]; 14658888Smckusick char *cp, *bufp, buf[BUFSIZ], strval[BUFSIZ]; 14758888Smckusick 14858888Smckusick bufp = buf; 14958888Smckusick snprintf(buf, BUFSIZ, "%s", string); 15058888Smckusick if ((cp = strchr(string, '=')) != NULL) { 15158888Smckusick if (!wflag) { 15258888Smckusick fprintf(stderr, "Must specify -w to set variables\n"); 15358888Smckusick exit(2); 15458888Smckusick } 15558888Smckusick *strchr(buf, '=') = '\0'; 15658888Smckusick *cp++ = '\0'; 15758888Smckusick while (isspace(*cp)) 15858888Smckusick cp++; 15959140Smckusick newval = cp; 16059140Smckusick newsize = strlen(cp); 16158888Smckusick } 16259140Smckusick if ((indx = findname(string, "top", &bufp, &toplist)) == -1) 16358888Smckusick return; 16458888Smckusick mib[0] = indx; 165*59159Smckusick if (indx == CTL_DEBUG) 166*59159Smckusick debuginit(); 16758888Smckusick lp = &secondlevel[indx]; 16858888Smckusick if (lp->list == 0) { 16958888Smckusick fprintf(stderr, "%s: class is not implemented\n", 17058888Smckusick topname[indx]); 17158888Smckusick return; 17258888Smckusick } 17358910Smckusick if (bufp == NULL) { 17459140Smckusick listall(topname[indx].ctl_name, lp); 17558910Smckusick return; 17658910Smckusick } 17758888Smckusick if ((indx = findname(string, "second", &bufp, lp)) == -1) 17858888Smckusick return; 17958888Smckusick mib[1] = indx; 18059140Smckusick type = lp->list[indx].ctl_type; 18159140Smckusick len = 2; 18258888Smckusick switch (mib[0]) { 18358888Smckusick 18458888Smckusick case CTL_KERN: 18558888Smckusick switch (mib[1]) { 18658888Smckusick case KERN_VNODE: 18758888Smckusick case KERN_FILE: 18858888Smckusick if (flags == 0) 18958888Smckusick return; 19058888Smckusick fprintf(stderr, 19158888Smckusick "Use pstat to view %s information\n", string); 19258888Smckusick return; 19358888Smckusick case KERN_PROC: 19458888Smckusick if (flags == 0) 19558888Smckusick return; 19658888Smckusick fprintf(stderr, 19758888Smckusick "Use ps to view %s information\n", string); 19858888Smckusick return; 19958888Smckusick case KERN_CLOCKRATE: 20058888Smckusick isclockrate = 1; 20158888Smckusick break; 20258888Smckusick } 20358888Smckusick break; 20458888Smckusick 20558888Smckusick case CTL_HW: 20658888Smckusick break; 20758888Smckusick 20858888Smckusick case CTL_VM: 20958888Smckusick if (mib[1] == VM_LOADAVG) { 21058888Smckusick double loads[3]; 21158888Smckusick 21258888Smckusick getloadavg(loads, 3); 21358910Smckusick if (!nflag) 21458910Smckusick fprintf(stdout, "%s: ", string); 21558910Smckusick fprintf(stdout, "%.2f %.2f %.2f\n", 21658888Smckusick loads[0], loads[1], loads[2]); 21758888Smckusick return; 21858888Smckusick } 21958888Smckusick if (flags == 0) 22058888Smckusick return; 22158888Smckusick fprintf(stderr, 22258888Smckusick "Use vmstat or systat to view %s information\n", string); 22358888Smckusick return; 22458888Smckusick 22558888Smckusick case CTL_NET: 22659140Smckusick if (mib[1] == PF_INET) { 22759140Smckusick len = sysctl_inet(string, &bufp, mib, flags, &type); 22859140Smckusick if (len >= 0) 22959140Smckusick break; 23059140Smckusick return; 23159140Smckusick } 23258888Smckusick if (flags == 0) 23358888Smckusick return; 23458888Smckusick fprintf(stderr, "Use netstat to view %s information\n", string); 23558888Smckusick return; 23658888Smckusick 237*59159Smckusick case CTL_DEBUG: 238*59159Smckusick mib[2] = CTL_DEBUG_VALUE; 239*59159Smckusick len = 3; 240*59159Smckusick break; 241*59159Smckusick 24258888Smckusick case CTL_FS: 24358888Smckusick case CTL_MACHDEP: 24458888Smckusick break; 24558888Smckusick 24658888Smckusick default: 24758888Smckusick fprintf(stderr, "Illegal top level value: %d\n", mib[0]); 24858888Smckusick return; 24958888Smckusick 25058888Smckusick } 25159140Smckusick if (bufp) { 25259140Smckusick fprintf(stderr, "name %s in %s is unknown\n", *bufp, string); 25359140Smckusick return; 25459140Smckusick } 25559140Smckusick if (newsize > 0) { 25659140Smckusick switch (type) { 25759140Smckusick case CTLTYPE_INT: 25859140Smckusick intval = atoi(newval); 25959140Smckusick newval = &intval; 26059140Smckusick newsize = sizeof intval; 26159140Smckusick break; 26258888Smckusick 26359140Smckusick case CTLTYPE_QUAD: 26459140Smckusick sscanf(newval, "%qd", &quadval); 26559140Smckusick newval = &quadval; 26659140Smckusick newsize = sizeof quadval; 26759140Smckusick break; 26859140Smckusick } 26959140Smckusick } 27058888Smckusick size = BUFSIZ; 27159140Smckusick if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) { 27258888Smckusick if (flags == 0) 27358888Smckusick return; 27458888Smckusick switch (errno) { 27558888Smckusick case EOPNOTSUPP: 27658888Smckusick fprintf(stderr, "%s: value is not available\n", string); 27758888Smckusick return; 27858888Smckusick case ENOTDIR: 27958888Smckusick fprintf(stderr, "%s: specification is incomplete\n", 28058888Smckusick string); 28158888Smckusick return; 28258888Smckusick case ENOMEM: 28358888Smckusick fprintf(stderr, "%s: type is unknown to this program\n", 28458888Smckusick string); 28558888Smckusick return; 28658888Smckusick default: 28758888Smckusick perror(string); 28858888Smckusick return; 28958888Smckusick } 29058888Smckusick } 29158888Smckusick if (isclockrate) { 29258888Smckusick struct clockinfo *clkp = (struct clockinfo *)buf; 29358888Smckusick 29458910Smckusick if (!nflag) 29558910Smckusick fprintf(stdout, "%s: ", string); 29658888Smckusick fprintf(stdout, 29758910Smckusick "hz = %d, tick = %d, profhz = %d, stathz = %d\n", 29858910Smckusick clkp->hz, clkp->tick, clkp->profhz, clkp->stathz); 29958888Smckusick return; 30058888Smckusick } 30159140Smckusick switch (type) { 30259140Smckusick case CTLTYPE_INT: 30358910Smckusick if (newsize == 0) { 30458910Smckusick if (!nflag) 30558910Smckusick fprintf(stdout, "%s = ", string); 30658910Smckusick fprintf(stdout, "%d\n", *(int *)buf); 30758910Smckusick } else { 30858910Smckusick if (!nflag) 30958910Smckusick fprintf(stdout, "%s: %d -> ", string, 31058910Smckusick *(int *)buf); 31158910Smckusick fprintf(stdout, "%d\n", *(int *)newval); 31258910Smckusick } 31359140Smckusick return; 31459140Smckusick 31559140Smckusick case CTLTYPE_STRING: 31658910Smckusick if (newsize == 0) { 31758910Smckusick if (!nflag) 31858910Smckusick fprintf(stdout, "%s = ", string); 31958910Smckusick fprintf(stdout, "%s\n", buf); 32058910Smckusick } else { 32158910Smckusick if (!nflag) 32258910Smckusick fprintf(stdout, "%s: %s -> ", string, buf); 32358910Smckusick fprintf(stdout, "%s\n", newval); 32458910Smckusick } 32559140Smckusick return; 32659140Smckusick 32759140Smckusick case CTLTYPE_QUAD: 32859140Smckusick if (newsize == 0) { 32959140Smckusick if (!nflag) 33059140Smckusick fprintf(stdout, "%s = ", string); 33159140Smckusick fprintf(stdout, "%qd\n", *(quad_t *)buf); 33259140Smckusick } else { 33359140Smckusick if (!nflag) 33459140Smckusick fprintf(stdout, "%s: %qd -> ", string, 33559140Smckusick *(quad_t *)buf); 33659140Smckusick fprintf(stdout, "%qd\n", *(quad_t *)newval); 33759140Smckusick } 33859140Smckusick return; 33959140Smckusick 34059140Smckusick case CTLTYPE_STRUCT: 34159140Smckusick fprintf(stderr, "%s: unknown structure returned\n", 34259140Smckusick string); 34359140Smckusick return; 34459140Smckusick 34559140Smckusick default: 34659140Smckusick case CTLTYPE_NODE: 34759140Smckusick fprintf(stderr, "%s: unknown type returned\n", 34859140Smckusick string); 34959140Smckusick return; 35059140Smckusick } 35158888Smckusick } 35258888Smckusick 353*59159Smckusick /* 354*59159Smckusick * Initialize the set of debugging names 355*59159Smckusick */ 356*59159Smckusick debuginit() 357*59159Smckusick { 358*59159Smckusick int mib[3], size, loc, i; 359*59159Smckusick 360*59159Smckusick if (secondlevel[CTL_DEBUG].list != 0) 361*59159Smckusick return; 362*59159Smckusick secondlevel[CTL_DEBUG].list = debugname; 363*59159Smckusick mib[0] = CTL_DEBUG; 364*59159Smckusick mib[2] = CTL_DEBUG_NAME; 365*59159Smckusick for (loc = 0, i = 0; i < CTL_DEBUG_MAXID; i++) { 366*59159Smckusick mib[1] = i; 367*59159Smckusick size = BUFSIZ - loc; 368*59159Smckusick if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1) 369*59159Smckusick continue; 370*59159Smckusick debugname[i].ctl_name = &names[loc]; 371*59159Smckusick debugname[i].ctl_type = CTLTYPE_INT; 372*59159Smckusick loc += size; 373*59159Smckusick } 374*59159Smckusick } 375*59159Smckusick 37659140Smckusick struct ctlname inetname[] = CTL_IPPROTO_NAMES; 37759140Smckusick struct ctlname ipname[] = IPCTL_NAMES; 37859140Smckusick struct ctlname icmpname[] = ICMPCTL_NAMES; 37959140Smckusick struct list inetlist = { inetname, IPPROTO_MAXID }; 38059140Smckusick struct list inetvars[] = { 38159140Smckusick { ipname, IPCTL_MAXID }, 38259140Smckusick { icmpname, ICMPCTL_MAXID }, 38359140Smckusick }; 38459140Smckusick 38558888Smckusick /* 38659140Smckusick * handle internet requests 38759140Smckusick */ 38859140Smckusick sysctl_inet(string, bufpp, mib, flags, typep) 38959140Smckusick char *string; 39059140Smckusick char **bufpp; 39159140Smckusick int mib[]; 39259140Smckusick int flags; 39359140Smckusick int *typep; 39459140Smckusick { 39559140Smckusick struct list *lp; 39659140Smckusick int indx; 39759140Smckusick 39859140Smckusick if (*bufpp == NULL) { 39959140Smckusick listall(string, &inetlist); 40059140Smckusick return (-1); 40159140Smckusick } 40259140Smckusick if ((indx = findname(string, "third", bufpp, &inetlist)) == -1) 40359140Smckusick return (-1); 40459140Smckusick mib[2] = indx; 40559140Smckusick if (indx < 2) 40659140Smckusick lp = &inetvars[indx]; 40759140Smckusick else if (!flags) 40859140Smckusick return (-1); 40959140Smckusick else { 41059140Smckusick fprintf(stderr, "%s: no variables defined for this protocol\n", 41159140Smckusick string); 41259140Smckusick return (-1); 41359140Smckusick } 41459140Smckusick if (*bufpp == NULL) { 41559140Smckusick listall(string, lp); 41659140Smckusick return (-1); 41759140Smckusick } 41859140Smckusick if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 41959140Smckusick return (-1); 42059140Smckusick mib[3] = indx; 42159140Smckusick *typep = lp->list[indx].ctl_type; 42259140Smckusick return (4); 42359140Smckusick } 42459140Smckusick 42559140Smckusick /* 42658888Smckusick * Scan a list of names searching for a particular name. 42758888Smckusick */ 42858888Smckusick findname(string, level, bufp, namelist) 42958888Smckusick char *string; 43058888Smckusick char *level; 43158888Smckusick char **bufp; 43258888Smckusick struct list *namelist; 43358888Smckusick { 43458888Smckusick char *name; 43558888Smckusick int i; 43658888Smckusick 43758888Smckusick if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { 43858888Smckusick fprintf(stderr, "%s: incomplete specification\n", string); 43958888Smckusick return (-1); 44058888Smckusick } 44158888Smckusick for (i = 0; i < namelist->size; i++) 44259140Smckusick if (!strcmp(name, namelist->list[i].ctl_name)) 44358888Smckusick break; 44458888Smckusick if (i == namelist->size) { 44558888Smckusick fprintf(stderr, "%s level name %s in %s is invalid\n", 44658888Smckusick level, name, string); 44758888Smckusick return (-1); 44858888Smckusick } 44958888Smckusick return (i); 45058888Smckusick } 45158888Smckusick 45258888Smckusick usage() 45358888Smckusick { 45458888Smckusick 45558911Smckusick (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n", 45658911Smckusick "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...", 45758911Smckusick "sysctl [-n] -a", "sysctl [-n] -A"); 45858888Smckusick exit(1); 45958888Smckusick } 460