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