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