GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/sysctl/sysctl.c Lines: 100 1134 8.8 %
Date: 2017-11-07 Branches: 76 847 9.0 %

Line Branch Exec Source
1
/*	$OpenBSD: sysctl.c,v 1.228 2017/07/19 06:30:54 florian 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
112
struct ctlname topname[] = CTL_NAMES;
113
struct ctlname kernname[] = CTL_KERN_NAMES;
114
struct ctlname vmname[] = CTL_VM_NAMES;
115
struct ctlname fsname[] = CTL_FS_NAMES;
116
struct ctlname netname[] = CTL_NET_NAMES;
117
struct ctlname hwname[] = CTL_HW_NAMES;
118
struct ctlname debugname[CTL_DEBUG_MAXID];
119
struct ctlname kernmallocname[] = CTL_KERN_MALLOC_NAMES;
120
struct ctlname forkstatname[] = CTL_KERN_FORKSTAT_NAMES;
121
struct ctlname nchstatsname[] = CTL_KERN_NCHSTATS_NAMES;
122
struct ctlname ttysname[] = CTL_KERN_TTY_NAMES;
123
struct ctlname semname[] = CTL_KERN_SEMINFO_NAMES;
124
struct ctlname shmname[] = CTL_KERN_SHMINFO_NAMES;
125
struct ctlname watchdogname[] = CTL_KERN_WATCHDOG_NAMES;
126
struct ctlname tcname[] = CTL_KERN_TIMECOUNTER_NAMES;
127
struct ctlname *vfsname;
128
#ifdef CTL_MACHDEP_NAMES
129
struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
130
#endif
131
struct ctlname ddbname[] = CTL_DDB_NAMES;
132
char names[BUFSIZ];
133
int lastused;
134
135
/* Maximum size object to expect from sysctl(3) */
136
#define SYSCTL_BUFSIZ	8192
137
138
struct list {
139
	struct	ctlname *list;
140
	int	size;
141
};
142
struct list toplist = { topname, CTL_MAXID };
143
struct list secondlevel[] = {
144
	{ 0, 0 },			/* CTL_UNSPEC */
145
	{ kernname, KERN_MAXID },	/* CTL_KERN */
146
	{ vmname, VM_MAXID },		/* CTL_VM */
147
	{ fsname, FS_MAXID },		/* CTL_FS */
148
	{ netname, NET_MAXID },		/* CTL_NET */
149
	{ 0, CTL_DEBUG_MAXID },		/* CTL_DEBUG */
150
	{ hwname, HW_MAXID },		/* CTL_HW */
151
#ifdef CTL_MACHDEP_NAMES
152
	{ machdepname, CPU_MAXID },	/* CTL_MACHDEP */
153
#else
154
	{ 0, 0 },			/* CTL_MACHDEP */
155
#endif
156
	{ 0, 0 },			/* was CTL_USER */
157
	{ ddbname, DBCTL_MAXID },	/* CTL_DDB_NAMES */
158
	{ 0, 0 },			/* CTL_VFS */
159
};
160
161
int	Aflag, aflag, nflag, qflag;
162
163
/*
164
 * Variables requiring special processing.
165
 */
166
#define	CLOCK		0x00000001
167
#define	BOOTTIME	0x00000002
168
#define	CHRDEV		0x00000004
169
#define	BLKDEV		0x00000008
170
#define	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
#define	SMALLBUF	0x00004000
180
#define	HEX		0x00008000
181
182
/* prototypes */
183
void debuginit(void);
184
void listall(char *, struct list *);
185
void parse(char *, int);
186
void parse_baddynamic(int *, size_t, char *, void **, size_t *, int, int);
187
void usage(void);
188
int findname(char *, char *, char **, struct list *);
189
int sysctl_inet(char *, char **, int *, int, int *);
190
int sysctl_inet6(char *, char **, int *, int, int *);
191
int sysctl_bpf(char *, char **, int *, int, int *);
192
int sysctl_mpls(char *, char **, int *, int, int *);
193
int sysctl_pipex(char *, char **, int *, int, int *);
194
int sysctl_fs(char *, char **, int *, int, int *);
195
static int sysctl_vfs(char *, char **, int[], int, int *);
196
static int sysctl_vfsgen(char *, char **, int[], int, int *);
197
int sysctl_bios(char *, char **, int *, int, int *);
198
int sysctl_swpenc(char *, char **, int *, int, int *);
199
int sysctl_forkstat(char *, char **, int *, int, int *);
200
int sysctl_tty(char *, char **, int *, int, int *);
201
int sysctl_nchstats(char *, char **, int *, int, int *);
202
int sysctl_malloc(char *, char **, int *, int, int *);
203
int sysctl_seminfo(char *, char **, int *, int, int *);
204
int sysctl_shminfo(char *, char **, int *, int, int *);
205
int sysctl_watchdog(char *, char **, int *, int, int *);
206
int sysctl_tc(char *, char **, int *, int, int *);
207
int sysctl_sensors(char *, char **, int *, int, int *);
208
void print_sensordev(char *, int *, u_int, struct sensordev *);
209
void print_sensor(struct sensor *);
210
#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
84
	while ((ch = getopt(argc, argv, "Aanqw")) != -1) {
223

24
		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
12
			nflag = 1;
235
12
			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
24
	argc -= optind;
250
24
	argv += optind;
251
252
24
	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
72
	for (; *argv != NULL; ++argv)
260
24
		parse(*argv, 1);
261
24
	return (0);
262
24
}
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
48
	int indx, type, state, intval, len;
298
24
	size_t size, newsize = 0;
299
	int lal = 0, special = 0;
300
24
	void *newval = NULL;
301
24
	int64_t quadval;
302
	struct list *lp;
303
24
	int mib[CTL_MAXNAME];
304
24
	char *cp, *bufp, buf[SYSCTL_BUFSIZ];
305
306
24
	(void)strlcpy(buf, string, sizeof(buf));
307
24
	bufp = buf;
308
24
	if ((cp = strchr(string, '=')) != NULL) {
309
		*strchr(buf, '=') = '\0';
310
		*cp++ = '\0';
311
		while (isspace((unsigned char)*cp))
312
			cp++;
313
		newval = cp;
314
		newsize = strlen(cp);
315
	}
316
24
	if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
317
		return;
318
24
	mib[0] = indx;
319
24
	if (indx == CTL_VFS)
320
		vfsinit();
321
24
	if (indx == CTL_DEBUG)
322
		debuginit();
323
24
	lp = &secondlevel[indx];
324
24
	if (lp->list == 0) {
325
		warnx("%s: class is not implemented", topname[indx].ctl_name);
326
		return;
327
	}
328
24
	if (bufp == NULL) {
329
		listall(topname[indx].ctl_name, lp);
330
		return;
331
	}
332
24
	if ((indx = findname(string, "second", &bufp, lp)) == -1)
333
		return;
334
36
	mib[1] = indx;
335
36
	type = lp->list[indx].ctl_type;
336
	len = 2;
337


