sysctl.c revision 1.190
1/*	$OpenBSD: sysctl.c,v 1.190 2013/06/08 14:24:39 yasuoka 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/sem.h>
37#include <sys/shm.h>
38#include <sys/sysctl.h>
39#include <sys/socket.h>
40#include <sys/malloc.h>
41#include <sys/dkstat.h>
42#include <sys/uio.h>
43#include <sys/tty.h>
44#include <sys/namei.h>
45#include <sys/sensors.h>
46#include <net/route.h>
47#include <net/if.h>
48
49#include <netinet/in.h>
50#include <netinet/in_systm.h>
51#include <netinet/ip.h>
52#include <netinet/in_pcb.h>
53#include <netinet/ip_icmp.h>
54#include <netinet/ip_ipip.h>
55#include <netinet/ip_ether.h>
56#include <netinet/ip_ah.h>
57#include <netinet/ip_esp.h>
58#include <netinet/icmp_var.h>
59#include <netinet/igmp_var.h>
60#include <netinet/ip_var.h>
61#include <netinet/udp.h>
62#include <netinet/udp_var.h>
63#include <netinet/tcp.h>
64#include <netinet/tcp_timer.h>
65#include <netinet/tcp_var.h>
66#include <netinet/ip_gre.h>
67#include <netinet/ip_ipcomp.h>
68#include <netinet/ip_carp.h>
69#include <netinet/ip_divert.h>
70
71#include <net/pfvar.h>
72#include <net/if_pfsync.h>
73#include <net/pipex.h>
74
75#ifdef INET6
76#include <netinet/ip6.h>
77#include <netinet/icmp6.h>
78#include <netinet6/ip6_var.h>
79#include <netinet6/pim6_var.h>
80#include <netinet6/ip6_divert.h>
81#endif
82
83#include <netmpls/mpls.h>
84
85#include <uvm/uvm_swap_encrypt.h>
86
87#include <ufs/ufs/quota.h>
88#include <ufs/ufs/inode.h>
89#include <ufs/ffs/ffs_extern.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
104#include <machine/cpu.h>
105
106#ifdef CPU_BIOS
107#include <machine/biosvar.h>
108#endif
109
110struct ctlname topname[] = CTL_NAMES;
111struct ctlname kernname[] = CTL_KERN_NAMES;
112struct ctlname vmname[] = CTL_VM_NAMES;
113struct ctlname fsname[] = CTL_FS_NAMES;
114struct ctlname netname[] = CTL_NET_NAMES;
115struct ctlname hwname[] = CTL_HW_NAMES;
116struct ctlname debugname[CTL_DEBUG_MAXID];
117struct ctlname kernmallocname[] = CTL_KERN_MALLOC_NAMES;
118struct ctlname forkstatname[] = CTL_KERN_FORKSTAT_NAMES;
119struct ctlname nchstatsname[] = CTL_KERN_NCHSTATS_NAMES;
120struct ctlname ttysname[] = CTL_KERN_TTY_NAMES;
121struct ctlname semname[] = CTL_KERN_SEMINFO_NAMES;
122struct ctlname shmname[] = CTL_KERN_SHMINFO_NAMES;
123struct ctlname watchdogname[] = CTL_KERN_WATCHDOG_NAMES;
124struct ctlname tcname[] = CTL_KERN_TIMECOUNTER_NAMES;
125struct ctlname *vfsname;
126#ifdef CTL_MACHDEP_NAMES
127struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
128#endif
129struct ctlname ddbname[] = CTL_DDB_NAMES;
130char names[BUFSIZ];
131int lastused;
132
133/* Maximum size object to expect from sysctl(3) */
134#define SYSCTL_BUFSIZ	8192
135
136struct list {
137	struct	ctlname *list;
138	int	size;
139};
140struct list toplist = { topname, CTL_MAXID };
141struct list secondlevel[] = {
142	{ 0, 0 },			/* CTL_UNSPEC */
143	{ kernname, KERN_MAXID },	/* CTL_KERN */
144	{ vmname, VM_MAXID },		/* CTL_VM */
145	{ fsname, FS_MAXID },		/* CTL_FS */
146	{ netname, NET_MAXID },		/* CTL_NET */
147	{ 0, CTL_DEBUG_MAXID },		/* CTL_DEBUG */
148	{ hwname, HW_MAXID },		/* CTL_HW */
149#ifdef CTL_MACHDEP_NAMES
150	{ machdepname, CPU_MAXID },	/* CTL_MACHDEP */
151#else
152	{ 0, 0 },			/* CTL_MACHDEP */
153#endif
154	{ 0, 0 },			/* was CTL_USER */
155	{ ddbname, DBCTL_MAXID },	/* CTL_DDB_NAMES */
156	{ 0, 0 },			/* CTL_VFS */
157};
158
159int	Aflag, aflag, nflag, qflag;
160
161/*
162 * Variables requiring special processing.
163 */
164#define	CLOCK		0x00000001
165#define	BOOTTIME	0x00000002
166#define	CHRDEV		0x00000004
167#define	BLKDEV		0x00000008
168#define	RNDSTATS	0x00000010
169#define	BADDYNAMIC	0x00000020
170#define	BIOSGEO		0x00000040
171#define	BIOSDEV		0x00000080
172#define	MAJ2DEV		0x00000100
173#define	UNSIGNED	0x00000200
174#define	KMEMBUCKETS	0x00000400
175#define	LONGARRAY	0x00000800
176#define	KMEMSTATS	0x00001000
177#define	SENSORS		0x00002000
178
179/* prototypes */
180void debuginit(void);
181void listall(char *, struct list *);
182void parse(char *, int);
183void parse_baddynamic(int *, size_t, char *, void **, size_t *, int, int);
184void usage(void);
185int findname(char *, char *, char **, struct list *);
186int sysctl_inet(char *, char **, int *, int, int *);
187#ifdef INET6
188int sysctl_inet6(char *, char **, int *, int, int *);
189#endif
190int sysctl_bpf(char *, char **, int *, int, int *);
191int sysctl_mpls(char *, char **, int *, int, int *);
192int sysctl_pipex(char *, char **, int *, int, int *);
193int sysctl_fs(char *, char **, int *, int, int *);
194static int sysctl_vfs(char *, char **, int[], int, int *);
195static int sysctl_vfsgen(char *, char **, int[], int, int *);
196int sysctl_bios(char *, char **, int *, int, int *);
197int sysctl_swpenc(char *, char **, int *, int, int *);
198int sysctl_forkstat(char *, char **, int *, int, int *);
199int sysctl_tty(char *, char **, int *, int, int *);
200int sysctl_nchstats(char *, char **, int *, int, int *);
201int sysctl_malloc(char *, char **, int *, int, int *);
202int sysctl_seminfo(char *, char **, int *, int, int *);
203int sysctl_shminfo(char *, char **, int *, int, int *);
204int sysctl_watchdog(char *, char **, int *, int, int *);
205int sysctl_tc(char *, char **, int *, int, int *);
206int sysctl_sensors(char *, char **, int *, int, int *);
207void print_sensordev(char *, int *, u_int, struct sensordev *);
208void print_sensor(struct sensor *);
209int sysctl_emul(char *, char *, int);
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(*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_VNODE:
388		case KERN_FILE:
389			if (flags == 0)
390				return;
391			warnx("use pstat to view %s information", string);
392			return;
393		case KERN_PROC:
394			if (flags == 0)
395				return;
396			warnx("use ps to view %s information", string);
397			return;
398		case KERN_CLOCKRATE:
399			special |= CLOCK;
400			break;
401		case KERN_BOOTTIME:
402			special |= BOOTTIME;
403			break;
404		case KERN_RND:
405			special |= RNDSTATS;
406			break;
407		case KERN_HOSTID:
408		case KERN_ARND:
409			special |= UNSIGNED;
410			break;
411		case KERN_CPTIME:
412			special |= LONGARRAY;
413			lal = CPUSTATES;
414			break;
415		case KERN_SEMINFO:
416			len = sysctl_seminfo(string, &bufp, mib, flags, &type);
417			if (len < 0)
418				return;
419			break;
420		case KERN_SHMINFO:
421			len = sysctl_shminfo(string, &bufp, mib, flags, &type);
422			if (len < 0)
423				return;
424			break;
425		case KERN_WATCHDOG:
426			len = sysctl_watchdog(string, &bufp, mib, flags,
427			    &type);
428			if (len < 0)
429				return;
430			break;
431		case KERN_TIMECOUNTER:
432			len = sysctl_tc(string, &bufp, mib, flags,
433			    &type);
434			if (len < 0)
435				return;
436			break;
437		case KERN_EMUL:
438			sysctl_emul(string, newval, flags);
439			return;
440		case KERN_FILE2:
441			if (flags == 0)
442				return;
443			warnx("use fstat to view %s information", string);
444			return;
445		case KERN_CONSDEV:
446			special |= CHRDEV;
447			break;
448		case KERN_NETLIVELOCKS:
449			special |= UNSIGNED;
450			break;
451		}
452		break;
453
454	case CTL_HW:
455		switch (mib[1]) {
456		case HW_DISKSTATS:
457			/*
458			 * Only complain if someone asks explicitly for this,
459			 * otherwise "fail" silently.
460			 */
461			if (flags)
462				warnx("use vmstat to view %s information",
463				    string);
464			return;
465		case HW_SENSORS:
466			special |= SENSORS;
467			len = sysctl_sensors(string, &bufp, mib, flags, &type);
468			if (len < 0)
469				return;
470			break;
471		case HW_PHYSMEM:
472		case HW_USERMEM:
473			/*
474			 * Don't print these; we'll print the 64-bit
475			 * variants instead.
476			 */
477			return;
478		}
479		break;
480
481	case CTL_VM:
482		if (mib[1] == VM_LOADAVG) {
483			double loads[3];
484
485			getloadavg(loads, 3);
486			if (!nflag)
487				(void)printf("%s%s", string, equ);
488			(void)printf("%.2f %.2f %.2f\n", loads[0],
489			    loads[1], loads[2]);
490			return;
491		} else if (mib[1] == VM_PSSTRINGS) {
492			struct _ps_strings _ps;
493
494			size = sizeof(_ps);
495			if (sysctl(mib, 2, &_ps, &size, NULL, 0) == -1) {
496				if (flags == 0)
497					return;
498				if (!nflag)
499					(void)printf("%s: ", string);
500				(void)puts("can't find ps strings");
501				return;
502			}
503			if (!nflag)
504				(void)printf("%s%s", string, equ);
505			(void)printf("%p\n", _ps.val);
506			return;
507		} else if (mib[1] == VM_SWAPENCRYPT) {
508			len = sysctl_swpenc(string, &bufp, mib, flags, &type);
509			if (len < 0)
510				return;
511
512			break;
513		} else if (mib[1] == VM_NKMEMPAGES ||
514		    mib[1] == VM_ANONMIN ||
515		    mib[1] == VM_VTEXTMIN ||
516		    mib[1] == VM_VNODEMIN) {
517			break;
518		}
519		if (flags == 0)
520			return;
521		warnx("use vmstat or systat to view %s information", string);
522		return;
523
524		break;
525
526	case CTL_NET:
527		if (mib[1] == PF_INET) {
528			len = sysctl_inet(string, &bufp, mib, flags, &type);
529			if (len < 0)
530				return;
531
532			if ((mib[2] == IPPROTO_IP && mib[3] == IPCTL_MRTSTATS) ||
533			    (mib[2] == IPPROTO_IP && mib[3] == IPCTL_STATS) ||
534			    (mib[2] == IPPROTO_TCP && mib[3] == TCPCTL_STATS) ||
535			    (mib[2] == IPPROTO_UDP && mib[3] == UDPCTL_STATS) ||
536			    (mib[2] == IPPROTO_ESP && mib[3] == ESPCTL_STATS) ||
537			    (mib[2] == IPPROTO_AH && mib[3] == AHCTL_STATS) ||
538			    (mib[2] == IPPROTO_IGMP && mib[3] == IGMPCTL_STATS) ||
539			    (mib[2] == IPPROTO_ETHERIP && mib[3] == ETHERIPCTL_STATS) ||
540			    (mib[2] == IPPROTO_IPIP && mib[3] == IPIPCTL_STATS) ||
541			    (mib[2] == IPPROTO_IPCOMP && mib[3] == IPCOMPCTL_STATS) ||
542			    (mib[2] == IPPROTO_ICMP && mib[3] == ICMPCTL_STATS) ||
543			    (mib[2] == IPPROTO_CARP && mib[3] == CARPCTL_STATS) ||
544			    (mib[2] == IPPROTO_PFSYNC && mib[3] == PFSYNCCTL_STATS) ||
545			    (mib[2] == IPPROTO_DIVERT && mib[3] == DIVERTCTL_STATS)) {
546				if (flags == 0)
547					return;
548				warnx("use netstat to view %s information",
549				    string);
550				return;
551			} else if ((mib[2] == IPPROTO_TCP &&
552			    mib[3] == TCPCTL_BADDYNAMIC) ||
553			    (mib[2] == IPPROTO_UDP &&
554			    mib[3] == UDPCTL_BADDYNAMIC)) {
555
556				special |= BADDYNAMIC;
557
558				if (newval != NULL)
559					parse_baddynamic(mib, len, string,
560					    &newval, &newsize, flags, nflag);
561			}
562			break;
563		}
564#ifdef INET6
565		if (mib[1] == PF_INET6) {
566			len = sysctl_inet6(string, &bufp, mib, flags, &type);
567			if (len < 0)
568				return;
569
570			if ((mib[2] == IPPROTO_PIM && mib[3] == PIM6CTL_STATS) ||
571			    (mib[2] == IPPROTO_DIVERT && mib[3] == DIVERT6CTL_STATS)) {
572				if (flags == 0)
573					return;
574				warnx("use netstat to view %s information",
575				    string);
576				return;
577			}
578			break;
579		}
580#endif
581		if (mib[1] == PF_BPF) {
582			len = sysctl_bpf(string, &bufp, mib, flags, &type);
583			if (len < 0)
584				return;
585			break;
586		}
587		if (mib[1] == PF_MPLS) {
588			len = sysctl_mpls(string, &bufp, mib, flags, &type);
589			if (len < 0)
590				return;
591			break;
592		}
593		if (mib[1] == PF_PIPEX) {
594			len = sysctl_pipex(string, &bufp, mib, flags, &type);
595			if (len < 0)
596				return;
597			break;
598		}
599		if (flags == 0)
600			return;
601		warnx("use netstat to view %s information", string);
602		return;
603
604	case CTL_DEBUG:
605		mib[2] = CTL_DEBUG_VALUE;
606		len = 3;
607		break;
608
609	case CTL_MACHDEP:
610#ifdef CPU_CONSDEV
611		if (mib[1] == CPU_CONSDEV)
612			special |= CHRDEV;
613#endif
614#ifdef CPU_BLK2CHR
615		if (mib[1] == CPU_BLK2CHR) {
616			if (bufp == NULL)
617				return;
618			mib[2] = makedev(atoi(bufp),0);
619			bufp = NULL;
620			len = 3;
621			special |= CHRDEV;
622			break;
623		}
624#endif
625#ifdef CPU_CHR2BLK
626		if (mib[1] == CPU_CHR2BLK) {
627			if (bufp == NULL)
628				return;
629			mib[2] = makedev(atoi(bufp),0);
630			bufp = NULL;
631			len = 3;
632			special |= BLKDEV;
633			break;
634		}
635#endif
636#ifdef CPU_BIOS
637		if (mib[1] == CPU_BIOS) {
638			len = sysctl_bios(string, &bufp, mib, flags, &type);
639			if (len < 0)
640				return;
641			if (mib[2] == BIOS_DEV)
642				special |= BIOSDEV;
643			if (mib[2] == BIOS_DISKINFO)
644				special |= BIOSGEO;
645			break;
646		}
647#endif
648#ifdef CPU_CHIPSET
649		if (mib[1] == CPU_CHIPSET) {
650			len = sysctl_chipset(string, &bufp, mib, flags, &type);
651			if (len < 0)
652				return;
653			break;
654		}
655#endif
656		break;
657
658	case CTL_FS:
659		len = sysctl_fs(string, &bufp, mib, flags, &type);
660		if (len >= 0)
661			break;
662		return;
663
664	case CTL_VFS:
665		if (mib[1])
666			len = sysctl_vfs(string, &bufp, mib, flags, &type);
667		else
668			len = sysctl_vfsgen(string, &bufp, mib, flags, &type);
669		if (len >= 0) {
670			if (type == CTLTYPE_STRUCT) {
671				if (flags)
672					warnx("use nfsstat to view %s information",
673					    MOUNT_NFS);
674				return;
675			} else
676				break;
677		}
678		return;
679
680	case CTL_DDB:
681		break;
682
683	default:
684		warnx("illegal top level value: %d", mib[0]);
685		return;
686
687	}
688	if (bufp) {
689		warnx("name %s in %s is unknown", bufp, string);
690		return;
691	}
692	if (newsize > 0) {
693		switch (type) {
694		case CTLTYPE_INT:
695			errno = 0;
696			if (special & UNSIGNED)
697				intval = strtoul(newval, &cp, 10);
698			else
699				intval = strtol(newval, &cp, 10);
700			if (*cp != '\0') {
701				warnx("%s: illegal value: %s", string,
702				    (char *)newval);
703				return;
704			}
705			if (errno == ERANGE) {
706				warnx("%s: value %s out of range", string,
707				    (char *)newval);
708				return;
709			}
710			newval = &intval;
711			newsize = sizeof(intval);
712			break;
713
714		case CTLTYPE_QUAD:
715			/* XXX - assumes sizeof(long long) == sizeof(quad_t) */
716			(void)sscanf(newval, "%lld", (long long *)&quadval);
717			newval = &quadval;
718			newsize = sizeof(quadval);
719			break;
720		}
721	}
722	size = 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 & RNDSTATS) {
863		struct rndstats *rndstats = (struct rndstats *)buf;
864		int i;
865
866		if (!nflag)
867			(void)printf("%s%s", string, equ);
868		printf("tot: %llu used: %llu read: %llu stirs: %llu"
869		    " enqs: %llu deqs: %llu drops: %llu ledrops: %llu",
870		    rndstats->rnd_total, rndstats->rnd_used,
871		    rndstats->arc4_reads, rndstats->arc4_nstirs,
872		    rndstats->rnd_enqs, rndstats->rnd_deqs,
873		    rndstats->rnd_drops, rndstats->rnd_drople);
874		printf(" ed:");
875		for (i = 0;
876		    i < sizeof(rndstats->rnd_ed)/sizeof(rndstats->rnd_ed[0]);
877		    i++)
878			printf(" %llu", (unsigned long long)rndstats->rnd_ed[i]);
879		printf(" sc:");
880		for (i = 0;
881		    i < sizeof(rndstats->rnd_sc)/sizeof(rndstats->rnd_sc[0]);
882		    i++)
883			printf(" %llu", (unsigned long long)rndstats->rnd_sc[i]);
884		printf(" sb:");
885		for (i = 0;
886		    i < sizeof(rndstats->rnd_sb)/sizeof(rndstats->rnd_sb[0]);
887		    i++)
888			printf(" %llu", (unsigned long long)rndstats->rnd_sb[i]);
889		printf("\n");
890		return;
891	}
892	if (special & BADDYNAMIC) {
893		u_int port, lastport;
894		u_int32_t *baddynamic = (u_int32_t *)buf;
895
896		if (!qflag) {
897			if (!nflag)
898				(void)printf("%s%s", string,
899				    newsize ? ": " : equ);
900			lastport = 0;
901			for (port = 0; port < 65536; port++)
902				if (DP_ISSET(baddynamic, port)) {
903					(void)printf("%s%u",
904					    lastport ? "," : "", port);
905					lastport = port;
906				}
907			if (newsize != 0) {
908				if (!nflag)
909					fputs(" -> ", stdout);
910				baddynamic = (u_int32_t *)newval;
911				lastport = 0;
912				for (port = 0; port < 65536; port++)
913					if (DP_ISSET(baddynamic, port)) {
914						(void)printf("%s%u",
915						    lastport ? "," : "", port);
916						lastport = port;
917					}
918			}
919			(void)putchar('\n');
920		}
921		return;
922	}
923	if (special & LONGARRAY) {
924		long *la = (long *)buf;
925		if (!nflag)
926			printf("%s%s", string, equ);
927		while (lal--)
928			printf("%ld%s", *la++, lal? ",":"");
929		putchar('\n');
930		return;
931	}
932	if (special & SENSORS) {
933		struct sensor *s = (struct sensor *)buf;
934
935		if (size > 0 && (s->flags & SENSOR_FINVALID) == 0) {
936			if (!nflag)
937				printf("%s%s", string, equ);
938			print_sensor(s);
939			printf("\n");
940		}
941		return;
942	}
943	switch (type) {
944	case CTLTYPE_INT:
945		if (newsize == 0) {
946			if (!nflag)
947				(void)printf("%s%s", string, equ);
948			(void)printf("%d\n", *(int *)buf);
949		} else {
950			if (!qflag) {
951				if (!nflag)
952					(void)printf("%s: %d -> ", string,
953					    *(int *)buf);
954				(void)printf("%d\n", *(int *)newval);
955			}
956		}
957		return;
958
959	case CTLTYPE_STRING:
960		if (newval == NULL) {
961			if (!nflag)
962				(void)printf("%s%s", string, equ);
963			(void)puts(buf);
964		} else {
965			if (!qflag) {
966				if (!nflag)
967					(void)printf("%s: %s -> ", string, buf);
968				(void)puts((char *)newval);
969			}
970		}
971		return;
972
973	case CTLTYPE_QUAD:
974		if (newsize == 0) {
975			long long tmp = *(quad_t *)buf;
976
977			if (!nflag)
978				(void)printf("%s%s", string, equ);
979			(void)printf("%lld\n", tmp);
980		} else {
981			long long tmp = *(quad_t *)buf;
982
983			if (!qflag) {
984				if (!nflag)
985					(void)printf("%s: %lld -> ",
986					    string, tmp);
987				tmp = *(quad_t *)newval;
988				(void)printf("%qd\n", tmp);
989			}
990		}
991		return;
992
993	case CTLTYPE_STRUCT:
994		warnx("%s: unknown structure returned", string);
995		return;
996
997	default:
998	case CTLTYPE_NODE:
999		warnx("%s: unknown type returned", string);
1000		return;
1001	}
1002}
1003
1004static void
1005parse_ports(char *portspec, int *port, int *high_port)
1006{
1007	char *dash;
1008	const char *errstr;
1009
1010	if ((dash = strchr(portspec, '-')) != NULL)
1011		*dash++ = '\0';
1012	*port = strtonum(portspec, 0, 65535, &errstr);
1013	if (errstr != NULL)
1014		errx(1, "port is %s: %s", errstr, portspec);
1015	if (dash != NULL) {
1016		*high_port = strtonum(dash, 0, 65535, &errstr);
1017		if (errstr != NULL)
1018			errx(1, "high port is %s: %s", errstr, dash);
1019		if (*high_port < *port)
1020			errx(1, "high port %d is lower than %d",
1021			    *high_port, *port);
1022	} else
1023		*high_port = *port;
1024}
1025
1026void
1027parse_baddynamic(int mib[], size_t len, char *string, void **newvalp,
1028    size_t *newsizep, int flags, int nflag)
1029{
1030	static u_int32_t newbaddynamic[DP_MAPSIZE];
1031	int port, high_port, baddynamic_loaded = 0, full_list_set = 0;
1032	size_t size;
1033	char action, *cp;
1034
1035	while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) {
1036		if (*cp == '+' || *cp == '-') {
1037			if (full_list_set)
1038				errx(1, "cannot mix +/- with full list");
1039			action = *cp++;
1040			if (!baddynamic_loaded) {
1041				size = sizeof(newbaddynamic);
1042				if (sysctl(mib, len, newbaddynamic,
1043				    &size, 0, 0) == -1) {
1044					if (flags == 0)
1045						return;
1046					if (!nflag)
1047						printf("%s: ", string);
1048					puts("kernel does contain bad dynamic "
1049					    "port tables");
1050					return;
1051				}
1052				baddynamic_loaded = 1;
1053			}
1054			parse_ports(cp, &port, &high_port);
1055			for (; port <= high_port; port++) {
1056				if (action == '+')
1057					DP_SET(newbaddynamic, port);
1058				else
1059					DP_CLR(newbaddynamic, port);
1060			}
1061		} else {
1062			if (baddynamic_loaded)
1063				errx(1, "cannot mix +/- with full list");
1064			if (!full_list_set) {
1065				bzero(newbaddynamic, sizeof(newbaddynamic));
1066				full_list_set = 1;
1067			}
1068			parse_ports(cp, &port, &high_port);
1069			for (; port <= high_port; port++)
1070				DP_SET(newbaddynamic, port);
1071		}
1072	}
1073	*newvalp = (void *)newbaddynamic;
1074	*newsizep = sizeof(newbaddynamic);
1075}
1076
1077/*
1078 * Initialize the set of debugging names
1079 */
1080void
1081debuginit(void)
1082{
1083	int mib[3], loc, i;
1084	size_t size;
1085
1086	if (secondlevel[CTL_DEBUG].list != 0)
1087		return;
1088	secondlevel[CTL_DEBUG].list = debugname;
1089	mib[0] = CTL_DEBUG;
1090	mib[2] = CTL_DEBUG_NAME;
1091	for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) {
1092		mib[1] = i;
1093		size = BUFSIZ - loc;
1094		if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
1095			continue;
1096		debugname[i].ctl_name = &names[loc];
1097		debugname[i].ctl_type = CTLTYPE_INT;
1098		loc += size;
1099	}
1100	lastused = loc;
1101}
1102
1103struct ctlname vfsgennames[] = CTL_VFSGENCTL_NAMES;
1104struct ctlname ffsname[] = FFS_NAMES;
1105struct ctlname nfsname[] = FS_NFS_NAMES;
1106struct list *vfsvars;
1107int *vfs_typenums;
1108
1109/*
1110 * Initialize the set of filesystem names
1111 */
1112void
1113vfsinit(void)
1114{
1115	int mib[4], maxtypenum, cnt, loc, size;
1116	struct vfsconf vfc;
1117	size_t buflen;
1118
1119	if (secondlevel[CTL_VFS].list != 0)
1120		return;
1121	mib[0] = CTL_VFS;
1122	mib[1] = VFS_GENERIC;
1123	mib[2] = VFS_MAXTYPENUM;
1124	buflen = 4;
1125	if (sysctl(mib, 3, &maxtypenum, &buflen, (void *)0, (size_t)0) < 0)
1126		return;
1127	maxtypenum++;	/* + generic */
1128	if ((vfs_typenums = calloc(maxtypenum, sizeof(int))) == NULL)
1129		return;
1130	if ((vfsvars = calloc(maxtypenum, sizeof(*vfsvars))) == NULL) {
1131		free(vfs_typenums);
1132		return;
1133	}
1134	if ((vfsname = calloc(maxtypenum, sizeof(*vfsname))) == NULL) {
1135		free(vfs_typenums);
1136		free(vfsvars);
1137		return;
1138	}
1139	mib[2] = VFS_CONF;
1140	buflen = sizeof vfc;
1141	for (loc = lastused, cnt = 1; cnt < maxtypenum; cnt++) {
1142		mib[3] = cnt - 1;
1143		if (sysctl(mib, 4, &vfc, &buflen, (void *)0, (size_t)0) < 0) {
1144			if (errno == EOPNOTSUPP)
1145				continue;
1146			warn("vfsinit");
1147			free(vfsname);
1148			free(vfsvars);
1149			free(vfs_typenums);
1150			return;
1151		}
1152		if (!strcmp(vfc.vfc_name, MOUNT_FFS)) {
1153			vfsvars[cnt].list = ffsname;
1154			vfsvars[cnt].size = FFS_MAXID;
1155		}
1156		if (!strcmp(vfc.vfc_name, MOUNT_NFS)) {
1157			vfsvars[cnt].list = nfsname;
1158			vfsvars[cnt].size = NFS_MAXID;
1159		}
1160		vfs_typenums[cnt] = vfc.vfc_typenum;
1161		strlcat(&names[loc], vfc.vfc_name, sizeof names - loc);
1162		vfsname[cnt].ctl_name = &names[loc];
1163		vfsname[cnt].ctl_type = CTLTYPE_NODE;
1164		size = strlen(vfc.vfc_name) + 1;
1165		loc += size;
1166	}
1167	lastused = loc;
1168
1169	vfsname[0].ctl_name = "mounts";
1170	vfsname[0].ctl_type = CTLTYPE_NODE;
1171	vfsvars[0].list = vfsname + 1;
1172	vfsvars[0].size = maxtypenum - 1;
1173
1174	secondlevel[CTL_VFS].list = vfsname;
1175	secondlevel[CTL_VFS].size = maxtypenum;
1176	return;
1177}
1178
1179int
1180sysctl_vfsgen(char *string, char **bufpp, int mib[], int flags, int *typep)
1181{
1182	int indx;
1183	size_t size;
1184	struct vfsconf vfc;
1185
1186	if (*bufpp == NULL) {
1187		listall(string, vfsvars);
1188		return (-1);
1189	}
1190
1191	if ((indx = findname(string, "third", bufpp, vfsvars)) == -1)
1192		return (-1);
1193
1194	mib[1] = VFS_GENERIC;
1195	mib[2] = VFS_CONF;
1196	mib[3] = indx;
1197	size = sizeof vfc;
1198	if (sysctl(mib, 4, &vfc, &size, (void *)0, (size_t)0) < 0) {
1199		if (errno != EOPNOTSUPP)
1200			warn("vfs print");
1201		return -1;
1202	}
1203	if (flags == 0 && vfc.vfc_refcount == 0)
1204		return -1;
1205	if (!nflag)
1206		fprintf(stdout, "%s has %d mounted instance%s\n",
1207		    string, vfc.vfc_refcount,
1208		    vfc.vfc_refcount != 1 ? "s" : "");
1209	else
1210		fprintf(stdout, "%d\n", vfc.vfc_refcount);
1211
1212	return -1;
1213}
1214
1215int
1216sysctl_vfs(char *string, char **bufpp, int mib[], int flags, int *typep)
1217{
1218	struct list *lp = &vfsvars[mib[1]];
1219	int indx;
1220
1221	if (lp->list == NULL) {
1222		if (flags)
1223			warnx("No variables defined for file system %s", string);
1224		return (-1);
1225	}
1226	if (*bufpp == NULL) {
1227		listall(string, lp);
1228		return (-1);
1229	}
1230	if ((indx = findname(string, "third", bufpp, lp)) == -1)
1231		return (-1);
1232
1233	mib[1] = vfs_typenums[mib[1]];
1234	mib[2] = indx;
1235	*typep = lp->list[indx].ctl_type;
1236	return (3);
1237}
1238
1239struct ctlname posixname[] = CTL_FS_POSIX_NAMES;
1240struct list fslist = { posixname, FS_POSIX_MAXID };
1241
1242/*
1243 * handle file system requests
1244 */
1245int
1246sysctl_fs(char *string, char **bufpp, int mib[], int flags, int *typep)
1247{
1248	int indx;
1249
1250	if (*bufpp == NULL) {
1251		listall(string, &fslist);
1252		return (-1);
1253	}
1254	if ((indx = findname(string, "third", bufpp, &fslist)) == -1)
1255		return (-1);
1256	mib[2] = indx;
1257	*typep = fslist.list[indx].ctl_type;
1258	return (3);
1259}
1260
1261#ifdef CPU_BIOS
1262struct ctlname biosname[] = CTL_BIOS_NAMES;
1263struct list bioslist = { biosname, BIOS_MAXID };
1264
1265/*
1266 * handle BIOS requests
1267 */
1268int
1269sysctl_bios(char *string, char **bufpp, int mib[], int flags, int *typep)
1270{
1271	char *name;
1272	int indx;
1273
1274	if (*bufpp == NULL) {
1275		listall(string, &bioslist);
1276		return (-1);
1277	}
1278	if ((indx = findname(string, "third", bufpp, &bioslist)) == -1)
1279		return (-1);
1280	mib[2] = indx;
1281	if (indx == BIOS_DISKINFO) {
1282		if (*bufpp == NULL) {
1283			char name[BUFSIZ];
1284
1285			/* scan all the bios devices */
1286			for (indx = 0; indx < 256; indx++) {
1287				snprintf(name, sizeof(name), "%s.%u",
1288				    string, indx);
1289				parse(name, 1);
1290			}
1291			return (-1);
1292		}
1293		if ((name = strsep(bufpp, ".")) == NULL) {
1294			warnx("%s: incomplete specification", string);
1295			return (-1);
1296		}
1297		mib[3] = atoi(name);
1298		*typep = CTLTYPE_STRUCT;
1299		return (4);
1300	} else {
1301		*typep = bioslist.list[indx].ctl_type;
1302		return (3);
1303	}
1304}
1305#endif
1306
1307struct ctlname swpencname[] = CTL_SWPENC_NAMES;
1308struct list swpenclist = { swpencname, SWPENC_MAXID };
1309
1310/*
1311 * handle swap encrypt requests
1312 */
1313int
1314sysctl_swpenc(char *string, char **bufpp, int mib[], int flags, int *typep)
1315{
1316	int indx;
1317
1318	if (*bufpp == NULL) {
1319		listall(string, &swpenclist);
1320		return (-1);
1321	}
1322	if ((indx = findname(string, "third", bufpp, &swpenclist)) == -1)
1323		return (-1);
1324	mib[2] = indx;
1325	*typep = swpenclist.list[indx].ctl_type;
1326	return (3);
1327}
1328
1329struct ctlname inetname[] = CTL_IPPROTO_NAMES;
1330struct ctlname ipname[] = IPCTL_NAMES;
1331struct ctlname icmpname[] = ICMPCTL_NAMES;
1332struct ctlname igmpname[] = IGMPCTL_NAMES;
1333struct ctlname ipipname[] = IPIPCTL_NAMES;
1334struct ctlname tcpname[] = TCPCTL_NAMES;
1335struct ctlname udpname[] = UDPCTL_NAMES;
1336struct ctlname espname[] = ESPCTL_NAMES;
1337struct ctlname ahname[] = AHCTL_NAMES;
1338struct ctlname etheripname[] = ETHERIPCTL_NAMES;
1339struct ctlname grename[] = GRECTL_NAMES;
1340struct ctlname mobileipname[] = MOBILEIPCTL_NAMES;
1341struct ctlname ipcompname[] = IPCOMPCTL_NAMES;
1342struct ctlname carpname[] = CARPCTL_NAMES;
1343struct ctlname pfsyncname[] = PFSYNCCTL_NAMES;
1344struct ctlname divertname[] = DIVERTCTL_NAMES;
1345struct ctlname bpfname[] = CTL_NET_BPF_NAMES;
1346struct ctlname ifqname[] = CTL_IFQ_NAMES;
1347struct ctlname pipexname[] = PIPEXCTL_NAMES;
1348struct list inetlist = { inetname, IPPROTO_MAXID };
1349struct list inetvars[] = {
1350	{ ipname, IPCTL_MAXID },	/* ip */
1351	{ icmpname, ICMPCTL_MAXID },	/* icmp */
1352	{ igmpname, IGMPCTL_MAXID },	/* igmp */
1353	{ 0, 0 },			/* ggmp */
1354	{ ipipname, IPIPCTL_MAXID },	/* ipencap */
1355	{ 0, 0 },
1356	{ tcpname, TCPCTL_MAXID },	/* tcp */
1357	{ 0, 0 },
1358	{ 0, 0 },			/* egp */
1359	{ 0, 0 },
1360	{ 0, 0 },
1361	{ 0, 0 },
1362	{ 0, 0 },			/* pup */
1363	{ 0, 0 },
1364	{ 0, 0 },
1365	{ 0, 0 },
1366	{ 0, 0 },
1367	{ udpname, UDPCTL_MAXID },	/* udp */
1368	{ 0, 0 },
1369	{ 0, 0 },
1370	{ 0, 0 },
1371	{ 0, 0 },
1372	{ 0, 0 },
1373	{ 0, 0 },
1374	{ 0, 0 },
1375	{ 0, 0 },
1376	{ 0, 0 },
1377	{ 0, 0 },
1378	{ 0, 0 },
1379	{ 0, 0 },
1380	{ 0, 0 },
1381	{ 0, 0 },
1382	{ 0, 0 },
1383	{ 0, 0 },
1384	{ 0, 0 },
1385	{ 0, 0 },
1386	{ 0, 0 },
1387	{ 0, 0 },
1388	{ 0, 0 },
1389	{ 0, 0 },
1390	{ 0, 0 },
1391	{ 0, 0 },
1392	{ 0, 0 },
1393	{ 0, 0 },
1394	{ 0, 0 },
1395	{ 0, 0 },
1396	{ 0, 0 },
1397	{ grename, GRECTL_MAXID },	/* gre */
1398	{ 0, 0 },
1399	{ 0, 0 },
1400	{ espname, ESPCTL_MAXID },	/* esp */
1401	{ ahname, AHCTL_MAXID },	/* ah */
1402	{ 0, 0 },
1403	{ 0, 0 },
1404	{ 0, 0 },
1405	{ mobileipname, MOBILEIPCTL_MAXID }, /* mobileip */
1406	{ 0, 0 },
1407	{ 0, 0 },
1408	{ 0, 0 },
1409	{ 0, 0 },
1410	{ 0, 0 },
1411	{ 0, 0 },
1412	{ 0, 0 },
1413	{ 0, 0 },
1414	{ 0, 0 },
1415	{ 0, 0 },
1416	{ 0, 0 },
1417	{ 0, 0 },
1418	{ 0, 0 },
1419	{ 0, 0 },
1420	{ 0, 0 },
1421	{ 0, 0 },
1422	{ 0, 0 },
1423	{ 0, 0 },
1424	{ 0, 0 },
1425	{ 0, 0 },
1426	{ 0, 0 },
1427	{ 0, 0 },
1428	{ 0, 0 },
1429	{ 0, 0 },
1430	{ 0, 0 },
1431	{ 0, 0 },
1432	{ 0, 0 },
1433	{ 0, 0 },
1434	{ 0, 0 },
1435	{ 0, 0 },
1436	{ 0, 0 },
1437	{ 0, 0 },
1438	{ 0, 0 },
1439	{ 0, 0 },
1440	{ 0, 0 },
1441	{ 0, 0 },
1442	{ 0, 0 },
1443	{ 0, 0 },
1444	{ 0, 0 },
1445	{ 0, 0 },
1446	{ 0, 0 },
1447	{ etheripname, ETHERIPCTL_MAXID },
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	{ ipcompname, IPCOMPCTL_MAXID },
1459	{ 0, 0 },
1460	{ 0, 0 },
1461	{ 0, 0 },
1462	{ carpname, CARPCTL_MAXID },
1463	{ 0, 0 },
1464	{ 0, 0 },
1465	{ 0, 0 },
1466	{ 0, 0 },
1467	{ 0, 0 },
1468	{ 0, 0 },
1469	{ 0, 0 },
1470	{ 0, 0 },
1471	{ 0, 0 },
1472	{ 0, 0 },
1473	{ 0, 0 },
1474	{ 0, 0 },
1475	{ 0, 0 },
1476	{ 0, 0 },
1477	{ 0, 0 },
1478	{ 0, 0 },
1479	{ 0, 0 },
1480	{ 0, 0 },
1481	{ 0, 0 },
1482	{ 0, 0 },
1483	{ 0, 0 },
1484	{ 0, 0 },
1485	{ 0, 0 },
1486	{ 0, 0 },
1487	{ 0, 0 },
1488	{ 0, 0 },
1489	{ 0, 0 },
1490	{ 0, 0 },
1491	{ 0, 0 },
1492	{ 0, 0 },
1493	{ 0, 0 },
1494	{ 0, 0 },
1495	{ 0, 0 },
1496	{ 0, 0 },
1497	{ 0, 0 },
1498	{ 0, 0 },
1499	{ 0, 0 },
1500	{ 0, 0 },
1501	{ 0, 0 },
1502	{ 0, 0 },
1503	{ 0, 0 },
1504	{ 0, 0 },
1505	{ 0, 0 },
1506	{ 0, 0 },
1507	{ 0, 0 },
1508	{ 0, 0 },
1509	{ 0, 0 },
1510	{ 0, 0 },
1511	{ 0, 0 },
1512	{ 0, 0 },
1513	{ 0, 0 },
1514	{ 0, 0 },
1515	{ 0, 0 },
1516	{ 0, 0 },
1517	{ 0, 0 },
1518	{ 0, 0 },
1519	{ 0, 0 },
1520	{ 0, 0 },
1521	{ 0, 0 },
1522	{ 0, 0 },
1523	{ 0, 0 },
1524	{ 0, 0 },
1525	{ 0, 0 },
1526	{ 0, 0 },
1527	{ 0, 0 },
1528	{ 0, 0 },
1529	{ 0, 0 },
1530	{ 0, 0 },
1531	{ 0, 0 },
1532	{ 0, 0 },
1533	{ 0, 0 },
1534	{ 0, 0 },
1535	{ 0, 0 },
1536	{ 0, 0 },
1537	{ 0, 0 },
1538	{ 0, 0 },
1539	{ 0, 0 },
1540	{ 0, 0 },
1541	{ 0, 0 },
1542	{ 0, 0 },
1543	{ 0, 0 },
1544	{ 0, 0 },
1545	{ 0, 0 },
1546	{ 0, 0 },
1547	{ 0, 0 },
1548	{ 0, 0 },
1549	{ 0, 0 },
1550	{ 0, 0 },
1551	{ 0, 0 },
1552	{ 0, 0 },
1553	{ 0, 0 },
1554	{ 0, 0 },
1555	{ 0, 0 },
1556	{ 0, 0 },
1557	{ 0, 0 },
1558	{ 0, 0 },
1559	{ 0, 0 },
1560	{ 0, 0 },
1561	{ 0, 0 },
1562	{ 0, 0 },
1563	{ 0, 0 },
1564	{ 0, 0 },
1565	{ 0, 0 },
1566	{ 0, 0 },
1567	{ 0, 0 },
1568	{ 0, 0 },
1569	{ 0, 0 },
1570	{ 0, 0 },
1571	{ 0, 0 },
1572	{ 0, 0 },
1573	{ 0, 0 },
1574	{ 0, 0 },
1575	{ 0, 0 },
1576	{ 0, 0 },
1577	{ 0, 0 },
1578	{ 0, 0 },
1579	{ 0, 0 },
1580	{ 0, 0 },
1581	{ 0, 0 },
1582	{ 0, 0 },
1583	{ 0, 0 },
1584	{ 0, 0 },
1585	{ 0, 0 },
1586	{ 0, 0 },
1587	{ 0, 0 },
1588	{ 0, 0 },
1589	{ 0, 0 },
1590	{ 0, 0 },
1591	{ 0, 0 },
1592	{ 0, 0 },
1593	{ 0, 0 },
1594	{ 0, 0 },
1595	{ 0, 0 },
1596	{ 0, 0 },
1597	{ 0, 0 },
1598	{ 0, 0 },
1599	{ pfsyncname, PFSYNCCTL_MAXID },
1600	{ 0, 0 },
1601	{ 0, 0 },
1602	{ 0, 0 },
1603	{ 0, 0 },
1604	{ 0, 0 },
1605	{ 0, 0 },
1606	{ 0, 0 },
1607	{ 0, 0 },
1608	{ divertname, DIVERTCTL_MAXID },
1609};
1610struct list bpflist = { bpfname, NET_BPF_MAXID };
1611struct list ifqlist = { ifqname, IFQCTL_MAXID };
1612struct list pipexlist = { pipexname, PIPEXCTL_MAXID };
1613
1614struct list kernmalloclist = { kernmallocname, KERN_MALLOC_MAXID };
1615struct list forkstatlist = { forkstatname, KERN_FORKSTAT_MAXID };
1616struct list nchstatslist = { nchstatsname, KERN_NCHSTATS_MAXID };
1617struct list ttylist = { ttysname, KERN_TTY_MAXID };
1618struct list semlist = { semname, KERN_SEMINFO_MAXID };
1619struct list shmlist = { shmname, KERN_SHMINFO_MAXID };
1620struct list watchdoglist = { watchdogname, KERN_WATCHDOG_MAXID };
1621struct list tclist = { tcname, KERN_TIMECOUNTER_MAXID };
1622
1623/*
1624 * handle vfs namei cache statistics
1625 */
1626int
1627sysctl_nchstats(char *string, char **bufpp, int mib[], int flags, int *typep)
1628{
1629	static struct nchstats nch;
1630	int indx;
1631	size_t size;
1632	static int keepvalue = 0;
1633
1634	if (*bufpp == NULL) {
1635		bzero(&nch, sizeof(struct nchstats));
1636		listall(string, &nchstatslist);
1637		return (-1);
1638	}
1639	if ((indx = findname(string, "third", bufpp, &nchstatslist)) == -1)
1640		return (-1);
1641	mib[2] = indx;
1642	if (*bufpp != NULL) {
1643		warnx("fourth level name in %s is invalid", string);
1644		return (-1);
1645	}
1646	if (keepvalue == 0) {
1647		size = sizeof(struct nchstats);
1648		if (sysctl(mib, 2, &nch, &size, NULL, 0) < 0)
1649			return (-1);
1650		keepvalue = 1;
1651	}
1652	if (!nflag)
1653		(void)printf("%s%s", string, equ);
1654	switch (indx) {
1655	case KERN_NCHSTATS_GOODHITS:
1656		(void)printf("%llu\n", nch.ncs_goodhits);
1657		break;
1658	case KERN_NCHSTATS_NEGHITS:
1659		(void)printf("%llu\n", nch.ncs_neghits);
1660		break;
1661	case KERN_NCHSTATS_BADHITS:
1662		(void)printf("%llu\n", nch.ncs_badhits);
1663		break;
1664	case KERN_NCHSTATS_FALSEHITS:
1665		(void)printf("%llu\n", nch.ncs_falsehits);
1666		break;
1667	case KERN_NCHSTATS_MISS:
1668		(void)printf("%llu\n", nch.ncs_miss);
1669		break;
1670	case KERN_NCHSTATS_LONG:
1671		(void)printf("%llu\n", nch.ncs_long);
1672		break;
1673	case KERN_NCHSTATS_PASS2:
1674		(void)printf("%llu\n", nch.ncs_pass2);
1675		break;
1676	case KERN_NCHSTATS_2PASSES:
1677		(void)printf("%llu\n", nch.ncs_2passes);
1678		break;
1679	case KERN_NCHSTATS_REVHITS:
1680		(void)printf("%llu\n", nch.ncs_revhits);
1681		break;
1682	case KERN_NCHSTATS_REVMISS:
1683		(void)printf("%llu\n", nch.ncs_revmiss);
1684		break;
1685	case KERN_NCHSTATS_DOTHITS:
1686		(void)printf("%llu\n", nch.ncs_dothits);
1687		break;
1688	case KERN_NCHSTATS_DOTDOTHITS:
1689		(void)printf("%llu\n", nch.ncs_dotdothits);
1690		break;
1691	}
1692	return (-1);
1693}
1694
1695/*
1696 * handle tty statistics
1697 */
1698int
1699sysctl_tty(char *string, char **bufpp, int mib[], int flags, int *typep)
1700{
1701	int indx;
1702
1703	if (*bufpp == NULL) {
1704		listall(string, &ttylist);
1705		return (-1);
1706	}
1707	if ((indx = findname(string, "third", bufpp, &ttylist)) == -1)
1708		return (-1);
1709	mib[2] = indx;
1710
1711	if ((*typep = ttylist.list[indx].ctl_type) == CTLTYPE_STRUCT) {
1712		if (flags)
1713			warnx("use pstat -t to view %s information",
1714			    string);
1715		return (-1);
1716	}
1717	return (3);
1718}
1719
1720/*
1721 * handle fork statistics
1722 */
1723int
1724sysctl_forkstat(char *string, char **bufpp, int mib[], int flags, int *typep)
1725{
1726	static struct forkstat fks;
1727	static int keepvalue = 0;
1728	int indx;
1729	size_t size;
1730
1731	if (*bufpp == NULL) {
1732		bzero(&fks, sizeof(struct forkstat));
1733		listall(string, &forkstatlist);
1734		return (-1);
1735	}
1736	if ((indx = findname(string, "third", bufpp, &forkstatlist)) == -1)
1737		return (-1);
1738	if (*bufpp != NULL) {
1739		warnx("fourth level name in %s is invalid", string);
1740		return (-1);
1741	}
1742	if (keepvalue == 0) {
1743		size = sizeof(struct forkstat);
1744		if (sysctl(mib, 2, &fks, &size, NULL, 0) < 0)
1745			return (-1);
1746		keepvalue = 1;
1747	}
1748	if (!nflag)
1749		(void)printf("%s%s", string, equ);
1750	switch (indx)	{
1751	case KERN_FORKSTAT_FORK:
1752		(void)printf("%d\n", fks.cntfork);
1753		break;
1754	case KERN_FORKSTAT_VFORK:
1755		(void)printf("%d\n", fks.cntvfork);
1756		break;
1757	case KERN_FORKSTAT_TFORK:
1758		(void)printf("%d\n", fks.cnttfork);
1759		break;
1760	case KERN_FORKSTAT_KTHREAD:
1761		(void)printf("%d\n", fks.cntkthread);
1762		break;
1763	case KERN_FORKSTAT_SIZFORK:
1764		(void)printf("%d\n", fks.sizfork);
1765		break;
1766	case KERN_FORKSTAT_SIZVFORK:
1767		(void)printf("%d\n", fks.sizvfork);
1768		break;
1769	case KERN_FORKSTAT_SIZTFORK:
1770		(void)printf("%d\n", fks.siztfork);
1771		break;
1772	case KERN_FORKSTAT_SIZKTHREAD:
1773		(void)printf("%d\n", fks.sizkthread);
1774		break;
1775	}
1776	return (-1);
1777}
1778
1779/*
1780 * handle malloc statistics
1781 */
1782int
1783sysctl_malloc(char *string, char **bufpp, int mib[], int flags, int *typep)
1784{
1785	int indx, stor, i;
1786	char *name, bufp[SYSCTL_BUFSIZ], *buf, *ptr;
1787	struct list lp;
1788	size_t size;
1789
1790	if (*bufpp == NULL) {
1791		listall(string, &kernmalloclist);
1792		return (-1);
1793	}
1794	if ((indx = findname(string, "third", bufpp, &kernmalloclist)) == -1)
1795		return (-1);
1796	mib[2] = indx;
1797	if (mib[2] == KERN_MALLOC_BUCKET) {
1798		if ((name = strsep(bufpp, ".")) == NULL) {
1799			size = SYSCTL_BUFSIZ;
1800			stor = mib[2];
1801			mib[2] = KERN_MALLOC_BUCKETS;
1802			buf = bufp;
1803			if (sysctl(mib, 3, buf, &size, NULL, 0) < 0)
1804				return (-1);
1805			mib[2] = stor;
1806			for (stor = 0, i = 0; i < size; i++)
1807				if (buf[i] == ',')
1808					stor++;
1809			lp.list = calloc(stor + 2, sizeof(struct ctlname));
1810			if (lp.list == NULL)
1811				return (-1);
1812			lp.size = stor + 2;
1813			for (i = 1;
1814			    (lp.list[i].ctl_name = strsep(&buf, ",")) != NULL;
1815			    i++) {
1816				lp.list[i].ctl_type = CTLTYPE_STRUCT;
1817			}
1818			lp.list[i].ctl_name = buf;
1819			lp.list[i].ctl_type = CTLTYPE_STRUCT;
1820			listall(string, &lp);
1821			free(lp.list);
1822			return (-1);
1823		}
1824		mib[3] = atoi(name);
1825		return (4);
1826	} else if (mib[2] == KERN_MALLOC_BUCKETS) {
1827		*typep = CTLTYPE_STRING;
1828		return (3);
1829	} else if (mib[2] == KERN_MALLOC_KMEMSTATS) {
1830		size = SYSCTL_BUFSIZ;
1831		stor = mib[2];
1832		mib[2] = KERN_MALLOC_KMEMNAMES;
1833		buf = bufp;
1834		if (sysctl(mib, 3, buf, &size, NULL, 0) < 0)
1835			return (-1);
1836		mib[2] = stor;
1837		if ((name = strsep(bufpp, ".")) == NULL) {
1838			for (stor = 0, i = 0; i < size; i++)
1839				if (buf[i] == ',')
1840					stor++;
1841			lp.list = calloc(stor + 2, sizeof(struct ctlname));
1842			if (lp.list == NULL)
1843				return (-1);
1844			lp.size = stor + 2;
1845			for (i = 1;
1846			    (lp.list[i].ctl_name = strsep(&buf, ",")) != NULL;
1847			    i++) {
1848				if (lp.list[i].ctl_name[0] == '\0') {
1849					i--;
1850					continue;
1851				}
1852				lp.list[i].ctl_type = CTLTYPE_STRUCT;
1853			}
1854			lp.list[i].ctl_name = buf;
1855			lp.list[i].ctl_type = CTLTYPE_STRUCT;
1856			listall(string, &lp);
1857			free(lp.list);
1858			return (-1);
1859		}
1860		ptr = strstr(buf, name);
1861 tryagain:
1862		if (ptr == NULL) {
1863			warnx("fourth level name %s in %s is invalid", name,
1864			    string);
1865			return (-1);
1866		}
1867		if ((*(ptr + strlen(name)) != ',') &&
1868		    (*(ptr + strlen(name)) != '\0')) {
1869			ptr = strstr(ptr + 1, name); /* retry */
1870			goto tryagain;
1871		}
1872		if ((ptr != buf) && (*(ptr - 1) != ',')) {
1873			ptr = strstr(ptr + 1, name); /* retry */
1874			goto tryagain;
1875		}
1876		for (i = 0, stor = 0; buf + i < ptr; i++)
1877			if (buf[i] == ',')
1878				stor++;
1879		mib[3] = stor;
1880		return (4);
1881	} else if (mib[2] == KERN_MALLOC_KMEMNAMES) {
1882		*typep = CTLTYPE_STRING;
1883		return (3);
1884	}
1885	return (-1);
1886}
1887
1888#ifdef CPU_CHIPSET
1889/*
1890 * handle machdep.chipset requests
1891 */
1892struct ctlname chipsetname[] = CTL_CHIPSET_NAMES;
1893struct list chipsetlist = { chipsetname, CPU_CHIPSET_MAXID };
1894
1895int
1896sysctl_chipset(char *string, char **bufpp, int mib[], int flags, int *typep)
1897{
1898	int indx, bwx;
1899	static void *q;
1900	size_t len;
1901	char *p;
1902
1903	if (*bufpp == NULL) {
1904		listall(string, &chipsetlist);
1905		return (-1);
1906	}
1907	if ((indx = findname(string, "third", bufpp, &chipsetlist)) == -1)
1908		return (-1);
1909	mib[2] = indx;
1910	if (!nflag)
1911		printf("%s%s", string, equ);
1912	switch(mib[2]) {
1913	case CPU_CHIPSET_MEM:
1914	case CPU_CHIPSET_DENSE:
1915	case CPU_CHIPSET_PORTS:
1916	case CPU_CHIPSET_HAE_MASK:
1917		len = sizeof(void *);
1918		if (sysctl(mib, 3, &q, &len, NULL, 0) < 0)
1919			goto done;
1920		printf("%p", q);
1921		break;
1922	case CPU_CHIPSET_BWX:
1923		len = sizeof(int);
1924		if (sysctl(mib, 3, &bwx, &len, NULL, 0) < 0)
1925			goto done;
1926		printf("%d", bwx);
1927		break;
1928	case CPU_CHIPSET_TYPE:
1929		if (sysctl(mib, 3, NULL, &len, NULL, 0) < 0)
1930			goto done;
1931		p = malloc(len + 1);
1932		if (p == NULL)
1933			goto done;
1934		if (sysctl(mib, 3, p, &len, NULL, 0) < 0) {
1935			free(p);
1936			goto done;
1937		}
1938		p[len] = '\0';
1939		printf("%s", p);
1940		free(p);
1941		break;
1942	}
1943done:
1944	printf("\n");
1945	return (-1);
1946}
1947#endif
1948/*
1949 * handle internet requests
1950 */
1951int
1952sysctl_inet(char *string, char **bufpp, int mib[], int flags, int *typep)
1953{
1954	struct list *lp;
1955	int indx;
1956
1957	if (*bufpp == NULL) {
1958		listall(string, &inetlist);
1959		return (-1);
1960	}
1961	if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
1962		return (-1);
1963	mib[2] = indx;
1964	if (indx < IPPROTO_MAXID && inetvars[indx].list != NULL)
1965		lp = &inetvars[indx];
1966	else if (!flags)
1967		return (-1);
1968	else {
1969		warnx("%s: no variables defined for this protocol", string);
1970		return (-1);
1971	}
1972	if (*bufpp == NULL) {
1973		listall(string, lp);
1974		return (-1);
1975	}
1976	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1977		return (-1);
1978	mib[3] = indx;
1979	*typep = lp->list[indx].ctl_type;
1980	if (*typep == CTLTYPE_NODE) {
1981		int tindx;
1982
1983		if (*bufpp == NULL) {
1984			listall(string, &ifqlist);
1985			return(-1);
1986		}
1987		lp = &ifqlist;
1988		if ((tindx = findname(string, "fifth", bufpp, lp)) == -1)
1989			return (-1);
1990		mib[4] = tindx;
1991		*typep = lp->list[tindx].ctl_type;
1992		return(5);
1993	}
1994	return (4);
1995}
1996
1997#ifdef INET6
1998struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES;
1999struct ctlname ip6name[] = IPV6CTL_NAMES;
2000struct ctlname icmp6name[] = ICMPV6CTL_NAMES;
2001struct ctlname pim6name[] = PIM6CTL_NAMES;
2002struct ctlname divert6name[] = DIVERT6CTL_NAMES;
2003struct list inet6list = { inet6name, IPV6PROTO_MAXID };
2004struct list inet6vars[] = {
2005/*0*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2006	{ 0, 0 },
2007	{ 0, 0 },
2008	{ 0, 0 },
2009	{ 0, 0 },
2010	{ 0, 0 },
2011/*10*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2012	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2013/*20*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2014	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2015/*30*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2016	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2017/*40*/	{ 0, 0 },
2018	{ ip6name, IPV6CTL_MAXID },	/* ipv6 */
2019	{ 0, 0 },
2020	{ 0, 0 },
2021	{ 0, 0 },
2022	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2023/*50*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2024	{ 0, 0 },
2025	{ 0, 0 },
2026	{ 0, 0 },
2027	{ icmp6name, ICMPV6CTL_MAXID },	/* icmp6 */
2028	{ 0, 0 },
2029/*60*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2030	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2031/*70*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2032	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2033/*80*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2034	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2035/*90*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2036	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2037/*100*/	{ 0, 0 },
2038	{ 0, 0 },
2039	{ 0, 0 },
2040	{ pim6name, PIM6CTL_MAXID },	/* pim6 */
2041	{ 0, 0 },
2042	{ 0, 0 },
2043	{ 0, 0 },
2044	{ 0, 0 },
2045	{ 0, 0 },
2046	{ 0, 0 },
2047/*110*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2048	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2049/*120*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2050	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2051/*130*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2052	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2053/*140*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2054	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2055/*150*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2056	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2057/*160*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2058	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2059/*170*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2060	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2061/*180*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2062	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2063/*190*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2064	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2065/*200*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2066	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2067/*210*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2068	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2069/*220*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2070	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2071/*230*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2072	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2073/*240*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2074	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2075/*250*/	{ 0, 0 },
2076	{ 0, 0 },
2077	{ 0, 0 },
2078	{ 0, 0 },
2079	{ 0, 0 },
2080	{ 0, 0 },
2081	{ 0, 0 },
2082	{ 0, 0 },
2083	{ divert6name, DIVERT6CTL_MAXID },
2084};
2085
2086/*
2087 * handle internet6 requests
2088 */
2089int
2090sysctl_inet6(char *string, char **bufpp, int mib[], int flags, int *typep)
2091{
2092	struct list *lp;
2093	int indx;
2094
2095	if (*bufpp == NULL) {
2096		listall(string, &inet6list);
2097		return (-1);
2098	}
2099	if ((indx = findname(string, "third", bufpp, &inet6list)) == -1)
2100		return (-1);
2101	mib[2] = indx;
2102	if (indx < IPV6PROTO_MAXID && inet6vars[indx].list != NULL)
2103		lp = &inet6vars[indx];
2104	else if (!flags)
2105		return (-1);
2106	else {
2107		warnx("%s: no variables defined for this protocol", string);
2108		return (-1);
2109	}
2110	if (*bufpp == NULL) {
2111		listall(string, lp);
2112		return (-1);
2113	}
2114	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
2115		return (-1);
2116	mib[3] = indx;
2117	*typep = lp->list[indx].ctl_type;
2118	return (4);
2119}
2120#endif
2121
2122/* handle bpf requests */
2123int
2124sysctl_bpf(char *string, char **bufpp, int mib[], int flags, int *typep)
2125{
2126	int indx;
2127
2128	if (*bufpp == NULL) {
2129		listall(string, &bpflist);
2130		return (-1);
2131	}
2132	if ((indx = findname(string, "third", bufpp, &bpflist)) == -1)
2133		return (-1);
2134	mib[2] = indx;
2135	*typep = CTLTYPE_INT;
2136	return (3);
2137}
2138
2139struct ctlname mplsname[] = MPLSCTL_NAMES;
2140struct list mplslist = { mplsname, MPLSCTL_MAXID };
2141
2142/* handle MPLS requests */
2143int
2144sysctl_mpls(char *string, char **bufpp, int mib[], int flags, int *typep)
2145{
2146	struct list *lp;
2147	int indx;
2148
2149	if (*bufpp == NULL) {
2150		listall(string, &mplslist);
2151		return (-1);
2152	}
2153	if ((indx = findname(string, "third", bufpp, &mplslist)) == -1)
2154		return (-1);
2155	mib[2] = indx;
2156	*typep = mplslist.list[indx].ctl_type;
2157	if (*typep == CTLTYPE_NODE) {
2158		int tindx;
2159
2160		if (*bufpp == NULL) {
2161			listall(string, &ifqlist);
2162			return(-1);
2163		}
2164		lp = &ifqlist;
2165		if ((tindx = findname(string, "fourth", bufpp, lp)) == -1)
2166			return (-1);
2167		mib[3] = tindx;
2168		*typep = lp->list[tindx].ctl_type;
2169		return(4);
2170	}
2171	return (3);
2172}
2173
2174/* handle PIPEX requests */
2175int
2176sysctl_pipex(char *string, char **bufpp, int mib[], int flags, int *typep)
2177{
2178	struct list *lp;
2179	int indx;
2180
2181	if (*bufpp == NULL) {
2182		listall(string, &pipexlist);
2183		return (-1);
2184	}
2185	if ((indx = findname(string, "third", bufpp, &pipexlist)) == -1)
2186		return (-1);
2187	mib[2] = indx;
2188	*typep = pipexlist.list[indx].ctl_type;
2189	if (*typep == CTLTYPE_NODE) {
2190		int tindx;
2191
2192		if (*bufpp == NULL) {
2193			listall(string, &ifqlist);
2194			return(-1);
2195		}
2196		lp = &ifqlist;
2197		if ((tindx = findname(string, "fourth", bufpp, lp)) == -1)
2198			return (-1);
2199		mib[3] = tindx;
2200		*typep = lp->list[tindx].ctl_type;
2201		return(4);
2202	}
2203	return (3);
2204}
2205
2206/*
2207 * Handle SysV semaphore info requests
2208 */
2209int
2210sysctl_seminfo(string, bufpp, mib, flags, typep)
2211	char *string;
2212	char **bufpp;
2213	int mib[];
2214	int flags;
2215	int *typep;
2216{
2217	int indx;
2218
2219	if (*bufpp == NULL) {
2220		listall(string, &semlist);
2221		return (-1);
2222	}
2223	if ((indx = findname(string, "third", bufpp, &semlist)) == -1)
2224		return (-1);
2225	mib[2] = indx;
2226	*typep = CTLTYPE_INT;
2227	return (3);
2228}
2229
2230/*
2231 * Handle SysV shared memory info requests
2232 */
2233int
2234sysctl_shminfo(string, bufpp, mib, flags, typep)
2235	char *string;
2236	char **bufpp;
2237	int mib[];
2238	int flags;
2239	int *typep;
2240{
2241	int indx;
2242
2243	if (*bufpp == NULL) {
2244		listall(string, &shmlist);
2245		return (-1);
2246	}
2247	if ((indx = findname(string, "third", bufpp, &shmlist)) == -1)
2248		return (-1);
2249	mib[2] = indx;
2250	*typep = CTLTYPE_INT;
2251	return (3);
2252}
2253
2254/*
2255 * Handle watchdog support
2256 */
2257int
2258sysctl_watchdog(char *string, char **bufpp, int mib[], int flags,
2259    int *typep)
2260{
2261	int indx;
2262
2263	if (*bufpp == NULL) {
2264		listall(string, &watchdoglist);
2265		return (-1);
2266	}
2267	if ((indx = findname(string, "third", bufpp, &watchdoglist)) == -1)
2268		return (-1);
2269	mib[2] = indx;
2270	*typep = watchdoglist.list[indx].ctl_type;
2271	return (3);
2272}
2273
2274/*
2275 * Handle timecounter support
2276 */
2277int
2278sysctl_tc(char *string, char **bufpp, int mib[], int flags,
2279    int *typep)
2280{
2281	int indx;
2282
2283	if (*bufpp == NULL) {
2284		listall(string, &tclist);
2285		return (-1);
2286	}
2287	if ((indx = findname(string, "third", bufpp, &tclist)) == -1)
2288		return (-1);
2289	mib[2] = indx;
2290	*typep = tclist.list[indx].ctl_type;
2291	return (3);
2292}
2293
2294/*
2295 * Handle hardware monitoring sensors support
2296 */
2297int
2298sysctl_sensors(char *string, char **bufpp, int mib[], int flags, int *typep)
2299{
2300	char *devname, *typename;
2301	int dev, numt, i;
2302	enum sensor_type type;
2303	struct sensordev snsrdev;
2304	size_t sdlen = sizeof(snsrdev);
2305
2306	if (*bufpp == NULL) {
2307		char buf[SYSCTL_BUFSIZ];
2308
2309		/* scan all sensor devices */
2310		for (dev = 0; ; dev++) {
2311			mib[2] = dev;
2312			if (sysctl(mib, 3, &snsrdev, &sdlen, NULL, 0) == -1) {
2313				if (errno == ENXIO)
2314					continue;
2315				if (errno == ENOENT)
2316					break;
2317			}
2318			snprintf(buf, sizeof(buf), "%s.%s",
2319			    string, snsrdev.xname);
2320			print_sensordev(buf, mib, 3, &snsrdev);
2321		}
2322		return (-1);
2323	}
2324
2325	/*
2326	 * If we get this far, it means that some arguments were
2327	 * provided below hw.sensors tree.
2328	 * The first branch of hw.sensors tree is the device name.
2329	 */
2330	if ((devname = strsep(bufpp, ".")) == NULL) {
2331		warnx("%s: incomplete specification", string);
2332		return (-1);
2333	}
2334	/* convert sensor device string to an integer */
2335	for (dev = 0; ; dev++) {
2336		mib[2] = dev;
2337		if (sysctl(mib, 3, &snsrdev, &sdlen, NULL, 0) == -1) {
2338			if (errno == ENXIO)
2339				continue;
2340			if (errno == ENOENT)
2341				break;
2342		}
2343		if (strcmp(devname, snsrdev.xname) == 0)
2344			break;
2345	}
2346	if (strcmp(devname, snsrdev.xname) != 0) {
2347		warnx("%s: sensor device not found: %s", string, devname);
2348		return (-1);
2349	}
2350	if (*bufpp == NULL) {
2351		/* only device name was provided -- let's print all sensors
2352		 * that are attached to the specified device
2353		 */
2354		print_sensordev(string, mib, 3, &snsrdev);
2355		return (-1);
2356	}
2357
2358	/*
2359	 * At this point we have identified the sensor device,
2360	 * now let's go further and identify sensor type.
2361	 */
2362	if ((typename = strsep(bufpp, ".")) == NULL) {
2363		warnx("%s: incomplete specification", string);
2364		return (-1);
2365	}
2366	numt = -1;
2367	for (i = 0; typename[i] != '\0'; i++)
2368		if (isdigit(typename[i])) {
2369			numt = atoi(&typename[i]);
2370			typename[i] = '\0';
2371			break;
2372		}
2373	for (type = 0; type < SENSOR_MAX_TYPES; type++)
2374		if (strcmp(typename, sensor_type_s[type]) == 0)
2375			break;
2376	if (type == SENSOR_MAX_TYPES) {
2377		warnx("%s: sensor type not recognised: %s", string, typename);
2378		return (-1);
2379	}
2380	mib[3] = type;
2381
2382	/*
2383	 * If no integer was provided after sensor_type, let's
2384	 * print all sensors of the specified type.
2385	 */
2386	if (numt == -1) {
2387		print_sensordev(string, mib, 4, &snsrdev);
2388		return (-1);
2389	}
2390
2391	/*
2392	 * At this point we know that we have received a direct request
2393	 * via command-line for a specific sensor. Let's have the parse()
2394	 * function deal with it further, and report any errors if such
2395	 * sensor node does not exist.
2396	 */
2397	mib[4] = numt;
2398	*typep = CTLTYPE_STRUCT;
2399	return (5);
2400}
2401
2402/*
2403 * Print sensors from the specified device.
2404 */
2405
2406void
2407print_sensordev(char *string, int mib[], u_int mlen, struct sensordev *snsrdev)
2408{
2409	char buf[SYSCTL_BUFSIZ];
2410	enum sensor_type type;
2411
2412	if (mlen == 3) {
2413		for (type = 0; type < SENSOR_MAX_TYPES; type++) {
2414			mib[3] = type;
2415			snprintf(buf, sizeof(buf), "%s.%s",
2416			    string, sensor_type_s[type]);
2417			print_sensordev(buf, mib, mlen+1, snsrdev);
2418		}
2419		return;
2420	}
2421
2422	if (mlen == 4) {
2423		int numt;
2424
2425		type = mib[3];
2426		for (numt = 0; numt < snsrdev->maxnumt[type]; numt++) {
2427			mib[4] = numt;
2428			snprintf(buf, sizeof(buf), "%s%u", string, numt);
2429			print_sensordev(buf, mib, mlen+1, snsrdev);
2430		}
2431		return;
2432	}
2433
2434	if (mlen == 5) {
2435		struct sensor snsr;
2436		size_t slen = sizeof(snsr);
2437
2438		/* this function is only printing sensors in bulk, so we
2439		 * do not return any error messages if the requested sensor
2440		 * is not found by sysctl(3)
2441		 */
2442		if (sysctl(mib, 5, &snsr, &slen, NULL, 0) == -1)
2443			return;
2444
2445		if (slen > 0 && (snsr.flags & SENSOR_FINVALID) == 0) {
2446			if (!nflag)
2447				printf("%s%s", string, equ);
2448			print_sensor(&snsr);
2449			printf("\n");
2450		}
2451		return;
2452	}
2453}
2454
2455void
2456print_sensor(struct sensor *s)
2457{
2458	const char *name;
2459
2460	if (s->flags & SENSOR_FUNKNOWN)
2461		printf("unknown");
2462	else {
2463		switch (s->type) {
2464		case SENSOR_TEMP:
2465			printf("%.2f degC",
2466			    (s->value - 273150000) / 1000000.0);
2467			break;
2468		case SENSOR_FANRPM:
2469			printf("%lld RPM", s->value);
2470			break;
2471		case SENSOR_VOLTS_DC:
2472			printf("%.2f VDC", s->value / 1000000.0);
2473			break;
2474		case SENSOR_VOLTS_AC:
2475			printf("%.2f VAC", s->value / 1000000.0);
2476			break;
2477		case SENSOR_OHMS:
2478			printf("%lld ohm", s->value);
2479			break;
2480		case SENSOR_WATTS:
2481			printf("%.2f W", s->value / 1000000.0);
2482			break;
2483		case SENSOR_AMPS:
2484			printf("%.2f A", s->value / 1000000.0);
2485			break;
2486		case SENSOR_WATTHOUR:
2487			printf("%.2f Wh", s->value / 1000000.0);
2488			break;
2489		case SENSOR_AMPHOUR:
2490			printf("%.2f Ah", s->value / 1000000.0);
2491			break;
2492		case SENSOR_INDICATOR:
2493			printf("%s", s->value ? "On" : "Off");
2494			break;
2495		case SENSOR_INTEGER:
2496			printf("%lld", s->value);
2497			break;
2498		case SENSOR_PERCENT:
2499			printf("%.2f%%", s->value / 1000.0);
2500			break;
2501		case SENSOR_LUX:
2502			printf("%.2f lx", s->value / 1000000.0);
2503			break;
2504		case SENSOR_DRIVE:
2505			switch (s->value) {
2506			case SENSOR_DRIVE_EMPTY:
2507				name = "empty";
2508				break;
2509			case SENSOR_DRIVE_READY:
2510				name = "ready";
2511				break;
2512			case SENSOR_DRIVE_POWERUP:
2513				name = "powering up";
2514				break;
2515			case SENSOR_DRIVE_ONLINE:
2516				name = "online";
2517				break;
2518			case SENSOR_DRIVE_IDLE:
2519				name = "idle";
2520				break;
2521			case SENSOR_DRIVE_ACTIVE:
2522				name = "active";
2523				break;
2524			case SENSOR_DRIVE_REBUILD:
2525				name = "rebuilding";
2526				break;
2527			case SENSOR_DRIVE_POWERDOWN:
2528				name = "powering down";
2529				break;
2530			case SENSOR_DRIVE_FAIL:
2531				name = "failed";
2532				break;
2533			case SENSOR_DRIVE_PFAIL:
2534				name = "degraded";
2535				break;
2536			default:
2537				name = "unknown";
2538				break;
2539			}
2540			printf(name);
2541			break;
2542		case SENSOR_TIMEDELTA:
2543			printf("%.6f secs", s->value / 1000000000.0);
2544			break;
2545		case SENSOR_HUMIDITY:
2546			printf("%.2f%%", s->value / 1000.0);
2547			break;
2548		case SENSOR_FREQ:
2549			printf("%.2f Hz", s->value / 1000000.0);
2550			break;
2551		case SENSOR_ANGLE:
2552			printf("%3.4f degrees", s->value / 1000000.0);
2553			break;
2554		case SENSOR_DISTANCE:
2555			printf("%.2f mm", s->value / 1000.0);
2556			break;
2557		case SENSOR_PRESSURE:
2558			printf("%.2f Pa", s->value / 1000.0);
2559			break;
2560		case SENSOR_ACCEL:
2561			printf("%2.4f m/s^2", s->value / 1000000.0);
2562			break;
2563		default:
2564			printf("unknown");
2565		}
2566	}
2567
2568	if (s->desc[0] != '\0')
2569		printf(" (%s)", s->desc);
2570
2571	switch (s->status) {
2572	case SENSOR_S_UNSPEC:
2573		break;
2574	case SENSOR_S_OK:
2575		printf(", OK");
2576		break;
2577	case SENSOR_S_WARN:
2578		printf(", WARNING");
2579		break;
2580	case SENSOR_S_CRIT:
2581		printf(", CRITICAL");
2582		break;
2583	case SENSOR_S_UNKNOWN:
2584		printf(", UNKNOWN");
2585		break;
2586	}
2587
2588	if (s->tv.tv_sec) {
2589		time_t t = s->tv.tv_sec;
2590		char ct[26];
2591
2592		ctime_r(&t, ct);
2593		ct[19] = '\0';
2594		printf(", %s.%03ld", ct, s->tv.tv_usec / 1000);
2595	}
2596}
2597
2598struct emulname {
2599	char *name;
2600	int index;
2601} *emul_names;
2602int	emul_num, nemuls;
2603int	emul_init(void);
2604
2605int
2606sysctl_emul(char *string, char *newval, int flags)
2607{
2608	int mib[4], enabled, i, old, print, found = 0;
2609	char *head, *target;
2610	size_t len;
2611
2612	if (emul_init() == -1) {
2613		warnx("emul_init: out of memory");
2614		return (1);
2615	}
2616
2617	mib[0] = CTL_KERN;
2618	mib[1] = KERN_EMUL;
2619	mib[3] = KERN_EMUL_ENABLED;
2620	head = "kern.emul.";
2621
2622	if (aflag || strcmp(string, "kern.emul") == 0) {
2623		if (newval) {
2624			warnx("%s: specification is incomplete", string);
2625			return (1);
2626		}
2627		if (nflag)
2628			printf("%d\n", nemuls);
2629		else
2630			printf("%snemuls%s%d\n", head, equ, nemuls);
2631		for (i = 0; i < emul_num; i++) {
2632			if (emul_names[i].name == NULL)
2633				break;
2634			if (i > 0 && strcmp(emul_names[i].name,
2635			    emul_names[i-1].name) == 0)
2636				continue;
2637			mib[2] = emul_names[i].index;
2638			len = sizeof(int);
2639			if (sysctl(mib, 4, &enabled, &len, NULL, 0) == -1) {
2640				warn("%s", string);
2641				continue;
2642			}
2643			if (nflag)
2644				printf("%d\n", enabled);
2645			else
2646				printf("%s%s%s%d\n", head, emul_names[i].name,
2647				    equ, enabled);
2648		}
2649		return (0);
2650	}
2651	/* User specified a third level name */
2652	target = strrchr(string, '.');
2653	target++;
2654	if (strcmp(target, "nemuls") == 0) {
2655		if (newval) {
2656			warnx("Operation not permitted");
2657			return (1);
2658		}
2659		if (nflag)
2660			printf("%d\n", nemuls);
2661		else
2662			printf("%snemuls = %d\n", head, nemuls);
2663		return (0);
2664	}
2665	print = 1;
2666	for (i = 0; i < emul_num; i++) {
2667		if (!emul_names[i].name || (strcmp(target, emul_names[i].name)))
2668			continue;
2669		found = 1;
2670		mib[2] = emul_names[i].index;
2671		len = sizeof(int);
2672		if (newval) {
2673			enabled = atoi(newval);
2674			if (sysctl(mib, 4, &old, &len, &enabled, len) == -1) {
2675				warn("%s", string);
2676				print = 0;
2677				continue;
2678			}
2679			if (print) {
2680				if (nflag)
2681					printf("%d\n", enabled);
2682				else
2683					printf("%s%s: %d -> %d\n", head,
2684					    target, old, enabled);
2685			}
2686		} else {
2687			if (sysctl(mib, 4, &enabled, &len, NULL, 0) == -1) {
2688				warn("%s", string);
2689				continue;
2690			}
2691			if (print) {
2692				if (nflag)
2693					printf("%d\n", enabled);
2694				else
2695					printf("%s%s = %d\n", head, target,
2696					    enabled);
2697			}
2698		}
2699		print = 0;
2700	}
2701	if (!found)
2702		warnx("third level name %s in kern.emul is invalid",
2703		    string);
2704	return (0);
2705
2706
2707}
2708
2709int
2710emulcmp(const void *m, const void *n)
2711{
2712	const struct emulname *a = m, *b = n;
2713
2714	if (!a || !a->name)
2715		return 1;
2716	if (!b || !b->name)
2717		return -1;
2718	return (strcmp(a->name, b->name));
2719}
2720
2721int
2722emul_init(void)
2723{
2724	static int done;
2725	char string[16];
2726	int mib[4], i;
2727	size_t len;
2728
2729	if (done)
2730		return (0);
2731	done = 1;
2732
2733	mib[0] = CTL_KERN;
2734	mib[1] = KERN_EMUL;
2735	mib[2] = KERN_EMUL_NUM;
2736	len = sizeof(int);
2737	if (sysctl(mib, 3, &emul_num, &len, NULL, 0) == -1)
2738		return (-1);
2739
2740	emul_names = calloc(emul_num, sizeof(*emul_names));
2741	if (emul_names == NULL)
2742		return (-1);
2743
2744	nemuls = emul_num;
2745	for (i = 0; i < emul_num; i++) {
2746		emul_names[i].index = mib[2] = i + 1;
2747		mib[3] = KERN_EMUL_NAME;
2748		len = sizeof(string);
2749		if (sysctl(mib, 4, string, &len, NULL, 0) == -1)
2750			continue;
2751		if (strcmp(string, "native") == 0)
2752			continue;
2753		emul_names[i].name = strdup(string);
2754		if (emul_names[i].name == NULL) {
2755			free(emul_names);
2756			return (-1);
2757		}
2758	}
2759	qsort(emul_names, nemuls, sizeof(*emul_names), emulcmp);
2760	for (i = 0; i < emul_num; i++) {
2761		if (!emul_names[i].name || (i > 0 &&
2762		    strcmp(emul_names[i].name, emul_names[i - 1].name) == 0))
2763			nemuls--;
2764	}
2765	return (0);
2766}
2767
2768/*
2769 * Scan a list of names searching for a particular name.
2770 */
2771int
2772findname(char *string, char *level, char **bufp, struct list *namelist)
2773{
2774	char *name;
2775	int i;
2776
2777	if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
2778		warnx("%s: incomplete specification", string);
2779		return (-1);
2780	}
2781	for (i = 0; i < namelist->size; i++)
2782		if (namelist->list[i].ctl_name != NULL &&
2783		    strcmp(name, namelist->list[i].ctl_name) == 0)
2784			break;
2785	if (i == namelist->size) {
2786		warnx("%s level name %s in %s is invalid", level, name, string);
2787		return (-1);
2788	}
2789	return (i);
2790}
2791
2792void
2793usage(void)
2794{
2795
2796	(void)fprintf(stderr,
2797	    "usage: sysctl [-Aan]\n"
2798	    "       sysctl [-n] name ...\n"
2799	    "       sysctl [-nq] name=value ...\n");
2800	exit(1);
2801}
2802