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