36
	switch (mib[0]) {
338
339
	case CTL_KERN:
340





12
		switch (mib[1]) {
341
		case KERN_PROF:
342
			mib[2] = GPROF_STATE;
343
			mib[3] = 0; /* Assume CPU ID 0 is always valid. */
344
			size = sizeof(state);
345
			if (sysctl(mib, 4, &state, &size, NULL, 0) == -1) {
346
				if (flags == 0)
347
					return;
348
				if (!nflag)
349
					(void)printf("%s: ", string);
350
				(void)puts("kernel is not compiled for profiling");
351
				return;
352
			}
353
			if (!nflag)
354
				(void)printf("%s = %s\n", string,
355
				    state == GMON_PROF_OFF ? "off" : "running");
356
			return;
357
		case KERN_FORKSTAT:
358
			sysctl_forkstat(string, &bufp, mib, flags, &type);
359
			return;
360
		case KERN_TTY:
361
			len = sysctl_tty(string, &bufp, mib, flags, &type);
362
			if (len < 0)
363
				return;
364
			break;
365
		case KERN_NCHSTATS:
366
			sysctl_nchstats(string, &bufp, mib, flags, &type);
367
			return;
368
		case KERN_MALLOCSTATS:
369
			len = sysctl_malloc(string, &bufp, mib, flags, &type);
370
			if (len < 0)
371
				return;
372
			if (mib[2] == KERN_MALLOC_BUCKET)
373
				special |= KMEMBUCKETS;
374
			if (mib[2] == KERN_MALLOC_KMEMSTATS)
375
				special |= KMEMSTATS;
376
			newsize = 0;
377
			break;
378
		case KERN_MBSTAT:
379
			if (flags == 0)
380
				return;
381
			warnx("use netstat to view %s", string);
382
			return;
383
		case KERN_MSGBUF:
384
			if (flags == 0)
385
				return;
386
			warnx("use dmesg to view %s", string);
387
			return;
388
		case KERN_PROC:
389
			if (flags == 0)
390
				return;
391
			warnx("use ps to view %s information", string);
392
			return;
393
		case KERN_CLOCKRATE:
394
			special |= CLOCK;
395
			break;
396
		case KERN_BOOTTIME:
397
			special |= BOOTTIME;
398
			break;
399
		case KERN_HOSTID:
400
			special |= UNSIGNED;
401
			special |= SMALLBUF;
402
			break;
403
		case KERN_CPTIME:
404
			special |= LONGARRAY;
405
			lal = CPUSTATES;
406
			break;
407
		case KERN_SEMINFO:
408
			len = sysctl_seminfo(string, &bufp, mib, flags, &type);
409
			if (len < 0)
410
				return;
411
			break;
412
		case KERN_SHMINFO:
413
			len = sysctl_shminfo(string, &bufp, mib, flags, &type);
414
			if (len < 0)
415
				return;
416
			break;
417
		case KERN_INTRCNT:
418
			if (flags == 0)
419
				return;
420
			warnx("use vmstat or systat to view %s information",
421
			    string);
422
			return;
423
		case KERN_WATCHDOG:
424
			len = sysctl_watchdog(string, &bufp, mib, flags,
425
			    &type);
426
			if (len < 0)
427
				return;
428
			break;
429
		case KERN_TIMECOUNTER:
430
			len = sysctl_tc(string, &bufp, mib, flags,
431
			    &type);
432
			if (len < 0)
433
				return;
434
			break;
435
		case KERN_FILE:
436
			if (flags == 0)
437
				return;
438
			warnx("use fstat to view %s information", string);
439
			return;
440
		case KERN_CONSDEV:
441
			special |= CHRDEV;
442
			break;
443
		case KERN_NETLIVELOCKS:
444
		case KERN_SOMAXCONN:
445
		case KERN_SOMINCONN:
446
			special |= UNSIGNED;
447
			break;
448
		}
449
		break;
450
451
	case CTL_HW:
452
		switch (mib[1]) {
453
		case HW_DISKSTATS:
454
			/*
455
			 * Only complain if someone asks explicitly for this,
456
			 * otherwise "fail" silently.
457
			 */
458
			if (flags)
459
				warnx("use vmstat to view %s information",
460
				    string);
461
			return;
462
		case HW_SENSORS:
463
			special |= SENSORS;
464
			len = sysctl_sensors(string, &bufp, mib, flags, &type);
465
			if (len < 0)
466
				return;
467
			break;
468
		case HW_PHYSMEM:
469
		case HW_USERMEM:
470
			/*
471
			 * Don't print these; we'll print the 64-bit
472
			 * variants instead.
473
			 */
474
			return;
475
		}
476
		break;
477
478
	case CTL_VM:
479
		if (mib[1] == VM_LOADAVG) {
480
			double loads[3];
481
482
			getloadavg(loads, 3);
483
			if (!nflag)
484
				(void)printf("%s%s", string, equ);
485
			(void)printf("%.2f %.2f %.2f\n", loads[0],
486
			    loads[1], loads[2]);
487
			return;
488
		} else if (mib[1] == VM_PSSTRINGS) {
489
			struct _ps_strings _ps;
490
491
			size = sizeof(_ps);
492
			if (sysctl(mib, 2, &_ps, &size, NULL, 0) == -1) {
493
				if (flags == 0)
494
					return;
495
				if (!nflag)
496
					(void)printf("%s: ", string);
497
				(void)puts("can't find ps strings");
498
				return;
499
			}
500
			if (!nflag)
501
				(void)printf("%s%s", string, equ);
502
			(void)printf("%p\n", _ps.val);
503
			return;
504
		} else if (mib[1] == VM_SWAPENCRYPT) {
505
			len = sysctl_swpenc(string, &bufp, mib, flags, &type);
506
			if (len < 0)
507
				return;
508
509
			break;
510
		} else if (mib[1] == VM_NKMEMPAGES ||
511
		    mib[1] == VM_ANONMIN ||
512
		    mib[1] == VM_VTEXTMIN ||
513
		    mib[1] == VM_VNODEMIN) {
514
			break;
515
		}
516
		if (flags == 0)
517
			return;
518
		warnx("use vmstat or systat to view %s information", string);
519
		return;
520
521
		break;
522
523
	case CTL_NET:
524
12
		if (mib[1] == PF_INET) {
525
12
			len = sysctl_inet(string, &bufp, mib, flags, &type);
526
12
			if (len < 0)
527
				return;
528
529

12
			if ((mib[2] == IPPROTO_IP && mib[3] == IPCTL_MRTSTATS) ||
530

12
			    (mib[2] == IPPROTO_IP && mib[3] == IPCTL_STATS) ||
531

12
			    (mib[2] == IPPROTO_IP && mib[3] == IPCTL_MRTMFC) ||
532

12
			    (mib[2] == IPPROTO_IP && mib[3] == IPCTL_MRTVIF) ||
533

12
			    (mib[2] == IPPROTO_TCP && mib[3] == TCPCTL_STATS) ||
534

12
			    (mib[2] == IPPROTO_UDP && mib[3] == UDPCTL_STATS) ||
535

12
			    (mib[2] == IPPROTO_ESP && mib[3] == ESPCTL_STATS) ||
536

12
			    (mib[2] == IPPROTO_AH && mib[3] == AHCTL_STATS) ||
537

12
			    (mib[2] == IPPROTO_IGMP && mib[3] == IGMPCTL_STATS) ||
538

12
			    (mib[2] == IPPROTO_ETHERIP && mib[3] == ETHERIPCTL_STATS) ||
539

12
			    (mib[2] == IPPROTO_IPIP && mib[3] == IPIPCTL_STATS) ||
540

12
			    (mib[2] == IPPROTO_IPCOMP && mib[3] == IPCOMPCTL_STATS) ||
541

12
			    (mib[2] == IPPROTO_ICMP && mib[3] == ICMPCTL_STATS) ||
542

24
			    (mib[2] == IPPROTO_CARP && mib[3] == CARPCTL_STATS) ||
543

12
			    (mib[2] == IPPROTO_PFSYNC && mib[3] == PFSYNCCTL_STATS) ||
544
12
			    (mib[2] == IPPROTO_DIVERT && mib[3] == DIVERTCTL_STATS)) {
545
				if (flags == 0)
546
					return;
547
				warnx("use netstat to view %s information",
548
				    string);
549
				return;
550

12
			} else if ((mib[2] == IPPROTO_TCP &&
551
			    (mib[3] == TCPCTL_BADDYNAMIC ||
552
			    mib[3] == TCPCTL_ROOTONLY)) ||
553
12
			    (mib[2] == IPPROTO_UDP &&
554
			    (mib[3] == UDPCTL_BADDYNAMIC ||
555
			    mib[3] == UDPCTL_ROOTONLY))) {
556
557
				special |= BADDYNAMIC;
558
559
				if (newval != NULL)
560
					parse_baddynamic(mib, len, string,
561
					    &newval, &newsize, flags, nflag);
562
			}
563
			break;
564
		}
565
		if (mib[1] == PF_INET6) {
566
			len = sysctl_inet6(string, &bufp, mib, flags, &type);
567
			if (len < 0)
568
				return;
569
570
			if ((mib[2] == IPPROTO_IPV6 && mib[3] == IPV6CTL_MRTMFC) ||
571
			    (mib[2] == IPPROTO_IPV6 && mib[3] == IPV6CTL_MRTMIF) ||
572
			    (mib[2] == IPPROTO_DIVERT && mib[3] == DIVERT6CTL_STATS)) {
573
				if (flags == 0)
574
					return;
575
				warnx("use netstat to view %s information",
576
				    string);
577
				return;
578
			}
579
			break;
580
		}
581
		if (mib[1] == PF_BPF) {
582
			len = sysctl_bpf(string, &bufp, mib, flags, &type);
583
			if (len < 0)
584
				return;
585
			break;
586
		}
587
		if (mib[1] == PF_MPLS) {
588
			len = sysctl_mpls(string, &bufp, mib, flags, &type);
589
			if (len < 0)
590
				return;
591
			break;
592
		}
593
		if (mib[1] == PF_PIPEX) {
594
			len = sysctl_pipex(string, &bufp, mib, flags, &type);
595
			if (len < 0)
596
				return;
597
			break;
598
		}
599
		if (flags == 0)
600
			return;
601
		warnx("use netstat to view %s information", string);
602
		return;
603
604
	case CTL_DEBUG:
605
		mib[2] = CTL_DEBUG_VALUE;
606
		len = 3;
607
		break;
608
609
	case CTL_MACHDEP:
610
#ifdef CPU_CONSDEV
611
		if (mib[1] == CPU_CONSDEV)
612
			special |= CHRDEV;
613
#endif
614
#ifdef CPU_CPUFEATURE
615
		if (mib[1] == CPU_CPUFEATURE)
616
			special |= HEX;
617
#endif
618
#ifdef CPU_BLK2CHR
619
		if (mib[1] == CPU_BLK2CHR) {
620
			if (bufp == NULL)
621
				return;
622
			mib[2] = makedev(atoi(bufp),0);
623
			bufp = NULL;
624
			len = 3;
625
			special |= CHRDEV;
626
			break;
627
		}
628
#endif
629
#ifdef CPU_CHR2BLK
630
		if (mib[1] == CPU_CHR2BLK) {
631
			if (bufp == NULL)
632
				return;
633
			mib[2] = makedev(atoi(bufp),0);
634
			bufp = NULL;
635
			len = 3;
636
			special |= BLKDEV;
637
			break;
638
		}
639
#endif
640
#ifdef CPU_BIOS
641
		if (mib[1] == CPU_BIOS) {
642
			len = sysctl_bios(string, &bufp, mib, flags, &type);
643
			if (len < 0)
644
				return;
645
			if (mib[2] == BIOS_DEV)
646
				special |= BIOSDEV;
647
			if (mib[2] == BIOS_DISKINFO)
648
				special |= BIOSGEO;
649
			break;
650
		}
651
#endif
652
#ifdef CPU_CHIPSET
653
		if (mib[1] == CPU_CHIPSET) {
654
			len = sysctl_chipset(string, &bufp, mib, flags, &type);
655
			if (len < 0)
656
				return;
657
			break;
658
		}
659
#endif
660
		break;
661
662
	case CTL_FS:
663
		len = sysctl_fs(string, &bufp, mib, flags, &type);
664
		if (len >= 0)
665
			break;
666
		return;
667
668
	case CTL_VFS:
669
		if (mib[1])
670
			len = sysctl_vfs(string, &bufp, mib, flags, &type);
671
		else
672
			len = sysctl_vfsgen(string, &bufp, mib, flags, &type);
673
		if (len >= 0) {
674
			if (type == CTLTYPE_STRUCT) {
675
				if (flags)
676
					warnx("use nfsstat to view %s information",
677
					    MOUNT_NFS);
678
				return;
679
			} else
680
				break;
681
		}
682
		return;
683
684
	case CTL_DDB:
685
		break;
686
687
	default:
688
		warnx("illegal top level value: %d", mib[0]);
689
		return;
690
691
	}
692
24
	if (bufp) {
693
		warnx("name %s in %s is unknown", bufp, string);
694
		return;
695
	}
696
24
	if (newsize > 0) {
697
		const char *errstr;
698
699
		switch (type) {
700
		case CTLTYPE_INT:
701
			if (special & UNSIGNED)
702
				intval = strtonum(newval, 0, UINT_MAX, &errstr);
703
			else
704
				intval = strtonum(newval, INT_MIN, INT_MAX,
705
				    &errstr);
706
			if (errstr != NULL) {
707
				warnx("%s: value is %s: %s", string, errstr,
708
				    (char *)newval);
709
				return;
710
			}
711
			newval = &intval;
712
			newsize = sizeof(intval);
713
			break;
714
715
		case CTLTYPE_QUAD:
716
			(void)sscanf(newval, "%lld", &quadval);
717
			newval = &quadval;
718
			newsize = sizeof(quadval);
719
			break;
720
		}
721
	}
722
24
	size = (special & SMALLBUF) ? 512 : SYSCTL_BUFSIZ;
723
24
	if (sysctl(mib, len, buf, &size, newval, newsize) == -1) {
724
		if (flags == 0)
725
			return;
726
		switch (errno) {
727
		case EOPNOTSUPP:
728
			warnx("%s: value is not available", string);
729
			return;
730
		case ENOTDIR:
731
			warnx("%s: specification is incomplete", string);
732
			return;
733
		case ENOMEM:
734
			warnx("%s: type is unknown to this program", string);
735
			return;
736
		case ENXIO:
737
			if (special & BIOSGEO)
738
				return;
739
		default:
740
			warn("%s", string);
741
			return;
742
		}
743
	}
744
24
	if (special & KMEMBUCKETS) {
745
		struct kmembuckets *kb = (struct kmembuckets *)buf;
746
		if (!nflag)
747
			(void)printf("%s%s", string, equ);
748
		printf("(");
749
		printf("calls = %llu ", (long long)kb->kb_calls);
750
		printf("total_allocated = %llu ", (long long)kb->kb_total);
751
		printf("total_free = %lld ", (long long)kb->kb_totalfree);
752
		printf("elements = %lld ", (long long)kb->kb_elmpercl);
753
		printf("high watermark = %lld ", (long long)kb->kb_highwat);
754
		printf("could_free = %lld", (long long)kb->kb_couldfree);
755
		printf(")\n");
756
		return;
757
	}
