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