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