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