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