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