sysctl.c revision 1.178
1/*	$OpenBSD: sysctl.c,v 1.178 2011/09/16 15:44:31 yuo 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/stat.h>
37#include <sys/sem.h>
38#include <sys/shm.h>
39#include <sys/sysctl.h>
40#include <sys/socket.h>
41#include <sys/malloc.h>
42#include <sys/dkstat.h>
43#include <sys/uio.h>
44#include <sys/tty.h>
45#include <sys/namei.h>
46#include <sys/sensors.h>
47#include <machine/cpu.h>
48#include <net/route.h>
49#include <net/if.h>
50
51#include <netinet/in.h>
52#include <netinet/in_systm.h>
53#include <netinet/ip.h>
54#include <netinet/in_pcb.h>
55#include <netinet/ip_icmp.h>
56#include <netinet/ip_ipip.h>
57#include <netinet/ip_ether.h>
58#include <netinet/ip_ah.h>
59#include <netinet/ip_esp.h>
60#include <netinet/icmp_var.h>
61#include <netinet/igmp_var.h>
62#include <netinet/ip_var.h>
63#include <netinet/udp.h>
64#include <netinet/udp_var.h>
65#include <netinet/tcp.h>
66#include <netinet/tcp_timer.h>
67#include <netinet/tcp_var.h>
68#include <netinet/ip_gre.h>
69#include <netinet/ip_ipcomp.h>
70#include <netinet/ip_carp.h>
71#include <netinet/ip_divert.h>
72
73#include <net/pfvar.h>
74#include <net/if_pfsync.h>
75#include <net/pipex.h>
76
77#ifdef INET6
78#include <netinet/ip6.h>
79#include <netinet/icmp6.h>
80#include <netinet6/ip6_var.h>
81#include <netinet6/pim6_var.h>
82#include <netinet6/ip6_divert.h>
83#endif
84
85#include <netmpls/mpls.h>
86
87#include <uvm/uvm_swap_encrypt.h>
88
89#include <ufs/ufs/quota.h>
90#include <ufs/ufs/inode.h>
91#include <ufs/ffs/fs.h>
92#include <ufs/ffs/ffs_extern.h>
93
94#include <nfs/rpcv2.h>
95#include <nfs/nfsproto.h>
96#include <nfs/nfs.h>
97
98#include <ddb/db_var.h>
99#include <dev/rndvar.h>
100
101#include <err.h>
102#include <errno.h>
103#include <stdio.h>
104#include <stdlib.h>
105#include <string.h>
106#include <ctype.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 username[] = CTL_USER_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	{ username, USER_MAXID },	/* CTL_USER_NAMES */
158	{ ddbname, DBCTL_MAXID },	/* CTL_DDB_NAMES */
159	{ 0, 0 },			/* CTL_VFS */
160};
161
162int	Aflag, aflag, nflag, qflag;
163
164/*
165 * Variables requiring special processing.
166 */
167#define	CLOCK		0x00000001
168#define	BOOTTIME	0x00000002
169#define	CHRDEV		0x00000004
170#define	BLKDEV		0x00000008
171#define	RNDSTATS	0x00000010
172#define	BADDYNAMIC	0x00000020
173#define	BIOSGEO		0x00000040
174#define	BIOSDEV		0x00000080
175#define	MAJ2DEV		0x00000100
176#define	UNSIGNED	0x00000200
177#define	KMEMBUCKETS	0x00000400
178#define	LONGARRAY	0x00000800
179#define	KMEMSTATS	0x00001000
180#define	SENSORS		0x00002000
181
182/* prototypes */
183void debuginit(void);
184void listall(char *, struct list *);
185void parse(char *, int);
186void parse_baddynamic(int *, size_t, char *, void **, size_t *, int, int);
187void usage(void);
188int findname(char *, char *, char **, struct list *);
189int sysctl_inet(char *, char **, int *, int, int *);
190#ifdef INET6
191int sysctl_inet6(char *, char **, int *, int, int *);
192#endif
193int sysctl_bpf(char *, char **, int *, int, int *);
194int sysctl_mpls(char *, char **, int *, int, int *);
195int sysctl_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_USER:
683	case CTL_DDB:
684		break;
685
686	default:
687		warnx("illegal top level value: %d", mib[0]);
688		return;
689
690	}
691	if (bufp) {
692		warnx("name %s in %s is unknown", bufp, string);
693		return;
694	}
695	if (newsize > 0) {
696		switch (type) {
697		case CTLTYPE_INT:
698			errno = 0;
699			if (special & UNSIGNED)
700				intval = strtoul(newval, &cp, 10);
701			else
702				intval = strtol(newval, &cp, 10);
703			if (*cp != '\0') {
704				warnx("%s: illegal value: %s", string,
705				    (char *)newval);
706				return;
707			}
708			if (errno == ERANGE) {
709				warnx("%s: value %s out of range", string,
710				    (char *)newval);
711				return;
712			}
713			newval = &intval;
714			newsize = sizeof(intval);
715			break;
716
717		case CTLTYPE_QUAD:
718			/* XXX - assumes sizeof(long long) == sizeof(quad_t) */
719			(void)sscanf(newval, "%lld", (long long *)&quadval);
720			newval = &quadval;
721			newsize = sizeof(quadval);
722			break;
723		}
724	}
725	size = SYSCTL_BUFSIZ;
726	if (sysctl(mib, len, buf, &size, newval, newsize) == -1) {
727		if (flags == 0)
728			return;
729		switch (errno) {
730		case EOPNOTSUPP:
731			warnx("%s: value is not available", string);
732			return;
733		case ENOTDIR:
734			warnx("%s: specification is incomplete", string);
735			return;
736		case ENOMEM:
737			warnx("%s: type is unknown to this program", string);
738			return;
739		case ENXIO:
740			if (special & BIOSGEO)
741				return;
742		default:
743			warn("%s", string);
744			return;
745		}
746	}
747	if (special & KMEMBUCKETS) {
748		struct kmembuckets *kb = (struct kmembuckets *)buf;
749		if (!nflag)
750			(void)printf("%s%s", string, equ);
751		printf("(");
752		printf("calls = %llu ", (long long)kb->kb_calls);
753		printf("total_allocated = %llu ", (long long)kb->kb_total);
754		printf("total_free = %lld ", (long long)kb->kb_totalfree);
755		printf("elements = %lld ", (long long)kb->kb_elmpercl);
756		printf("high watermark = %lld ", (long long)kb->kb_highwat);
757		printf("could_free = %lld", (long long)kb->kb_couldfree);
758		printf(")\n");
759		return;
760	}
761	if (special & KMEMSTATS) {
762		struct kmemstats *km = (struct kmemstats *)buf;
763		int j, first = 1;
764
765		if (!nflag)
766			(void)printf("%s%s", string, equ);
767		(void)printf("(inuse = %ld, calls = %ld, memuse = %ldK, "
768		    "limblocks = %d, mapblocks = %d, maxused = %ldK, "
769		    "limit = %ldK, spare = %ld, sizes = (",
770		    km->ks_inuse, km->ks_calls,
771		    (km->ks_memuse + 1023) / 1024, km->ks_limblocks,
772		    km->ks_mapblocks, (km->ks_maxused + 1023) / 1024,
773		    (km->ks_limit + 1023) / 1024, km->ks_spare);
774		for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
775			if ((km->ks_size & j ) == 0)
776				continue;
777			if (first)
778				(void)printf("%d", j);
779			else
780				(void)printf(",%d", j);
781			first = 0;
782		}
783		if (first)
784			(void)printf("none");
785		(void)printf("))\n");
786		return;
787	}
788	if (special & CLOCK) {
789		struct clockinfo *clkp = (struct clockinfo *)buf;
790
791		if (!nflag)
792			(void)printf("%s%s", string, equ);
793		(void)printf(
794		    "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n",
795		    clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz);
796		return;
797	}
798	if (special & BOOTTIME) {
799		struct timeval *btp = (struct timeval *)buf;
800		time_t boottime;
801
802		if (!nflag) {
803			boottime = btp->tv_sec;
804			(void)printf("%s%s%s", string, equ, ctime(&boottime));
805		} else
806			(void)printf("%ld\n", btp->tv_sec);
807		return;
808	}
809	if (special & BLKDEV) {
810		dev_t dev = *(dev_t *)buf;
811
812		if (!nflag)
813			(void)printf("%s%s%s\n", string, equ,
814			    devname(dev, S_IFBLK));
815		else
816			(void)printf("0x%x\n", dev);
817		return;
818	}
819	if (special & CHRDEV) {
820		dev_t dev = *(dev_t *)buf;
821
822		if (!nflag)
823			(void)printf("%s%s%s\n", string, equ,
824			    devname(dev, S_IFCHR));
825		else
826			(void)printf("0x%x\n", dev);
827		return;
828	}
829#ifdef CPU_BIOS
830	if (special & BIOSGEO) {
831		bios_diskinfo_t *pdi = (bios_diskinfo_t *)buf;
832
833		if (!nflag)
834			(void)printf("%s%s", string, equ);
835		(void)printf("bootdev = 0x%x, "
836		    "cylinders = %u, heads = %u, sectors = %u\n",
837		    pdi->bsd_dev, pdi->bios_cylinders,
838		    pdi->bios_heads, pdi->bios_sectors);
839		return;
840	}
841	if (special & BIOSDEV) {
842		int dev = *(int*)buf;
843
844		if (!nflag)
845			(void)printf("%s%s", string, equ);
846		(void) printf("0x%02x\n", dev);
847		return;
848	}
849#endif
850	if (special & UNSIGNED) {
851		if (newsize == 0) {
852			if (!nflag)
853				(void)printf("%s%s", string, equ);
854			(void)printf("%u\n", *(u_int *)buf);
855		} else {
856			if (!qflag) {
857				if (!nflag)
858					(void)printf("%s: %u -> ", string,
859					    *(u_int *)buf);
860				(void)printf("%u\n", *(u_int *)newval);
861			}
862		}
863		return;
864	}
865	if (special & RNDSTATS) {
866		struct rndstats *rndstats = (struct rndstats *)buf;
867		int i;
868
869		if (!nflag)
870			(void)printf("%s%s", string, equ);
871		(void)printf(
872		"%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
873		    (unsigned long long)rndstats->rnd_total,
874		    (unsigned long long)rndstats->rnd_used,
875		    (unsigned long long)rndstats->rnd_reads,
876		    (unsigned long long)rndstats->arc4_reads,
877		    (unsigned long long)rndstats->arc4_nstirs,
878		    (unsigned long long)rndstats->arc4_stirs,
879		    (unsigned long long)rndstats->rnd_pad[0],
880		    (unsigned long long)rndstats->rnd_pad[1],
881		    (unsigned long long)rndstats->rnd_pad[2],
882		    (unsigned long long)rndstats->rnd_pad[3],
883		    (unsigned long long)rndstats->rnd_pad[4],
884		    (unsigned long long)rndstats->rnd_waits,
885		    (unsigned long long)rndstats->rnd_enqs,
886		    (unsigned long long)rndstats->rnd_deqs,
887		    (unsigned long long)rndstats->rnd_drops,
888		    (unsigned long long)rndstats->rnd_drople);
889		for (i = 0; i < sizeof(rndstats->rnd_ed)/sizeof(rndstats->rnd_ed[0]);
890		    i++)
891			(void)printf(" %llu", (unsigned long long)rndstats->rnd_ed[i]);
892		for (i = 0; i < sizeof(rndstats->rnd_sc)/sizeof(rndstats->rnd_sc[0]);
893		    i++)
894			(void)printf(" %llu", (unsigned long long)rndstats->rnd_sc[i]);
895		for (i = 0; i < sizeof(rndstats->rnd_sb)/sizeof(rndstats->rnd_sb[0]);
896		    i++)
897			(void)printf(" %llu", (unsigned long long)rndstats->rnd_sb[i]);
898		printf("\n");
899		return;
900	}
901	if (special & BADDYNAMIC) {
902		u_int port, lastport;
903		u_int32_t *baddynamic = (u_int32_t *)buf;
904
905		if (!qflag) {
906			if (!nflag)
907				(void)printf("%s%s", string,
908				    newsize ? ": " : equ);
909			lastport = 0;
910			for (port = 0; port < 65536; port++)
911				if (DP_ISSET(baddynamic, port)) {
912					(void)printf("%s%u",
913					    lastport ? "," : "", port);
914					lastport = port;
915				}
916			if (newsize != 0) {
917				if (!nflag)
918					fputs(" -> ", stdout);
919				baddynamic = (u_int32_t *)newval;
920				lastport = 0;
921				for (port = 0; port < 65536; port++)
922					if (DP_ISSET(baddynamic, port)) {
923						(void)printf("%s%u",
924						    lastport ? "," : "", port);
925						lastport = port;
926					}
927			}
928			(void)putchar('\n');
929		}
930		return;
931	}
932	if (special & LONGARRAY) {
933		long *la = (long *)buf;
934		if (!nflag)
935			printf("%s%s", string, equ);
936		while (lal--)
937			printf("%ld%s", *la++, lal? ",":"");
938		putchar('\n');
939		return;
940	}
941	if (special & SENSORS) {
942		struct sensor *s = (struct sensor *)buf;
943
944		if (size > 0 && (s->flags & SENSOR_FINVALID) == 0) {
945			if (!nflag)
946				printf("%s%s", string, equ);
947			print_sensor(s);
948			printf("\n");
949		}
950		return;
951	}
952	switch (type) {
953	case CTLTYPE_INT:
954		if (newsize == 0) {
955			if (!nflag)
956				(void)printf("%s%s", string, equ);
957			(void)printf("%d\n", *(int *)buf);
958		} else {
959			if (!qflag) {
960				if (!nflag)
961					(void)printf("%s: %d -> ", string,
962					    *(int *)buf);
963				(void)printf("%d\n", *(int *)newval);
964			}
965		}
966		return;
967
968	case CTLTYPE_STRING:
969		if (newval == NULL) {
970			if (!nflag)
971				(void)printf("%s%s", string, equ);
972			(void)puts(buf);
973		} else {
974			if (!qflag) {
975				if (!nflag)
976					(void)printf("%s: %s -> ", string, buf);
977				(void)puts((char *)newval);
978			}
979		}
980		return;
981
982	case CTLTYPE_QUAD:
983		if (newsize == 0) {
984			long long tmp = *(quad_t *)buf;
985
986			if (!nflag)
987				(void)printf("%s%s", string, equ);
988			(void)printf("%lld\n", tmp);
989		} else {
990			long long tmp = *(quad_t *)buf;
991
992			if (!qflag) {
993				if (!nflag)
994					(void)printf("%s: %lld -> ",
995					    string, tmp);
996				tmp = *(quad_t *)newval;
997				(void)printf("%qd\n", tmp);
998			}
999		}
1000		return;
1001
1002	case CTLTYPE_STRUCT:
1003		warnx("%s: unknown structure returned", string);
1004		return;
1005
1006	default:
1007	case CTLTYPE_NODE:
1008		warnx("%s: unknown type returned", string);
1009		return;
1010	}
1011}
1012
1013static void
1014parse_ports(char *portspec, int *port, int *high_port)
1015{
1016	char *dash;
1017	const char *errstr;
1018
1019	if ((dash = strchr(portspec, '-')) != NULL)
1020		*dash++ = '\0';
1021	*port = strtonum(portspec, 0, 65535, &errstr);
1022	if (errstr != NULL)
1023		errx(1, "port is %s: %s", errstr, portspec);
1024	if (dash != NULL) {
1025		*high_port = strtonum(dash, 0, 65535, &errstr);
1026		if (errstr != NULL)
1027			errx(1, "high port is %s: %s", errstr, dash);
1028		if (*high_port < *port)
1029			errx(1, "high port %d is lower than %d",
1030			    *high_port, *port);
1031	} else
1032		*high_port = *port;
1033}
1034
1035void
1036parse_baddynamic(int mib[], size_t len, char *string, void **newvalp,
1037    size_t *newsizep, int flags, int nflag)
1038{
1039	static u_int32_t newbaddynamic[DP_MAPSIZE];
1040	int port, high_port, baddynamic_loaded = 0, full_list_set = 0;
1041	size_t size;
1042	char action, *cp;
1043
1044	while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) {
1045		if (*cp == '+' || *cp == '-') {
1046			if (full_list_set)
1047				errx(1, "cannot mix +/- with full list");
1048			action = *cp++;
1049			if (!baddynamic_loaded) {
1050				size = sizeof(newbaddynamic);
1051				if (sysctl(mib, len, newbaddynamic,
1052				    &size, 0, 0) == -1) {
1053					if (flags == 0)
1054						return;
1055					if (!nflag)
1056						printf("%s: ", string);
1057					puts("kernel does contain bad dynamic "
1058					    "port tables");
1059					return;
1060				}
1061				baddynamic_loaded = 1;
1062			}
1063			parse_ports(cp, &port, &high_port);
1064			for (; port <= high_port; port++) {
1065				if (action == '+')
1066					DP_SET(newbaddynamic, port);
1067				else
1068					DP_CLR(newbaddynamic, port);
1069			}
1070		} else {
1071			if (baddynamic_loaded)
1072				errx(1, "cannot mix +/- with full list");
1073			if (!full_list_set) {
1074				bzero(newbaddynamic, sizeof(newbaddynamic));
1075				full_list_set = 1;
1076			}
1077			parse_ports(cp, &port, &high_port);
1078			for (; port <= high_port; port++)
1079				DP_SET(newbaddynamic, port);
1080		}
1081	}
1082	*newvalp = (void *)newbaddynamic;
1083	*newsizep = sizeof(newbaddynamic);
1084}
1085
1086/*
1087 * Initialize the set of debugging names
1088 */
1089void
1090debuginit(void)
1091{
1092	int mib[3], loc, i;
1093	size_t size;
1094
1095	if (secondlevel[CTL_DEBUG].list != 0)
1096		return;
1097	secondlevel[CTL_DEBUG].list = debugname;
1098	mib[0] = CTL_DEBUG;
1099	mib[2] = CTL_DEBUG_NAME;
1100	for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) {
1101		mib[1] = i;
1102		size = BUFSIZ - loc;
1103		if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
1104			continue;
1105		debugname[i].ctl_name = &names[loc];
1106		debugname[i].ctl_type = CTLTYPE_INT;
1107		loc += size;
1108	}
1109	lastused = loc;
1110}
1111
1112struct ctlname vfsgennames[] = CTL_VFSGENCTL_NAMES;
1113struct ctlname ffsname[] = FFS_NAMES;
1114struct ctlname nfsname[] = FS_NFS_NAMES;
1115struct list *vfsvars;
1116int *vfs_typenums;
1117
1118/*
1119 * Initialize the set of filesystem names
1120 */
1121void
1122vfsinit(void)
1123{
1124	int mib[4], maxtypenum, cnt, loc, size;
1125	struct vfsconf vfc;
1126	size_t buflen;
1127
1128	if (secondlevel[CTL_VFS].list != 0)
1129		return;
1130	mib[0] = CTL_VFS;
1131	mib[1] = VFS_GENERIC;
1132	mib[2] = VFS_MAXTYPENUM;
1133	buflen = 4;
1134	if (sysctl(mib, 3, &maxtypenum, &buflen, (void *)0, (size_t)0) < 0)
1135		return;
1136	maxtypenum++;	/* + generic */
1137	if ((vfs_typenums = calloc(maxtypenum, sizeof(int))) == NULL)
1138		return;
1139	if ((vfsvars = calloc(maxtypenum, sizeof(*vfsvars))) == NULL) {
1140		free(vfs_typenums);
1141		return;
1142	}
1143	if ((vfsname = calloc(maxtypenum, sizeof(*vfsname))) == NULL) {
1144		free(vfs_typenums);
1145		free(vfsvars);
1146		return;
1147	}
1148	mib[2] = VFS_CONF;
1149	buflen = sizeof vfc;
1150	for (loc = lastused, cnt = 1; cnt < maxtypenum; cnt++) {
1151		mib[3] = cnt - 1;
1152		if (sysctl(mib, 4, &vfc, &buflen, (void *)0, (size_t)0) < 0) {
1153			if (errno == EOPNOTSUPP)
1154				continue;
1155			warn("vfsinit");
1156			free(vfsname);
1157			free(vfsvars);
1158			free(vfs_typenums);
1159			return;
1160		}
1161		if (!strcmp(vfc.vfc_name, MOUNT_FFS)) {
1162			vfsvars[cnt].list = ffsname;
1163			vfsvars[cnt].size = FFS_MAXID;
1164		}
1165		if (!strcmp(vfc.vfc_name, MOUNT_NFS)) {
1166			vfsvars[cnt].list = nfsname;
1167			vfsvars[cnt].size = NFS_MAXID;
1168		}
1169		vfs_typenums[cnt] = vfc.vfc_typenum;
1170		strlcat(&names[loc], vfc.vfc_name, sizeof names - loc);
1171		vfsname[cnt].ctl_name = &names[loc];
1172		vfsname[cnt].ctl_type = CTLTYPE_NODE;
1173		size = strlen(vfc.vfc_name) + 1;
1174		loc += size;
1175	}
1176	lastused = loc;
1177
1178	vfsname[0].ctl_name = "mounts";
1179	vfsname[0].ctl_type = CTLTYPE_NODE;
1180	vfsvars[0].list = vfsname + 1;
1181	vfsvars[0].size = maxtypenum - 1;
1182
1183	secondlevel[CTL_VFS].list = vfsname;
1184	secondlevel[CTL_VFS].size = maxtypenum;
1185	return;
1186}
1187
1188int
1189sysctl_vfsgen(char *string, char **bufpp, int mib[], int flags, int *typep)
1190{
1191	int indx;
1192	size_t size;
1193	struct vfsconf vfc;
1194
1195	if (*bufpp == NULL) {
1196		listall(string, vfsvars);
1197		return (-1);
1198	}
1199
1200	if ((indx = findname(string, "third", bufpp, vfsvars)) == -1)
1201		return (-1);
1202
1203	mib[1] = VFS_GENERIC;
1204	mib[2] = VFS_CONF;
1205	mib[3] = indx;
1206	size = sizeof vfc;
1207	if (sysctl(mib, 4, &vfc, &size, (void *)0, (size_t)0) < 0) {
1208		if (errno != EOPNOTSUPP)
1209			warn("vfs print");
1210		return -1;
1211	}
1212	if (flags == 0 && vfc.vfc_refcount == 0)
1213		return -1;
1214	if (!nflag)
1215		fprintf(stdout, "%s has %d mounted instance%s\n",
1216		    string, vfc.vfc_refcount,
1217		    vfc.vfc_refcount != 1 ? "s" : "");
1218	else
1219		fprintf(stdout, "%d\n", vfc.vfc_refcount);
1220
1221	return -1;
1222}
1223
1224int
1225sysctl_vfs(char *string, char **bufpp, int mib[], int flags, int *typep)
1226{
1227	struct list *lp = &vfsvars[mib[1]];
1228	int indx;
1229
1230	if (lp->list == NULL) {
1231		if (flags)
1232			warnx("No variables defined for file system %s", string);
1233		return (-1);
1234	}
1235	if (*bufpp == NULL) {
1236		listall(string, lp);
1237		return (-1);
1238	}
1239	if ((indx = findname(string, "third", bufpp, lp)) == -1)
1240		return (-1);
1241
1242	mib[1] = vfs_typenums[mib[1]];
1243	mib[2] = indx;
1244	*typep = lp->list[indx].ctl_type;
1245	return (3);
1246}
1247
1248struct ctlname posixname[] = CTL_FS_POSIX_NAMES;
1249struct list fslist = { posixname, FS_POSIX_MAXID };
1250
1251/*
1252 * handle file system requests
1253 */
1254int
1255sysctl_fs(char *string, char **bufpp, int mib[], int flags, int *typep)
1256{
1257	int indx;
1258
1259	if (*bufpp == NULL) {
1260		listall(string, &fslist);
1261		return (-1);
1262	}
1263	if ((indx = findname(string, "third", bufpp, &fslist)) == -1)
1264		return (-1);
1265	mib[2] = indx;
1266	*typep = fslist.list[indx].ctl_type;
1267	return (3);
1268}
1269
1270#ifdef CPU_BIOS
1271struct ctlname biosname[] = CTL_BIOS_NAMES;
1272struct list bioslist = { biosname, BIOS_MAXID };
1273
1274/*
1275 * handle BIOS requests
1276 */
1277int
1278sysctl_bios(char *string, char **bufpp, int mib[], int flags, int *typep)
1279{
1280	char *name;
1281	int indx;
1282
1283	if (*bufpp == NULL) {
1284		listall(string, &bioslist);
1285		return (-1);
1286	}
1287	if ((indx = findname(string, "third", bufpp, &bioslist)) == -1)
1288		return (-1);
1289	mib[2] = indx;
1290	if (indx == BIOS_DISKINFO) {
1291		if (*bufpp == NULL) {
1292			char name[BUFSIZ];
1293
1294			/* scan all the bios devices */
1295			for (indx = 0; indx < 256; indx++) {
1296				snprintf(name, sizeof(name), "%s.%u",
1297				    string, indx);
1298				parse(name, 1);
1299			}
1300			return (-1);
1301		}
1302		if ((name = strsep(bufpp, ".")) == NULL) {
1303			warnx("%s: incomplete specification", string);
1304			return (-1);
1305		}
1306		mib[3] = atoi(name);
1307		*typep = CTLTYPE_STRUCT;
1308		return (4);
1309	} else {
1310		*typep = bioslist.list[indx].ctl_type;
1311		return (3);
1312	}
1313}
1314#endif
1315
1316struct ctlname swpencname[] = CTL_SWPENC_NAMES;
1317struct list swpenclist = { swpencname, SWPENC_MAXID };
1318
1319/*
1320 * handle swap encrypt requests
1321 */
1322int
1323sysctl_swpenc(char *string, char **bufpp, int mib[], int flags, int *typep)
1324{
1325	int indx;
1326
1327	if (*bufpp == NULL) {
1328		listall(string, &swpenclist);
1329		return (-1);
1330	}
1331	if ((indx = findname(string, "third", bufpp, &swpenclist)) == -1)
1332		return (-1);
1333	mib[2] = indx;
1334	*typep = swpenclist.list[indx].ctl_type;
1335	return (3);
1336}
1337
1338struct ctlname inetname[] = CTL_IPPROTO_NAMES;
1339struct ctlname ipname[] = IPCTL_NAMES;
1340struct ctlname icmpname[] = ICMPCTL_NAMES;
1341struct ctlname igmpname[] = IGMPCTL_NAMES;
1342struct ctlname ipipname[] = IPIPCTL_NAMES;
1343struct ctlname tcpname[] = TCPCTL_NAMES;
1344struct ctlname udpname[] = UDPCTL_NAMES;
1345struct ctlname espname[] = ESPCTL_NAMES;
1346struct ctlname ahname[] = AHCTL_NAMES;
1347struct ctlname etheripname[] = ETHERIPCTL_NAMES;
1348struct ctlname grename[] = GRECTL_NAMES;
1349struct ctlname mobileipname[] = MOBILEIPCTL_NAMES;
1350struct ctlname ipcompname[] = IPCOMPCTL_NAMES;
1351struct ctlname carpname[] = CARPCTL_NAMES;
1352struct ctlname pfsyncname[] = PFSYNCCTL_NAMES;
1353struct ctlname divertname[] = DIVERTCTL_NAMES;
1354struct ctlname bpfname[] = CTL_NET_BPF_NAMES;
1355struct ctlname ifqname[] = CTL_IFQ_NAMES;
1356struct ctlname pipexname[] = PIPEXCTL_NAMES;
1357struct list inetlist = { inetname, IPPROTO_MAXID };
1358struct list inetvars[] = {
1359	{ ipname, IPCTL_MAXID },	/* ip */
1360	{ icmpname, ICMPCTL_MAXID },	/* icmp */
1361	{ igmpname, IGMPCTL_MAXID },	/* igmp */
1362	{ 0, 0 },			/* ggmp */
1363	{ ipipname, IPIPCTL_MAXID },	/* ipencap */
1364	{ 0, 0 },
1365	{ tcpname, TCPCTL_MAXID },	/* tcp */
1366	{ 0, 0 },
1367	{ 0, 0 },			/* egp */
1368	{ 0, 0 },
1369	{ 0, 0 },
1370	{ 0, 0 },
1371	{ 0, 0 },			/* pup */
1372	{ 0, 0 },
1373	{ 0, 0 },
1374	{ 0, 0 },
1375	{ 0, 0 },
1376	{ udpname, UDPCTL_MAXID },	/* udp */
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	{ 0, 0 },
1405	{ 0, 0 },
1406	{ grename, GRECTL_MAXID },	/* gre */
1407	{ 0, 0 },
1408	{ 0, 0 },
1409	{ espname, ESPCTL_MAXID },	/* esp */
1410	{ ahname, AHCTL_MAXID },	/* ah */
1411	{ 0, 0 },
1412	{ 0, 0 },
1413	{ 0, 0 },
1414	{ mobileipname, MOBILEIPCTL_MAXID }, /* mobileip */
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	{ 0, 0 },
1455	{ 0, 0 },
1456	{ etheripname, ETHERIPCTL_MAXID },
1457	{ 0, 0 },
1458	{ 0, 0 },
1459	{ 0, 0 },
1460	{ 0, 0 },
1461	{ 0, 0 },
1462	{ 0, 0 },
1463	{ 0, 0 },
1464	{ 0, 0 },
1465	{ 0, 0 },
1466	{ 0, 0 },
1467	{ ipcompname, IPCOMPCTL_MAXID },
1468	{ 0, 0 },
1469	{ 0, 0 },
1470	{ 0, 0 },
1471	{ carpname, CARPCTL_MAXID },
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	{ 0, 0 },
1607	{ 0, 0 },
1608	{ pfsyncname, PFSYNCCTL_MAXID },
1609	{ 0, 0 },
1610	{ 0, 0 },
1611	{ 0, 0 },
1612	{ 0, 0 },
1613	{ 0, 0 },
1614	{ 0, 0 },
1615	{ 0, 0 },
1616	{ 0, 0 },
1617	{ divertname, DIVERTCTL_MAXID },
1618};
1619struct list bpflist = { bpfname, NET_BPF_MAXID };
1620struct list ifqlist = { ifqname, IFQCTL_MAXID };
1621struct list pipexlist = { pipexname, PIPEXCTL_MAXID };
1622
1623struct list kernmalloclist = { kernmallocname, KERN_MALLOC_MAXID };
1624struct list forkstatlist = { forkstatname, KERN_FORKSTAT_MAXID };
1625struct list nchstatslist = { nchstatsname, KERN_NCHSTATS_MAXID };
1626struct list ttylist = { ttysname, KERN_TTY_MAXID };
1627struct list semlist = { semname, KERN_SEMINFO_MAXID };
1628struct list shmlist = { shmname, KERN_SHMINFO_MAXID };
1629struct list watchdoglist = { watchdogname, KERN_WATCHDOG_MAXID };
1630struct list tclist = { tcname, KERN_TIMECOUNTER_MAXID };
1631
1632/*
1633 * handle vfs namei cache statistics
1634 */
1635int
1636sysctl_nchstats(char *string, char **bufpp, int mib[], int flags, int *typep)
1637{
1638	static struct nchstats nch;
1639	int indx;
1640	size_t size;
1641	static int keepvalue = 0;
1642
1643	if (*bufpp == NULL) {
1644		bzero(&nch, sizeof(struct nchstats));
1645		listall(string, &nchstatslist);
1646		return (-1);
1647	}
1648	if ((indx = findname(string, "third", bufpp, &nchstatslist)) == -1)
1649		return (-1);
1650	mib[2] = indx;
1651	if (*bufpp != NULL) {
1652		warnx("fourth level name in %s is invalid", string);
1653		return (-1);
1654	}
1655	if (keepvalue == 0) {
1656		size = sizeof(struct nchstats);
1657		if (sysctl(mib, 2, &nch, &size, NULL, 0) < 0)
1658			return (-1);
1659		keepvalue = 1;
1660	}
1661	if (!nflag)
1662		(void)printf("%s%s", string, equ);
1663	switch (indx) {
1664	case KERN_NCHSTATS_GOODHITS:
1665		(void)printf("%llu\n", nch.ncs_goodhits);
1666		break;
1667	case KERN_NCHSTATS_NEGHITS:
1668		(void)printf("%llu\n", nch.ncs_neghits);
1669		break;
1670	case KERN_NCHSTATS_BADHITS:
1671		(void)printf("%llu\n", nch.ncs_badhits);
1672		break;
1673	case KERN_NCHSTATS_FALSEHITS:
1674		(void)printf("%llu\n", nch.ncs_falsehits);
1675		break;
1676	case KERN_NCHSTATS_MISS:
1677		(void)printf("%llu\n", nch.ncs_miss);
1678		break;
1679	case KERN_NCHSTATS_LONG:
1680		(void)printf("%llu\n", nch.ncs_long);
1681		break;
1682	case KERN_NCHSTATS_PASS2:
1683		(void)printf("%llu\n", nch.ncs_pass2);
1684		break;
1685	case KERN_NCHSTATS_2PASSES:
1686		(void)printf("%llu\n", nch.ncs_2passes);
1687		break;
1688	case KERN_NCHSTATS_REVHITS:
1689		(void)printf("%llu\n", nch.ncs_revhits);
1690		break;
1691	case KERN_NCHSTATS_REVMISS:
1692		(void)printf("%llu\n", nch.ncs_revmiss);
1693		break;
1694	case KERN_NCHSTATS_DOTHITS:
1695		(void)printf("%llu\n", nch.ncs_dothits);
1696		break;
1697	case KERN_NCHSTATS_DOTDOTHITS:
1698		(void)printf("%llu\n", nch.ncs_dotdothits);
1699		break;
1700	}
1701	return (-1);
1702}
1703
1704/*
1705 * handle tty statistics
1706 */
1707int
1708sysctl_tty(char *string, char **bufpp, int mib[], int flags, int *typep)
1709{
1710	int indx;
1711
1712	if (*bufpp == NULL) {
1713		listall(string, &ttylist);
1714		return (-1);
1715	}
1716	if ((indx = findname(string, "third", bufpp, &ttylist)) == -1)
1717		return (-1);
1718	mib[2] = indx;
1719
1720	if ((*typep = ttylist.list[indx].ctl_type) == CTLTYPE_STRUCT) {
1721		if (flags)
1722			warnx("use pstat -t to view %s information",
1723			    string);
1724		return (-1);
1725	}
1726	return (3);
1727}
1728
1729/*
1730 * handle fork statistics
1731 */
1732int
1733sysctl_forkstat(char *string, char **bufpp, int mib[], int flags, int *typep)
1734{
1735	static struct forkstat fks;
1736	static int keepvalue = 0;
1737	int indx;
1738	size_t size;
1739
1740	if (*bufpp == NULL) {
1741		bzero(&fks, sizeof(struct forkstat));
1742		listall(string, &forkstatlist);
1743		return (-1);
1744	}
1745	if ((indx = findname(string, "third", bufpp, &forkstatlist)) == -1)
1746		return (-1);
1747	if (*bufpp != NULL) {
1748		warnx("fourth level name in %s is invalid", string);
1749		return (-1);
1750	}
1751	if (keepvalue == 0) {
1752		size = sizeof(struct forkstat);
1753		if (sysctl(mib, 2, &fks, &size, NULL, 0) < 0)
1754			return (-1);
1755		keepvalue = 1;
1756	}
1757	if (!nflag)
1758		(void)printf("%s%s", string, equ);
1759	switch (indx)	{
1760	case KERN_FORKSTAT_FORK:
1761		(void)printf("%d\n", fks.cntfork);
1762		break;
1763	case KERN_FORKSTAT_VFORK:
1764		(void)printf("%d\n", fks.cntvfork);
1765		break;
1766	case KERN_FORKSTAT_RFORK:
1767		(void)printf("%d\n", fks.cntrfork);
1768		break;
1769	case KERN_FORKSTAT_KTHREAD:
1770		(void)printf("%d\n", fks.cntkthread);
1771		break;
1772	case KERN_FORKSTAT_SIZFORK:
1773		(void)printf("%d\n", fks.sizfork);
1774		break;
1775	case KERN_FORKSTAT_SIZVFORK:
1776		(void)printf("%d\n", fks.sizvfork);
1777		break;
1778	case KERN_FORKSTAT_SIZRFORK:
1779		(void)printf("%d\n", fks.sizrfork);
1780		break;
1781	case KERN_FORKSTAT_SIZKTHREAD:
1782		(void)printf("%d\n", fks.sizkthread);
1783		break;
1784	}
1785	return (-1);
1786}
1787
1788/*
1789 * handle malloc statistics
1790 */
1791int
1792sysctl_malloc(char *string, char **bufpp, int mib[], int flags, int *typep)
1793{
1794	int indx, stor, i;
1795	char *name, bufp[SYSCTL_BUFSIZ], *buf, *ptr;
1796	struct list lp;
1797	size_t size;
1798
1799	if (*bufpp == NULL) {
1800		listall(string, &kernmalloclist);
1801		return (-1);
1802	}
1803	if ((indx = findname(string, "third", bufpp, &kernmalloclist)) == -1)
1804		return (-1);
1805	mib[2] = indx;
1806	if (mib[2] == KERN_MALLOC_BUCKET) {
1807		if ((name = strsep(bufpp, ".")) == NULL) {
1808			size = SYSCTL_BUFSIZ;
1809			stor = mib[2];
1810			mib[2] = KERN_MALLOC_BUCKETS;
1811			buf = bufp;
1812			if (sysctl(mib, 3, buf, &size, NULL, 0) < 0)
1813				return (-1);
1814			mib[2] = stor;
1815			for (stor = 0, i = 0; i < size; i++)
1816				if (buf[i] == ',')
1817					stor++;
1818			lp.list = calloc(stor + 2, sizeof(struct ctlname));
1819			if (lp.list == NULL)
1820				return (-1);
1821			lp.size = stor + 2;
1822			for (i = 1;
1823			    (lp.list[i].ctl_name = strsep(&buf, ",")) != NULL;
1824			    i++) {
1825				lp.list[i].ctl_type = CTLTYPE_STRUCT;
1826			}
1827			lp.list[i].ctl_name = buf;
1828			lp.list[i].ctl_type = CTLTYPE_STRUCT;
1829			listall(string, &lp);
1830			free(lp.list);
1831			return (-1);
1832		}
1833		mib[3] = atoi(name);
1834		return (4);
1835	} else if (mib[2] == KERN_MALLOC_BUCKETS) {
1836		*typep = CTLTYPE_STRING;
1837		return (3);
1838	} else if (mib[2] == KERN_MALLOC_KMEMSTATS) {
1839		size = SYSCTL_BUFSIZ;
1840		stor = mib[2];
1841		mib[2] = KERN_MALLOC_KMEMNAMES;
1842		buf = bufp;
1843		if (sysctl(mib, 3, buf, &size, NULL, 0) < 0)
1844			return (-1);
1845		mib[2] = stor;
1846		if ((name = strsep(bufpp, ".")) == NULL) {
1847			for (stor = 0, i = 0; i < size; i++)
1848				if (buf[i] == ',')
1849					stor++;
1850			lp.list = calloc(stor + 2, sizeof(struct ctlname));
1851			if (lp.list == NULL)
1852				return (-1);
1853			lp.size = stor + 2;
1854			for (i = 1;
1855			    (lp.list[i].ctl_name = strsep(&buf, ",")) != NULL;
1856			    i++) {
1857				if (lp.list[i].ctl_name[0] == '\0') {
1858					i--;
1859					continue;
1860				}
1861				lp.list[i].ctl_type = CTLTYPE_STRUCT;
1862			}
1863			lp.list[i].ctl_name = buf;
1864			lp.list[i].ctl_type = CTLTYPE_STRUCT;
1865			listall(string, &lp);
1866			free(lp.list);
1867			return (-1);
1868		}
1869		ptr = strstr(buf, name);
1870 tryagain:
1871		if (ptr == NULL) {
1872			warnx("fourth level name %s in %s is invalid", name,
1873			    string);
1874			return (-1);
1875		}
1876		if ((*(ptr + strlen(name)) != ',') &&
1877		    (*(ptr + strlen(name)) != '\0')) {
1878			ptr = strstr(ptr + 1, name); /* retry */
1879			goto tryagain;
1880		}
1881		if ((ptr != buf) && (*(ptr - 1) != ',')) {
1882			ptr = strstr(ptr + 1, name); /* retry */
1883			goto tryagain;
1884		}
1885		for (i = 0, stor = 0; buf + i < ptr; i++)
1886			if (buf[i] == ',')
1887				stor++;
1888		mib[3] = stor;
1889		return (4);
1890	} else if (mib[2] == KERN_MALLOC_KMEMNAMES) {
1891		*typep = CTLTYPE_STRING;
1892		return (3);
1893	}
1894	return (-1);
1895}
1896
1897#ifdef CPU_CHIPSET
1898/*
1899 * handle machdep.chipset requests
1900 */
1901struct ctlname chipsetname[] = CTL_CHIPSET_NAMES;
1902struct list chipsetlist = { chipsetname, CPU_CHIPSET_MAXID };
1903
1904int
1905sysctl_chipset(char *string, char **bufpp, int mib[], int flags, int *typep)
1906{
1907	int indx, bwx;
1908	static void *q;
1909	size_t len;
1910	char *p;
1911
1912	if (*bufpp == NULL) {
1913		listall(string, &chipsetlist);
1914		return (-1);
1915	}
1916	if ((indx = findname(string, "third", bufpp, &chipsetlist)) == -1)
1917		return (-1);
1918	mib[2] = indx;
1919	if (!nflag)
1920		printf("%s%s", string, equ);
1921	switch(mib[2]) {
1922	case CPU_CHIPSET_MEM:
1923	case CPU_CHIPSET_DENSE:
1924	case CPU_CHIPSET_PORTS:
1925	case CPU_CHIPSET_HAE_MASK:
1926		len = sizeof(void *);
1927		if (sysctl(mib, 3, &q, &len, NULL, 0) < 0)
1928			goto done;
1929		printf("%p", q);
1930		break;
1931	case CPU_CHIPSET_BWX:
1932		len = sizeof(int);
1933		if (sysctl(mib, 3, &bwx, &len, NULL, 0) < 0)
1934			goto done;
1935		printf("%d", bwx);
1936		break;
1937	case CPU_CHIPSET_TYPE:
1938		if (sysctl(mib, 3, NULL, &len, NULL, 0) < 0)
1939			goto done;
1940		p = malloc(len + 1);
1941		if (p == NULL)
1942			goto done;
1943		if (sysctl(mib, 3, p, &len, NULL, 0) < 0) {
1944			free(p);
1945			goto done;
1946		}
1947		p[len] = '\0';
1948		printf("%s", p);
1949		free(p);
1950		break;
1951	}
1952done:
1953	printf("\n");
1954	return (-1);
1955}
1956#endif
1957/*
1958 * handle internet requests
1959 */
1960int
1961sysctl_inet(char *string, char **bufpp, int mib[], int flags, int *typep)
1962{
1963	struct list *lp;
1964	int indx;
1965
1966	if (*bufpp == NULL) {
1967		listall(string, &inetlist);
1968		return (-1);
1969	}
1970	if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
1971		return (-1);
1972	mib[2] = indx;
1973	if (indx < IPPROTO_MAXID && inetvars[indx].list != NULL)
1974		lp = &inetvars[indx];
1975	else if (!flags)
1976		return (-1);
1977	else {
1978		warnx("%s: no variables defined for this protocol", string);
1979		return (-1);
1980	}
1981	if (*bufpp == NULL) {
1982		listall(string, lp);
1983		return (-1);
1984	}
1985	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1986		return (-1);
1987	mib[3] = indx;
1988	*typep = lp->list[indx].ctl_type;
1989	if (*typep == CTLTYPE_NODE) {
1990		int tindx;
1991
1992		if (*bufpp == NULL) {
1993			listall(string, &ifqlist);
1994			return(-1);
1995		}
1996		lp = &ifqlist;
1997		if ((tindx = findname(string, "fifth", bufpp, lp)) == -1)
1998			return (-1);
1999		mib[4] = tindx;
2000		*typep = lp->list[tindx].ctl_type;
2001		return(5);
2002	}
2003	return (4);
2004}
2005
2006#ifdef INET6
2007struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES;
2008struct ctlname ip6name[] = IPV6CTL_NAMES;
2009struct ctlname icmp6name[] = ICMPV6CTL_NAMES;
2010struct ctlname pim6name[] = PIM6CTL_NAMES;
2011struct ctlname divert6name[] = DIVERT6CTL_NAMES;
2012struct list inet6list = { inet6name, IPV6PROTO_MAXID };
2013struct list inet6vars[] = {
2014/*0*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2015	{ 0, 0 },
2016	{ 0, 0 },
2017	{ 0, 0 },
2018	{ 0, 0 },
2019	{ 0, 0 },
2020/*10*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2021	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2022/*20*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2023	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2024/*30*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2025	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2026/*40*/	{ 0, 0 },
2027	{ ip6name, IPV6CTL_MAXID },	/* ipv6 */
2028	{ 0, 0 },
2029	{ 0, 0 },
2030	{ 0, 0 },
2031	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2032/*50*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2033	{ 0, 0 },
2034	{ 0, 0 },
2035	{ 0, 0 },
2036	{ icmp6name, ICMPV6CTL_MAXID },	/* icmp6 */
2037	{ 0, 0 },
2038/*60*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2039	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2040/*70*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2041	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2042/*80*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2043	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2044/*90*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2045	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2046/*100*/	{ 0, 0 },
2047	{ 0, 0 },
2048	{ 0, 0 },
2049	{ pim6name, PIM6CTL_MAXID },	/* pim6 */
2050	{ 0, 0 },
2051	{ 0, 0 },
2052	{ 0, 0 },
2053	{ 0, 0 },
2054	{ 0, 0 },
2055	{ 0, 0 },
2056/*110*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2057	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2058/*120*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2059	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2060/*130*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2061	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2062/*140*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2063	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2064/*150*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2065	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2066/*160*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2067	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2068/*170*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2069	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2070/*180*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2071	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2072/*190*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2073	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2074/*200*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2075	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2076/*210*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2077	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2078/*220*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2079	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2080/*230*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2081	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2082/*240*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2083	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2084/*250*/	{ 0, 0 },
2085	{ 0, 0 },
2086	{ 0, 0 },
2087	{ 0, 0 },
2088	{ 0, 0 },
2089	{ 0, 0 },
2090	{ 0, 0 },
2091	{ 0, 0 },
2092	{ divert6name, DIVERT6CTL_MAXID },
2093};
2094
2095/*
2096 * handle internet6 requests
2097 */
2098int
2099sysctl_inet6(char *string, char **bufpp, int mib[], int flags, int *typep)
2100{
2101	struct list *lp;
2102	int indx;
2103
2104	if (*bufpp == NULL) {
2105		listall(string, &inet6list);
2106		return (-1);
2107	}
2108	if ((indx = findname(string, "third", bufpp, &inet6list)) == -1)
2109		return (-1);
2110	mib[2] = indx;
2111	if (indx < IPV6PROTO_MAXID && inet6vars[indx].list != NULL)
2112		lp = &inet6vars[indx];
2113	else if (!flags)
2114		return (-1);
2115	else {
2116		warnx("%s: no variables defined for this protocol", string);
2117		return (-1);
2118	}
2119	if (*bufpp == NULL) {
2120		listall(string, lp);
2121		return (-1);
2122	}
2123	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
2124		return (-1);
2125	mib[3] = indx;
2126	*typep = lp->list[indx].ctl_type;
2127	return (4);
2128}
2129#endif
2130
2131/* handle bpf requests */
2132int
2133sysctl_bpf(char *string, char **bufpp, int mib[], int flags, int *typep)
2134{
2135	int indx;
2136
2137	if (*bufpp == NULL) {
2138		listall(string, &bpflist);
2139		return (-1);
2140	}
2141	if ((indx = findname(string, "third", bufpp, &bpflist)) == -1)
2142		return (-1);
2143	mib[2] = indx;
2144	*typep = CTLTYPE_INT;
2145	return (3);
2146}
2147
2148struct ctlname mplsname[] = MPLSCTL_NAMES;
2149struct list mplslist = { mplsname, MPLSCTL_MAXID };
2150
2151/* handle MPLS requests */
2152int
2153sysctl_mpls(char *string, char **bufpp, int mib[], int flags, int *typep)
2154{
2155	struct list *lp;
2156	int indx;
2157
2158	if (*bufpp == NULL) {
2159		listall(string, &mplslist);
2160		return (-1);
2161	}
2162	if ((indx = findname(string, "third", bufpp, &mplslist)) == -1)
2163		return (-1);
2164	mib[2] = indx;
2165	*typep = mplslist.list[indx].ctl_type;
2166	if (*typep == CTLTYPE_NODE) {
2167		int tindx;
2168
2169		if (*bufpp == NULL) {
2170			listall(string, &ifqlist);
2171			return(-1);
2172		}
2173		lp = &ifqlist;
2174		if ((tindx = findname(string, "fourth", bufpp, lp)) == -1)
2175			return (-1);
2176		mib[3] = tindx;
2177		*typep = lp->list[tindx].ctl_type;
2178		return(4);
2179	}
2180	return (3);
2181}
2182
2183/* handle PIPEX requests */
2184int
2185sysctl_pipex(char *string, char **bufpp, int mib[], int flags, int *typep)
2186{
2187	struct list *lp;
2188	int indx;
2189
2190	if (*bufpp == NULL) {
2191		listall(string, &pipexlist);
2192		return (-1);
2193	}
2194	if ((indx = findname(string, "third", bufpp, &pipexlist)) == -1)
2195		return (-1);
2196	mib[2] = indx;
2197	*typep = pipexlist.list[indx].ctl_type;
2198	return (3);
2199}
2200
2201/*
2202 * Handle SysV semaphore info requests
2203 */
2204int
2205sysctl_seminfo(string, bufpp, mib, flags, typep)
2206	char *string;
2207	char **bufpp;
2208	int mib[];
2209	int flags;
2210	int *typep;
2211{
2212	int indx;
2213
2214	if (*bufpp == NULL) {
2215		listall(string, &semlist);
2216		return (-1);
2217	}
2218	if ((indx = findname(string, "third", bufpp, &semlist)) == -1)
2219		return (-1);
2220	mib[2] = indx;
2221	*typep = CTLTYPE_INT;
2222	return (3);
2223}
2224
2225/*
2226 * Handle SysV shared memory info requests
2227 */
2228int
2229sysctl_shminfo(string, bufpp, mib, flags, typep)
2230	char *string;
2231	char **bufpp;
2232	int mib[];
2233	int flags;
2234	int *typep;
2235{
2236	int indx;
2237
2238	if (*bufpp == NULL) {
2239		listall(string, &shmlist);
2240		return (-1);
2241	}
2242	if ((indx = findname(string, "third", bufpp, &shmlist)) == -1)
2243		return (-1);
2244	mib[2] = indx;
2245	*typep = CTLTYPE_INT;
2246	return (3);
2247}
2248
2249/*
2250 * Handle watchdog support
2251 */
2252int
2253sysctl_watchdog(char *string, char **bufpp, int mib[], int flags,
2254    int *typep)
2255{
2256	int indx;
2257
2258	if (*bufpp == NULL) {
2259		listall(string, &watchdoglist);
2260		return (-1);
2261	}
2262	if ((indx = findname(string, "third", bufpp, &watchdoglist)) == -1)
2263		return (-1);
2264	mib[2] = indx;
2265	*typep = watchdoglist.list[indx].ctl_type;
2266	return (3);
2267}
2268
2269/*
2270 * Handle timecounter support
2271 */
2272int
2273sysctl_tc(char *string, char **bufpp, int mib[], int flags,
2274    int *typep)
2275{
2276	int indx;
2277
2278	if (*bufpp == NULL) {
2279		listall(string, &tclist);
2280		return (-1);
2281	}
2282	if ((indx = findname(string, "third", bufpp, &tclist)) == -1)
2283		return (-1);
2284	mib[2] = indx;
2285	*typep = tclist.list[indx].ctl_type;
2286	return (3);
2287}
2288
2289/*
2290 * Handle hardware monitoring sensors support
2291 */
2292int
2293sysctl_sensors(char *string, char **bufpp, int mib[], int flags, int *typep)
2294{
2295	char *devname, *typename;
2296	int dev, numt, i;
2297	enum sensor_type type;
2298	struct sensordev snsrdev;
2299	size_t sdlen = sizeof(snsrdev);
2300
2301	if (*bufpp == NULL) {
2302		char buf[SYSCTL_BUFSIZ];
2303
2304		/* scan all sensor devices */
2305		for (dev = 0; ; dev++) {
2306			mib[2] = dev;
2307			if (sysctl(mib, 3, &snsrdev, &sdlen, NULL, 0) == -1) {
2308				if (errno == ENXIO)
2309					continue;
2310				if (errno == ENOENT)
2311					break;
2312			}
2313			snprintf(buf, sizeof(buf), "%s.%s",
2314			    string, snsrdev.xname);
2315			print_sensordev(buf, mib, 3, &snsrdev);
2316		}
2317		return (-1);
2318	}
2319
2320	/*
2321	 * If we get this far, it means that some arguments were
2322	 * provided below hw.sensors tree.
2323	 * The first branch of hw.sensors tree is the device name.
2324	 */
2325	if ((devname = strsep(bufpp, ".")) == NULL) {
2326		warnx("%s: incomplete specification", string);
2327		return (-1);
2328	}
2329	/* convert sensor device string to an integer */
2330	for (dev = 0; ; dev++) {
2331		mib[2] = dev;
2332		if (sysctl(mib, 3, &snsrdev, &sdlen, NULL, 0) == -1) {
2333			if (errno == ENXIO)
2334				continue;
2335			if (errno == ENOENT)
2336				break;
2337		}
2338		if (strcmp(devname, snsrdev.xname) == 0)
2339			break;
2340	}
2341	if (strcmp(devname, snsrdev.xname) != 0) {
2342		warnx("%s: sensor device not found: %s", string, devname);
2343		return (-1);
2344	}
2345	if (*bufpp == NULL) {
2346		/* only device name was provided -- let's print all sensors
2347		 * that are attached to the specified device
2348		 */
2349		print_sensordev(string, mib, 3, &snsrdev);
2350		return (-1);
2351	}
2352
2353	/*
2354	 * At this point we have identified the sensor device,
2355	 * now let's go further and identify sensor type.
2356	 */
2357	if ((typename = strsep(bufpp, ".")) == NULL) {
2358		warnx("%s: incomplete specification", string);
2359		return (-1);
2360	}
2361	numt = -1;
2362	for (i = 0; typename[i] != '\0'; i++)
2363		if (isdigit(typename[i])) {
2364			numt = atoi(&typename[i]);
2365			typename[i] = '\0';
2366			break;
2367		}
2368	for (type = 0; type < SENSOR_MAX_TYPES; type++)
2369		if (strcmp(typename, sensor_type_s[type]) == 0)
2370			break;
2371	if (type == SENSOR_MAX_TYPES) {
2372		warnx("%s: sensor type not recognised: %s", string, typename);
2373		return (-1);
2374	}
2375	mib[3] = type;
2376
2377	/*
2378	 * If no integer was provided after sensor_type, let's
2379	 * print all sensors of the specified type.
2380	 */
2381	if (numt == -1) {
2382		print_sensordev(string, mib, 4, &snsrdev);
2383		return (-1);
2384	}
2385
2386	/*
2387	 * At this point we know that we have received a direct request
2388	 * via command-line for a specific sensor. Let's have the parse()
2389	 * function deal with it further, and report any errors if such
2390	 * sensor node does not exist.
2391	 */
2392	mib[4] = numt;
2393	*typep = CTLTYPE_STRUCT;
2394	return (5);
2395}
2396
2397/*
2398 * Print sensors from the specified device.
2399 */
2400
2401void
2402print_sensordev(char *string, int mib[], u_int mlen, struct sensordev *snsrdev)
2403{
2404	char buf[SYSCTL_BUFSIZ];
2405	enum sensor_type type;
2406
2407	if (mlen == 3) {
2408		for (type = 0; type < SENSOR_MAX_TYPES; type++) {
2409			mib[3] = type;
2410			snprintf(buf, sizeof(buf), "%s.%s",
2411			    string, sensor_type_s[type]);
2412			print_sensordev(buf, mib, mlen+1, snsrdev);
2413		}
2414		return;
2415	}
2416
2417	if (mlen == 4) {
2418		int numt;
2419
2420		type = mib[3];
2421		for (numt = 0; numt < snsrdev->maxnumt[type]; numt++) {
2422			mib[4] = numt;
2423			snprintf(buf, sizeof(buf), "%s%u", string, numt);
2424			print_sensordev(buf, mib, mlen+1, snsrdev);
2425		}
2426		return;
2427	}
2428
2429	if (mlen == 5) {
2430		struct sensor snsr;
2431		size_t slen = sizeof(snsr);
2432
2433		/* this function is only printing sensors in bulk, so we
2434		 * do not return any error messages if the requested sensor
2435		 * is not found by sysctl(3)
2436		 */
2437		if (sysctl(mib, 5, &snsr, &slen, NULL, 0) == -1)
2438			return;
2439
2440		if (slen > 0 && (snsr.flags & SENSOR_FINVALID) == 0) {
2441			if (!nflag)
2442				printf("%s%s", string, equ);
2443			print_sensor(&snsr);
2444			printf("\n");
2445		}
2446		return;
2447	}
2448}
2449
2450void
2451print_sensor(struct sensor *s)
2452{
2453	const char *name;
2454
2455	if (s->flags & SENSOR_FUNKNOWN)
2456		printf("unknown");
2457	else {
2458		switch (s->type) {
2459		case SENSOR_TEMP:
2460			printf("%.2f degC",
2461			    (s->value - 273150000) / 1000000.0);
2462			break;
2463		case SENSOR_FANRPM:
2464			printf("%lld RPM", s->value);
2465			break;
2466		case SENSOR_VOLTS_AC:
2467			printf("%.2f ADC", s->value / 1000000.0);
2468			break;
2469		case SENSOR_VOLTS_DC:
2470			printf("%.2f VDC", s->value / 1000000.0);
2471			break;
2472		case SENSOR_WATTS:
2473			printf("%.2f W", s->value / 1000000.0);
2474			break;
2475		case SENSOR_AMPS:
2476			printf("%.2f A", s->value / 1000000.0);
2477			break;
2478		case SENSOR_WATTHOUR:
2479			printf("%.2f Wh", s->value / 1000000.0);
2480			break;
2481		case SENSOR_AMPHOUR:
2482			printf("%.2f Ah", s->value / 1000000.0);
2483			break;
2484		case SENSOR_INDICATOR:
2485			printf("%s", s->value ? "On" : "Off");
2486			break;
2487		case SENSOR_INTEGER:
2488			printf("%lld", s->value);
2489			break;
2490		case SENSOR_PERCENT:
2491			printf("%.2f%%", s->value / 1000.0);
2492			break;
2493		case SENSOR_LUX:
2494			printf("%.2f lx", s->value / 1000000.0);
2495			break;
2496		case SENSOR_DRIVE:
2497			switch (s->value) {
2498			case SENSOR_DRIVE_EMPTY:
2499				name = "empty";
2500				break;
2501			case SENSOR_DRIVE_READY:
2502				name = "ready";
2503				break;
2504			case SENSOR_DRIVE_POWERUP:
2505				name = "powering up";
2506				break;
2507			case SENSOR_DRIVE_ONLINE:
2508				name = "online";
2509				break;
2510			case SENSOR_DRIVE_IDLE:
2511				name = "idle";
2512				break;
2513			case SENSOR_DRIVE_ACTIVE:
2514				name = "active";
2515				break;
2516			case SENSOR_DRIVE_REBUILD:
2517				name = "rebuilding";
2518				break;
2519			case SENSOR_DRIVE_POWERDOWN:
2520				name = "powering down";
2521				break;
2522			case SENSOR_DRIVE_FAIL:
2523				name = "failed";
2524				break;
2525			case SENSOR_DRIVE_PFAIL:
2526				name = "degraded";
2527				break;
2528			default:
2529				name = "unknown";
2530				break;
2531			}
2532			printf(name);
2533			break;
2534		case SENSOR_TIMEDELTA:
2535			printf("%.6f secs", s->value / 1000000000.0);
2536			break;
2537		case SENSOR_HUMIDITY:
2538			printf("%.2f%%", s->value / 1000.0);
2539			break;
2540		case SENSOR_FREQ:
2541			printf("%.2f Hz", s->value / 1000000.0);
2542			break;
2543		case SENSOR_ANGLE:
2544			printf("%3.4f degrees", s->value / 1000000.0);
2545			break;
2546		default:
2547			printf("unknown");
2548		}
2549	}
2550
2551	if (s->desc[0] != '\0')
2552		printf(" (%s)", s->desc);
2553
2554	switch (s->status) {
2555	case SENSOR_S_UNSPEC:
2556		break;
2557	case SENSOR_S_OK:
2558		printf(", OK");
2559		break;
2560	case SENSOR_S_WARN:
2561		printf(", WARNING");
2562		break;
2563	case SENSOR_S_CRIT:
2564		printf(", CRITICAL");
2565		break;
2566	case SENSOR_S_UNKNOWN:
2567		printf(", UNKNOWN");
2568		break;
2569	}
2570
2571	if (s->tv.tv_sec) {
2572		time_t t = s->tv.tv_sec;
2573		char ct[26];
2574
2575		ctime_r(&t, ct);
2576		ct[19] = '\0';
2577		printf(", %s.%03ld", ct, s->tv.tv_usec / 1000);
2578	}
2579}
2580
2581struct emulname {
2582	char *name;
2583	int index;
2584} *emul_names;
2585int	emul_num, nemuls;
2586int	emul_init(void);
2587
2588int
2589sysctl_emul(char *string, char *newval, int flags)
2590{
2591	int mib[4], enabled, i, old, print, found = 0;
2592	char *head, *target;
2593	size_t len;
2594
2595	if (emul_init() == -1) {
2596		warnx("emul_init: out of memory");
2597		return (1);
2598	}
2599
2600	mib[0] = CTL_KERN;
2601	mib[1] = KERN_EMUL;
2602	mib[3] = KERN_EMUL_ENABLED;
2603	head = "kern.emul.";
2604
2605	if (aflag || strcmp(string, "kern.emul") == 0) {
2606		if (newval) {
2607			warnx("%s: specification is incomplete", string);
2608			return (1);
2609		}
2610		if (nflag)
2611			printf("%d\n", nemuls);
2612		else
2613			printf("%snemuls%s%d\n", head, equ, nemuls);
2614		for (i = 0; i < emul_num; i++) {
2615			if (emul_names[i].name == NULL)
2616				break;
2617			if (i > 0 && strcmp(emul_names[i].name,
2618			    emul_names[i-1].name) == 0)
2619				continue;
2620			mib[2] = emul_names[i].index;
2621			len = sizeof(int);
2622			if (sysctl(mib, 4, &enabled, &len, NULL, 0) == -1) {
2623				warn("%s", string);
2624				continue;
2625			}
2626			if (nflag)
2627				printf("%d\n", enabled);
2628			else
2629				printf("%s%s%s%d\n", head, emul_names[i].name,
2630				    equ, enabled);
2631		}
2632		return (0);
2633	}
2634	/* User specified a third level name */
2635	target = strrchr(string, '.');
2636	target++;
2637	if (strcmp(target, "nemuls") == 0) {
2638		if (newval) {
2639			warnx("Operation not permitted");
2640			return (1);
2641		}
2642		if (nflag)
2643			printf("%d\n", nemuls);
2644		else
2645			printf("%snemuls = %d\n", head, nemuls);
2646		return (0);
2647	}
2648	print = 1;
2649	for (i = 0; i < emul_num; i++) {
2650		if (!emul_names[i].name || (strcmp(target, emul_names[i].name)))
2651			continue;
2652		found = 1;
2653		mib[2] = emul_names[i].index;
2654		len = sizeof(int);
2655		if (newval) {
2656			enabled = atoi(newval);
2657			if (sysctl(mib, 4, &old, &len, &enabled, len) == -1) {
2658				warn("%s", string);
2659				print = 0;
2660				continue;
2661			}
2662			if (print) {
2663				if (nflag)
2664					printf("%d\n", enabled);
2665				else
2666					printf("%s%s: %d -> %d\n", head,
2667					    target, old, enabled);
2668			}
2669		} else {
2670			if (sysctl(mib, 4, &enabled, &len, NULL, 0) == -1) {
2671				warn("%s", string);
2672				continue;
2673			}
2674			if (print) {
2675				if (nflag)
2676					printf("%d\n", enabled);
2677				else
2678					printf("%s%s = %d\n", head, target,
2679					    enabled);
2680			}
2681		}
2682		print = 0;
2683	}
2684	if (!found)
2685		warnx("third level name %s in kern.emul is invalid",
2686		    string);
2687	return (0);
2688
2689
2690}
2691
2692int
2693emulcmp(const void *m, const void *n)
2694{
2695	const struct emulname *a = m, *b = n;
2696
2697	if (!a || !a->name)
2698		return 1;
2699	if (!b || !b->name)
2700		return -1;
2701	return (strcmp(a->name, b->name));
2702}
2703
2704int
2705emul_init(void)
2706{
2707	static int done;
2708	char string[16];
2709	int mib[4], i;
2710	size_t len;
2711
2712	if (done)
2713		return (0);
2714	done = 1;
2715
2716	mib[0] = CTL_KERN;
2717	mib[1] = KERN_EMUL;
2718	mib[2] = KERN_EMUL_NUM;
2719	len = sizeof(int);
2720	if (sysctl(mib, 3, &emul_num, &len, NULL, 0) == -1)
2721		return (-1);
2722
2723	emul_names = calloc(emul_num, sizeof(*emul_names));
2724	if (emul_names == NULL)
2725		return (-1);
2726
2727	nemuls = emul_num;
2728	for (i = 0; i < emul_num; i++) {
2729		emul_names[i].index = mib[2] = i + 1;
2730		mib[3] = KERN_EMUL_NAME;
2731		len = sizeof(string);
2732		if (sysctl(mib, 4, string, &len, NULL, 0) == -1)
2733			continue;
2734		if (strcmp(string, "native") == 0)
2735			continue;
2736		emul_names[i].name = strdup(string);
2737		if (emul_names[i].name == NULL) {
2738			free(emul_names);
2739			return (-1);
2740		}
2741	}
2742	qsort(emul_names, nemuls, sizeof(*emul_names), emulcmp);
2743	for (i = 0; i < emul_num; i++) {
2744		if (!emul_names[i].name || (i > 0 &&
2745		    strcmp(emul_names[i].name, emul_names[i - 1].name) == 0))
2746			nemuls--;
2747	}
2748	return (0);
2749}
2750
2751/*
2752 * Scan a list of names searching for a particular name.
2753 */
2754int
2755findname(char *string, char *level, char **bufp, struct list *namelist)
2756{
2757	char *name;
2758	int i;
2759
2760	if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
2761		warnx("%s: incomplete specification", string);
2762		return (-1);
2763	}
2764	for (i = 0; i < namelist->size; i++)
2765		if (namelist->list[i].ctl_name != NULL &&
2766		    strcmp(name, namelist->list[i].ctl_name) == 0)
2767			break;
2768	if (i == namelist->size) {
2769		warnx("%s level name %s in %s is invalid", level, name, string);
2770		return (-1);
2771	}
2772	return (i);
2773}
2774
2775void
2776usage(void)
2777{
2778
2779	(void)fprintf(stderr,
2780	    "usage: sysctl [-Aan]\n"
2781	    "       sysctl [-n] name ...\n"
2782	    "       sysctl [-nq] name=value ...\n");
2783	exit(1);
2784}
2785