sysctl.c revision 1.199
1/*	$OpenBSD: sysctl.c,v 1.199 2014/01/23 03:00:04 guenther Exp $	*/
2/*	$NetBSD: sysctl.c,v 1.9 1995/09/30 07:12:50 thorpej Exp $	*/
3
4/*
5 * Copyright (c) 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/param.h>
34#include <sys/gmon.h>
35#include <sys/mount.h>
36#include <sys/sem.h>
37#include <sys/shm.h>
38#include <sys/sysctl.h>
39#include <sys/socket.h>
40#include <sys/malloc.h>
41#include <sys/dkstat.h>
42#include <sys/uio.h>
43#include <sys/tty.h>
44#include <sys/namei.h>
45#include <sys/sensors.h>
46#include <net/route.h>
47#include <net/if.h>
48
49#include <netinet/in.h>
50#include <netinet/in_systm.h>
51#include <netinet/ip.h>
52#include <netinet/in_pcb.h>
53#include <netinet/ip_icmp.h>
54#include <netinet/ip_ipip.h>
55#include <netinet/ip_ether.h>
56#include <netinet/ip_ah.h>
57#include <netinet/ip_esp.h>
58#include <netinet/icmp_var.h>
59#include <netinet/igmp_var.h>
60#include <netinet/ip_var.h>
61#include <netinet/udp.h>
62#include <netinet/udp_var.h>
63#include <netinet/tcp.h>
64#include <netinet/tcp_timer.h>
65#include <netinet/tcp_var.h>
66#include <netinet/ip_gre.h>
67#include <netinet/ip_ipcomp.h>
68#include <netinet/ip_carp.h>
69#include <netinet/ip_divert.h>
70
71#include <net/pfvar.h>
72#include <net/if_pfsync.h>
73#include <net/pipex.h>
74
75#ifdef INET6
76#include <netinet/ip6.h>
77#include <netinet/icmp6.h>
78#include <netinet6/ip6_var.h>
79#include <netinet6/pim6_var.h>
80#include <netinet6/ip6_divert.h>
81#endif
82
83#include <netmpls/mpls.h>
84
85#include <uvm/uvm_swap_encrypt.h>
86
87#include <ufs/ufs/quota.h>
88#include <ufs/ufs/inode.h>
89#include <ufs/ffs/ffs_extern.h>
90
91#include <miscfs/fuse/fusefs.h>
92
93#include <nfs/nfsproto.h>
94#include <nfs/nfs.h>
95
96#include <ddb/db_var.h>
97#include <dev/rndvar.h>
98
99#include <err.h>
100#include <errno.h>
101#include <stdio.h>
102#include <stdlib.h>
103#include <string.h>
104#include <ctype.h>
105#include <unistd.h>
106
107#include <machine/cpu.h>
108
109#ifdef CPU_BIOS
110#include <machine/biosvar.h>
111#endif
112
113struct ctlname topname[] = CTL_NAMES;
114struct ctlname kernname[] = CTL_KERN_NAMES;
115struct ctlname vmname[] = CTL_VM_NAMES;
116struct ctlname fsname[] = CTL_FS_NAMES;
117struct ctlname netname[] = CTL_NET_NAMES;
118struct ctlname hwname[] = CTL_HW_NAMES;
119struct ctlname debugname[CTL_DEBUG_MAXID];
120struct ctlname kernmallocname[] = CTL_KERN_MALLOC_NAMES;
121struct ctlname forkstatname[] = CTL_KERN_FORKSTAT_NAMES;
122struct ctlname nchstatsname[] = CTL_KERN_NCHSTATS_NAMES;
123struct ctlname ttysname[] = CTL_KERN_TTY_NAMES;
124struct ctlname semname[] = CTL_KERN_SEMINFO_NAMES;
125struct ctlname shmname[] = CTL_KERN_SHMINFO_NAMES;
126struct ctlname watchdogname[] = CTL_KERN_WATCHDOG_NAMES;
127struct ctlname tcname[] = CTL_KERN_TIMECOUNTER_NAMES;
128struct ctlname *vfsname;
129#ifdef CTL_MACHDEP_NAMES
130struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
131#endif
132struct ctlname ddbname[] = CTL_DDB_NAMES;
133char names[BUFSIZ];
134int lastused;
135
136/* Maximum size object to expect from sysctl(3) */
137#define SYSCTL_BUFSIZ	8192
138
139struct list {
140	struct	ctlname *list;
141	int	size;
142};
143struct list toplist = { topname, CTL_MAXID };
144struct list secondlevel[] = {
145	{ 0, 0 },			/* CTL_UNSPEC */
146	{ kernname, KERN_MAXID },	/* CTL_KERN */
147	{ vmname, VM_MAXID },		/* CTL_VM */
148	{ fsname, FS_MAXID },		/* CTL_FS */
149	{ netname, NET_MAXID },		/* CTL_NET */
150	{ 0, CTL_DEBUG_MAXID },		/* CTL_DEBUG */
151	{ hwname, HW_MAXID },		/* CTL_HW */
152#ifdef CTL_MACHDEP_NAMES
153	{ machdepname, CPU_MAXID },	/* CTL_MACHDEP */
154#else
155	{ 0, 0 },			/* CTL_MACHDEP */
156#endif
157	{ 0, 0 },			/* was CTL_USER */
158	{ ddbname, DBCTL_MAXID },	/* CTL_DDB_NAMES */
159	{ 0, 0 },			/* CTL_VFS */
160};
161
162int	Aflag, aflag, nflag, qflag;
163
164/*
165 * Variables requiring special processing.
166 */
167#define	CLOCK		0x00000001
168#define	BOOTTIME	0x00000002
169#define	CHRDEV		0x00000004
170#define	BLKDEV		0x00000008
171#define	RNDSTATS	0x00000010
172#define	BADDYNAMIC	0x00000020
173#define	BIOSGEO		0x00000040
174#define	BIOSDEV		0x00000080
175#define	MAJ2DEV		0x00000100
176#define	UNSIGNED	0x00000200
177#define	KMEMBUCKETS	0x00000400
178#define	LONGARRAY	0x00000800
179#define	KMEMSTATS	0x00001000
180#define	SENSORS		0x00002000
181
182/* prototypes */
183void debuginit(void);
184void listall(char *, struct list *);
185void parse(char *, int);
186void parse_baddynamic(int *, size_t, char *, void **, size_t *, int, int);
187void usage(void);
188int findname(char *, char *, char **, struct list *);
189int sysctl_inet(char *, char **, int *, int, int *);
190#ifdef INET6
191int sysctl_inet6(char *, char **, int *, int, int *);
192#endif
193int sysctl_bpf(char *, char **, int *, int, int *);
194int sysctl_mpls(char *, char **, int *, int, int *);
195int sysctl_pipex(char *, char **, int *, int, int *);
196int sysctl_fs(char *, char **, int *, int, int *);
197static int sysctl_vfs(char *, char **, int[], int, int *);
198static int sysctl_vfsgen(char *, char **, int[], int, int *);
199int sysctl_bios(char *, char **, int *, int, int *);
200int sysctl_swpenc(char *, char **, int *, int, int *);
201int sysctl_forkstat(char *, char **, int *, int, int *);
202int sysctl_tty(char *, char **, int *, int, int *);
203int sysctl_nchstats(char *, char **, int *, int, int *);
204int sysctl_malloc(char *, char **, int *, int, int *);
205int sysctl_seminfo(char *, char **, int *, int, int *);
206int sysctl_shminfo(char *, char **, int *, int, int *);
207int sysctl_watchdog(char *, char **, int *, int, int *);
208int sysctl_tc(char *, char **, int *, int, int *);
209int sysctl_sensors(char *, char **, int *, int, int *);
210void print_sensordev(char *, int *, u_int, struct sensordev *);
211void print_sensor(struct sensor *);
212int sysctl_emul(char *, char *, int);
213#ifdef CPU_CHIPSET
214int sysctl_chipset(char *, char **, int *, int, int *);
215#endif
216void vfsinit(void);
217
218char *equ = "=";
219
220int
221main(int argc, char *argv[])
222{
223	int ch, lvl1;
224
225	while ((ch = getopt(argc, argv, "Aanqw")) != -1) {
226		switch (ch) {
227
228		case 'A':
229			Aflag = 1;
230			break;
231
232		case 'a':
233			aflag = 1;
234			break;
235
236		case 'n':
237			nflag = 1;
238			break;
239
240		case 'q':
241			qflag = 1;
242			break;
243
244		case 'w':
245			/* flag no longer needed; var=value implies write */
246			break;
247
248		default:
249			usage();
250		}
251	}
252	argc -= optind;
253	argv += optind;
254
255	if (argc == 0 || (Aflag || aflag)) {
256		debuginit();
257		vfsinit();
258		for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
259			listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
260		return (0);
261	}
262	for (; *argv != NULL; ++argv)
263		parse(*argv, 1);
264	return (0);
265}
266
267/*
268 * List all variables known to the system.
269 */
270void
271listall(char *prefix, struct list *lp)
272{
273	char *cp, name[BUFSIZ];
274	int lvl2, len;
275
276	if (lp->list == NULL)
277		return;
278	if ((len = strlcpy(name, prefix, sizeof(name))) >= sizeof(name))
279		errx(1, "%s: name too long", prefix);
280	cp = name + len++;
281	*cp++ = '.';
282	for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
283		if (lp->list[lvl2].ctl_name == NULL)
284			continue;
285		if (strlcpy(cp, lp->list[lvl2].ctl_name,
286		    sizeof(name) - len) >= sizeof(name) - len)
287			warn("%s: name too long", lp->list[lvl2].ctl_name);
288		parse(name, Aflag);
289	}
290}
291
292/*
293 * Parse a name into a MIB entry.
294 * Lookup and print out the MIB entry if it exists.
295 * Set a new value if requested.
296 */
297void
298parse(char *string, int flags)
299{
300	int indx, type, state, intval, len;
301	size_t size, newsize = 0;
302	int lal = 0, special = 0;
303	void *newval = NULL;
304	int64_t quadval;
305	struct list *lp;
306	int mib[CTL_MAXNAME];
307	char *cp, *bufp, buf[SYSCTL_BUFSIZ];
308
309	(void)strlcpy(buf, string, sizeof(buf));
310	bufp = buf;
311	if ((cp = strchr(string, '=')) != NULL) {
312		*strchr(buf, '=') = '\0';
313		*cp++ = '\0';
314		while (isspace((unsigned char)*cp))
315			cp++;
316		newval = cp;
317		newsize = strlen(cp);
318	}
319	if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
320		return;
321	mib[0] = indx;
322	if (indx == CTL_VFS)
323		vfsinit();
324	if (indx == CTL_DEBUG)
325		debuginit();
326	lp = &secondlevel[indx];
327	if (lp->list == 0) {
328		warnx("%s: class is not implemented", topname[indx].ctl_name);
329		return;
330	}
331	if (bufp == NULL) {
332		listall(topname[indx].ctl_name, lp);
333		return;
334	}
335	if ((indx = findname(string, "second", &bufp, lp)) == -1)
336		return;
337	mib[1] = indx;
338	type = lp->list[indx].ctl_type;
339	len = 2;
340	switch (mib[0]) {
341
342	case CTL_KERN:
343		switch (mib[1]) {
344		case KERN_PROF:
345			mib[2] = GPROF_STATE;
346			size = sizeof(state);
347			if (sysctl(mib, 3, &state, &size, NULL, 0) == -1) {
348				if (flags == 0)
349					return;
350				if (!nflag)
351					(void)printf("%s: ", string);
352				(void)puts("kernel is not compiled for profiling");
353				return;
354			}
355			if (!nflag)
356				(void)printf("%s = %s\n", string,
357				    state == GMON_PROF_OFF ? "off" : "running");
358			return;
359		case KERN_FORKSTAT:
360			sysctl_forkstat(string, &bufp, mib, flags, &type);
361			return;
362		case KERN_TTY:
363			len = sysctl_tty(string, &bufp, mib, flags, &type);
364			if (len < 0)
365				return;
366			break;
367		case KERN_NCHSTATS:
368			sysctl_nchstats(string, &bufp, mib, flags, &type);
369			return;
370		case KERN_MALLOCSTATS:
371			len = sysctl_malloc(string, &bufp, mib, flags, &type);
372			if (len < 0)
373				return;
374			if (mib[2] == KERN_MALLOC_BUCKET)
375				special |= KMEMBUCKETS;
376			if (mib[2] == KERN_MALLOC_KMEMSTATS)
377				special |= KMEMSTATS;
378			newsize = 0;
379			break;
380		case KERN_MBSTAT:
381			if (flags == 0)
382				return;
383			warnx("use netstat to view %s", string);
384			return;
385		case KERN_MSGBUF:
386			if (flags == 0)
387				return;
388			warnx("use dmesg to view %s", string);
389			return;
390		case KERN_VNODE:
391			if (flags == 0)
392				return;
393			warnx("use pstat to view %s information", string);
394			return;
395		case KERN_PROC:
396			if (flags == 0)
397				return;
398			warnx("use ps to view %s information", string);
399			return;
400		case KERN_CLOCKRATE:
401			special |= CLOCK;
402			break;
403		case KERN_BOOTTIME:
404			special |= BOOTTIME;
405			break;
406		case KERN_RND:
407			special |= RNDSTATS;
408			break;
409		case KERN_HOSTID:
410		case KERN_ARND:
411			special |= UNSIGNED;
412			break;
413		case KERN_CPTIME:
414			special |= LONGARRAY;
415			lal = CPUSTATES;
416			break;
417		case KERN_SEMINFO:
418			len = sysctl_seminfo(string, &bufp, mib, flags, &type);
419			if (len < 0)
420				return;
421			break;
422		case KERN_SHMINFO:
423			len = sysctl_shminfo(string, &bufp, mib, flags, &type);
424			if (len < 0)
425				return;
426			break;
427		case KERN_INTRCNT:
428			if (flags == 0)
429				return;
430			warnx("use vmstat or systat to view %s information",
431			    string);
432			return;
433		case KERN_WATCHDOG:
434			len = sysctl_watchdog(string, &bufp, mib, flags,
435			    &type);
436			if (len < 0)
437				return;
438			break;
439		case KERN_TIMECOUNTER:
440			len = sysctl_tc(string, &bufp, mib, flags,
441			    &type);
442			if (len < 0)
443				return;
444			break;
445		case KERN_EMUL:
446			sysctl_emul(string, newval, flags);
447			return;
448		case KERN_FILE:
449			if (flags == 0)
450				return;
451			warnx("use fstat to view %s information", string);
452			return;
453		case KERN_CONSDEV:
454			special |= CHRDEV;
455			break;
456		case KERN_NETLIVELOCKS:
457			special |= UNSIGNED;
458			break;
459		}
460		break;
461
462	case CTL_HW:
463		switch (mib[1]) {
464		case HW_DISKSTATS:
465			/*
466			 * Only complain if someone asks explicitly for this,
467			 * otherwise "fail" silently.
468			 */
469			if (flags)
470				warnx("use vmstat to view %s information",
471				    string);
472			return;
473		case HW_SENSORS:
474			special |= SENSORS;
475			len = sysctl_sensors(string, &bufp, mib, flags, &type);
476			if (len < 0)
477				return;
478			break;
479		case HW_PHYSMEM:
480		case HW_USERMEM:
481			/*
482			 * Don't print these; we'll print the 64-bit
483			 * variants instead.
484			 */
485			return;
486		}
487		break;
488
489	case CTL_VM:
490		if (mib[1] == VM_LOADAVG) {
491			double loads[3];
492
493			getloadavg(loads, 3);
494			if (!nflag)
495				(void)printf("%s%s", string, equ);
496			(void)printf("%.2f %.2f %.2f\n", loads[0],
497			    loads[1], loads[2]);
498			return;
499		} else if (mib[1] == VM_PSSTRINGS) {
500			struct _ps_strings _ps;
501
502			size = sizeof(_ps);
503			if (sysctl(mib, 2, &_ps, &size, NULL, 0) == -1) {
504				if (flags == 0)
505					return;
506				if (!nflag)
507					(void)printf("%s: ", string);
508				(void)puts("can't find ps strings");
509				return;
510			}
511			if (!nflag)
512				(void)printf("%s%s", string, equ);
513			(void)printf("%p\n", _ps.val);
514			return;
515		} else if (mib[1] == VM_SWAPENCRYPT) {
516			len = sysctl_swpenc(string, &bufp, mib, flags, &type);
517			if (len < 0)
518				return;
519
520			break;
521		} else if (mib[1] == VM_NKMEMPAGES ||
522		    mib[1] == VM_ANONMIN ||
523		    mib[1] == VM_VTEXTMIN ||
524		    mib[1] == VM_VNODEMIN) {
525			break;
526		}
527		if (flags == 0)
528			return;
529		warnx("use vmstat or systat to view %s information", string);
530		return;
531
532		break;
533
534	case CTL_NET:
535		if (mib[1] == PF_INET) {
536			len = sysctl_inet(string, &bufp, mib, flags, &type);
537			if (len < 0)
538				return;
539
540			if ((mib[2] == IPPROTO_IP && mib[3] == IPCTL_MRTSTATS) ||
541			    (mib[2] == IPPROTO_IP && mib[3] == IPCTL_STATS) ||
542			    (mib[2] == IPPROTO_TCP && mib[3] == TCPCTL_STATS) ||
543			    (mib[2] == IPPROTO_UDP && mib[3] == UDPCTL_STATS) ||
544			    (mib[2] == IPPROTO_ESP && mib[3] == ESPCTL_STATS) ||
545			    (mib[2] == IPPROTO_AH && mib[3] == AHCTL_STATS) ||
546			    (mib[2] == IPPROTO_IGMP && mib[3] == IGMPCTL_STATS) ||
547			    (mib[2] == IPPROTO_ETHERIP && mib[3] == ETHERIPCTL_STATS) ||
548			    (mib[2] == IPPROTO_IPIP && mib[3] == IPIPCTL_STATS) ||
549			    (mib[2] == IPPROTO_IPCOMP && mib[3] == IPCOMPCTL_STATS) ||
550			    (mib[2] == IPPROTO_ICMP && mib[3] == ICMPCTL_STATS) ||
551			    (mib[2] == IPPROTO_CARP && mib[3] == CARPCTL_STATS) ||
552			    (mib[2] == IPPROTO_PFSYNC && mib[3] == PFSYNCCTL_STATS) ||
553			    (mib[2] == IPPROTO_DIVERT && mib[3] == DIVERTCTL_STATS)) {
554				if (flags == 0)
555					return;
556				warnx("use netstat to view %s information",
557				    string);
558				return;
559			} else if ((mib[2] == IPPROTO_TCP &&
560			    mib[3] == TCPCTL_BADDYNAMIC) ||
561			    (mib[2] == IPPROTO_UDP &&
562			    mib[3] == UDPCTL_BADDYNAMIC)) {
563
564				special |= BADDYNAMIC;
565
566				if (newval != NULL)
567					parse_baddynamic(mib, len, string,
568					    &newval, &newsize, flags, nflag);
569			}
570			break;
571		}
572#ifdef INET6
573		if (mib[1] == PF_INET6) {
574			len = sysctl_inet6(string, &bufp, mib, flags, &type);
575			if (len < 0)
576				return;
577
578			if ((mib[2] == IPPROTO_PIM && mib[3] == PIM6CTL_STATS) ||
579			    (mib[2] == IPPROTO_DIVERT && mib[3] == DIVERT6CTL_STATS)) {
580				if (flags == 0)
581					return;
582				warnx("use netstat to view %s information",
583				    string);
584				return;
585			}
586			break;
587		}
588#endif
589		if (mib[1] == PF_BPF) {
590			len = sysctl_bpf(string, &bufp, mib, flags, &type);
591			if (len < 0)
592				return;
593			break;
594		}
595		if (mib[1] == PF_MPLS) {
596			len = sysctl_mpls(string, &bufp, mib, flags, &type);
597			if (len < 0)
598				return;
599			break;
600		}
601		if (mib[1] == PF_PIPEX) {
602			len = sysctl_pipex(string, &bufp, mib, flags, &type);
603			if (len < 0)
604				return;
605			break;
606		}
607		if (flags == 0)
608			return;
609		warnx("use netstat to view %s information", string);
610		return;
611
612	case CTL_DEBUG:
613		mib[2] = CTL_DEBUG_VALUE;
614		len = 3;
615		break;
616
617	case CTL_MACHDEP:
618#ifdef CPU_CONSDEV
619		if (mib[1] == CPU_CONSDEV)
620			special |= CHRDEV;
621#endif
622#ifdef CPU_BLK2CHR
623		if (mib[1] == CPU_BLK2CHR) {
624			if (bufp == NULL)
625				return;
626			mib[2] = makedev(atoi(bufp),0);
627			bufp = NULL;
628			len = 3;
629			special |= CHRDEV;
630			break;
631		}
632#endif
633#ifdef CPU_CHR2BLK
634		if (mib[1] == CPU_CHR2BLK) {
635			if (bufp == NULL)
636				return;
637			mib[2] = makedev(atoi(bufp),0);
638			bufp = NULL;
639			len = 3;
640			special |= BLKDEV;
641			break;
642		}
643#endif
644#ifdef CPU_BIOS
645		if (mib[1] == CPU_BIOS) {
646			len = sysctl_bios(string, &bufp, mib, flags, &type);
647			if (len < 0)
648				return;
649			if (mib[2] == BIOS_DEV)
650				special |= BIOSDEV;
651			if (mib[2] == BIOS_DISKINFO)
652				special |= BIOSGEO;
653			break;
654		}
655#endif
656#ifdef CPU_CHIPSET
657		if (mib[1] == CPU_CHIPSET) {
658			len = sysctl_chipset(string, &bufp, mib, flags, &type);
659			if (len < 0)
660				return;
661			break;
662		}
663#endif
664		break;
665
666	case CTL_FS:
667		len = sysctl_fs(string, &bufp, mib, flags, &type);
668		if (len >= 0)
669			break;
670		return;
671
672	case CTL_VFS:
673		if (mib[1])
674			len = sysctl_vfs(string, &bufp, mib, flags, &type);
675		else
676			len = sysctl_vfsgen(string, &bufp, mib, flags, &type);
677		if (len >= 0) {
678			if (type == CTLTYPE_STRUCT) {
679				if (flags)
680					warnx("use nfsstat to view %s information",
681					    MOUNT_NFS);
682				return;
683			} else
684				break;
685		}
686		return;
687
688	case CTL_DDB:
689		break;
690
691	default:
692		warnx("illegal top level value: %d", mib[0]);
693		return;
694
695	}
696	if (bufp) {
697		warnx("name %s in %s is unknown", bufp, string);
698		return;
699	}
700	if (newsize > 0) {
701		switch (type) {
702		case CTLTYPE_INT:
703			errno = 0;
704			if (special & UNSIGNED)
705				intval = strtoul(newval, &cp, 10);
706			else
707				intval = strtol(newval, &cp, 10);
708			if (*cp != '\0') {
709				warnx("%s: illegal value: %s", string,
710				    (char *)newval);
711				return;
712			}
713			if (errno == ERANGE) {
714				warnx("%s: value %s out of range", string,
715				    (char *)newval);
716				return;
717			}
718			newval = &intval;
719			newsize = sizeof(intval);
720			break;
721
722		case CTLTYPE_QUAD:
723			/* XXX - assumes sizeof(long long) == sizeof(quad_t) */
724			(void)sscanf(newval, "%lld", (long long *)&quadval);
725			newval = &quadval;
726			newsize = sizeof(quadval);
727			break;
728		}
729	}
730	size = SYSCTL_BUFSIZ;
731	if (sysctl(mib, len, buf, &size, newval, newsize) == -1) {
732		if (flags == 0)
733			return;
734		switch (errno) {
735		case EOPNOTSUPP:
736			warnx("%s: value is not available", string);
737			return;
738		case ENOTDIR:
739			warnx("%s: specification is incomplete", string);
740			return;
741		case ENOMEM:
742			warnx("%s: type is unknown to this program", string);
743			return;
744		case ENXIO:
745			if (special & BIOSGEO)
746				return;
747		default:
748			warn("%s", string);
749			return;
750		}
751	}
752	if (special & KMEMBUCKETS) {
753		struct kmembuckets *kb = (struct kmembuckets *)buf;
754		if (!nflag)
755			(void)printf("%s%s", string, equ);
756		printf("(");
757		printf("calls = %llu ", (long long)kb->kb_calls);
758		printf("total_allocated = %llu ", (long long)kb->kb_total);
759		printf("total_free = %lld ", (long long)kb->kb_totalfree);
760		printf("elements = %lld ", (long long)kb->kb_elmpercl);
761		printf("high watermark = %lld ", (long long)kb->kb_highwat);
762		printf("could_free = %lld", (long long)kb->kb_couldfree);
763		printf(")\n");
764		return;
765	}
766	if (special & KMEMSTATS) {
767		struct kmemstats *km = (struct kmemstats *)buf;
768		int j, first = 1;
769
770		if (!nflag)
771			(void)printf("%s%s", string, equ);
772		(void)printf("(inuse = %ld, calls = %ld, memuse = %ldK, "
773		    "limblocks = %d, mapblocks = %d, maxused = %ldK, "
774		    "limit = %ldK, spare = %ld, sizes = (",
775		    km->ks_inuse, km->ks_calls,
776		    (km->ks_memuse + 1023) / 1024, km->ks_limblocks,
777		    km->ks_mapblocks, (km->ks_maxused + 1023) / 1024,
778		    (km->ks_limit + 1023) / 1024, km->ks_spare);
779		for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
780			if ((km->ks_size & j ) == 0)
781				continue;
782			if (first)
783				(void)printf("%d", j);
784			else
785				(void)printf(",%d", j);
786			first = 0;
787		}
788		if (first)
789			(void)printf("none");
790		(void)printf("))\n");
791		return;
792	}
793	if (special & CLOCK) {
794		struct clockinfo *clkp = (struct clockinfo *)buf;
795
796		if (!nflag)
797			(void)printf("%s%s", string, equ);
798		(void)printf(
799		    "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n",
800		    clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz);
801		return;
802	}
803	if (special & BOOTTIME) {
804		struct timeval *btp = (struct timeval *)buf;
805		time_t boottime;
806
807		if (!nflag) {
808			boottime = btp->tv_sec;
809			(void)printf("%s%s%s", string, equ, ctime(&boottime));
810		} else
811			(void)printf("%lld\n", (long long)btp->tv_sec);
812		return;
813	}
814	if (special & BLKDEV) {
815		dev_t dev = *(dev_t *)buf;
816
817		if (!nflag)
818			(void)printf("%s%s%s\n", string, equ,
819			    devname(dev, S_IFBLK));
820		else
821			(void)printf("0x%x\n", dev);
822		return;
823	}
824	if (special & CHRDEV) {
825		dev_t dev = *(dev_t *)buf;
826
827		if (!nflag)
828			(void)printf("%s%s%s\n", string, equ,
829			    devname(dev, S_IFCHR));
830		else
831			(void)printf("0x%x\n", dev);
832		return;
833	}
834#ifdef CPU_BIOS
835	if (special & BIOSGEO) {
836		bios_diskinfo_t *pdi = (bios_diskinfo_t *)buf;
837
838		if (!nflag)
839			(void)printf("%s%s", string, equ);
840		(void)printf("bootdev = 0x%x, "
841		    "cylinders = %u, heads = %u, sectors = %u\n",
842		    pdi->bsd_dev, pdi->bios_cylinders,
843		    pdi->bios_heads, pdi->bios_sectors);
844		return;
845	}
846	if (special & BIOSDEV) {
847		int dev = *(int*)buf;
848
849		if (!nflag)
850			(void)printf("%s%s", string, equ);
851		(void) printf("0x%02x\n", dev);
852		return;
853	}
854#endif
855	if (special & UNSIGNED) {
856		if (newsize == 0) {
857			if (!nflag)
858				(void)printf("%s%s", string, equ);
859			(void)printf("%u\n", *(u_int *)buf);
860		} else {
861			if (!qflag) {
862				if (!nflag)
863					(void)printf("%s: %u -> ", string,
864					    *(u_int *)buf);
865				(void)printf("%u\n", *(u_int *)newval);
866			}
867		}
868		return;
869	}
870	if (special & RNDSTATS) {
871		struct rndstats *rndstats = (struct rndstats *)buf;
872		int i;
873
874		if (!nflag)
875			(void)printf("%s%s", string, equ);
876		printf("tot: %llu used: %llu read: %llu stirs: %llu"
877		    " enqs: %llu deqs: %llu drops: %llu ledrops: %llu",
878		    rndstats->rnd_total, rndstats->rnd_used,
879		    rndstats->arc4_reads, rndstats->arc4_nstirs,
880		    rndstats->rnd_enqs, rndstats->rnd_deqs,
881		    rndstats->rnd_drops, rndstats->rnd_drople);
882		printf(" ed:");
883		for (i = 0;
884		    i < sizeof(rndstats->rnd_ed)/sizeof(rndstats->rnd_ed[0]);
885		    i++)
886			printf(" %llu", (unsigned long long)rndstats->rnd_ed[i]);
887		printf(" sc:");
888		for (i = 0;
889		    i < sizeof(rndstats->rnd_sc)/sizeof(rndstats->rnd_sc[0]);
890		    i++)
891			printf(" %llu", (unsigned long long)rndstats->rnd_sc[i]);
892		printf(" sb:");
893		for (i = 0;
894		    i < sizeof(rndstats->rnd_sb)/sizeof(rndstats->rnd_sb[0]);
895		    i++)
896			printf(" %llu", (unsigned long long)rndstats->rnd_sb[i]);
897		printf("\n");
898		return;
899	}
900	if (special & BADDYNAMIC) {
901		u_int port, lastport;
902		u_int32_t *baddynamic = (u_int32_t *)buf;
903
904		if (!qflag) {
905			if (!nflag)
906				(void)printf("%s%s", string,
907				    newsize ? ": " : equ);
908			lastport = 0;
909			for (port = 0; port < 65536; port++)
910				if (DP_ISSET(baddynamic, port)) {
911					(void)printf("%s%u",
912					    lastport ? "," : "", port);
913					lastport = port;
914				}
915			if (newsize != 0) {
916				if (!nflag)
917					fputs(" -> ", stdout);
918				baddynamic = (u_int32_t *)newval;
919				lastport = 0;
920				for (port = 0; port < 65536; port++)
921					if (DP_ISSET(baddynamic, port)) {
922						(void)printf("%s%u",
923						    lastport ? "," : "", port);
924						lastport = port;
925					}
926			}
927			(void)putchar('\n');
928		}
929		return;
930	}
931	if (special & LONGARRAY) {
932		long *la = (long *)buf;
933		if (!nflag)
934			printf("%s%s", string, equ);
935		while (lal--)
936			printf("%ld%s", *la++, lal? ",":"");
937		putchar('\n');
938		return;
939	}
940	if (special & SENSORS) {
941		struct sensor *s = (struct sensor *)buf;
942
943		if (size > 0 && (s->flags & SENSOR_FINVALID) == 0) {
944			if (!nflag)
945				printf("%s%s", string, equ);
946			print_sensor(s);
947			printf("\n");
948		}
949		return;
950	}
951	switch (type) {
952	case CTLTYPE_INT:
953		if (newsize == 0) {
954			if (!nflag)
955				(void)printf("%s%s", string, equ);
956			(void)printf("%d\n", *(int *)buf);
957		} else {
958			if (!qflag) {
959				if (!nflag)
960					(void)printf("%s: %d -> ", string,
961					    *(int *)buf);
962				(void)printf("%d\n", *(int *)newval);
963			}
964		}
965		return;
966
967	case CTLTYPE_STRING:
968		if (newval == NULL) {
969			if (!nflag)
970				(void)printf("%s%s", string, equ);
971			(void)puts(buf);
972		} else {
973			if (!qflag) {
974				if (!nflag)
975					(void)printf("%s: %s -> ", string, buf);
976				(void)puts((char *)newval);
977			}
978		}
979		return;
980
981	case CTLTYPE_QUAD:
982		if (newsize == 0) {
983			long long tmp = *(quad_t *)buf;
984
985			if (!nflag)
986				(void)printf("%s%s", string, equ);
987			(void)printf("%lld\n", tmp);
988		} else {
989			long long tmp = *(quad_t *)buf;
990
991			if (!qflag) {
992				if (!nflag)
993					(void)printf("%s: %lld -> ",
994					    string, tmp);
995				tmp = *(quad_t *)newval;
996				(void)printf("%qd\n", tmp);
997			}
998		}
999		return;
1000
1001	case CTLTYPE_STRUCT:
1002		warnx("%s: unknown structure returned", string);
1003		return;
1004
1005	default:
1006	case CTLTYPE_NODE:
1007		warnx("%s: unknown type returned", string);
1008		return;
1009	}
1010}
1011
1012static void
1013parse_ports(char *portspec, int *port, int *high_port)
1014{
1015	char *dash;
1016	const char *errstr;
1017
1018	if ((dash = strchr(portspec, '-')) != NULL)
1019		*dash++ = '\0';
1020	*port = strtonum(portspec, 0, 65535, &errstr);
1021	if (errstr != NULL)
1022		errx(1, "port is %s: %s", errstr, portspec);
1023	if (dash != NULL) {
1024		*high_port = strtonum(dash, 0, 65535, &errstr);
1025		if (errstr != NULL)
1026			errx(1, "high port is %s: %s", errstr, dash);
1027		if (*high_port < *port)
1028			errx(1, "high port %d is lower than %d",
1029			    *high_port, *port);
1030	} else
1031		*high_port = *port;
1032}
1033
1034void
1035parse_baddynamic(int mib[], size_t len, char *string, void **newvalp,
1036    size_t *newsizep, int flags, int nflag)
1037{
1038	static u_int32_t newbaddynamic[DP_MAPSIZE];
1039	int port, high_port, baddynamic_loaded = 0, full_list_set = 0;
1040	size_t size;
1041	char action, *cp;
1042
1043	while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) {
1044		if (*cp == '+' || *cp == '-') {
1045			if (full_list_set)
1046				errx(1, "cannot mix +/- with full list");
1047			action = *cp++;
1048			if (!baddynamic_loaded) {
1049				size = sizeof(newbaddynamic);
1050				if (sysctl(mib, len, newbaddynamic,
1051				    &size, 0, 0) == -1) {
1052					if (flags == 0)
1053						return;
1054					if (!nflag)
1055						printf("%s: ", string);
1056					puts("kernel does contain bad dynamic "
1057					    "port tables");
1058					return;
1059				}
1060				baddynamic_loaded = 1;
1061			}
1062			parse_ports(cp, &port, &high_port);
1063			for (; port <= high_port; port++) {
1064				if (action == '+')
1065					DP_SET(newbaddynamic, port);
1066				else
1067					DP_CLR(newbaddynamic, port);
1068			}
1069		} else {
1070			if (baddynamic_loaded)
1071				errx(1, "cannot mix +/- with full list");
1072			if (!full_list_set) {
1073				bzero(newbaddynamic, sizeof(newbaddynamic));
1074				full_list_set = 1;
1075			}
1076			parse_ports(cp, &port, &high_port);
1077			for (; port <= high_port; port++)
1078				DP_SET(newbaddynamic, port);
1079		}
1080	}
1081	*newvalp = (void *)newbaddynamic;
1082	*newsizep = sizeof(newbaddynamic);
1083}
1084
1085/*
1086 * Initialize the set of debugging names
1087 */
1088void
1089debuginit(void)
1090{
1091	int mib[3], loc, i;
1092	size_t size;
1093
1094	if (secondlevel[CTL_DEBUG].list != 0)
1095		return;
1096	secondlevel[CTL_DEBUG].list = debugname;
1097	mib[0] = CTL_DEBUG;
1098	mib[2] = CTL_DEBUG_NAME;
1099	for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) {
1100		mib[1] = i;
1101		size = BUFSIZ - loc;
1102		if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
1103			continue;
1104		debugname[i].ctl_name = &names[loc];
1105		debugname[i].ctl_type = CTLTYPE_INT;
1106		loc += size;
1107	}
1108	lastused = loc;
1109}
1110
1111struct ctlname vfsgennames[] = CTL_VFSGENCTL_NAMES;
1112struct ctlname ffsname[] = FFS_NAMES;
1113struct ctlname nfsname[] = FS_NFS_NAMES;
1114struct ctlname fusefsname[] = FUSEFS_NAMES;
1115struct list *vfsvars;
1116int *vfs_typenums;
1117
1118/*
1119 * Initialize the set of filesystem names
1120 */
1121void
1122vfsinit(void)
1123{
1124	int mib[4], maxtypenum, cnt, loc, size;
1125	struct vfsconf vfc;
1126	size_t buflen;
1127
1128	if (secondlevel[CTL_VFS].list != 0)
1129		return;
1130	mib[0] = CTL_VFS;
1131	mib[1] = VFS_GENERIC;
1132	mib[2] = VFS_MAXTYPENUM;
1133	buflen = 4;
1134	if (sysctl(mib, 3, &maxtypenum, &buflen, (void *)0, (size_t)0) < 0)
1135		return;
1136	/*
1137         * We need to do 0..maxtypenum so add one, and then we offset them
1138	 * all by (another) one by inserting VFS_GENERIC entries at zero
1139	 */
1140	maxtypenum += 2;
1141	if ((vfs_typenums = calloc(maxtypenum, sizeof(int))) == NULL)
1142		return;
1143	if ((vfsvars = calloc(maxtypenum, sizeof(*vfsvars))) == NULL) {
1144		free(vfs_typenums);
1145		return;
1146	}
1147	if ((vfsname = calloc(maxtypenum, sizeof(*vfsname))) == NULL) {
1148		free(vfs_typenums);
1149		free(vfsvars);
1150		return;
1151	}
1152	mib[2] = VFS_CONF;
1153	buflen = sizeof vfc;
1154	for (loc = lastused, cnt = 1; cnt < maxtypenum; cnt++) {
1155		mib[3] = cnt - 1;
1156		if (sysctl(mib, 4, &vfc, &buflen, (void *)0, (size_t)0) < 0) {
1157			if (errno == EOPNOTSUPP)
1158				continue;
1159			warn("vfsinit");
1160			free(vfsname);
1161			free(vfsvars);
1162			free(vfs_typenums);
1163			return;
1164		}
1165		if (!strcmp(vfc.vfc_name, MOUNT_FFS)) {
1166			vfsvars[cnt].list = ffsname;
1167			vfsvars[cnt].size = FFS_MAXID;
1168		}
1169		if (!strcmp(vfc.vfc_name, MOUNT_NFS)) {
1170			vfsvars[cnt].list = nfsname;
1171			vfsvars[cnt].size = NFS_MAXID;
1172		}
1173		if (!strcmp(vfc.vfc_name, MOUNT_FUSEFS)) {
1174			vfsvars[cnt].list = fusefsname;
1175			vfsvars[cnt].size = FUSEFS_MAXID;
1176		}
1177		vfs_typenums[cnt] = vfc.vfc_typenum;
1178		strlcat(&names[loc], vfc.vfc_name, sizeof names - loc);
1179		vfsname[cnt].ctl_name = &names[loc];
1180		vfsname[cnt].ctl_type = CTLTYPE_NODE;
1181		size = strlen(vfc.vfc_name) + 1;
1182		loc += size;
1183	}
1184	lastused = loc;
1185
1186	vfsname[0].ctl_name = "mounts";
1187	vfsname[0].ctl_type = CTLTYPE_NODE;
1188	vfsvars[0].list = vfsname + 1;
1189	vfsvars[0].size = maxtypenum - 1;
1190
1191	secondlevel[CTL_VFS].list = vfsname;
1192	secondlevel[CTL_VFS].size = maxtypenum;
1193	return;
1194}
1195
1196int
1197sysctl_vfsgen(char *string, char **bufpp, int mib[], int flags, int *typep)
1198{
1199	int indx;
1200	size_t size;
1201	struct vfsconf vfc;
1202
1203	if (*bufpp == NULL) {
1204		listall(string, vfsvars);
1205		return (-1);
1206	}
1207
1208	if ((indx = findname(string, "third", bufpp, vfsvars)) == -1)
1209		return (-1);
1210
1211	mib[1] = VFS_GENERIC;
1212	mib[2] = VFS_CONF;
1213	mib[3] = indx;
1214	size = sizeof vfc;
1215	if (sysctl(mib, 4, &vfc, &size, (void *)0, (size_t)0) < 0) {
1216		if (errno != EOPNOTSUPP)
1217			warn("vfs print");
1218		return -1;
1219	}
1220	if (flags == 0 && vfc.vfc_refcount == 0)
1221		return -1;
1222	if (!nflag)
1223		fprintf(stdout, "%s has %d mounted instance%s\n",
1224		    string, vfc.vfc_refcount,
1225		    vfc.vfc_refcount != 1 ? "s" : "");
1226	else
1227		fprintf(stdout, "%d\n", vfc.vfc_refcount);
1228
1229	return -1;
1230}
1231
1232int
1233sysctl_vfs(char *string, char **bufpp, int mib[], int flags, int *typep)
1234{
1235	struct list *lp = &vfsvars[mib[1]];
1236	int indx;
1237
1238	if (lp->list == NULL) {
1239		if (flags)
1240			warnx("No variables defined for file system %s", string);
1241		return (-1);
1242	}
1243	if (*bufpp == NULL) {
1244		listall(string, lp);
1245		return (-1);
1246	}
1247	if ((indx = findname(string, "third", bufpp, lp)) == -1)
1248		return (-1);
1249
1250	mib[1] = vfs_typenums[mib[1]];
1251	mib[2] = indx;
1252	*typep = lp->list[indx].ctl_type;
1253	return (3);
1254}
1255
1256struct ctlname posixname[] = CTL_FS_POSIX_NAMES;
1257struct list fslist = { posixname, FS_POSIX_MAXID };
1258
1259/*
1260 * handle file system requests
1261 */
1262int
1263sysctl_fs(char *string, char **bufpp, int mib[], int flags, int *typep)
1264{
1265	int indx;
1266
1267	if (*bufpp == NULL) {
1268		listall(string, &fslist);
1269		return (-1);
1270	}
1271	if ((indx = findname(string, "third", bufpp, &fslist)) == -1)
1272		return (-1);
1273	mib[2] = indx;
1274	*typep = fslist.list[indx].ctl_type;
1275	return (3);
1276}
1277
1278#ifdef CPU_BIOS
1279struct ctlname biosname[] = CTL_BIOS_NAMES;
1280struct list bioslist = { biosname, BIOS_MAXID };
1281
1282/*
1283 * handle BIOS requests
1284 */
1285int
1286sysctl_bios(char *string, char **bufpp, int mib[], int flags, int *typep)
1287{
1288	char *name;
1289	int indx;
1290
1291	if (*bufpp == NULL) {
1292		listall(string, &bioslist);
1293		return (-1);
1294	}
1295	if ((indx = findname(string, "third", bufpp, &bioslist)) == -1)
1296		return (-1);
1297	mib[2] = indx;
1298	if (indx == BIOS_DISKINFO) {
1299		if (*bufpp == NULL) {
1300			char name[BUFSIZ];
1301
1302			/* scan all the bios devices */
1303			for (indx = 0; indx < 256; indx++) {
1304				snprintf(name, sizeof(name), "%s.%u",
1305				    string, indx);
1306				parse(name, 1);
1307			}
1308			return (-1);
1309		}
1310		if ((name = strsep(bufpp, ".")) == NULL) {
1311			warnx("%s: incomplete specification", string);
1312			return (-1);
1313		}
1314		mib[3] = atoi(name);
1315		*typep = CTLTYPE_STRUCT;
1316		return (4);
1317	} else {
1318		*typep = bioslist.list[indx].ctl_type;
1319		return (3);
1320	}
1321}
1322#endif
1323
1324struct ctlname swpencname[] = CTL_SWPENC_NAMES;
1325struct list swpenclist = { swpencname, SWPENC_MAXID };
1326
1327/*
1328 * handle swap encrypt requests
1329 */
1330int
1331sysctl_swpenc(char *string, char **bufpp, int mib[], int flags, int *typep)
1332{
1333	int indx;
1334
1335	if (*bufpp == NULL) {
1336		listall(string, &swpenclist);
1337		return (-1);
1338	}
1339	if ((indx = findname(string, "third", bufpp, &swpenclist)) == -1)
1340		return (-1);
1341	mib[2] = indx;
1342	*typep = swpenclist.list[indx].ctl_type;
1343	return (3);
1344}
1345
1346struct ctlname inetname[] = CTL_IPPROTO_NAMES;
1347struct ctlname ipname[] = IPCTL_NAMES;
1348struct ctlname icmpname[] = ICMPCTL_NAMES;
1349struct ctlname igmpname[] = IGMPCTL_NAMES;
1350struct ctlname ipipname[] = IPIPCTL_NAMES;
1351struct ctlname tcpname[] = TCPCTL_NAMES;
1352struct ctlname udpname[] = UDPCTL_NAMES;
1353struct ctlname espname[] = ESPCTL_NAMES;
1354struct ctlname ahname[] = AHCTL_NAMES;
1355struct ctlname etheripname[] = ETHERIPCTL_NAMES;
1356struct ctlname grename[] = GRECTL_NAMES;
1357struct ctlname mobileipname[] = MOBILEIPCTL_NAMES;
1358struct ctlname ipcompname[] = IPCOMPCTL_NAMES;
1359struct ctlname carpname[] = CARPCTL_NAMES;
1360struct ctlname pfsyncname[] = PFSYNCCTL_NAMES;
1361struct ctlname divertname[] = DIVERTCTL_NAMES;
1362struct ctlname bpfname[] = CTL_NET_BPF_NAMES;
1363struct ctlname ifqname[] = CTL_IFQ_NAMES;
1364struct ctlname pipexname[] = PIPEXCTL_NAMES;
1365struct list inetlist = { inetname, IPPROTO_MAXID };
1366struct list inetvars[] = {
1367	{ ipname, IPCTL_MAXID },	/* ip */
1368	{ icmpname, ICMPCTL_MAXID },	/* icmp */
1369	{ igmpname, IGMPCTL_MAXID },	/* igmp */
1370	{ 0, 0 },			/* ggmp */
1371	{ ipipname, IPIPCTL_MAXID },	/* ipencap */
1372	{ 0, 0 },
1373	{ tcpname, TCPCTL_MAXID },	/* tcp */
1374	{ 0, 0 },
1375	{ 0, 0 },			/* egp */
1376	{ 0, 0 },
1377	{ 0, 0 },
1378	{ 0, 0 },
1379	{ 0, 0 },			/* pup */
1380	{ 0, 0 },
1381	{ 0, 0 },
1382	{ 0, 0 },
1383	{ 0, 0 },
1384	{ udpname, UDPCTL_MAXID },	/* udp */
1385	{ 0, 0 },
1386	{ 0, 0 },
1387	{ 0, 0 },
1388	{ 0, 0 },
1389	{ 0, 0 },
1390	{ 0, 0 },
1391	{ 0, 0 },
1392	{ 0, 0 },
1393	{ 0, 0 },
1394	{ 0, 0 },
1395	{ 0, 0 },
1396	{ 0, 0 },
1397	{ 0, 0 },
1398	{ 0, 0 },
1399	{ 0, 0 },
1400	{ 0, 0 },
1401	{ 0, 0 },
1402	{ 0, 0 },
1403	{ 0, 0 },
1404	{ 0, 0 },
1405	{ 0, 0 },
1406	{ 0, 0 },
1407	{ 0, 0 },
1408	{ 0, 0 },
1409	{ 0, 0 },
1410	{ 0, 0 },
1411	{ 0, 0 },
1412	{ 0, 0 },
1413	{ 0, 0 },
1414	{ grename, GRECTL_MAXID },	/* gre */
1415	{ 0, 0 },
1416	{ 0, 0 },
1417	{ espname, ESPCTL_MAXID },	/* esp */
1418	{ ahname, AHCTL_MAXID },	/* ah */
1419	{ 0, 0 },
1420	{ 0, 0 },
1421	{ 0, 0 },
1422	{ mobileipname, MOBILEIPCTL_MAXID }, /* mobileip */
1423	{ 0, 0 },
1424	{ 0, 0 },
1425	{ 0, 0 },
1426	{ 0, 0 },
1427	{ 0, 0 },
1428	{ 0, 0 },
1429	{ 0, 0 },
1430	{ 0, 0 },
1431	{ 0, 0 },
1432	{ 0, 0 },
1433	{ 0, 0 },
1434	{ 0, 0 },
1435	{ 0, 0 },
1436	{ 0, 0 },
1437	{ 0, 0 },
1438	{ 0, 0 },
1439	{ 0, 0 },
1440	{ 0, 0 },
1441	{ 0, 0 },
1442	{ 0, 0 },
1443	{ 0, 0 },
1444	{ 0, 0 },
1445	{ 0, 0 },
1446	{ 0, 0 },
1447	{ 0, 0 },
1448	{ 0, 0 },
1449	{ 0, 0 },
1450	{ 0, 0 },
1451	{ 0, 0 },
1452	{ 0, 0 },
1453	{ 0, 0 },
1454	{ 0, 0 },
1455	{ 0, 0 },
1456	{ 0, 0 },
1457	{ 0, 0 },
1458	{ 0, 0 },
1459	{ 0, 0 },
1460	{ 0, 0 },
1461	{ 0, 0 },
1462	{ 0, 0 },
1463	{ 0, 0 },
1464	{ etheripname, ETHERIPCTL_MAXID },
1465	{ 0, 0 },
1466	{ 0, 0 },
1467	{ 0, 0 },
1468	{ 0, 0 },
1469	{ 0, 0 },
1470	{ 0, 0 },
1471	{ 0, 0 },
1472	{ 0, 0 },
1473	{ 0, 0 },
1474	{ 0, 0 },
1475	{ ipcompname, IPCOMPCTL_MAXID },
1476	{ 0, 0 },
1477	{ 0, 0 },
1478	{ 0, 0 },
1479	{ carpname, CARPCTL_MAXID },
1480	{ 0, 0 },
1481	{ 0, 0 },
1482	{ 0, 0 },
1483	{ 0, 0 },
1484	{ 0, 0 },
1485	{ 0, 0 },
1486	{ 0, 0 },
1487	{ 0, 0 },
1488	{ 0, 0 },
1489	{ 0, 0 },
1490	{ 0, 0 },
1491	{ 0, 0 },
1492	{ 0, 0 },
1493	{ 0, 0 },
1494	{ 0, 0 },
1495	{ 0, 0 },
1496	{ 0, 0 },
1497	{ 0, 0 },
1498	{ 0, 0 },
1499	{ 0, 0 },
1500	{ 0, 0 },
1501	{ 0, 0 },
1502	{ 0, 0 },
1503	{ 0, 0 },
1504	{ 0, 0 },
1505	{ 0, 0 },
1506	{ 0, 0 },
1507	{ 0, 0 },
1508	{ 0, 0 },
1509	{ 0, 0 },
1510	{ 0, 0 },
1511	{ 0, 0 },
1512	{ 0, 0 },
1513	{ 0, 0 },
1514	{ 0, 0 },
1515	{ 0, 0 },
1516	{ 0, 0 },
1517	{ 0, 0 },
1518	{ 0, 0 },
1519	{ 0, 0 },
1520	{ 0, 0 },
1521	{ 0, 0 },
1522	{ 0, 0 },
1523	{ 0, 0 },
1524	{ 0, 0 },
1525	{ 0, 0 },
1526	{ 0, 0 },
1527	{ 0, 0 },
1528	{ 0, 0 },
1529	{ 0, 0 },
1530	{ 0, 0 },
1531	{ 0, 0 },
1532	{ 0, 0 },
1533	{ 0, 0 },
1534	{ 0, 0 },
1535	{ 0, 0 },
1536	{ 0, 0 },
1537	{ 0, 0 },
1538	{ 0, 0 },
1539	{ 0, 0 },
1540	{ 0, 0 },
1541	{ 0, 0 },
1542	{ 0, 0 },
1543	{ 0, 0 },
1544	{ 0, 0 },
1545	{ 0, 0 },
1546	{ 0, 0 },
1547	{ 0, 0 },
1548	{ 0, 0 },
1549	{ 0, 0 },
1550	{ 0, 0 },
1551	{ 0, 0 },
1552	{ 0, 0 },
1553	{ 0, 0 },
1554	{ 0, 0 },
1555	{ 0, 0 },
1556	{ 0, 0 },
1557	{ 0, 0 },
1558	{ 0, 0 },
1559	{ 0, 0 },
1560	{ 0, 0 },
1561	{ 0, 0 },
1562	{ 0, 0 },
1563	{ 0, 0 },
1564	{ 0, 0 },
1565	{ 0, 0 },
1566	{ 0, 0 },
1567	{ 0, 0 },
1568	{ 0, 0 },
1569	{ 0, 0 },
1570	{ 0, 0 },
1571	{ 0, 0 },
1572	{ 0, 0 },
1573	{ 0, 0 },
1574	{ 0, 0 },
1575	{ 0, 0 },
1576	{ 0, 0 },
1577	{ 0, 0 },
1578	{ 0, 0 },
1579	{ 0, 0 },
1580	{ 0, 0 },
1581	{ 0, 0 },
1582	{ 0, 0 },
1583	{ 0, 0 },
1584	{ 0, 0 },
1585	{ 0, 0 },
1586	{ 0, 0 },
1587	{ 0, 0 },
1588	{ 0, 0 },
1589	{ 0, 0 },
1590	{ 0, 0 },
1591	{ 0, 0 },
1592	{ 0, 0 },
1593	{ 0, 0 },
1594	{ 0, 0 },
1595	{ 0, 0 },
1596	{ 0, 0 },
1597	{ 0, 0 },
1598	{ 0, 0 },
1599	{ 0, 0 },
1600	{ 0, 0 },
1601	{ 0, 0 },
1602	{ 0, 0 },
1603	{ 0, 0 },
1604	{ 0, 0 },
1605	{ 0, 0 },
1606	{ 0, 0 },
1607	{ 0, 0 },
1608	{ 0, 0 },
1609	{ 0, 0 },
1610	{ 0, 0 },
1611	{ 0, 0 },
1612	{ 0, 0 },
1613	{ 0, 0 },
1614	{ 0, 0 },
1615	{ 0, 0 },
1616	{ pfsyncname, PFSYNCCTL_MAXID },
1617	{ 0, 0 },
1618	{ 0, 0 },
1619	{ 0, 0 },
1620	{ 0, 0 },
1621	{ 0, 0 },
1622	{ 0, 0 },
1623	{ 0, 0 },
1624	{ 0, 0 },
1625	{ divertname, DIVERTCTL_MAXID },
1626};
1627struct list bpflist = { bpfname, NET_BPF_MAXID };
1628struct list ifqlist = { ifqname, IFQCTL_MAXID };
1629struct list pipexlist = { pipexname, PIPEXCTL_MAXID };
1630
1631struct list kernmalloclist = { kernmallocname, KERN_MALLOC_MAXID };
1632struct list forkstatlist = { forkstatname, KERN_FORKSTAT_MAXID };
1633struct list nchstatslist = { nchstatsname, KERN_NCHSTATS_MAXID };
1634struct list ttylist = { ttysname, KERN_TTY_MAXID };
1635struct list semlist = { semname, KERN_SEMINFO_MAXID };
1636struct list shmlist = { shmname, KERN_SHMINFO_MAXID };
1637struct list watchdoglist = { watchdogname, KERN_WATCHDOG_MAXID };
1638struct list tclist = { tcname, KERN_TIMECOUNTER_MAXID };
1639
1640/*
1641 * handle vfs namei cache statistics
1642 */
1643int
1644sysctl_nchstats(char *string, char **bufpp, int mib[], int flags, int *typep)
1645{
1646	static struct nchstats nch;
1647	int indx;
1648	size_t size;
1649	static int keepvalue = 0;
1650
1651	if (*bufpp == NULL) {
1652		bzero(&nch, sizeof(struct nchstats));
1653		listall(string, &nchstatslist);
1654		return (-1);
1655	}
1656	if ((indx = findname(string, "third", bufpp, &nchstatslist)) == -1)
1657		return (-1);
1658	mib[2] = indx;
1659	if (*bufpp != NULL) {
1660		warnx("fourth level name in %s is invalid", string);
1661		return (-1);
1662	}
1663	if (keepvalue == 0) {
1664		size = sizeof(struct nchstats);
1665		if (sysctl(mib, 2, &nch, &size, NULL, 0) < 0)
1666			return (-1);
1667		keepvalue = 1;
1668	}
1669	if (!nflag)
1670		(void)printf("%s%s", string, equ);
1671	switch (indx) {
1672	case KERN_NCHSTATS_GOODHITS:
1673		(void)printf("%llu\n", nch.ncs_goodhits);
1674		break;
1675	case KERN_NCHSTATS_NEGHITS:
1676		(void)printf("%llu\n", nch.ncs_neghits);
1677		break;
1678	case KERN_NCHSTATS_BADHITS:
1679		(void)printf("%llu\n", nch.ncs_badhits);
1680		break;
1681	case KERN_NCHSTATS_FALSEHITS:
1682		(void)printf("%llu\n", nch.ncs_falsehits);
1683		break;
1684	case KERN_NCHSTATS_MISS:
1685		(void)printf("%llu\n", nch.ncs_miss);
1686		break;
1687	case KERN_NCHSTATS_LONG:
1688		(void)printf("%llu\n", nch.ncs_long);
1689		break;
1690	case KERN_NCHSTATS_PASS2:
1691		(void)printf("%llu\n", nch.ncs_pass2);
1692		break;
1693	case KERN_NCHSTATS_2PASSES:
1694		(void)printf("%llu\n", nch.ncs_2passes);
1695		break;
1696	case KERN_NCHSTATS_REVHITS:
1697		(void)printf("%llu\n", nch.ncs_revhits);
1698		break;
1699	case KERN_NCHSTATS_REVMISS:
1700		(void)printf("%llu\n", nch.ncs_revmiss);
1701		break;
1702	case KERN_NCHSTATS_DOTHITS:
1703		(void)printf("%llu\n", nch.ncs_dothits);
1704		break;
1705	case KERN_NCHSTATS_DOTDOTHITS:
1706		(void)printf("%llu\n", nch.ncs_dotdothits);
1707		break;
1708	}
1709	return (-1);
1710}
1711
1712/*
1713 * handle tty statistics
1714 */
1715int
1716sysctl_tty(char *string, char **bufpp, int mib[], int flags, int *typep)
1717{
1718	int indx;
1719
1720	if (*bufpp == NULL) {
1721		listall(string, &ttylist);
1722		return (-1);
1723	}
1724	if ((indx = findname(string, "third", bufpp, &ttylist)) == -1)
1725		return (-1);
1726	mib[2] = indx;
1727
1728	if ((*typep = ttylist.list[indx].ctl_type) == CTLTYPE_STRUCT) {
1729		if (flags)
1730			warnx("use pstat -t to view %s information",
1731			    string);
1732		return (-1);
1733	}
1734	return (3);
1735}
1736
1737/*
1738 * handle fork statistics
1739 */
1740int
1741sysctl_forkstat(char *string, char **bufpp, int mib[], int flags, int *typep)
1742{
1743	static struct forkstat fks;
1744	static int keepvalue = 0;
1745	int indx;
1746	size_t size;
1747
1748	if (*bufpp == NULL) {
1749		bzero(&fks, sizeof(struct forkstat));
1750		listall(string, &forkstatlist);
1751		return (-1);
1752	}
1753	if ((indx = findname(string, "third", bufpp, &forkstatlist)) == -1)
1754		return (-1);
1755	if (*bufpp != NULL) {
1756		warnx("fourth level name in %s is invalid", string);
1757		return (-1);
1758	}
1759	if (keepvalue == 0) {
1760		size = sizeof(struct forkstat);
1761		if (sysctl(mib, 2, &fks, &size, NULL, 0) < 0)
1762			return (-1);
1763		keepvalue = 1;
1764	}
1765	if (!nflag)
1766		(void)printf("%s%s", string, equ);
1767	switch (indx)	{
1768	case KERN_FORKSTAT_FORK:
1769		(void)printf("%d\n", fks.cntfork);
1770		break;
1771	case KERN_FORKSTAT_VFORK:
1772		(void)printf("%d\n", fks.cntvfork);
1773		break;
1774	case KERN_FORKSTAT_TFORK:
1775		(void)printf("%d\n", fks.cnttfork);
1776		break;
1777	case KERN_FORKSTAT_KTHREAD:
1778		(void)printf("%d\n", fks.cntkthread);
1779		break;
1780	case KERN_FORKSTAT_SIZFORK:
1781		(void)printf("%d\n", fks.sizfork);
1782		break;
1783	case KERN_FORKSTAT_SIZVFORK:
1784		(void)printf("%d\n", fks.sizvfork);
1785		break;
1786	case KERN_FORKSTAT_SIZTFORK:
1787		(void)printf("%d\n", fks.siztfork);
1788		break;
1789	case KERN_FORKSTAT_SIZKTHREAD:
1790		(void)printf("%d\n", fks.sizkthread);
1791		break;
1792	}
1793	return (-1);
1794}
1795
1796/*
1797 * handle malloc statistics
1798 */
1799int
1800sysctl_malloc(char *string, char **bufpp, int mib[], int flags, int *typep)
1801{
1802	int indx, stor, i;
1803	char *name, bufp[SYSCTL_BUFSIZ], *buf, *ptr;
1804	struct list lp;
1805	size_t size;
1806
1807	if (*bufpp == NULL) {
1808		listall(string, &kernmalloclist);
1809		return (-1);
1810	}
1811	if ((indx = findname(string, "third", bufpp, &kernmalloclist)) == -1)
1812		return (-1);
1813	mib[2] = indx;
1814	if (mib[2] == KERN_MALLOC_BUCKET) {
1815		if ((name = strsep(bufpp, ".")) == NULL) {
1816			size = SYSCTL_BUFSIZ;
1817			stor = mib[2];
1818			mib[2] = KERN_MALLOC_BUCKETS;
1819			buf = bufp;
1820			if (sysctl(mib, 3, buf, &size, NULL, 0) < 0)
1821				return (-1);
1822			mib[2] = stor;
1823			for (stor = 0, i = 0; i < size; i++)
1824				if (buf[i] == ',')
1825					stor++;
1826			lp.list = calloc(stor + 2, sizeof(struct ctlname));
1827			if (lp.list == NULL)
1828				return (-1);
1829			lp.size = stor + 2;
1830			for (i = 1;
1831			    (lp.list[i].ctl_name = strsep(&buf, ",")) != NULL;
1832			    i++) {
1833				lp.list[i].ctl_type = CTLTYPE_STRUCT;
1834			}
1835			lp.list[i].ctl_name = buf;
1836			lp.list[i].ctl_type = CTLTYPE_STRUCT;
1837			listall(string, &lp);
1838			free(lp.list);
1839			return (-1);
1840		}
1841		mib[3] = atoi(name);
1842		return (4);
1843	} else if (mib[2] == KERN_MALLOC_BUCKETS) {
1844		*typep = CTLTYPE_STRING;
1845		return (3);
1846	} else if (mib[2] == KERN_MALLOC_KMEMSTATS) {
1847		size = SYSCTL_BUFSIZ;
1848		stor = mib[2];
1849		mib[2] = KERN_MALLOC_KMEMNAMES;
1850		buf = bufp;
1851		if (sysctl(mib, 3, buf, &size, NULL, 0) < 0)
1852			return (-1);
1853		mib[2] = stor;
1854		if ((name = strsep(bufpp, ".")) == NULL) {
1855			for (stor = 0, i = 0; i < size; i++)
1856				if (buf[i] == ',')
1857					stor++;
1858			lp.list = calloc(stor + 2, sizeof(struct ctlname));
1859			if (lp.list == NULL)
1860				return (-1);
1861			lp.size = stor + 2;
1862			for (i = 1;
1863			    (lp.list[i].ctl_name = strsep(&buf, ",")) != NULL;
1864			    i++) {
1865				if (lp.list[i].ctl_name[0] == '\0') {
1866					i--;
1867					continue;
1868				}
1869				lp.list[i].ctl_type = CTLTYPE_STRUCT;
1870			}
1871			lp.list[i].ctl_name = buf;
1872			lp.list[i].ctl_type = CTLTYPE_STRUCT;
1873			listall(string, &lp);
1874			free(lp.list);
1875			return (-1);
1876		}
1877		ptr = strstr(buf, name);
1878 tryagain:
1879		if (ptr == NULL) {
1880			warnx("fourth level name %s in %s is invalid", name,
1881			    string);
1882			return (-1);
1883		}
1884		if ((*(ptr + strlen(name)) != ',') &&
1885		    (*(ptr + strlen(name)) != '\0')) {
1886			ptr = strstr(ptr + 1, name); /* retry */
1887			goto tryagain;
1888		}
1889		if ((ptr != buf) && (*(ptr - 1) != ',')) {
1890			ptr = strstr(ptr + 1, name); /* retry */
1891			goto tryagain;
1892		}
1893		for (i = 0, stor = 0; buf + i < ptr; i++)
1894			if (buf[i] == ',')
1895				stor++;
1896		mib[3] = stor;
1897		return (4);
1898	} else if (mib[2] == KERN_MALLOC_KMEMNAMES) {
1899		*typep = CTLTYPE_STRING;
1900		return (3);
1901	}
1902	return (-1);
1903}
1904
1905#ifdef CPU_CHIPSET
1906/*
1907 * handle machdep.chipset requests
1908 */
1909struct ctlname chipsetname[] = CTL_CHIPSET_NAMES;
1910struct list chipsetlist = { chipsetname, CPU_CHIPSET_MAXID };
1911
1912int
1913sysctl_chipset(char *string, char **bufpp, int mib[], int flags, int *typep)
1914{
1915	int indx, bwx;
1916	static void *q;
1917	size_t len;
1918	char *p;
1919
1920	if (*bufpp == NULL) {
1921		listall(string, &chipsetlist);
1922		return (-1);
1923	}
1924	if ((indx = findname(string, "third", bufpp, &chipsetlist)) == -1)
1925		return (-1);
1926	mib[2] = indx;
1927	if (!nflag)
1928		printf("%s%s", string, equ);
1929	switch(mib[2]) {
1930	case CPU_CHIPSET_MEM:
1931	case CPU_CHIPSET_DENSE:
1932	case CPU_CHIPSET_PORTS:
1933	case CPU_CHIPSET_HAE_MASK:
1934		len = sizeof(void *);
1935		if (sysctl(mib, 3, &q, &len, NULL, 0) < 0)
1936			goto done;
1937		printf("%p", q);
1938		break;
1939	case CPU_CHIPSET_BWX:
1940		len = sizeof(int);
1941		if (sysctl(mib, 3, &bwx, &len, NULL, 0) < 0)
1942			goto done;
1943		printf("%d", bwx);
1944		break;
1945	case CPU_CHIPSET_TYPE:
1946		if (sysctl(mib, 3, NULL, &len, NULL, 0) < 0)
1947			goto done;
1948		p = malloc(len + 1);
1949		if (p == NULL)
1950			goto done;
1951		if (sysctl(mib, 3, p, &len, NULL, 0) < 0) {
1952			free(p);
1953			goto done;
1954		}
1955		p[len] = '\0';
1956		printf("%s", p);
1957		free(p);
1958		break;
1959	}
1960done:
1961	printf("\n");
1962	return (-1);
1963}
1964#endif
1965/*
1966 * handle internet requests
1967 */
1968int
1969sysctl_inet(char *string, char **bufpp, int mib[], int flags, int *typep)
1970{
1971	struct list *lp;
1972	int indx;
1973
1974	if (*bufpp == NULL) {
1975		listall(string, &inetlist);
1976		return (-1);
1977	}
1978	if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
1979		return (-1);
1980	mib[2] = indx;
1981	if (indx < IPPROTO_MAXID && inetvars[indx].list != NULL)
1982		lp = &inetvars[indx];
1983	else if (!flags)
1984		return (-1);
1985	else {
1986		warnx("%s: no variables defined for this protocol", string);
1987		return (-1);
1988	}
1989	if (*bufpp == NULL) {
1990		listall(string, lp);
1991		return (-1);
1992	}
1993	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1994		return (-1);
1995	mib[3] = indx;
1996	*typep = lp->list[indx].ctl_type;
1997	if (*typep == CTLTYPE_NODE) {
1998		int tindx;
1999
2000		if (*bufpp == NULL) {
2001			listall(string, &ifqlist);
2002			return(-1);
2003		}
2004		lp = &ifqlist;
2005		if ((tindx = findname(string, "fifth", bufpp, lp)) == -1)
2006			return (-1);
2007		mib[4] = tindx;
2008		*typep = lp->list[tindx].ctl_type;
2009		return(5);
2010	}
2011	return (4);
2012}
2013
2014#ifdef INET6
2015struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES;
2016struct ctlname ip6name[] = IPV6CTL_NAMES;
2017struct ctlname icmp6name[] = ICMPV6CTL_NAMES;
2018struct ctlname pim6name[] = PIM6CTL_NAMES;
2019struct ctlname divert6name[] = DIVERT6CTL_NAMES;
2020struct list inet6list = { inet6name, IPV6PROTO_MAXID };
2021struct list inet6vars[] = {
2022/*0*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2023	{ 0, 0 },
2024	{ 0, 0 },
2025	{ 0, 0 },
2026	{ 0, 0 },
2027	{ 0, 0 },
2028/*10*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2029	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2030/*20*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2031	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2032/*30*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2033	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2034/*40*/	{ 0, 0 },
2035	{ ip6name, IPV6CTL_MAXID },	/* ipv6 */
2036	{ 0, 0 },
2037	{ 0, 0 },
2038	{ 0, 0 },
2039	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2040/*50*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2041	{ 0, 0 },
2042	{ 0, 0 },
2043	{ 0, 0 },
2044	{ icmp6name, ICMPV6CTL_MAXID },	/* icmp6 */
2045	{ 0, 0 },
2046/*60*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2047	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2048/*70*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2049	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2050/*80*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2051	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2052/*90*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2053	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2054/*100*/	{ 0, 0 },
2055	{ 0, 0 },
2056	{ 0, 0 },
2057	{ pim6name, PIM6CTL_MAXID },	/* pim6 */
2058	{ 0, 0 },
2059	{ 0, 0 },
2060	{ 0, 0 },
2061	{ 0, 0 },
2062	{ 0, 0 },
2063	{ 0, 0 },
2064/*110*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2065	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2066/*120*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2067	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2068/*130*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2069	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2070/*140*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2071	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2072/*150*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2073	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2074/*160*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2075	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2076/*170*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2077	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2078/*180*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2079	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2080/*190*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2081	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2082/*200*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2083	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2084/*210*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2085	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2086/*220*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2087	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2088/*230*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2089	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2090/*240*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2091	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2092/*250*/	{ 0, 0 },
2093	{ 0, 0 },
2094	{ 0, 0 },
2095	{ 0, 0 },
2096	{ 0, 0 },
2097	{ 0, 0 },
2098	{ 0, 0 },
2099	{ 0, 0 },
2100	{ divert6name, DIVERT6CTL_MAXID },
2101};
2102
2103/*
2104 * handle internet6 requests
2105 */
2106int
2107sysctl_inet6(char *string, char **bufpp, int mib[], int flags, int *typep)
2108{
2109	struct list *lp;
2110	int indx;
2111
2112	if (*bufpp == NULL) {
2113		listall(string, &inet6list);
2114		return (-1);
2115	}
2116	if ((indx = findname(string, "third", bufpp, &inet6list)) == -1)
2117		return (-1);
2118	mib[2] = indx;
2119	if (indx < IPV6PROTO_MAXID && inet6vars[indx].list != NULL)
2120		lp = &inet6vars[indx];
2121	else if (!flags)
2122		return (-1);
2123	else {
2124		warnx("%s: no variables defined for this protocol", string);
2125		return (-1);
2126	}
2127	if (*bufpp == NULL) {
2128		listall(string, lp);
2129		return (-1);
2130	}
2131	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
2132		return (-1);
2133	mib[3] = indx;
2134	*typep = lp->list[indx].ctl_type;
2135	return (4);
2136}
2137#endif
2138
2139/* handle bpf requests */
2140int
2141sysctl_bpf(char *string, char **bufpp, int mib[], int flags, int *typep)
2142{
2143	int indx;
2144
2145	if (*bufpp == NULL) {
2146		listall(string, &bpflist);
2147		return (-1);
2148	}
2149	if ((indx = findname(string, "third", bufpp, &bpflist)) == -1)
2150		return (-1);
2151	mib[2] = indx;
2152	*typep = CTLTYPE_INT;
2153	return (3);
2154}
2155
2156struct ctlname mplsname[] = MPLSCTL_NAMES;
2157struct list mplslist = { mplsname, MPLSCTL_MAXID };
2158
2159/* handle MPLS requests */
2160int
2161sysctl_mpls(char *string, char **bufpp, int mib[], int flags, int *typep)
2162{
2163	struct list *lp;
2164	int indx;
2165
2166	if (*bufpp == NULL) {
2167		listall(string, &mplslist);
2168		return (-1);
2169	}
2170	if ((indx = findname(string, "third", bufpp, &mplslist)) == -1)
2171		return (-1);
2172	mib[2] = indx;
2173	*typep = mplslist.list[indx].ctl_type;
2174	if (*typep == CTLTYPE_NODE) {
2175		int tindx;
2176
2177		if (*bufpp == NULL) {
2178			listall(string, &ifqlist);
2179			return(-1);
2180		}
2181		lp = &ifqlist;
2182		if ((tindx = findname(string, "fourth", bufpp, lp)) == -1)
2183			return (-1);
2184		mib[3] = tindx;
2185		*typep = lp->list[tindx].ctl_type;
2186		return(4);
2187	}
2188	return (3);
2189}
2190
2191/* handle PIPEX requests */
2192int
2193sysctl_pipex(char *string, char **bufpp, int mib[], int flags, int *typep)
2194{
2195	struct list *lp;
2196	int indx;
2197
2198	if (*bufpp == NULL) {
2199		listall(string, &pipexlist);
2200		return (-1);
2201	}
2202	if ((indx = findname(string, "third", bufpp, &pipexlist)) == -1)
2203		return (-1);
2204	mib[2] = indx;
2205	*typep = pipexlist.list[indx].ctl_type;
2206	if (*typep == CTLTYPE_NODE) {
2207		int tindx;
2208
2209		if (*bufpp == NULL) {
2210			listall(string, &ifqlist);
2211			return(-1);
2212		}
2213		lp = &ifqlist;
2214		if ((tindx = findname(string, "fourth", bufpp, lp)) == -1)
2215			return (-1);
2216		mib[3] = tindx;
2217		*typep = lp->list[tindx].ctl_type;
2218		return(4);
2219	}
2220	return (3);
2221}
2222
2223/*
2224 * Handle SysV semaphore info requests
2225 */
2226int
2227sysctl_seminfo(string, bufpp, mib, flags, typep)
2228	char *string;
2229	char **bufpp;
2230	int mib[];
2231	int flags;
2232	int *typep;
2233{
2234	int indx;
2235
2236	if (*bufpp == NULL) {
2237		listall(string, &semlist);
2238		return (-1);
2239	}
2240	if ((indx = findname(string, "third", bufpp, &semlist)) == -1)
2241		return (-1);
2242	mib[2] = indx;
2243	*typep = CTLTYPE_INT;
2244	return (3);
2245}
2246
2247/*
2248 * Handle SysV shared memory info requests
2249 */
2250int
2251sysctl_shminfo(string, bufpp, mib, flags, typep)
2252	char *string;
2253	char **bufpp;
2254	int mib[];
2255	int flags;
2256	int *typep;
2257{
2258	int indx;
2259
2260	if (*bufpp == NULL) {
2261		listall(string, &shmlist);
2262		return (-1);
2263	}
2264	if ((indx = findname(string, "third", bufpp, &shmlist)) == -1)
2265		return (-1);
2266	mib[2] = indx;
2267	*typep = CTLTYPE_INT;
2268	return (3);
2269}
2270
2271/*
2272 * Handle watchdog support
2273 */
2274int
2275sysctl_watchdog(char *string, char **bufpp, int mib[], int flags,
2276    int *typep)
2277{
2278	int indx;
2279
2280	if (*bufpp == NULL) {
2281		listall(string, &watchdoglist);
2282		return (-1);
2283	}
2284	if ((indx = findname(string, "third", bufpp, &watchdoglist)) == -1)
2285		return (-1);
2286	mib[2] = indx;
2287	*typep = watchdoglist.list[indx].ctl_type;
2288	return (3);
2289}
2290
2291/*
2292 * Handle timecounter support
2293 */
2294int
2295sysctl_tc(char *string, char **bufpp, int mib[], int flags,
2296    int *typep)
2297{
2298	int indx;
2299
2300	if (*bufpp == NULL) {
2301		listall(string, &tclist);
2302		return (-1);
2303	}
2304	if ((indx = findname(string, "third", bufpp, &tclist)) == -1)
2305		return (-1);
2306	mib[2] = indx;
2307	*typep = tclist.list[indx].ctl_type;
2308	return (3);
2309}
2310
2311/*
2312 * Handle hardware monitoring sensors support
2313 */
2314int
2315sysctl_sensors(char *string, char **bufpp, int mib[], int flags, int *typep)
2316{
2317	char *devname, *typename;
2318	int dev, numt, i;
2319	enum sensor_type type;
2320	struct sensordev snsrdev;
2321	size_t sdlen = sizeof(snsrdev);
2322
2323	if (*bufpp == NULL) {
2324		char buf[SYSCTL_BUFSIZ];
2325
2326		/* scan all sensor devices */
2327		for (dev = 0; ; dev++) {
2328			mib[2] = dev;
2329			if (sysctl(mib, 3, &snsrdev, &sdlen, NULL, 0) == -1) {
2330				if (errno == ENXIO)
2331					continue;
2332				if (errno == ENOENT)
2333					break;
2334			}
2335			snprintf(buf, sizeof(buf), "%s.%s",
2336			    string, snsrdev.xname);
2337			print_sensordev(buf, mib, 3, &snsrdev);
2338		}
2339		return (-1);
2340	}
2341
2342	/*
2343	 * If we get this far, it means that some arguments were
2344	 * provided below hw.sensors tree.
2345	 * The first branch of hw.sensors tree is the device name.
2346	 */
2347	if ((devname = strsep(bufpp, ".")) == NULL) {
2348		warnx("%s: incomplete specification", string);
2349		return (-1);
2350	}
2351	/* convert sensor device string to an integer */
2352	for (dev = 0; ; dev++) {
2353		mib[2] = dev;
2354		if (sysctl(mib, 3, &snsrdev, &sdlen, NULL, 0) == -1) {
2355			if (errno == ENXIO)
2356				continue;
2357			if (errno == ENOENT)
2358				break;
2359		}
2360		if (strcmp(devname, snsrdev.xname) == 0)
2361			break;
2362	}
2363	if (strcmp(devname, snsrdev.xname) != 0) {
2364		warnx("%s: sensor device not found: %s", string, devname);
2365		return (-1);
2366	}
2367	if (*bufpp == NULL) {
2368		/* only device name was provided -- let's print all sensors
2369		 * that are attached to the specified device
2370		 */
2371		print_sensordev(string, mib, 3, &snsrdev);
2372		return (-1);
2373	}
2374
2375	/*
2376	 * At this point we have identified the sensor device,
2377	 * now let's go further and identify sensor type.
2378	 */
2379	if ((typename = strsep(bufpp, ".")) == NULL) {
2380		warnx("%s: incomplete specification", string);
2381		return (-1);
2382	}
2383	numt = -1;
2384	for (i = 0; typename[i] != '\0'; i++)
2385		if (isdigit((unsigned char)typename[i])) {
2386			numt = atoi(&typename[i]);
2387			typename[i] = '\0';
2388			break;
2389		}
2390	for (type = 0; type < SENSOR_MAX_TYPES; type++)
2391		if (strcmp(typename, sensor_type_s[type]) == 0)
2392			break;
2393	if (type == SENSOR_MAX_TYPES) {
2394		warnx("%s: sensor type not recognised: %s", string, typename);
2395		return (-1);
2396	}
2397	mib[3] = type;
2398
2399	/*
2400	 * If no integer was provided after sensor_type, let's
2401	 * print all sensors of the specified type.
2402	 */
2403	if (numt == -1) {
2404		print_sensordev(string, mib, 4, &snsrdev);
2405		return (-1);
2406	}
2407
2408	/*
2409	 * At this point we know that we have received a direct request
2410	 * via command-line for a specific sensor. Let's have the parse()
2411	 * function deal with it further, and report any errors if such
2412	 * sensor node does not exist.
2413	 */
2414	mib[4] = numt;
2415	*typep = CTLTYPE_STRUCT;
2416	return (5);
2417}
2418
2419/*
2420 * Print sensors from the specified device.
2421 */
2422
2423void
2424print_sensordev(char *string, int mib[], u_int mlen, struct sensordev *snsrdev)
2425{
2426	char buf[SYSCTL_BUFSIZ];
2427	enum sensor_type type;
2428
2429	if (mlen == 3) {
2430		for (type = 0; type < SENSOR_MAX_TYPES; type++) {
2431			mib[3] = type;
2432			snprintf(buf, sizeof(buf), "%s.%s",
2433			    string, sensor_type_s[type]);
2434			print_sensordev(buf, mib, mlen+1, snsrdev);
2435		}
2436		return;
2437	}
2438
2439	if (mlen == 4) {
2440		int numt;
2441
2442		type = mib[3];
2443		for (numt = 0; numt < snsrdev->maxnumt[type]; numt++) {
2444			mib[4] = numt;
2445			snprintf(buf, sizeof(buf), "%s%u", string, numt);
2446			print_sensordev(buf, mib, mlen+1, snsrdev);
2447		}
2448		return;
2449	}
2450
2451	if (mlen == 5) {
2452		struct sensor snsr;
2453		size_t slen = sizeof(snsr);
2454
2455		/* this function is only printing sensors in bulk, so we
2456		 * do not return any error messages if the requested sensor
2457		 * is not found by sysctl(3)
2458		 */
2459		if (sysctl(mib, 5, &snsr, &slen, NULL, 0) == -1)
2460			return;
2461
2462		if (slen > 0 && (snsr.flags & SENSOR_FINVALID) == 0) {
2463			if (!nflag)
2464				printf("%s%s", string, equ);
2465			print_sensor(&snsr);
2466			printf("\n");
2467		}
2468		return;
2469	}
2470}
2471
2472void
2473print_sensor(struct sensor *s)
2474{
2475	const char *name;
2476
2477	if (s->flags & SENSOR_FUNKNOWN)
2478		printf("unknown");
2479	else {
2480		switch (s->type) {
2481		case SENSOR_TEMP:
2482			printf("%.2f degC",
2483			    (s->value - 273150000) / 1000000.0);
2484			break;
2485		case SENSOR_FANRPM:
2486			printf("%lld RPM", s->value);
2487			break;
2488		case SENSOR_VOLTS_DC:
2489			printf("%.2f VDC", s->value / 1000000.0);
2490			break;
2491		case SENSOR_VOLTS_AC:
2492			printf("%.2f VAC", s->value / 1000000.0);
2493			break;
2494		case SENSOR_OHMS:
2495			printf("%lld ohm", s->value);
2496			break;
2497		case SENSOR_WATTS:
2498			printf("%.2f W", s->value / 1000000.0);
2499			break;
2500		case SENSOR_AMPS:
2501			printf("%.2f A", s->value / 1000000.0);
2502			break;
2503		case SENSOR_WATTHOUR:
2504			printf("%.2f Wh", s->value / 1000000.0);
2505			break;
2506		case SENSOR_AMPHOUR:
2507			printf("%.2f Ah", s->value / 1000000.0);
2508			break;
2509		case SENSOR_INDICATOR:
2510			printf("%s", s->value ? "On" : "Off");
2511			break;
2512		case SENSOR_INTEGER:
2513			printf("%lld", s->value);
2514			break;
2515		case SENSOR_PERCENT:
2516			printf("%.2f%%", s->value / 1000.0);
2517			break;
2518		case SENSOR_LUX:
2519			printf("%.2f lx", s->value / 1000000.0);
2520			break;
2521		case SENSOR_DRIVE:
2522			switch (s->value) {
2523			case SENSOR_DRIVE_EMPTY:
2524				name = "empty";
2525				break;
2526			case SENSOR_DRIVE_READY:
2527				name = "ready";
2528				break;
2529			case SENSOR_DRIVE_POWERUP:
2530				name = "powering up";
2531				break;
2532			case SENSOR_DRIVE_ONLINE:
2533				name = "online";
2534				break;
2535			case SENSOR_DRIVE_IDLE:
2536				name = "idle";
2537				break;
2538			case SENSOR_DRIVE_ACTIVE:
2539				name = "active";
2540				break;
2541			case SENSOR_DRIVE_REBUILD:
2542				name = "rebuilding";
2543				break;
2544			case SENSOR_DRIVE_POWERDOWN:
2545				name = "powering down";
2546				break;
2547			case SENSOR_DRIVE_FAIL:
2548				name = "failed";
2549				break;
2550			case SENSOR_DRIVE_PFAIL:
2551				name = "degraded";
2552				break;
2553			default:
2554				name = "unknown";
2555				break;
2556			}
2557			printf(name);
2558			break;
2559		case SENSOR_TIMEDELTA:
2560			printf("%.6f secs", s->value / 1000000000.0);
2561			break;
2562		case SENSOR_HUMIDITY:
2563			printf("%.2f%%", s->value / 1000.0);
2564			break;
2565		case SENSOR_FREQ:
2566			printf("%.2f Hz", s->value / 1000000.0);
2567			break;
2568		case SENSOR_ANGLE:
2569			printf("%3.4f degrees", s->value / 1000000.0);
2570			break;
2571		case SENSOR_DISTANCE:
2572			printf("%.2f mm", s->value / 1000.0);
2573			break;
2574		case SENSOR_PRESSURE:
2575			printf("%.2f Pa", s->value / 1000.0);
2576			break;
2577		case SENSOR_ACCEL:
2578			printf("%2.4f m/s^2", s->value / 1000000.0);
2579			break;
2580		default:
2581			printf("unknown");
2582		}
2583	}
2584
2585	if (s->desc[0] != '\0')
2586		printf(" (%s)", s->desc);
2587
2588	switch (s->status) {
2589	case SENSOR_S_UNSPEC:
2590		break;
2591	case SENSOR_S_OK:
2592		printf(", OK");
2593		break;
2594	case SENSOR_S_WARN:
2595		printf(", WARNING");
2596		break;
2597	case SENSOR_S_CRIT:
2598		printf(", CRITICAL");
2599		break;
2600	case SENSOR_S_UNKNOWN:
2601		printf(", UNKNOWN");
2602		break;
2603	}
2604
2605	if (s->tv.tv_sec) {
2606		time_t t = s->tv.tv_sec;
2607		char ct[26];
2608
2609		ctime_r(&t, ct);
2610		ct[19] = '\0';
2611		printf(", %s.%03ld", ct, s->tv.tv_usec / 1000);
2612	}
2613}
2614
2615struct emulname {
2616	char *name;
2617	int index;
2618} *emul_names;
2619int	emul_num, nemuls;
2620int	emul_init(void);
2621
2622int
2623sysctl_emul(char *string, char *newval, int flags)
2624{
2625	int mib[4], enabled, i, old, print, found = 0;
2626	char *head, *target;
2627	size_t len;
2628
2629	if (emul_init() == -1) {
2630		warnx("emul_init: out of memory");
2631		return (1);
2632	}
2633
2634	mib[0] = CTL_KERN;
2635	mib[1] = KERN_EMUL;
2636	mib[3] = KERN_EMUL_ENABLED;
2637	head = "kern.emul.";
2638
2639	if (aflag || strcmp(string, "kern.emul") == 0) {
2640		if (newval) {
2641			warnx("%s: specification is incomplete", string);
2642			return (1);
2643		}
2644		if (nflag)
2645			printf("%d\n", nemuls);
2646		else
2647			printf("%snemuls%s%d\n", head, equ, nemuls);
2648		for (i = 0; i < emul_num; i++) {
2649			if (emul_names[i].name == NULL)
2650				break;
2651			if (i > 0 && strcmp(emul_names[i].name,
2652			    emul_names[i-1].name) == 0)
2653				continue;
2654			mib[2] = emul_names[i].index;
2655			len = sizeof(int);
2656			if (sysctl(mib, 4, &enabled, &len, NULL, 0) == -1) {
2657				warn("%s", string);
2658				continue;
2659			}
2660			if (nflag)
2661				printf("%d\n", enabled);
2662			else
2663				printf("%s%s%s%d\n", head, emul_names[i].name,
2664				    equ, enabled);
2665		}
2666		return (0);
2667	}
2668	/* User specified a third level name */
2669	target = strrchr(string, '.');
2670	target++;
2671	if (strcmp(target, "nemuls") == 0) {
2672		if (newval) {
2673			warnx("Operation not permitted");
2674			return (1);
2675		}
2676		if (nflag)
2677			printf("%d\n", nemuls);
2678		else
2679			printf("%snemuls = %d\n", head, nemuls);
2680		return (0);
2681	}
2682	print = 1;
2683	for (i = 0; i < emul_num; i++) {
2684		if (!emul_names[i].name || (strcmp(target, emul_names[i].name)))
2685			continue;
2686		found = 1;
2687		mib[2] = emul_names[i].index;
2688		len = sizeof(int);
2689		if (newval) {
2690			enabled = atoi(newval);
2691			if (sysctl(mib, 4, &old, &len, &enabled, len) == -1) {
2692				warn("%s", string);
2693				print = 0;
2694				continue;
2695			}
2696			if (print) {
2697				if (nflag)
2698					printf("%d\n", enabled);
2699				else
2700					printf("%s%s: %d -> %d\n", head,
2701					    target, old, enabled);
2702			}
2703		} else {
2704			if (sysctl(mib, 4, &enabled, &len, NULL, 0) == -1) {
2705				warn("%s", string);
2706				continue;
2707			}
2708			if (print) {
2709				if (nflag)
2710					printf("%d\n", enabled);
2711				else
2712					printf("%s%s = %d\n", head, target,
2713					    enabled);
2714			}
2715		}
2716		print = 0;
2717	}
2718	if (!found)
2719		warnx("third level name %s in kern.emul is invalid",
2720		    string);
2721	return (0);
2722
2723
2724}
2725
2726static int
2727emulcmp(const void *m, const void *n)
2728{
2729	const struct emulname *a = m, *b = n;
2730
2731	if (!a || !a->name)
2732		return 1;
2733	if (!b || !b->name)
2734		return -1;
2735	return (strcmp(a->name, b->name));
2736}
2737
2738int
2739emul_init(void)
2740{
2741	static int done;
2742	char string[16];
2743	int mib[4], i;
2744	size_t len;
2745
2746	if (done)
2747		return (0);
2748	done = 1;
2749
2750	mib[0] = CTL_KERN;
2751	mib[1] = KERN_EMUL;
2752	mib[2] = KERN_EMUL_NUM;
2753	len = sizeof(int);
2754	if (sysctl(mib, 3, &emul_num, &len, NULL, 0) == -1)
2755		return (-1);
2756
2757	emul_names = calloc(emul_num, sizeof(*emul_names));
2758	if (emul_names == NULL)
2759		return (-1);
2760
2761	nemuls = emul_num;
2762	for (i = 0; i < emul_num; i++) {
2763		emul_names[i].index = mib[2] = i + 1;
2764		mib[3] = KERN_EMUL_NAME;
2765		len = sizeof(string);
2766		if (sysctl(mib, 4, string, &len, NULL, 0) == -1)
2767			continue;
2768		if (strcmp(string, "native") == 0)
2769			continue;
2770		emul_names[i].name = strdup(string);
2771		if (emul_names[i].name == NULL) {
2772			free(emul_names);
2773			return (-1);
2774		}
2775	}
2776	qsort(emul_names, nemuls, sizeof(*emul_names), emulcmp);
2777	for (i = 0; i < emul_num; i++) {
2778		if (!emul_names[i].name || (i > 0 &&
2779		    strcmp(emul_names[i].name, emul_names[i - 1].name) == 0))
2780			nemuls--;
2781	}
2782	return (0);
2783}
2784
2785/*
2786 * Scan a list of names searching for a particular name.
2787 */
2788int
2789findname(char *string, char *level, char **bufp, struct list *namelist)
2790{
2791	char *name;
2792	int i;
2793
2794	if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
2795		warnx("%s: incomplete specification", string);
2796		return (-1);
2797	}
2798	for (i = 0; i < namelist->size; i++)
2799		if (namelist->list[i].ctl_name != NULL &&
2800		    strcmp(name, namelist->list[i].ctl_name) == 0)
2801			break;
2802	if (i == namelist->size) {
2803		warnx("%s level name %s in %s is invalid", level, name, string);
2804		return (-1);
2805	}
2806	return (i);
2807}
2808
2809void
2810usage(void)
2811{
2812
2813	(void)fprintf(stderr,
2814	    "usage: sysctl [-Aan]\n"
2815	    "       sysctl [-n] name ...\n"
2816	    "       sysctl [-nq] name=value ...\n");
2817	exit(1);
2818}
2819