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