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