GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/sysctl/sysctl.c Lines: 0 1090 0.0 %
Date: 2016-12-06 Branches: 0 844 0.0 %

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