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*59658Smckusick static char sccsid[] = "@(#)sysctl.c 5.9 (Berkeley) 05/02/93"; 1658888Smckusick #endif /* not lint */ 1758888Smckusick 1859379Sbostic #include <sys/param.h> 19*59658Smckusick #include <sys/gmon.h> 2058888Smckusick #include <sys/stat.h> 2158888Smckusick #include <sys/sysctl.h> 2258888Smckusick #include <sys/socket.h> 2358888Smckusick #include <vm/vm_param.h> 2459379Sbostic 2559140Smckusick #include <netinet/in.h> 2659140Smckusick #include <netinet/in_systm.h> 2759140Smckusick #include <netinet/ip.h> 2859140Smckusick #include <netinet/ip_icmp.h> 2959140Smckusick #include <netinet/icmp_var.h> 3059311Smckusick #include <netinet/ip_var.h> 3159311Smckusick #include <netinet/udp.h> 3259311Smckusick #include <netinet/udp_var.h> 3359379Sbostic 3458888Smckusick #include <errno.h> 3559379Sbostic #include <stdio.h> 3658888Smckusick #include <stdlib.h> 3758888Smckusick #include <string.h> 3858888Smckusick 3959140Smckusick struct ctlname topname[] = CTL_NAMES; 4059140Smckusick struct ctlname kernname[] = CTL_KERN_NAMES; 4159140Smckusick struct ctlname vmname[] = CTL_VM_NAMES; 4259140Smckusick struct ctlname netname[] = CTL_NET_NAMES; 4359140Smckusick struct ctlname hwname[] = CTL_HW_NAMES; 4459159Smckusick struct ctlname debugname[CTL_DEBUG_MAXID]; 4559159Smckusick char names[BUFSIZ]; 4658888Smckusick 4758888Smckusick struct list { 4859140Smckusick struct ctlname *list; 4958888Smckusick int size; 5059140Smckusick }; 5159140Smckusick struct list toplist = { topname, CTL_MAXID }; 5259140Smckusick struct list secondlevel[] = { 5358888Smckusick { 0, 0 }, /* CTL_UNSPEC */ 5458888Smckusick { kernname, KERN_MAXID }, /* CTL_KERN */ 5558888Smckusick { vmname, VM_MAXID }, /* CTL_VM */ 5658888Smckusick { 0, 0 }, /* CTL_FS */ 5758888Smckusick { netname, NET_MAXID }, /* CTL_NET */ 5859159Smckusick { 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */ 5958888Smckusick { hwname, HW_MAXID }, /* CTL_HW */ 6058888Smckusick { 0, 0 }, /* CTL_MACHDEP */ 6158888Smckusick }; 6258888Smckusick 6358910Smckusick int Aflag, aflag, nflag, wflag; 6458888Smckusick 6558888Smckusick int 6658888Smckusick main(argc, argv) 6758888Smckusick int argc; 6858888Smckusick char *argv[]; 6958888Smckusick { 7058888Smckusick extern char *optarg; 7158888Smckusick extern int optind; 7258910Smckusick int ch, lvl1; 7358888Smckusick 7458910Smckusick while ((ch = getopt(argc, argv, "Aanw")) != EOF) { 7558888Smckusick switch (ch) { 7658888Smckusick 7758888Smckusick case 'A': 7858888Smckusick Aflag = 1; 7958888Smckusick break; 8058888Smckusick 8158888Smckusick case 'a': 8258888Smckusick aflag = 1; 8358888Smckusick break; 8458888Smckusick 8558910Smckusick case 'n': 8658910Smckusick nflag = 1; 8758910Smckusick break; 8858910Smckusick 8958888Smckusick case 'w': 9058888Smckusick wflag = 1; 9158888Smckusick break; 9258888Smckusick 9358888Smckusick default: 9458888Smckusick usage(); 9558888Smckusick } 9658888Smckusick } 9758888Smckusick argc -= optind; 9858888Smckusick argv += optind; 9958888Smckusick 10058888Smckusick if (Aflag || aflag) { 10159159Smckusick debuginit(); 10258910Smckusick for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++) 10359140Smckusick listall(topname[lvl1].ctl_name, &secondlevel[lvl1]); 10458888Smckusick exit(0); 10558888Smckusick } 10658888Smckusick if (argc == 0) 10758888Smckusick usage(); 10858888Smckusick while (argc-- > 0) 10958888Smckusick parse(*argv, 1); 11058888Smckusick exit(0); 11158888Smckusick } 11258888Smckusick 11358888Smckusick /* 11458888Smckusick * List all variables known to the system. 11558888Smckusick */ 11659140Smckusick listall(prefix, lp) 11759140Smckusick char *prefix; 11859140Smckusick struct list *lp; 11958888Smckusick { 12058910Smckusick int lvl2; 12158888Smckusick char *cp, name[BUFSIZ]; 12258888Smckusick 12358910Smckusick if (lp->list == 0) 12458910Smckusick return; 12559140Smckusick strcpy(name, prefix); 12658910Smckusick cp = &name[strlen(name)]; 12758910Smckusick *cp++ = '.'; 12859140Smckusick for (lvl2 = 0; lvl2 < lp->size; lvl2++) { 12959140Smckusick if (lp->list[lvl2].ctl_name == 0) 13059140Smckusick continue; 13159140Smckusick strcpy(cp, lp->list[lvl2].ctl_name); 13258910Smckusick parse(name, Aflag); 13358888Smckusick } 13458888Smckusick } 13558888Smckusick 13658888Smckusick /* 13758888Smckusick * Parse a name into a MIB entry. 13858888Smckusick * Lookup and print out the MIB entry if it exists. 13958888Smckusick * Set a new value if requested. 14058888Smckusick */ 14158888Smckusick parse(string, flags) 14258888Smckusick char *string; 14358888Smckusick int flags; 14458888Smckusick { 145*59658Smckusick int indx, type, state, size, len; 14658888Smckusick int isclockrate = 0; 14758888Smckusick void *newval = 0; 14858888Smckusick int intval, newsize = 0; 14959140Smckusick quad_t quadval; 15059140Smckusick struct list *lp; 15158888Smckusick int mib[CTL_MAXNAME]; 15258888Smckusick char *cp, *bufp, buf[BUFSIZ], strval[BUFSIZ]; 15358888Smckusick 15458888Smckusick bufp = buf; 15558888Smckusick snprintf(buf, BUFSIZ, "%s", string); 15658888Smckusick if ((cp = strchr(string, '=')) != NULL) { 15758888Smckusick if (!wflag) { 15858888Smckusick fprintf(stderr, "Must specify -w to set variables\n"); 15958888Smckusick exit(2); 16058888Smckusick } 16158888Smckusick *strchr(buf, '=') = '\0'; 16258888Smckusick *cp++ = '\0'; 16358888Smckusick while (isspace(*cp)) 16458888Smckusick cp++; 16559140Smckusick newval = cp; 16659140Smckusick newsize = strlen(cp); 16758888Smckusick } 16859140Smckusick if ((indx = findname(string, "top", &bufp, &toplist)) == -1) 16958888Smckusick return; 17058888Smckusick mib[0] = indx; 17159159Smckusick if (indx == CTL_DEBUG) 17259159Smckusick debuginit(); 17358888Smckusick lp = &secondlevel[indx]; 17458888Smckusick if (lp->list == 0) { 17558888Smckusick fprintf(stderr, "%s: class is not implemented\n", 17658888Smckusick topname[indx]); 17758888Smckusick return; 17858888Smckusick } 17958910Smckusick if (bufp == NULL) { 18059140Smckusick listall(topname[indx].ctl_name, lp); 18158910Smckusick return; 18258910Smckusick } 18358888Smckusick if ((indx = findname(string, "second", &bufp, lp)) == -1) 18458888Smckusick return; 18558888Smckusick mib[1] = indx; 18659140Smckusick type = lp->list[indx].ctl_type; 18759140Smckusick len = 2; 18858888Smckusick switch (mib[0]) { 18958888Smckusick 19058888Smckusick case CTL_KERN: 19158888Smckusick switch (mib[1]) { 192*59658Smckusick case KERN_PROF: 193*59658Smckusick mib[2] = GPROF_STATE; 194*59658Smckusick size = sizeof state; 195*59658Smckusick if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) { 196*59658Smckusick if (flags == 0) 197*59658Smckusick return; 198*59658Smckusick if (!nflag) 199*59658Smckusick fprintf(stdout, "%s: ", string); 200*59658Smckusick fprintf(stderr, 201*59658Smckusick "kernel is not compiled for profiling\n"); 202*59658Smckusick return; 203*59658Smckusick } 204*59658Smckusick if (!nflag) 205*59658Smckusick fprintf(stdout, "%s: %s\n", string, 206*59658Smckusick state == GMON_PROF_OFF ? "off" : "running"); 207*59658Smckusick return; 20858888Smckusick case KERN_VNODE: 20958888Smckusick case KERN_FILE: 21058888Smckusick if (flags == 0) 21158888Smckusick return; 21258888Smckusick fprintf(stderr, 21358888Smckusick "Use pstat to view %s information\n", string); 21458888Smckusick return; 21558888Smckusick case KERN_PROC: 21658888Smckusick if (flags == 0) 21758888Smckusick return; 21858888Smckusick fprintf(stderr, 21958888Smckusick "Use ps to view %s information\n", string); 22058888Smckusick return; 22158888Smckusick case KERN_CLOCKRATE: 22258888Smckusick isclockrate = 1; 22358888Smckusick break; 22458888Smckusick } 22558888Smckusick break; 22658888Smckusick 22758888Smckusick case CTL_HW: 22858888Smckusick break; 22958888Smckusick 23058888Smckusick case CTL_VM: 23158888Smckusick if (mib[1] == VM_LOADAVG) { 23258888Smckusick double loads[3]; 23358888Smckusick 23458888Smckusick getloadavg(loads, 3); 23558910Smckusick if (!nflag) 23658910Smckusick fprintf(stdout, "%s: ", string); 23758910Smckusick fprintf(stdout, "%.2f %.2f %.2f\n", 23858888Smckusick loads[0], loads[1], loads[2]); 23958888Smckusick return; 24058888Smckusick } 24158888Smckusick if (flags == 0) 24258888Smckusick return; 24358888Smckusick fprintf(stderr, 24458888Smckusick "Use vmstat or systat to view %s information\n", string); 24558888Smckusick return; 24658888Smckusick 24758888Smckusick case CTL_NET: 24859140Smckusick if (mib[1] == PF_INET) { 24959140Smckusick len = sysctl_inet(string, &bufp, mib, flags, &type); 25059140Smckusick if (len >= 0) 25159140Smckusick break; 25259140Smckusick return; 25359140Smckusick } 25458888Smckusick if (flags == 0) 25558888Smckusick return; 25658888Smckusick fprintf(stderr, "Use netstat to view %s information\n", string); 25758888Smckusick return; 25858888Smckusick 25959159Smckusick case CTL_DEBUG: 26059159Smckusick mib[2] = CTL_DEBUG_VALUE; 26159159Smckusick len = 3; 26259159Smckusick break; 26359159Smckusick 26458888Smckusick case CTL_FS: 26558888Smckusick case CTL_MACHDEP: 26658888Smckusick break; 26758888Smckusick 26858888Smckusick default: 26958888Smckusick fprintf(stderr, "Illegal top level value: %d\n", mib[0]); 27058888Smckusick return; 27158888Smckusick 27258888Smckusick } 27359140Smckusick if (bufp) { 27459140Smckusick fprintf(stderr, "name %s in %s is unknown\n", *bufp, string); 27559140Smckusick return; 27659140Smckusick } 27759140Smckusick if (newsize > 0) { 27859140Smckusick switch (type) { 27959140Smckusick case CTLTYPE_INT: 28059140Smckusick intval = atoi(newval); 28159140Smckusick newval = &intval; 28259140Smckusick newsize = sizeof intval; 28359140Smckusick break; 28458888Smckusick 28559140Smckusick case CTLTYPE_QUAD: 28659140Smckusick sscanf(newval, "%qd", &quadval); 28759140Smckusick newval = &quadval; 28859140Smckusick newsize = sizeof quadval; 28959140Smckusick break; 29059140Smckusick } 29159140Smckusick } 29258888Smckusick size = BUFSIZ; 29359140Smckusick if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) { 29458888Smckusick if (flags == 0) 29558888Smckusick return; 29658888Smckusick switch (errno) { 29758888Smckusick case EOPNOTSUPP: 29858888Smckusick fprintf(stderr, "%s: value is not available\n", string); 29958888Smckusick return; 30058888Smckusick case ENOTDIR: 30158888Smckusick fprintf(stderr, "%s: specification is incomplete\n", 30258888Smckusick string); 30358888Smckusick return; 30458888Smckusick case ENOMEM: 30558888Smckusick fprintf(stderr, "%s: type is unknown to this program\n", 30658888Smckusick string); 30758888Smckusick return; 30858888Smckusick default: 30958888Smckusick perror(string); 31058888Smckusick return; 31158888Smckusick } 31258888Smckusick } 31358888Smckusick if (isclockrate) { 31458888Smckusick struct clockinfo *clkp = (struct clockinfo *)buf; 31558888Smckusick 31658910Smckusick if (!nflag) 31758910Smckusick fprintf(stdout, "%s: ", string); 31858888Smckusick fprintf(stdout, 31958910Smckusick "hz = %d, tick = %d, profhz = %d, stathz = %d\n", 32058910Smckusick clkp->hz, clkp->tick, clkp->profhz, clkp->stathz); 32158888Smckusick return; 32258888Smckusick } 32359140Smckusick switch (type) { 32459140Smckusick case CTLTYPE_INT: 32558910Smckusick if (newsize == 0) { 32658910Smckusick if (!nflag) 32758910Smckusick fprintf(stdout, "%s = ", string); 32858910Smckusick fprintf(stdout, "%d\n", *(int *)buf); 32958910Smckusick } else { 33058910Smckusick if (!nflag) 33158910Smckusick fprintf(stdout, "%s: %d -> ", string, 33258910Smckusick *(int *)buf); 33358910Smckusick fprintf(stdout, "%d\n", *(int *)newval); 33458910Smckusick } 33559140Smckusick return; 33659140Smckusick 33759140Smckusick case CTLTYPE_STRING: 33858910Smckusick if (newsize == 0) { 33958910Smckusick if (!nflag) 34058910Smckusick fprintf(stdout, "%s = ", string); 34158910Smckusick fprintf(stdout, "%s\n", buf); 34258910Smckusick } else { 34358910Smckusick if (!nflag) 34458910Smckusick fprintf(stdout, "%s: %s -> ", string, buf); 34558910Smckusick fprintf(stdout, "%s\n", newval); 34658910Smckusick } 34759140Smckusick return; 34859140Smckusick 34959140Smckusick case CTLTYPE_QUAD: 35059140Smckusick if (newsize == 0) { 35159140Smckusick if (!nflag) 35259140Smckusick fprintf(stdout, "%s = ", string); 35359140Smckusick fprintf(stdout, "%qd\n", *(quad_t *)buf); 35459140Smckusick } else { 35559140Smckusick if (!nflag) 35659140Smckusick fprintf(stdout, "%s: %qd -> ", string, 35759140Smckusick *(quad_t *)buf); 35859140Smckusick fprintf(stdout, "%qd\n", *(quad_t *)newval); 35959140Smckusick } 36059140Smckusick return; 36159140Smckusick 36259140Smckusick case CTLTYPE_STRUCT: 36359140Smckusick fprintf(stderr, "%s: unknown structure returned\n", 36459140Smckusick string); 36559140Smckusick return; 36659140Smckusick 36759140Smckusick default: 36859140Smckusick case CTLTYPE_NODE: 36959140Smckusick fprintf(stderr, "%s: unknown type returned\n", 37059140Smckusick string); 37159140Smckusick return; 37259140Smckusick } 37358888Smckusick } 37458888Smckusick 37559159Smckusick /* 37659159Smckusick * Initialize the set of debugging names 37759159Smckusick */ 37859159Smckusick debuginit() 37959159Smckusick { 38059159Smckusick int mib[3], size, loc, i; 38159159Smckusick 38259159Smckusick if (secondlevel[CTL_DEBUG].list != 0) 38359159Smckusick return; 38459159Smckusick secondlevel[CTL_DEBUG].list = debugname; 38559159Smckusick mib[0] = CTL_DEBUG; 38659159Smckusick mib[2] = CTL_DEBUG_NAME; 38759159Smckusick for (loc = 0, i = 0; i < CTL_DEBUG_MAXID; i++) { 38859159Smckusick mib[1] = i; 38959159Smckusick size = BUFSIZ - loc; 39059159Smckusick if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1) 39159159Smckusick continue; 39259159Smckusick debugname[i].ctl_name = &names[loc]; 39359159Smckusick debugname[i].ctl_type = CTLTYPE_INT; 39459159Smckusick loc += size; 39559159Smckusick } 39659159Smckusick } 39759159Smckusick 39859140Smckusick struct ctlname inetname[] = CTL_IPPROTO_NAMES; 39959140Smckusick struct ctlname ipname[] = IPCTL_NAMES; 40059140Smckusick struct ctlname icmpname[] = ICMPCTL_NAMES; 40159311Smckusick struct ctlname udpname[] = UDPCTL_NAMES; 40259140Smckusick struct list inetlist = { inetname, IPPROTO_MAXID }; 40359140Smckusick struct list inetvars[] = { 40459311Smckusick { ipname, IPCTL_MAXID }, /* ip */ 40559311Smckusick { icmpname, ICMPCTL_MAXID }, /* icmp */ 40659311Smckusick { 0, 0 }, /* igmp */ 40759311Smckusick { 0, 0 }, /* ggmp */ 40859311Smckusick { 0, 0 }, 40959311Smckusick { 0, 0 }, 41059311Smckusick { 0, 0 }, /* tcp */ 41159311Smckusick { 0, 0 }, 41259311Smckusick { 0, 0 }, /* egp */ 41359311Smckusick { 0, 0 }, 41459311Smckusick { 0, 0 }, 41559311Smckusick { 0, 0 }, 41659311Smckusick { 0, 0 }, /* pup */ 41759311Smckusick { 0, 0 }, 41859311Smckusick { 0, 0 }, 41959311Smckusick { 0, 0 }, 42059311Smckusick { 0, 0 }, 42159311Smckusick { udpname, UDPCTL_MAXID }, /* udp */ 42259140Smckusick }; 42359140Smckusick 42458888Smckusick /* 42559140Smckusick * handle internet requests 42659140Smckusick */ 42759140Smckusick sysctl_inet(string, bufpp, mib, flags, typep) 42859140Smckusick char *string; 42959140Smckusick char **bufpp; 43059140Smckusick int mib[]; 43159140Smckusick int flags; 43259140Smckusick int *typep; 43359140Smckusick { 43459140Smckusick struct list *lp; 43559140Smckusick int indx; 43659140Smckusick 43759140Smckusick if (*bufpp == NULL) { 43859140Smckusick listall(string, &inetlist); 43959140Smckusick return (-1); 44059140Smckusick } 44159140Smckusick if ((indx = findname(string, "third", bufpp, &inetlist)) == -1) 44259140Smckusick return (-1); 44359140Smckusick mib[2] = indx; 44459311Smckusick if (indx <= IPPROTO_UDP && inetvars[indx].list != NULL) 44559140Smckusick lp = &inetvars[indx]; 44659140Smckusick else if (!flags) 44759140Smckusick return (-1); 44859140Smckusick else { 44959140Smckusick fprintf(stderr, "%s: no variables defined for this protocol\n", 45059140Smckusick string); 45159140Smckusick return (-1); 45259140Smckusick } 45359140Smckusick if (*bufpp == NULL) { 45459140Smckusick listall(string, lp); 45559140Smckusick return (-1); 45659140Smckusick } 45759140Smckusick if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 45859140Smckusick return (-1); 45959140Smckusick mib[3] = indx; 46059140Smckusick *typep = lp->list[indx].ctl_type; 46159140Smckusick return (4); 46259140Smckusick } 46359140Smckusick 46459140Smckusick /* 46558888Smckusick * Scan a list of names searching for a particular name. 46658888Smckusick */ 46758888Smckusick findname(string, level, bufp, namelist) 46858888Smckusick char *string; 46958888Smckusick char *level; 47058888Smckusick char **bufp; 47158888Smckusick struct list *namelist; 47258888Smckusick { 47358888Smckusick char *name; 47458888Smckusick int i; 47558888Smckusick 47658888Smckusick if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { 47758888Smckusick fprintf(stderr, "%s: incomplete specification\n", string); 47858888Smckusick return (-1); 47958888Smckusick } 48058888Smckusick for (i = 0; i < namelist->size; i++) 48159252Storek if (namelist->list[i].ctl_name != NULL && 48259252Storek strcmp(name, namelist->list[i].ctl_name) == 0) 48358888Smckusick break; 48458888Smckusick if (i == namelist->size) { 48558888Smckusick fprintf(stderr, "%s level name %s in %s is invalid\n", 48658888Smckusick level, name, string); 48758888Smckusick return (-1); 48858888Smckusick } 48958888Smckusick return (i); 49058888Smckusick } 49158888Smckusick 49258888Smckusick usage() 49358888Smckusick { 49458888Smckusick 49558911Smckusick (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n", 49658911Smckusick "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...", 49758911Smckusick "sysctl [-n] -a", "sysctl [-n] -A"); 49858888Smckusick exit(1); 49958888Smckusick } 500