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