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