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