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