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