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