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