sysctl.c revision 1.241
1/* $OpenBSD: sysctl.c,v 1.241 2019/02/21 16:37:13 bluhm 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 } 513 break; 514 515 case CTL_HW: 516 switch (mib[1]) { 517 case HW_DISKSTATS: 518 /* 519 * Only complain if someone asks explicitly for this, 520 * otherwise "fail" silently. 521 */ 522 if (flags) 523 warnx("use vmstat to view %s information", 524 string); 525 return; 526 case HW_SENSORS: 527 special |= SENSORS; 528 len = sysctl_sensors(string, &bufp, mib, flags, &type); 529 if (len < 0) 530 return; 531 break; 532 case HW_PHYSMEM: 533 case HW_USERMEM: 534 /* 535 * Don't print these; we'll print the 64-bit 536 * variants instead. 537 */ 538 return; 539 } 540 break; 541 542 case CTL_VM: 543 if (mib[1] == VM_LOADAVG) { 544 double loads[3]; 545 546 getloadavg(loads, 3); 547 if (!nflag) 548 (void)printf("%s%s", string, equ); 549 (void)printf("%.2f %.2f %.2f\n", loads[0], 550 loads[1], loads[2]); 551 return; 552 } else if (mib[1] == VM_PSSTRINGS) { 553 struct _ps_strings _ps; 554 555 size = sizeof(_ps); 556 if (sysctl(mib, 2, &_ps, &size, NULL, 0) == -1) { 557 if (flags == 0) 558 return; 559 if (!nflag) 560 (void)printf("%s: ", string); 561 (void)puts("can't find ps strings"); 562 return; 563 } 564 if (!nflag) 565 (void)printf("%s%s", string, equ); 566 (void)printf("%p\n", _ps.val); 567 return; 568 } else if (mib[1] == VM_SWAPENCRYPT) { 569 len = sysctl_swpenc(string, &bufp, mib, flags, &type); 570 if (len < 0) 571 return; 572 573 break; 574 } else if (mib[1] == VM_NKMEMPAGES || 575 mib[1] == VM_ANONMIN || 576 mib[1] == VM_VTEXTMIN || 577 mib[1] == VM_VNODEMIN || 578 mib[1] == VM_MALLOC_CONF) { 579 break; 580 } 581 if (flags == 0) 582 return; 583 warnx("use vmstat or systat to view %s information", string); 584 return; 585 586 break; 587 588 case CTL_NET: 589 if (mib[1] == PF_INET) { 590 len = sysctl_inet(string, &bufp, mib, flags, &type); 591 if (len < 0) 592 return; 593 594 if ((mib[2] == IPPROTO_IP && mib[3] == IPCTL_MRTSTATS) || 595 (mib[2] == IPPROTO_IP && mib[3] == IPCTL_STATS) || 596 (mib[2] == IPPROTO_IP && mib[3] == IPCTL_MRTMFC) || 597 (mib[2] == IPPROTO_IP && mib[3] == IPCTL_MRTVIF) || 598 (mib[2] == IPPROTO_TCP && mib[3] == TCPCTL_STATS) || 599 (mib[2] == IPPROTO_UDP && mib[3] == UDPCTL_STATS) || 600 (mib[2] == IPPROTO_ESP && mib[3] == ESPCTL_STATS) || 601 (mib[2] == IPPROTO_AH && mib[3] == AHCTL_STATS) || 602 (mib[2] == IPPROTO_IGMP && mib[3] == IGMPCTL_STATS) || 603 (mib[2] == IPPROTO_ETHERIP && mib[3] == ETHERIPCTL_STATS) || 604 (mib[2] == IPPROTO_IPIP && mib[3] == IPIPCTL_STATS) || 605 (mib[2] == IPPROTO_IPCOMP && mib[3] == IPCOMPCTL_STATS) || 606 (mib[2] == IPPROTO_ICMP && mib[3] == ICMPCTL_STATS) || 607 (mib[2] == IPPROTO_CARP && mib[3] == CARPCTL_STATS) || 608 (mib[2] == IPPROTO_PFSYNC && mib[3] == PFSYNCCTL_STATS) || 609 (mib[2] == IPPROTO_DIVERT && mib[3] == DIVERTCTL_STATS)) { 610 if (flags == 0) 611 return; 612 warnx("use netstat to view %s information", 613 string); 614 return; 615 } else if ((mib[2] == IPPROTO_TCP && 616 (mib[3] == TCPCTL_BADDYNAMIC || 617 mib[3] == TCPCTL_ROOTONLY)) || 618 (mib[2] == IPPROTO_UDP && 619 (mib[3] == UDPCTL_BADDYNAMIC || 620 mib[3] == UDPCTL_ROOTONLY))) { 621 622 special |= BADDYNAMIC; 623 624 if (newval != NULL) 625 parse_baddynamic(mib, len, string, 626 &newval, &newsize, flags, nflag); 627 } 628 break; 629 } 630 if (mib[1] == PF_INET6) { 631 len = sysctl_inet6(string, &bufp, mib, flags, &type); 632 if (len < 0) 633 return; 634 635 if (mib[2] == IPPROTO_IPV6 && 636 mib[3] == IPV6CTL_SOIIKEY) 637 special |= HEX; 638 639 if ((mib[2] == IPPROTO_IPV6 && mib[3] == IPV6CTL_MRTMFC) || 640 (mib[2] == IPPROTO_IPV6 && mib[3] == IPV6CTL_MRTMIF) || 641 (mib[2] == IPPROTO_DIVERT && mib[3] == DIVERT6CTL_STATS)) { 642 if (flags == 0) 643 return; 644 warnx("use netstat to view %s information", 645 string); 646 return; 647 } 648 break; 649 } 650 if (mib[1] == PF_BPF) { 651 len = sysctl_bpf(string, &bufp, mib, flags, &type); 652 if (len < 0) 653 return; 654 break; 655 } 656 if (mib[1] == PF_MPLS) { 657 len = sysctl_mpls(string, &bufp, mib, flags, &type); 658 if (len < 0) 659 return; 660 break; 661 } 662 if (mib[1] == PF_PIPEX) { 663 len = sysctl_pipex(string, &bufp, mib, flags, &type); 664 if (len < 0) 665 return; 666 break; 667 } 668 if (flags == 0) 669 return; 670 warnx("use netstat to view %s information", string); 671 return; 672 673 case CTL_DEBUG: 674 mib[2] = CTL_DEBUG_VALUE; 675 len = 3; 676 break; 677 678 case CTL_MACHDEP: 679#ifdef CPU_CONSDEV 680 if (mib[1] == CPU_CONSDEV) 681 special |= CHRDEV; 682#endif 683#ifdef CPU_CPUID 684 if (mib[1] == CPU_CPUID) 685 special |= HEX; 686#endif 687#ifdef CPU_CPUFEATURE 688 if (mib[1] == CPU_CPUFEATURE) 689 special |= HEX; 690#endif 691#ifdef CPU_BLK2CHR 692 if (mib[1] == CPU_BLK2CHR) { 693 if (bufp == NULL) 694 return; 695 mib[2] = makedev(atoi(bufp),0); 696 bufp = NULL; 697 len = 3; 698 special |= CHRDEV; 699 break; 700 } 701#endif 702#ifdef CPU_CHR2BLK 703 if (mib[1] == CPU_CHR2BLK) { 704 if (bufp == NULL) 705 return; 706 mib[2] = makedev(atoi(bufp),0); 707 bufp = NULL; 708 len = 3; 709 special |= BLKDEV; 710 break; 711 } 712#endif 713#ifdef CPU_BIOS 714 if (mib[1] == CPU_BIOS) { 715 len = sysctl_bios(string, &bufp, mib, flags, &type); 716 if (len < 0) 717 return; 718 if (mib[2] == BIOS_DEV) 719 special |= BIOSDEV; 720 if (mib[2] == BIOS_DISKINFO) 721 special |= BIOSGEO; 722 break; 723 } 724#endif 725#ifdef CPU_CHIPSET 726 if (mib[1] == CPU_CHIPSET) { 727 len = sysctl_chipset(string, &bufp, mib, flags, &type); 728 if (len < 0) 729 return; 730 break; 731 } 732#endif 733 break; 734 735 case CTL_FS: 736 len = sysctl_fs(string, &bufp, mib, flags, &type); 737 if (len >= 0) 738 break; 739 return; 740 741 case CTL_VFS: 742 if (mib[1]) 743 len = sysctl_vfs(string, &bufp, mib, flags, &type); 744 else 745 len = sysctl_vfsgen(string, &bufp, mib, flags, &type); 746 if (len >= 0) { 747 if (type == CTLTYPE_STRUCT) { 748 if (flags) 749 warnx("use nfsstat to view %s information", 750 MOUNT_NFS); 751 return; 752 } else 753 break; 754 } 755 return; 756 757 case CTL_DDB: 758 break; 759 760 default: 761 warnx("illegal top level value: %d", mib[0]); 762 return; 763 764 } 765 if (bufp) { 766 warnx("name %s in %s is unknown", bufp, string); 767 return; 768 } 769 if (newsize > 0) { 770 const char *errstr; 771 772 switch (type) { 773 case CTLTYPE_INT: 774 if (special & UNSIGNED) 775 intval = strtonum(newval, 0, UINT_MAX, &errstr); 776 else 777 intval = strtonum(newval, INT_MIN, INT_MAX, 778 &errstr); 779 if (errstr != NULL) { 780 warnx("%s: value is %s: %s", string, errstr, 781 (char *)newval); 782 return; 783 } 784 newval = &intval; 785 newsize = sizeof(intval); 786 break; 787 788 case CTLTYPE_QUAD: 789 (void)sscanf(newval, "%lld", &quadval); 790 newval = &quadval; 791 newsize = sizeof(quadval); 792 break; 793 case CTLTYPE_STRING: 794 if (special & HEX) { 795 ssize_t len; 796 797 len = parse_hex_string(hex, sizeof(hex), 798 newval); 799 if (len == -1) { 800 warnx("%s: hex string %s: invalid", 801 string, newval); 802 return; 803 } 804 if (len > sizeof(hex)) { 805 warnx("%s: hex string %s: too long", 806 string, newval); 807 return; 808 } 809 810 newval = hex; 811 newsize = len; 812 } 813 break; 814 } 815 } 816 size = (special & SMALLBUF) ? 512 : SYSCTL_BUFSIZ; 817 if (sysctl(mib, len, buf, &size, newval, newsize) == -1) { 818 if (flags == 0) 819 return; 820 switch (errno) { 821 case EOPNOTSUPP: 822 warnx("%s: value is not available", string); 823 return; 824 case ENOTDIR: 825 warnx("%s: specification is incomplete", string); 826 return; 827 case ENOMEM: 828 warnx("%s: type is unknown to this program", string); 829 return; 830 case ENXIO: 831 if (special & BIOSGEO) 832 return; 833 default: 834 warn("%s", string); 835 return; 836 } 837 } 838 if (special & KMEMBUCKETS) { 839 struct kmembuckets *kb = (struct kmembuckets *)buf; 840 if (!nflag) 841 (void)printf("%s%s", string, equ); 842 printf("("); 843 printf("calls = %llu ", (long long)kb->kb_calls); 844 printf("total_allocated = %llu ", (long long)kb->kb_total); 845 printf("total_free = %lld ", (long long)kb->kb_totalfree); 846 printf("elements = %lld ", (long long)kb->kb_elmpercl); 847 printf("high watermark = %lld ", (long long)kb->kb_highwat); 848 printf("could_free = %lld", (long long)kb->kb_couldfree); 849 printf(")\n"); 850 return; 851 } 852 if (special & KMEMSTATS) { 853 struct kmemstats *km = (struct kmemstats *)buf; 854 int j, first = 1; 855 856 if (!nflag) 857 (void)printf("%s%s", string, equ); 858 (void)printf("(inuse = %ld, calls = %ld, memuse = %ldK, " 859 "limblocks = %d, mapblocks = %d, maxused = %ldK, " 860 "limit = %ldK, spare = %ld, sizes = (", 861 km->ks_inuse, km->ks_calls, 862 (km->ks_memuse + 1023) / 1024, km->ks_limblocks, 863 km->ks_mapblocks, (km->ks_maxused + 1023) / 1024, 864 (km->ks_limit + 1023) / 1024, km->ks_spare); 865 for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) { 866 if ((km->ks_size & j ) == 0) 867 continue; 868 if (first) 869 (void)printf("%d", j); 870 else 871 (void)printf(",%d", j); 872 first = 0; 873 } 874 if (first) 875 (void)printf("none"); 876 (void)printf("))\n"); 877 return; 878 } 879 if (special & CLOCK) { 880 struct clockinfo *clkp = (struct clockinfo *)buf; 881 882 if (!nflag) 883 (void)printf("%s%s", string, equ); 884 (void)printf( 885 "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n", 886 clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz); 887 return; 888 } 889 if (special & BOOTTIME) { 890 struct timeval *btp = (struct timeval *)buf; 891 time_t boottime; 892 893 if (!nflag) { 894 boottime = btp->tv_sec; 895 (void)printf("%s%s%s", string, equ, ctime(&boottime)); 896 } else 897 (void)printf("%lld\n", (long long)btp->tv_sec); 898 return; 899 } 900 if (special & BLKDEV) { 901 dev_t dev = *(dev_t *)buf; 902 903 if (!nflag) 904 (void)printf("%s%s%s\n", string, equ, 905 devname(dev, S_IFBLK)); 906 else 907 (void)printf("0x%x\n", dev); 908 return; 909 } 910 if (special & CHRDEV) { 911 dev_t dev = *(dev_t *)buf; 912 913 if (!nflag) 914 (void)printf("%s%s%s\n", string, equ, 915 devname(dev, S_IFCHR)); 916 else 917 (void)printf("0x%x\n", dev); 918 return; 919 } 920#ifdef CPU_BIOS 921 if (special & BIOSGEO) { 922 bios_diskinfo_t *pdi = (bios_diskinfo_t *)buf; 923 924 if (!nflag) 925 (void)printf("%s%s", string, equ); 926 (void)printf("bootdev = 0x%x, " 927 "cylinders = %u, heads = %u, sectors = %u\n", 928 pdi->bsd_dev, pdi->bios_cylinders, 929 pdi->bios_heads, pdi->bios_sectors); 930 return; 931 } 932 if (special & BIOSDEV) { 933 int dev = *(int*)buf; 934 935 if (!nflag) 936 (void)printf("%s%s", string, equ); 937 (void) printf("0x%02x\n", dev); 938 return; 939 } 940#endif 941 if (special & UNSIGNED) { 942 if (newsize == 0) { 943 if (!nflag) 944 (void)printf("%s%s", string, equ); 945 (void)printf("%u\n", *(u_int *)buf); 946 } else { 947 if (!qflag) { 948 if (!nflag) 949 (void)printf("%s: %u -> ", string, 950 *(u_int *)buf); 951 (void)printf("%u\n", *(u_int *)newval); 952 } 953 } 954 return; 955 } 956 if (special & BADDYNAMIC) { 957 u_int port, lastport; 958 u_int32_t *baddynamic = (u_int32_t *)buf; 959 960 if (!qflag) { 961 if (!nflag) 962 (void)printf("%s%s", string, 963 newsize ? ": " : equ); 964 lastport = 0; 965 for (port = 0; port < 65536; port++) 966 if (DP_ISSET(baddynamic, port)) { 967 (void)printf("%s%u", 968 lastport ? "," : "", port); 969 lastport = port; 970 } 971 if (newsize != 0) { 972 if (!nflag) 973 fputs(" -> ", stdout); 974 baddynamic = (u_int32_t *)newval; 975 lastport = 0; 976 for (port = 0; port < 65536; port++) 977 if (DP_ISSET(baddynamic, port)) { 978 (void)printf("%s%u", 979 lastport ? "," : "", port); 980 lastport = port; 981 } 982 } 983 (void)putchar('\n'); 984 } 985 return; 986 } 987 if (special & LONGARRAY) { 988 long *la = (long *)buf; 989 if (!nflag) 990 printf("%s%s", string, equ); 991 while (lal--) 992 printf("%ld%s", *la++, lal? ",":""); 993 putchar('\n'); 994 return; 995 } 996 if (special & SENSORS) { 997 struct sensor *s = (struct sensor *)buf; 998 999 if (size > 0 && (s->flags & SENSOR_FINVALID) == 0) { 1000 if (!nflag) 1001 printf("%s%s", string, equ); 1002 print_sensor(s); 1003 printf("\n"); 1004 } 1005 return; 1006 } 1007 switch (type) { 1008 case CTLTYPE_INT: 1009 if (newsize == 0) { 1010 if (!nflag) 1011 (void)printf("%s%s", string, equ); 1012 if (special & HEX) 1013 (void)printf("0x%x\n", *(int *)buf); 1014 else 1015 (void)printf("%d\n", *(int *)buf); 1016 } else { 1017 if (!qflag) { 1018 if (!nflag) 1019 (void)printf("%s: %d -> ", string, 1020 *(int *)buf); 1021 if (special & HEX) 1022 (void)printf("0x%x\n", *(int *)newval); 1023 else 1024 (void)printf("%d\n", *(int *)newval); 1025 } 1026 } 1027 return; 1028 1029 case CTLTYPE_STRING: 1030 if (newval == NULL) { 1031 if (!nflag) 1032 (void)printf("%s%s", string, equ); 1033 if (special & HEX) { 1034 size_t i; 1035 for (i = 0; i < size; i++) { 1036 (void)printf("%02x", 1037 (unsigned char)buf[i]); 1038 } 1039 (void)printf("\n"); 1040 } else 1041 (void)puts(buf); 1042 } else if (!qflag) { 1043 if (!nflag) { 1044 (void)printf("%s: ", string); 1045 if (special & HEX) { 1046 size_t i; 1047 for (i = 0; i < size; i++) { 1048 (void)printf("%02x", 1049 (unsigned char)buf[i]); 1050 } 1051 } else 1052 (void)printf("%s", buf); 1053 1054 (void)printf(" -> "); 1055 } 1056 (void)puts(cp); 1057 } 1058 return; 1059 1060 case CTLTYPE_QUAD: 1061 if (newsize == 0) { 1062 int64_t tmp; 1063 1064 memcpy(&tmp, buf, sizeof tmp); 1065 if (!nflag) 1066 (void)printf("%s%s", string, equ); 1067 (void)printf("%lld\n", tmp); 1068 } else { 1069 int64_t tmp; 1070 1071 memcpy(&tmp, buf, sizeof tmp); 1072 if (!qflag) { 1073 if (!nflag) 1074 (void)printf("%s: %lld -> ", 1075 string, tmp); 1076 memcpy(&tmp, newval, sizeof tmp); 1077 (void)printf("%lld\n", tmp); 1078 } 1079 } 1080 return; 1081 1082 case CTLTYPE_STRUCT: 1083 warnx("%s: unknown structure returned", string); 1084 return; 1085 1086 default: 1087 case CTLTYPE_NODE: 1088 warnx("%s: unknown type returned", string); 1089 return; 1090 } 1091} 1092 1093static void 1094parse_ports(char *portspec, int *port, int *high_port) 1095{ 1096 char *dash; 1097 const char *errstr; 1098 1099 if ((dash = strchr(portspec, '-')) != NULL) 1100 *dash++ = '\0'; 1101 *port = strtonum(portspec, 0, 65535, &errstr); 1102 if (errstr != NULL) 1103 errx(1, "port is %s: %s", errstr, portspec); 1104 if (dash != NULL) { 1105 *high_port = strtonum(dash, 0, 65535, &errstr); 1106 if (errstr != NULL) 1107 errx(1, "high port is %s: %s", errstr, dash); 1108 if (*high_port < *port) 1109 errx(1, "high port %d is lower than %d", 1110 *high_port, *port); 1111 } else 1112 *high_port = *port; 1113} 1114 1115void 1116parse_baddynamic(int mib[], size_t len, char *string, void **newvalp, 1117 size_t *newsizep, int flags, int nflag) 1118{ 1119 static u_int32_t newbaddynamic[DP_MAPSIZE]; 1120 int port, high_port, baddynamic_loaded = 0, full_list_set = 0; 1121 size_t size; 1122 char action, *cp; 1123 1124 while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) { 1125 if (*cp == '+' || *cp == '-') { 1126 if (full_list_set) 1127 errx(1, "cannot mix +/- with full list"); 1128 action = *cp++; 1129 if (!baddynamic_loaded) { 1130 size = sizeof(newbaddynamic); 1131 if (sysctl(mib, len, newbaddynamic, 1132 &size, 0, 0) == -1) { 1133 if (flags == 0) 1134 return; 1135 if (!nflag) 1136 printf("%s: ", string); 1137 puts("kernel does not contain bad " 1138 "dynamic port tables"); 1139 return; 1140 } 1141 baddynamic_loaded = 1; 1142 } 1143 parse_ports(cp, &port, &high_port); 1144 for (; port <= high_port; port++) { 1145 if (action == '+') 1146 DP_SET(newbaddynamic, port); 1147 else 1148 DP_CLR(newbaddynamic, port); 1149 } 1150 } else { 1151 if (baddynamic_loaded) 1152 errx(1, "cannot mix +/- with full list"); 1153 if (!full_list_set) { 1154 bzero(newbaddynamic, sizeof(newbaddynamic)); 1155 full_list_set = 1; 1156 } 1157 parse_ports(cp, &port, &high_port); 1158 for (; port <= high_port; port++) 1159 DP_SET(newbaddynamic, port); 1160 } 1161 } 1162 *newvalp = (void *)newbaddynamic; 1163 *newsizep = sizeof(newbaddynamic); 1164} 1165 1166/* 1167 * Initialize the set of debugging names 1168 */ 1169void 1170debuginit(void) 1171{ 1172 int mib[3], loc, i; 1173 size_t size; 1174 1175 if (secondlevel[CTL_DEBUG].list != 0) 1176 return; 1177 secondlevel[CTL_DEBUG].list = debugname; 1178 mib[0] = CTL_DEBUG; 1179 mib[2] = CTL_DEBUG_NAME; 1180 for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) { 1181 mib[1] = i; 1182 size = BUFSIZ - loc; 1183 if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1) 1184 continue; 1185 debugname[i].ctl_name = &names[loc]; 1186 debugname[i].ctl_type = CTLTYPE_INT; 1187 loc += size; 1188 } 1189 lastused = loc; 1190} 1191 1192struct ctlname vfsgennames[] = CTL_VFSGENCTL_NAMES; 1193struct ctlname ffsname[] = FFS_NAMES; 1194struct ctlname nfsname[] = FS_NFS_NAMES; 1195struct ctlname fusefsname[] = FUSEFS_NAMES; 1196struct list *vfsvars; 1197int *vfs_typenums; 1198 1199/* 1200 * Initialize the set of filesystem names 1201 */ 1202void 1203vfsinit(void) 1204{ 1205 int mib[4], maxtypenum, cnt, loc, size; 1206 struct vfsconf vfc; 1207 size_t buflen; 1208 1209 if (secondlevel[CTL_VFS].list != 0) 1210 return; 1211 mib[0] = CTL_VFS; 1212 mib[1] = VFS_GENERIC; 1213 mib[2] = VFS_MAXTYPENUM; 1214 buflen = 4; 1215 if (sysctl(mib, 3, &maxtypenum, &buflen, NULL, 0) < 0) 1216 return; 1217 /* 1218 * We need to do 0..maxtypenum so add one, and then we offset them 1219 * all by (another) one by inserting VFS_GENERIC entries at zero 1220 */ 1221 maxtypenum += 2; 1222 if ((vfs_typenums = calloc(maxtypenum, sizeof(int))) == NULL) 1223 return; 1224 if ((vfsvars = calloc(maxtypenum, sizeof(*vfsvars))) == NULL) { 1225 free(vfs_typenums); 1226 return; 1227 } 1228 if ((vfsname = calloc(maxtypenum, sizeof(*vfsname))) == NULL) { 1229 free(vfs_typenums); 1230 free(vfsvars); 1231 return; 1232 } 1233 mib[2] = VFS_CONF; 1234 buflen = sizeof vfc; 1235 for (loc = lastused, cnt = 1; cnt < maxtypenum; cnt++) { 1236 mib[3] = cnt - 1; 1237 if (sysctl(mib, 4, &vfc, &buflen, NULL, 0) < 0) { 1238 if (errno == EOPNOTSUPP) 1239 continue; 1240 warn("vfsinit"); 1241 free(vfsname); 1242 free(vfsvars); 1243 free(vfs_typenums); 1244 return; 1245 } 1246 if (!strcmp(vfc.vfc_name, MOUNT_FFS)) { 1247 vfsvars[cnt].list = ffsname; 1248 vfsvars[cnt].size = FFS_MAXID; 1249 } 1250 if (!strcmp(vfc.vfc_name, MOUNT_NFS)) { 1251 vfsvars[cnt].list = nfsname; 1252 vfsvars[cnt].size = NFS_MAXID; 1253 } 1254 if (!strcmp(vfc.vfc_name, MOUNT_FUSEFS)) { 1255 vfsvars[cnt].list = fusefsname; 1256 vfsvars[cnt].size = FUSEFS_MAXID; 1257 } 1258 vfs_typenums[cnt] = vfc.vfc_typenum; 1259 strlcat(&names[loc], vfc.vfc_name, sizeof names - loc); 1260 vfsname[cnt].ctl_name = &names[loc]; 1261 vfsname[cnt].ctl_type = CTLTYPE_NODE; 1262 size = strlen(vfc.vfc_name) + 1; 1263 loc += size; 1264 } 1265 lastused = loc; 1266 1267 vfsname[0].ctl_name = "mounts"; 1268 vfsname[0].ctl_type = CTLTYPE_NODE; 1269 vfsvars[0].list = vfsname + 1; 1270 vfsvars[0].size = maxtypenum - 1; 1271 1272 secondlevel[CTL_VFS].list = vfsname; 1273 secondlevel[CTL_VFS].size = maxtypenum; 1274 return; 1275} 1276 1277int 1278sysctl_vfsgen(char *string, char **bufpp, int mib[], int flags, int *typep) 1279{ 1280 int indx; 1281 size_t size; 1282 struct vfsconf vfc; 1283 1284 if (*bufpp == NULL) { 1285 listall(string, vfsvars); 1286 return (-1); 1287 } 1288 1289 if ((indx = findname(string, "third", bufpp, vfsvars)) == -1) 1290 return (-1); 1291 1292 mib[1] = VFS_GENERIC; 1293 mib[2] = VFS_CONF; 1294 mib[3] = indx; 1295 size = sizeof vfc; 1296 if (sysctl(mib, 4, &vfc, &size, NULL, 0) < 0) { 1297 if (errno != EOPNOTSUPP) 1298 warn("vfs print"); 1299 return -1; 1300 } 1301 if (flags == 0 && vfc.vfc_refcount == 0) 1302 return -1; 1303 if (!nflag) 1304 fprintf(stdout, "%s has %u mounted instance%s\n", 1305 string, vfc.vfc_refcount, 1306 vfc.vfc_refcount != 1 ? "s" : ""); 1307 else 1308 fprintf(stdout, "%u\n", vfc.vfc_refcount); 1309 1310 return -1; 1311} 1312 1313int 1314sysctl_vfs(char *string, char **bufpp, int mib[], int flags, int *typep) 1315{ 1316 struct list *lp = &vfsvars[mib[1]]; 1317 int indx; 1318 1319 if (lp->list == NULL) { 1320 if (flags) 1321 warnx("No variables defined for file system %s", string); 1322 return (-1); 1323 } 1324 if (*bufpp == NULL) { 1325 listall(string, lp); 1326 return (-1); 1327 } 1328 if ((indx = findname(string, "third", bufpp, lp)) == -1) 1329 return (-1); 1330 1331 mib[1] = vfs_typenums[mib[1]]; 1332 mib[2] = indx; 1333 *typep = lp->list[indx].ctl_type; 1334 return (3); 1335} 1336 1337struct ctlname posixname[] = CTL_FS_POSIX_NAMES; 1338struct list fslist = { posixname, FS_POSIX_MAXID }; 1339 1340/* 1341 * handle file system requests 1342 */ 1343int 1344sysctl_fs(char *string, char **bufpp, int mib[], int flags, int *typep) 1345{ 1346 int indx; 1347 1348 if (*bufpp == NULL) { 1349 listall(string, &fslist); 1350 return (-1); 1351 } 1352 if ((indx = findname(string, "third", bufpp, &fslist)) == -1) 1353 return (-1); 1354 mib[2] = indx; 1355 *typep = fslist.list[indx].ctl_type; 1356 return (3); 1357} 1358 1359#ifdef CPU_BIOS 1360struct ctlname biosname[] = CTL_BIOS_NAMES; 1361struct list bioslist = { biosname, BIOS_MAXID }; 1362 1363/* 1364 * handle BIOS requests 1365 */ 1366int 1367sysctl_bios(char *string, char **bufpp, int mib[], int flags, int *typep) 1368{ 1369 char *name; 1370 int indx; 1371 1372 if (*bufpp == NULL) { 1373 listall(string, &bioslist); 1374 return (-1); 1375 } 1376 if ((indx = findname(string, "third", bufpp, &bioslist)) == -1) 1377 return (-1); 1378 mib[2] = indx; 1379 if (indx == BIOS_DISKINFO) { 1380 const char *errstr; 1381 1382 if (*bufpp == NULL) { 1383 char name[BUFSIZ]; 1384 1385 /* scan all the bios devices */ 1386 for (indx = 0; indx < 256; indx++) { 1387 snprintf(name, sizeof(name), "%s.%u", 1388 string, indx); 1389 parse(name, 1); 1390 } 1391 return (-1); 1392 } 1393 if ((name = strsep(bufpp, ".")) == NULL) { 1394 warnx("%s: incomplete specification", string); 1395 return (-1); 1396 } 1397 mib[3] = strtonum(name, 0, INT_MAX, &errstr); 1398 if (errstr) { 1399 warnx("%s: %s", string, errstr); 1400 return (-1); 1401 } 1402 *typep = CTLTYPE_STRUCT; 1403 return (4); 1404 } else { 1405 *typep = bioslist.list[indx].ctl_type; 1406 return (3); 1407 } 1408} 1409#endif 1410 1411struct ctlname swpencname[] = CTL_SWPENC_NAMES; 1412struct list swpenclist = { swpencname, SWPENC_MAXID }; 1413 1414/* 1415 * handle swap encrypt requests 1416 */ 1417int 1418sysctl_swpenc(char *string, char **bufpp, int mib[], int flags, int *typep) 1419{ 1420 int indx; 1421 1422 if (*bufpp == NULL) { 1423 listall(string, &swpenclist); 1424 return (-1); 1425 } 1426 if ((indx = findname(string, "third", bufpp, &swpenclist)) == -1) 1427 return (-1); 1428 mib[2] = indx; 1429 *typep = swpenclist.list[indx].ctl_type; 1430 return (3); 1431} 1432 1433struct ctlname inetname[] = CTL_IPPROTO_NAMES; 1434struct ctlname ipname[] = IPCTL_NAMES; 1435struct ctlname icmpname[] = ICMPCTL_NAMES; 1436struct ctlname igmpname[] = IGMPCTL_NAMES; 1437struct ctlname ipipname[] = IPIPCTL_NAMES; 1438struct ctlname tcpname[] = TCPCTL_NAMES; 1439struct ctlname udpname[] = UDPCTL_NAMES; 1440struct ctlname espname[] = ESPCTL_NAMES; 1441struct ctlname ahname[] = AHCTL_NAMES; 1442struct ctlname etheripname[] = ETHERIPCTL_NAMES; 1443struct ctlname grename[] = GRECTL_NAMES; 1444struct ctlname mobileipname[] = MOBILEIPCTL_NAMES; 1445struct ctlname ipcompname[] = IPCOMPCTL_NAMES; 1446struct ctlname carpname[] = CARPCTL_NAMES; 1447struct ctlname pfsyncname[] = PFSYNCCTL_NAMES; 1448struct ctlname divertname[] = DIVERTCTL_NAMES; 1449struct ctlname bpfname[] = CTL_NET_BPF_NAMES; 1450struct ctlname ifqname[] = CTL_IFQ_NAMES; 1451struct ctlname pipexname[] = PIPEXCTL_NAMES; 1452struct list inetlist = { inetname, IPPROTO_MAXID }; 1453struct list inetvars[] = { 1454 { ipname, IPCTL_MAXID }, /* ip */ 1455 { icmpname, ICMPCTL_MAXID }, /* icmp */ 1456 { igmpname, IGMPCTL_MAXID }, /* igmp */ 1457 { 0, 0 }, /* ggmp */ 1458 { ipipname, IPIPCTL_MAXID }, /* ipencap */ 1459 { 0, 0 }, 1460 { tcpname, TCPCTL_MAXID }, /* tcp */ 1461 { 0, 0 }, 1462 { 0, 0 }, /* egp */ 1463 { 0, 0 }, 1464 { 0, 0 }, 1465 { 0, 0 }, 1466 { 0, 0 }, /* pup */ 1467 { 0, 0 }, 1468 { 0, 0 }, 1469 { 0, 0 }, 1470 { 0, 0 }, 1471 { udpname, UDPCTL_MAXID }, /* udp */ 1472 { 0, 0 }, 1473 { 0, 0 }, 1474 { 0, 0 }, 1475 { 0, 0 }, 1476 { 0, 0 }, 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 { grename, GRECTL_MAXID }, /* gre */ 1502 { 0, 0 }, 1503 { 0, 0 }, 1504 { espname, ESPCTL_MAXID }, /* esp */ 1505 { ahname, AHCTL_MAXID }, /* ah */ 1506 { 0, 0 }, 1507 { 0, 0 }, 1508 { 0, 0 }, 1509 { mobileipname, MOBILEIPCTL_MAXID }, /* mobileip */ 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 { etheripname, ETHERIPCTL_MAXID }, 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 { ipcompname, IPCOMPCTL_MAXID }, 1563 { 0, 0 }, 1564 { 0, 0 }, 1565 { 0, 0 }, 1566 { carpname, CARPCTL_MAXID }, 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 { 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 { pfsyncname, PFSYNCCTL_MAXID }, 1704 { 0, 0 }, 1705 { 0, 0 }, 1706 { 0, 0 }, 1707 { 0, 0 }, 1708 { 0, 0 }, 1709 { 0, 0 }, 1710 { 0, 0 }, 1711 { 0, 0 }, 1712 { divertname, DIVERTCTL_MAXID }, 1713}; 1714struct list bpflist = { bpfname, NET_BPF_MAXID }; 1715struct list ifqlist = { ifqname, IFQCTL_MAXID }; 1716struct list pipexlist = { pipexname, PIPEXCTL_MAXID }; 1717 1718struct list kernmalloclist = { kernmallocname, KERN_MALLOC_MAXID }; 1719struct list forkstatlist = { forkstatname, KERN_FORKSTAT_MAXID }; 1720struct list nchstatslist = { nchstatsname, KERN_NCHSTATS_MAXID }; 1721struct list ttylist = { ttysname, KERN_TTY_MAXID }; 1722struct list semlist = { semname, KERN_SEMINFO_MAXID }; 1723struct list shmlist = { shmname, KERN_SHMINFO_MAXID }; 1724struct list watchdoglist = { watchdogname, KERN_WATCHDOG_MAXID }; 1725struct list tclist = { tcname, KERN_TIMECOUNTER_MAXID }; 1726struct list audiolist = { audioname, KERN_AUDIO_MAXID }; 1727struct list witnesslist = { witnessname, KERN_WITNESS_MAXID }; 1728 1729/* 1730 * handle vfs namei cache statistics 1731 */ 1732int 1733sysctl_nchstats(char *string, char **bufpp, int mib[], int flags, int *typep) 1734{ 1735 static struct nchstats nch; 1736 int indx; 1737 size_t size; 1738 static int keepvalue = 0; 1739 1740 if (*bufpp == NULL) { 1741 bzero(&nch, sizeof(struct nchstats)); 1742 listall(string, &nchstatslist); 1743 return (-1); 1744 } 1745 if ((indx = findname(string, "third", bufpp, &nchstatslist)) == -1) 1746 return (-1); 1747 mib[2] = indx; 1748 if (*bufpp != NULL) { 1749 warnx("fourth level name in %s is invalid", string); 1750 return (-1); 1751 } 1752 if (keepvalue == 0) { 1753 size = sizeof(struct nchstats); 1754 if (sysctl(mib, 2, &nch, &size, NULL, 0) < 0) 1755 return (-1); 1756 keepvalue = 1; 1757 } 1758 if (!nflag) 1759 (void)printf("%s%s", string, equ); 1760 switch (indx) { 1761 case KERN_NCHSTATS_GOODHITS: 1762 (void)printf("%llu\n", nch.ncs_goodhits); 1763 break; 1764 case KERN_NCHSTATS_NEGHITS: 1765 (void)printf("%llu\n", nch.ncs_neghits); 1766 break; 1767 case KERN_NCHSTATS_BADHITS: 1768 (void)printf("%llu\n", nch.ncs_badhits); 1769 break; 1770 case KERN_NCHSTATS_FALSEHITS: 1771 (void)printf("%llu\n", nch.ncs_falsehits); 1772 break; 1773 case KERN_NCHSTATS_MISS: 1774 (void)printf("%llu\n", nch.ncs_miss); 1775 break; 1776 case KERN_NCHSTATS_LONG: 1777 (void)printf("%llu\n", nch.ncs_long); 1778 break; 1779 case KERN_NCHSTATS_PASS2: 1780 (void)printf("%llu\n", nch.ncs_pass2); 1781 break; 1782 case KERN_NCHSTATS_2PASSES: 1783 (void)printf("%llu\n", nch.ncs_2passes); 1784 break; 1785 case KERN_NCHSTATS_REVHITS: 1786 (void)printf("%llu\n", nch.ncs_revhits); 1787 break; 1788 case KERN_NCHSTATS_REVMISS: 1789 (void)printf("%llu\n", nch.ncs_revmiss); 1790 break; 1791 case KERN_NCHSTATS_DOTHITS: 1792 (void)printf("%llu\n", nch.ncs_dothits); 1793 break; 1794 case KERN_NCHSTATS_DOTDOTHITS: 1795 (void)printf("%llu\n", nch.ncs_dotdothits); 1796 break; 1797 } 1798 return (-1); 1799} 1800 1801/* 1802 * handle tty statistics 1803 */ 1804int 1805sysctl_tty(char *string, char **bufpp, int mib[], int flags, int *typep) 1806{ 1807 int indx; 1808 1809 if (*bufpp == NULL) { 1810 listall(string, &ttylist); 1811 return (-1); 1812 } 1813 if ((indx = findname(string, "third", bufpp, &ttylist)) == -1) 1814 return (-1); 1815 mib[2] = indx; 1816 1817 if ((*typep = ttylist.list[indx].ctl_type) == CTLTYPE_STRUCT) { 1818 if (flags) 1819 warnx("use pstat -t to view %s information", 1820 string); 1821 return (-1); 1822 } 1823 return (3); 1824} 1825 1826/* 1827 * handle fork statistics 1828 */ 1829int 1830sysctl_forkstat(char *string, char **bufpp, int mib[], int flags, int *typep) 1831{ 1832 static struct forkstat fks; 1833 static int keepvalue = 0; 1834 int indx; 1835 size_t size; 1836 1837 if (*bufpp == NULL) { 1838 bzero(&fks, sizeof(struct forkstat)); 1839 listall(string, &forkstatlist); 1840 return (-1); 1841 } 1842 if ((indx = findname(string, "third", bufpp, &forkstatlist)) == -1) 1843 return (-1); 1844 if (*bufpp != NULL) { 1845 warnx("fourth level name in %s is invalid", string); 1846 return (-1); 1847 } 1848 if (keepvalue == 0) { 1849 size = sizeof(struct forkstat); 1850 if (sysctl(mib, 2, &fks, &size, NULL, 0) < 0) 1851 return (-1); 1852 keepvalue = 1; 1853 } 1854 if (!nflag) 1855 (void)printf("%s%s", string, equ); 1856 switch (indx) { 1857 case KERN_FORKSTAT_FORK: 1858 (void)printf("%u\n", fks.cntfork); 1859 break; 1860 case KERN_FORKSTAT_VFORK: 1861 (void)printf("%u\n", fks.cntvfork); 1862 break; 1863 case KERN_FORKSTAT_TFORK: 1864 (void)printf("%u\n", fks.cnttfork); 1865 break; 1866 case KERN_FORKSTAT_KTHREAD: 1867 (void)printf("%u\n", fks.cntkthread); 1868 break; 1869 case KERN_FORKSTAT_SIZFORK: 1870 (void)printf("%llu\n", fks.sizfork); 1871 break; 1872 case KERN_FORKSTAT_SIZVFORK: 1873 (void)printf("%llu\n", fks.sizvfork); 1874 break; 1875 case KERN_FORKSTAT_SIZTFORK: 1876 (void)printf("%llu\n", fks.siztfork); 1877 break; 1878 case KERN_FORKSTAT_SIZKTHREAD: 1879 (void)printf("%llu\n", fks.sizkthread); 1880 break; 1881 } 1882 return (-1); 1883} 1884 1885/* 1886 * handle malloc statistics 1887 */ 1888int 1889sysctl_malloc(char *string, char **bufpp, int mib[], int flags, int *typep) 1890{ 1891 int indx, stor, i; 1892 char *name, bufp[SYSCTL_BUFSIZ], *buf, *ptr; 1893 const char *errstr; 1894 struct list lp; 1895 size_t size; 1896 1897 if (*bufpp == NULL) { 1898 listall(string, &kernmalloclist); 1899 return (-1); 1900 } 1901 if ((indx = findname(string, "third", bufpp, &kernmalloclist)) == -1) 1902 return (-1); 1903 mib[2] = indx; 1904 if (mib[2] == KERN_MALLOC_BUCKET) { 1905 if ((name = strsep(bufpp, ".")) == NULL) { 1906 size = SYSCTL_BUFSIZ; 1907 stor = mib[2]; 1908 mib[2] = KERN_MALLOC_BUCKETS; 1909 buf = bufp; 1910 if (sysctl(mib, 3, buf, &size, NULL, 0) < 0) 1911 return (-1); 1912 mib[2] = stor; 1913 for (stor = 0, i = 0; i < size; i++) 1914 if (buf[i] == ',') 1915 stor++; 1916 lp.list = calloc(stor + 2, sizeof(struct ctlname)); 1917 if (lp.list == NULL) 1918 return (-1); 1919 lp.size = stor + 2; 1920 for (i = 1; (ptr = strsep(&buf, ",")) != NULL; i++) { 1921 lp.list[i].ctl_name = ptr; 1922 lp.list[i].ctl_type = CTLTYPE_STRUCT; 1923 } 1924 listall(string, &lp); 1925 free(lp.list); 1926 return (-1); 1927 } 1928 mib[3] = strtonum(name, 0, INT_MAX, &errstr); 1929 if (errstr) 1930 return -1; 1931 return (4); 1932 } else if (mib[2] == KERN_MALLOC_BUCKETS) { 1933 *typep = CTLTYPE_STRING; 1934 return (3); 1935 } else if (mib[2] == KERN_MALLOC_KMEMSTATS) { 1936 size = SYSCTL_BUFSIZ; 1937 stor = mib[2]; 1938 mib[2] = KERN_MALLOC_KMEMNAMES; 1939 buf = bufp; 1940 if (sysctl(mib, 3, buf, &size, NULL, 0) < 0) 1941 return (-1); 1942 mib[2] = stor; 1943 if ((name = strsep(bufpp, ".")) == NULL) { 1944 for (stor = 0, i = 0; i < size; i++) 1945 if (buf[i] == ',') 1946 stor++; 1947 lp.list = calloc(stor + 2, sizeof(struct ctlname)); 1948 if (lp.list == NULL) 1949 return (-1); 1950 lp.size = stor + 2; 1951 for (i = 1; (ptr = strsep(&buf, ",")) != NULL; i++) { 1952 if (ptr[0] == '\0') { 1953 i--; 1954 continue; 1955 } 1956 lp.list[i].ctl_name = ptr; 1957 lp.list[i].ctl_type = CTLTYPE_STRUCT; 1958 } 1959 listall(string, &lp); 1960 free(lp.list); 1961 return (-1); 1962 } 1963 ptr = strstr(buf, name); 1964 tryagain: 1965 if (ptr == NULL) { 1966 warnx("fourth level name %s in %s is invalid", name, 1967 string); 1968 return (-1); 1969 } 1970 if ((*(ptr + strlen(name)) != ',') && 1971 (*(ptr + strlen(name)) != '\0')) { 1972 ptr = strstr(ptr + 1, name); /* retry */ 1973 goto tryagain; 1974 } 1975 if ((ptr != buf) && (*(ptr - 1) != ',')) { 1976 ptr = strstr(ptr + 1, name); /* retry */ 1977 goto tryagain; 1978 } 1979 for (i = 0, stor = 0; buf + i < ptr; i++) 1980 if (buf[i] == ',') 1981 stor++; 1982 mib[3] = stor; 1983 return (4); 1984 } else if (mib[2] == KERN_MALLOC_KMEMNAMES) { 1985 *typep = CTLTYPE_STRING; 1986 return (3); 1987 } 1988 return (-1); 1989} 1990 1991#ifdef CPU_CHIPSET 1992/* 1993 * handle machdep.chipset requests 1994 */ 1995struct ctlname chipsetname[] = CTL_CHIPSET_NAMES; 1996struct list chipsetlist = { chipsetname, CPU_CHIPSET_MAXID }; 1997 1998int 1999sysctl_chipset(char *string, char **bufpp, int mib[], int flags, int *typep) 2000{ 2001 int indx, bwx; 2002 static void *q; 2003 size_t len; 2004 char *p; 2005 2006 if (*bufpp == NULL) { 2007 listall(string, &chipsetlist); 2008 return (-1); 2009 } 2010 if ((indx = findname(string, "third", bufpp, &chipsetlist)) == -1) 2011 return (-1); 2012 mib[2] = indx; 2013 if (!nflag) 2014 printf("%s%s", string, equ); 2015 switch(mib[2]) { 2016 case CPU_CHIPSET_MEM: 2017 case CPU_CHIPSET_DENSE: 2018 case CPU_CHIPSET_PORTS: 2019 case CPU_CHIPSET_HAE_MASK: 2020 len = sizeof(void *); 2021 if (sysctl(mib, 3, &q, &len, NULL, 0) < 0) 2022 goto done; 2023 printf("%p", q); 2024 break; 2025 case CPU_CHIPSET_BWX: 2026 len = sizeof(int); 2027 if (sysctl(mib, 3, &bwx, &len, NULL, 0) < 0) 2028 goto done; 2029 printf("%d", bwx); 2030 break; 2031 case CPU_CHIPSET_TYPE: 2032 if (sysctl(mib, 3, NULL, &len, NULL, 0) < 0) 2033 goto done; 2034 p = malloc(len + 1); 2035 if (p == NULL) 2036 goto done; 2037 if (sysctl(mib, 3, p, &len, NULL, 0) < 0) { 2038 free(p); 2039 goto done; 2040 } 2041 p[len] = '\0'; 2042 printf("%s", p); 2043 free(p); 2044 break; 2045 } 2046done: 2047 printf("\n"); 2048 return (-1); 2049} 2050#endif 2051/* 2052 * handle internet requests 2053 */ 2054int 2055sysctl_inet(char *string, char **bufpp, int mib[], int flags, int *typep) 2056{ 2057 struct list *lp; 2058 int indx; 2059 2060 if (*bufpp == NULL) { 2061 listall(string, &inetlist); 2062 return (-1); 2063 } 2064 if ((indx = findname(string, "third", bufpp, &inetlist)) == -1) 2065 return (-1); 2066 mib[2] = indx; 2067 if (indx < IPPROTO_MAXID && inetvars[indx].list != NULL) 2068 lp = &inetvars[indx]; 2069 else if (!flags) 2070 return (-1); 2071 else { 2072 warnx("%s: no variables defined for this protocol", string); 2073 return (-1); 2074 } 2075 if (*bufpp == NULL) { 2076 listall(string, lp); 2077 return (-1); 2078 } 2079 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 2080 return (-1); 2081 mib[3] = indx; 2082 *typep = lp->list[indx].ctl_type; 2083 if (*typep == CTLTYPE_NODE) { 2084 int tindx; 2085 2086 if (*bufpp == NULL) { 2087 listall(string, &ifqlist); 2088 return(-1); 2089 } 2090 lp = &ifqlist; 2091 if ((tindx = findname(string, "fifth", bufpp, lp)) == -1) 2092 return (-1); 2093 mib[4] = tindx; 2094 *typep = lp->list[tindx].ctl_type; 2095 return(5); 2096 } 2097 return (4); 2098} 2099 2100struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES; 2101struct ctlname ip6name[] = IPV6CTL_NAMES; 2102struct ctlname icmp6name[] = ICMPV6CTL_NAMES; 2103struct ctlname divert6name[] = DIVERT6CTL_NAMES; 2104struct list inet6list = { inet6name, IPV6PROTO_MAXID }; 2105struct list inet6vars[] = { 2106/*0*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2107 { 0, 0 }, 2108 { 0, 0 }, 2109 { 0, 0 }, 2110 { 0, 0 }, 2111 { 0, 0 }, 2112/*10*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2113 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2114/*20*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2115 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2116/*30*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2117 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2118/*40*/ { 0, 0 }, 2119 { ip6name, IPV6CTL_MAXID }, /* ipv6 */ 2120 { 0, 0 }, 2121 { 0, 0 }, 2122 { 0, 0 }, 2123 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2124/*50*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2125 { 0, 0 }, 2126 { 0, 0 }, 2127 { 0, 0 }, 2128 { icmp6name, ICMPV6CTL_MAXID }, /* icmp6 */ 2129 { 0, 0 }, 2130/*60*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2131 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2132/*70*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2133 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2134/*80*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2135 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2136/*90*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2137 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2138/*100*/ { 0, 0 }, 2139 { 0, 0 }, 2140 { 0, 0 }, 2141 { 0, 0 }, /* pim6 */ 2142 { 0, 0 }, 2143 { 0, 0 }, 2144 { 0, 0 }, 2145 { 0, 0 }, 2146 { 0, 0 }, 2147 { 0, 0 }, 2148/*110*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2149 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2150/*120*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2151 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2152/*130*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2153 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2154/*140*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2155 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2156/*150*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2157 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2158/*160*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2159 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2160/*170*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2161 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2162/*180*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2163 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2164/*190*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2165 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2166/*200*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2167 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2168/*210*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2169 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2170/*220*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2171 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2172/*230*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2173 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2174/*240*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2175 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, 2176/*250*/ { 0, 0 }, 2177 { 0, 0 }, 2178 { 0, 0 }, 2179 { 0, 0 }, 2180 { 0, 0 }, 2181 { 0, 0 }, 2182 { 0, 0 }, 2183 { 0, 0 }, 2184 { divert6name, DIVERT6CTL_MAXID }, 2185}; 2186 2187/* 2188 * handle internet6 requests 2189 */ 2190int 2191sysctl_inet6(char *string, char **bufpp, int mib[], int flags, int *typep) 2192{ 2193 struct list *lp; 2194 int indx; 2195 2196 if (*bufpp == NULL) { 2197 listall(string, &inet6list); 2198 return (-1); 2199 } 2200 if ((indx = findname(string, "third", bufpp, &inet6list)) == -1) 2201 return (-1); 2202 mib[2] = indx; 2203 if (indx < IPV6PROTO_MAXID && inet6vars[indx].list != NULL) 2204 lp = &inet6vars[indx]; 2205 else if (!flags) 2206 return (-1); 2207 else { 2208 warnx("%s: no variables defined for this protocol", string); 2209 return (-1); 2210 } 2211 if (*bufpp == NULL) { 2212 listall(string, lp); 2213 return (-1); 2214 } 2215 if ((indx = findname(string, "fourth", bufpp, lp)) == -1) 2216 return (-1); 2217 mib[3] = indx; 2218 *typep = lp->list[indx].ctl_type; 2219 if (*typep == CTLTYPE_NODE) { 2220 int tindx; 2221 2222 if (*bufpp == NULL) { 2223 listall(string, &ifqlist); 2224 return(-1); 2225 } 2226 lp = &ifqlist; 2227 if ((tindx = findname(string, "fifth", bufpp, lp)) == -1) 2228 return (-1); 2229 mib[4] = tindx; 2230 *typep = lp->list[tindx].ctl_type; 2231 return(5); 2232 } 2233 return (4); 2234} 2235 2236/* handle bpf requests */ 2237int 2238sysctl_bpf(char *string, char **bufpp, int mib[], int flags, int *typep) 2239{ 2240 int indx; 2241 2242 if (*bufpp == NULL) { 2243 listall(string, &bpflist); 2244 return (-1); 2245 } 2246 if ((indx = findname(string, "third", bufpp, &bpflist)) == -1) 2247 return (-1); 2248 mib[2] = indx; 2249 *typep = CTLTYPE_INT; 2250 return (3); 2251} 2252 2253struct ctlname mplsname[] = MPLSCTL_NAMES; 2254struct list mplslist = { mplsname, MPLSCTL_MAXID }; 2255 2256/* handle MPLS requests */ 2257int 2258sysctl_mpls(char *string, char **bufpp, int mib[], int flags, int *typep) 2259{ 2260 struct list *lp; 2261 int indx; 2262 2263 if (*bufpp == NULL) { 2264 listall(string, &mplslist); 2265 return (-1); 2266 } 2267 if ((indx = findname(string, "third", bufpp, &mplslist)) == -1) 2268 return (-1); 2269 mib[2] = indx; 2270 *typep = mplslist.list[indx].ctl_type; 2271 if (*typep == CTLTYPE_NODE) { 2272 int tindx; 2273 2274 if (*bufpp == NULL) { 2275 listall(string, &ifqlist); 2276 return(-1); 2277 } 2278 lp = &ifqlist; 2279 if ((tindx = findname(string, "fourth", bufpp, lp)) == -1) 2280 return (-1); 2281 mib[3] = tindx; 2282 *typep = lp->list[tindx].ctl_type; 2283 return(4); 2284 } 2285 return (3); 2286} 2287 2288/* handle PIPEX requests */ 2289int 2290sysctl_pipex(char *string, char **bufpp, int mib[], int flags, int *typep) 2291{ 2292 struct list *lp; 2293 int indx; 2294 2295 if (*bufpp == NULL) { 2296 listall(string, &pipexlist); 2297 return (-1); 2298 } 2299 if ((indx = findname(string, "third", bufpp, &pipexlist)) == -1) 2300 return (-1); 2301 mib[2] = indx; 2302 *typep = pipexlist.list[indx].ctl_type; 2303 if (*typep == CTLTYPE_NODE) { 2304 int tindx; 2305 2306 if (*bufpp == NULL) { 2307 listall(string, &ifqlist); 2308 return(-1); 2309 } 2310 lp = &ifqlist; 2311 if ((tindx = findname(string, "fourth", bufpp, lp)) == -1) 2312 return (-1); 2313 mib[3] = tindx; 2314 *typep = lp->list[tindx].ctl_type; 2315 return(4); 2316 } 2317 return (3); 2318} 2319 2320/* 2321 * Handle SysV semaphore info requests 2322 */ 2323int 2324sysctl_seminfo(char *string, char **bufpp, int mib[], int flags, int *typep) 2325{ 2326 int indx; 2327 2328 if (*bufpp == NULL) { 2329 listall(string, &semlist); 2330 return (-1); 2331 } 2332 if ((indx = findname(string, "third", bufpp, &semlist)) == -1) 2333 return (-1); 2334 mib[2] = indx; 2335 *typep = CTLTYPE_INT; 2336 return (3); 2337} 2338 2339/* 2340 * Handle SysV shared memory info requests 2341 */ 2342int 2343sysctl_shminfo(char *string, char **bufpp, int mib[], int flags, int *typep) 2344{ 2345 int indx; 2346 2347 if (*bufpp == NULL) { 2348 listall(string, &shmlist); 2349 return (-1); 2350 } 2351 if ((indx = findname(string, "third", bufpp, &shmlist)) == -1) 2352 return (-1); 2353 mib[2] = indx; 2354 *typep = CTLTYPE_INT; 2355 return (3); 2356} 2357 2358/* 2359 * Handle watchdog support 2360 */ 2361int 2362sysctl_watchdog(char *string, char **bufpp, int mib[], int flags, 2363 int *typep) 2364{ 2365 int indx; 2366 2367 if (*bufpp == NULL) { 2368 listall(string, &watchdoglist); 2369 return (-1); 2370 } 2371 if ((indx = findname(string, "third", bufpp, &watchdoglist)) == -1) 2372 return (-1); 2373 mib[2] = indx; 2374 *typep = watchdoglist.list[indx].ctl_type; 2375 return (3); 2376} 2377 2378/* 2379 * Handle timecounter support 2380 */ 2381int 2382sysctl_tc(char *string, char **bufpp, int mib[], int flags, 2383 int *typep) 2384{ 2385 int indx; 2386 2387 if (*bufpp == NULL) { 2388 listall(string, &tclist); 2389 return (-1); 2390 } 2391 if ((indx = findname(string, "third", bufpp, &tclist)) == -1) 2392 return (-1); 2393 mib[2] = indx; 2394 *typep = tclist.list[indx].ctl_type; 2395 return (3); 2396} 2397 2398/* 2399 * Handle hardware monitoring sensors support 2400 */ 2401int 2402sysctl_sensors(char *string, char **bufpp, int mib[], int flags, int *typep) 2403{ 2404 char *devname, *typename; 2405 int dev, numt, i; 2406 enum sensor_type type; 2407 struct sensordev snsrdev; 2408 size_t sdlen = sizeof(snsrdev); 2409 2410 if (*bufpp == NULL) { 2411 char buf[SYSCTL_BUFSIZ]; 2412 2413 /* scan all sensor devices */ 2414 for (dev = 0; ; dev++) { 2415 mib[2] = dev; 2416 if (sysctl(mib, 3, &snsrdev, &sdlen, NULL, 0) == -1) { 2417 if (errno == ENXIO) 2418 continue; 2419 if (errno == ENOENT) 2420 break; 2421 warn("sensors dev %d", dev); 2422 return (-1); 2423 } 2424 snprintf(buf, sizeof(buf), "%s.%s", 2425 string, snsrdev.xname); 2426 print_sensordev(buf, mib, 3, &snsrdev); 2427 } 2428 return (-1); 2429 } 2430 2431 /* 2432 * If we get this far, it means that some arguments were 2433 * provided below hw.sensors tree. 2434 * The first branch of hw.sensors tree is the device name. 2435 */ 2436 if ((devname = strsep(bufpp, ".")) == NULL) { 2437 warnx("%s: incomplete specification", string); 2438 return (-1); 2439 } 2440 /* convert sensor device string to an integer */ 2441 for (dev = 0; ; dev++) { 2442 mib[2] = dev; 2443 if (sysctl(mib, 3, &snsrdev, &sdlen, NULL, 0) == -1) { 2444 if (errno == ENXIO) 2445 continue; 2446 if (errno == ENOENT) 2447 break; 2448 warn("sensors dev %d", dev); 2449 return (-1); 2450 } 2451 if (strcmp(devname, snsrdev.xname) == 0) 2452 break; 2453 } 2454 if (strcmp(devname, snsrdev.xname) != 0) { 2455 warnx("%s: sensor device not found: %s", string, devname); 2456 return (-1); 2457 } 2458 if (*bufpp == NULL) { 2459 /* only device name was provided -- let's print all sensors 2460 * that are attached to the specified device 2461 */ 2462 print_sensordev(string, mib, 3, &snsrdev); 2463 return (-1); 2464 } 2465 2466 /* 2467 * At this point we have identified the sensor device, 2468 * now let's go further and identify sensor type. 2469 */ 2470 if ((typename = strsep(bufpp, ".")) == NULL) { 2471 warnx("%s: incomplete specification", string); 2472 return (-1); 2473 } 2474 numt = -1; 2475 for (i = 0; typename[i] != '\0'; i++) 2476 if (isdigit((unsigned char)typename[i])) { 2477 const char *errstr; 2478 2479 numt = strtonum(&typename[i], 0, INT_MAX, &errstr); 2480 if (errstr) { 2481 warnx("%s: %s", string, errstr); 2482 return (-1); 2483 } 2484 typename[i] = '\0'; 2485 break; 2486 } 2487 for (type = 0; type < SENSOR_MAX_TYPES; type++) 2488 if (strcmp(typename, sensor_type_s[type]) == 0) 2489 break; 2490 if (type == SENSOR_MAX_TYPES) { 2491 warnx("%s: sensor type not recognised: %s", string, typename); 2492 return (-1); 2493 } 2494 mib[3] = type; 2495 2496 /* 2497 * If no integer was provided after sensor_type, let's 2498 * print all sensors of the specified type. 2499 */ 2500 if (numt == -1) { 2501 print_sensordev(string, mib, 4, &snsrdev); 2502 return (-1); 2503 } 2504 2505 /* 2506 * At this point we know that we have received a direct request 2507 * via command-line for a specific sensor. Let's have the parse() 2508 * function deal with it further, and report any errors if such 2509 * sensor node does not exist. 2510 */ 2511 mib[4] = numt; 2512 *typep = CTLTYPE_STRUCT; 2513 return (5); 2514} 2515 2516/* 2517 * Print sensors from the specified device. 2518 */ 2519 2520void 2521print_sensordev(char *string, int mib[], u_int mlen, struct sensordev *snsrdev) 2522{ 2523 char buf[SYSCTL_BUFSIZ]; 2524 enum sensor_type type; 2525 2526 if (mlen == 3) { 2527 for (type = 0; type < SENSOR_MAX_TYPES; type++) { 2528 mib[3] = type; 2529 snprintf(buf, sizeof(buf), "%s.%s", 2530 string, sensor_type_s[type]); 2531 print_sensordev(buf, mib, mlen+1, snsrdev); 2532 } 2533 return; 2534 } 2535 2536 if (mlen == 4) { 2537 int numt; 2538 2539 type = mib[3]; 2540 for (numt = 0; numt < snsrdev->maxnumt[type]; numt++) { 2541 mib[4] = numt; 2542 snprintf(buf, sizeof(buf), "%s%u", string, numt); 2543 print_sensordev(buf, mib, mlen+1, snsrdev); 2544 } 2545 return; 2546 } 2547 2548 if (mlen == 5) { 2549 struct sensor snsr; 2550 size_t slen = sizeof(snsr); 2551 2552 /* this function is only printing sensors in bulk, so we 2553 * do not return any error messages if the requested sensor 2554 * is not found by sysctl(3) 2555 */ 2556 if (sysctl(mib, 5, &snsr, &slen, NULL, 0) == -1) 2557 return; 2558 2559 if (slen > 0 && (snsr.flags & SENSOR_FINVALID) == 0) { 2560 if (!nflag) 2561 printf("%s%s", string, equ); 2562 print_sensor(&snsr); 2563 printf("\n"); 2564 } 2565 return; 2566 } 2567} 2568 2569void 2570print_sensor(struct sensor *s) 2571{ 2572 const char *name; 2573 2574 if (s->flags & SENSOR_FUNKNOWN) 2575 printf("unknown"); 2576 else { 2577 switch (s->type) { 2578 case SENSOR_TEMP: 2579 printf("%.2f degC", 2580 (s->value - 273150000) / 1000000.0); 2581 break; 2582 case SENSOR_FANRPM: 2583 printf("%lld RPM", s->value); 2584 break; 2585 case SENSOR_VOLTS_DC: 2586 printf("%.2f VDC", s->value / 1000000.0); 2587 break; 2588 case SENSOR_VOLTS_AC: 2589 printf("%.2f VAC", s->value / 1000000.0); 2590 break; 2591 case SENSOR_OHMS: 2592 printf("%lld ohm", s->value); 2593 break; 2594 case SENSOR_WATTS: 2595 printf("%.2f W", s->value / 1000000.0); 2596 break; 2597 case SENSOR_AMPS: 2598 printf("%.2f A", s->value / 1000000.0); 2599 break; 2600 case SENSOR_WATTHOUR: 2601 printf("%.2f Wh", s->value / 1000000.0); 2602 break; 2603 case SENSOR_AMPHOUR: 2604 printf("%.2f Ah", s->value / 1000000.0); 2605 break; 2606 case SENSOR_INDICATOR: 2607 printf("%s", s->value ? "On" : "Off"); 2608 break; 2609 case SENSOR_INTEGER: 2610 printf("%lld", s->value); 2611 break; 2612 case SENSOR_PERCENT: 2613 printf("%.2f%%", s->value / 1000.0); 2614 break; 2615 case SENSOR_LUX: 2616 printf("%.2f lx", s->value / 1000000.0); 2617 break; 2618 case SENSOR_DRIVE: 2619 switch (s->value) { 2620 case SENSOR_DRIVE_EMPTY: 2621 name = "empty"; 2622 break; 2623 case SENSOR_DRIVE_READY: 2624 name = "ready"; 2625 break; 2626 case SENSOR_DRIVE_POWERUP: 2627 name = "powering up"; 2628 break; 2629 case SENSOR_DRIVE_ONLINE: 2630 name = "online"; 2631 break; 2632 case SENSOR_DRIVE_IDLE: 2633 name = "idle"; 2634 break; 2635 case SENSOR_DRIVE_ACTIVE: 2636 name = "active"; 2637 break; 2638 case SENSOR_DRIVE_REBUILD: 2639 name = "rebuilding"; 2640 break; 2641 case SENSOR_DRIVE_POWERDOWN: 2642 name = "powering down"; 2643 break; 2644 case SENSOR_DRIVE_FAIL: 2645 name = "failed"; 2646 break; 2647 case SENSOR_DRIVE_PFAIL: 2648 name = "degraded"; 2649 break; 2650 default: 2651 name = "unknown"; 2652 break; 2653 } 2654 printf("%s", name); 2655 break; 2656 case SENSOR_TIMEDELTA: 2657 printf("%.6f secs", s->value / 1000000000.0); 2658 break; 2659 case SENSOR_HUMIDITY: 2660 printf("%.2f%%", s->value / 1000.0); 2661 break; 2662 case SENSOR_FREQ: 2663 printf("%.2f Hz", s->value / 1000000.0); 2664 break; 2665 case SENSOR_ANGLE: 2666 printf("%3.4f degrees", s->value / 1000000.0); 2667 break; 2668 case SENSOR_DISTANCE: 2669 printf("%.3f m", s->value / 1000000.0); 2670 break; 2671 case SENSOR_PRESSURE: 2672 printf("%.2f Pa", s->value / 1000.0); 2673 break; 2674 case SENSOR_ACCEL: 2675 printf("%2.4f m/s^2", s->value / 1000000.0); 2676 break; 2677 case SENSOR_VELOCITY: 2678 printf("%4.3f m/s", s->value / 1000000.0); 2679 break; 2680 default: 2681 printf("unknown"); 2682 } 2683 } 2684 2685 if (s->desc[0] != '\0') 2686 printf(" (%s)", s->desc); 2687 2688 switch (s->status) { 2689 case SENSOR_S_UNSPEC: 2690 break; 2691 case SENSOR_S_OK: 2692 printf(", OK"); 2693 break; 2694 case SENSOR_S_WARN: 2695 printf(", WARNING"); 2696 break; 2697 case SENSOR_S_CRIT: 2698 printf(", CRITICAL"); 2699 break; 2700 case SENSOR_S_UNKNOWN: 2701 printf(", UNKNOWN"); 2702 break; 2703 } 2704 2705 if (s->tv.tv_sec) { 2706 time_t t = s->tv.tv_sec; 2707 char ct[26]; 2708 2709 ctime_r(&t, ct); 2710 ct[19] = '\0'; 2711 printf(", %s.%03ld", ct, s->tv.tv_usec / 1000); 2712 } 2713} 2714 2715/* 2716 * Handle audio support 2717 */ 2718int 2719sysctl_audio(char *string, char **bufpp, int mib[], int flags, int *typep) 2720{ 2721 int indx; 2722 2723 if (*bufpp == NULL) { 2724 listall(string, &audiolist); 2725 return (-1); 2726 } 2727 if ((indx = findname(string, "third", bufpp, &audiolist)) == -1) 2728 return (-1); 2729 mib[2] = indx; 2730 *typep = audiolist.list[indx].ctl_type; 2731 return (3); 2732} 2733 2734/* 2735 * Handle witness support 2736 */ 2737int 2738sysctl_witness(char *string, char **bufpp, int mib[], int flags, int *typep) 2739{ 2740 int indx; 2741 2742 if (*bufpp == NULL) { 2743 listall(string, &witnesslist); 2744 return (-1); 2745 } 2746 if ((indx = findname(string, "third", bufpp, &witnesslist)) == -1) 2747 return (-1); 2748 mib[2] = indx; 2749 *typep = witnesslist.list[indx].ctl_type; 2750 return (3); 2751} 2752 2753/* 2754 * Scan a list of names searching for a particular name. 2755 */ 2756int 2757findname(char *string, char *level, char **bufp, struct list *namelist) 2758{ 2759 char *name; 2760 int i; 2761 2762 if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { 2763 warnx("%s: incomplete specification", string); 2764 return (-1); 2765 } 2766 for (i = 0; i < namelist->size; i++) 2767 if (namelist->list[i].ctl_name != NULL && 2768 strcmp(name, namelist->list[i].ctl_name) == 0) 2769 break; 2770 if (i == namelist->size) { 2771 warnx("%s level name %s in %s is invalid", level, name, string); 2772 return (-1); 2773 } 2774 return (i); 2775} 2776 2777void 2778usage(void) 2779{ 2780 2781 (void)fprintf(stderr, 2782 "usage: sysctl [-Aanq] [name[=value]]\n"); 2783 exit(1); 2784} 2785