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