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