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