758
24
	if (special & KMEMSTATS) {
759
		struct kmemstats *km = (struct kmemstats *)buf;
760
		int j, first = 1;
761
762
		if (!nflag)
763
			(void)printf("%s%s", string, equ);
764
		(void)printf("(inuse = %ld, calls = %ld, memuse = %ldK, "
765
		    "limblocks = %d, mapblocks = %d, maxused = %ldK, "
766
		    "limit = %ldK, spare = %ld, sizes = (",
767
		    km->ks_inuse, km->ks_calls,
768
		    (km->ks_memuse + 1023) / 1024, km->ks_limblocks,
769
		    km->ks_mapblocks, (km->ks_maxused + 1023) / 1024,
770
		    (km->ks_limit + 1023) / 1024, km->ks_spare);
771
		for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
772
			if ((km->ks_size & j ) == 0)
773
				continue;
774
			if (first)
775
				(void)printf("%d", j);
776
			else
777
				(void)printf(",%d", j);
778
			first = 0;
779
		}
780
		if (first)
781
			(void)printf("none");
782
		(void)printf("))\n");
783
		return;
784
	}
785
24
	if (special & CLOCK) {
786
		struct clockinfo *clkp = (struct clockinfo *)buf;
787
788
		if (!nflag)
789
			(void)printf("%s%s", string, equ);
790
		(void)printf(
791
		    "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n",
792
		    clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz);
793
		return;
794
	}
795
24
	if (special & BOOTTIME) {
796
		struct timeval *btp = (struct timeval *)buf;
797
		time_t boottime;
798
799
		if (!nflag) {
800
			boottime = btp->tv_sec;
801
			(void)printf("%s%s%s", string, equ, ctime(&boottime));
802
		} else
803
			(void)printf("%lld\n", (long long)btp->tv_sec);
804
		return;
805
	}
806
24
	if (special & BLKDEV) {
807
		dev_t dev = *(dev_t *)buf;
808
809
		if (!nflag)
810
			(void)printf("%s%s%s\n", string, equ,
811
			    devname(dev, S_IFBLK));
812
		else
813
			(void)printf("0x%x\n", dev);
814
		return;
815
	}
816
24
	if (special & CHRDEV) {
817
		dev_t dev = *(dev_t *)buf;
818
819
		if (!nflag)
820
			(void)printf("%s%s%s\n", string, equ,
821
			    devname(dev, S_IFCHR));
822
		else
823
			(void)printf("0x%x\n", dev);
824
		return;
825
	}
826
#ifdef CPU_BIOS
827
24
	if (special & BIOSGEO) {
828
		bios_diskinfo_t *pdi = (bios_diskinfo_t *)buf;
829
830
		if (!nflag)
831
			(void)printf("%s%s", string, equ);
832
		(void)printf("bootdev = 0x%x, "
833
		    "cylinders = %u, heads = %u, sectors = %u\n",
834
		    pdi->bsd_dev, pdi->bios_cylinders,
835
		    pdi->bios_heads, pdi->bios_sectors);
836
		return;
837
	}
838
24
	if (special & BIOSDEV) {
839
		int dev = *(int*)buf;
840
841
		if (!nflag)
842
			(void)printf("%s%s", string, equ);
843
		(void) printf("0x%02x\n", dev);
844
		return;
845
	}
846
#endif
847
24
	if (special & UNSIGNED) {
848
		if (newsize == 0) {
849
			if (!nflag)
850
				(void)printf("%s%s", string, equ);
851
			(void)printf("%u\n", *(u_int *)buf);
852
		} else {
853
			if (!qflag) {
854
				if (!nflag)
855
					(void)printf("%s: %u -> ", string,
856
					    *(u_int *)buf);
857
				(void)printf("%u\n", *(u_int *)newval);
858
			}
859
		}
860
		return;
861
	}
862
24
	if (special & BADDYNAMIC) {
863
		u_int port, lastport;
864
		u_int32_t *baddynamic = (u_int32_t *)buf;
865
866
		if (!qflag) {
867
			if (!nflag)
868
				(void)printf("%s%s", string,
869
				    newsize ? ": " : equ);
870
			lastport = 0;
871
			for (port = 0; port < 65536; port++)
872
				if (DP_ISSET(baddynamic, port)) {
873
					(void)printf("%s%u",
874
					    lastport ? "," : "", port);
875
					lastport = port;
876
				}
877
			if (newsize != 0) {
878
				if (!nflag)
879
					fputs(" -> ", stdout);
880
				baddynamic = (u_int32_t *)newval;
881
				lastport = 0;
882
				for (port = 0; port < 65536; port++)
883
					if (DP_ISSET(baddynamic, port)) {
884
						(void)printf("%s%u",
885
						    lastport ? "," : "", port);
886
						lastport = port;
887
					}
888
			}
889
			(void)putchar('\n');
890
		}
891
		return;
892
	}
893
24
	if (special & LONGARRAY) {
894
		long *la = (long *)buf;
895
		if (!nflag)
896
			printf("%s%s", string, equ);
897
		while (lal--)
898
			printf("%ld%s", *la++, lal? ",":"");
899
		putchar('\n');
900
		return;
901
	}
902
24
	if (special & SENSORS) {
903
		struct sensor *s = (struct sensor *)buf;
904
905
		if (size > 0 && (s->flags & SENSOR_FINVALID) == 0) {
906
			if (!nflag)
907
				printf("%s%s", string, equ);
908
			print_sensor(s);
909
			printf("\n");
910
		}
911
		return;
912
	}
913

24
	switch (type) {
914
	case CTLTYPE_INT:
915
12
		if (newsize == 0) {
916
12
			if (!nflag)
917
12
				(void)printf("%s%s", string, equ);
918
12
			if (special & HEX)
919
				(void)printf("0x%x\n", *(int *)buf);
920
			else
921
12
				(void)printf("%d\n", *(int *)buf);
922
		} else {
923
			if (!qflag) {
924
				if (!nflag)
925
					(void)printf("%s: %d -> ", string,
926
					    *(int *)buf);
927
				if (special & HEX)
928
					(void)printf("0x%x\n", *(int *)newval);
929
				else
930
					(void)printf("%d\n", *(int *)newval);
931
			}
932
		}
933
12
		return;
934
935
	case CTLTYPE_STRING:
936
12
		if (newval == NULL) {
937
12
			if (!nflag)
938
				(void)printf("%s%s", string, equ);
939
12
			(void)puts(buf);
940
12
		} else {
941
			if (!qflag) {
942
				if (!nflag)
943
					(void)printf("%s: %s -> ", string, buf);
944
				(void)puts((char *)newval);
945
			}
946
		}
947
12
		return;
948
949
	case CTLTYPE_QUAD:
950
		if (newsize == 0) {
951
			int64_t tmp;
952
953
			memcpy(&tmp, buf, sizeof tmp);
954
			if (!nflag)
955
				(void)printf("%s%s", string, equ);
956
			(void)printf("%lld\n", tmp);
957
		} else {
958
			int64_t tmp;
959
960
			memcpy(&tmp, buf, sizeof tmp);
961
			if (!qflag) {
962
				if (!nflag)
963
					(void)printf("%s: %lld -> ",
964
					    string, tmp);
965
				memcpy(&tmp, newval, sizeof tmp);
966
				(void)printf("%lld\n", tmp);
967
			}
968
		}
969
		return;
970
971
	case CTLTYPE_STRUCT:
972
		warnx("%s: unknown structure returned", string);
973
		return;
974
975
	default:
976
	case CTLTYPE_NODE:
977
		warnx("%s: unknown type returned", string);
978
		return;
979
	}
980
24
}
981
982
static void
983
parse_ports(char *portspec, int *port, int *high_port)
984
{
985
	char *dash;
986
	const char *errstr;
987
988
	if ((dash = strchr(portspec, '-')) != NULL)
989
		*dash++ = '\0';
990
	*port = strtonum(portspec, 0, 65535, &errstr);
991
	if (errstr != NULL)
992
		errx(1, "port is %s: %s", errstr, portspec);
993
	if (dash != NULL) {
994
		*high_port = strtonum(dash, 0, 65535, &errstr);
995
		if (errstr != NULL)
996
			errx(1, "high port is %s: %s", errstr, dash);
997
		if (*high_port < *port)
998
			errx(1, "high port %d is lower than %d",
999
			    *high_port, *port);
1000
	} else
1001
		*high_port = *port;
1002
}
1003
1004
void
1005
parse_baddynamic(int mib[], size_t len, char *string, void **newvalp,
1006
    size_t *newsizep, int flags, int nflag)
1007
{
1008
	static u_int32_t newbaddynamic[DP_MAPSIZE];
1009
	int port, high_port, baddynamic_loaded = 0, full_list_set = 0;
1010
	size_t size;
1011
	char action, *cp;
1012
1013
	while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) {
1014
		if (*cp == '+' || *cp == '-') {
1015
			if (full_list_set)
1016
				errx(1, "cannot mix +/- with full list");
1017
			action = *cp++;
1018
			if (!baddynamic_loaded) {
1019
				size = sizeof(newbaddynamic);
1020
				if (sysctl(mib, len, newbaddynamic,
1021
				    &size, 0, 0) == -1) {
1022
					if (flags == 0)
1023
						return;
1024
					if (!nflag)
1025
						printf("%s: ", string);
1026
					puts("kernel does not contain bad "
1027
					    "dynamic port tables");
1028
					return;
1029
				}
1030
				baddynamic_loaded = 1;
1031
			}
1032
			parse_ports(cp, &port, &high_port);
1033
			for (; port <= high_port; port++) {
1034
				if (action == '+')
1035
					DP_SET(newbaddynamic, port);
1036
				else
1037
					DP_CLR(newbaddynamic, port);
1038
			}
1039
		} else {
1040
			if (baddynamic_loaded)
1041
				errx(1, "cannot mix +/- with full list");
1042
			if (!full_list_set) {
1043
				bzero(newbaddynamic, sizeof(newbaddynamic));
1044
				full_list_set = 1;
1045
			}
1046
			parse_ports(cp, &port, &high_port);
1047
			for (; port <= high_port; port++)
1048
				DP_SET(newbaddynamic, port);
1049
		}
1050
	}
1051
	*newvalp = (void *)newbaddynamic;
1052
	*newsizep = sizeof(newbaddynamic);
1053
}
1054
1055
/*
1056
 * Initialize the set of debugging names
1057
 */
1058
void
1059
debuginit(void)
1060
{
1061
	int mib[3], loc, i;
1062
	size_t size;
1063
1064
	if (secondlevel[CTL_DEBUG].list != 0)
1065
		return;
1066
	secondlevel[CTL_DEBUG].list = debugname;
1067
	mib[0] = CTL_DEBUG;
1068
	mib[2] = CTL_DEBUG_NAME;
1069
	for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) {
1070
		mib[1] = i;
1071
		size = BUFSIZ - loc;
1072
		if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
1073
			continue;
1074
		debugname[i].ctl_name = &names[loc];
1075
		debugname[i].ctl_type = CTLTYPE_INT;
1076
		loc += size;
1077
	}
