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