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*60154Smckusick static char sccsid[] = "@(#)sysctl.c 5.11 (Berkeley) 05/20/93"; 1658888Smckusick #endif /* not lint */ 1758888Smckusick 1859379Sbostic #include <sys/param.h> 1959658Smckusick #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; 4459719Sbostic struct ctlname username[] = CTL_USER_NAMES; 4559159Smckusick struct ctlname debugname[CTL_DEBUG_MAXID]; 4659159Smckusick char names[BUFSIZ]; 4758888Smckusick 4858888Smckusick struct list { 4959140Smckusick struct ctlname *list; 5058888Smckusick int size; 5159140Smckusick }; 5259140Smckusick struct list toplist = { topname, CTL_MAXID }; 5359140Smckusick struct list secondlevel[] = { 5458888Smckusick { 0, 0 }, /* CTL_UNSPEC */ 5558888Smckusick { kernname, KERN_MAXID }, /* CTL_KERN */ 5658888Smckusick { vmname, VM_MAXID }, /* CTL_VM */ 5758888Smckusick { 0, 0 }, /* CTL_FS */ 5858888Smckusick { netname, NET_MAXID }, /* CTL_NET */ 5959159Smckusick { 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */ 6058888Smckusick { hwname, HW_MAXID }, /* CTL_HW */ 6158888Smckusick { 0, 0 }, /* CTL_MACHDEP */ 6259719Sbostic { username, USER_MAXID }, /* CTL_USER_NAMES */ 6358888Smckusick }; 6458888Smckusick 6558910Smckusick int Aflag, aflag, nflag, wflag; 6658888Smckusick 6758888Smckusick int 6858888Smckusick main(argc, argv) 6958888Smckusick int argc; 7058888Smckusick char *argv[]; 7158888Smckusick { 7258888Smckusick extern char *optarg; 7358888Smckusick extern int optind; 7458910Smckusick int ch, lvl1; 7558888Smckusick 7658910Smckusick while ((ch = getopt(argc, argv, "Aanw")) != EOF) { 7758888Smckusick switch (ch) { 7858888Smckusick 7958888Smckusick case 'A': 8058888Smckusick Aflag = 1; 8158888Smckusick break; 8258888Smckusick 8358888Smckusick case 'a': 8458888Smckusick aflag = 1; 8558888Smckusick break; 8658888Smckusick 8758910Smckusick case 'n': 8858910Smckusick nflag = 1; 8958910Smckusick break; 9058910Smckusick 9158888Smckusick case 'w': 9258888Smckusick wflag = 1; 9358888Smckusick break; 9458888Smckusick 9558888Smckusick default: 9658888Smckusick usage(); 9758888Smckusick } 9858888Smckusick } 9958888Smckusick argc -= optind; 10058888Smckusick argv += optind; 10158888Smckusick 10258888Smckusick if (Aflag || aflag) { 10359159Smckusick debuginit(); 10458910Smckusick for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++) 10559140Smckusick listall(topname[lvl1].ctl_name, &secondlevel[lvl1]); 10658888Smckusick exit(0); 10758888Smckusick } 10858888Smckusick if (argc == 0) 10958888Smckusick usage(); 11058888Smckusick while (argc-- > 0) 11158888Smckusick parse(*argv, 1); 11258888Smckusick exit(0); 11358888Smckusick } 11458888Smckusick 11558888Smckusick /* 11658888Smckusick * List all variables known to the system. 11758888Smckusick */ 11859140Smckusick listall(prefix, lp) 11959140Smckusick char *prefix; 12059140Smckusick struct list *lp; 12158888Smckusick { 12258910Smckusick int lvl2; 12358888Smckusick char *cp, name[BUFSIZ]; 12458888Smckusick 12558910Smckusick if (lp->list == 0) 12658910Smckusick return; 12759140Smckusick strcpy(name, prefix); 12858910Smckusick cp = &name[strlen(name)]; 12958910Smckusick *cp++ = '.'; 13059140Smckusick for (lvl2 = 0; lvl2 < lp->size; lvl2++) { 13159140Smckusick if (lp->list[lvl2].ctl_name == 0) 13259140Smckusick continue; 13359140Smckusick strcpy(cp, lp->list[lvl2].ctl_name); 13458910Smckusick parse(name, Aflag); 13558888Smckusick } 13658888Smckusick } 13758888Smckusick 13858888Smckusick /* 13958888Smckusick * Parse a name into a MIB entry. 14058888Smckusick * Lookup and print out the MIB entry if it exists. 14158888Smckusick * Set a new value if requested. 14258888Smckusick */ 14358888Smckusick parse(string, flags) 14458888Smckusick char *string; 14558888Smckusick int flags; 14658888Smckusick { 14759658Smckusick int indx, type, state, size, len; 14858888Smckusick int isclockrate = 0; 149*60154Smckusick int isboottime = 0; 15058888Smckusick void *newval = 0; 15158888Smckusick int intval, newsize = 0; 15259140Smckusick quad_t quadval; 15359140Smckusick struct list *lp; 15458888Smckusick int mib[CTL_MAXNAME]; 15558888Smckusick char *cp, *bufp, buf[BUFSIZ], strval[BUFSIZ]; 15658888Smckusick 15758888Smckusick bufp = buf; 15858888Smckusick snprintf(buf, BUFSIZ, "%s", string); 15958888Smckusick if ((cp = strchr(string, '=')) != NULL) { 16058888Smckusick if (!wflag) { 16158888Smckusick fprintf(stderr, "Must specify -w to set variables\n"); 16258888Smckusick exit(2); 16358888Smckusick } 16458888Smckusick *strchr(buf, '=') = '\0'; 16558888Smckusick *cp++ = '\0'; 16658888Smckusick while (isspace(*cp)) 16758888Smckusick cp++; 16859140Smckusick newval = cp; 16959140Smckusick newsize = strlen(cp); 17058888Smckusick } 17159140Smckusick if ((indx = findname(string, "top", &bufp, &toplist)) == -1) 17258888Smckusick return; 17358888Smckusick mib[0] = indx; 17459159Smckusick if (indx == CTL_DEBUG) 17559159Smckusick debuginit(); 17658888Smckusick lp = &secondlevel[indx]; 17758888Smckusick if (lp->list == 0) { 17858888Smckusick fprintf(stderr, "%s: class is not implemented\n", 17958888Smckusick topname[indx]); 18058888Smckusick return; 18158888Smckusick } 18258910Smckusick if (bufp == NULL) { 18359140Smckusick listall(topname[indx].ctl_name, lp); 18458910Smckusick return; 18558910Smckusick } 18658888Smckusick if ((indx = findname(string, "second", &bufp, lp)) == -1) 18758888Smckusick return; 18858888Smckusick mib[1] = indx; 18959140Smckusick type = lp->list[indx].ctl_type; 19059140Smckusick len = 2; 19158888Smckusick switch (mib[0]) { 19258888Smckusick 19358888Smckusick case CTL_KERN: 19458888Smckusick switch (mib[1]) { 19559658Smckusick case KERN_PROF: 19659658Smckusick mib[2] = GPROF_STATE; 19759658Smckusick size = sizeof state; 19859658Smckusick if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) { 19959658Smckusick if (flags == 0) 20059658Smckusick return; 20159658Smckusick if (!nflag) 20259658Smckusick fprintf(stdout, "%s: ", string); 20359658Smckusick fprintf(stderr, 20459658Smckusick "kernel is not compiled for profiling\n"); 20559658Smckusick return; 20659658Smckusick } 20759658Smckusick if (!nflag) 20859658Smckusick fprintf(stdout, "%s: %s\n", string, 20959658Smckusick state == GMON_PROF_OFF ? "off" : "running"); 21059658Smckusick return; 21158888Smckusick case KERN_VNODE: 21258888Smckusick case KERN_FILE: 21358888Smckusick if (flags == 0) 21458888Smckusick return; 21558888Smckusick fprintf(stderr, 21658888Smckusick "Use pstat to view %s information\n", string); 21758888Smckusick return; 21858888Smckusick case KERN_PROC: 21958888Smckusick if (flags == 0) 22058888Smckusick return; 22158888Smckusick fprintf(stderr, 22258888Smckusick "Use ps to view %s information\n", string); 22358888Smckusick return; 22458888Smckusick case KERN_CLOCKRATE: 22558888Smckusick isclockrate = 1; 22658888Smckusick break; 227*60154Smckusick case KERN_BOOTTIME: 228*60154Smckusick isboottime = 1; 229*60154Smckusick break; 23058888Smckusick } 23158888Smckusick break; 23258888Smckusick 23358888Smckusick case CTL_HW: 23458888Smckusick break; 23558888Smckusick 23658888Smckusick case CTL_VM: 23758888Smckusick if (mib[1] == VM_LOADAVG) { 23858888Smckusick double loads[3]; 23958888Smckusick 24058888Smckusick getloadavg(loads, 3); 24158910Smckusick if (!nflag) 24258910Smckusick fprintf(stdout, "%s: ", string); 24358910Smckusick fprintf(stdout, "%.2f %.2f %.2f\n", 24458888Smckusick loads[0], loads[1], loads[2]); 24558888Smckusick return; 24658888Smckusick } 24758888Smckusick if (flags == 0) 24858888Smckusick return; 24958888Smckusick fprintf(stderr, 25058888Smckusick "Use vmstat or systat to view %s information\n", string); 25158888Smckusick return; 25258888Smckusick 25358888Smckusick case CTL_NET: 25459140Smckusick if (mib[1] == PF_INET) { 25559140Smckusick len = sysctl_inet(string, &bufp, mib, flags, &type); 25659140Smckusick if (len >= 0) 25759140Smckusick break; 25859140Smckusick return; 25959140Smckusick } 26058888Smckusick if (flags == 0) 26158888Smckusick return; 26258888Smckusick fprintf(stderr, "Use netstat to view %s information\n", string); 26358888Smckusick return; 26458888Smckusick 26559159Smckusick case CTL_DEBUG: 26659159Smckusick mib[2] = CTL_DEBUG_VALUE; 26759159Smckusick len = 3; 26859159Smckusick break; 26959159Smckusick 27058888Smckusick case CTL_FS: 27158888Smckusick case CTL_MACHDEP: 27259719Sbostic case CTL_USER: 27358888Smckusick break; 27458888Smckusick 27558888Smckusick default: 27658888Smckusick fprintf(stderr, "Illegal top level value: %d\n", mib[0]); 27758888Smckusick return; 27858888Smckusick 27958888Smckusick } 28059140Smckusick if (bufp) { 28159140Smckusick fprintf(stderr, "name %s in %s is unknown\n", *bufp, string); 28259140Smckusick return; 28359140Smckusick } 28459140Smckusick if (newsize > 0) { 28559140Smckusick switch (type) { 28659140Smckusick case CTLTYPE_INT: 28759140Smckusick intval = atoi(newval); 28859140Smckusick newval = &intval; 28959140Smckusick newsize = sizeof intval; 29059140Smckusick break; 29158888Smckusick 29259140Smckusick case CTLTYPE_QUAD: 29359140Smckusick sscanf(newval, "%qd", &quadval); 29459140Smckusick newval = &quadval; 29559140Smckusick newsize = sizeof quadval; 29659140Smckusick break; 29759140Smckusick } 29859140Smckusick } 29958888Smckusick size = BUFSIZ; 30059140Smckusick if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) { 30158888Smckusick if (flags == 0) 30258888Smckusick return; 30358888Smckusick switch (errno) { 30458888Smckusick case EOPNOTSUPP: 30558888Smckusick fprintf(stderr, "%s: value is not available\n", string); 30658888Smckusick return; 30758888Smckusick case ENOTDIR: 30858888Smckusick fprintf(stderr, "%s: specification is incomplete\n", 30958888Smckusick string); 31058888Smckusick return; 31158888Smckusick case ENOMEM: 31258888Smckusick fprintf(stderr, "%s: type is unknown to this program\n", 31358888Smckusick string); 31458888Smckusick return; 31558888Smckusick default: 31658888Smckusick perror(string); 31758888Smckusick return; 31858888Smckusick } 31958888Smckusick } 32058888Smckusick if (isclockrate) { 32158888Smckusick struct clockinfo *clkp = (struct clockinfo *)buf; 32258888Smckusick 32358910Smckusick if (!nflag) 32458910Smckusick fprintf(stdout, "%s: ", string); 32558888Smckusick fprintf(stdout, 32658910Smckusick "hz = %d, tick = %d, profhz = %d, stathz = %d\n", 32758910Smckusick clkp->hz, clkp->tick, clkp->profhz, clkp->stathz); 32858888Smckusick return; 32958888Smckusick } 330*60154Smckusick if (isboottime) { 331*60154Smckusick struct timeval *btp = (struct timeval *)buf; 332*60154Smckusick 333*60154Smckusick if (!nflag) 334*60154Smckusick fprintf(stdout, "%s = %s\n", string, 335*60154Smckusick ctime(&btp->tv_sec)); 336*60154Smckusick else 337*60154Smckusick fprintf(stdout, "%d\n", btp->tv_sec); 338*60154Smckusick return; 339*60154Smckusick } 34059140Smckusick switch (type) { 34159140Smckusick case CTLTYPE_INT: 34258910Smckusick if (newsize == 0) { 34358910Smckusick if (!nflag) 34458910Smckusick fprintf(stdout, "%s = ", string); 34558910Smckusick fprintf(stdout, "%d\n", *(int *)buf); 34658910Smckusick } else { 34758910Smckusick if (!nflag) 34858910Smckusick fprintf(stdout, "%s: %d -> ", string, 34958910Smckusick *(int *)buf); 35058910Smckusick fprintf(stdout, "%d\n", *(int *)newval); 35158910Smckusick } 35259140Smckusick return; 35359140Smckusick 35459140Smckusick case CTLTYPE_STRING: 35558910Smckusick if (newsize == 0) { 35658910Smckusick if (!nflag) 35758910Smckusick fprintf(stdout, "%s = ", string); 35858910Smckusick fprintf(stdout, "%s\n", buf); 35958910Smckusick } else { 36058910Smckusick if (!nflag) 36158910Smckusick fprintf(stdout, "%s: %s -> ", string, buf); 36258910Smckusick fprintf(stdout, "%s\n", newval); 36358910Smckusick } 36459140Smckusick return; 36559140Smckusick 36659140Smckusick case CTLTYPE_QUAD: 36759140Smckusick if (newsize == 0) { 36859140Smckusick if (!nflag) 36959140Smckusick fprintf(stdout, "%s = ", string); 37059140Smckusick fprintf(stdout, "%qd\n", *(quad_t *)buf); 37159140Smckusick } else { 37259140Smckusick if (!nflag) 37359140Smckusick fprintf(stdout, "%s: %qd -> ", string, 37459140Smckusick *(quad_t *)buf); 37559140Smckusick fprintf(stdout, "%qd\n", *(quad_t *)newval); 37659140Smckusick } 37759140Smckusick return; 37859140Smckusick 37959140Smckusick case CTLTYPE_STRUCT: 38059140Smckusick fprintf(stderr, "%s: unknown structure returned\n", 38159140Smckusick string); 38259140Smckusick return; 38359140Smckusick 38459140Smckusick default: 38559140Smckusick case CTLTYPE_NODE: 38659140Smckusick fprintf(stderr, "%s: unknown type returned\n", 38759140Smckusick string); 38859140Smckusick return; 38959140Smckusick } 39058888Smckusick } 39158888Smckusick 39259159Smckusick /* 39359159Smckusick * Initialize the set of debugging names 39459159Smckusick */ 39559159Smckusick debuginit() 39659159Smckusick { 39759159Smckusick int mib[3], size, loc, i; 39859159Smckusick 39959159Smckusick if (secondlevel[CTL_DEBUG].list != 0) 40059159Smckusick return; 40159159Smckusick secondlevel[CTL_DEBUG].list = debugname; 40259159Smckusick mib[0] = CTL_DEBUG; 40359159Smckusick mib[2] = CTL_DEBUG_NAME; 40459159Smckusick for (loc = 0, i = 0; i < CTL_DEBUG_MAXID; i++) { 40559159Smckusick mib[1] = i; 40659159Smckusick size = BUFSIZ - loc; 40759159Smckusick if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1) 40859159Smckusick continue; 40959159Smckusick debugname[i].ctl_name = &names[loc]; 41059159Smckusick debugname[i].ctl_type = CTLTYPE_INT; 41159159Smckusick loc += size; 41259159Smckusick } 41359159Smckusick } 41459159Smckusick 41559140Smckusick struct ctlname inetname[] = CTL_IPPROTO_NAMES; 41659140Smckusick struct ctlname ipname[] = IPCTL_NAMES; 41759140Smckusick struct ctlname icmpname[] = ICMPCTL_NAMES; 41859311Smckusick struct ctlname udpname[] = UDPCTL_NAMES; 41959140Smckusick struct list inetlist = { inetname, IPPROTO_MAXID }; 42059140Smckusick struct list inetvars[] = { 42159311Smckusick { ipname, IPCTL_MAXID }, /* ip */ 42259311Smckusick { icmpname, ICMPCTL_MAXID }, /* icmp */ 42359311Smckusick { 0, 0 }, /* igmp */ 42459311Smckusick { 0, 0 }, /* ggmp */ 42559311Smckusick { 0, 0 }, 42659311Smckusick { 0, 0 }, 42759311Smckusick { 0, 0 }, /* tcp */ 42859311Smckusick { 0, 0 }, 42959311Smckusick { 0, 0 }, /* egp */ 43059311Smckusick { 0, 0 }, 43159311Smckusick { 0, 0 }, 43259311Smckusick { 0, 0 }, 43359311Smckusick { 0, 0 }, /* pup */ 43459311Smckusick { 0, 0 }, 43559311Smckusick { 0, 0 }, 43659311Smckusick { 0, 0 }, 43759311Smckusick { 0, 0 }, 43859311Smckusick { udpname, UDPCTL_MAXID }, /* udp */ 43959140Smckusick }; 44059140Smckusick 44158888Smckusick /* 44259140Smckusick * handle internet requests 44359140Smckusick */ 44459140Smckusick sysctl_inet(string, bufpp, mib, flags, typep) 44559140Smckusick char *string; 44659140Smckusick char **bufpp; 44759140Smckusick int mib[]; 44859140Smckusick int flags; 44959140Smckusick int *typep; 45059140Smckusick { 45159140Smckusick struct list *lp; 45259140Smckusick int indx; 45359140Smckusick 45459140Smckusick if (*bufpp == NULL) { 45559140Smckusick listall(string, &inetlist); 45659140Smckusick return (-1); 45759140Smckusick } 45859140Smckusick if ((indx = findname(string, "third", bufpp, &inetlist)) == -1) 45959140Smckusick return (-1); 46059140Smckusick mib[2] = indx; 46159311Smckusick if (indx <= IPPROTO_UDP && inetvars[indx].list != NULL) 46259140Smckusick lp = &inetvars[indx]; 46359140Smckusick else if (!flags) 46459140Smckusick return (-1); 46559140Smckusick else { 46659140Smckusick fprintf(stderr, "%s: no variables defined for this protocol\n", 46759140Smckusick string); 46859140Smckusick return (-1); 46959140Smckusick } 47059140Smckusick if (*bufpp == NULL) { 47159140Smckusick listall(string, lp); 47259140Smckusick return (-1); 47359140Smckusick } 47459140Smckusick if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 47559140Smckusick return (-1); 47659140Smckusick mib[3] = indx; 47759140Smckusick *typep = lp->list[indx].ctl_type; 47859140Smckusick return (4); 47959140Smckusick } 48059140Smckusick 48159140Smckusick /* 48258888Smckusick * Scan a list of names searching for a particular name. 48358888Smckusick */ 48458888Smckusick findname(string, level, bufp, namelist) 48558888Smckusick char *string; 48658888Smckusick char *level; 48758888Smckusick char **bufp; 48858888Smckusick struct list *namelist; 48958888Smckusick { 49058888Smckusick char *name; 49158888Smckusick int i; 49258888Smckusick 49358888Smckusick if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { 49458888Smckusick fprintf(stderr, "%s: incomplete specification\n", string); 49558888Smckusick return (-1); 49658888Smckusick } 49758888Smckusick for (i = 0; i < namelist->size; i++) 49859252Storek if (namelist->list[i].ctl_name != NULL && 49959252Storek strcmp(name, namelist->list[i].ctl_name) == 0) 50058888Smckusick break; 50158888Smckusick if (i == namelist->size) { 50258888Smckusick fprintf(stderr, "%s level name %s in %s is invalid\n", 50358888Smckusick level, name, string); 50458888Smckusick return (-1); 50558888Smckusick } 50658888Smckusick return (i); 50758888Smckusick } 50858888Smckusick 50958888Smckusick usage() 51058888Smckusick { 51158888Smckusick 51258911Smckusick (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n", 51358911Smckusick "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...", 51458911Smckusick "sysctl [-n] -a", "sysctl [-n] -A"); 51558888Smckusick exit(1); 51658888Smckusick } 517