1078
	lastused = loc;
1079
}
1080
1081
struct ctlname vfsgennames[] = CTL_VFSGENCTL_NAMES;
1082
struct ctlname ffsname[] = FFS_NAMES;
1083
struct ctlname nfsname[] = FS_NFS_NAMES;
1084
struct ctlname fusefsname[] = FUSEFS_NAMES;
1085
struct list *vfsvars;
1086
int *vfs_typenums;
1087
1088
/*
1089
 * Initialize the set of filesystem names
1090
 */
1091
void
1092
vfsinit(void)
1093
{
1094
	int mib[4], maxtypenum, cnt, loc, size;
1095
	struct vfsconf vfc;
1096
	size_t buflen;
1097
1098
	if (secondlevel[CTL_VFS].list != 0)
1099
		return;
1100
	mib[0] = CTL_VFS;
1101
	mib[1] = VFS_GENERIC;
1102
	mib[2] = VFS_MAXTYPENUM;
1103
	buflen = 4;
1104
	if (sysctl(mib, 3, &maxtypenum, &buflen, NULL, 0) < 0)
1105
		return;
1106
	/*
1107
         * We need to do 0..maxtypenum so add one, and then we offset them
1108
	 * all by (another) one by inserting VFS_GENERIC entries at zero
1109
	 */
1110
	maxtypenum += 2;
1111
	if ((vfs_typenums = calloc(maxtypenum, sizeof(int))) == NULL)
1112
		return;
1113
	if ((vfsvars = calloc(maxtypenum, sizeof(*vfsvars))) == NULL) {
1114
		free(vfs_typenums);
1115
		return;
1116
	}
1117
	if ((vfsname = calloc(maxtypenum, sizeof(*vfsname))) == NULL) {
1118
		free(vfs_typenums);
1119
		free(vfsvars);
1120
		return;
1121
	}
1122
	mib[2] = VFS_CONF;
1123
	buflen = sizeof vfc;
1124
	for (loc = lastused, cnt = 1; cnt < maxtypenum; cnt++) {
1125
		mib[3] = cnt - 1;
1126
		if (sysctl(mib, 4, &vfc, &buflen, NULL, 0) < 0) {
1127
			if (errno == EOPNOTSUPP)
1128
				continue;
1129
			warn("vfsinit");
1130
			free(vfsname);
1131
			free(vfsvars);
1132
			free(vfs_typenums);
1133
			return;
1134
		}
1135
		if (!strcmp(vfc.vfc_name, MOUNT_FFS)) {
1136
			vfsvars[cnt].list = ffsname;
1137
			vfsvars[cnt].size = FFS_MAXID;
1138
		}
1139
		if (!strcmp(vfc.vfc_name, MOUNT_NFS)) {
1140
			vfsvars[cnt].list = nfsname;
1141
			vfsvars[cnt].size = NFS_MAXID;
1142
		}
1143
		if (!strcmp(vfc.vfc_name, MOUNT_FUSEFS)) {
1144
			vfsvars[cnt].list = fusefsname;
1145
			vfsvars[cnt].size = FUSEFS_MAXID;
1146
		}
1147
		vfs_typenums[cnt] = vfc.vfc_typenum;
1148
		strlcat(&names[loc], vfc.vfc_name, sizeof names - loc);
1149
		vfsname[cnt].ctl_name = &names[loc];
1150
		vfsname[cnt].ctl_type = CTLTYPE_NODE;
1151
		size = strlen(vfc.vfc_name) + 1;
1152
		loc += size;
1153
	}
1154
	lastused = loc;
1155
1156
	vfsname[0].ctl_name = "mounts";
1157
	vfsname[0].ctl_type = CTLTYPE_NODE;
1158
	vfsvars[0].list = vfsname + 1;
1159
	vfsvars[0].size = maxtypenum - 1;
1160
1161
	secondlevel[CTL_VFS].list = vfsname;
1162
	secondlevel[CTL_VFS].size = maxtypenum;
1163
	return;
1164
}
1165
1166
int
1167
sysctl_vfsgen(char *string, char **bufpp, int mib[], int flags, int *typep)
1168
{
1169
	int indx;
1170
	size_t size;
1171
	struct vfsconf vfc;
1172
1173
	if (*bufpp == NULL) {
1174
		listall(string, vfsvars);
1175
		return (-1);
1176
	}
1177
1178
	if ((indx = findname(string, "third", bufpp, vfsvars)) == -1)
1179
		return (-1);
1180
1181
	mib[1] = VFS_GENERIC;
1182
	mib[2] = VFS_CONF;
1183
	mib[3] = indx;
1184
	size = sizeof vfc;
1185
	if (sysctl(mib, 4, &vfc, &size, NULL, 0) < 0) {
1186
		if (errno != EOPNOTSUPP)
1187
			warn("vfs print");
1188
		return -1;
1189
	}
1190
	if (flags == 0 && vfc.vfc_refcount == 0)
1191
		return -1;
1192
	if (!nflag)
1193
		fprintf(stdout, "%s has %d mounted instance%s\n",
1194
		    string, vfc.vfc_refcount,
1195
		    vfc.vfc_refcount != 1 ? "s" : "");
1196
	else
1197
		fprintf(stdout, "%d\n", vfc.vfc_refcount);
1198
1199
	return -1;
1200
}
1201
1202
int
1203
sysctl_vfs(char *string, char **bufpp, int mib[], int flags, int *typep)
1204
{
1205
	struct list *lp = &vfsvars[mib[1]];
1206
	int indx;
1207
1208
	if (lp->list == NULL) {
1209
		if (flags)
1210
			warnx("No variables defined for file system %s", string);
1211
		return (-1);
1212
	}
1213
	if (*bufpp == NULL) {
1214
		listall(string, lp);
1215
		return (-1);
1216
	}
1217
	if ((indx = findname(string, "third", bufpp, lp)) == -1)
1218
		return (-1);
1219
1220
	mib[1] = vfs_typenums[mib[1]];
1221
	mib[2] = indx;
1222
	*typep = lp->list[indx].ctl_type;
1223
	return (3);
1224
}
1225
1226
struct ctlname posixname[] = CTL_FS_POSIX_NAMES;
1227
struct list fslist = { posixname, FS_POSIX_MAXID };
1228
1229
/*
1230
 * handle file system requests
1231
 */
1232
int
1233
sysctl_fs(char *string, char **bufpp, int mib[], int flags, int *typep)
1234
{
1235
	int indx;
1236
1237
	if (*bufpp == NULL) {
1238
		listall(string, &fslist);
1239
		return (-1);
1240
	}
1241
	if ((indx = findname(string, "third", bufpp, &fslist)) == -1)
1242
		return (-1);
1243
	mib[2] = indx;
1244
	*typep = fslist.list[indx].ctl_type;
1245
	return (3);
1246
}
1247
1248
#ifdef CPU_BIOS
1249
struct ctlname biosname[] = CTL_BIOS_NAMES;
1250
struct list bioslist = { biosname, BIOS_MAXID };
1251
1252
/*
1253
 * handle BIOS requests
1254
 */
1255
int
1256
sysctl_bios(char *string, char **bufpp, int mib[], int flags, int *typep)
1257
{
1258
	char *name;
1259
	int indx;
1260
1261
	if (*bufpp == NULL) {
1262
		listall(string, &bioslist);
1263
		return (-1);
1264
	}
1265
	if ((indx = findname(string, "third", bufpp, &bioslist)) == -1)
1266
		return (-1);
1267
	mib[2] = indx;
1268
	if (indx == BIOS_DISKINFO) {
1269
		const char *errstr;
1270
1271
		if (*bufpp == NULL) {
1272
			char name[BUFSIZ];
1273
1274
			/* scan all the bios devices */
1275
			for (indx = 0; indx < 256; indx++) {
1276
				snprintf(name, sizeof(name), "%s.%u",
1277
				    string, indx);
1278
				parse(name, 1);
1279
			}
1280
			return (-1);
1281
		}
1282
		if ((name = strsep(bufpp, ".")) == NULL) {
1283
			warnx("%s: incomplete specification", string);
1284
			return (-1);
1285
		}
1286
		mib[3] = strtonum(name, 0, INT_MAX, &errstr);
1287
		if (errstr) {
1288
			warnx("%s: %s", string, errstr);
1289
			return (-1);
1290
		}
1291
		*typep = CTLTYPE_STRUCT;
1292
		return (4);
1293
	} else {
1294
		*typep = bioslist.list[indx].ctl_type;
1295
		return (3);
1296
	}
1297
}
1298
#endif
1299
1300
struct ctlname swpencname[] = CTL_SWPENC_NAMES;
1301
struct list swpenclist = { swpencname, SWPENC_MAXID };
1302
1303
/*
1304
 * handle swap encrypt requests
1305
 */
