sysctl.c revision 1.81
1238384Sjkim/*	$OpenBSD: sysctl.c,v 1.81 2002/06/09 04:49:19 angelos Exp $	*/
2238384Sjkim/*	$NetBSD: sysctl.c,v 1.9 1995/09/30 07:12:50 thorpej Exp $	*/
3238384Sjkim
4238384Sjkim/*
5238384Sjkim * Copyright (c) 1993
6238384Sjkim *	The Regents of the University of California.  All rights reserved.
7238384Sjkim *
8238384Sjkim * Redistribution and use in source and binary forms, with or without
9238384Sjkim * modification, are permitted provided that the following conditions
10238384Sjkim * are met:
11238384Sjkim * 1. Redistributions of source code must retain the above copyright
12238384Sjkim *    notice, this list of conditions and the following disclaimer.
13238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright
14238384Sjkim *    notice, this list of conditions and the following disclaimer in the
15238384Sjkim *    documentation and/or other materials provided with the distribution.
16238384Sjkim * 3. All advertising materials mentioning features or use of this software
17238384Sjkim *    must display the following acknowledgement:
18238384Sjkim *	This product includes software developed by the University of
19238384Sjkim *	California, Berkeley and its contributors.
20238384Sjkim * 4. Neither the name of the University nor the names of its contributors
21238384Sjkim *    may be used to endorse or promote products derived from this software
22238384Sjkim *    without specific prior written permission.
23238384Sjkim *
24238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25238384Sjkim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27238384Sjkim * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28238384Sjkim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29238384Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30238384Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32238384Sjkim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33238384Sjkim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34238384Sjkim * SUCH DAMAGE.
35238384Sjkim */
36238384Sjkim
37238384Sjkim#ifndef lint
38238384Sjkimstatic char copyright[] =
39238384Sjkim"@(#) Copyright (c) 1993\n\
40238384Sjkim	The Regents of the University of California.  All rights reserved.\n";
41238384Sjkim#endif /* not lint */
42238384Sjkim
43238384Sjkim#ifndef lint
44238384Sjkim#if 0
45238384Sjkimstatic char sccsid[] = "@(#)sysctl.c	8.5 (Berkeley) 5/9/95";
46238384Sjkim#else
47238384Sjkimstatic char *rcsid = "$OpenBSD: sysctl.c,v 1.81 2002/06/09 04:49:19 angelos Exp $";
48238384Sjkim#endif
49238384Sjkim#endif /* not lint */
50238384Sjkim
51238384Sjkim#include <sys/param.h>
52238384Sjkim#include <sys/gmon.h>
53238384Sjkim#include <sys/mount.h>
54238384Sjkim#include <sys/stat.h>
55238384Sjkim#include <sys/sysctl.h>
56238384Sjkim#include <sys/socket.h>
57238384Sjkim#include <sys/malloc.h>
58238384Sjkim#include <sys/dkstat.h>
59238384Sjkim#include <sys/uio.h>
60238384Sjkim#include <sys/tty.h>
61238384Sjkim#include <sys/namei.h>
62238384Sjkim#include <machine/cpu.h>
63238384Sjkim#include <net/route.h>
64238384Sjkim
65238384Sjkim#include <netinet/in.h>
66238384Sjkim#include <netinet/in_systm.h>
67238384Sjkim#include <netinet/ip.h>
68238384Sjkim#include <netinet/in_pcb.h>
69238384Sjkim#include <netinet/ip_icmp.h>
70238384Sjkim#include <netinet/ip_ipip.h>
71238384Sjkim#include <netinet/ip_ether.h>
72238384Sjkim#include <netinet/ip_ah.h>
73238384Sjkim#include <netinet/ip_esp.h>
74238384Sjkim#include <netinet/icmp_var.h>
75238384Sjkim#include <netinet/ip_var.h>
76238384Sjkim#include <netinet/udp.h>
77238384Sjkim#include <netinet/udp_var.h>
78238384Sjkim#include <netinet/tcp.h>
79238384Sjkim#include <netinet/tcp_timer.h>
80238384Sjkim#include <netinet/tcp_var.h>
81238384Sjkim#include <netinet/ip_gre.h>
82238384Sjkim#include <netinet/ip_ipcomp.h>
83238384Sjkim
84238384Sjkim#ifdef INET6
85238384Sjkim#include <netinet/ip6.h>
86238384Sjkim#include <netinet/icmp6.h>
87238384Sjkim#include <netinet6/ip6_var.h>
88238384Sjkim#include <netinet6/pim6_var.h>
89238384Sjkim#endif
90238384Sjkim
91238384Sjkim#include <uvm/uvm_swap_encrypt.h>
92238384Sjkim
93238384Sjkim#include <ufs/ufs/quota.h>
94238384Sjkim#include <ufs/ufs/inode.h>
95238384Sjkim#include <ufs/ffs/fs.h>
96238384Sjkim#include <ufs/ffs/ffs_extern.h>
97238384Sjkim
98238384Sjkim#include <nfs/rpcv2.h>
99238384Sjkim#include <nfs/nfsproto.h>
100238384Sjkim#include <nfs/nfs.h>
101238384Sjkim
102238384Sjkim#include <netipx/ipx.h>
103238384Sjkim#include <netipx/ipx_var.h>
104238384Sjkim#include <netipx/spx_var.h>
105238384Sjkim#include <ddb/db_var.h>
106238384Sjkim#include <dev/rndvar.h>
107238384Sjkim
108238384Sjkim#include <err.h>
109238384Sjkim#include <errno.h>
110238384Sjkim#include <stdio.h>
111238384Sjkim#include <stdlib.h>
112238384Sjkim#include <string.h>
113238384Sjkim#include <ctype.h>
114238384Sjkim
115238384Sjkim#ifdef CPU_BIOS
116238384Sjkim#include <machine/biosvar.h>
117238384Sjkim#endif
118238384Sjkim
119238384Sjkimstruct ctlname topname[] = CTL_NAMES;
120238384Sjkimstruct ctlname kernname[] = CTL_KERN_NAMES;
121238384Sjkimstruct ctlname vmname[] = CTL_VM_NAMES;
122238384Sjkimstruct ctlname fsname[] = CTL_FS_NAMES;
123238384Sjkimstruct ctlname netname[] = CTL_NET_NAMES;
124238384Sjkimstruct ctlname hwname[] = CTL_HW_NAMES;
125238384Sjkimstruct ctlname username[] = CTL_USER_NAMES;
126238384Sjkimstruct ctlname debugname[CTL_DEBUG_MAXID];
127238384Sjkimstruct ctlname kernmallocname[] = CTL_KERN_MALLOC_NAMES;
128238384Sjkimstruct ctlname forkstatname[] = CTL_KERN_FORKSTAT_NAMES;
129238384Sjkimstruct ctlname nchstatsname[] = CTL_KERN_NCHSTATS_NAMES;
130238384Sjkimstruct ctlname ttyname[] = CTL_KERN_TTY_NAMES;
131238384Sjkimstruct ctlname *vfsname;
132238384Sjkim#ifdef CTL_MACHDEP_NAMES
133238384Sjkimstruct ctlname machdepname[] = CTL_MACHDEP_NAMES;
134238384Sjkim#endif
135238384Sjkimstruct ctlname ddbname[] = CTL_DDB_NAMES;
136238384Sjkimchar names[BUFSIZ];
137238384Sjkimint lastused;
138238384Sjkim
139238384Sjkimstruct list {
140238384Sjkim	struct	ctlname *list;
141238384Sjkim	int	size;
142238384Sjkim};
143238384Sjkimstruct list toplist = { topname, CTL_MAXID };
144238384Sjkimstruct list secondlevel[] = {
145238384Sjkim	{ 0, 0 },			/* CTL_UNSPEC */
146238384Sjkim	{ kernname, KERN_MAXID },	/* CTL_KERN */
147238384Sjkim	{ vmname, VM_MAXID },		/* CTL_VM */
148238384Sjkim	{ fsname, FS_MAXID },		/* CTL_FS */
149238384Sjkim	{ netname, NET_MAXID },		/* CTL_NET */
150238384Sjkim	{ 0, CTL_DEBUG_MAXID },		/* CTL_DEBUG */
151238384Sjkim	{ hwname, HW_MAXID },		/* CTL_HW */
152238384Sjkim#ifdef CTL_MACHDEP_NAMES
153238384Sjkim	{ machdepname, CPU_MAXID },	/* CTL_MACHDEP */
154238384Sjkim#else
155238384Sjkim	{ 0, 0 },			/* CTL_MACHDEP */
156238384Sjkim#endif
157238384Sjkim	{ username, USER_MAXID },	/* CTL_USER_NAMES */
158238384Sjkim	{ ddbname, DBCTL_MAXID },	/* CTL_DDB_NAMES */
159238384Sjkim	{ 0, 0 },			/* CTL_VFS */
160238384Sjkim};
161238384Sjkim
162238384Sjkimint	Aflag, aflag, nflag, wflag;
163238384Sjkim
164238384Sjkim/*
165238384Sjkim * Variables requiring special processing.
166238384Sjkim */
167238384Sjkim#define	CLOCK		0x00000001
168238384Sjkim#define	BOOTTIME	0x00000002
169238384Sjkim#define	CHRDEV		0x00000004
170238384Sjkim#define	BLKDEV		0x00000008
171238384Sjkim#define	RNDSTATS	0x00000010
172238384Sjkim#define	BADDYNAMIC	0x00000020
173238384Sjkim#define	BIOSGEO		0x00000040
174238384Sjkim#define	BIOSDEV		0x00000080
175238384Sjkim#define	MAJ2DEV		0x00000100
176238384Sjkim#define	UNSIGNED	0x00000200
177238384Sjkim#define	KMEMBUCKETS	0x00000400
178238384Sjkim#define	LONGARRAY	0x00000800
179238384Sjkim#define KMEMSTATS	0x00001000
180238384Sjkim
181238384Sjkim/* prototypes */
182238384Sjkimvoid debuginit(void);
183238384Sjkimvoid listall(char *, struct list *);
184238384Sjkimvoid parse(char *, int);
185238384Sjkimvoid parse_baddynamic(int *, size_t, char *, void **, size_t *, int, int);
186238384Sjkimvoid usage(void);
187238384Sjkimint findname(char *, char *, char **, struct list *);
188238384Sjkimint sysctl_inet(char *, char **, int *, int, int *);
189238384Sjkim#ifdef INET6
190238384Sjkimint sysctl_inet6(char *, char **, int *, int, int *);
191238384Sjkim#endif
192238384Sjkimint sysctl_ipx(char *, char **, int *, int, int *);
193238384Sjkimint sysctl_fs(char *, char **, int *, int, int *);
194238384Sjkimstatic int sysctl_vfs(char *, char **, int[], int, int *);
195238384Sjkimstatic int sysctl_vfsgen(char *, char **, int[], int, int *);
196238384Sjkimint sysctl_bios(char *, char **, int *, int, int *);
197238384Sjkimint sysctl_swpenc(char *, char **, int *, int, int *);
198238384Sjkimint sysctl_forkstat(char *, char **, int *, int, int *);
199238384Sjkimint sysctl_tty(char *, char **, int *, int, int *);
200238384Sjkimint sysctl_nchstats(char *, char **, int *, int, int *);
201238384Sjkimint sysctl_malloc(char *, char **, int *, int, int *);
202238384Sjkim#ifdef CPU_CHIPSET
203238384Sjkimint sysctl_chipset(char *, char **, int *, int, int *);
204238384Sjkim#endif
205238384Sjkimvoid vfsinit(void);
206238384Sjkim
207238384Sjkimint
208238384Sjkimmain(argc, argv)
209238384Sjkim	int argc;
210238384Sjkim	char *argv[];
211238384Sjkim{
212238384Sjkim	int ch, lvl1;
213238384Sjkim
214238384Sjkim	while ((ch = getopt(argc, argv, "Aanw")) != -1) {
215238384Sjkim		switch (ch) {
216238384Sjkim
217238384Sjkim		case 'A':
218238384Sjkim			Aflag = 1;
219238384Sjkim			break;
220238384Sjkim
221238384Sjkim		case 'a':
222238384Sjkim			aflag = 1;
223238384Sjkim			break;
224238384Sjkim
225238384Sjkim		case 'n':
226238384Sjkim			nflag = 1;
227238384Sjkim			break;
228238384Sjkim
229238384Sjkim		case 'w':
230238384Sjkim			wflag = 1;
231238384Sjkim			break;
232238384Sjkim
233238384Sjkim		default:
234238384Sjkim			usage();
235238384Sjkim		}
236238384Sjkim	}
237238384Sjkim	argc -= optind;
238238384Sjkim	argv += optind;
239238384Sjkim
240238384Sjkim	if (argc == 0 && (Aflag || aflag)) {
241238384Sjkim		debuginit();
242238384Sjkim		vfsinit();
243238384Sjkim		for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
244238384Sjkim			listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
245238384Sjkim		return (0);
246238384Sjkim	}
247238384Sjkim	if (argc == 0)
248238384Sjkim		usage();
249238384Sjkim	for (; *argv != NULL; ++argv)
250238384Sjkim		parse(*argv, 1);
251238384Sjkim	return (0);
252238384Sjkim}
253238384Sjkim
254238384Sjkim/*
255238384Sjkim * List all variables known to the system.
256238384Sjkim */
257238384Sjkimvoid
258238384Sjkimlistall(prefix, lp)
259238384Sjkim	char *prefix;
260238384Sjkim	struct list *lp;
261279264Sdelphij{
262279264Sdelphij	char *cp, name[BUFSIZ];
263279264Sdelphij	int lvl2, len;
264279264Sdelphij
265279264Sdelphij	if (lp->list == NULL)
266279264Sdelphij		return;
267238384Sjkim	if ((len = strlcpy(name, prefix, sizeof(name))) >= sizeof(name))
268238384Sjkim		warn("%s: name too long", prefix);
269238384Sjkim	cp = name + len++;
270238384Sjkim	*cp++ = '.';
271238384Sjkim	for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
272238384Sjkim		if (lp->list[lvl2].ctl_name == NULL)
273238384Sjkim			continue;
274238384Sjkim		if (strlcpy(cp, lp->list[lvl2].ctl_name,
275238384Sjkim		    sizeof(name) - len) >= sizeof(name) - len)
276238384Sjkim			warn("%s: name too long", lp->list[lvl2].ctl_name);
277238384Sjkim		parse(name, Aflag);
278238384Sjkim	}
279238384Sjkim}
280238384Sjkim
281238384Sjkim/*
282238384Sjkim * Parse a name into a MIB entry.
283238384Sjkim * Lookup and print out the MIB entry if it exists.
284238384Sjkim * Set a new value if requested.
285238384Sjkim */
286238384Sjkimvoid
287238384Sjkimparse(string, flags)
288238384Sjkim	char *string;
289238384Sjkim	int flags;
290238384Sjkim{
291238384Sjkim	int indx, type, state, intval, len;
292238384Sjkim	size_t size, newsize = 0;
293238384Sjkim	int lal = 0, special = 0;
294238384Sjkim	void *newval = 0;
295238384Sjkim	int64_t quadval;
296238384Sjkim	struct list *lp;
297238384Sjkim	int mib[CTL_MAXNAME];
298238384Sjkim	char *cp, *bufp, buf[BUFSIZ];
299238384Sjkim
300238384Sjkim	(void)strlcpy(buf, string, sizeof(buf));
301238384Sjkim	bufp = buf;
302238384Sjkim	if ((cp = strchr(string, '=')) != NULL) {
303238384Sjkim		if (!wflag)
304238384Sjkim			errx(2, "must specify -w to set variables");
305238384Sjkim		*strchr(buf, '=') = '\0';
306238384Sjkim		*cp++ = '\0';
307238384Sjkim		while (isspace(*cp))
308238384Sjkim			cp++;
309238384Sjkim		newval = cp;
310238384Sjkim		newsize = strlen(cp);
311238384Sjkim	}
312238384Sjkim	if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
313238384Sjkim		return;
314238384Sjkim	mib[0] = indx;
315238384Sjkim	if (indx == CTL_VFS)
316238384Sjkim		vfsinit();
317238384Sjkim	if (indx == CTL_DEBUG)
318238384Sjkim		debuginit();
319238384Sjkim	lp = &secondlevel[indx];
320238384Sjkim	if (lp->list == 0) {
321238384Sjkim		warnx("%s: class is not implemented", topname[indx].ctl_name);
322238384Sjkim		return;
323238384Sjkim	}
324238384Sjkim	if (bufp == NULL) {
325238384Sjkim		listall(topname[indx].ctl_name, lp);
326238384Sjkim		return;
327238384Sjkim	}
328238384Sjkim	if ((indx = findname(string, "second", &bufp, lp)) == -1)
329238384Sjkim		return;
330238384Sjkim	mib[1] = indx;
331238384Sjkim	type = lp->list[indx].ctl_type;
332238384Sjkim	len = 2;
333238384Sjkim	switch (mib[0]) {
334238384Sjkim
335238384Sjkim	case CTL_KERN:
336238384Sjkim		switch (mib[1]) {
337238384Sjkim		case KERN_PROF:
338238384Sjkim			mib[2] = GPROF_STATE;
339238384Sjkim			size = sizeof(state);
340238384Sjkim			if (sysctl(mib, 3, &state, &size, NULL, 0) == -1) {
341238384Sjkim				if (flags == 0)
342238384Sjkim					return;
343238384Sjkim				if (!nflag)
344238384Sjkim					(void)printf("%s: ", string);
345238384Sjkim				(void)puts("kernel is not compiled for profiling");
346238384Sjkim				return;
347238384Sjkim			}
348238384Sjkim			if (!nflag)
349238384Sjkim				(void)printf("%s = %s\n", string,
350238384Sjkim				    state == GMON_PROF_OFF ? "off" : "running");
351238384Sjkim			return;
352238384Sjkim		case KERN_FORKSTAT:
353238384Sjkim			sysctl_forkstat(string, &bufp, mib, flags, &type);
354238384Sjkim			return;
355238384Sjkim		case KERN_TTY:
356238384Sjkim			len = sysctl_tty(string, &bufp, mib, flags, &type);
357238384Sjkim			if (len < 0)
358238384Sjkim				return;
359238384Sjkim			newsize = 0;
360238384Sjkim			break;
361238384Sjkim		case KERN_NCHSTATS:
362238384Sjkim			sysctl_nchstats(string, &bufp, mib, flags, &type);
363238384Sjkim			return;
364238384Sjkim		case KERN_MALLOCSTATS:
365238384Sjkim			len = sysctl_malloc(string, &bufp, mib, flags, &type);
366238384Sjkim			if (len < 0)
367238384Sjkim				return;
368238384Sjkim			if (mib[2] == KERN_MALLOC_BUCKET)
369238384Sjkim				special |= KMEMBUCKETS;
370238384Sjkim			if (mib[2] == KERN_MALLOC_KMEMSTATS)
371238384Sjkim				special |= KMEMSTATS;
372238384Sjkim			newsize = 0;
373238384Sjkim			break;
374238384Sjkim		case KERN_MBSTAT:
375238384Sjkim			if (flags == 0)
376238384Sjkim				return;
377238384Sjkim			warnx("use netstat to view %s", string);
378238384Sjkim			return;
379238384Sjkim		case KERN_MSGBUF:
380238384Sjkim			if (flags == 0)
381238384Sjkim				return;
382238384Sjkim			warnx("use dmesg to view %s", string);
383238384Sjkim			return;
384238384Sjkim		case KERN_VNODE:
385238384Sjkim		case KERN_FILE:
386238384Sjkim			if (flags == 0)
387238384Sjkim				return;
388238384Sjkim			warnx("use pstat to view %s information", string);
389238384Sjkim			return;
390238384Sjkim		case KERN_PROC:
391238384Sjkim			if (flags == 0)
392238384Sjkim				return;
393238384Sjkim			warnx("use ps to view %s information", string);
394238384Sjkim			return;
395238384Sjkim		case KERN_NTPTIME:
396238384Sjkim			if (flags == 0)
397238384Sjkim				return;
398238384Sjkim			warnx("use xntpdc to view %s information", string);
399238384Sjkim			return;
400238384Sjkim		case KERN_CLOCKRATE:
401238384Sjkim			special |= CLOCK;
402238384Sjkim			break;
403238384Sjkim		case KERN_BOOTTIME:
404238384Sjkim			special |= BOOTTIME;
405238384Sjkim			break;
406238384Sjkim		case KERN_RND:
407238384Sjkim			special |= RNDSTATS;
408238384Sjkim			break;
409238384Sjkim		case KERN_HOSTID:
410238384Sjkim		case KERN_ARND:
411238384Sjkim			special |= UNSIGNED;
412238384Sjkim			break;
413238384Sjkim		case KERN_CPTIME:
414238384Sjkim			special |= LONGARRAY;
415238384Sjkim			lal = CPUSTATES;
416238384Sjkim			break;
417238384Sjkim		}
418238384Sjkim		break;
419238384Sjkim
420238384Sjkim	case CTL_HW:
421238384Sjkim		switch (mib[1]) {
422238384Sjkim		case HW_DISKSTATS:
423238384Sjkim			/*
424238384Sjkim			 * Only complain if someone asks explicitly for this,
425238384Sjkim			 * otherwise "fail" silently.
426238384Sjkim			 */
427238384Sjkim			if (flags)
428238384Sjkim				warnx("use vmstat to view %s information",
429238384Sjkim				    string);
430238384Sjkim			return;
431238384Sjkim		}
432238384Sjkim		break;
433238384Sjkim
434238384Sjkim	case CTL_VM:
435238384Sjkim		if (mib[1] == VM_LOADAVG) {
436238384Sjkim			double loads[3];
437238384Sjkim
438238384Sjkim			getloadavg(loads, 3);
439238384Sjkim			if (!nflag)
440238384Sjkim				(void)printf("%s = ", string);
441238384Sjkim			(void)printf("%.2f %.2f %.2f\n", loads[0],
442238384Sjkim			    loads[1], loads[2]);
443238384Sjkim			return;
444238384Sjkim		} else if (mib[1] == VM_PSSTRINGS) {
445238384Sjkim			struct _ps_strings _ps;
446238384Sjkim
447238384Sjkim			size = sizeof(_ps);
448238384Sjkim			if (sysctl(mib, 2, &_ps, &size, NULL, 0) == -1) {
449238384Sjkim				if (flags == 0)
450238384Sjkim					return;
451238384Sjkim				if (!nflag)
452238384Sjkim					(void)printf("%s: ", string);
453238384Sjkim				(void)puts("can't find ps strings");
454238384Sjkim				return;
455238384Sjkim			}
456238384Sjkim			if (!nflag)
457238384Sjkim				(void)printf("%s = ", string);
458238384Sjkim			(void)printf("%p\n", _ps.val);
459238384Sjkim			return;
460238384Sjkim		} else if (mib[1] == VM_SWAPENCRYPT) {
461238384Sjkim			len = sysctl_swpenc(string, &bufp, mib, flags, &type);
462238384Sjkim			if (len < 0)
463238384Sjkim				return;
464238384Sjkim
465238384Sjkim			break;
466		} else if (mib[1] == VM_NKMEMPAGES ||
467		    mib[1] == VM_ANONMIN ||
468		    mib[1] == VM_VTEXTMIN ||
469		    mib[1] == VM_VNODEMIN) {
470			break;
471		}
472		if (flags == 0)
473			return;
474		warnx("use vmstat or systat to view %s information", string);
475		return;
476
477		break;
478
479	case CTL_NET:
480		if (mib[1] == PF_INET) {
481			len = sysctl_inet(string, &bufp, mib, flags, &type);
482			if (len < 0)
483				return;
484
485			if ((mib[2] == IPPROTO_TCP &&
486			     mib[3] == TCPCTL_BADDYNAMIC) ||
487			    (mib[2] == IPPROTO_UDP &&
488			     mib[3] == UDPCTL_BADDYNAMIC)) {
489
490				special |= BADDYNAMIC;
491
492				if (newval != NULL)
493					parse_baddynamic(mib, len, string,
494					    &newval, &newsize, flags, nflag);
495			}
496			break;
497		}
498#ifdef INET6
499		if (mib[1] == PF_INET6) {
500			len = sysctl_inet6(string, &bufp, mib, flags, &type);
501			if (len < 0)
502				return;
503
504			break;
505		}
506#endif
507		if (mib[1] == PF_IPX) {
508			len = sysctl_ipx(string, &bufp, mib, flags, &type);
509			if (len >= 0)
510				break;
511			return;
512		}
513		if (flags == 0)
514			return;
515		warnx("use netstat to view %s information", string);
516		return;
517
518	case CTL_DEBUG:
519		mib[2] = CTL_DEBUG_VALUE;
520		len = 3;
521		break;
522
523	case CTL_MACHDEP:
524#ifdef CPU_CONSDEV
525		if (mib[1] == CPU_CONSDEV)
526			special |= CHRDEV;
527#endif
528#ifdef CPU_BLK2CHR
529		if (mib[1] == CPU_BLK2CHR) {
530			if (bufp == NULL)
531				return;
532			mib[2] = makedev(atoi(bufp),0);
533			bufp = NULL;
534			len = 3;
535			special |= CHRDEV;
536			break;
537		}
538#endif
539#ifdef CPU_CHR2BLK
540		if (mib[1] == CPU_CHR2BLK) {
541			if (bufp == NULL)
542				return;
543			mib[2] = makedev(atoi(bufp),0);
544			bufp = NULL;
545			len = 3;
546			special |= BLKDEV;
547			break;
548		}
549#endif
550#ifdef CPU_BIOS
551		if (mib[1] == CPU_BIOS) {
552			len = sysctl_bios(string, &bufp, mib, flags, &type);
553			if (len < 0)
554				return;
555			if (mib[2] == BIOS_DEV)
556				special |= BIOSDEV;
557			if (mib[2] == BIOS_DISKINFO)
558				special |= BIOSGEO;
559			break;
560		}
561#endif
562#ifdef CPU_CHIPSET
563		if (mib[1] == CPU_CHIPSET) {
564			len = sysctl_chipset(string, &bufp, mib, flags, &type);
565			if (len < 0)
566				return;
567			break;
568		}
569#endif
570		break;
571
572	case CTL_FS:
573		len = sysctl_fs(string, &bufp, mib, flags, &type);
574		if (len >= 0)
575			break;
576		return;
577
578	case CTL_VFS:
579		if (mib[1])
580			len = sysctl_vfs(string, &bufp, mib, flags, &type);
581		else
582			len = sysctl_vfsgen(string, &bufp, mib, flags, &type);
583		if (len >= 0) {
584			if (type == CTLTYPE_STRUCT) {
585				if (flags)
586					warnx("use nfsstat to view %s information",
587					    MOUNT_NFS);
588				return;
589			} else
590				break;
591		}
592		return;
593
594	case CTL_USER:
595	case CTL_DDB:
596		break;
597
598	default:
599		warnx("illegal top level value: %d", mib[0]);
600		return;
601
602	}
603	if (bufp) {
604		warnx("name %s in %s is unknown", bufp, string);
605		return;
606	}
607	if (newsize > 0) {
608		switch (type) {
609		case CTLTYPE_INT:
610			errno = 0;
611			if (special & UNSIGNED)
612				intval = strtoul(newval, &cp, 10);
613			else
614				intval = strtol(newval, &cp, 10);
615			if (*cp != '\0') {
616				warnx("%s: illegal value: %s", string,
617				    (char *)newval);
618				return;
619			}
620			if (errno == ERANGE) {
621				warnx("%s: value %s out of range", string,
622				    (char *)newval);
623				return;
624			}
625			newval = &intval;
626			newsize = sizeof(intval);
627			break;
628
629		case CTLTYPE_QUAD:
630			/* XXX - assumes sizeof(long long) == sizeof(quad_t) */
631			(void)sscanf(newval, "%lld", (long long *)&quadval);
632			newval = &quadval;
633			newsize = sizeof(quadval);
634			break;
635		}
636	}
637	size = BUFSIZ;
638	if (sysctl(mib, len, buf, &size, newval, newsize) == -1) {
639		if (flags == 0)
640			return;
641		switch (errno) {
642		case EOPNOTSUPP:
643			warnx("%s: value is not available", string);
644			return;
645		case ENOTDIR:
646			warnx("%s: specification is incomplete", string);
647			return;
648		case ENOMEM:
649			warnx("%s: type is unknown to this program", string);
650			return;
651		case ENXIO:
652			if (special & BIOSGEO)
653				return;
654		default:
655			warn("%s", string);
656			return;
657		}
658	}
659	if (special & KMEMBUCKETS) {
660		struct kmembuckets *kb = (struct kmembuckets *)buf;
661		if (!nflag)
662			(void)printf("%s = ", string);
663		printf("(");
664		printf("calls = %llu ", (long long)kb->kb_calls);
665		printf("total_allocated = %llu ", (long long)kb->kb_total);
666		printf("total_free = %lld ", (long long)kb->kb_totalfree);
667		printf("elements = %lld ", (long long)kb->kb_elmpercl);
668		printf("high watermark = %lld ", (long long)kb->kb_highwat);
669		printf("could_free = %lld", (long long)kb->kb_couldfree);
670		printf(")\n");
671		return;
672	}
673	if (special & KMEMSTATS) {
674		struct kmemstats *km = (struct kmemstats *)buf;
675		int j, first = 1;
676
677		if (!nflag)
678			(void)printf("%s = ", string);
679		(void)printf("(inuse = %ld, calls = %ld, memuse = %ldK, limblocks = %d, mapblocks = %d, maxused = %ldK, limit = %ldK, spare = %ld, sizes = (", km->ks_inuse, km->ks_calls, (km->ks_memuse + 1023) / 1024, km->ks_limblocks, km->ks_mapblocks, (km->ks_maxused + 1023) / 1024, (km->ks_limit + 1023) / 1024, km->ks_spare);
680		for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
681		 	if ((km->ks_size & j ) == 0)
682				continue;
683			if (first)
684				(void)printf("%d", j);
685			else
686				(void)printf(",%d", j);
687			first = 0;
688		}
689		if (first)
690			(void)printf("none");
691		(void)printf("))\n");
692		return;
693	}
694	if (special & CLOCK) {
695		struct clockinfo *clkp = (struct clockinfo *)buf;
696
697		if (!nflag)
698			(void)printf("%s = ", string);
699		(void)printf(
700		    "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n",
701		    clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz);
702		return;
703	}
704	if (special & BOOTTIME) {
705		struct timeval *btp = (struct timeval *)buf;
706		time_t boottime;
707
708		if (!nflag) {
709			boottime = btp->tv_sec;
710			(void)printf("%s = %s", string, ctime(&boottime));
711		} else
712			(void)printf("%ld\n", btp->tv_sec);
713		return;
714	}
715	if (special & BLKDEV) {
716		dev_t dev = *(dev_t *)buf;
717
718		if (!nflag)
719			(void)printf("%s = %s\n", string,
720			    devname(dev, S_IFBLK));
721		else
722			(void)printf("0x%x\n", dev);
723		return;
724	}
725	if (special & CHRDEV) {
726		dev_t dev = *(dev_t *)buf;
727
728		if (!nflag)
729			(void)printf("%s = %s\n", string,
730			    devname(dev, S_IFCHR));
731		else
732			(void)printf("0x%x\n", dev);
733		return;
734	}
735#ifdef CPU_BIOS
736	if (special & BIOSGEO) {
737		bios_diskinfo_t *pdi = (bios_diskinfo_t *)buf;
738
739		if (!nflag)
740			(void)printf("%s = ", string);
741		(void)printf("bootdev = 0x%x, "
742			     "cylinders = %u, heads = %u, sectors = %u\n",
743			     pdi->bsd_dev, pdi->bios_cylinders,
744			     pdi->bios_heads, pdi->bios_sectors);
745		return;
746	}
747	if (special & BIOSDEV) {
748		int dev = *(int*)buf;
749
750		if (!nflag)
751			(void)printf("%s = ", string);
752		(void) printf("0x%02x\n", dev);
753		return;
754	}
755#endif
756	if (special & UNSIGNED) {
757		if (newsize == 0) {
758			if (!nflag)
759				(void)printf("%s = ", string);
760			(void)printf("%u\n", *(u_int *)buf);
761		} else {
762			if (!nflag)
763				(void)printf("%s: %u -> ", string,
764				    *(u_int *)buf);
765			(void)printf("%u\n", *(u_int *)newval);
766		}
767		return;
768	}
769	if (special & RNDSTATS) {
770		struct rndstats *rndstats = (struct rndstats *)buf;
771		int i;
772
773		if (!nflag)
774			(void)printf("%s = ", string);
775		(void)printf(
776		"%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
777		    (unsigned long long)rndstats->rnd_total,
778		    (unsigned long long)rndstats->rnd_used,
779		    (unsigned long long)rndstats->rnd_reads,
780		    (unsigned long long)rndstats->arc4_reads,
781		    (unsigned long long)rndstats->arc4_nstirs,
782		    (unsigned long long)rndstats->arc4_stirs,
783		    (unsigned long long)rndstats->rnd_pad[0],
784		    (unsigned long long)rndstats->rnd_pad[1],
785		    (unsigned long long)rndstats->rnd_pad[2],
786		    (unsigned long long)rndstats->rnd_pad[3],
787		    (unsigned long long)rndstats->rnd_pad[4],
788		    (unsigned long long)rndstats->rnd_waits,
789		    (unsigned long long)rndstats->rnd_enqs,
790		    (unsigned long long)rndstats->rnd_deqs,
791		    (unsigned long long)rndstats->rnd_drops,
792		    (unsigned long long)rndstats->rnd_drople);
793		for (i = 0; i < sizeof(rndstats->rnd_ed)/sizeof(rndstats->rnd_ed[0]); i++)
794			(void)printf(" %llu", (unsigned long long)rndstats->rnd_ed[i]);
795		for (i = 0; i < sizeof(rndstats->rnd_sc)/sizeof(rndstats->rnd_sc[0]); i++)
796			(void)printf(" %llu", (unsigned long long)rndstats->rnd_sc[i]);
797		for (i = 0; i < sizeof(rndstats->rnd_sb)/sizeof(rndstats->rnd_sb[0]); i++)
798			(void)printf(" %llu", (unsigned long long)rndstats->rnd_sb[i]);
799		printf("\n");
800		return;
801	}
802	if (special & BADDYNAMIC) {
803		in_port_t port, lastport;
804		u_int32_t *baddynamic = (u_int32_t *)buf;
805
806		if (!nflag)
807			(void)printf("%s%s", string, newsize ? ": " : " = ");
808		lastport = 0;
809		for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED; port++)
810			if (DP_ISSET(baddynamic, port)) {
811				(void)printf("%s%hd", lastport ? "," : "",
812				    port);
813				lastport = port;
814			}
815		if (newsize != 0) {
816			if (!nflag)
817				fputs(" -> ", stdout);
818			baddynamic = (u_int32_t *)newval;
819			lastport = 0;
820			for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED;
821			    port++)
822				if (DP_ISSET(baddynamic, port)) {
823					(void)printf("%s%hd",
824					    lastport ? "," : "", port);
825					lastport = port;
826				}
827		}
828		(void)putchar('\n');
829		return;
830	}
831	if (special & LONGARRAY) {
832		long *la = (long *)buf;
833		if (!nflag)
834			printf("%s = ", string);
835		while (lal--)
836			printf("%ld%s", *la++, lal? ",":"");
837		putchar('\n');
838		return;
839	}
840	switch (type) {
841	case CTLTYPE_INT:
842		if (newsize == 0) {
843			if (!nflag)
844				(void)printf("%s = ", string);
845			(void)printf("%d\n", *(int *)buf);
846		} else {
847			if (!nflag)
848				(void)printf("%s: %d -> ", string,
849				    *(int *)buf);
850			(void)printf("%d\n", *(int *)newval);
851		}
852		return;
853
854	case CTLTYPE_STRING:
855		if (newval == NULL) {
856			if (!nflag)
857				(void)printf("%s = ", string);
858			(void)puts(buf);
859		} else {
860			if (!nflag)
861				(void)printf("%s: %s -> ", string, buf);
862			(void)puts((char *)newval);
863		}
864		return;
865
866	case CTLTYPE_QUAD:
867		if (newsize == 0) {
868			long long tmp = *(quad_t *)buf;
869
870			if (!nflag)
871				(void)printf("%s = ", string);
872			(void)printf("%lld\n", tmp);
873		} else {
874			long long tmp = *(quad_t *)buf;
875
876			if (!nflag)
877				(void)printf("%s: %lld -> ", string, tmp);
878			tmp = *(quad_t *)newval;
879			(void)printf("%qd\n", tmp);
880		}
881		return;
882
883	case CTLTYPE_STRUCT:
884		warnx("%s: unknown structure returned", string);
885		return;
886
887	default:
888	case CTLTYPE_NODE:
889		warnx("%s: unknown type returned", string);
890		return;
891	}
892}
893
894void
895parse_baddynamic(mib, len, string, newvalp, newsizep, flags, nflag)
896	int mib[];
897	size_t len;
898	char *string;
899	void **newvalp;
900	size_t *newsizep;
901	int flags;
902	int nflag;
903{
904	static u_int32_t newbaddynamic[DP_MAPSIZE];
905	in_port_t port;
906	size_t size;
907	char action, *cp;
908
909	if (strchr((char *)*newvalp, '+') || strchr((char *)*newvalp, '-')) {
910		size = sizeof(newbaddynamic);
911		if (sysctl(mib, len, newbaddynamic, &size, 0, 0) == -1) {
912			if (flags == 0)
913				return;
914			if (!nflag)
915				(void)printf("%s: ", string);
916			(void)puts("kernel does contain bad dynamic port tables");
917			return;
918		}
919
920		while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) {
921			if (*cp != '+' && *cp != '-')
922				errx(1, "cannot mix +/- with full list");
923			action = *cp++;
924			port = atoi(cp);
925			if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED)
926				errx(1, "invalid port, range is %d to %d",
927				    IPPORT_RESERVED/2, IPPORT_RESERVED-1);
928			if (action == '+')
929				DP_SET(newbaddynamic, port);
930			else
931				DP_CLR(newbaddynamic, port);
932		}
933	} else {
934		(void)memset((void *)newbaddynamic, 0, sizeof(newbaddynamic));
935		while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) {
936			port = atoi(cp);
937			if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED)
938				errx(1, "invalid port, range is %d to %d",
939				    IPPORT_RESERVED/2, IPPORT_RESERVED-1);
940			DP_SET(newbaddynamic, port);
941		}
942	}
943
944	*newvalp = (void *)newbaddynamic;
945	*newsizep = sizeof(newbaddynamic);
946}
947
948/*
949 * Initialize the set of debugging names
950 */
951void
952debuginit()
953{
954	int mib[3], loc, i;
955	size_t size;
956
957	if (secondlevel[CTL_DEBUG].list != 0)
958		return;
959	secondlevel[CTL_DEBUG].list = debugname;
960	mib[0] = CTL_DEBUG;
961	mib[2] = CTL_DEBUG_NAME;
962	for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) {
963		mib[1] = i;
964		size = BUFSIZ - loc;
965		if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
966			continue;
967		debugname[i].ctl_name = &names[loc];
968		debugname[i].ctl_type = CTLTYPE_INT;
969		loc += size;
970	}
971	lastused = loc;
972}
973
974struct ctlname vfsgennames[] = CTL_VFSGENCTL_NAMES;
975struct ctlname ffsname[] = FFS_NAMES;
976struct ctlname nfsname[] = FS_NFS_NAMES;
977struct list *vfsvars;
978int *vfs_typenums;
979
980/*
981 * Initialize the set of filesystem names
982 */
983void
984vfsinit()
985{
986	int mib[4], maxtypenum, cnt, loc, size;
987	struct vfsconf vfc;
988	size_t buflen;
989
990	if (secondlevel[CTL_VFS].list != 0)
991		return;
992	mib[0] = CTL_VFS;
993	mib[1] = VFS_GENERIC;
994	mib[2] = VFS_MAXTYPENUM;
995	buflen = 4;
996	if (sysctl(mib, 3, &maxtypenum, &buflen, (void *)0, (size_t)0) < 0)
997		return;
998	maxtypenum++;	/* + generic */
999	if ((vfs_typenums = malloc(maxtypenum * sizeof(int))) == NULL)
1000		return;
1001	memset(vfs_typenums, 0, maxtypenum * sizeof(int));
1002	if ((vfsvars = malloc(maxtypenum * sizeof(*vfsvars))) == NULL) {
1003		free(vfs_typenums);
1004		return;
1005	}
1006	memset(vfsvars, 0, maxtypenum * sizeof(*vfsvars));
1007	if ((vfsname = malloc(maxtypenum * sizeof(*vfsname))) == NULL) {
1008		free(vfs_typenums);
1009		free(vfsvars);
1010		return;
1011	}
1012	memset(vfsname, 0, maxtypenum * sizeof(*vfsname));
1013	mib[2] = VFS_CONF;
1014	buflen = sizeof vfc;
1015	for (loc = lastused, cnt = 1; cnt < maxtypenum; cnt++) {
1016		mib[3] = cnt - 1;
1017		if (sysctl(mib, 4, &vfc, &buflen, (void *)0, (size_t)0) < 0) {
1018			if (errno == EOPNOTSUPP)
1019				continue;
1020			warn("vfsinit");
1021			free(vfsname);
1022			return;
1023		}
1024		if (!strcmp(vfc.vfc_name, MOUNT_FFS)) {
1025			vfsvars[cnt].list = ffsname;
1026			vfsvars[cnt].size = FFS_MAXID;
1027		}
1028		if (!strcmp(vfc.vfc_name, MOUNT_NFS)) {
1029			vfsvars[cnt].list = nfsname;
1030			vfsvars[cnt].size = NFS_MAXID;
1031		}
1032		vfs_typenums[cnt] = vfc.vfc_typenum;
1033		strcat(&names[loc], vfc.vfc_name);
1034		vfsname[cnt].ctl_name = &names[loc];
1035		vfsname[cnt].ctl_type = CTLTYPE_NODE;
1036		size = strlen(vfc.vfc_name) + 1;
1037		loc += size;
1038	}
1039	lastused = loc;
1040
1041	vfsname[0].ctl_name = "mounts";
1042	vfsname[0].ctl_type = CTLTYPE_NODE;
1043	vfsvars[0].list = vfsname + 1;
1044	vfsvars[0].size = maxtypenum - 1;
1045
1046	secondlevel[CTL_VFS].list = vfsname;
1047	secondlevel[CTL_VFS].size = maxtypenum;
1048	return;
1049}
1050
1051int
1052sysctl_vfsgen(string, bufpp, mib, flags, typep)
1053	char *string;
1054	char **bufpp;
1055	int mib[];
1056	int flags;
1057	int *typep;
1058{
1059	int indx;
1060	size_t size;
1061	struct vfsconf vfc;
1062
1063	if (*bufpp == NULL) {
1064		listall(string, vfsvars);
1065		return (-1);
1066	}
1067
1068	if ((indx = findname(string, "third", bufpp, vfsvars)) == -1)
1069		return (-1);
1070
1071	mib[1] = VFS_GENERIC;
1072	mib[2] = VFS_CONF;
1073	mib[3] = indx;
1074	size = sizeof vfc;
1075	if (sysctl(mib, 4, &vfc, &size, (void *)0, (size_t)0) < 0) {
1076		if (errno != EOPNOTSUPP)
1077			warn("vfs print");
1078		return -1;
1079	}
1080	if (flags == 0 && vfc.vfc_refcount == 0)
1081		return -1;
1082	if (!nflag)
1083		fprintf(stdout, "%s has %d mounted instance%s\n",
1084		    string, vfc.vfc_refcount,
1085		    vfc.vfc_refcount != 1 ? "s" : "");
1086	else
1087		fprintf(stdout, "%d\n", vfc.vfc_refcount);
1088
1089	return -1;
1090}
1091
1092int
1093sysctl_vfs(string, bufpp, mib, flags, typep)
1094	char *string;
1095	char **bufpp;
1096	int mib[];
1097	int flags;
1098	int *typep;
1099{
1100	struct list *lp = &vfsvars[mib[1]];
1101	int indx;
1102
1103	if (lp->list == NULL) {
1104		if (flags)
1105			warnx("No variables defined for file system %s", string);
1106		return(-1);
1107	}
1108	if (*bufpp == NULL) {
1109		listall(string, lp);
1110		return (-1);
1111	}
1112	if ((indx = findname(string, "third", bufpp, lp)) == -1)
1113		return (-1);
1114
1115	mib[1] = vfs_typenums[mib[1]];
1116	mib[2] = indx;
1117	*typep = lp->list[indx].ctl_type;
1118	return (3);
1119}
1120
1121struct ctlname posixname[] = CTL_FS_POSIX_NAMES;
1122struct list fslist = { posixname, FS_POSIX_MAXID };
1123
1124/*
1125 * handle file system requests
1126 */
1127int
1128sysctl_fs(string, bufpp, mib, flags, typep)
1129	char *string;
1130	char **bufpp;
1131	int mib[];
1132	int flags;
1133	int *typep;
1134{
1135	int indx;
1136
1137	if (*bufpp == NULL) {
1138		listall(string, &fslist);
1139		return(-1);
1140	}
1141	if ((indx = findname(string, "third", bufpp, &fslist)) == -1)
1142		return(-1);
1143	mib[2] = indx;
1144	*typep = fslist.list[indx].ctl_type;
1145	return(3);
1146}
1147
1148#ifdef CPU_BIOS
1149struct ctlname biosname[] = CTL_BIOS_NAMES;
1150struct list bioslist = { biosname, BIOS_MAXID };
1151
1152/*
1153 * handle BIOS requests
1154 */
1155int
1156sysctl_bios(string, bufpp, mib, flags, typep)
1157	char *string;
1158	char **bufpp;
1159	int mib[];
1160	int flags;
1161	int *typep;
1162{
1163	char *name;
1164	int indx;
1165
1166	if (*bufpp == NULL) {
1167		listall(string, &bioslist);
1168		return(-1);
1169	}
1170	if ((indx = findname(string, "third", bufpp, &bioslist)) == -1)
1171		return(-1);
1172	mib[2] = indx;
1173	if (indx == BIOS_DISKINFO) {
1174		if (*bufpp == NULL) {
1175			char name[BUFSIZ];
1176
1177			/* scan all the bios devices */
1178			for (indx = 0; indx < 256; indx++) {
1179				snprintf(name, sizeof(name), "%s.%u",
1180					 string, indx);
1181				parse(name, 1);
1182			}
1183			return(-1);
1184		}
1185		if ((name = strsep(bufpp, ".")) == NULL) {
1186			warnx("%s: incomplete specification", string);
1187			return(-1);
1188		}
1189		mib[3] = atoi(name);
1190		*typep = CTLTYPE_STRUCT;
1191		return(4);
1192	} else {
1193		*typep = bioslist.list[indx].ctl_type;
1194		return(3);
1195	}
1196}
1197#endif
1198
1199struct ctlname swpencname[] = CTL_SWPENC_NAMES;
1200struct list swpenclist = { swpencname, SWPENC_MAXID };
1201
1202/*
1203 * handle swap encrypt requests
1204 */
1205int
1206sysctl_swpenc(string, bufpp, mib, flags, typep)
1207	char *string;
1208	char **bufpp;
1209	int mib[];
1210	int flags;
1211	int *typep;
1212{
1213	int indx;
1214
1215	if (*bufpp == NULL) {
1216		listall(string, &swpenclist);
1217		return(-1);
1218	}
1219	if ((indx = findname(string, "third", bufpp, &swpenclist)) == -1)
1220		return(-1);
1221	mib[2] = indx;
1222	*typep = swpenclist.list[indx].ctl_type;
1223	return(3);
1224}
1225
1226struct ctlname inetname[] = CTL_IPPROTO_NAMES;
1227struct ctlname ipname[] = IPCTL_NAMES;
1228struct ctlname icmpname[] = ICMPCTL_NAMES;
1229struct ctlname ipipname[] = IPIPCTL_NAMES;
1230struct ctlname tcpname[] = TCPCTL_NAMES;
1231struct ctlname udpname[] = UDPCTL_NAMES;
1232struct ctlname espname[] = ESPCTL_NAMES;
1233struct ctlname ahname[] = AHCTL_NAMES;
1234struct ctlname etheripname[] = ETHERIPCTL_NAMES;
1235struct ctlname grename[] = GRECTL_NAMES;
1236struct ctlname mobileipname[] = MOBILEIPCTL_NAMES;
1237struct ctlname ipcompname[] = IPCOMPCTL_NAMES;
1238struct list inetlist = { inetname, IPPROTO_MAXID };
1239struct list inetvars[] = {
1240	{ ipname, IPCTL_MAXID },	/* ip */
1241	{ icmpname, ICMPCTL_MAXID },	/* icmp */
1242	{ 0, 0 },			/* igmp */
1243	{ 0, 0 },			/* ggmp */
1244	{ ipipname, IPIPCTL_MAXID },	/* ipencap */
1245	{ 0, 0 },
1246	{ tcpname, TCPCTL_MAXID },	/* tcp */
1247	{ 0, 0 },
1248	{ 0, 0 },			/* egp */
1249	{ 0, 0 },
1250	{ 0, 0 },
1251	{ 0, 0 },
1252	{ 0, 0 },			/* pup */
1253	{ 0, 0 },
1254	{ 0, 0 },
1255	{ 0, 0 },
1256	{ 0, 0 },
1257	{ udpname, UDPCTL_MAXID },	/* udp */
1258	{ 0, 0 },
1259	{ 0, 0 },
1260	{ 0, 0 },
1261	{ 0, 0 },
1262	{ 0, 0 },
1263	{ 0, 0 },
1264	{ 0, 0 },
1265	{ 0, 0 },
1266	{ 0, 0 },
1267	{ 0, 0 },
1268	{ 0, 0 },
1269	{ 0, 0 },
1270	{ 0, 0 },
1271	{ 0, 0 },
1272	{ 0, 0 },
1273	{ 0, 0 },
1274	{ 0, 0 },
1275	{ 0, 0 },
1276	{ 0, 0 },
1277	{ 0, 0 },
1278	{ 0, 0 },
1279	{ 0, 0 },
1280	{ 0, 0 },
1281	{ 0, 0 },
1282	{ 0, 0 },
1283	{ 0, 0 },
1284	{ 0, 0 },
1285	{ 0, 0 },
1286	{ 0, 0 },
1287	{ grename, GRECTL_MAXID }, /* GRE */
1288	{ 0, 0 },
1289	{ 0, 0 },
1290	{ espname, ESPCTL_MAXID },	/* esp */
1291	{ ahname, AHCTL_MAXID },	/* ah */
1292	{ 0, 0 },
1293	{ 0, 0 },
1294	{ 0, 0 },
1295	{ mobileipname, MOBILEIPCTL_MAXID }, /* mobileip */
1296	{ 0, 0 },
1297	{ 0, 0 },
1298	{ 0, 0 },
1299	{ 0, 0 },
1300	{ 0, 0 },
1301	{ 0, 0 },
1302	{ 0, 0 },
1303	{ 0, 0 },
1304	{ 0, 0 },
1305	{ 0, 0 },
1306	{ 0, 0 },
1307	{ 0, 0 },
1308	{ 0, 0 },
1309	{ 0, 0 },
1310	{ 0, 0 },
1311	{ 0, 0 },
1312	{ 0, 0 },
1313	{ 0, 0 },
1314	{ 0, 0 },
1315	{ 0, 0 },
1316	{ 0, 0 },
1317	{ 0, 0 },
1318	{ 0, 0 },
1319	{ 0, 0 },
1320	{ 0, 0 },
1321	{ 0, 0 },
1322	{ 0, 0 },
1323	{ 0, 0 },
1324	{ 0, 0 },
1325	{ 0, 0 },
1326	{ 0, 0 },
1327	{ 0, 0 },
1328	{ 0, 0 },
1329	{ 0, 0 },
1330	{ 0, 0 },
1331	{ 0, 0 },
1332	{ 0, 0 },
1333	{ 0, 0 },
1334	{ 0, 0 },
1335	{ 0, 0 },
1336	{ 0, 0 },
1337	{ etheripname, ETHERIPCTL_MAXID },
1338	{ 0, 0 },
1339	{ 0, 0 },
1340	{ 0, 0 },
1341	{ 0, 0 },
1342	{ 0, 0 },
1343	{ 0, 0 },
1344	{ 0, 0 },
1345	{ 0, 0 },
1346	{ 0, 0 },
1347	{ 0, 0 },
1348	{ ipcompname, IPCOMPCTL_MAXID },
1349};
1350
1351struct list kernmalloclist = { kernmallocname, KERN_MALLOC_MAXID };
1352struct list forkstatlist = { forkstatname, KERN_FORKSTAT_MAXID };
1353struct list nchstatslist = { nchstatsname, KERN_NCHSTATS_MAXID };
1354struct list ttylist = { ttyname, KERN_TTY_MAXID };
1355
1356/*
1357 * handle vfs namei cache statistics
1358 */
1359int
1360sysctl_nchstats(string, bufpp, mib, flags, typep)
1361	char *string;
1362	char **bufpp;
1363	int mib[];
1364	int flags;
1365	int *typep;
1366{
1367	static struct nchstats nch;
1368	int indx;
1369	size_t size;
1370	static int keepvalue = 0;
1371
1372	if (*bufpp == NULL) {
1373		bzero(&nch, sizeof(struct nchstats));
1374		listall(string, &nchstatslist);
1375		return(-1);
1376	}
1377	if ((indx = findname(string, "third", bufpp, &nchstatslist)) == -1)
1378		return(-1);
1379	mib[2] = indx;
1380	if (*bufpp != NULL) {
1381		warnx("fourth level name in %s is invalid", string);
1382		return(-1);
1383	}
1384	if (keepvalue == 0) {
1385		size = sizeof(struct nchstats);
1386		if (sysctl(mib, 2, &nch, &size, NULL, 0) < 0)
1387			return(-1);
1388		keepvalue = 1;
1389	}
1390	if (!nflag)
1391		(void)printf("%s = ", string);
1392	switch (indx) {
1393	case KERN_NCHSTATS_GOODHITS:
1394		(void)printf("%ld\n", nch.ncs_goodhits);
1395		break;
1396	case KERN_NCHSTATS_NEGHITS:
1397		(void)printf("%ld\n", nch.ncs_neghits);
1398		break;
1399	case KERN_NCHSTATS_BADHITS:
1400		(void)printf("%ld\n", nch.ncs_badhits);
1401		break;
1402	case KERN_NCHSTATS_FALSEHITS:
1403		(void)printf("%ld\n", nch.ncs_falsehits);
1404		break;
1405	case KERN_NCHSTATS_MISS:
1406		(void)printf("%ld\n", nch.ncs_miss);
1407		break;
1408	case KERN_NCHSTATS_LONG:
1409		(void)printf("%ld\n", nch.ncs_long);
1410		break;
1411	case KERN_NCHSTATS_PASS2:
1412		(void)printf("%ld\n", nch.ncs_pass2);
1413		break;
1414	case KERN_NCHSTATS_2PASSES:
1415		(void)printf("%ld\n", nch.ncs_2passes);
1416		break;
1417	}
1418	return(-1);
1419}
1420
1421/*
1422 * handle tty statistics
1423 */
1424int
1425sysctl_tty(string, bufpp, mib, flags, typep)
1426	char *string;
1427	char **bufpp;
1428	int mib[];
1429	int flags;
1430	int *typep;
1431{
1432	int indx;
1433
1434	if (*bufpp == NULL) {
1435		listall(string, &ttylist);
1436		return(-1);
1437	}
1438	if ((indx = findname(string, "third", bufpp, &ttylist)) == -1)
1439		return(-1);
1440	mib[2] = indx;
1441	*typep = CTLTYPE_QUAD;
1442	return(3);
1443}
1444
1445/*
1446 * handle fork statistics
1447 */
1448int
1449sysctl_forkstat(string, bufpp, mib, flags, typep)
1450	char *string;
1451	char **bufpp;
1452	int mib[];
1453	int flags;
1454	int *typep;
1455{
1456	static struct forkstat fks;
1457	static int keepvalue = 0;
1458	int indx;
1459	size_t size;
1460
1461	if (*bufpp == NULL) {
1462		bzero(&fks, sizeof(struct forkstat));
1463		listall(string, &forkstatlist);
1464		return(-1);
1465	}
1466	if ((indx = findname(string, "third", bufpp, &forkstatlist)) == -1)
1467		return(-1);
1468	if (*bufpp != NULL) {
1469		warnx("fourth level name in %s is invalid", string);
1470		return(-1);
1471	}
1472	if (keepvalue == 0) {
1473		size = sizeof(struct forkstat);
1474		if (sysctl(mib, 2, &fks, &size, NULL, 0) < 0)
1475			return(-1);
1476		keepvalue = 1;
1477	}
1478	if (!nflag)
1479		(void)printf("%s = ", string);
1480	switch (indx)	{
1481	case KERN_FORKSTAT_FORK:
1482		(void)printf("%d\n", fks.cntfork);
1483		break;
1484	case KERN_FORKSTAT_VFORK:
1485		(void)printf("%d\n", fks.cntvfork);
1486		break;
1487	case KERN_FORKSTAT_RFORK:
1488		(void)printf("%d\n", fks.cntrfork);
1489		break;
1490	case KERN_FORKSTAT_KTHREAD:
1491		(void)printf("%d\n", fks.cntkthread);
1492		break;
1493	case KERN_FORKSTAT_SIZFORK:
1494		(void)printf("%d\n", fks.sizfork);
1495		break;
1496	case KERN_FORKSTAT_SIZVFORK:
1497		(void)printf("%d\n", fks.sizvfork);
1498		break;
1499	case KERN_FORKSTAT_SIZRFORK:
1500		(void)printf("%d\n", fks.sizrfork);
1501		break;
1502	case KERN_FORKSTAT_SIZKTHREAD:
1503		(void)printf("%d\n", fks.sizkthread);
1504		break;
1505	}
1506	return(-1);
1507}
1508
1509/*
1510 * handle malloc statistics
1511 */
1512int
1513sysctl_malloc(string, bufpp, mib, flags, typep)
1514	char *string;
1515	char **bufpp;
1516	int mib[];
1517	int flags;
1518	int *typep;
1519{
1520	int indx, stor, i;
1521	char *name, bufp[BUFSIZ], *buf, *ptr;
1522	struct list lp;
1523	size_t size;
1524
1525	if (*bufpp == NULL) {
1526		listall(string, &kernmalloclist);
1527		return(-1);
1528	}
1529	if ((indx = findname(string, "third", bufpp, &kernmalloclist)) == -1)
1530		return(-1);
1531	mib[2] = indx;
1532	if (mib[2] == KERN_MALLOC_BUCKET) {
1533		if ((name = strsep(bufpp, ".")) == NULL) {
1534			size = BUFSIZ;
1535			stor = mib[2];
1536			mib[2] = KERN_MALLOC_BUCKETS;
1537			buf = bufp;
1538			if (sysctl(mib, 3, buf, &size, NULL, 0) < 0)
1539				return(-1);
1540			mib[2] = stor;
1541			for (stor = 0, i = 0; i < size; i++)
1542				if (buf[i] == ',')
1543					stor++;
1544			lp.list = calloc(stor + 2, sizeof(struct ctlname));
1545			if (lp.list == NULL)
1546				return(-1);
1547			lp.size = stor + 2;
1548			for (i = 1;
1549			    (lp.list[i].ctl_name = strsep(&buf, ",")) != NULL;
1550			    i++) {
1551				lp.list[i].ctl_type = CTLTYPE_STRUCT;
1552			}
1553			lp.list[i].ctl_name = buf;
1554			lp.list[i].ctl_type = CTLTYPE_STRUCT;
1555			listall(string, &lp);
1556			free(lp.list);
1557			return(-1);
1558		}
1559		mib[3] = atoi(name);
1560		return(4);
1561	} else if (mib[2] == KERN_MALLOC_BUCKETS) {
1562		*typep = CTLTYPE_STRING;
1563		return(3);
1564	} else if (mib[2] == KERN_MALLOC_KMEMSTATS) {
1565		size = BUFSIZ;
1566		stor = mib[2];
1567		mib[2] = KERN_MALLOC_KMEMNAMES;
1568		buf = bufp;
1569		if (sysctl(mib, 3, buf, &size, NULL, 0) < 0)
1570			return(-1);
1571		mib[2] = stor;
1572		if ((name = strsep(bufpp, ".")) == NULL) {
1573			for (stor = 0, i = 0; i < size; i++)
1574				if (buf[i] == ',')
1575					stor++;
1576			lp.list = calloc(stor + 2, sizeof(struct ctlname));
1577			if (lp.list == NULL)
1578				return(-1);
1579			lp.size = stor + 2;
1580			for (i = 1; (lp.list[i].ctl_name = strsep(&buf, ",")) != NULL; i++) {
1581				if (lp.list[i].ctl_name[0] == '\0') {
1582					i--;
1583					continue;
1584				}
1585				lp.list[i].ctl_type = CTLTYPE_STRUCT;
1586			}
1587			lp.list[i].ctl_name = buf;
1588			lp.list[i].ctl_type = CTLTYPE_STRUCT;
1589			listall(string, &lp);
1590			free(lp.list);
1591			return(-1);
1592		}
1593		ptr = strstr(buf, name);
1594 tryagain:
1595		if (ptr == NULL) {
1596		       warnx("fourth level name %s in %s is invalid", name,
1597			     string);
1598		       return(-1);
1599		}
1600		if ((*(ptr + strlen(name)) != ',') &&
1601		    (*(ptr + strlen(name)) != '\0')) {
1602			ptr = strstr(ptr + 1, name); /* retry */
1603			goto tryagain;
1604		}
1605		if ((ptr != buf) && (*(ptr - 1) != ',')) {
1606			ptr = strstr(ptr + 1, name); /* retry */
1607			goto tryagain;
1608		}
1609		for (i = 0, stor = 0; buf + i < ptr; i++)
1610			if (buf[i] == ',')
1611				stor++;
1612		mib[3] = stor;
1613		return(4);
1614	} else if (mib[2] == KERN_MALLOC_KMEMNAMES) {
1615		*typep = CTLTYPE_STRING;
1616		return(3);
1617	}
1618	return(-1);
1619}
1620
1621#ifdef CPU_CHIPSET
1622/*
1623 * handle machdep.chipset requests
1624 */
1625struct ctlname chipsetname[] = CTL_CHIPSET_NAMES;
1626struct list chipsetlist = { chipsetname, CPU_CHIPSET_MAXID };
1627
1628int
1629sysctl_chipset(string, bufpp, mib, flags, typep)
1630	char *string;
1631	char **bufpp;
1632	int mib[];
1633	int flags;
1634	int *typep;
1635{
1636	int indx, bwx;
1637	static void *q;
1638	size_t len;
1639	char *p;
1640
1641	if (*bufpp == NULL) {
1642		listall(string, &chipsetlist);
1643		return (-1);
1644	}
1645	if ((indx = findname(string, "third", bufpp, &chipsetlist)) == -1)
1646		return(-1);
1647	mib[2] = indx;
1648	if (!nflag)
1649		printf("%s = ", string);
1650	switch(mib[2]) {
1651	case CPU_CHIPSET_MEM:
1652	case CPU_CHIPSET_DENSE:
1653	case CPU_CHIPSET_PORTS:
1654	case CPU_CHIPSET_HAE_MASK:
1655		len = sizeof(void *);
1656		if (sysctl(mib, 3, &q, &len, NULL, 0) < 0)
1657			return (-1);
1658		printf("%p\n", q);
1659		break;
1660	case CPU_CHIPSET_BWX:
1661		len = sizeof(int);
1662		if (sysctl(mib, 3, &bwx, &len, NULL, 0) < 0)
1663			return (-1);
1664		printf("%d\n", bwx);
1665		break;
1666	case CPU_CHIPSET_TYPE:
1667		if (sysctl(mib, 3, NULL, &len, NULL, 0) < 0)
1668			return (-1);
1669		p = malloc(len + 1);
1670		if (p == NULL)
1671			return (-1);
1672		if (sysctl(mib, 3, p, &len, NULL, 0) < 0)
1673			return (-1);
1674		p[len] = '\0';
1675		printf("%s\n", p);
1676		break;
1677	}
1678	return (-1);
1679}
1680#endif
1681/*
1682 * handle internet requests
1683 */
1684int
1685sysctl_inet(string, bufpp, mib, flags, typep)
1686	char *string;
1687	char **bufpp;
1688	int mib[];
1689	int flags;
1690	int *typep;
1691{
1692	struct list *lp;
1693	int indx;
1694
1695	if (*bufpp == NULL) {
1696		listall(string, &inetlist);
1697		return(-1);
1698	}
1699	if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
1700		return(-1);
1701	mib[2] = indx;
1702	if (indx < IPPROTO_MAXID && inetvars[indx].list != NULL)
1703		lp = &inetvars[indx];
1704	else if (!flags)
1705		return(-1);
1706	else {
1707		warnx("%s: no variables defined for this protocol", string);
1708		return(-1);
1709	}
1710	if (*bufpp == NULL) {
1711		listall(string, lp);
1712		return(-1);
1713	}
1714	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1715		return(-1);
1716	mib[3] = indx;
1717	*typep = lp->list[indx].ctl_type;
1718	return(4);
1719}
1720
1721#ifdef INET6
1722struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES;
1723struct ctlname ip6name[] = IPV6CTL_NAMES;
1724struct ctlname icmp6name[] = ICMPV6CTL_NAMES;
1725struct ctlname pim6name[] = PIM6CTL_NAMES;
1726struct list inet6list = { inet6name, IPV6PROTO_MAXID };
1727struct list inet6vars[] = {
1728/*0*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1729	{ 0, 0 },
1730	{ 0, 0 },
1731	{ 0, 0 },
1732	{ 0, 0 },
1733	{ 0, 0 },
1734/*10*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1735	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1736/*20*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1737	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1738/*30*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1739	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1740/*40*/	{ 0, 0 },
1741	{ ip6name, IPV6CTL_MAXID },	/* ipv6 */
1742	{ 0, 0 },
1743	{ 0, 0 },
1744	{ 0, 0 },
1745	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1746/*50*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1747	{ 0, 0 },
1748	{ 0, 0 },
1749	{ 0, 0 },
1750	{ icmp6name, ICMPV6CTL_MAXID },	/* icmp6 */
1751	{ 0, 0 },
1752/*60*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1753	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1754/*70*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1755	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1756/*80*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1757	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1758/*90*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1759	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1760/*100*/	{ 0, 0 },
1761	{ 0, 0 },
1762	{ 0, 0 },
1763	{ pim6name, PIM6CTL_MAXID },	/* pim6 */
1764};
1765
1766/*
1767 * handle internet6 requests
1768 */
1769int
1770sysctl_inet6(string, bufpp, mib, flags, typep)
1771	char *string;
1772	char **bufpp;
1773	int mib[];
1774	int flags;
1775	int *typep;
1776{
1777	struct list *lp;
1778	int indx;
1779
1780	if (*bufpp == NULL) {
1781		listall(string, &inet6list);
1782		return(-1);
1783	}
1784	if ((indx = findname(string, "third", bufpp, &inet6list)) == -1)
1785		return(-1);
1786	mib[2] = indx;
1787	if (indx < IPV6PROTO_MAXID && inet6vars[indx].list != NULL)
1788		lp = &inet6vars[indx];
1789	else if (!flags)
1790		return(-1);
1791	else {
1792		warnx("%s: no variables defined for this protocol", string);
1793		return(-1);
1794	}
1795	if (*bufpp == NULL) {
1796		listall(string, lp);
1797		return(-1);
1798	}
1799	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1800		return(-1);
1801	mib[3] = indx;
1802	*typep = lp->list[indx].ctl_type;
1803	return(4);
1804}
1805#endif
1806
1807struct ctlname ipxname[] = CTL_IPXPROTO_NAMES;
1808struct ctlname ipxpname[] = IPXCTL_NAMES;
1809struct ctlname spxpname[] = SPXCTL_NAMES;
1810struct list ipxlist = { ipxname, IPXCTL_MAXID };
1811struct list ipxvars[] = {
1812	{ ipxpname, IPXCTL_MAXID },	/* ipx */
1813	{ 0, 0 },
1814	{ 0, 0 },
1815	{ 0, 0 },
1816	{ 0, 0 },
1817	{ spxpname, SPXCTL_MAXID },
1818};
1819
1820/*
1821 * Handle internet requests
1822 */
1823int
1824sysctl_ipx(string, bufpp, mib, flags, typep)
1825	char *string;
1826	char **bufpp;
1827	int mib[];
1828	int flags;
1829	int *typep;
1830{
1831	struct list *lp;
1832	int indx;
1833
1834	if (*bufpp == NULL) {
1835		listall(string, &ipxlist);
1836		return(-1);
1837	}
1838	if ((indx = findname(string, "third", bufpp, &ipxlist)) == -1)
1839		return(-1);
1840	mib[2] = indx;
1841	if (indx <= IPXPROTO_SPX && ipxvars[indx].list != NULL)
1842		lp = &ipxvars[indx];
1843	else if (!flags)
1844		return(-1);
1845	else {
1846		warnx("%s: no variables defined for this protocol", string);
1847		return(-1);
1848	}
1849	if (*bufpp == NULL) {
1850		listall(string, lp);
1851		return(-1);
1852	}
1853	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1854		return(-1);
1855	mib[3] = indx;
1856	*typep = lp->list[indx].ctl_type;
1857	return(4);
1858}
1859
1860/*
1861 * Scan a list of names searching for a particular name.
1862 */
1863int
1864findname(string, level, bufp, namelist)
1865	char *string;
1866	char *level;
1867	char **bufp;
1868	struct list *namelist;
1869{
1870	char *name;
1871	int i;
1872
1873	if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
1874		warnx("%s: incomplete specification", string);
1875		return(-1);
1876	}
1877	for (i = 0; i < namelist->size; i++)
1878		if (namelist->list[i].ctl_name != NULL &&
1879		    strcmp(name, namelist->list[i].ctl_name) == 0)
1880			break;
1881	if (i == namelist->size) {
1882		warnx("%s level name %s in %s is invalid", level, name, string);
1883		return(-1);
1884	}
1885	return(i);
1886}
1887
1888void
1889usage()
1890{
1891
1892	(void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n",
1893	    "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...",
1894	    "sysctl [-n] -a", "sysctl [-n] -A");
1895	exit(1);
1896}
1897