xref: /openbsd-src/sbin/sysctl/sysctl.c (revision d874cce4b1d9fe6b41c9e4f2117a77d8a4a37b92)
1 /*	$OpenBSD: sysctl.c,v 1.157 2008/04/28 11:52:53 norby 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.157 2008/04/28 11:52:53 norby 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 struct list {
148 	struct	ctlname *list;
149 	int	size;
150 };
151 struct list toplist = { topname, CTL_MAXID };
152 struct list secondlevel[] = {
153 	{ 0, 0 },			/* CTL_UNSPEC */
154 	{ kernname, KERN_MAXID },	/* CTL_KERN */
155 	{ vmname, VM_MAXID },		/* CTL_VM */
156 	{ fsname, FS_MAXID },		/* CTL_FS */
157 	{ netname, NET_MAXID },		/* CTL_NET */
158 	{ 0, CTL_DEBUG_MAXID },		/* CTL_DEBUG */
159 	{ hwname, HW_MAXID },		/* CTL_HW */
160 #ifdef CTL_MACHDEP_NAMES
161 	{ machdepname, CPU_MAXID },	/* CTL_MACHDEP */
162 #else
163 	{ 0, 0 },			/* CTL_MACHDEP */
164 #endif
165 	{ username, USER_MAXID },	/* CTL_USER_NAMES */
166 	{ ddbname, DBCTL_MAXID },	/* CTL_DDB_NAMES */
167 	{ 0, 0 },			/* CTL_VFS */
168 };
169 
170 int	Aflag, aflag, nflag, qflag;
171 
172 /*
173  * Variables requiring special processing.
174  */
175 #define	CLOCK		0x00000001
176 #define	BOOTTIME	0x00000002
177 #define	CHRDEV		0x00000004
178 #define	BLKDEV		0x00000008
179 #define	RNDSTATS	0x00000010
180 #define	BADDYNAMIC	0x00000020
181 #define	BIOSGEO		0x00000040
182 #define	BIOSDEV		0x00000080
183 #define	MAJ2DEV		0x00000100
184 #define	UNSIGNED	0x00000200
185 #define	KMEMBUCKETS	0x00000400
186 #define	LONGARRAY	0x00000800
187 #define	KMEMSTATS	0x00001000
188 #define	SENSORS		0x00002000
189 
190 /* prototypes */
191 void debuginit(void);
192 void listall(char *, struct list *);
193 void parse(char *, int);
194 void parse_baddynamic(int *, size_t, char *, void **, size_t *, int, int);
195 void usage(void);
196 int findname(char *, char *, char **, struct list *);
197 int sysctl_inet(char *, char **, int *, int, int *);
198 #ifdef INET6
199 int sysctl_inet6(char *, char **, int *, int, int *);
200 #endif
201 int sysctl_bpf(char *, char **, int *, int, int *);
202 int sysctl_mpls(char *, char **, int *, int, int *);
203 int sysctl_fs(char *, char **, int *, int, int *);
204 static int sysctl_vfs(char *, char **, int[], int, int *);
205 static int sysctl_vfsgen(char *, char **, int[], int, int *);
206 int sysctl_bios(char *, char **, int *, int, int *);
207 int sysctl_swpenc(char *, char **, int *, int, int *);
208 int sysctl_forkstat(char *, char **, int *, int, int *);
209 int sysctl_tty(char *, char **, int *, int, int *);
210 int sysctl_nchstats(char *, char **, int *, int, int *);
211 int sysctl_malloc(char *, char **, int *, int, int *);
212 int sysctl_seminfo(char *, char **, int *, int, int *);
213 int sysctl_shminfo(char *, char **, int *, int, int *);
214 int sysctl_watchdog(char *, char **, int *, int, int *);
215 int sysctl_tc(char *, char **, int *, int, int *);
216 int sysctl_sensors(char *, char **, int *, int, int *);
217 void print_sensordev(char *, int *, u_int, struct sensordev *);
218 void print_sensor(struct sensor *);
219 int sysctl_emul(char *, char *, int);
220 #ifdef CPU_CHIPSET
221 int sysctl_chipset(char *, char **, int *, int, int *);
222 #endif
223 void vfsinit(void);
224 
225 char *equ = "=";
226 
227 int
228 main(int argc, char *argv[])
229 {
230 	int ch, lvl1;
231 
232 	while ((ch = getopt(argc, argv, "Aanqw")) != -1) {
233 		switch (ch) {
234 
235 		case 'A':
236 			Aflag = 1;
237 			break;
238 
239 		case 'a':
240 			aflag = 1;
241 			break;
242 
243 		case 'n':
244 			nflag = 1;
245 			break;
246 
247 		case 'q':
248 			qflag = 1;
249 			break;
250 
251 		case 'w':
252 			/* flag no longer needed; var=value implies write */
253 			break;
254 
255 		default:
256 			usage();
257 		}
258 	}
259 	argc -= optind;
260 	argv += optind;
261 
262 	if (argc == 0 || (Aflag || aflag)) {
263 		debuginit();
264 		vfsinit();
265 		for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
266 			listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
267 		return (0);
268 	}
269 	for (; *argv != NULL; ++argv)
270 		parse(*argv, 1);
271 	return (0);
272 }
273 
274 /*
275  * List all variables known to the system.
276  */
277 void
278 listall(char *prefix, struct list *lp)
279 {
280 	char *cp, name[BUFSIZ];
281 	int lvl2, len;
282 
283 	if (lp->list == NULL)
284 		return;
285 	if ((len = strlcpy(name, prefix, sizeof(name))) >= sizeof(name))
286 		errx(1, "%s: name too long", prefix);
287 	cp = name + len++;
288 	*cp++ = '.';
289 	for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
290 		if (lp->list[lvl2].ctl_name == NULL)
291 			continue;
292 		if (strlcpy(cp, lp->list[lvl2].ctl_name,
293 		    sizeof(name) - len) >= sizeof(name) - len)
294 			warn("%s: name too long", lp->list[lvl2].ctl_name);
295 		parse(name, Aflag);
296 	}
297 }
298 
299 /*
300  * Parse a name into a MIB entry.
301  * Lookup and print out the MIB entry if it exists.
302  * Set a new value if requested.
303  */
304 void
305 parse(char *string, int flags)
306 {
307 	int indx, type, state, intval, len;
308 	size_t size, newsize = 0;
309 	int lal = 0, special = 0;
310 	void *newval = NULL;
311 	int64_t quadval;
312 	struct list *lp;
313 	int mib[CTL_MAXNAME];
314 	char *cp, *bufp, buf[BUFSIZ];
315 
316 	(void)strlcpy(buf, string, sizeof(buf));
317 	bufp = buf;
318 	if ((cp = strchr(string, '=')) != NULL) {
319 		*strchr(buf, '=') = '\0';
320 		*cp++ = '\0';
321 		while (isspace(*cp))
322 			cp++;
323 		newval = cp;
324 		newsize = strlen(cp);
325 	}
326 	if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
327 		return;
328 	mib[0] = indx;
329 	if (indx == CTL_VFS)
330 		vfsinit();
331 	if (indx == CTL_DEBUG)
332 		debuginit();
333 	lp = &secondlevel[indx];
334 	if (lp->list == 0) {
335 		warnx("%s: class is not implemented", topname[indx].ctl_name);
336 		return;
337 	}
338 	if (bufp == NULL) {
339 		listall(topname[indx].ctl_name, lp);
340 		return;
341 	}
342 	if ((indx = findname(string, "second", &bufp, lp)) == -1)
343 		return;
344 	mib[1] = indx;
345 	type = lp->list[indx].ctl_type;
346 	len = 2;
347 	switch (mib[0]) {
348 
349 	case CTL_KERN:
350 		switch (mib[1]) {
351 		case KERN_PROF:
352 			mib[2] = GPROF_STATE;
353 			size = sizeof(state);
354 			if (sysctl(mib, 3, &state, &size, NULL, 0) == -1) {
355 				if (flags == 0)
356 					return;
357 				if (!nflag)
358 					(void)printf("%s: ", string);
359 				(void)puts("kernel is not compiled for profiling");
360 				return;
361 			}
362 			if (!nflag)
363 				(void)printf("%s = %s\n", string,
364 				    state == GMON_PROF_OFF ? "off" : "running");
365 			return;
366 		case KERN_FORKSTAT:
367 			sysctl_forkstat(string, &bufp, mib, flags, &type);
368 			return;
369 		case KERN_TTY:
370 			len = sysctl_tty(string, &bufp, mib, flags, &type);
371 			if (len < 0)
372 				return;
373 			break;
374 		case KERN_NCHSTATS:
375 			sysctl_nchstats(string, &bufp, mib, flags, &type);
376 			return;
377 		case KERN_MALLOCSTATS:
378 			len = sysctl_malloc(string, &bufp, mib, flags, &type);
379 			if (len < 0)
380 				return;
381 			if (mib[2] == KERN_MALLOC_BUCKET)
382 				special |= KMEMBUCKETS;
383 			if (mib[2] == KERN_MALLOC_KMEMSTATS)
384 				special |= KMEMSTATS;
385 			newsize = 0;
386 			break;
387 		case KERN_MBSTAT:
388 			if (flags == 0)
389 				return;
390 			warnx("use netstat to view %s", string);
391 			return;
392 		case KERN_MSGBUF:
393 			if (flags == 0)
394 				return;
395 			warnx("use dmesg to view %s", string);
396 			return;
397 		case KERN_VNODE:
398 		case KERN_FILE:
399 			if (flags == 0)
400 				return;
401 			warnx("use pstat to view %s information", string);
402 			return;
403 		case KERN_PROC:
404 		case KERN_PROC2:
405 			if (flags == 0)
406 				return;
407 			warnx("use ps to view %s information", string);
408 			return;
409 		case KERN_CLOCKRATE:
410 			special |= CLOCK;
411 			break;
412 		case KERN_BOOTTIME:
413 			special |= BOOTTIME;
414 			break;
415 		case KERN_RND:
416 			special |= RNDSTATS;
417 			break;
418 		case KERN_HOSTID:
419 		case KERN_ARND:
420 			special |= UNSIGNED;
421 			break;
422 		case KERN_CPTIME:
423 			special |= LONGARRAY;
424 			lal = CPUSTATES;
425 			break;
426 		case KERN_SEMINFO:
427 			len = sysctl_seminfo(string, &bufp, mib, flags, &type);
428 			if (len < 0)
429 				return;
430 			break;
431 		case KERN_SHMINFO:
432 			len = sysctl_shminfo(string, &bufp, mib, flags, &type);
433 			if (len < 0)
434 				return;
435 			break;
436 		case KERN_WATCHDOG:
437 			len = sysctl_watchdog(string, &bufp, mib, flags,
438 			    &type);
439 			if (len < 0)
440 				return;
441 			break;
442 		case KERN_TIMECOUNTER:
443 			len = sysctl_tc(string, &bufp, mib, flags,
444 			    &type);
445 			if (len < 0)
446 				return;
447 			break;
448 		case KERN_EMUL:
449 			sysctl_emul(string, newval, flags);
450 			return;
451 		}
452 		break;
453 
454 	case CTL_HW:
455 		switch (mib[1]) {
456 		case HW_DISKSTATS:
457 			/*
458 			 * Only complain if someone asks explicitly for this,
459 			 * otherwise "fail" silently.
460 			 */
461 			if (flags)
462 				warnx("use vmstat to view %s information",
463 				    string);
464 			return;
465 		case HW_SENSORS:
466 			special |= SENSORS;
467 			len = sysctl_sensors(string, &bufp, mib, flags, &type);
468 			if (len < 0)
469 				return;
470 			break;
471 		case HW_PHYSMEM:
472 		case HW_USERMEM:
473 			/*
474 			 * Don't print these; we'll print the 64-bit
475 			 * variants instead.
476 			 */
477 			return;
478 		}
479 		break;
480 
481 	case CTL_VM:
482 		if (mib[1] == VM_LOADAVG) {
483 			double loads[3];
484 
485 			getloadavg(loads, 3);
486 			if (!nflag)
487 				(void)printf("%s%s", string, equ);
488 			(void)printf("%.2f %.2f %.2f\n", loads[0],
489 			    loads[1], loads[2]);
490 			return;
491 		} else if (mib[1] == VM_PSSTRINGS) {
492 			struct _ps_strings _ps;
493 
494 			size = sizeof(_ps);
495 			if (sysctl(mib, 2, &_ps, &size, NULL, 0) == -1) {
496 				if (flags == 0)
497 					return;
498 				if (!nflag)
499 					(void)printf("%s: ", string);
500 				(void)puts("can't find ps strings");
501 				return;
502 			}
503 			if (!nflag)
504 				(void)printf("%s%s", string, equ);
505 			(void)printf("%p\n", _ps.val);
506 			return;
507 		} else if (mib[1] == VM_SWAPENCRYPT) {
508 			len = sysctl_swpenc(string, &bufp, mib, flags, &type);
509 			if (len < 0)
510 				return;
511 
512 			break;
513 		} else if (mib[1] == VM_NKMEMPAGES ||
514 		    mib[1] == VM_ANONMIN ||
515 		    mib[1] == VM_VTEXTMIN ||
516 		    mib[1] == VM_VNODEMIN) {
517 			break;
518 		}
519 		if (flags == 0)
520 			return;
521 		warnx("use vmstat or systat to view %s information", string);
522 		return;
523 
524 		break;
525 
526 	case CTL_NET:
527 		if (mib[1] == PF_INET) {
528 			len = sysctl_inet(string, &bufp, mib, flags, &type);
529 			if (len < 0)
530 				return;
531 
532 			if ((mib[2] == IPPROTO_IP && mib[3] == IPCTL_MRTSTATS) ||
533 			    (mib[2] == IPPROTO_IP && mib[3] == IPCTL_STATS) ||
534 			    (mib[2] == IPPROTO_TCP && mib[3] == TCPCTL_STATS) ||
535 			    (mib[2] == IPPROTO_UDP && mib[3] == UDPCTL_STATS) ||
536 			    (mib[2] == IPPROTO_ESP && mib[3] == ESPCTL_STATS) ||
537 			    (mib[2] == IPPROTO_AH && mib[3] == AHCTL_STATS) ||
538 			    (mib[2] == IPPROTO_IGMP && mib[3] == IGMPCTL_STATS) ||
539 			    (mib[2] == IPPROTO_ETHERIP && mib[3] == ETHERIPCTL_STATS) ||
540 			    (mib[2] == IPPROTO_IPIP && mib[3] == IPIPCTL_STATS) ||
541 			    (mib[2] == IPPROTO_IPCOMP && mib[3] == IPCOMPCTL_STATS) ||
542 			    (mib[2] == IPPROTO_ICMP && mib[3] == ICMPCTL_STATS) ||
543 			    (mib[2] == IPPROTO_CARP && mib[3] == CARPCTL_STATS) ||
544 			    (mib[2] == IPPROTO_PFSYNC && mib[3] == PFSYNCCTL_STATS)) {
545 				if (flags == 0)
546 					return;
547 				warnx("use netstat to view %s information",
548 				    string);
549 				return;
550 			} else if ((mib[2] == IPPROTO_TCP &&
551 			    mib[3] == TCPCTL_BADDYNAMIC) ||
552 			    (mib[2] == IPPROTO_UDP &&
553 			    mib[3] == UDPCTL_BADDYNAMIC)) {
554 
555 				special |= BADDYNAMIC;
556 
557 				if (newval != NULL)
558 					parse_baddynamic(mib, len, string,
559 					    &newval, &newsize, flags, nflag);
560 			}
561 			break;
562 		}
563 #ifdef INET6
564 		if (mib[1] == PF_INET6) {
565 			len = sysctl_inet6(string, &bufp, mib, flags, &type);
566 			if (len < 0)
567 				return;
568 
569 			if ((mib[2] == IPPROTO_PIM && mib[3] == PIM6CTL_STATS)) {
570 				if (flags == 0)
571 					return;
572 				warnx("use netstat to view %s information",
573 				    string);
574 				return;
575 			}
576 			break;
577 		}
578 #endif
579 		if (mib[1] == PF_BPF) {
580 			len = sysctl_bpf(string, &bufp, mib, flags, &type);
581 			if (len < 0)
582 				return;
583 			break;
584 		}
585 		if (mib[1] == PF_MPLS) {
586 			len = sysctl_mpls(string, &bufp, mib, flags, &type);
587 			if (len < 0)
588 				return;
589 			break;
590 		}
591 		if (flags == 0)
592 			return;
593 		warnx("use netstat to view %s information", string);
594 		return;
595 
596 	case CTL_DEBUG:
597 		mib[2] = CTL_DEBUG_VALUE;
598 		len = 3;
599 		break;
600 
601 	case CTL_MACHDEP:
602 #ifdef CPU_CONSDEV
603 		if (mib[1] == CPU_CONSDEV)
604 			special |= CHRDEV;
605 #endif
606 #ifdef CPU_BLK2CHR
607 		if (mib[1] == CPU_BLK2CHR) {
608 			if (bufp == NULL)
609 				return;
610 			mib[2] = makedev(atoi(bufp),0);
611 			bufp = NULL;
612 			len = 3;
613 			special |= CHRDEV;
614 			break;
615 		}
616 #endif
617 #ifdef CPU_CHR2BLK
618 		if (mib[1] == CPU_CHR2BLK) {
619 			if (bufp == NULL)
620 				return;
621 			mib[2] = makedev(atoi(bufp),0);
622 			bufp = NULL;
623 			len = 3;
624 			special |= BLKDEV;
625 			break;
626 		}
627 #endif
628 #ifdef CPU_BIOS
629 		if (mib[1] == CPU_BIOS) {
630 			len = sysctl_bios(string, &bufp, mib, flags, &type);
631 			if (len < 0)
632 				return;
633 			if (mib[2] == BIOS_DEV)
634 				special |= BIOSDEV;
635 			if (mib[2] == BIOS_DISKINFO)
636 				special |= BIOSGEO;
637 			break;
638 		}
639 #endif
640 #ifdef CPU_CHIPSET
641 		if (mib[1] == CPU_CHIPSET) {
642 			len = sysctl_chipset(string, &bufp, mib, flags, &type);
643 			if (len < 0)
644 				return;
645 			break;
646 		}
647 #endif
648 		break;
649 
650 	case CTL_FS:
651 		len = sysctl_fs(string, &bufp, mib, flags, &type);
652 		if (len >= 0)
653 			break;
654 		return;
655 
656 	case CTL_VFS:
657 		if (mib[1])
658 			len = sysctl_vfs(string, &bufp, mib, flags, &type);
659 		else
660 			len = sysctl_vfsgen(string, &bufp, mib, flags, &type);
661 		if (len >= 0) {
662 			if (type == CTLTYPE_STRUCT) {
663 				if (flags)
664 					warnx("use nfsstat to view %s information",
665 					    MOUNT_NFS);
666 				return;
667 			} else
668 				break;
669 		}
670 		return;
671 
672 	case CTL_USER:
673 	case CTL_DDB:
674 		break;
675 
676 	default:
677 		warnx("illegal top level value: %d", mib[0]);
678 		return;
679 
680 	}
681 	if (bufp) {
682 		warnx("name %s in %s is unknown", bufp, string);
683 		return;
684 	}
685 	if (newsize > 0) {
686 		switch (type) {
687 		case CTLTYPE_INT:
688 			errno = 0;
689 			if (special & UNSIGNED)
690 				intval = strtoul(newval, &cp, 10);
691 			else
692 				intval = strtol(newval, &cp, 10);
693 			if (*cp != '\0') {
694 				warnx("%s: illegal value: %s", string,
695 				    (char *)newval);
696 				return;
697 			}
698 			if (errno == ERANGE) {
699 				warnx("%s: value %s out of range", string,
700 				    (char *)newval);
701 				return;
702 			}
703 			newval = &intval;
704 			newsize = sizeof(intval);
705 			break;
706 
707 		case CTLTYPE_QUAD:
708 			/* XXX - assumes sizeof(long long) == sizeof(quad_t) */
709 			(void)sscanf(newval, "%lld", (long long *)&quadval);
710 			newval = &quadval;
711 			newsize = sizeof(quadval);
712 			break;
713 		}
714 	}
715 	size = BUFSIZ;
716 	if (sysctl(mib, len, buf, &size, newval, newsize) == -1) {
717 		if (flags == 0)
718 			return;
719 		switch (errno) {
720 		case EOPNOTSUPP:
721 			warnx("%s: value is not available", string);
722 			return;
723 		case ENOTDIR:
724 			warnx("%s: specification is incomplete", string);
725 			return;
726 		case ENOMEM:
727 			warnx("%s: type is unknown to this program", string);
728 			return;
729 		case ENXIO:
730 			if (special & BIOSGEO)
731 				return;
732 		default:
733 			warn("%s", string);
734 			return;
735 		}
736 	}
737 	if (special & KMEMBUCKETS) {
738 		struct kmembuckets *kb = (struct kmembuckets *)buf;
739 		if (!nflag)
740 			(void)printf("%s%s", string, equ);
741 		printf("(");
742 		printf("calls = %llu ", (long long)kb->kb_calls);
743 		printf("total_allocated = %llu ", (long long)kb->kb_total);
744 		printf("total_free = %lld ", (long long)kb->kb_totalfree);
745 		printf("elements = %lld ", (long long)kb->kb_elmpercl);
746 		printf("high watermark = %lld ", (long long)kb->kb_highwat);
747 		printf("could_free = %lld", (long long)kb->kb_couldfree);
748 		printf(")\n");
749 		return;
750 	}
751 	if (special & KMEMSTATS) {
752 		struct kmemstats *km = (struct kmemstats *)buf;
753 		int j, first = 1;
754 
755 		if (!nflag)
756 			(void)printf("%s%s", string, equ);
757 		(void)printf("(inuse = %ld, calls = %ld, memuse = %ldK, "
758 		    "limblocks = %d, mapblocks = %d, maxused = %ldK, "
759 		    "limit = %ldK, spare = %ld, sizes = (",
760 		    km->ks_inuse, km->ks_calls,
761 		    (km->ks_memuse + 1023) / 1024, km->ks_limblocks,
762 		    km->ks_mapblocks, (km->ks_maxused + 1023) / 1024,
763 		    (km->ks_limit + 1023) / 1024, km->ks_spare);
764 		for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
765 			if ((km->ks_size & j ) == 0)
766 				continue;
767 			if (first)
768 				(void)printf("%d", j);
769 			else
770 				(void)printf(",%d", j);
771 			first = 0;
772 		}
773 		if (first)
774 			(void)printf("none");
775 		(void)printf("))\n");
776 		return;
777 	}
778 	if (special & CLOCK) {
779 		struct clockinfo *clkp = (struct clockinfo *)buf;
780 
781 		if (!nflag)
782 			(void)printf("%s%s", string, equ);
783 		(void)printf(
784 		    "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n",
785 		    clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz);
786 		return;
787 	}
788 	if (special & BOOTTIME) {
789 		struct timeval *btp = (struct timeval *)buf;
790 		time_t boottime;
791 
792 		if (!nflag) {
793 			boottime = btp->tv_sec;
794 			(void)printf("%s%s%s", string, equ, ctime(&boottime));
795 		} else
796 			(void)printf("%ld\n", btp->tv_sec);
797 		return;
798 	}
799 	if (special & BLKDEV) {
800 		dev_t dev = *(dev_t *)buf;
801 
802 		if (!nflag)
803 			(void)printf("%s%s%s\n", string, equ,
804 			    devname(dev, S_IFBLK));
805 		else
806 			(void)printf("0x%x\n", dev);
807 		return;
808 	}
809 	if (special & CHRDEV) {
810 		dev_t dev = *(dev_t *)buf;
811 
812 		if (!nflag)
813 			(void)printf("%s%s%s\n", string, equ,
814 			    devname(dev, S_IFCHR));
815 		else
816 			(void)printf("0x%x\n", dev);
817 		return;
818 	}
819 #ifdef CPU_BIOS
820 	if (special & BIOSGEO) {
821 		bios_diskinfo_t *pdi = (bios_diskinfo_t *)buf;
822 
823 		if (!nflag)
824 			(void)printf("%s%s", string, equ);
825 		(void)printf("bootdev = 0x%x, "
826 		    "cylinders = %u, heads = %u, sectors = %u\n",
827 		    pdi->bsd_dev, pdi->bios_cylinders,
828 		    pdi->bios_heads, pdi->bios_sectors);
829 		return;
830 	}
831 	if (special & BIOSDEV) {
832 		int dev = *(int*)buf;
833 
834 		if (!nflag)
835 			(void)printf("%s%s", string, equ);
836 		(void) printf("0x%02x\n", dev);
837 		return;
838 	}
839 #endif
840 	if (special & UNSIGNED) {
841 		if (newsize == 0) {
842 			if (!nflag)
843 				(void)printf("%s%s", string, equ);
844 			(void)printf("%u\n", *(u_int *)buf);
845 		} else {
846 			if (!qflag) {
847 				if (!nflag)
848 					(void)printf("%s: %u -> ", string,
849 					    *(u_int *)buf);
850 				(void)printf("%u\n", *(u_int *)newval);
851 			}
852 		}
853 		return;
854 	}
855 	if (special & RNDSTATS) {
856 		struct rndstats *rndstats = (struct rndstats *)buf;
857 		int i;
858 
859 		if (!nflag)
860 			(void)printf("%s%s", string, equ);
861 		(void)printf(
862 		"%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
863 		    (unsigned long long)rndstats->rnd_total,
864 		    (unsigned long long)rndstats->rnd_used,
865 		    (unsigned long long)rndstats->rnd_reads,
866 		    (unsigned long long)rndstats->arc4_reads,
867 		    (unsigned long long)rndstats->arc4_nstirs,
868 		    (unsigned long long)rndstats->arc4_stirs,
869 		    (unsigned long long)rndstats->rnd_pad[0],
870 		    (unsigned long long)rndstats->rnd_pad[1],
871 		    (unsigned long long)rndstats->rnd_pad[2],
872 		    (unsigned long long)rndstats->rnd_pad[3],
873 		    (unsigned long long)rndstats->rnd_pad[4],
874 		    (unsigned long long)rndstats->rnd_waits,
875 		    (unsigned long long)rndstats->rnd_enqs,
876 		    (unsigned long long)rndstats->rnd_deqs,
877 		    (unsigned long long)rndstats->rnd_drops,
878 		    (unsigned long long)rndstats->rnd_drople);
879 		for (i = 0; i < sizeof(rndstats->rnd_ed)/sizeof(rndstats->rnd_ed[0]);
880 		    i++)
881 			(void)printf(" %llu", (unsigned long long)rndstats->rnd_ed[i]);
882 		for (i = 0; i < sizeof(rndstats->rnd_sc)/sizeof(rndstats->rnd_sc[0]);
883 		    i++)
884 			(void)printf(" %llu", (unsigned long long)rndstats->rnd_sc[i]);
885 		for (i = 0; i < sizeof(rndstats->rnd_sb)/sizeof(rndstats->rnd_sb[0]);
886 		    i++)
887 			(void)printf(" %llu", (unsigned long long)rndstats->rnd_sb[i]);
888 		printf("\n");
889 		return;
890 	}
891 	if (special & BADDYNAMIC) {
892 		in_port_t port, lastport;
893 		u_int32_t *baddynamic = (u_int32_t *)buf;
894 
895 		if (!qflag) {
896 			if (!nflag)
897 				(void)printf("%s%s", string,
898 				    newsize ? ": " : equ);
899 			lastport = 0;
900 			for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED;
901 			    port++)
902 				if (DP_ISSET(baddynamic, port)) {
903 					(void)printf("%s%hd",
904 					    lastport ? "," : "", port);
905 					lastport = port;
906 				}
907 			if (newsize != 0) {
908 				if (!nflag)
909 					fputs(" -> ", stdout);
910 				baddynamic = (u_int32_t *)newval;
911 				lastport = 0;
912 				for (port = IPPORT_RESERVED/2;
913 				    port < IPPORT_RESERVED; port++)
914 					if (DP_ISSET(baddynamic, port)) {
915 						(void)printf("%s%hd",
916 						    lastport ? "," : "", port);
917 						lastport = port;
918 					}
919 			}
920 			(void)putchar('\n');
921 		}
922 		return;
923 	}
924 	if (special & LONGARRAY) {
925 		long *la = (long *)buf;
926 		if (!nflag)
927 			printf("%s%s", string, equ);
928 		while (lal--)
929 			printf("%ld%s", *la++, lal? ",":"");
930 		putchar('\n');
931 		return;
932 	}
933 	if (special & SENSORS) {
934 		struct sensor *s = (struct sensor *)buf;
935 
936 		if (size > 0 && (s->flags & SENSOR_FINVALID) == 0) {
937 			if (!nflag)
938 				printf("%s%s", string, equ);
939 			print_sensor(s);
940 			printf("\n");
941 		}
942 		return;
943 	}
944 	switch (type) {
945 	case CTLTYPE_INT:
946 		if (newsize == 0) {
947 			if (!nflag)
948 				(void)printf("%s%s", string, equ);
949 			(void)printf("%d\n", *(int *)buf);
950 		} else {
951 			if (!qflag) {
952 				if (!nflag)
953 					(void)printf("%s: %d -> ", string,
954 					    *(int *)buf);
955 				(void)printf("%d\n", *(int *)newval);
956 			}
957 		}
958 		return;
959 
960 	case CTLTYPE_STRING:
961 		if (newval == NULL) {
962 			if (!nflag)
963 				(void)printf("%s%s", string, equ);
964 			(void)puts(buf);
965 		} else {
966 			if (!qflag) {
967 				if (!nflag)
968 					(void)printf("%s: %s -> ", string, buf);
969 				(void)puts((char *)newval);
970 			}
971 		}
972 		return;
973 
974 	case CTLTYPE_QUAD:
975 		if (newsize == 0) {
976 			long long tmp = *(quad_t *)buf;
977 
978 			if (!nflag)
979 				(void)printf("%s%s", string, equ);
980 			(void)printf("%lld\n", tmp);
981 		} else {
982 			long long tmp = *(quad_t *)buf;
983 
984 			if (!qflag) {
985 				if (!nflag)
986 					(void)printf("%s: %lld -> ",
987 					    string, tmp);
988 				tmp = *(quad_t *)newval;
989 				(void)printf("%qd\n", tmp);
990 			}
991 		}
992 		return;
993 
994 	case CTLTYPE_STRUCT:
995 		warnx("%s: unknown structure returned", string);
996 		return;
997 
998 	default:
999 	case CTLTYPE_NODE:
1000 		warnx("%s: unknown type returned", string);
1001 		return;
1002 	}
1003 }
1004 
1005 void
1006 parse_baddynamic(int mib[], size_t len, char *string, void **newvalp,
1007     size_t *newsizep, int flags, int nflag)
1008 {
1009 	static u_int32_t newbaddynamic[DP_MAPSIZE];
1010 	in_port_t port;
1011 	size_t size;
1012 	char action, *cp;
1013 
1014 	if (strchr((char *)*newvalp, '+') || strchr((char *)*newvalp, '-')) {
1015 		size = sizeof(newbaddynamic);
1016 		if (sysctl(mib, len, newbaddynamic, &size, 0, 0) == -1) {
1017 			if (flags == 0)
1018 				return;
1019 			if (!nflag)
1020 				(void)printf("%s: ", string);
1021 			(void)puts("kernel does contain bad dynamic port tables");
1022 			return;
1023 		}
1024 
1025 		while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) {
1026 			if (*cp != '+' && *cp != '-')
1027 				errx(1, "cannot mix +/- with full list");
1028 			action = *cp++;
1029 			port = atoi(cp);
1030 			if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED)
1031 				errx(1, "invalid port, range is %d to %d",
1032 				    IPPORT_RESERVED/2, IPPORT_RESERVED-1);
1033 			if (action == '+')
1034 				DP_SET(newbaddynamic, port);
1035 			else
1036 				DP_CLR(newbaddynamic, port);
1037 		}
1038 	} else {
1039 		(void)memset((void *)newbaddynamic, 0, sizeof(newbaddynamic));
1040 		while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) {
1041 			port = atoi(cp);
1042 			if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED)
1043 				errx(1, "invalid port, range is %d to %d",
1044 				    IPPORT_RESERVED/2, IPPORT_RESERVED-1);
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("%ld\n", nch.ncs_goodhits);
1621 		break;
1622 	case KERN_NCHSTATS_NEGHITS:
1623 		(void)printf("%ld\n", nch.ncs_neghits);
1624 		break;
1625 	case KERN_NCHSTATS_BADHITS:
1626 		(void)printf("%ld\n", nch.ncs_badhits);
1627 		break;
1628 	case KERN_NCHSTATS_FALSEHITS:
1629 		(void)printf("%ld\n", nch.ncs_falsehits);
1630 		break;
1631 	case KERN_NCHSTATS_MISS:
1632 		(void)printf("%ld\n", nch.ncs_miss);
1633 		break;
1634 	case KERN_NCHSTATS_LONG:
1635 		(void)printf("%ld\n", nch.ncs_long);
1636 		break;
1637 	case KERN_NCHSTATS_PASS2:
1638 		(void)printf("%ld\n", nch.ncs_pass2);
1639 		break;
1640 	case KERN_NCHSTATS_2PASSES:
1641 		(void)printf("%ld\n", nch.ncs_2passes);
1642 		break;
1643 	case KERN_NCHSTATS_REVHITS:
1644 		(void)printf("%ld\n", nch.ncs_revhits);
1645 		break;
1646 	case KERN_NCHSTATS_REVMISS:
1647 		(void)printf("%ld\n", nch.ncs_revmiss);
1648 		break;
1649 	}
1650 	return (-1);
1651 }
1652 
1653 /*
1654  * handle tty statistics
1655  */
1656 int
1657 sysctl_tty(char *string, char **bufpp, int mib[], int flags, int *typep)
1658 {
1659 	int indx;
1660 
1661 	if (*bufpp == NULL) {
1662 		listall(string, &ttylist);
1663 		return (-1);
1664 	}
1665 	if ((indx = findname(string, "third", bufpp, &ttylist)) == -1)
1666 		return (-1);
1667 	mib[2] = indx;
1668 
1669 	if ((*typep = ttylist.list[indx].ctl_type) == CTLTYPE_STRUCT) {
1670 		if (flags)
1671 			warnx("use pstat -t to view %s information",
1672 			    string);
1673 		return (-1);
1674 	}
1675 	return (3);
1676 }
1677 
1678 /*
1679  * handle fork statistics
1680  */
1681 int
1682 sysctl_forkstat(char *string, char **bufpp, int mib[], int flags, int *typep)
1683 {
1684 	static struct forkstat fks;
1685 	static int keepvalue = 0;
1686 	int indx;
1687 	size_t size;
1688 
1689 	if (*bufpp == NULL) {
1690 		bzero(&fks, sizeof(struct forkstat));
1691 		listall(string, &forkstatlist);
1692 		return (-1);
1693 	}
1694 	if ((indx = findname(string, "third", bufpp, &forkstatlist)) == -1)
1695 		return (-1);
1696 	if (*bufpp != NULL) {
1697 		warnx("fourth level name in %s is invalid", string);
1698 		return (-1);
1699 	}
1700 	if (keepvalue == 0) {
1701 		size = sizeof(struct forkstat);
1702 		if (sysctl(mib, 2, &fks, &size, NULL, 0) < 0)
1703 			return (-1);
1704 		keepvalue = 1;
1705 	}
1706 	if (!nflag)
1707 		(void)printf("%s%s", string, equ);
1708 	switch (indx)	{
1709 	case KERN_FORKSTAT_FORK:
1710 		(void)printf("%d\n", fks.cntfork);
1711 		break;
1712 	case KERN_FORKSTAT_VFORK:
1713 		(void)printf("%d\n", fks.cntvfork);
1714 		break;
1715 	case KERN_FORKSTAT_RFORK:
1716 		(void)printf("%d\n", fks.cntrfork);
1717 		break;
1718 	case KERN_FORKSTAT_KTHREAD:
1719 		(void)printf("%d\n", fks.cntkthread);
1720 		break;
1721 	case KERN_FORKSTAT_SIZFORK:
1722 		(void)printf("%d\n", fks.sizfork);
1723 		break;
1724 	case KERN_FORKSTAT_SIZVFORK:
1725 		(void)printf("%d\n", fks.sizvfork);
1726 		break;
1727 	case KERN_FORKSTAT_SIZRFORK:
1728 		(void)printf("%d\n", fks.sizrfork);
1729 		break;
1730 	case KERN_FORKSTAT_SIZKTHREAD:
1731 		(void)printf("%d\n", fks.sizkthread);
1732 		break;
1733 	}
1734 	return (-1);
1735 }
1736 
1737 /*
1738  * handle malloc statistics
1739  */
1740 int
1741 sysctl_malloc(char *string, char **bufpp, int mib[], int flags, int *typep)
1742 {
1743 	int indx, stor, i;
1744 	char *name, bufp[BUFSIZ], *buf, *ptr;
1745 	struct list lp;
1746 	size_t size;
1747 
1748 	if (*bufpp == NULL) {
1749 		listall(string, &kernmalloclist);
1750 		return (-1);
1751 	}
1752 	if ((indx = findname(string, "third", bufpp, &kernmalloclist)) == -1)
1753 		return (-1);
1754 	mib[2] = indx;
1755 	if (mib[2] == KERN_MALLOC_BUCKET) {
1756 		if ((name = strsep(bufpp, ".")) == NULL) {
1757 			size = BUFSIZ;
1758 			stor = mib[2];
1759 			mib[2] = KERN_MALLOC_BUCKETS;
1760 			buf = bufp;
1761 			if (sysctl(mib, 3, buf, &size, NULL, 0) < 0)
1762 				return (-1);
1763 			mib[2] = stor;
1764 			for (stor = 0, i = 0; i < size; i++)
1765 				if (buf[i] == ',')
1766 					stor++;
1767 			lp.list = calloc(stor + 2, sizeof(struct ctlname));
1768 			if (lp.list == NULL)
1769 				return (-1);
1770 			lp.size = stor + 2;
1771 			for (i = 1;
1772 			    (lp.list[i].ctl_name = strsep(&buf, ",")) != NULL;
1773 			    i++) {
1774 				lp.list[i].ctl_type = CTLTYPE_STRUCT;
1775 			}
1776 			lp.list[i].ctl_name = buf;
1777 			lp.list[i].ctl_type = CTLTYPE_STRUCT;
1778 			listall(string, &lp);
1779 			free(lp.list);
1780 			return (-1);
1781 		}
1782 		mib[3] = atoi(name);
1783 		return (4);
1784 	} else if (mib[2] == KERN_MALLOC_BUCKETS) {
1785 		*typep = CTLTYPE_STRING;
1786 		return (3);
1787 	} else if (mib[2] == KERN_MALLOC_KMEMSTATS) {
1788 		size = BUFSIZ;
1789 		stor = mib[2];
1790 		mib[2] = KERN_MALLOC_KMEMNAMES;
1791 		buf = bufp;
1792 		if (sysctl(mib, 3, buf, &size, NULL, 0) < 0)
1793 			return (-1);
1794 		mib[2] = stor;
1795 		if ((name = strsep(bufpp, ".")) == NULL) {
1796 			for (stor = 0, i = 0; i < size; i++)
1797 				if (buf[i] == ',')
1798 					stor++;
1799 			lp.list = calloc(stor + 2, sizeof(struct ctlname));
1800 			if (lp.list == NULL)
1801 				return (-1);
1802 			lp.size = stor + 2;
1803 			for (i = 1;
1804 			    (lp.list[i].ctl_name = strsep(&buf, ",")) != NULL;
1805 			    i++) {
1806 				if (lp.list[i].ctl_name[0] == '\0') {
1807 					i--;
1808 					continue;
1809 				}
1810 				lp.list[i].ctl_type = CTLTYPE_STRUCT;
1811 			}
1812 			lp.list[i].ctl_name = buf;
1813 			lp.list[i].ctl_type = CTLTYPE_STRUCT;
1814 			listall(string, &lp);
1815 			free(lp.list);
1816 			return (-1);
1817 		}
1818 		ptr = strstr(buf, name);
1819  tryagain:
1820 		if (ptr == NULL) {
1821 			warnx("fourth level name %s in %s is invalid", name,
1822 			    string);
1823 			return (-1);
1824 		}
1825 		if ((*(ptr + strlen(name)) != ',') &&
1826 		    (*(ptr + strlen(name)) != '\0')) {
1827 			ptr = strstr(ptr + 1, name); /* retry */
1828 			goto tryagain;
1829 		}
1830 		if ((ptr != buf) && (*(ptr - 1) != ',')) {
1831 			ptr = strstr(ptr + 1, name); /* retry */
1832 			goto tryagain;
1833 		}
1834 		for (i = 0, stor = 0; buf + i < ptr; i++)
1835 			if (buf[i] == ',')
1836 				stor++;
1837 		mib[3] = stor;
1838 		return (4);
1839 	} else if (mib[2] == KERN_MALLOC_KMEMNAMES) {
1840 		*typep = CTLTYPE_STRING;
1841 		return (3);
1842 	}
1843 	return (-1);
1844 }
1845 
1846 #ifdef CPU_CHIPSET
1847 /*
1848  * handle machdep.chipset requests
1849  */
1850 struct ctlname chipsetname[] = CTL_CHIPSET_NAMES;
1851 struct list chipsetlist = { chipsetname, CPU_CHIPSET_MAXID };
1852 
1853 int
1854 sysctl_chipset(char *string, char **bufpp, int mib[], int flags, int *typep)
1855 {
1856 	int indx, bwx;
1857 	static void *q;
1858 	size_t len;
1859 	char *p;
1860 
1861 	if (*bufpp == NULL) {
1862 		listall(string, &chipsetlist);
1863 		return (-1);
1864 	}
1865 	if ((indx = findname(string, "third", bufpp, &chipsetlist)) == -1)
1866 		return (-1);
1867 	mib[2] = indx;
1868 	if (!nflag)
1869 		printf("%s%s", string, equ);
1870 	switch(mib[2]) {
1871 	case CPU_CHIPSET_MEM:
1872 	case CPU_CHIPSET_DENSE:
1873 	case CPU_CHIPSET_PORTS:
1874 	case CPU_CHIPSET_HAE_MASK:
1875 		len = sizeof(void *);
1876 		if (sysctl(mib, 3, &q, &len, NULL, 0) < 0)
1877 			return (-1);
1878 		printf("%p\n", q);
1879 		break;
1880 	case CPU_CHIPSET_BWX:
1881 		len = sizeof(int);
1882 		if (sysctl(mib, 3, &bwx, &len, NULL, 0) < 0)
1883 			return (-1);
1884 		printf("%d\n", bwx);
1885 		break;
1886 	case CPU_CHIPSET_TYPE:
1887 		if (sysctl(mib, 3, NULL, &len, NULL, 0) < 0)
1888 			return (-1);
1889 		p = malloc(len + 1);
1890 		if (p == NULL)
1891 			return (-1);
1892 		if (sysctl(mib, 3, p, &len, NULL, 0) < 0) {
1893 			free(p);
1894 			return (-1);
1895 		}
1896 		p[len] = '\0';
1897 		printf("%s\n", p);
1898 		free(p);
1899 		break;
1900 	}
1901 	return (-1);
1902 }
1903 #endif
1904 /*
1905  * handle internet requests
1906  */
1907 int
1908 sysctl_inet(char *string, char **bufpp, int mib[], int flags, int *typep)
1909 {
1910 	struct list *lp;
1911 	int indx;
1912 
1913 	if (*bufpp == NULL) {
1914 		listall(string, &inetlist);
1915 		return (-1);
1916 	}
1917 	if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
1918 		return (-1);
1919 	mib[2] = indx;
1920 	if (indx < IPPROTO_MAXID && inetvars[indx].list != NULL)
1921 		lp = &inetvars[indx];
1922 	else if (!flags)
1923 		return (-1);
1924 	else {
1925 		warnx("%s: no variables defined for this protocol", string);
1926 		return (-1);
1927 	}
1928 	if (*bufpp == NULL) {
1929 		listall(string, lp);
1930 		return (-1);
1931 	}
1932 	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1933 		return (-1);
1934 	mib[3] = indx;
1935 	*typep = lp->list[indx].ctl_type;
1936 	if (*typep == CTLTYPE_NODE) {
1937 		int tindx;
1938 
1939 		if (*bufpp == NULL) {
1940 			listall(string, &ifqlist);
1941 			return(-1);
1942 		}
1943 		lp = &ifqlist;
1944 		if ((tindx = findname(string, "fifth", bufpp, lp)) == -1)
1945 			return (-1);
1946 		mib[4] = tindx;
1947 		*typep = lp->list[tindx].ctl_type;
1948 		return(5);
1949 	}
1950 	return (4);
1951 }
1952 
1953 #ifdef INET6
1954 struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES;
1955 struct ctlname ip6name[] = IPV6CTL_NAMES;
1956 struct ctlname icmp6name[] = ICMPV6CTL_NAMES;
1957 struct ctlname pim6name[] = PIM6CTL_NAMES;
1958 struct list inet6list = { inet6name, IPV6PROTO_MAXID };
1959 struct list inet6vars[] = {
1960 /*0*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1961 	{ 0, 0 },
1962 	{ 0, 0 },
1963 	{ 0, 0 },
1964 	{ 0, 0 },
1965 	{ 0, 0 },
1966 /*10*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1967 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1968 /*20*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1969 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1970 /*30*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1971 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1972 /*40*/	{ 0, 0 },
1973 	{ ip6name, IPV6CTL_MAXID },	/* ipv6 */
1974 	{ 0, 0 },
1975 	{ 0, 0 },
1976 	{ 0, 0 },
1977 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1978 /*50*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1979 	{ 0, 0 },
1980 	{ 0, 0 },
1981 	{ 0, 0 },
1982 	{ icmp6name, ICMPV6CTL_MAXID },	/* icmp6 */
1983 	{ 0, 0 },
1984 /*60*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1985 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1986 /*70*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1987 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1988 /*80*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1989 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1990 /*90*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1991 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1992 /*100*/	{ 0, 0 },
1993 	{ 0, 0 },
1994 	{ 0, 0 },
1995 	{ pim6name, PIM6CTL_MAXID },	/* pim6 */
1996 };
1997 
1998 /*
1999  * handle internet6 requests
2000  */
2001 int
2002 sysctl_inet6(char *string, char **bufpp, int mib[], int flags, int *typep)
2003 {
2004 	struct list *lp;
2005 	int indx;
2006 
2007 	if (*bufpp == NULL) {
2008 		listall(string, &inet6list);
2009 		return (-1);
2010 	}
2011 	if ((indx = findname(string, "third", bufpp, &inet6list)) == -1)
2012 		return (-1);
2013 	mib[2] = indx;
2014 	if (indx < IPV6PROTO_MAXID && inet6vars[indx].list != NULL)
2015 		lp = &inet6vars[indx];
2016 	else if (!flags)
2017 		return (-1);
2018 	else {
2019 		warnx("%s: no variables defined for this protocol", string);
2020 		return (-1);
2021 	}
2022 	if (*bufpp == NULL) {
2023 		listall(string, lp);
2024 		return (-1);
2025 	}
2026 	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
2027 		return (-1);
2028 	mib[3] = indx;
2029 	*typep = lp->list[indx].ctl_type;
2030 	return (4);
2031 }
2032 #endif
2033 
2034 /* handle bpf requests */
2035 int
2036 sysctl_bpf(char *string, char **bufpp, int mib[], int flags, int *typep)
2037 {
2038 	int indx;
2039 
2040 	if (*bufpp == NULL) {
2041 		listall(string, &bpflist);
2042 		return (-1);
2043 	}
2044 	if ((indx = findname(string, "third", bufpp, &bpflist)) == -1)
2045 		return (-1);
2046 	mib[2] = indx;
2047 	*typep = CTLTYPE_INT;
2048 	return (3);
2049 }
2050 
2051 struct ctlname mplsname[] = MPLSCTL_NAMES;
2052 struct list mplslist = { mplsname, MPLSCTL_MAXID };
2053 
2054 /* handle MPLS requests */
2055 int
2056 sysctl_mpls(char *string, char **bufpp, int mib[], int flags, int *typep)
2057 {
2058 	struct list *lp;
2059 	int indx;
2060 
2061 	if (*bufpp == NULL) {
2062 		listall(string, &mplslist);
2063 		return (-1);
2064 	}
2065 	if ((indx = findname(string, "third", bufpp, &mplslist)) == -1)
2066 		return (-1);
2067 	mib[2] = indx;
2068 	*typep = mplslist.list[indx].ctl_type;
2069 	if (*typep == CTLTYPE_NODE) {
2070 		int tindx;
2071 
2072 		if (*bufpp == NULL) {
2073 			listall(string, &ifqlist);
2074 			return(-1);
2075 		}
2076 		lp = &ifqlist;
2077 		if ((tindx = findname(string, "fourth", bufpp, lp)) == -1)
2078 			return (-1);
2079 		mib[3] = tindx;
2080 		*typep = lp->list[tindx].ctl_type;
2081 		return(4);
2082 	}
2083 	return (3);
2084 }
2085 
2086 /*
2087  * Handle SysV semaphore info requests
2088  */
2089 int
2090 sysctl_seminfo(string, bufpp, mib, flags, typep)
2091 	char *string;
2092 	char **bufpp;
2093 	int mib[];
2094 	int flags;
2095 	int *typep;
2096 {
2097 	int indx;
2098 
2099 	if (*bufpp == NULL) {
2100 		listall(string, &semlist);
2101 		return (-1);
2102 	}
2103 	if ((indx = findname(string, "third", bufpp, &semlist)) == -1)
2104 		return (-1);
2105 	mib[2] = indx;
2106 	*typep = CTLTYPE_INT;
2107 	return (3);
2108 }
2109 
2110 /*
2111  * Handle SysV shared memory info requests
2112  */
2113 int
2114 sysctl_shminfo(string, bufpp, mib, flags, typep)
2115 	char *string;
2116 	char **bufpp;
2117 	int mib[];
2118 	int flags;
2119 	int *typep;
2120 {
2121 	int indx;
2122 
2123 	if (*bufpp == NULL) {
2124 		listall(string, &shmlist);
2125 		return (-1);
2126 	}
2127 	if ((indx = findname(string, "third", bufpp, &shmlist)) == -1)
2128 		return (-1);
2129 	mib[2] = indx;
2130 	*typep = CTLTYPE_INT;
2131 	return (3);
2132 }
2133 
2134 /*
2135  * Handle watchdog support
2136  */
2137 int
2138 sysctl_watchdog(char *string, char **bufpp, int mib[], int flags,
2139     int *typep)
2140 {
2141 	int indx;
2142 
2143 	if (*bufpp == NULL) {
2144 		listall(string, &watchdoglist);
2145 		return (-1);
2146 	}
2147 	if ((indx = findname(string, "third", bufpp, &watchdoglist)) == -1)
2148 		return (-1);
2149 	mib[2] = indx;
2150 	*typep = watchdoglist.list[indx].ctl_type;
2151 	return (3);
2152 }
2153 
2154 /*
2155  * Handle timecounter support
2156  */
2157 int
2158 sysctl_tc(char *string, char **bufpp, int mib[], int flags,
2159     int *typep)
2160 {
2161 	int indx;
2162 
2163 	if (*bufpp == NULL) {
2164 		listall(string, &tclist);
2165 		return (-1);
2166 	}
2167 	if ((indx = findname(string, "third", bufpp, &tclist)) == -1)
2168 		return (-1);
2169 	mib[2] = indx;
2170 	*typep = tclist.list[indx].ctl_type;
2171 	return (3);
2172 }
2173 
2174 /*
2175  * Handle hardware monitoring sensors support
2176  */
2177 int
2178 sysctl_sensors(char *string, char **bufpp, int mib[], int flags, int *typep)
2179 {
2180 	char *devname, *typename;
2181 	int dev, numt, i;
2182 	enum sensor_type type;
2183 	struct sensordev snsrdev;
2184 	size_t sdlen = sizeof(snsrdev);
2185 
2186 	if (*bufpp == NULL) {
2187 		char buf[BUFSIZ];
2188 
2189 		/* scan all sensor devices */
2190 		for (dev = 0; dev < MAXSENSORDEVICES; dev++) {
2191 			mib[2] = dev;
2192 			if (sysctl(mib, 3, &snsrdev, &sdlen, NULL, 0) == -1)
2193 				continue;
2194 			snprintf(buf, sizeof(buf), "%s.%s",
2195 			    string, snsrdev.xname);
2196 			print_sensordev(buf, mib, 3, &snsrdev);
2197 		}
2198 		return (-1);
2199 	}
2200 
2201 	/*
2202 	 * If we get this far, it means that some arguments were
2203 	 * provided below hw.sensors tree.
2204 	 * The first branch of hw.sensors tree is the device name.
2205 	 */
2206 	if ((devname = strsep(bufpp, ".")) == NULL) {
2207 		warnx("%s: incomplete specification", string);
2208 		return (-1);
2209 	}
2210 	/* convert sensor device string to an integer */
2211 	for (dev = 0; dev < MAXSENSORDEVICES; dev++) {
2212 		mib[2] = dev;
2213 		if (sysctl(mib, 3, &snsrdev, &sdlen, NULL, 0) == -1)
2214 			continue;
2215 		if (strcmp(devname, snsrdev.xname) == 0)
2216 			break;
2217 	}
2218 	if (strcmp(devname, snsrdev.xname) != 0) {
2219 		warnx("%s: sensor device not found: %s", string, devname);
2220 		return (-1);
2221 	}
2222 	if (*bufpp == NULL) {
2223 		/* only device name was provided -- let's print all sensors
2224 		 * that are attached to the specified device
2225 		 */
2226 		print_sensordev(string, mib, 3, &snsrdev);
2227 		return (-1);
2228 	}
2229 
2230 	/*
2231 	 * At this point we have identified the sensor device,
2232 	 * now let's go further and identify sensor type.
2233 	 */
2234 	if ((typename = strsep(bufpp, ".")) == NULL) {
2235 		warnx("%s: incomplete specification", string);
2236 		return (-1);
2237 	}
2238 	numt = -1;
2239 	for (i = 0; typename[i] != '\0'; i++)
2240 		if (isdigit(typename[i])) {
2241 			numt = atoi(&typename[i]);
2242 			typename[i] = '\0';
2243 			break;
2244 		}
2245 	for (type = 0; type < SENSOR_MAX_TYPES; type++)
2246 		if (strcmp(typename, sensor_type_s[type]) == 0)
2247 			break;
2248 	if (type == SENSOR_MAX_TYPES) {
2249 		warnx("%s: sensor type not recognised: %s", string, typename);
2250 		return (-1);
2251 	}
2252 	mib[3] = type;
2253 
2254 	/*
2255 	 * If no integer was provided after sensor_type, let's
2256 	 * print all sensors of the specified type.
2257 	 */
2258 	if (numt == -1) {
2259 		print_sensordev(string, mib, 4, &snsrdev);
2260 		return (-1);
2261 	}
2262 
2263 	/*
2264 	 * At this point we know that we have received a direct request
2265 	 * via command-line for a specific sensor. Let's have the parse()
2266 	 * function deal with it further, and report any errors if such
2267 	 * sensor node does not exist.
2268 	 */
2269 	mib[4] = numt;
2270 	*typep = CTLTYPE_STRUCT;
2271 	return (5);
2272 }
2273 
2274 /*
2275  * Print sensors from the specified device.
2276  */
2277 
2278 void
2279 print_sensordev(char *string, int mib[], u_int mlen, struct sensordev *snsrdev)
2280 {
2281 	char buf[BUFSIZ];
2282 	enum sensor_type type;
2283 
2284 	if (mlen == 3) {
2285 		for (type = 0; type < SENSOR_MAX_TYPES; type++) {
2286 			mib[3] = type;
2287 			snprintf(buf, sizeof(buf), "%s.%s",
2288 			    string, sensor_type_s[type]);
2289 			print_sensordev(buf, mib, mlen+1, snsrdev);
2290 		}
2291 		return;
2292 	}
2293 
2294 	if (mlen == 4) {
2295 		int numt;
2296 
2297 		type = mib[3];
2298 		for (numt = 0; numt < snsrdev->maxnumt[type]; numt++) {
2299 			mib[4] = numt;
2300 			snprintf(buf, sizeof(buf), "%s%u", string, numt);
2301 			print_sensordev(buf, mib, mlen+1, snsrdev);
2302 		}
2303 		return;
2304 	}
2305 
2306 	if (mlen == 5) {
2307 		struct sensor snsr;
2308 		size_t slen = sizeof(snsr);
2309 
2310 		/* this function is only printing sensors in bulk, so we
2311 		 * do not return any error messages if the requested sensor
2312 		 * is not found by sysctl(3)
2313 		 */
2314 		if (sysctl(mib, 5, &snsr, &slen, NULL, 0) == -1)
2315 			return;
2316 
2317 		if (slen > 0 && (snsr.flags & SENSOR_FINVALID) == 0) {
2318 			if (!nflag)
2319 				printf("%s%s", string, equ);
2320 			print_sensor(&snsr);
2321 			printf("\n");
2322 		}
2323 		return;
2324 	}
2325 }
2326 
2327 void
2328 print_sensor(struct sensor *s)
2329 {
2330 	const char *name;
2331 
2332 	if (s->flags & SENSOR_FUNKNOWN)
2333 		printf("unknown");
2334 	else {
2335 		switch (s->type) {
2336 		case SENSOR_TEMP:
2337 			printf("%.2f degC",
2338 			    (s->value - 273150000) / 1000000.0);
2339 			break;
2340 		case SENSOR_FANRPM:
2341 			printf("%lld RPM", s->value);
2342 			break;
2343 		case SENSOR_VOLTS_DC:
2344 			printf("%.2f VDC", s->value / 1000000.0);
2345 			break;
2346 		case SENSOR_AMPS:
2347 			printf("%.2f A", s->value / 1000000.0);
2348 			break;
2349 		case SENSOR_WATTHOUR:
2350 			printf("%.2f Wh", s->value / 1000000.0);
2351 			break;
2352 		case SENSOR_AMPHOUR:
2353 			printf("%.2f Ah", s->value / 1000000.0);
2354 			break;
2355 		case SENSOR_INDICATOR:
2356 			printf("%s", s->value ? "On" : "Off");
2357 			break;
2358 		case SENSOR_INTEGER:
2359 			printf("%lld", s->value);
2360 			break;
2361 		case SENSOR_PERCENT:
2362 			printf("%.2f%%", s->value / 1000.0);
2363 			break;
2364 		case SENSOR_LUX:
2365 			printf("%.2f lx", s->value / 1000000.0);
2366 			break;
2367 		case SENSOR_DRIVE:
2368 			switch (s->value) {
2369 			case SENSOR_DRIVE_EMPTY:
2370 				name = "empty";
2371 				break;
2372 			case SENSOR_DRIVE_READY:
2373 				name = "ready";
2374 				break;
2375 			case SENSOR_DRIVE_POWERUP:
2376 				name = "powering up";
2377 				break;
2378 			case SENSOR_DRIVE_ONLINE:
2379 				name = "online";
2380 				break;
2381 			case SENSOR_DRIVE_IDLE:
2382 				name = "idle";
2383 				break;
2384 			case SENSOR_DRIVE_ACTIVE:
2385 				name = "active";
2386 				break;
2387 			case SENSOR_DRIVE_REBUILD:
2388 				name = "rebuilding";
2389 				break;
2390 			case SENSOR_DRIVE_POWERDOWN:
2391 				name = "powering down";
2392 				break;
2393 			case SENSOR_DRIVE_FAIL:
2394 				name = "failed";
2395 				break;
2396 			case SENSOR_DRIVE_PFAIL:
2397 				name = "degraded";
2398 				break;
2399 			default:
2400 				name = "unknown";
2401 				break;
2402 			}
2403 			printf(name);
2404 			break;
2405 		case SENSOR_TIMEDELTA:
2406 			printf("%.6f secs", s->value / 1000000000.0);
2407 			break;
2408 		default:
2409 			printf("unknown");
2410 		}
2411 	}
2412 
2413 	if (s->desc[0] != '\0')
2414 		printf(" (%s)", s->desc);
2415 
2416 	switch (s->status) {
2417 	case SENSOR_S_UNSPEC:
2418 		break;
2419 	case SENSOR_S_OK:
2420 		printf(", OK");
2421 		break;
2422 	case SENSOR_S_WARN:
2423 		printf(", WARNING");
2424 		break;
2425 	case SENSOR_S_CRIT:
2426 		printf(", CRITICAL");
2427 		break;
2428 	case SENSOR_S_UNKNOWN:
2429 		printf(", UNKNOWN");
2430 		break;
2431 	}
2432 
2433 	if (s->tv.tv_sec) {
2434 		time_t t = s->tv.tv_sec;
2435 		char ct[26];
2436 
2437 		ctime_r(&t, ct);
2438 		ct[19] = '\0';
2439 		printf(", %s.%03ld", ct, s->tv.tv_usec / 1000);
2440 	}
2441 }
2442 
2443 struct emulname {
2444 	char *name;
2445 	int index;
2446 } *emul_names;
2447 int	emul_num, nemuls;
2448 int	emul_init(void);
2449 
2450 int
2451 sysctl_emul(char *string, char *newval, int flags)
2452 {
2453 	int mib[4], enabled, i, old, print, found = 0;
2454 	char *head, *target;
2455 	size_t len;
2456 
2457 	if (emul_init() == -1) {
2458 		warnx("emul_init: out of memory");
2459 		return (1);
2460 	}
2461 
2462 	mib[0] = CTL_KERN;
2463 	mib[1] = KERN_EMUL;
2464 	mib[3] = KERN_EMUL_ENABLED;
2465 	head = "kern.emul.";
2466 
2467 	if (aflag || strcmp(string, "kern.emul") == 0) {
2468 		if (newval) {
2469 			warnx("%s: specification is incomplete", string);
2470 			return (1);
2471 		}
2472 		if (nflag)
2473 			printf("%d\n", nemuls);
2474 		else
2475 			printf("%snemuls%s%d\n", head, equ, nemuls);
2476 		for (i = 0; i < emul_num; i++) {
2477 			if (emul_names[i].name == NULL)
2478 				break;
2479 			if (i > 0 && strcmp(emul_names[i].name,
2480 			    emul_names[i-1].name) == 0)
2481 				continue;
2482 			mib[2] = emul_names[i].index;
2483 			len = sizeof(int);
2484 			if (sysctl(mib, 4, &enabled, &len, NULL, 0) == -1) {
2485 				warn("%s", string);
2486 				continue;
2487 			}
2488 			if (nflag)
2489 				printf("%d\n", enabled);
2490 			else
2491 				printf("%s%s%s%d\n", head, emul_names[i].name,
2492 				    equ, enabled);
2493 		}
2494 		return (0);
2495 	}
2496 	/* User specified a third level name */
2497 	target = strrchr(string, '.');
2498 	target++;
2499 	if (strcmp(target, "nemuls") == 0) {
2500 		if (newval) {
2501 			warnx("Operation not permitted");
2502 			return (1);
2503 		}
2504 		if (nflag)
2505 			printf("%d\n", nemuls);
2506 		else
2507 			printf("%snemuls = %d\n", head, nemuls);
2508 		return (0);
2509 	}
2510 	print = 1;
2511 	for (i = 0; i < emul_num; i++) {
2512 		if (!emul_names[i].name || (strcmp(target, emul_names[i].name)))
2513 			continue;
2514 		found = 1;
2515 		mib[2] = emul_names[i].index;
2516 		len = sizeof(int);
2517 		if (newval) {
2518 			enabled = atoi(newval);
2519 			if (sysctl(mib, 4, &old, &len, &enabled, len) == -1) {
2520 				warn("%s", string);
2521 				print = 0;
2522 				continue;
2523 			}
2524 			if (print) {
2525 				if (nflag)
2526 					printf("%d\n", enabled);
2527 				else
2528 					printf("%s%s: %d -> %d\n", head,
2529 					    target, old, enabled);
2530 			}
2531 		} else {
2532 			if (sysctl(mib, 4, &enabled, &len, NULL, 0) == -1) {
2533 				warn("%s", string);
2534 				continue;
2535 			}
2536 			if (print) {
2537 				if (nflag)
2538 					printf("%d\n", enabled);
2539 				else
2540 					printf("%s%s = %d\n", head, target,
2541 					    enabled);
2542 			}
2543 		}
2544 		print = 0;
2545 	}
2546 	if (!found)
2547 		warnx("third level name %s in kern.emul is invalid",
2548 		    string);
2549 	return (0);
2550 
2551 
2552 }
2553 
2554 int
2555 emulcmp(const void *m, const void *n)
2556 {
2557 	const struct emulname *a = m, *b = n;
2558 
2559 	if (!a || !a->name)
2560 		return 1;
2561 	if (!b || !b->name)
2562 		return -1;
2563 	return (strcmp(a->name, b->name));
2564 }
2565 
2566 int
2567 emul_init(void)
2568 {
2569 	static int done;
2570 	char string[16];
2571 	int mib[4], i;
2572 	size_t len;
2573 
2574 	if (done)
2575 		return (0);
2576 	done = 1;
2577 
2578 	mib[0] = CTL_KERN;
2579 	mib[1] = KERN_EMUL;
2580 	mib[2] = KERN_EMUL_NUM;
2581 	len = sizeof(int);
2582 	if (sysctl(mib, 3, &emul_num, &len, NULL, 0) == -1)
2583 		return (-1);
2584 
2585 	emul_names = calloc(emul_num, sizeof(*emul_names));
2586 	if (emul_names == NULL)
2587 		return (-1);
2588 
2589 	nemuls = emul_num;
2590 	for (i = 0; i < emul_num; i++) {
2591 		emul_names[i].index = mib[2] = i + 1;
2592 		mib[3] = KERN_EMUL_NAME;
2593 		len = sizeof(string);
2594 		if (sysctl(mib, 4, string, &len, NULL, 0) == -1)
2595 			continue;
2596 		if (strcmp(string, "native") == 0)
2597 			continue;
2598 		emul_names[i].name = strdup(string);
2599 		if (emul_names[i].name == NULL) {
2600 			free(emul_names);
2601 			return (-1);
2602 		}
2603 	}
2604 	qsort(emul_names, nemuls, sizeof(*emul_names), emulcmp);
2605 	for (i = 0; i < emul_num; i++) {
2606 		if (!emul_names[i].name || (i > 0 &&
2607 		    strcmp(emul_names[i].name, emul_names[i - 1].name) == 0))
2608 			nemuls--;
2609 	}
2610 	return (0);
2611 }
2612 
2613 /*
2614  * Scan a list of names searching for a particular name.
2615  */
2616 int
2617 findname(char *string, char *level, char **bufp, struct list *namelist)
2618 {
2619 	char *name;
2620 	int i;
2621 
2622 	if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
2623 		warnx("%s: incomplete specification", string);
2624 		return (-1);
2625 	}
2626 	for (i = 0; i < namelist->size; i++)
2627 		if (namelist->list[i].ctl_name != NULL &&
2628 		    strcmp(name, namelist->list[i].ctl_name) == 0)
2629 			break;
2630 	if (i == namelist->size) {
2631 		warnx("%s level name %s in %s is invalid", level, name, string);
2632 		return (-1);
2633 	}
2634 	return (i);
2635 }
2636 
2637 void
2638 usage(void)
2639 {
2640 
2641 	(void)fprintf(stderr,
2642 	    "usage: sysctl [-Aan]\n"
2643 	    "       sysctl [-n] name ...\n"
2644 	    "       sysctl [-nq] name=value ...\n");
2645 	exit(1);
2646 }
2647