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