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