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