sysctl.c revision 6284
11553Srgrimes/*
21553Srgrimes * Copyright (c) 1993
31553Srgrimes *	The Regents of the University of California.  All rights reserved.
41553Srgrimes *
51553Srgrimes * Redistribution and use in source and binary forms, with or without
61553Srgrimes * modification, are permitted provided that the following conditions
71553Srgrimes * are met:
81553Srgrimes * 1. Redistributions of source code must retain the above copyright
91553Srgrimes *    notice, this list of conditions and the following disclaimer.
101553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111553Srgrimes *    notice, this list of conditions and the following disclaimer in the
121553Srgrimes *    documentation and/or other materials provided with the distribution.
131553Srgrimes * 3. All advertising materials mentioning features or use of this software
141553Srgrimes *    must display the following acknowledgement:
151553Srgrimes *	This product includes software developed by the University of
161553Srgrimes *	California, Berkeley and its contributors.
171553Srgrimes * 4. Neither the name of the University nor the names of its contributors
181553Srgrimes *    may be used to endorse or promote products derived from this software
191553Srgrimes *    without specific prior written permission.
201553Srgrimes *
211553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241553Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311553Srgrimes * SUCH DAMAGE.
321553Srgrimes */
331553Srgrimes
341553Srgrimes#ifndef lint
351553Srgrimesstatic char copyright[] =
361553Srgrimes"@(#) Copyright (c) 1993\n\
371553Srgrimes	The Regents of the University of California.  All rights reserved.\n";
381553Srgrimes#endif /* not lint */
391553Srgrimes
401553Srgrimes#ifndef lint
416284Swollman/*static char sccsid[] = "From: @(#)sysctl.c	8.1 (Berkeley) 6/6/93"; */
426284Swollmanstatic const char rcsid[] =
436284Swollman	"$Id$";
441553Srgrimes#endif /* not lint */
451553Srgrimes
461553Srgrimes#include <sys/param.h>
471553Srgrimes#include <sys/gmon.h>
481553Srgrimes#include <sys/stat.h>
491553Srgrimes#include <sys/sysctl.h>
501553Srgrimes#include <sys/socket.h>
511553Srgrimes#include <vm/vm_param.h>
521553Srgrimes#include <machine/cpu.h>
531553Srgrimes
541553Srgrimes#include <netinet/in.h>
551553Srgrimes#include <netinet/in_systm.h>
561553Srgrimes#include <netinet/ip.h>
571553Srgrimes#include <netinet/ip_icmp.h>
581553Srgrimes#include <netinet/icmp_var.h>
591553Srgrimes#include <netinet/ip_var.h>
601553Srgrimes#include <netinet/udp.h>
611553Srgrimes#include <netinet/udp_var.h>
626284Swollman#include <netinet/tcp.h>
636284Swollman#include <netinet/tcp_seq.h>
646284Swollman#include <netinet/tcp_timer.h>
656284Swollman#include <netinet/tcp_var.h>
661553Srgrimes
671553Srgrimes#include <errno.h>
681553Srgrimes#include <stdio.h>
691553Srgrimes#include <stdlib.h>
701553Srgrimes#include <string.h>
711553Srgrimes
721553Srgrimesstruct ctlname topname[] = CTL_NAMES;
731553Srgrimesstruct ctlname kernname[] = CTL_KERN_NAMES;
741553Srgrimesstruct ctlname vmname[] = CTL_VM_NAMES;
751553Srgrimesstruct ctlname netname[] = CTL_NET_NAMES;
761553Srgrimesstruct ctlname hwname[] = CTL_HW_NAMES;
771553Srgrimesstruct ctlname username[] = CTL_USER_NAMES;
781553Srgrimesstruct ctlname debugname[CTL_DEBUG_MAXID];
791553Srgrimes#ifdef CTL_MACHDEP_NAMES
801553Srgrimesstruct ctlname machdepname[] = CTL_MACHDEP_NAMES;
811553Srgrimes#endif
821553Srgrimeschar names[BUFSIZ];
831553Srgrimes
841553Srgrimesstruct list {
851553Srgrimes	struct	ctlname *list;
861553Srgrimes	int	size;
871553Srgrimes};
881553Srgrimesstruct list toplist = { topname, CTL_MAXID };
891553Srgrimesstruct list secondlevel[] = {
901553Srgrimes	{ 0, 0 },			/* CTL_UNSPEC */
911553Srgrimes	{ kernname, KERN_MAXID },	/* CTL_KERN */
921553Srgrimes	{ vmname, VM_MAXID },		/* CTL_VM */
931553Srgrimes	{ 0, 0 },			/* CTL_FS */
941553Srgrimes	{ netname, NET_MAXID },		/* CTL_NET */
951553Srgrimes	{ 0, CTL_DEBUG_MAXID },		/* CTL_DEBUG */
961553Srgrimes	{ hwname, HW_MAXID },		/* CTL_HW */
971553Srgrimes#ifdef CTL_MACHDEP_NAMES
981553Srgrimes	{ machdepname, CPU_MAXID },	/* CTL_MACHDEP */
991553Srgrimes#else
1001553Srgrimes	{ 0, 0 },			/* CTL_MACHDEP */
1011553Srgrimes#endif
1021553Srgrimes	{ username, USER_MAXID },	/* CTL_USER_NAMES */
1031553Srgrimes};
1041553Srgrimes
1051553Srgrimesint	Aflag, aflag, nflag, wflag;
1061553Srgrimes
1071553Srgrimes/*
1081553Srgrimes * Variables requiring special processing.
1091553Srgrimes */
1101553Srgrimes#define	CLOCK		0x00000001
1111553Srgrimes#define	BOOTTIME	0x00000002
1121553Srgrimes#define	CONSDEV		0x00000004
1131553Srgrimes
1141553Srgrimesint
1151553Srgrimesmain(argc, argv)
1161553Srgrimes	int argc;
1171553Srgrimes	char *argv[];
1181553Srgrimes{
1191553Srgrimes	extern char *optarg;
1201553Srgrimes	extern int optind;
1211553Srgrimes	int ch, lvl1;
1221553Srgrimes
1231553Srgrimes	while ((ch = getopt(argc, argv, "Aanw")) != EOF) {
1241553Srgrimes		switch (ch) {
1251553Srgrimes
1261553Srgrimes		case 'A':
1271553Srgrimes			Aflag = 1;
1281553Srgrimes			break;
1291553Srgrimes
1301553Srgrimes		case 'a':
1311553Srgrimes			aflag = 1;
1321553Srgrimes			break;
1331553Srgrimes
1341553Srgrimes		case 'n':
1351553Srgrimes			nflag = 1;
1361553Srgrimes			break;
1371553Srgrimes
1381553Srgrimes		case 'w':
1391553Srgrimes			wflag = 1;
1401553Srgrimes			break;
1411553Srgrimes
1421553Srgrimes		default:
1431553Srgrimes			usage();
1441553Srgrimes		}
1451553Srgrimes	}
1461553Srgrimes	argc -= optind;
1471553Srgrimes	argv += optind;
1481553Srgrimes
1491553Srgrimes	if (Aflag || aflag) {
1501553Srgrimes		debuginit();
1511553Srgrimes		for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
1521553Srgrimes			listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
1531553Srgrimes		exit(0);
1541553Srgrimes	}
1551553Srgrimes	if (argc == 0)
1561553Srgrimes		usage();
1571553Srgrimes	while (argc-- > 0)
1581553Srgrimes		parse(*argv, 1);
1591553Srgrimes	exit(0);
1601553Srgrimes}
1611553Srgrimes
1621553Srgrimes/*
1631553Srgrimes * List all variables known to the system.
1641553Srgrimes */
1651553Srgrimeslistall(prefix, lp)
1661553Srgrimes	char *prefix;
1671553Srgrimes	struct list *lp;
1681553Srgrimes{
1691553Srgrimes	int lvl2;
1701553Srgrimes	char *cp, name[BUFSIZ];
1711553Srgrimes
1721553Srgrimes	if (lp->list == 0)
1731553Srgrimes		return;
1741553Srgrimes	strcpy(name, prefix);
1751553Srgrimes	cp = &name[strlen(name)];
1761553Srgrimes	*cp++ = '.';
1771553Srgrimes	for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
1781553Srgrimes		if (lp->list[lvl2].ctl_name == 0)
1791553Srgrimes			continue;
1801553Srgrimes		strcpy(cp, lp->list[lvl2].ctl_name);
1811553Srgrimes		parse(name, Aflag);
1821553Srgrimes	}
1831553Srgrimes}
1841553Srgrimes
1851553Srgrimes/*
1861553Srgrimes * Parse a name into a MIB entry.
1871553Srgrimes * Lookup and print out the MIB entry if it exists.
1881553Srgrimes * Set a new value if requested.
1891553Srgrimes */
1901553Srgrimesparse(string, flags)
1911553Srgrimes	char *string;
1921553Srgrimes	int flags;
1931553Srgrimes{
1941553Srgrimes	int indx, type, state, size, len;
1951553Srgrimes	int special = 0;
1961553Srgrimes	void *newval = 0;
1971553Srgrimes	int intval, newsize = 0;
1981553Srgrimes	quad_t quadval;
1991553Srgrimes	struct list *lp;
2001553Srgrimes	int mib[CTL_MAXNAME];
2011553Srgrimes	char *cp, *bufp, buf[BUFSIZ], strval[BUFSIZ];
2021553Srgrimes
2031553Srgrimes	bufp = buf;
2041553Srgrimes	snprintf(buf, BUFSIZ, "%s", string);
2051553Srgrimes	if ((cp = strchr(string, '=')) != NULL) {
2061553Srgrimes		if (!wflag) {
2071553Srgrimes			fprintf(stderr, "Must specify -w to set variables\n");
2081553Srgrimes			exit(2);
2091553Srgrimes		}
2101553Srgrimes		*strchr(buf, '=') = '\0';
2111553Srgrimes		*cp++ = '\0';
2121553Srgrimes		while (isspace(*cp))
2131553Srgrimes			cp++;
2141553Srgrimes		newval = cp;
2151553Srgrimes		newsize = strlen(cp);
2161553Srgrimes	}
2171553Srgrimes	if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
2181553Srgrimes		return;
2191553Srgrimes	mib[0] = indx;
2201553Srgrimes	if (indx == CTL_DEBUG)
2211553Srgrimes		debuginit();
2221553Srgrimes	lp = &secondlevel[indx];
2231553Srgrimes	if (lp->list == 0) {
2241553Srgrimes		fprintf(stderr, "%s: class is not implemented\n",
2251553Srgrimes		    topname[indx]);
2261553Srgrimes		return;
2271553Srgrimes	}
2281553Srgrimes	if (bufp == NULL) {
2291553Srgrimes		listall(topname[indx].ctl_name, lp);
2301553Srgrimes		return;
2311553Srgrimes	}
2321553Srgrimes	if ((indx = findname(string, "second", &bufp, lp)) == -1)
2331553Srgrimes		return;
2341553Srgrimes	mib[1] = indx;
2351553Srgrimes	type = lp->list[indx].ctl_type;
2361553Srgrimes	len = 2;
2371553Srgrimes	switch (mib[0]) {
2381553Srgrimes
2391553Srgrimes	case CTL_KERN:
2401553Srgrimes		switch (mib[1]) {
2411553Srgrimes		case KERN_PROF:
2421553Srgrimes			mib[2] = GPROF_STATE;
2431553Srgrimes			size = sizeof state;
2441553Srgrimes			if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) {
2451553Srgrimes				if (flags == 0)
2461553Srgrimes					return;
2471553Srgrimes				if (!nflag)
2481553Srgrimes					fprintf(stdout, "%s: ", string);
2491553Srgrimes				fprintf(stderr,
2501553Srgrimes				    "kernel is not compiled for profiling\n");
2511553Srgrimes				return;
2521553Srgrimes			}
2531553Srgrimes			if (!nflag)
2541553Srgrimes				fprintf(stdout, "%s: %s\n", string,
2551553Srgrimes				    state == GMON_PROF_OFF ? "off" : "running");
2561553Srgrimes			return;
2571553Srgrimes		case KERN_VNODE:
2581553Srgrimes		case KERN_FILE:
2591553Srgrimes			if (flags == 0)
2601553Srgrimes				return;
2611553Srgrimes			fprintf(stderr,
2621553Srgrimes			    "Use pstat to view %s information\n", string);
2631553Srgrimes			return;
2641553Srgrimes		case KERN_PROC:
2651553Srgrimes			if (flags == 0)
2661553Srgrimes				return;
2671553Srgrimes			fprintf(stderr,
2681553Srgrimes			    "Use ps to view %s information\n", string);
2691553Srgrimes			return;
2701553Srgrimes		case KERN_CLOCKRATE:
2711553Srgrimes			special |= CLOCK;
2721553Srgrimes			break;
2731553Srgrimes		case KERN_BOOTTIME:
2741553Srgrimes			special |= BOOTTIME;
2751553Srgrimes			break;
2761553Srgrimes		}
2771553Srgrimes		break;
2781553Srgrimes
2791553Srgrimes	case CTL_HW:
2801553Srgrimes		break;
2811553Srgrimes
2821553Srgrimes	case CTL_VM:
2831553Srgrimes		if (mib[1] == VM_LOADAVG) {
2841553Srgrimes			double loads[3];
2851553Srgrimes
2861553Srgrimes			getloadavg(loads, 3);
2871553Srgrimes			if (!nflag)
2881553Srgrimes				fprintf(stdout, "%s: ", string);
2891553Srgrimes			fprintf(stdout, "%.2f %.2f %.2f\n",
2901553Srgrimes			    loads[0], loads[1], loads[2]);
2911553Srgrimes			return;
2921553Srgrimes		}
2931553Srgrimes		if (flags == 0)
2941553Srgrimes			return;
2951553Srgrimes		fprintf(stderr,
2961553Srgrimes		    "Use vmstat or systat to view %s information\n", string);
2971553Srgrimes		return;
2981553Srgrimes
2991553Srgrimes	case CTL_NET:
3001553Srgrimes		if (mib[1] == PF_INET) {
3011553Srgrimes			len = sysctl_inet(string, &bufp, mib, flags, &type);
3021553Srgrimes			if (len >= 0)
3031553Srgrimes				break;
3041553Srgrimes			return;
3051553Srgrimes		}
3061553Srgrimes		if (flags == 0)
3071553Srgrimes			return;
3081553Srgrimes		fprintf(stderr, "Use netstat to view %s information\n", string);
3091553Srgrimes		return;
3101553Srgrimes
3111553Srgrimes	case CTL_DEBUG:
3121553Srgrimes		mib[2] = CTL_DEBUG_VALUE;
3131553Srgrimes		len = 3;
3141553Srgrimes		break;
3151553Srgrimes
3161553Srgrimes	case CTL_MACHDEP:
3171553Srgrimes#ifdef CPU_CONSDEV
3181553Srgrimes		if (mib[1] == CPU_CONSDEV)
3191553Srgrimes			special |= CONSDEV;
3201553Srgrimes#endif
3211553Srgrimes		break;
3221553Srgrimes
3231553Srgrimes	case CTL_FS:
3241553Srgrimes	case CTL_USER:
3251553Srgrimes		break;
3261553Srgrimes
3271553Srgrimes	default:
3281553Srgrimes		fprintf(stderr, "Illegal top level value: %d\n", mib[0]);
3291553Srgrimes		return;
3301553Srgrimes
3311553Srgrimes	}
3321553Srgrimes	if (bufp) {
3331553Srgrimes		fprintf(stderr, "name %s in %s is unknown\n", *bufp, string);
3341553Srgrimes		return;
3351553Srgrimes	}
3361553Srgrimes	if (newsize > 0) {
3371553Srgrimes		switch (type) {
3381553Srgrimes		case CTLTYPE_INT:
3391553Srgrimes			intval = atoi(newval);
3401553Srgrimes			newval = &intval;
3411553Srgrimes			newsize = sizeof intval;
3421553Srgrimes			break;
3431553Srgrimes
3441553Srgrimes		case CTLTYPE_QUAD:
3451553Srgrimes			sscanf(newval, "%qd", &quadval);
3461553Srgrimes			newval = &quadval;
3471553Srgrimes			newsize = sizeof quadval;
3481553Srgrimes			break;
3491553Srgrimes		}
3501553Srgrimes	}
3511553Srgrimes	size = BUFSIZ;
3521553Srgrimes	if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) {
3531553Srgrimes		if (flags == 0)
3541553Srgrimes			return;
3551553Srgrimes		switch (errno) {
3561553Srgrimes		case EOPNOTSUPP:
3571553Srgrimes			fprintf(stderr, "%s: value is not available\n", string);
3581553Srgrimes			return;
3591553Srgrimes		case ENOTDIR:
3601553Srgrimes			fprintf(stderr, "%s: specification is incomplete\n",
3611553Srgrimes			    string);
3621553Srgrimes			return;
3631553Srgrimes		case ENOMEM:
3641553Srgrimes			fprintf(stderr, "%s: type is unknown to this program\n",
3651553Srgrimes			    string);
3661553Srgrimes			return;
3671553Srgrimes		default:
3681553Srgrimes			perror(string);
3691553Srgrimes			return;
3701553Srgrimes		}
3711553Srgrimes	}
3721553Srgrimes	if (special & CLOCK) {
3731553Srgrimes		struct clockinfo *clkp = (struct clockinfo *)buf;
3741553Srgrimes
3751553Srgrimes		if (!nflag)
3761553Srgrimes			fprintf(stdout, "%s: ", string);
3771553Srgrimes		fprintf(stdout,
3781553Srgrimes		    "hz = %d, tick = %d, profhz = %d, stathz = %d\n",
3791553Srgrimes		    clkp->hz, clkp->tick, clkp->profhz, clkp->stathz);
3801553Srgrimes		return;
3811553Srgrimes	}
3821553Srgrimes	if (special & BOOTTIME) {
3831553Srgrimes		struct timeval *btp = (struct timeval *)buf;
3841553Srgrimes
3851553Srgrimes		if (!nflag)
3861951Swollman			fprintf(stdout, "%s = %s", string,
3871553Srgrimes			    ctime(&btp->tv_sec));
3881553Srgrimes		else
3891553Srgrimes			fprintf(stdout, "%d\n", btp->tv_sec);
3901553Srgrimes		return;
3911553Srgrimes	}
3921553Srgrimes	if (special & CONSDEV) {
3931553Srgrimes		dev_t dev = *(dev_t *)buf;
3941553Srgrimes
3951553Srgrimes		if (!nflag)
3961553Srgrimes			fprintf(stdout, "%s = %s\n", string,
3971553Srgrimes			    devname(dev, S_IFCHR));
3981553Srgrimes		else
3991553Srgrimes			fprintf(stdout, "0x%x\n", dev);
4001553Srgrimes		return;
4011553Srgrimes	}
4021553Srgrimes	switch (type) {
4031553Srgrimes	case CTLTYPE_INT:
4041553Srgrimes		if (newsize == 0) {
4051553Srgrimes			if (!nflag)
4061553Srgrimes				fprintf(stdout, "%s = ", string);
4071553Srgrimes			fprintf(stdout, "%d\n", *(int *)buf);
4081553Srgrimes		} else {
4091553Srgrimes			if (!nflag)
4101553Srgrimes				fprintf(stdout, "%s: %d -> ", string,
4111553Srgrimes				    *(int *)buf);
4121553Srgrimes			fprintf(stdout, "%d\n", *(int *)newval);
4131553Srgrimes		}
4141553Srgrimes		return;
4151553Srgrimes
4161553Srgrimes	case CTLTYPE_STRING:
4171553Srgrimes		if (newsize == 0) {
4181553Srgrimes			if (!nflag)
4191553Srgrimes				fprintf(stdout, "%s = ", string);
4201553Srgrimes			fprintf(stdout, "%s\n", buf);
4211553Srgrimes		} else {
4221553Srgrimes			if (!nflag)
4231553Srgrimes				fprintf(stdout, "%s: %s -> ", string, buf);
4241553Srgrimes			fprintf(stdout, "%s\n", newval);
4251553Srgrimes		}
4261553Srgrimes		return;
4271553Srgrimes
4281553Srgrimes	case CTLTYPE_QUAD:
4291553Srgrimes		if (newsize == 0) {
4301553Srgrimes			if (!nflag)
4311553Srgrimes				fprintf(stdout, "%s = ", string);
4321553Srgrimes			fprintf(stdout, "%qd\n", *(quad_t *)buf);
4331553Srgrimes		} else {
4341553Srgrimes			if (!nflag)
4351553Srgrimes				fprintf(stdout, "%s: %qd -> ", string,
4361553Srgrimes				    *(quad_t *)buf);
4371553Srgrimes			fprintf(stdout, "%qd\n", *(quad_t *)newval);
4381553Srgrimes		}
4391553Srgrimes		return;
4401553Srgrimes
4411553Srgrimes	case CTLTYPE_STRUCT:
4421553Srgrimes		fprintf(stderr, "%s: unknown structure returned\n",
4431553Srgrimes		    string);
4441553Srgrimes		return;
4451553Srgrimes
4461553Srgrimes	default:
4471553Srgrimes	case CTLTYPE_NODE:
4481553Srgrimes		fprintf(stderr, "%s: unknown type returned\n",
4491553Srgrimes		    string);
4501553Srgrimes		return;
4511553Srgrimes	}
4521553Srgrimes}
4531553Srgrimes
4541553Srgrimes/*
4551553Srgrimes * Initialize the set of debugging names
4561553Srgrimes */
4571553Srgrimesdebuginit()
4581553Srgrimes{
4591553Srgrimes	int mib[3], size, loc, i;
4601553Srgrimes
4611553Srgrimes	if (secondlevel[CTL_DEBUG].list != 0)
4621553Srgrimes		return;
4631553Srgrimes	secondlevel[CTL_DEBUG].list = debugname;
4641553Srgrimes	mib[0] = CTL_DEBUG;
4651553Srgrimes	mib[2] = CTL_DEBUG_NAME;
4661553Srgrimes	for (loc = 0, i = 0; i < CTL_DEBUG_MAXID; i++) {
4671553Srgrimes		mib[1] = i;
4681553Srgrimes		size = BUFSIZ - loc;
4691553Srgrimes		if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
4701553Srgrimes			continue;
4711553Srgrimes		debugname[i].ctl_name = &names[loc];
4721553Srgrimes		debugname[i].ctl_type = CTLTYPE_INT;
4731553Srgrimes		loc += size;
4741553Srgrimes	}
4751553Srgrimes}
4761553Srgrimes
4771553Srgrimesstruct ctlname inetname[] = CTL_IPPROTO_NAMES;
4781553Srgrimesstruct ctlname ipname[] = IPCTL_NAMES;
4791553Srgrimesstruct ctlname icmpname[] = ICMPCTL_NAMES;
4801553Srgrimesstruct ctlname udpname[] = UDPCTL_NAMES;
4816284Swollmanstruct ctlname tcpname[] = TCPCTL_NAMES;
4821553Srgrimesstruct list inetlist = { inetname, IPPROTO_MAXID };
4831553Srgrimesstruct list inetvars[] = {
4841553Srgrimes	{ ipname, IPCTL_MAXID },	/* ip */
4851553Srgrimes	{ icmpname, ICMPCTL_MAXID },	/* icmp */
4861553Srgrimes	{ 0, 0 },			/* igmp */
4871553Srgrimes	{ 0, 0 },			/* ggmp */
4881553Srgrimes	{ 0, 0 },
4891553Srgrimes	{ 0, 0 },
4906284Swollman	{ tcpname, TCPCTL_MAXID },	/* tcp */
4911553Srgrimes	{ 0, 0 },
4921553Srgrimes	{ 0, 0 },			/* egp */
4931553Srgrimes	{ 0, 0 },
4941553Srgrimes	{ 0, 0 },
4951553Srgrimes	{ 0, 0 },
4961553Srgrimes	{ 0, 0 },			/* pup */
4971553Srgrimes	{ 0, 0 },
4981553Srgrimes	{ 0, 0 },
4991553Srgrimes	{ 0, 0 },
5001553Srgrimes	{ 0, 0 },
5011553Srgrimes	{ udpname, UDPCTL_MAXID },	/* udp */
5021553Srgrimes};
5031553Srgrimes
5041553Srgrimes/*
5051553Srgrimes * handle internet requests
5061553Srgrimes */
5071553Srgrimessysctl_inet(string, bufpp, mib, flags, typep)
5081553Srgrimes	char *string;
5091553Srgrimes	char **bufpp;
5101553Srgrimes	int mib[];
5111553Srgrimes	int flags;
5121553Srgrimes	int *typep;
5131553Srgrimes{
5141553Srgrimes	struct list *lp;
5151553Srgrimes	int indx;
5161553Srgrimes
5171553Srgrimes	if (*bufpp == NULL) {
5181553Srgrimes		listall(string, &inetlist);
5191553Srgrimes		return (-1);
5201553Srgrimes	}
5211553Srgrimes	if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
5221553Srgrimes		return (-1);
5231553Srgrimes	mib[2] = indx;
5241553Srgrimes	if (indx <= IPPROTO_UDP && inetvars[indx].list != NULL)
5251553Srgrimes		lp = &inetvars[indx];
5261553Srgrimes	else if (!flags)
5271553Srgrimes		return (-1);
5281553Srgrimes	else {
5291553Srgrimes		fprintf(stderr, "%s: no variables defined for this protocol\n",
5301553Srgrimes		    string);
5311553Srgrimes		return (-1);
5321553Srgrimes	}
5331553Srgrimes	if (*bufpp == NULL) {
5341553Srgrimes		listall(string, lp);
5351553Srgrimes		return (-1);
5361553Srgrimes	}
5371553Srgrimes	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
5381553Srgrimes		return (-1);
5391553Srgrimes	mib[3] = indx;
5401553Srgrimes	*typep = lp->list[indx].ctl_type;
5411553Srgrimes	return (4);
5421553Srgrimes}
5431553Srgrimes
5441553Srgrimes/*
5451553Srgrimes * Scan a list of names searching for a particular name.
5461553Srgrimes */
5471553Srgrimesfindname(string, level, bufp, namelist)
5481553Srgrimes	char *string;
5491553Srgrimes	char *level;
5501553Srgrimes	char **bufp;
5511553Srgrimes	struct list *namelist;
5521553Srgrimes{
5531553Srgrimes	char *name;
5541553Srgrimes	int i;
5551553Srgrimes
5561553Srgrimes	if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
5571553Srgrimes		fprintf(stderr, "%s: incomplete specification\n", string);
5581553Srgrimes		return (-1);
5591553Srgrimes	}
5601553Srgrimes	for (i = 0; i < namelist->size; i++)
5611553Srgrimes		if (namelist->list[i].ctl_name != NULL &&
5621553Srgrimes		    strcmp(name, namelist->list[i].ctl_name) == 0)
5631553Srgrimes			break;
5641553Srgrimes	if (i == namelist->size) {
5651553Srgrimes		fprintf(stderr, "%s level name %s in %s is invalid\n",
5661553Srgrimes		    level, name, string);
5671553Srgrimes		return (-1);
5681553Srgrimes	}
5691553Srgrimes	return (i);
5701553Srgrimes}
5711553Srgrimes
5721553Srgrimesusage()
5731553Srgrimes{
5741553Srgrimes
5751553Srgrimes	(void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n",
5761553Srgrimes	    "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...",
5771553Srgrimes	    "sysctl [-n] -a", "sysctl [-n] -A");
5781553Srgrimes	exit(1);
5791553Srgrimes}
580