xref: /original-bsd/usr.sbin/sysctl/sysctl.c (revision 4444460a)
148356cf6Smckusick /*
276f30379Sbostic  * Copyright (c) 1993
376f30379Sbostic  *	The Regents of the University of California.  All rights reserved.
448356cf6Smckusick  *
548356cf6Smckusick  * %sccs.include.redist.c%
648356cf6Smckusick  */
748356cf6Smckusick 
848356cf6Smckusick #ifndef lint
976f30379Sbostic static char copyright[] =
1076f30379Sbostic "@(#) Copyright (c) 1993\n\
1176f30379Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1248356cf6Smckusick #endif /* not lint */
1348356cf6Smckusick 
1448356cf6Smckusick #ifndef lint
15*4444460aSmckusick static char sccsid[] = "@(#)sysctl.c	8.5 (Berkeley) 05/09/95";
1648356cf6Smckusick #endif /* not lint */
1748356cf6Smckusick 
18ffe81a7bSbostic #include <sys/param.h>
197d6a41feSmckusick #include <sys/gmon.h>
2038187f89Smckusick #include <sys/mount.h>
2148356cf6Smckusick #include <sys/stat.h>
2248356cf6Smckusick #include <sys/sysctl.h>
2348356cf6Smckusick #include <sys/socket.h>
2448356cf6Smckusick #include <vm/vm_param.h>
25205717e4Smckusick #include <machine/cpu.h>
26ffe81a7bSbostic 
27a3a5e311Smckusick #include <netinet/in.h>
28a3a5e311Smckusick #include <netinet/in_systm.h>
29a3a5e311Smckusick #include <netinet/ip.h>
30a3a5e311Smckusick #include <netinet/ip_icmp.h>
31a3a5e311Smckusick #include <netinet/icmp_var.h>
324310f570Smckusick #include <netinet/ip_var.h>
334310f570Smckusick #include <netinet/udp.h>
344310f570Smckusick #include <netinet/udp_var.h>
35ffe81a7bSbostic 
3648356cf6Smckusick #include <errno.h>
37ffe81a7bSbostic #include <stdio.h>
3848356cf6Smckusick #include <stdlib.h>
3948356cf6Smckusick #include <string.h>
4048356cf6Smckusick 
41a3a5e311Smckusick struct ctlname topname[] = CTL_NAMES;
42a3a5e311Smckusick struct ctlname kernname[] = CTL_KERN_NAMES;
43a3a5e311Smckusick struct ctlname vmname[] = CTL_VM_NAMES;
44a3a5e311Smckusick struct ctlname netname[] = CTL_NET_NAMES;
45a3a5e311Smckusick struct ctlname hwname[] = CTL_HW_NAMES;
465c1800e7Sbostic struct ctlname username[] = CTL_USER_NAMES;
47314e6e3aSmckusick struct ctlname debugname[CTL_DEBUG_MAXID];
4838187f89Smckusick struct ctlname *vfsname;
49205717e4Smckusick #ifdef CTL_MACHDEP_NAMES
50205717e4Smckusick struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
51205717e4Smckusick #endif
52314e6e3aSmckusick char names[BUFSIZ];
5338187f89Smckusick int lastused;
5448356cf6Smckusick 
5548356cf6Smckusick struct list {
56a3a5e311Smckusick 	struct	ctlname *list;
5748356cf6Smckusick 	int	size;
58a3a5e311Smckusick };
59a3a5e311Smckusick struct list toplist = { topname, CTL_MAXID };
60a3a5e311Smckusick struct list secondlevel[] = {
6148356cf6Smckusick 	{ 0, 0 },			/* CTL_UNSPEC */
6248356cf6Smckusick 	{ kernname, KERN_MAXID },	/* CTL_KERN */
6348356cf6Smckusick 	{ vmname, VM_MAXID },		/* CTL_VM */
6438187f89Smckusick 	{ 0, 0 },			/* CTL_VFS */
6548356cf6Smckusick 	{ netname, NET_MAXID },		/* CTL_NET */
66314e6e3aSmckusick 	{ 0, CTL_DEBUG_MAXID },		/* CTL_DEBUG */
6748356cf6Smckusick 	{ hwname, HW_MAXID },		/* CTL_HW */
68205717e4Smckusick #ifdef CTL_MACHDEP_NAMES
69205717e4Smckusick 	{ machdepname, CPU_MAXID },	/* CTL_MACHDEP */
70205717e4Smckusick #else
7148356cf6Smckusick 	{ 0, 0 },			/* CTL_MACHDEP */
72205717e4Smckusick #endif
735c1800e7Sbostic 	{ username, USER_MAXID },	/* CTL_USER_NAMES */
7448356cf6Smckusick };
7548356cf6Smckusick 
76c42d362fSmckusick int	Aflag, aflag, nflag, wflag;
7748356cf6Smckusick 
78205717e4Smckusick /*
79205717e4Smckusick  * Variables requiring special processing.
80205717e4Smckusick  */
81205717e4Smckusick #define	CLOCK		0x00000001
82205717e4Smckusick #define	BOOTTIME	0x00000002
83205717e4Smckusick #define	CONSDEV		0x00000004
84205717e4Smckusick 
8548356cf6Smckusick int
main(argc,argv)8648356cf6Smckusick main(argc, argv)
8748356cf6Smckusick 	int argc;
8848356cf6Smckusick 	char *argv[];
8948356cf6Smckusick {
9048356cf6Smckusick 	extern char *optarg;
9148356cf6Smckusick 	extern int optind;
92c42d362fSmckusick 	int ch, lvl1;
9348356cf6Smckusick 
94c42d362fSmckusick 	while ((ch = getopt(argc, argv, "Aanw")) != EOF) {
9548356cf6Smckusick 		switch (ch) {
9648356cf6Smckusick 
9748356cf6Smckusick 		case 'A':
9848356cf6Smckusick 			Aflag = 1;
9948356cf6Smckusick 			break;
10048356cf6Smckusick 
10148356cf6Smckusick 		case 'a':
10248356cf6Smckusick 			aflag = 1;
10348356cf6Smckusick 			break;
10448356cf6Smckusick 
105c42d362fSmckusick 		case 'n':
106c42d362fSmckusick 			nflag = 1;
107c42d362fSmckusick 			break;
108c42d362fSmckusick 
10948356cf6Smckusick 		case 'w':
11048356cf6Smckusick 			wflag = 1;
11148356cf6Smckusick 			break;
11248356cf6Smckusick 
11348356cf6Smckusick 		default:
11448356cf6Smckusick 			usage();
11548356cf6Smckusick 		}
11648356cf6Smckusick 	}
11748356cf6Smckusick 	argc -= optind;
11848356cf6Smckusick 	argv += optind;
11948356cf6Smckusick 
120*4444460aSmckusick 	if (argc == 0 && (Aflag || aflag)) {
121314e6e3aSmckusick 		debuginit();
12238187f89Smckusick 		vfsinit();
123c42d362fSmckusick 		for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
124a3a5e311Smckusick 			listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
12548356cf6Smckusick 		exit(0);
12648356cf6Smckusick 	}
12748356cf6Smckusick 	if (argc == 0)
12848356cf6Smckusick 		usage();
129407fae98Sbostic 	for (; *argv != NULL; ++argv)
13048356cf6Smckusick 		parse(*argv, 1);
13148356cf6Smckusick 	exit(0);
13248356cf6Smckusick }
13348356cf6Smckusick 
13448356cf6Smckusick /*
13548356cf6Smckusick  * List all variables known to the system.
13648356cf6Smckusick  */
listall(prefix,lp)137a3a5e311Smckusick listall(prefix, lp)
138a3a5e311Smckusick 	char *prefix;
13948356cf6Smckusick 	struct list *lp;
140a3a5e311Smckusick {
141c42d362fSmckusick 	int lvl2;
14248356cf6Smckusick 	char *cp, name[BUFSIZ];
14348356cf6Smckusick 
14448356cf6Smckusick 	if (lp->list == 0)
145c42d362fSmckusick 		return;
146a3a5e311Smckusick 	strcpy(name, prefix);
14748356cf6Smckusick 	cp = &name[strlen(name)];
14848356cf6Smckusick 	*cp++ = '.';
149a3a5e311Smckusick 	for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
150a3a5e311Smckusick 		if (lp->list[lvl2].ctl_name == 0)
151a3a5e311Smckusick 			continue;
152a3a5e311Smckusick 		strcpy(cp, lp->list[lvl2].ctl_name);
15348356cf6Smckusick 		parse(name, Aflag);
15448356cf6Smckusick 	}
15548356cf6Smckusick }
15648356cf6Smckusick 
15748356cf6Smckusick /*
15848356cf6Smckusick  * Parse a name into a MIB entry.
15948356cf6Smckusick  * Lookup and print out the MIB entry if it exists.
16048356cf6Smckusick  * Set a new value if requested.
16148356cf6Smckusick  */
parse(string,flags)16248356cf6Smckusick parse(string, flags)
16348356cf6Smckusick 	char *string;
16448356cf6Smckusick 	int flags;
16548356cf6Smckusick {
16638187f89Smckusick 	int indx, type, state, len;
16738187f89Smckusick 	size_t size;
168205717e4Smckusick 	int special = 0;
16948356cf6Smckusick 	void *newval = 0;
17048356cf6Smckusick 	int intval, newsize = 0;
171a3a5e311Smckusick 	quad_t quadval;
172a3a5e311Smckusick 	struct list *lp;
17338187f89Smckusick 	struct vfsconf vfc;
17448356cf6Smckusick 	int mib[CTL_MAXNAME];
17548356cf6Smckusick 	char *cp, *bufp, buf[BUFSIZ], strval[BUFSIZ];
17648356cf6Smckusick 
17748356cf6Smckusick 	bufp = buf;
17848356cf6Smckusick 	snprintf(buf, BUFSIZ, "%s", string);
17948356cf6Smckusick 	if ((cp = strchr(string, '=')) != NULL) {
18048356cf6Smckusick 		if (!wflag) {
18148356cf6Smckusick 			fprintf(stderr, "Must specify -w to set variables\n");
18248356cf6Smckusick 			exit(2);
18348356cf6Smckusick 		}
18448356cf6Smckusick 		*strchr(buf, '=') = '\0';
18548356cf6Smckusick 		*cp++ = '\0';
18648356cf6Smckusick 		while (isspace(*cp))
18748356cf6Smckusick 			cp++;
18848356cf6Smckusick 		newval = cp;
18948356cf6Smckusick 		newsize = strlen(cp);
19048356cf6Smckusick 	}
191a3a5e311Smckusick 	if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
19248356cf6Smckusick 		return;
19348356cf6Smckusick 	mib[0] = indx;
19438187f89Smckusick 	if (indx == CTL_VFS)
19538187f89Smckusick 		vfsinit();
196314e6e3aSmckusick 	if (indx == CTL_DEBUG)
197314e6e3aSmckusick 		debuginit();
19848356cf6Smckusick 	lp = &secondlevel[indx];
19948356cf6Smckusick 	if (lp->list == 0) {
20048356cf6Smckusick 		fprintf(stderr, "%s: class is not implemented\n",
20148356cf6Smckusick 		    topname[indx]);
20248356cf6Smckusick 		return;
20348356cf6Smckusick 	}
204c42d362fSmckusick 	if (bufp == NULL) {
205a3a5e311Smckusick 		listall(topname[indx].ctl_name, lp);
206c42d362fSmckusick 		return;
207c42d362fSmckusick 	}
20848356cf6Smckusick 	if ((indx = findname(string, "second", &bufp, lp)) == -1)
20948356cf6Smckusick 		return;
21048356cf6Smckusick 	mib[1] = indx;
211a3a5e311Smckusick 	type = lp->list[indx].ctl_type;
212a3a5e311Smckusick 	len = 2;
21348356cf6Smckusick 	switch (mib[0]) {
21448356cf6Smckusick 
21548356cf6Smckusick 	case CTL_KERN:
21648356cf6Smckusick 		switch (mib[1]) {
2177d6a41feSmckusick 		case KERN_PROF:
2187d6a41feSmckusick 			mib[2] = GPROF_STATE;
2197d6a41feSmckusick 			size = sizeof state;
2207d6a41feSmckusick 			if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) {
2217d6a41feSmckusick 				if (flags == 0)
2227d6a41feSmckusick 					return;
2237d6a41feSmckusick 				if (!nflag)
2247d6a41feSmckusick 					fprintf(stdout, "%s: ", string);
2257d6a41feSmckusick 				fprintf(stderr,
2267d6a41feSmckusick 				    "kernel is not compiled for profiling\n");
2277d6a41feSmckusick 				return;
2287d6a41feSmckusick 			}
2297d6a41feSmckusick 			if (!nflag)
2307d6a41feSmckusick 				fprintf(stdout, "%s: %s\n", string,
2317d6a41feSmckusick 				    state == GMON_PROF_OFF ? "off" : "running");
2327d6a41feSmckusick 			return;
23348356cf6Smckusick 		case KERN_VNODE:
23448356cf6Smckusick 		case KERN_FILE:
23548356cf6Smckusick 			if (flags == 0)
23648356cf6Smckusick 				return;
23748356cf6Smckusick 			fprintf(stderr,
23848356cf6Smckusick 			    "Use pstat to view %s information\n", string);
23948356cf6Smckusick 			return;
24048356cf6Smckusick 		case KERN_PROC:
24148356cf6Smckusick 			if (flags == 0)
24248356cf6Smckusick 				return;
24348356cf6Smckusick 			fprintf(stderr,
24448356cf6Smckusick 			    "Use ps to view %s information\n", string);
24548356cf6Smckusick 			return;
24648356cf6Smckusick 		case KERN_CLOCKRATE:
247205717e4Smckusick 			special |= CLOCK;
24848356cf6Smckusick 			break;
2496e12f17fSmckusick 		case KERN_BOOTTIME:
250205717e4Smckusick 			special |= BOOTTIME;
2516e12f17fSmckusick 			break;
25248356cf6Smckusick 		}
25348356cf6Smckusick 		break;
25448356cf6Smckusick 
25548356cf6Smckusick 	case CTL_HW:
25648356cf6Smckusick 		break;
25748356cf6Smckusick 
25848356cf6Smckusick 	case CTL_VM:
25948356cf6Smckusick 		if (mib[1] == VM_LOADAVG) {
26048356cf6Smckusick 			double loads[3];
26148356cf6Smckusick 
26248356cf6Smckusick 			getloadavg(loads, 3);
263c42d362fSmckusick 			if (!nflag)
264c42d362fSmckusick 				fprintf(stdout, "%s: ", string);
265c42d362fSmckusick 			fprintf(stdout, "%.2f %.2f %.2f\n",
26648356cf6Smckusick 			    loads[0], loads[1], loads[2]);
26748356cf6Smckusick 			return;
26848356cf6Smckusick 		}
26948356cf6Smckusick 		if (flags == 0)
27048356cf6Smckusick 			return;
27148356cf6Smckusick 		fprintf(stderr,
27248356cf6Smckusick 		    "Use vmstat or systat to view %s information\n", string);
27348356cf6Smckusick 		return;
27448356cf6Smckusick 
27548356cf6Smckusick 	case CTL_NET:
276a3a5e311Smckusick 		if (mib[1] == PF_INET) {
277a3a5e311Smckusick 			len = sysctl_inet(string, &bufp, mib, flags, &type);
278a3a5e311Smckusick 			if (len >= 0)
279a3a5e311Smckusick 				break;
280a3a5e311Smckusick 			return;
281a3a5e311Smckusick 		}
28248356cf6Smckusick 		if (flags == 0)
28348356cf6Smckusick 			return;
28448356cf6Smckusick 		fprintf(stderr, "Use netstat to view %s information\n", string);
28548356cf6Smckusick 		return;
28648356cf6Smckusick 
28748356cf6Smckusick 	case CTL_DEBUG:
288314e6e3aSmckusick 		mib[2] = CTL_DEBUG_VALUE;
289314e6e3aSmckusick 		len = 3;
290314e6e3aSmckusick 		break;
291314e6e3aSmckusick 
29248356cf6Smckusick 	case CTL_MACHDEP:
293205717e4Smckusick #ifdef CPU_CONSDEV
294205717e4Smckusick 		if (mib[1] == CPU_CONSDEV)
295205717e4Smckusick 			special |= CONSDEV;
296205717e4Smckusick #endif
297205717e4Smckusick 		break;
298205717e4Smckusick 
29938187f89Smckusick 	case CTL_VFS:
30038187f89Smckusick 		mib[3] = mib[1];
30138187f89Smckusick 		mib[1] = VFS_GENERIC;
30238187f89Smckusick 		mib[2] = VFS_CONF;
30338187f89Smckusick 		len = 4;
30438187f89Smckusick 		size = sizeof vfc;
30538187f89Smckusick 		if (sysctl(mib, 4, &vfc, &size, (void *)0, (size_t)0) < 0) {
30638187f89Smckusick 			perror("vfs print");
30738187f89Smckusick 			return;
30838187f89Smckusick 		}
30938187f89Smckusick 		if (flags == 0 && vfc.vfc_refcount == 0)
31038187f89Smckusick 			return;
31138187f89Smckusick 		if (!nflag)
31238187f89Smckusick 			fprintf(stdout, "%s has %d mounted instance%s\n",
31338187f89Smckusick 			    string, vfc.vfc_refcount,
31438187f89Smckusick 			    vfc.vfc_refcount != 1 ? "s" : "");
31538187f89Smckusick 		else
31638187f89Smckusick 			fprintf(stdout, "%d\n", vfc.vfc_refcount);
31738187f89Smckusick 		return;
31838187f89Smckusick 
3195c1800e7Sbostic 	case CTL_USER:
32048356cf6Smckusick 		break;
32148356cf6Smckusick 
32248356cf6Smckusick 	default:
32348356cf6Smckusick 		fprintf(stderr, "Illegal top level value: %d\n", mib[0]);
32448356cf6Smckusick 		return;
32548356cf6Smckusick 
32648356cf6Smckusick 	}
327a3a5e311Smckusick 	if (bufp) {
328a3a5e311Smckusick 		fprintf(stderr, "name %s in %s is unknown\n", *bufp, string);
329a3a5e311Smckusick 		return;
330a3a5e311Smckusick 	}
331a3a5e311Smckusick 	if (newsize > 0) {
332a3a5e311Smckusick 		switch (type) {
333a3a5e311Smckusick 		case CTLTYPE_INT:
334a3a5e311Smckusick 			intval = atoi(newval);
335a3a5e311Smckusick 			newval = &intval;
336a3a5e311Smckusick 			newsize = sizeof intval;
337a3a5e311Smckusick 			break;
33848356cf6Smckusick 
339a3a5e311Smckusick 		case CTLTYPE_QUAD:
340a3a5e311Smckusick 			sscanf(newval, "%qd", &quadval);
341a3a5e311Smckusick 			newval = &quadval;
342a3a5e311Smckusick 			newsize = sizeof quadval;
343a3a5e311Smckusick 			break;
344a3a5e311Smckusick 		}
345a3a5e311Smckusick 	}
34648356cf6Smckusick 	size = BUFSIZ;
347a3a5e311Smckusick 	if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) {
34848356cf6Smckusick 		if (flags == 0)
34948356cf6Smckusick 			return;
35048356cf6Smckusick 		switch (errno) {
35148356cf6Smckusick 		case EOPNOTSUPP:
35248356cf6Smckusick 			fprintf(stderr, "%s: value is not available\n", string);
35348356cf6Smckusick 			return;
35448356cf6Smckusick 		case ENOTDIR:
35548356cf6Smckusick 			fprintf(stderr, "%s: specification is incomplete\n",
35648356cf6Smckusick 			    string);
35748356cf6Smckusick 			return;
35848356cf6Smckusick 		case ENOMEM:
35948356cf6Smckusick 			fprintf(stderr, "%s: type is unknown to this program\n",
36048356cf6Smckusick 			    string);
36148356cf6Smckusick 			return;
36248356cf6Smckusick 		default:
36348356cf6Smckusick 			perror(string);
36448356cf6Smckusick 			return;
36548356cf6Smckusick 		}
36648356cf6Smckusick 	}
367205717e4Smckusick 	if (special & CLOCK) {
36848356cf6Smckusick 		struct clockinfo *clkp = (struct clockinfo *)buf;
36948356cf6Smckusick 
370c42d362fSmckusick 		if (!nflag)
371c42d362fSmckusick 			fprintf(stdout, "%s: ", string);
37248356cf6Smckusick 		fprintf(stdout,
373c42d362fSmckusick 		    "hz = %d, tick = %d, profhz = %d, stathz = %d\n",
374c42d362fSmckusick 		    clkp->hz, clkp->tick, clkp->profhz, clkp->stathz);
37548356cf6Smckusick 		return;
37648356cf6Smckusick 	}
377205717e4Smckusick 	if (special & BOOTTIME) {
3786e12f17fSmckusick 		struct timeval *btp = (struct timeval *)buf;
3796e12f17fSmckusick 
3806e12f17fSmckusick 		if (!nflag)
3816e12f17fSmckusick 			fprintf(stdout, "%s = %s\n", string,
3826e12f17fSmckusick 			    ctime(&btp->tv_sec));
3836e12f17fSmckusick 		else
3846e12f17fSmckusick 			fprintf(stdout, "%d\n", btp->tv_sec);
3856e12f17fSmckusick 		return;
3866e12f17fSmckusick 	}
387205717e4Smckusick 	if (special & CONSDEV) {
388205717e4Smckusick 		dev_t dev = *(dev_t *)buf;
389205717e4Smckusick 
390205717e4Smckusick 		if (!nflag)
391205717e4Smckusick 			fprintf(stdout, "%s = %s\n", string,
392205717e4Smckusick 			    devname(dev, S_IFCHR));
393205717e4Smckusick 		else
394205717e4Smckusick 			fprintf(stdout, "0x%x\n", dev);
395205717e4Smckusick 		return;
396205717e4Smckusick 	}
397a3a5e311Smckusick 	switch (type) {
398a3a5e311Smckusick 	case CTLTYPE_INT:
399c42d362fSmckusick 		if (newsize == 0) {
400c42d362fSmckusick 			if (!nflag)
401c42d362fSmckusick 				fprintf(stdout, "%s = ", string);
402c42d362fSmckusick 			fprintf(stdout, "%d\n", *(int *)buf);
403c42d362fSmckusick 		} else {
404c42d362fSmckusick 			if (!nflag)
405c42d362fSmckusick 				fprintf(stdout, "%s: %d -> ", string,
406c42d362fSmckusick 				    *(int *)buf);
407c42d362fSmckusick 			fprintf(stdout, "%d\n", *(int *)newval);
408c42d362fSmckusick 		}
409a3a5e311Smckusick 		return;
410a3a5e311Smckusick 
411a3a5e311Smckusick 	case CTLTYPE_STRING:
412c42d362fSmckusick 		if (newsize == 0) {
413c42d362fSmckusick 			if (!nflag)
414c42d362fSmckusick 				fprintf(stdout, "%s = ", string);
415c42d362fSmckusick 			fprintf(stdout, "%s\n", buf);
416c42d362fSmckusick 		} else {
417c42d362fSmckusick 			if (!nflag)
418c42d362fSmckusick 				fprintf(stdout, "%s: %s -> ", string, buf);
419c42d362fSmckusick 			fprintf(stdout, "%s\n", newval);
420c42d362fSmckusick 		}
42148356cf6Smckusick 		return;
422a3a5e311Smckusick 
423a3a5e311Smckusick 	case CTLTYPE_QUAD:
424a3a5e311Smckusick 		if (newsize == 0) {
425a3a5e311Smckusick 			if (!nflag)
426a3a5e311Smckusick 				fprintf(stdout, "%s = ", string);
427a3a5e311Smckusick 			fprintf(stdout, "%qd\n", *(quad_t *)buf);
428a3a5e311Smckusick 		} else {
429a3a5e311Smckusick 			if (!nflag)
430a3a5e311Smckusick 				fprintf(stdout, "%s: %qd -> ", string,
431a3a5e311Smckusick 				    *(quad_t *)buf);
432a3a5e311Smckusick 			fprintf(stdout, "%qd\n", *(quad_t *)newval);
433a3a5e311Smckusick 		}
434a3a5e311Smckusick 		return;
435a3a5e311Smckusick 
436a3a5e311Smckusick 	case CTLTYPE_STRUCT:
437a3a5e311Smckusick 		fprintf(stderr, "%s: unknown structure returned\n",
438a3a5e311Smckusick 		    string);
439a3a5e311Smckusick 		return;
440a3a5e311Smckusick 
441a3a5e311Smckusick 	default:
442a3a5e311Smckusick 	case CTLTYPE_NODE:
443a3a5e311Smckusick 		fprintf(stderr, "%s: unknown type returned\n",
444a3a5e311Smckusick 		    string);
445a3a5e311Smckusick 		return;
446a3a5e311Smckusick 	}
447a3a5e311Smckusick }
448a3a5e311Smckusick 
449314e6e3aSmckusick /*
450314e6e3aSmckusick  * Initialize the set of debugging names
451314e6e3aSmckusick  */
debuginit()452314e6e3aSmckusick debuginit()
453314e6e3aSmckusick {
4547cd463d7Sbostic 	int mib[3], loc, i;
4557cd463d7Sbostic 	size_t size;
456314e6e3aSmckusick 
457314e6e3aSmckusick 	if (secondlevel[CTL_DEBUG].list != 0)
458314e6e3aSmckusick 		return;
459314e6e3aSmckusick 	secondlevel[CTL_DEBUG].list = debugname;
460314e6e3aSmckusick 	mib[0] = CTL_DEBUG;
461314e6e3aSmckusick 	mib[2] = CTL_DEBUG_NAME;
46238187f89Smckusick 	for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) {
463314e6e3aSmckusick 		mib[1] = i;
464314e6e3aSmckusick 		size = BUFSIZ - loc;
465314e6e3aSmckusick 		if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
466314e6e3aSmckusick 			continue;
467314e6e3aSmckusick 		debugname[i].ctl_name = &names[loc];
468314e6e3aSmckusick 		debugname[i].ctl_type = CTLTYPE_INT;
469314e6e3aSmckusick 		loc += size;
470314e6e3aSmckusick 	}
47138187f89Smckusick 	lastused = loc;
47238187f89Smckusick }
47338187f89Smckusick 
47438187f89Smckusick /*
47538187f89Smckusick  * Initialize the set of filesystem names
47638187f89Smckusick  */
vfsinit()47738187f89Smckusick vfsinit()
47838187f89Smckusick {
47938187f89Smckusick 	int mib[4], maxtypenum, cnt, loc, size;
48038187f89Smckusick 	struct vfsconf vfc;
48138187f89Smckusick 	size_t buflen;
48238187f89Smckusick 
48338187f89Smckusick 	if (secondlevel[CTL_VFS].list != 0)
48438187f89Smckusick 		return;
48538187f89Smckusick 	mib[0] = CTL_VFS;
48638187f89Smckusick 	mib[1] = VFS_GENERIC;
48738187f89Smckusick 	mib[2] = VFS_MAXTYPENUM;
48838187f89Smckusick 	buflen = 4;
48938187f89Smckusick 	if (sysctl(mib, 3, &maxtypenum, &buflen, (void *)0, (size_t)0) < 0)
49038187f89Smckusick 		return;
49138187f89Smckusick 	if ((vfsname = malloc(maxtypenum * sizeof(*vfsname))) == 0)
49238187f89Smckusick 		return;
49338187f89Smckusick 	memset(vfsname, 0, maxtypenum * sizeof(*vfsname));
49438187f89Smckusick 	mib[2] = VFS_CONF;
49538187f89Smckusick 	buflen = sizeof vfc;
49638187f89Smckusick 	for (loc = lastused, cnt = 0; cnt < maxtypenum; cnt++) {
49738187f89Smckusick 		mib[3] = cnt;
49838187f89Smckusick 		if (sysctl(mib, 4, &vfc, &buflen, (void *)0, (size_t)0) < 0) {
49938187f89Smckusick 			if (errno == EOPNOTSUPP)
50038187f89Smckusick 				continue;
50138187f89Smckusick 			perror("vfsinit");
50238187f89Smckusick 			free(vfsname);
50338187f89Smckusick 			return;
50438187f89Smckusick 		}
50538187f89Smckusick 		strcat(&names[loc], vfc.vfc_name);
50638187f89Smckusick 		vfsname[cnt].ctl_name = &names[loc];
50738187f89Smckusick 		vfsname[cnt].ctl_type = CTLTYPE_INT;
50838187f89Smckusick 		size = strlen(vfc.vfc_name) + 1;
50938187f89Smckusick 		loc += size;
51038187f89Smckusick 	}
51138187f89Smckusick 	lastused = loc;
51238187f89Smckusick 	secondlevel[CTL_VFS].list = vfsname;
51338187f89Smckusick 	secondlevel[CTL_VFS].size = maxtypenum;
51438187f89Smckusick 	return;
515314e6e3aSmckusick }
516314e6e3aSmckusick 
517a3a5e311Smckusick struct ctlname inetname[] = CTL_IPPROTO_NAMES;
518a3a5e311Smckusick struct ctlname ipname[] = IPCTL_NAMES;
519a3a5e311Smckusick struct ctlname icmpname[] = ICMPCTL_NAMES;
5204310f570Smckusick struct ctlname udpname[] = UDPCTL_NAMES;
521a3a5e311Smckusick struct list inetlist = { inetname, IPPROTO_MAXID };
522a3a5e311Smckusick struct list inetvars[] = {
5234310f570Smckusick 	{ ipname, IPCTL_MAXID },	/* ip */
5244310f570Smckusick 	{ icmpname, ICMPCTL_MAXID },	/* icmp */
5254310f570Smckusick 	{ 0, 0 },			/* igmp */
5264310f570Smckusick 	{ 0, 0 },			/* ggmp */
5274310f570Smckusick 	{ 0, 0 },
5284310f570Smckusick 	{ 0, 0 },
5294310f570Smckusick 	{ 0, 0 },			/* tcp */
5304310f570Smckusick 	{ 0, 0 },
5314310f570Smckusick 	{ 0, 0 },			/* egp */
5324310f570Smckusick 	{ 0, 0 },
5334310f570Smckusick 	{ 0, 0 },
5344310f570Smckusick 	{ 0, 0 },
5354310f570Smckusick 	{ 0, 0 },			/* pup */
5364310f570Smckusick 	{ 0, 0 },
5374310f570Smckusick 	{ 0, 0 },
5384310f570Smckusick 	{ 0, 0 },
5394310f570Smckusick 	{ 0, 0 },
5404310f570Smckusick 	{ udpname, UDPCTL_MAXID },	/* udp */
541a3a5e311Smckusick };
542a3a5e311Smckusick 
543a3a5e311Smckusick /*
544a3a5e311Smckusick  * handle internet requests
545a3a5e311Smckusick  */
sysctl_inet(string,bufpp,mib,flags,typep)546a3a5e311Smckusick sysctl_inet(string, bufpp, mib, flags, typep)
547a3a5e311Smckusick 	char *string;
548a3a5e311Smckusick 	char **bufpp;
549a3a5e311Smckusick 	int mib[];
550a3a5e311Smckusick 	int flags;
551a3a5e311Smckusick 	int *typep;
552a3a5e311Smckusick {
553a3a5e311Smckusick 	struct list *lp;
554a3a5e311Smckusick 	int indx;
555a3a5e311Smckusick 
556a3a5e311Smckusick 	if (*bufpp == NULL) {
557a3a5e311Smckusick 		listall(string, &inetlist);
558a3a5e311Smckusick 		return (-1);
559a3a5e311Smckusick 	}
560a3a5e311Smckusick 	if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
561a3a5e311Smckusick 		return (-1);
562a3a5e311Smckusick 	mib[2] = indx;
5634310f570Smckusick 	if (indx <= IPPROTO_UDP && inetvars[indx].list != NULL)
564a3a5e311Smckusick 		lp = &inetvars[indx];
565a3a5e311Smckusick 	else if (!flags)
566a3a5e311Smckusick 		return (-1);
567a3a5e311Smckusick 	else {
568a3a5e311Smckusick 		fprintf(stderr, "%s: no variables defined for this protocol\n",
569a3a5e311Smckusick 		    string);
570a3a5e311Smckusick 		return (-1);
571a3a5e311Smckusick 	}
572a3a5e311Smckusick 	if (*bufpp == NULL) {
573a3a5e311Smckusick 		listall(string, lp);
574a3a5e311Smckusick 		return (-1);
575a3a5e311Smckusick 	}
576a3a5e311Smckusick 	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
577a3a5e311Smckusick 		return (-1);
578a3a5e311Smckusick 	mib[3] = indx;
579a3a5e311Smckusick 	*typep = lp->list[indx].ctl_type;
580a3a5e311Smckusick 	return (4);
58148356cf6Smckusick }
58248356cf6Smckusick 
58348356cf6Smckusick /*
58448356cf6Smckusick  * Scan a list of names searching for a particular name.
58548356cf6Smckusick  */
findname(string,level,bufp,namelist)58648356cf6Smckusick findname(string, level, bufp, namelist)
58748356cf6Smckusick 	char *string;
58848356cf6Smckusick 	char *level;
58948356cf6Smckusick 	char **bufp;
59048356cf6Smckusick 	struct list *namelist;
59148356cf6Smckusick {
59248356cf6Smckusick 	char *name;
59348356cf6Smckusick 	int i;
59448356cf6Smckusick 
59548356cf6Smckusick 	if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
59648356cf6Smckusick 		fprintf(stderr, "%s: incomplete specification\n", string);
59748356cf6Smckusick 		return (-1);
59848356cf6Smckusick 	}
59948356cf6Smckusick 	for (i = 0; i < namelist->size; i++)
60022798014Storek 		if (namelist->list[i].ctl_name != NULL &&
60122798014Storek 		    strcmp(name, namelist->list[i].ctl_name) == 0)
60248356cf6Smckusick 			break;
60348356cf6Smckusick 	if (i == namelist->size) {
60448356cf6Smckusick 		fprintf(stderr, "%s level name %s in %s is invalid\n",
60548356cf6Smckusick 		    level, name, string);
60648356cf6Smckusick 		return (-1);
60748356cf6Smckusick 	}
60848356cf6Smckusick 	return (i);
60948356cf6Smckusick }
61048356cf6Smckusick 
usage()61148356cf6Smckusick usage()
61248356cf6Smckusick {
61348356cf6Smckusick 
614733b6633Smckusick 	(void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n",
615733b6633Smckusick 	    "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...",
616733b6633Smckusick 	    "sysctl [-n] -a", "sysctl [-n] -A");
61748356cf6Smckusick 	exit(1);
61848356cf6Smckusick }
619