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