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