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