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