1306
int
1307
sysctl_swpenc(char *string, char **bufpp, int mib[], int flags, int *typep)
1308
{
1309
	int indx;
1310
1311
	if (*bufpp == NULL) {
1312
		listall(string, &swpenclist);
1313
		return (-1);
1314
	}
1315
	if ((indx = findname(string, "third", bufpp, &swpenclist)) == -1)
1316
		return (-1);
1317
	mib[2] = indx;
1318
	*typep = swpenclist.list[indx].ctl_type;
1319
	return (3);
1320
}
1321
1322
struct ctlname inetname[] = CTL_IPPROTO_NAMES;
1323
struct ctlname ipname[] = IPCTL_NAMES;
1324
struct ctlname icmpname[] = ICMPCTL_NAMES;
1325
struct ctlname igmpname[] = IGMPCTL_NAMES;
1326
struct ctlname ipipname[] = IPIPCTL_NAMES;
1327
struct ctlname tcpname[] = TCPCTL_NAMES;
1328
struct ctlname udpname[] = UDPCTL_NAMES;
1329
struct ctlname espname[] = ESPCTL_NAMES;
1330
struct ctlname ahname[] = AHCTL_NAMES;
1331
struct ctlname etheripname[] = ETHERIPCTL_NAMES;
1332
struct ctlname grename[] = GRECTL_NAMES;
1333
struct ctlname mobileipname[] = MOBILEIPCTL_NAMES;
1334
struct ctlname ipcompname[] = IPCOMPCTL_NAMES;
1335
struct ctlname carpname[] = CARPCTL_NAMES;
1336
struct ctlname pfsyncname[] = PFSYNCCTL_NAMES;
1337
struct ctlname divertname[] = DIVERTCTL_NAMES;
1338
struct ctlname bpfname[] = CTL_NET_BPF_NAMES;
1339
struct ctlname ifqname[] = CTL_IFQ_NAMES;
1340
struct ctlname pipexname[] = PIPEXCTL_NAMES;
1341
struct list inetlist = { inetname, IPPROTO_MAXID };
1342
struct list inetvars[] = {
1343
	{ ipname, IPCTL_MAXID },	/* ip */
1344
	{ icmpname, ICMPCTL_MAXID },	/* icmp */
1345
	{ igmpname, IGMPCTL_MAXID },	/* igmp */
1346
	{ 0, 0 },			/* ggmp */
1347
	{ ipipname, IPIPCTL_MAXID },	/* ipencap */
1348
	{ 0, 0 },
1349
	{ tcpname, TCPCTL_MAXID },	/* tcp */
1350
	{ 0, 0 },
1351
	{ 0, 0 },			/* egp */
1352
	{ 0, 0 },
1353
	{ 0, 0 },
1354
	{ 0, 0 },
1355
	{ 0, 0 },			/* pup */
1356
	{ 0, 0 },
1357
	{ 0, 0 },
1358
	{ 0, 0 },
1359
	{ 0, 0 },
1360
	{ udpname, UDPCTL_MAXID },	/* udp */
1361
	{ 0, 0 },
1362
	{ 0, 0 },
1363
	{ 0, 0 },
1364
	{ 0, 0 },
1365
	{ 0, 0 },
1366
	{ 0, 0 },
1367
	{ 0, 0 },
1368
	{ 0, 0 },
1369
	{ 0, 0 },
1370
	{ 0, 0 },
1371
	{ 0, 0 },
1372
	{ 0, 0 },
1373
	{ 0, 0 },
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
	{ grename, GRECTL_MAXID },	/* gre */
1391
	{ 0, 0 },
1392
	{ 0, 0 },
1393
	{ espname, ESPCTL_MAXID },	/* esp */
1394
	{ ahname, AHCTL_MAXID },	/* ah */
1395
	{ 0, 0 },
1396
	{ 0, 0 },
1397
	{ 0, 0 },
1398
	{ mobileipname, MOBILEIPCTL_MAXID }, /* mobileip */
1399
	{ 0, 0 },
1400
	{ 0, 0 },
1401
	{ 0, 0 },
1402
	{ 0, 0 },
1403
	{ 0, 0 },
1404
	{ 0, 0 },
1405
	{ 0, 0 },
1406
	{ 0, 0 },
1407
	{ 0, 0 },
1408
	{ 0, 0 },
1409
	{ 0, 0 },
1410
	{ 0, 0 },
1411
	{ 0, 0 },
1412
	{ 0, 0 },
1413
	{ 0, 0 },
1414
	{ 0, 0 },
1415
	{ 0, 0 },
1416
	{ 0, 0 },
1417
	{ 0, 0 },
1418
	{ 0, 0 },
1419
	{ 0, 0 },
1420
	{ 0, 0 },
1421
	{ 0, 0 },
1422
	{ 0, 0 },
1423
	{ 0, 0 },
1424
	{ 0, 0 },
1425
	{ 0, 0 },
1426
	{ 0, 0 },
1427
	{ 0, 0 },
1428
	{ 0, 0 },
1429
	{ 0, 0 },
1430
	{ 0, 0 },
1431
	{ 0, 0 },
1432
	{ 0, 0 },
1433
	{ 0, 0 },
1434
	{ 0, 0 },
1435
	{ 0, 0 },
1436
	{ 0, 0 },
1437
	{ 0, 0 },
1438
	{ 0, 0 },
1439
	{ 0, 0 },
1440
	{ etheripname, ETHERIPCTL_MAXID },
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
	{ ipcompname, IPCOMPCTL_MAXID },
1452
	{ 0, 0 },
1453
	{ 0, 0 },
1454
	{ 0, 0 },
1455
	{ carpname, CARPCTL_MAXID },
1456
	{ 0, 0 },
1457
	{ 0, 0 },
1458
	{ 0, 0 },
1459
	{ 0, 0 },
1460
	{ 0, 0 },
1461
	{ 0, 0 },
1462
	{ 0, 0 },
1463
	{ 0, 0 },
1464
	{ 0, 0 },
1465
	{ 0, 0 },
1466
	{ 0, 0 },
1467
	{ 0, 0 },
1468
	{ 0, 0 },
1469
	{ 0, 0 },
1470
	{ 0, 0 },
1471
	{ 0, 0 },
1472
	{ 0, 0 },
1473
	{ 0, 0 },
1474
	{ 0, 0 },
1475
	{ 0, 0 },
1476
	{ 0, 0 },
1477
	{ 0, 0 },
1478
	{ 0, 0 },
1479
	{ 0, 0 },
1480
	{ 0, 0 },
1481
	{ 0, 0 },
1482
	{ 0, 0 },
1483
	{ 0, 0 },
1484
	{ 0, 0 },
1485
	{ 0, 0 },
1486
	{ 0, 0 },
1487
	{ 0, 0 },
1488
	{ 0, 0 },
1489
	{ 0, 0 },
1490
	{ 0, 0 },
1491
	{ 0, 0 },
1492
	{ 0, 0 },
1493
	{ 0, 0 },
1494
	{ 0, 0 },
1495
	{ 0, 0 },
1496
	{ 0, 0 },
1497
	{ 0, 0 },
1498
	{ 0, 0 },
1499
	{ 0, 0 },
1500
	{ 0, 0 },
1501
	{ 0, 0 },
1502
	{ 0, 0 },
1503
	{ 0, 0 },
1504
	{ 0, 0 },
1505
	{ 0, 0 },
1506
	{ 0, 0 },
1507
	{ 0, 0 },
1508
	{ 0, 0 },
1509
	{ 0, 0 },
1510
	{ 0, 0 },
1511
	{ 0, 0 },
1512
	{ 0, 0 },
1513
	{ 0, 0 },
1514
	{ 0, 0 },
1515
	{ 0, 0 },
1516
	{ 0, 0 },
1517
	{ 0, 0 },
1518
	{ 0, 0 },
1519
	{ 0, 0 },
1520
	{ 0, 0 },
1521
	{ 0, 0 },
1522
	{ 0, 0 },
1523
	{ 0, 0 },
1524
	{ 0, 0 },
1525
	{ 0, 0 },
1526
	{ 0, 0 },
1527
	{ 0, 0 },
1528
	{ 0, 0 },
1529
	{ 0, 0 },
1530
	{ 0, 0 },
1531
	{ 0, 0 },
1532
	{ 0, 0 },
1533
	{ 0, 0 },
1534
	{ 0, 0 },
1535
	{ 0, 0 },
1536
	{ 0, 0 },
1537
	{ 0, 0 },
1538
	{ 0, 0 },
1539
	{ 0, 0 },
1540
	{ 0, 0 },
1541
	{ 0, 0 },
1542
	{ 0, 0 },
1543
	{ 0, 0 },
1544
	{ 0, 0 },
1545
	{ 0, 0 },
1546
	{ 0, 0 },
1547
	{ 0, 0 },
1548
	{ 0, 0 },
1549
	{ 0, 0 },
1550
	{ 0, 0 },
1551
	{ 0, 0 },
1552
	{ 0, 0 },
1553
	{ 0, 0 },
1554
	{ 0, 0 },
1555
	{ 0, 0 },
1556
	{ 0, 0 },
1557
	{ 0, 0 },
1558
	{ 0, 0 },
1559
	{ 0, 0 },
1560
	{ 0, 0 },
1561
	{ 0, 0 },
1562
	{ 0, 0 },
1563
	{ 0, 0 },
1564
	{ 0, 0 },
1565
	{ 0, 0 },
1566
	{ 0, 0 },
1567
	{ 0, 0 },
1568
	{ 0, 0 },
1569
	{ 0, 0 },
1570
	{ 0, 0 },
1571
	{ 0, 0 },
1572
	{ 0, 0 },
1573
	{ 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
	{ pfsyncname, PFSYNCCTL_MAXID },
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
	{ divertname, DIVERTCTL_MAXID },
1602
};
1603
struct list bpflist = { bpfname, NET_BPF_MAXID };
1604
struct list ifqlist = { ifqname, IFQCTL_MAXID };
1605
struct list pipexlist = { pipexname, PIPEXCTL_MAXID };
1606
1607
struct list kernmalloclist = { kernmallocname, KERN_MALLOC_MAXID };
1608
struct list forkstatlist = { forkstatname, KERN_FORKSTAT_MAXID };
1609
struct list nchstatslist = { nchstatsname, KERN_NCHSTATS_MAXID };
1610
struct list ttylist = { ttysname, KERN_TTY_MAXID };
1611
struct list semlist = { semname, KERN_SEMINFO_MAXID };
1612
struct list shmlist = { shmname, KERN_SHMINFO_MAXID };
1613
struct list watchdoglist = { watchdogname, KERN_WATCHDOG_MAXID };
1614
struct list tclist = { tcname, KERN_TIMECOUNTER_MAXID };
1615
1616
/*
1617
 * handle vfs namei cache statistics
1618
 */
1619
int
1620
sysctl_nchstats(char *string, char **bufpp, int mib[], int flags, int *typep)
1621
{
1622
	static struct nchstats nch;
1623
	int indx;
1624
	size_t size;
1625
	static int keepvalue = 0;
1626
1627
	if (*bufpp == NULL) {
1628
		bzero(&nch, sizeof(struct nchstats));
1629
		listall(string, &nchstatslist);
1630
		return (-1);
1631
	}
1632
	if ((indx = findname(string, "third", bufpp, &nchstatslist)) == -1)
1633
		return (-1);
1634
	mib[2] = indx;
1635
	if (*bufpp != NULL) {
1636
		warnx("fourth level name in %s is invalid", string);
1637
		return (-1);
1638
	}
1639
	if (keepvalue == 0) {
1640
		size = sizeof(struct nchstats);
1641
		if (sysctl(mib, 2, &nch, &size, NULL, 0) < 0)
1642
			return (-1);
1643
		keepvalue = 1;
1644
	}
1645
	if (!nflag)
1646
		(void)printf("%s%s", string, equ);
1647
	switch (indx) {
1648
	case KERN_NCHSTATS_GOODHITS:
1649
		(void)printf("%llu\n", nch.ncs_goodhits);
1650
		break;
1651
	case KERN_NCHSTATS_NEGHITS:
1652
		(void)printf("%llu\n", nch.ncs_neghits);
1653
		break;
1654
	case KERN_NCHSTATS_BADHITS:
1655
		(void)printf("%llu\n", nch.ncs_badhits);
1656
		break;
1657
	case KERN_NCHSTATS_FALSEHITS:
1658
		(void)printf("%llu\n", nch.ncs_falsehits);
1659
		break;
1660
	case KERN_NCHSTATS_MISS:
1661
		(void)printf("%llu\n", nch.ncs_miss);
1662
		break;
1663
	case KERN_NCHSTATS_LONG:
1664
		(void)printf("%llu\n", nch.ncs_long);
1665
		break;
1666
	case KERN_NCHSTATS_PASS2:
1667
		(void)printf("%llu\n", nch.ncs_pass2);
1668
		break;
1669
	case KERN_NCHSTATS_2PASSES:
1670
		(void)printf("%llu\n", nch.ncs_2passes);
1671
		break;
1672
	case KERN_NCHSTATS_REVHITS:
1673
		(void)printf("%llu\n", nch.ncs_revhits);
1674
		break;
1675
	case KERN_NCHSTATS_REVMISS:
1676
		(void)printf("%llu\n", nch.ncs_revmiss);
1677
		break;
1678
	case KERN_NCHSTATS_DOTHITS:
1679
		(void)printf("%llu\n", nch.ncs_dothits);
1680
		break;
1681
	case KERN_NCHSTATS_DOTDOTHITS:
1682
		(void)printf("%llu\n", nch.ncs_dotdothits);
1683
		break;
1684
	}
1685
	return (-1);
1686
}
1687
1688
/*
1689
 * handle tty statistics
1690
 */
1691
int
1692
sysctl_tty(char *string, char **bufpp, int mib[], int flags, int *typep)
1693
{
1694
	int indx;
1695
1696
	if (*bufpp == NULL) {
1697
		listall(string, &ttylist);
1698
		return (-1);
1699
	}
1700
	if ((indx = findname(string, "third", bufpp, &ttylist)) == -1)
1701
		return (-1);
1702
	mib[2] = indx;
1703
1704
	if ((*typep = ttylist.list[indx].ctl_type) == CTLTYPE_STRUCT) {
1705
		if (flags)
1706
			warnx("use pstat -t to view %s information",
1707
			    string);
1708
		return (-1);
1709
	}
1710
	return (3);
1711
}
1712
1713
/*
1714
 * handle fork statistics
1715
 */
1716
int
1717
sysctl_forkstat(char *string, char **bufpp, int mib[], int flags, int *typep)
1718
{
1719
	static struct forkstat fks;
1720
	static int keepvalue = 0;
1721
	int indx;
1722
	size_t size;
1723
1724
	if (*bufpp == NULL) {
1725
		bzero(&fks, sizeof(struct forkstat));
1726
		listall(string, &forkstatlist);
1727
		return (-1);
1728
	}
1729
	if ((indx = findname(string, "third", bufpp, &forkstatlist)) == -1)
1730
		return (-1);
1731
	if (*bufpp != NULL) {
1732
		warnx("fourth level name in %s is invalid", string);
1733
		return (-1);
1734
	}
1735
	if (keepvalue == 0) {
1736
		size = sizeof(struct forkstat);
1737
		if (sysctl(mib, 2, &fks, &size, NULL, 0) < 0)
1738
			return (-1);
1739
		keepvalue = 1;
1740
	}
1741
	if (!nflag)
1742
		(void)printf("%s%s", string, equ);
1743
	switch (indx)	{
1744
	case KERN_FORKSTAT_FORK:
1745
		(void)printf("%u\n", fks.cntfork);
1746
		break;
1747
	case KERN_FORKSTAT_VFORK:
1748
		(void)printf("%u\n", fks.cntvfork);
1749
		break;
1750
	case KERN_FORKSTAT_TFORK:
1751
		(void)printf("%u\n", fks.cnttfork);
1752
		break;
1753
	case KERN_FORKSTAT_KTHREAD:
1754
		(void)printf("%u\n", fks.cntkthread);
1755
		break;
1756
	case KERN_FORKSTAT_SIZFORK:
1757
		(void)printf("%llu\n", fks.sizfork);
1758
		break;
1759
	case KERN_FORKSTAT_SIZVFORK:
1760
		(void)printf("%llu\n", fks.sizvfork);
1761
		break;
1762
	case KERN_FORKSTAT_SIZTFORK:
1763
		(void)printf("%llu\n", fks.siztfork);
1764
		break;
1765
	case KERN_FORKSTAT_SIZKTHREAD:
1766
		(void)printf("%llu\n", fks.sizkthread);
1767
		break;
1768
	}
1769
	return (-1);
1770
}
1771
1772
/*
1773
 * handle malloc statistics
1774
 */
1775
int
1776
sysctl_malloc(char *string, char **bufpp, int mib[], int flags, int *typep)
1777
{
1778
	int indx, stor, i;
1779
	char *name, bufp[SYSCTL_BUFSIZ], *buf, *ptr;
1780
	const char *errstr;
1781
	struct list lp;
1782
	size_t size;
1783
1784
	if (*bufpp == NULL) {
1785
		listall(string, &kernmalloclist);
1786
		return (-1);
1787
	}
1788
	if ((indx = findname(string, "third", bufpp, &kernmalloclist)) == -1)
1789
		return (-1);
1790
	mib[2] = indx;
1791
	if (mib[2] == KERN_MALLOC_BUCKET) {
1792
		if ((name = strsep(bufpp, ".")) == NULL) {
1793
			size = SYSCTL_BUFSIZ;
1794
			stor = mib[2];
1795
			mib[2] = KERN_MALLOC_BUCKETS;
1796
			buf = bufp;
1797
			if (sysctl(mib, 3, buf, &size, NULL, 0) < 0)
1798
				return (-1);
1799
			mib[2] = stor;
1800
			for (stor = 0, i = 0; i < size; i++)
1801
				if (buf[i] == ',')
1802
					stor++;
1803
			lp.list = calloc(stor + 2, sizeof(struct ctlname));
1804
			if (lp.list == NULL)
1805
				return (-1);
1806
			lp.size = stor + 2;
1807
			for (i = 1; (ptr = strsep(&buf, ",")) != NULL; i++) {
1808
			        lp.list[i].ctl_name = ptr;
1809
				lp.list[i].ctl_type = CTLTYPE_STRUCT;
1810
			}
1811
			listall(string, &lp);
1812
			free(lp.list);
1813
			return (-1);
1814
		}
1815
		mib[3] = strtonum(name, 0, INT_MAX, &errstr);
1816
		if (errstr)
1817
			return -1;
1818
		return (4);
1819
	} else if (mib[2] == KERN_MALLOC_BUCKETS) {
1820
		*typep = CTLTYPE_STRING;
1821
		return (3);
1822
	} else if (mib[2] == KERN_MALLOC_KMEMSTATS) {
1823
		size = SYSCTL_BUFSIZ;
1824
		stor = mib[2];
1825
		mib[2] = KERN_MALLOC_KMEMNAMES;
1826
		buf = bufp;
1827
		if (sysctl(mib, 3, buf, &size, NULL, 0) < 0)
1828
			return (-1);
1829
		mib[2] = stor;
1830
		if ((name = strsep(bufpp, ".")) == NULL) {
1831
			for (stor = 0, i = 0; i < size; i++)
1832
				if (buf[i] == ',')
1833
					stor++;
1834
			lp.list = calloc(stor + 2, sizeof(struct ctlname));
1835
			if (lp.list == NULL)
1836
				return (-1);
1837
			lp.size = stor + 2;
1838
			for (i = 1; (ptr = strsep(&buf, ",")) != NULL; i++) {
1839
				if (ptr[0] == '\0') {
1840
					i--;
1841
					continue;
1842
				}
1843
			    	lp.list[i].ctl_name = ptr;
1844
				lp.list[i].ctl_type = CTLTYPE_STRUCT;
1845
			}
1846
			listall(string, &lp);
1847
			free(lp.list);
1848
			return (-1);
1849
		}
1850
		ptr = strstr(buf, name);
1851
 tryagain:
1852
		if (ptr == NULL) {
1853
			warnx("fourth level name %s in %s is invalid", name,
1854
			    string);
1855
			return (-1);
1856
		}
1857
		if ((*(ptr + strlen(name)) != ',') &&
1858
		    (*(ptr + strlen(name)) != '\0')) {
1859
			ptr = strstr(ptr + 1, name); /* retry */
1860
			goto tryagain;
1861
		}
1862
		if ((ptr != buf) && (*(ptr - 1) != ',')) {
1863
			ptr = strstr(ptr + 1, name); /* retry */
1864
			goto tryagain;
1865
		}
1866
		for (i = 0, stor = 0; buf + i < ptr; i++)
1867
			if (buf[i] == ',')
1868
				stor++;
1869
		mib[3] = stor;
1870
		return (4);
1871
	} else if (mib[2] == KERN_MALLOC_KMEMNAMES) {
1872
		*typep = CTLTYPE_STRING;
1873
		return (3);
1874
	}
1875
	return (-1);
1876
}
1877
1878
#ifdef CPU_CHIPSET
1879
/*
1880
 * handle machdep.chipset requests
1881
 */
1882
struct ctlname chipsetname[] = CTL_CHIPSET_NAMES;
1883
struct list chipsetlist = { chipsetname, CPU_CHIPSET_MAXID };
1884
1885
int
1886
sysctl_chipset(char *string, char **bufpp, int mib[], int flags, int *typep)
1887
{
1888
	int indx, bwx;
1889
	static void *q;
1890
	size_t len;
1891
	char *p;
1892
1893
	if (*bufpp == NULL) {
1894
		listall(string, &chipsetlist);
1895
		return (-1);
1896
	}
1897
	if ((indx = findname(string, "third", bufpp, &chipsetlist)) == -1)
1898
		return (-1);
1899
	mib[2] = indx;
1900
	if (!nflag)
1901
		printf("%s%s", string, equ);
1902
	switch(mib[2]) {
1903
	case CPU_CHIPSET_MEM:
1904
	case CPU_CHIPSET_DENSE:
1905
	case CPU_CHIPSET_PORTS:
1906
	case CPU_CHIPSET_HAE_MASK:
1907
		len = sizeof(void *);
1908
		if (sysctl(mib, 3, &q, &len, NULL, 0) < 0)
1909
			goto done;
1910
		printf("%p", q);
1911
		break;
1912
	case CPU_CHIPSET_BWX:
1913
		len = sizeof(int);
1914
		if (sysctl(mib, 3, &bwx, &len, NULL, 0) < 0)
1915
			goto done;
1916
		printf("%d", bwx);
1917
		break;
1918
	case CPU_CHIPSET_TYPE:
1919
		if (sysctl(mib, 3, NULL, &len, NULL, 0) < 0)
1920
			goto done;
1921
		p = malloc(len + 1);
1922
		if (p == NULL)
1923
			goto done;
1924
		if (sysctl(mib, 3, p, &len, NULL, 0) < 0) {
1925
			free(p);
1926
			goto done;
1927
		}
1928
		p[len] = '\0';
1929
		printf("%s", p);
1930
		free(p);
1931
		break;
1932
	}
1933
done:
1934
	printf("\n");
1935
	return (-1);
1936
}
1937
#endif
1938
/*
1939
 * handle internet requests
1940
 */
1941
int
1942
sysctl_inet(char *string, char **bufpp, int mib[], int flags, int *typep)
1943
{
1944
	struct list *lp;
1945
	int indx;
1946
1947
24
	if (*bufpp == NULL) {
1948
		listall(string, &inetlist);
1949
		return (-1);
1950
	}
1951
12
	if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
1952
		return (-1);
1953
12
	mib[2] = indx;
1954

24
	if (indx < IPPROTO_MAXID && inetvars[indx].list != NULL)
1955
		lp = &inetvars[indx];
1956
	else if (!flags)
1957
		return (-1);
1958
	else {
1959
		warnx("%s: no variables defined for this protocol", string);
1960
		return (-1);
1961
	}
1962
12
	if (*bufpp == NULL) {
1963
		listall(string, lp);
1964
		return (-1);
1965
	}
1966
12
	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
1967
		return (-1);
1968
12
	mib[3] = indx;
1969
12
	*typep = lp->list[indx].ctl_type;
1970
12
	if (*typep == CTLTYPE_NODE) {
1971
		int tindx;
1972
1973
		if (*bufpp == NULL) {
1974
			listall(string, &ifqlist);
1975
			return(-1);
1976
		}
1977
		lp = &ifqlist;
1978
		if ((tindx = findname(string, "fifth", bufpp, lp)) == -1)
1979
			return (-1);
1980
		mib[4] = tindx;
1981
		*typep = lp->list[tindx].ctl_type;
1982
		return(5);
1983
	}
1984
12
	return (4);
1985
12
}
1986
1987
struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES;
1988
struct ctlname ip6name[] = IPV6CTL_NAMES;
1989
struct ctlname icmp6name[] = ICMPV6CTL_NAMES;
1990
struct ctlname divert6name[] = DIVERT6CTL_NAMES;
1991
struct list inet6list = { inet6name, IPV6PROTO_MAXID };
1992
struct list inet6vars[] = {
1993
/*0*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1994
	{ 0, 0 },
1995
	{ 0, 0 },
1996
	{ 0, 0 },
1997
	{ 0, 0 },
1998
	{ 0, 0 },
1999
/*10*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2000
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2001
/*20*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2002
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2003
/*30*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2004
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2005
/*40*/	{ 0, 0 },
2006
	{ ip6name, IPV6CTL_MAXID },	/* ipv6 */
2007
	{ 0, 0 },
2008
	{ 0, 0 },
2009
	{ 0, 0 },
2010
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2011
/*50*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2012
	{ 0, 0 },
2013
	{ 0, 0 },
2014
	{ 0, 0 },
2015
	{ icmp6name, ICMPV6CTL_MAXID },	/* icmp6 */
2016
	{ 0, 0 },
2017
/*60*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2018
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2019
/*70*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2020
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2021
/*80*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2022
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2023
/*90*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2024
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2025
/*100*/	{ 0, 0 },
2026
	{ 0, 0 },
2027
	{ 0, 0 },
2028
	{ 0, 0 },	/* pim6 */
2029
	{ 0, 0 },
2030
	{ 0, 0 },
2031
	{ 0, 0 },
2032
	{ 0, 0 },
2033
	{ 0, 0 },
2034
	{ 0, 0 },
2035
/*110*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2036
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2037
/*120*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2038
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2039
/*130*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2040
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2041
/*140*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2042
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2043
/*150*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2044
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2045
/*160*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2046
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2047
/*170*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2048
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2049
/*180*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2050
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2051
/*190*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2052
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2053
/*200*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2054
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2055
/*210*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2056
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2057
/*220*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2058
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2059
/*230*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2060
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2061
/*240*/	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2062
	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2063
/*250*/	{ 0, 0 },
2064
	{ 0, 0 },
2065
	{ 0, 0 },
2066
	{ 0, 0 },
2067
	{ 0, 0 },
2068
	{ 0, 0 },
2069
	{ 0, 0 },
2070
	{ 0, 0 },
2071
	{ divert6name, DIVERT6CTL_MAXID },
2072
};
2073
2074
/*
2075
 * handle internet6 requests
2076
 */
2077
int
2078
sysctl_inet6(char *string, char **bufpp, int mib[], int flags, int *typep)
2079
{
2080
	struct list *lp;
2081
	int indx;
2082
2083
	if (*bufpp == NULL) {
2084
		listall(string, &inet6list);
2085
		return (-1);
2086
	}
2087
	if ((indx = findname(string, "third", bufpp, &inet6list)) == -1)
2088
		return (-1);
2089
	mib[2] = indx;
2090
	if (indx < IPV6PROTO_MAXID && inet6vars[indx].list != NULL)
2091
		lp = &inet6vars[indx];
2092
	else if (!flags)
2093
		return (-1);
2094
	else {
2095
		warnx("%s: no variables defined for this protocol", string);
2096
		return (-1);
2097
	}
2098
	if (*bufpp == NULL) {
2099
		listall(string, lp);
2100
		return (-1);
2101
	}
2102
	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
2103
		return (-1);
2104
	mib[3] = indx;
2105
	*typep = lp->list[indx].ctl_type;
2106
	if (*typep == CTLTYPE_NODE) {
2107
		int tindx;
2108
2109
		if (*bufpp == NULL) {
2110
			listall(string, &ifqlist);
2111
			return(-1);
2112
		}
2113
		lp = &ifqlist;
2114
		if ((tindx = findname(string, "fifth", bufpp, lp)) == -1)
2115
			return (-1);
2116
		mib[4] = tindx;
2117
		*typep = lp->list[tindx].ctl_type;
2118
		return(5);
2119
	}
2120
	return (4);
2121
}
2122
2123
/* handle bpf requests */
2124
int
2125
sysctl_bpf(char *string, char **bufpp, int mib[], int flags, int *typep)
2126
{
2127
	int indx;
2128
2129
	if (*bufpp == NULL) {
2130
		listall(string, &bpflist);
2131
		return (-1);
2132
	}
2133
	if ((indx = findname(string, "third", bufpp, &bpflist)) == -1)
2134
		return (-1);
2135
	mib[2] = indx;
2136
	*typep = CTLTYPE_INT;
2137
	return (3);
2138
}
2139
2140
struct ctlname mplsname[] = MPLSCTL_NAMES;
2141
struct list mplslist = { mplsname, MPLSCTL_MAXID };
2142
2143
/* handle MPLS requests */
2144
int
2145
sysctl_mpls(char *string, char **bufpp, int mib[], int flags, int *typep)
2146
{
2147
	struct list *lp;
2148
	int indx;
2149
2150
	if (*bufpp == NULL) {
2151
		listall(string, &mplslist);
2152
		return (-1);
2153
	}
2154
	if ((indx = findname(string, "third", bufpp, &mplslist)) == -1)
2155
		return (-1);
2156
	mib[2] = indx;
2157
	*typep = mplslist.list[indx].ctl_type;
2158
	if (*typep == CTLTYPE_NODE) {
2159
		int tindx;
2160
2161
		if (*bufpp == NULL) {
2162
			listall(string, &ifqlist);
2163
			return(-1);
2164
		}
2165
		lp = &ifqlist;
2166
		if ((tindx = findname(string, "fourth", bufpp, lp)) == -1)
2167
			return (-1);
2168
		mib[3] = tindx;
2169
		*typep = lp->list[tindx].ctl_type;
2170
		return(4);
2171
	}
2172
	return (3);
2173
}
2174
2175
/* handle PIPEX requests */
2176
int
2177
sysctl_pipex(char *string, char **bufpp, int mib[], int flags, int *typep)
2178
{
2179
	struct list *lp;
2180
	int indx;
2181
2182
	if (*bufpp == NULL) {
2183
		listall(string, &pipexlist);
2184
		return (-1);
2185
	}
2186
	if ((indx = findname(string, "third", bufpp, &pipexlist)) == -1)
2187
		return (-1);
2188
	mib[2] = indx;
2189
	*typep = pipexlist.list[indx].ctl_type;
2190
	if (*typep == CTLTYPE_NODE) {
2191
		int tindx;
2192
2193
		if (*bufpp == NULL) {
2194
			listall(string, &ifqlist);
2195
			return(-1);
2196
		}
2197
		lp = &ifqlist;
2198
		if ((tindx = findname(string, "fourth", bufpp, lp)) == -1)
2199
			return (-1);
2200
		mib[3] = tindx;
2201
		*typep = lp->list[tindx].ctl_type;
2202
		return(4);
2203
	}
2204
	return (3);
2205
}
2206
2207
/*
2208
 * Handle SysV semaphore info requests
2209
 */
2210
int
2211
sysctl_seminfo(string, bufpp, mib, flags, typep)
2212
	char *string;
2213
	char **bufpp;
2214
	int mib[];
2215
	int flags;
2216
	int *typep;
2217
{
2218
	int indx;
2219
2220
	if (*bufpp == NULL) {
2221
		listall(string, &semlist);
2222
		return (-1);
2223
	}
2224
	if ((indx = findname(string, "third", bufpp, &semlist)) == -1)
2225
		return (-1);
2226
	mib[2] = indx;
2227
	*typep = CTLTYPE_INT;
2228
	return (3);
2229
}
2230
2231
/*
2232
 * Handle SysV shared memory info requests
2233
 */
2234
int
2235
sysctl_shminfo(string, bufpp, mib, flags, typep)
2236
	char *string;
2237
	char **bufpp;
2238
	int mib[];
2239
	int flags;
2240
	int *typep;
2241
{
2242
	int indx;
2243
2244
	if (*bufpp == NULL) {
2245
		listall(string, &shmlist);
2246
		return (-1);
2247
	}
2248
	if ((indx = findname(string, "third", bufpp, &shmlist)) == -1)
2249
		return (-1);
2250
	mib[2] = indx;
2251
	*typep = CTLTYPE_INT;
2252
	return (3);
2253
}
2254
2255
/*
2256
 * Handle watchdog support
2257
 */
2258
int
2259
sysctl_watchdog(char *string, char **bufpp, int mib[], int flags,
2260
    int *typep)
2261
{
2262
	int indx;
2263
2264
	if (*bufpp == NULL) {
2265
		listall(string, &watchdoglist);
2266
		return (-1);
2267
	}
2268
	if ((indx = findname(string, "third", bufpp, &watchdoglist)) == -1)
2269
		return (-1);
2270
	mib[2] = indx;
2271
	*typep = watchdoglist.list[indx].ctl_type;
2272
	return (3);
2273
}
2274
2275
/*
2276
 * Handle timecounter support
2277
 */
2278
int
2279
sysctl_tc(char *string, char **bufpp, int mib[], int flags,
2280
    int *typep)
2281
{
2282
	int indx;
2283
2284
	if (*bufpp == NULL) {
2285
		listall(string, &tclist);
2286
		return (-1);
2287
	}
2288
	if ((indx = findname(string, "third", bufpp, &tclist)) == -1)
2289
		return (-1);
2290
	mib[2] = indx;
2291
	*typep = tclist.list[indx].ctl_type;
2292
	return (3);
2293
}
2294
2295
/*
2296
 * Handle hardware monitoring sensors support
2297
 */
2298
int
2299
sysctl_sensors(char *string, char **bufpp, int mib[], int flags, int *typep)
2300
{
2301
	char *devname, *typename;
2302
	int dev, numt, i;
2303
	enum sensor_type type;
2304
	struct sensordev snsrdev;
2305
	size_t sdlen = sizeof(snsrdev);
2306
2307
	if (*bufpp == NULL) {
2308
		char buf[SYSCTL_BUFSIZ];
2309
2310
		/* scan all sensor devices */
2311
		for (dev = 0; ; dev++) {
2312
			mib[2] = dev;
2313
			if (sysctl(mib, 3, &snsrdev, &sdlen, NULL, 0) == -1) {
2314
				if (errno == ENXIO)
2315
					continue;
2316
				if (errno == ENOENT)
2317
					break;
2318
			}
2319
			snprintf(buf, sizeof(buf), "%s.%s",
2320
			    string, snsrdev.xname);
2321
			print_sensordev(buf, mib, 3, &snsrdev);
2322
		}
2323
		return (-1);
2324
	}
2325
2326
	/*
2327
	 * If we get this far, it means that some arguments were
2328
	 * provided below hw.sensors tree.
2329
	 * The first branch of hw.sensors tree is the device name.
2330
	 */
2331
	if ((devname = strsep(bufpp, ".")) == NULL) {
2332
		warnx("%s: incomplete specification", string);
2333
		return (-1);
2334
	}
2335
	/* convert sensor device string to an integer */
2336
	for (dev = 0; ; dev++) {
2337
		mib[2] = dev;
2338
		if (sysctl(mib, 3, &snsrdev, &sdlen, NULL, 0) == -1) {
2339
			if (errno == ENXIO)
2340
				continue;
2341
			if (errno == ENOENT)
2342
				break;
2343
		}
2344
		if (strcmp(devname, snsrdev.xname) == 0)
2345
			break;
2346
	}
2347
	if (strcmp(devname, snsrdev.xname) != 0) {
2348
		warnx("%s: sensor device not found: %s", string, devname);
2349
		return (-1);
2350
	}
2351
	if (*bufpp == NULL) {
2352
		/* only device name was provided -- let's print all sensors
2353
		 * that are attached to the specified device
2354
		 */
2355
		print_sensordev(string, mib, 3, &snsrdev);
2356
		return (-1);
2357
	}
2358
2359
	/*
2360
	 * At this point we have identified the sensor device,
2361
	 * now let's go further and identify sensor type.
2362
	 */
2363
	if ((typename = strsep(bufpp, ".")) == NULL) {
2364
		warnx("%s: incomplete specification", string);
2365
		return (-1);
2366
	}
2367
	numt = -1;
2368
	for (i = 0; typename[i] != '\0'; i++)
2369
		if (isdigit((unsigned char)typename[i])) {
2370
			const char *errstr;
2371
2372
			numt = strtonum(&typename[i], 0, INT_MAX, &errstr);
2373
			if (errstr) {
2374
				warnx("%s: %s", string, errstr);
2375
				return (-1);
2376
			}
2377
			typename[i] = '\0';
2378
			break;
2379
		}
2380
	for (type = 0; type < SENSOR_MAX_TYPES; type++)
2381
		if (strcmp(typename, sensor_type_s[type]) == 0)
2382
			break;
2383
	if (type == SENSOR_MAX_TYPES) {
2384
		warnx("%s: sensor type not recognised: %s", string, typename);
2385
		return (-1);
2386
	}
2387
	mib[3] = type;
2388
2389
	/*
2390
	 * If no integer was provided after sensor_type, let's
2391
	 * print all sensors of the specified type.
2392
	 */
2393
	if (numt == -1) {
2394
		print_sensordev(string, mib, 4, &snsrdev);
2395
		return (-1);
2396
	}
2397
2398
	/*
2399
	 * At this point we know that we have received a direct request
2400
	 * via command-line for a specific sensor. Let's have the parse()
2401
	 * function deal with it further, and report any errors if such
2402
	 * sensor node does not exist.
2403
	 */
2404
	mib[4] = numt;
2405
	*typep = CTLTYPE_STRUCT;
2406
	return (5);
2407
}
2408
2409
/*
2410
 * Print sensors from the specified device.
2411
 */
2412
2413
void
2414
print_sensordev(char *string, int mib[], u_int mlen, struct sensordev *snsrdev)
2415
{
2416
	char buf[SYSCTL_BUFSIZ];
2417
	enum sensor_type type;
2418
2419
	if (mlen == 3) {
2420
		for (type = 0; type < SENSOR_MAX_TYPES; type++) {
2421
			mib[3] = type;
2422
			snprintf(buf, sizeof(buf), "%s.%s",
2423
			    string, sensor_type_s[type]);
2424
			print_sensordev(buf, mib, mlen+1, snsrdev);
2425
		}
2426
		return;
2427
	}
2428
2429
	if (mlen == 4) {
2430
		int numt;
2431
2432
		type = mib[3];
2433
		for (numt = 0; numt < snsrdev->maxnumt[type]; numt++) {
2434
			mib[4] = numt;
2435
			snprintf(buf, sizeof(buf), "%s%u", string, numt);
2436
			print_sensordev(buf, mib, mlen+1, snsrdev);
2437
		}
2438
		return;
2439
	}
2440
2441
	if (mlen == 5) {
2442
		struct sensor snsr;
2443
		size_t slen = sizeof(snsr);
2444
2445
		/* this function is only printing sensors in bulk, so we
2446
		 * do not return any error messages if the requested sensor
2447
		 * is not found by sysctl(3)
2448
		 */
2449
		if (sysctl(mib, 5, &snsr, &slen, NULL, 0) == -1)
2450
			return;
2451
2452
		if (slen > 0 && (snsr.flags & SENSOR_FINVALID) == 0) {
2453
			if (!nflag)
2454
				printf("%s%s", string, equ);
2455
			print_sensor(&snsr);
2456
			printf("\n");
2457
		}
2458
		return;
2459
	}
2460
}
2461
2462
void
2463
print_sensor(struct sensor *s)
2464
{
2465
	const char *name;
2466
2467
	if (s->flags & SENSOR_FUNKNOWN)
2468
		printf("unknown");
2469
	else {
2470
		switch (s->type) {
2471
		case SENSOR_TEMP:
2472
			printf("%.2f degC",
2473
			    (s->value - 273150000) / 1000000.0);
2474
			break;
2475
		case SENSOR_FANRPM:
2476
			printf("%lld RPM", s->value);
2477
			break;
2478
		case SENSOR_VOLTS_DC:
2479
			printf("%.2f VDC", s->value / 1000000.0);
2480
			break;
2481
		case SENSOR_VOLTS_AC:
2482
			printf("%.2f VAC", s->value / 1000000.0);
2483
			break;
2484
		case SENSOR_OHMS:
2485
			printf("%lld ohm", s->value);
2486
			break;
2487
		case SENSOR_WATTS:
2488
			printf("%.2f W", s->value / 1000000.0);
2489
			break;
2490
		case SENSOR_AMPS:
2491
			printf("%.2f A", s->value / 1000000.0);
2492
			break;
2493
		case SENSOR_WATTHOUR:
2494
			printf("%.2f Wh", s->value / 1000000.0);
2495
			break;
2496
		case SENSOR_AMPHOUR:
2497
			printf("%.2f Ah", s->value / 1000000.0);
2498
			break;
2499
		case SENSOR_INDICATOR:
2500
			printf("%s", s->value ? "On" : "Off");
2501
			break;
2502
		case SENSOR_INTEGER:
2503
			printf("%lld", s->value);
2504
			break;
2505
		case SENSOR_PERCENT:
2506
			printf("%.2f%%", s->value / 1000.0);
2507
			break;
2508
		case SENSOR_LUX:
2509
			printf("%.2f lx", s->value / 1000000.0);
2510
			break;
2511
		case SENSOR_DRIVE:
2512
			switch (s->value) {
2513
			case SENSOR_DRIVE_EMPTY:
2514
				name = "empty";
2515
				break;
2516
			case SENSOR_DRIVE_READY:
2517
				name = "ready";
2518
				break;
2519
			case SENSOR_DRIVE_POWERUP:
2520
				name = "powering up";
2521
				break;
2522
			case SENSOR_DRIVE_ONLINE:
2523
				name = "online";
2524
				break;
2525
			case SENSOR_DRIVE_IDLE:
2526
				name = "idle";
2527
				break;
2528
			case SENSOR_DRIVE_ACTIVE:
2529
				name = "active";
2530
				break;
2531
			case SENSOR_DRIVE_REBUILD:
2532
				name = "rebuilding";
2533
				break;
2534
			case SENSOR_DRIVE_POWERDOWN:
2535
				name = "powering down";
2536
				break;
2537
			case SENSOR_DRIVE_FAIL:
2538
				name = "failed";
2539
				break;
2540
			case SENSOR_DRIVE_PFAIL:
2541
				name = "degraded";
2542
				break;
2543
			default:
2544
				name = "unknown";
2545
				break;
2546
			}
2547
			printf("%s", name);
2548
			break;
2549
		case SENSOR_TIMEDELTA:
2550
			printf("%.6f secs", s->value / 1000000000.0);
2551
			break;
2552
		case SENSOR_HUMIDITY:
2553
			printf("%.2f%%", s->value / 1000.0);
2554
			break;
2555
		case SENSOR_FREQ:
2556
			printf("%.2f Hz", s->value / 1000000.0);
2557
			break;
2558
		case SENSOR_ANGLE:
2559
			printf("%3.4f degrees", s->value / 1000000.0);
2560
			break;
2561
		case SENSOR_DISTANCE:
2562
			printf("%.2f mm", s->value / 1000.0);
2563
			break;
2564
		case SENSOR_PRESSURE:
2565
			printf("%.2f Pa", s->value / 1000.0);
2566
			break;
2567
		case SENSOR_ACCEL:
2568
			printf("%2.4f m/s^2", s->value / 1000000.0);
2569
			break;
2570
		default:
2571
			printf("unknown");
2572
		}
2573
	}
2574
2575
	if (s->desc[0] != '\0')
2576
		printf(" (%s)", s->desc);
2577
2578
	switch (s->status) {
2579
	case SENSOR_S_UNSPEC:
2580
		break;
2581
	case SENSOR_S_OK:
2582
		printf(", OK");
2583
		break;
2584
	case SENSOR_S_WARN:
2585
		printf(", WARNING");
2586
		break;
2587
	case SENSOR_S_CRIT:
2588
		printf(", CRITICAL");
2589
		break;
2590
	case SENSOR_S_UNKNOWN:
2591
		printf(", UNKNOWN");
2592
		break;
2593
	}
2594
2595
	if (s->tv.tv_sec) {
2596
		time_t t = s->tv.tv_sec;
2597
		char ct[26];
2598
2599
		ctime_r(&t, ct);
2600
		ct[19] = '\0';
2601
		printf(", %s.%03ld", ct, s->tv.tv_usec / 1000);
2602
	}
2603
}
2604
2605
/*
2606
 * Scan a list of names searching for a particular name.
2607
 */
2608
int
2609
findname(char *string, char *level, char **bufp, struct list *namelist)
2610
{
2611
	char *name;
2612
	int i;
2613
2614

216
	if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
2615
		warnx("%s: incomplete specification", string);
2616
		return (-1);
2617
	}
2618
3120
	for (i = 0; i < namelist->size; i++)
2619

1896
		if (namelist->list[i].ctl_name != NULL &&
2620
336
		    strcmp(name, namelist->list[i].ctl_name) == 0)
2621
			break;
2622
72
	if (i == namelist->size) {
2623
		warnx("%s level name %s in %s is invalid", level, name, string);
2624
		return (-1);
2625
	}
2626
72
	return (i);
2627
72
}
2628
2629
void
2630
usage(void)
2631
{
2632
2633
	(void)fprintf(stderr,
2634
	    "usage: sysctl [-Aan]\n"
2635
	    "       sysctl [-n] name ...\n"
2636
	    "       sysctl [-nq] name=value ...\n");
2637
	exit(1);
2638
}