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