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