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