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