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