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