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