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