2981 lines
67 KiB
C
2981 lines
67 KiB
C
/* $OpenBSD: sysctl.c,v 1.261 2024/05/09 08:35:40 florian Exp $ */
|
|
/* $NetBSD: sysctl.c,v 1.9 1995/09/30 07:12:50 thorpej Exp $ */
|
|
|
|
/*
|
|
* Copyright (c) 1993
|
|
* The Regents of the University of California. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. Neither the name of the University nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/gmon.h>
|
|
#include <sys/mount.h>
|
|
#include <sys/sem.h>
|
|
#include <sys/shm.h>
|
|
#include <sys/sysctl.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/time.h>
|
|
#include <sys/malloc.h>
|
|
#include <sys/uio.h>
|
|
#include <sys/tty.h>
|
|
#include <sys/namei.h>
|
|
#include <sys/sched.h>
|
|
#include <sys/sensors.h>
|
|
#include <sys/vmmeter.h>
|
|
#include <net/route.h>
|
|
#include <net/if.h>
|
|
|
|
#include <netinet/in.h>
|
|
#include <netinet/ip.h>
|
|
#include <netinet/in_pcb.h>
|
|
#include <netinet/ip_icmp.h>
|
|
#include <netinet/ip_ipip.h>
|
|
#include <netinet/ip_ether.h>
|
|
#include <netinet/ip_ah.h>
|
|
#include <netinet/ip_esp.h>
|
|
#include <netinet/icmp_var.h>
|
|
#include <netinet/igmp_var.h>
|
|
#include <netinet/ip_var.h>
|
|
#include <netinet/udp.h>
|
|
#include <netinet/udp_var.h>
|
|
#include <netinet/tcp.h>
|
|
#include <netinet/tcp_timer.h>
|
|
#include <netinet/tcp_var.h>
|
|
#include <netinet/ip_gre.h>
|
|
#include <netinet/ip_ipcomp.h>
|
|
#include <netinet/ip_carp.h>
|
|
#include <netinet/ip_divert.h>
|
|
|
|
#include <net/pfvar.h>
|
|
#include <net/if_pfsync.h>
|
|
#include <net/pipex.h>
|
|
|
|
#include <netinet/ip6.h>
|
|
#include <netinet/icmp6.h>
|
|
#include <netinet6/ip6_divert.h>
|
|
|
|
#include <netmpls/mpls.h>
|
|
|
|
#include <uvm/uvm_swap_encrypt.h>
|
|
|
|
#include <ufs/ufs/quota.h>
|
|
#include <ufs/ufs/inode.h>
|
|
#include <ufs/ffs/ffs_extern.h>
|
|
|
|
#include <miscfs/fuse/fusefs.h>
|
|
|
|
#include <nfs/nfsproto.h>
|
|
#include <nfs/nfs.h>
|
|
|
|
#include <ddb/db_var.h>
|
|
|
|
#include <ctype.h>
|
|
#include <err.h>
|
|
#include <errno.h>
|
|
#include <limits.h>
|
|
#include <paths.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include <machine/cpu.h>
|
|
|
|
#ifdef CPU_BIOS
|
|
#include <machine/biosvar.h>
|
|
#endif
|
|
|
|
struct ctlname topname[] = CTL_NAMES;
|
|
struct ctlname kernname[] = CTL_KERN_NAMES;
|
|
struct ctlname vmname[] = CTL_VM_NAMES;
|
|
struct ctlname fsname[] = CTL_FS_NAMES;
|
|
struct ctlname netname[] = CTL_NET_NAMES;
|
|
struct ctlname hwname[] = CTL_HW_NAMES;
|
|
struct ctlname debugname[CTL_DEBUG_MAXID];
|
|
struct ctlname kernmallocname[] = CTL_KERN_MALLOC_NAMES;
|
|
struct ctlname forkstatname[] = CTL_KERN_FORKSTAT_NAMES;
|
|
struct ctlname nchstatsname[] = CTL_KERN_NCHSTATS_NAMES;
|
|
struct ctlname ttysname[] = CTL_KERN_TTY_NAMES;
|
|
struct ctlname semname[] = CTL_KERN_SEMINFO_NAMES;
|
|
struct ctlname shmname[] = CTL_KERN_SHMINFO_NAMES;
|
|
struct ctlname watchdogname[] = CTL_KERN_WATCHDOG_NAMES;
|
|
struct ctlname tcname[] = CTL_KERN_TIMECOUNTER_NAMES;
|
|
struct ctlname *vfsname;
|
|
#ifdef CTL_MACHDEP_NAMES
|
|
struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
|
|
#endif
|
|
struct ctlname ddbname[] = CTL_DDB_NAMES;
|
|
struct ctlname audioname[] = CTL_KERN_AUDIO_NAMES;
|
|
struct ctlname videoname[] = CTL_KERN_VIDEO_NAMES;
|
|
struct ctlname witnessname[] = CTL_KERN_WITNESS_NAMES;
|
|
struct ctlname batteryname[] = CTL_HW_BATTERY_NAMES;
|
|
char names[BUFSIZ];
|
|
int lastused;
|
|
|
|
/* Maximum size object to expect from sysctl(2) */
|
|
#define SYSCTL_BUFSIZ 8192
|
|
|
|
struct list {
|
|
struct ctlname *list;
|
|
int size;
|
|
};
|
|
struct list toplist = { topname, CTL_MAXID };
|
|
struct list secondlevel[] = {
|
|
{ 0, 0 }, /* CTL_UNSPEC */
|
|
{ kernname, KERN_MAXID }, /* CTL_KERN */
|
|
{ vmname, VM_MAXID }, /* CTL_VM */
|
|
{ fsname, FS_MAXID }, /* CTL_FS */
|
|
{ netname, NET_MAXID }, /* CTL_NET */
|
|
{ 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */
|
|
{ hwname, HW_MAXID }, /* CTL_HW */
|
|
#ifdef CTL_MACHDEP_NAMES
|
|
{ machdepname, CPU_MAXID }, /* CTL_MACHDEP */
|
|
#else
|
|
{ 0, 0 }, /* CTL_MACHDEP */
|
|
#endif
|
|
{ 0, 0 }, /* was CTL_USER */
|
|
{ ddbname, DBCTL_MAXID }, /* CTL_DDB_NAMES */
|
|
{ 0, 0 }, /* CTL_VFS */
|
|
};
|
|
|
|
int Aflag, aflag, nflag, qflag;
|
|
|
|
time_t boottime;
|
|
|
|
/*
|
|
* Variables requiring special processing.
|
|
*/
|
|
#define CLOCK 0x00000001
|
|
#define BOOTTIME 0x00000002
|
|
#define CHRDEV 0x00000004
|
|
#define BLKDEV 0x00000008
|
|
#define BADDYNAMIC 0x00000020
|
|
#define BIOSGEO 0x00000040
|
|
#define BIOSDEV 0x00000080
|
|
#define MAJ2DEV 0x00000100
|
|
#define UNSIGNED 0x00000200
|
|
#define KMEMBUCKETS 0x00000400
|
|
#define LONGARRAY 0x00000800
|
|
#define KMEMSTATS 0x00001000
|
|
#define SENSORS 0x00002000
|
|
#define SMALLBUF 0x00004000
|
|
#define HEX 0x00008000
|
|
#define TIMEOUT 0x00010000
|
|
|
|
/* prototypes */
|
|
void debuginit(void);
|
|
void listall(char *, struct list *);
|
|
int parse_hex_char(char);
|
|
ssize_t parse_hex_string(unsigned char *, size_t, const char *);
|
|
void parse(char *, int);
|
|
void parse_baddynamic(int *, size_t, char *, void **, size_t *, int, int);
|
|
void usage(void);
|
|
int findname(char *, char *, char **, struct list *);
|
|
int sysctl_inet(char *, char **, int *, int, int *);
|
|
int sysctl_inet6(char *, char **, int *, int, int *);
|
|
int sysctl_unix(char *, char **, int *, int, int *);
|
|
int sysctl_link(char *, char **, int *, int, int *);
|
|
int sysctl_bpf(char *, char **, int *, int, int *);
|
|
int sysctl_mpls(char *, char **, int *, int, int *);
|
|
int sysctl_pipex(char *, char **, int *, int, int *);
|
|
int sysctl_fs(char *, char **, int *, int, int *);
|
|
static int sysctl_vfs(char *, char **, int[], int, int *);
|
|
static int sysctl_vfsgen(char *, char **, int[], int, int *);
|
|
int sysctl_bios(char *, char **, int *, int, int *);
|
|
int sysctl_swpenc(char *, char **, int *, int, int *);
|
|
int sysctl_forkstat(char *, char **, int *, int, int *);
|
|
int sysctl_tty(char *, char **, int *, int, int *);
|
|
int sysctl_nchstats(char *, char **, int *, int, int *);
|
|
int sysctl_malloc(char *, char **, int *, int, int *);
|
|
int sysctl_seminfo(char *, char **, int *, int, int *);
|
|
int sysctl_shminfo(char *, char **, int *, int, int *);
|
|
int sysctl_watchdog(char *, char **, int *, int, int *);
|
|
int sysctl_tc(char *, char **, int *, int, int *);
|
|
int sysctl_sensors(char *, char **, int *, int, int *);
|
|
void print_sensordev(char *, int *, u_int, struct sensordev *);
|
|
void print_sensor(struct sensor *);
|
|
#ifdef CPU_CHIPSET
|
|
int sysctl_chipset(char *, char **, int *, int, int *);
|
|
#endif
|
|
int sysctl_audio(char *, char **, int *, int, int *);
|
|
int sysctl_video(char *, char **, int *, int, int *);
|
|
int sysctl_witness(char *, char **, int *, int, int *);
|
|
int sysctl_battery(char *, char **, int *, int, int *);
|
|
void vfsinit(void);
|
|
|
|
char *equ = "=";
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
int ch, lvl1;
|
|
|
|
while ((ch = getopt(argc, argv, "Aanqw")) != -1) {
|
|
switch (ch) {
|
|
|
|
case 'A':
|
|
Aflag = 1;
|
|
break;
|
|
|
|
case 'a':
|
|
aflag = 1;
|
|
break;
|
|
|
|
case 'n':
|
|
nflag = 1;
|
|
break;
|
|
|
|
case 'q':
|
|
qflag = 1;
|
|
break;
|
|
|
|
case 'w':
|
|
/* flag no longer needed; var=value implies write */
|
|
break;
|
|
|
|
default:
|
|
usage();
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
ctime(&boottime); /* satisfy potential $TZ expansion before unveil() */
|
|
|
|
if (unveil(_PATH_DEVDB, "r") == -1 && errno != ENOENT)
|
|
err(1,"unveil %s", _PATH_DEVDB);
|
|
if (unveil("/dev", "r") == -1 && errno != ENOENT)
|
|
err(1, "unveil /dev");
|
|
if (unveil(NULL, NULL) == -1)
|
|
err(1, "unveil");
|
|
|
|
if (argc == 0 || (Aflag || aflag)) {
|
|
debuginit();
|
|
vfsinit();
|
|
for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
|
|
listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
|
|
return (0);
|
|
}
|
|
for (; *argv != NULL; ++argv)
|
|
parse(*argv, 1);
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* List all variables known to the system.
|
|
*/
|
|
void
|
|
listall(char *prefix, struct list *lp)
|
|
{
|
|
char *cp, name[BUFSIZ];
|
|
int lvl2, len;
|
|
|
|
if (lp->list == NULL)
|
|
return;
|
|
if ((len = strlcpy(name, prefix, sizeof(name))) >= sizeof(name))
|
|
errx(1, "%s: name too long", prefix);
|
|
cp = name + len++;
|
|
*cp++ = '.';
|
|
for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
|
|
if (lp->list[lvl2].ctl_name == NULL)
|
|
continue;
|
|
if (strlcpy(cp, lp->list[lvl2].ctl_name,
|
|
sizeof(name) - len) >= sizeof(name) - len)
|
|
warn("%s: name too long", lp->list[lvl2].ctl_name);
|
|
parse(name, Aflag);
|
|
}
|
|
}
|
|
|
|
int
|
|
parse_hex_char(char ch)
|
|
{
|
|
if (ch >= '0' && ch <= '9')
|
|
return (ch - '0');
|
|
|
|
ch = tolower((unsigned char)ch);
|
|
if (ch >= 'a' && ch <= 'f')
|
|
return (ch - 'a' + 10);
|
|
|
|
return (-1);
|
|
}
|
|
|
|
ssize_t
|
|
parse_hex_string(unsigned char *dst, size_t dstlen, const char *src)
|
|
{
|
|
ssize_t len = 0;
|
|
int digit;
|
|
|
|
while (len < dstlen) {
|
|
if (*src == '\0')
|
|
return (len);
|
|
|
|
digit = parse_hex_char(*src++);
|
|
if (digit == -1)
|
|
return (-1);
|
|
dst[len] = digit << 4;
|
|
|
|
digit = parse_hex_char(*src++);
|
|
if (digit == -1)
|
|
return (-1);
|
|
|
|
dst[len] |= digit;
|
|
len++;
|
|
}
|
|
|
|
while (*src != '\0') {
|
|
if (parse_hex_char(*src++) == -1 ||
|
|
parse_hex_char(*src++) == -1)
|
|
return (-1);
|
|
|
|
len++;
|
|
}
|
|
|
|
return (len);
|
|
}
|
|
|
|
/*
|
|
* Parse a name into a MIB entry.
|
|
* Lookup and print out the MIB entry if it exists.
|
|
* Set a new value if requested.
|
|
*/
|
|
void
|
|
parse(char *string, int flags)
|
|
{
|
|
int indx, type, state, intval, len;
|
|
size_t size, newsize = 0;
|
|
int lal = 0, special = 0;
|
|
void *newval = NULL;
|
|
int64_t quadval;
|
|
struct list *lp;
|
|
int mib[CTL_MAXNAME];
|
|
char *cp, *bufp, buf[SYSCTL_BUFSIZ];
|
|
unsigned char hex[SYSCTL_BUFSIZ];
|
|
|
|
(void)strlcpy(buf, string, sizeof(buf));
|
|
bufp = buf;
|
|
if ((cp = strchr(string, '=')) != NULL) {
|
|
*strchr(buf, '=') = '\0';
|
|
*cp++ = '\0';
|
|
while (isspace((unsigned char)*cp))
|
|
cp++;
|
|
newval = cp;
|
|
newsize = strlen(cp);
|
|
}
|
|
if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
|
|
return;
|
|
mib[0] = indx;
|
|
if (indx == CTL_VFS)
|
|
vfsinit();
|
|
if (indx == CTL_DEBUG)
|
|
debuginit();
|
|
lp = &secondlevel[indx];
|
|
if (lp->list == 0) {
|
|
warnx("%s: class is not implemented", topname[indx].ctl_name);
|
|
return;
|
|
}
|
|
if (bufp == NULL) {
|
|
listall(topname[indx].ctl_name, lp);
|
|
return;
|
|
}
|
|
if ((indx = findname(string, "second", &bufp, lp)) == -1)
|
|
return;
|
|
mib[1] = indx;
|
|
type = lp->list[indx].ctl_type;
|
|
len = 2;
|
|
switch (mib[0]) {
|
|
|
|
case CTL_KERN:
|
|
switch (mib[1]) {
|
|
case KERN_PROF:
|
|
mib[2] = GPROF_STATE;
|
|
mib[3] = 0; /* Assume CPU ID 0 is always valid. */
|
|
size = sizeof(state);
|
|
if (sysctl(mib, 4, &state, &size, NULL, 0) == -1) {
|
|
if (flags == 0)
|
|
return;
|
|
if (!nflag)
|
|
(void)printf("%s: ", string);
|
|
(void)puts("kernel is not compiled for profiling");
|
|
return;
|
|
}
|
|
if (!nflag)
|
|
(void)printf("%s = %s\n", string,
|
|
state == GMON_PROF_OFF ? "off" : "running");
|
|
return;
|
|
case KERN_FORKSTAT:
|
|
sysctl_forkstat(string, &bufp, mib, flags, &type);
|
|
return;
|
|
case KERN_TTY:
|
|
len = sysctl_tty(string, &bufp, mib, flags, &type);
|
|
if (len < 0)
|
|
return;
|
|
break;
|
|
case KERN_NCHSTATS:
|
|
sysctl_nchstats(string, &bufp, mib, flags, &type);
|
|
return;
|
|
case KERN_MALLOCSTATS:
|
|
len = sysctl_malloc(string, &bufp, mib, flags, &type);
|
|
if (len < 0)
|
|
return;
|
|
if (mib[2] == KERN_MALLOC_BUCKET)
|
|
special |= KMEMBUCKETS;
|
|
if (mib[2] == KERN_MALLOC_KMEMSTATS)
|
|
special |= KMEMSTATS;
|
|
newsize = 0;
|
|
break;
|
|
case KERN_MBSTAT:
|
|
if (flags == 0)
|
|
return;
|
|
warnx("use netstat to view %s", string);
|
|
return;
|
|
case KERN_MSGBUF:
|
|
if (flags == 0)
|
|
return;
|
|
warnx("use dmesg to view %s", string);
|
|
return;
|
|
case KERN_PROC:
|
|
if (flags == 0)
|
|
return;
|
|
warnx("use ps to view %s information", string);
|
|
return;
|
|
case KERN_CLOCKRATE:
|
|
special |= CLOCK;
|
|
break;
|
|
case KERN_BOOTTIME:
|
|
special |= BOOTTIME;
|
|
break;
|
|
case KERN_HOSTID:
|
|
special |= UNSIGNED;
|
|
special |= SMALLBUF;
|
|
break;
|
|
case KERN_CPTIME:
|
|
special |= LONGARRAY;
|
|
lal = CPUSTATES;
|
|
break;
|
|
case KERN_SEMINFO:
|
|
len = sysctl_seminfo(string, &bufp, mib, flags, &type);
|
|
if (len < 0)
|
|
return;
|
|
break;
|
|
case KERN_SHMINFO:
|
|
len = sysctl_shminfo(string, &bufp, mib, flags, &type);
|
|
if (len < 0)
|
|
return;
|
|
break;
|
|
case KERN_INTRCNT:
|
|
if (flags == 0)
|
|
return;
|
|
warnx("use vmstat or systat to view %s information",
|
|
string);
|
|
return;
|
|
case KERN_WATCHDOG:
|
|
len = sysctl_watchdog(string, &bufp, mib, flags,
|
|
&type);
|
|
if (len < 0)
|
|
return;
|
|
break;
|
|
case KERN_TIMECOUNTER:
|
|
len = sysctl_tc(string, &bufp, mib, flags,
|
|
&type);
|
|
if (len < 0)
|
|
return;
|
|
break;
|
|
case KERN_FILE:
|
|
if (flags == 0)
|
|
return;
|
|
warnx("use fstat to view %s information", string);
|
|
return;
|
|
case KERN_CONSDEV:
|
|
special |= CHRDEV;
|
|
break;
|
|
case KERN_NETLIVELOCKS:
|
|
case KERN_SOMAXCONN:
|
|
case KERN_SOMINCONN:
|
|
special |= UNSIGNED;
|
|
break;
|
|
case KERN_AUDIO:
|
|
len = sysctl_audio(string, &bufp, mib, flags, &type);
|
|
if (len < 0)
|
|
return;
|
|
break;
|
|
case KERN_VIDEO:
|
|
len = sysctl_video(string, &bufp, mib, flags, &type);
|
|
if (len < 0)
|
|
return;
|
|
break;
|
|
case KERN_WITNESS:
|
|
len = sysctl_witness(string, &bufp, mib, flags, &type);
|
|
if (len < 0)
|
|
return;
|
|
break;
|
|
case KERN_PFSTATUS:
|
|
if (flags == 0)
|
|
return;
|
|
warnx("use pfctl to view %s information", string);
|
|
return;
|
|
case KERN_TIMEOUT_STATS:
|
|
special |= TIMEOUT;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case CTL_HW:
|
|
switch (mib[1]) {
|
|
case HW_DISKSTATS:
|
|
/*
|
|
* Only complain if someone asks explicitly for this,
|
|
* otherwise "fail" silently.
|
|
*/
|
|
if (flags)
|
|
warnx("use vmstat to view %s information",
|
|
string);
|
|
return;
|
|
case HW_SENSORS:
|
|
special |= SENSORS;
|
|
len = sysctl_sensors(string, &bufp, mib, flags, &type);
|
|
if (len < 0)
|
|
return;
|
|
break;
|
|
case HW_BATTERY:
|
|
len = sysctl_battery(string, &bufp, mib, flags, &type);
|
|
if (len < 0)
|
|
return;
|
|
break;
|
|
case HW_PHYSMEM:
|
|
case HW_USERMEM:
|
|
/*
|
|
* Don't print these; we'll print the 64-bit
|
|
* variants instead.
|
|
*/
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case CTL_VM:
|
|
if (mib[1] == VM_LOADAVG) {
|
|
double loads[3];
|
|
|
|
getloadavg(loads, 3);
|
|
if (!nflag)
|
|
(void)printf("%s%s", string, equ);
|
|
(void)printf("%.2f %.2f %.2f\n", loads[0],
|
|
loads[1], loads[2]);
|
|
return;
|
|
} else if (mib[1] == VM_PSSTRINGS) {
|
|
struct _ps_strings _ps;
|
|
|
|
size = sizeof(_ps);
|
|
if (sysctl(mib, 2, &_ps, &size, NULL, 0) == -1) {
|
|
if (flags == 0)
|
|
return;
|
|
if (!nflag)
|
|
(void)printf("%s: ", string);
|
|
(void)puts("can't find ps strings");
|
|
return;
|
|
}
|
|
if (!nflag)
|
|
(void)printf("%s%s", string, equ);
|
|
(void)printf("%p\n", _ps.val);
|
|
return;
|
|
} else if (mib[1] == VM_SWAPENCRYPT) {
|
|
len = sysctl_swpenc(string, &bufp, mib, flags, &type);
|
|
if (len < 0)
|
|
return;
|
|
|
|
break;
|
|
} else if (mib[1] == VM_NKMEMPAGES ||
|
|
mib[1] == VM_ANONMIN ||
|
|
mib[1] == VM_VTEXTMIN ||
|
|
mib[1] == VM_VNODEMIN ||
|
|
mib[1] == VM_MALLOC_CONF) {
|
|
break;
|
|
}
|
|
if (flags == 0)
|
|
return;
|
|
warnx("use vmstat or systat to view %s information", string);
|
|
return;
|
|
|
|
break;
|
|
|
|
case CTL_NET:
|
|
if (mib[1] == PF_INET) {
|
|
len = sysctl_inet(string, &bufp, mib, flags, &type);
|
|
if (len < 0)
|
|
return;
|
|
|
|
if ((mib[2] == IPPROTO_IP && mib[3] == IPCTL_MRTSTATS) ||
|
|
(mib[2] == IPPROTO_IP && mib[3] == IPCTL_STATS) ||
|
|
(mib[2] == IPPROTO_IP && mib[3] == IPCTL_MRTMFC) ||
|
|
(mib[2] == IPPROTO_IP && mib[3] == IPCTL_MRTVIF) ||
|
|
(mib[2] == IPPROTO_TCP && mib[3] == TCPCTL_STATS) ||
|
|
(mib[2] == IPPROTO_UDP && mib[3] == UDPCTL_STATS) ||
|
|
(mib[2] == IPPROTO_ESP && mib[3] == ESPCTL_STATS) ||
|
|
(mib[2] == IPPROTO_AH && mib[3] == AHCTL_STATS) ||
|
|
(mib[2] == IPPROTO_IGMP && mib[3] == IGMPCTL_STATS) ||
|
|
(mib[2] == IPPROTO_ETHERIP && mib[3] == ETHERIPCTL_STATS) ||
|
|
(mib[2] == IPPROTO_IPIP && mib[3] == IPIPCTL_STATS) ||
|
|
(mib[2] == IPPROTO_IPCOMP && mib[3] == IPCOMPCTL_STATS) ||
|
|
(mib[2] == IPPROTO_ICMP && mib[3] == ICMPCTL_STATS) ||
|
|
(mib[2] == IPPROTO_CARP && mib[3] == CARPCTL_STATS) ||
|
|
(mib[2] == IPPROTO_PFSYNC && mib[3] == PFSYNCCTL_STATS) ||
|
|
(mib[2] == IPPROTO_DIVERT && mib[3] == DIVERTCTL_STATS)) {
|
|
if (flags == 0)
|
|
return;
|
|
warnx("use netstat to view %s information",
|
|
string);
|
|
return;
|
|
} else if ((mib[2] == IPPROTO_TCP &&
|
|
(mib[3] == TCPCTL_BADDYNAMIC ||
|
|
mib[3] == TCPCTL_ROOTONLY)) ||
|
|
(mib[2] == IPPROTO_UDP &&
|
|
(mib[3] == UDPCTL_BADDYNAMIC ||
|
|
mib[3] == UDPCTL_ROOTONLY))) {
|
|
|
|
special |= BADDYNAMIC;
|
|
|
|
if (newval != NULL)
|
|
parse_baddynamic(mib, len, string,
|
|
&newval, &newsize, flags, nflag);
|
|
}
|
|
break;
|
|
}
|
|
if (mib[1] == PF_INET6) {
|
|
len = sysctl_inet6(string, &bufp, mib, flags, &type);
|
|
if (len < 0)
|
|
return;
|
|
|
|
if (mib[2] == IPPROTO_IPV6 &&
|
|
mib[3] == IPV6CTL_SOIIKEY)
|
|
special |= HEX;
|
|
|
|
if ((mib[2] == IPPROTO_IPV6 && mib[3] == IPV6CTL_MRTMFC) ||
|
|
(mib[2] == IPPROTO_IPV6 && mib[3] == IPV6CTL_MRTMIF) ||
|
|
(mib[2] == IPPROTO_DIVERT && mib[3] == DIVERT6CTL_STATS)) {
|
|
if (flags == 0)
|
|
return;
|
|
warnx("use netstat to view %s information",
|
|
string);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
if (mib[1] == PF_UNIX) {
|
|
len = sysctl_unix(string, &bufp, mib, flags, &type);
|
|
if (len < 0)
|
|
return;
|
|
break;
|
|
}
|
|
if (mib[1] == PF_LINK) {
|
|
len = sysctl_link(string, &bufp, mib, flags, &type);
|
|
if (len < 0)
|
|
return;
|
|
break;
|
|
}
|
|
if (mib[1] == PF_BPF) {
|
|
len = sysctl_bpf(string, &bufp, mib, flags, &type);
|
|
if (len < 0)
|
|
return;
|
|
break;
|
|
}
|
|
if (mib[1] == PF_MPLS) {
|
|
len = sysctl_mpls(string, &bufp, mib, flags, &type);
|
|
if (len < 0)
|
|
return;
|
|
break;
|
|
}
|
|
if (mib[1] == PF_PIPEX) {
|
|
len = sysctl_pipex(string, &bufp, mib, flags, &type);
|
|
if (len < 0)
|
|
return;
|
|
break;
|
|
}
|
|
if (flags == 0)
|
|
return;
|
|
warnx("use netstat to view %s information", string);
|
|
return;
|
|
|
|
case CTL_DEBUG:
|
|
mib[2] = CTL_DEBUG_VALUE;
|
|
len = 3;
|
|
break;
|
|
|
|
case CTL_MACHDEP:
|
|
#ifdef CPU_CONSDEV
|
|
if (mib[1] == CPU_CONSDEV)
|
|
special |= CHRDEV;
|
|
#endif
|
|
#ifdef CPU_CPUID
|
|
if (mib[1] == CPU_CPUID)
|
|
special |= HEX;
|
|
#endif
|
|
#ifdef CPU_CPUFEATURE
|
|
if (mib[1] == CPU_CPUFEATURE)
|
|
special |= HEX;
|
|
#endif
|
|
#ifdef CPU_BLK2CHR
|
|
if (mib[1] == CPU_BLK2CHR) {
|
|
if (bufp == NULL)
|
|
return;
|
|
mib[2] = makedev(atoi(bufp),0);
|
|
bufp = NULL;
|
|
len = 3;
|
|
special |= CHRDEV;
|
|
break;
|
|
}
|
|
#endif
|
|
#ifdef CPU_CHR2BLK
|
|
if (mib[1] == CPU_CHR2BLK) {
|
|
if (bufp == NULL)
|
|
return;
|
|
mib[2] = makedev(atoi(bufp),0);
|
|
bufp = NULL;
|
|
len = 3;
|
|
special |= BLKDEV;
|
|
break;
|
|
}
|
|
#endif
|
|
#ifdef CPU_BIOS
|
|
if (mib[1] == CPU_BIOS) {
|
|
len = sysctl_bios(string, &bufp, mib, flags, &type);
|
|
if (len < 0)
|
|
return;
|
|
if (mib[2] == BIOS_DEV)
|
|
special |= BIOSDEV;
|
|
if (mib[2] == BIOS_DISKINFO)
|
|
special |= BIOSGEO;
|
|
break;
|
|
}
|
|
#endif
|
|
#ifdef CPU_CHIPSET
|
|
if (mib[1] == CPU_CHIPSET) {
|
|
len = sysctl_chipset(string, &bufp, mib, flags, &type);
|
|
if (len < 0)
|
|
return;
|
|
break;
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case CTL_FS:
|
|
len = sysctl_fs(string, &bufp, mib, flags, &type);
|
|
if (len >= 0)
|
|
break;
|
|
return;
|
|
|
|
case CTL_VFS:
|
|
if (mib[1])
|
|
len = sysctl_vfs(string, &bufp, mib, flags, &type);
|
|
else
|
|
len = sysctl_vfsgen(string, &bufp, mib, flags, &type);
|
|
if (len >= 0) {
|
|
if (type == CTLTYPE_STRUCT) {
|
|
if (flags)
|
|
warnx("use nfsstat to view %s information",
|
|
MOUNT_NFS);
|
|
return;
|
|
} else
|
|
break;
|
|
}
|
|
return;
|
|
|
|
case CTL_DDB:
|
|
break;
|
|
|
|
default:
|
|
warnx("illegal top level value: %d", mib[0]);
|
|
return;
|
|
|
|
}
|
|
if (bufp) {
|
|
warnx("name %s in %s is unknown", bufp, string);
|
|
return;
|
|
}
|
|
if (newsize > 0) {
|
|
const char *errstr;
|
|
|
|
switch (type) {
|
|
case CTLTYPE_INT:
|
|
if (special & UNSIGNED)
|
|
intval = strtonum(newval, 0, UINT_MAX, &errstr);
|
|
else
|
|
intval = strtonum(newval, INT_MIN, INT_MAX,
|
|
&errstr);
|
|
if (errstr != NULL) {
|
|
warnx("%s: value is %s: %s", string, errstr,
|
|
(char *)newval);
|
|
return;
|
|
}
|
|
newval = &intval;
|
|
newsize = sizeof(intval);
|
|
break;
|
|
|
|
case CTLTYPE_QUAD:
|
|
(void)sscanf(newval, "%lld", &quadval);
|
|
newval = &quadval;
|
|
newsize = sizeof(quadval);
|
|
break;
|
|
case CTLTYPE_STRING:
|
|
if (special & HEX) {
|
|
ssize_t len;
|
|
|
|
len = parse_hex_string(hex, sizeof(hex),
|
|
newval);
|
|
if (len == -1) {
|
|
warnx("%s: hex string %s: invalid",
|
|
string, (char *)newval);
|
|
return;
|
|
}
|
|
if (len > sizeof(hex)) {
|
|
warnx("%s: hex string %s: too long",
|
|
string, (char *)newval);
|
|
return;
|
|
}
|
|
|
|
newval = hex;
|
|
newsize = len;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
size = (special & SMALLBUF) ? 512 : SYSCTL_BUFSIZ;
|
|
if (sysctl(mib, len, buf, &size, newval, newsize) == -1) {
|
|
if (flags == 0)
|
|
return;
|
|
switch (errno) {
|
|
case EOPNOTSUPP:
|
|
warnx("%s: value is not available", string);
|
|
return;
|
|
case ENOTDIR:
|
|
warnx("%s: specification is incomplete", string);
|
|
return;
|
|
case ENOMEM:
|
|
warnx("%s: type is unknown to this program", string);
|
|
return;
|
|
case ENXIO:
|
|
if (special & BIOSGEO)
|
|
return;
|
|
default:
|
|
warn("%s", string);
|
|
return;
|
|
}
|
|
}
|
|
if (special & KMEMBUCKETS) {
|
|
struct kmembuckets *kb = (struct kmembuckets *)buf;
|
|
if (!nflag)
|
|
(void)printf("%s%s", string, equ);
|
|
printf("(");
|
|
printf("calls = %llu ", (long long)kb->kb_calls);
|
|
printf("total_allocated = %llu ", (long long)kb->kb_total);
|
|
printf("total_free = %lld ", (long long)kb->kb_totalfree);
|
|
printf("elements = %lld ", (long long)kb->kb_elmpercl);
|
|
printf("high watermark = %lld ", (long long)kb->kb_highwat);
|
|
printf("could_free = %lld", (long long)kb->kb_couldfree);
|
|
printf(")\n");
|
|
return;
|
|
}
|
|
if (special & KMEMSTATS) {
|
|
struct kmemstats *km = (struct kmemstats *)buf;
|
|
int j, first = 1;
|
|
|
|
if (!nflag)
|
|
(void)printf("%s%s", string, equ);
|
|
(void)printf("(inuse = %ld, calls = %ld, memuse = %ldK, "
|
|
"limblocks = %d, maxused = %ldK, "
|
|
"limit = %ldK, spare = %ld, sizes = (",
|
|
km->ks_inuse, km->ks_calls,
|
|
(km->ks_memuse + 1023) / 1024, km->ks_limblocks,
|
|
(km->ks_maxused + 1023) / 1024,
|
|
(km->ks_limit + 1023) / 1024, km->ks_spare);
|
|
for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
|
|
if ((km->ks_size & j ) == 0)
|
|
continue;
|
|
if (first)
|
|
(void)printf("%d", j);
|
|
else
|
|
(void)printf(",%d", j);
|
|
first = 0;
|
|
}
|
|
if (first)
|
|
(void)printf("none");
|
|
(void)printf("))\n");
|
|
return;
|
|
}
|
|
if (special & CLOCK) {
|
|
struct clockinfo *clkp = (struct clockinfo *)buf;
|
|
|
|
if (!nflag)
|
|
(void)printf("%s%s", string, equ);
|
|
(void)printf(
|
|
"tick = %d, hz = %d, profhz = %d, stathz = %d\n",
|
|
clkp->tick, clkp->hz, clkp->profhz, clkp->stathz);
|
|
return;
|
|
}
|
|
if (special & BOOTTIME) {
|
|
struct timeval *btp = (struct timeval *)buf;
|
|
|
|
if (!nflag) {
|
|
char *ct;
|
|
boottime = btp->tv_sec;
|
|
ct = ctime(&boottime);
|
|
if (ct)
|
|
(void)printf("%s%s%s", string, equ, ct);
|
|
else
|
|
(void)printf("%s%s%lld\n", string, equ,
|
|
boottime);
|
|
} else
|
|
(void)printf("%lld\n", (long long)btp->tv_sec);
|
|
return;
|
|
}
|
|
if (special & BLKDEV) {
|
|
dev_t dev = *(dev_t *)buf;
|
|
|
|
if (!nflag)
|
|
(void)printf("%s%s%s\n", string, equ,
|
|
devname(dev, S_IFBLK));
|
|
else
|
|
(void)printf("0x%x\n", dev);
|
|
return;
|
|
}
|
|
if (special & CHRDEV) {
|
|
dev_t dev = *(dev_t *)buf;
|
|
|
|
if (!nflag)
|
|
(void)printf("%s%s%s\n", string, equ,
|
|
devname(dev, S_IFCHR));
|
|
else
|
|
(void)printf("0x%x\n", dev);
|
|
return;
|
|
}
|
|
#ifdef CPU_BIOS
|
|
if (special & BIOSGEO) {
|
|
bios_diskinfo_t *pdi = (bios_diskinfo_t *)buf;
|
|
|
|
if (!nflag)
|
|
(void)printf("%s%s", string, equ);
|
|
(void)printf("bootdev = 0x%x, "
|
|
"cylinders = %u, heads = %u, sectors = %u\n",
|
|
pdi->bsd_dev, pdi->bios_cylinders,
|
|
pdi->bios_heads, pdi->bios_sectors);
|
|
return;
|
|
}
|
|
if (special & BIOSDEV) {
|
|
int dev = *(int*)buf;
|
|
|
|
if (!nflag)
|
|
(void)printf("%s%s", string, equ);
|
|
(void) printf("0x%02x\n", dev);
|
|
return;
|
|
}
|
|
#endif
|
|
if (special & UNSIGNED) {
|
|
if (newsize == 0) {
|
|
if (!nflag)
|
|
(void)printf("%s%s", string, equ);
|
|
(void)printf("%u\n", *(u_int *)buf);
|
|
} else {
|
|
if (!qflag) {
|
|
if (!nflag)
|
|
(void)printf("%s: %u -> ", string,
|
|
*(u_int *)buf);
|
|
(void)printf("%u\n", *(u_int *)newval);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
if (special & BADDYNAMIC) {
|
|
u_int port, lastport;
|
|
u_int32_t *baddynamic = (u_int32_t *)buf;
|
|
|
|
if (!qflag) {
|
|
if (!nflag)
|
|
(void)printf("%s%s", string,
|
|
newsize ? ": " : equ);
|
|
lastport = 0;
|
|
for (port = 0; port < 65536; port++)
|
|
if (DP_ISSET(baddynamic, port)) {
|
|
(void)printf("%s%u",
|
|
lastport ? "," : "", port);
|
|
lastport = port;
|
|
}
|
|
if (newsize != 0) {
|
|
if (!nflag)
|
|
fputs(" -> ", stdout);
|
|
baddynamic = (u_int32_t *)newval;
|
|
lastport = 0;
|
|
for (port = 0; port < 65536; port++)
|
|
if (DP_ISSET(baddynamic, port)) {
|
|
(void)printf("%s%u",
|
|
lastport ? "," : "", port);
|
|
lastport = port;
|
|
}
|
|
}
|
|
(void)putchar('\n');
|
|
}
|
|
return;
|
|
}
|
|
if (special & LONGARRAY) {
|
|
long *la = (long *)buf;
|
|
if (!nflag)
|
|
printf("%s%s", string, equ);
|
|
while (lal--)
|
|
printf("%ld%s", *la++, lal? ",":"");
|
|
putchar('\n');
|
|
return;
|
|
}
|
|
if (special & SENSORS) {
|
|
struct sensor *s = (struct sensor *)buf;
|
|
|
|
if (size > 0 && (s->flags & SENSOR_FINVALID) == 0) {
|
|
if (!nflag)
|
|
printf("%s%s", string, equ);
|
|
print_sensor(s);
|
|
printf("\n");
|
|
}
|
|
return;
|
|
}
|
|
if (special & TIMEOUT) {
|
|
struct timeoutstat *tstat = (struct timeoutstat *)buf;
|
|
|
|
if (!nflag)
|
|
printf("%s%s", string, equ);
|
|
printf("added = %llu, cancelled = %llu, deleted = %llu, "
|
|
"late = %llu, pending = %llu, readded = %llu, "
|
|
"scheduled = %llu, rescheduled = %llu, "
|
|
"run_softclock = %llu, run_thread = %llu, "
|
|
"softclocks = %llu, thread_wakeups = %llu\n",
|
|
tstat->tos_added, tstat->tos_cancelled, tstat->tos_deleted,
|
|
tstat->tos_late, tstat->tos_pending, tstat->tos_readded,
|
|
tstat->tos_scheduled, tstat->tos_rescheduled,
|
|
tstat->tos_run_softclock, tstat->tos_run_thread,
|
|
tstat->tos_softclocks, tstat->tos_thread_wakeups);
|
|
return;
|
|
}
|
|
switch (type) {
|
|
case CTLTYPE_INT:
|
|
if (newsize == 0) {
|
|
if (!nflag)
|
|
(void)printf("%s%s", string, equ);
|
|
if (special & HEX)
|
|
(void)printf("0x%x\n", *(int *)buf);
|
|
else
|
|
(void)printf("%d\n", *(int *)buf);
|
|
} else {
|
|
if (!qflag) {
|
|
if (!nflag)
|
|
(void)printf("%s: %d -> ", string,
|
|
*(int *)buf);
|
|
if (special & HEX)
|
|
(void)printf("0x%x\n", *(int *)newval);
|
|
else
|
|
(void)printf("%d\n", *(int *)newval);
|
|
}
|
|
}
|
|
return;
|
|
|
|
case CTLTYPE_STRING:
|
|
if (newval == NULL) {
|
|
if (!nflag)
|
|
(void)printf("%s%s", string, equ);
|
|
if (special & HEX) {
|
|
size_t i;
|
|
for (i = 0; i < size; i++) {
|
|
(void)printf("%02x",
|
|
(unsigned char)buf[i]);
|
|
}
|
|
(void)printf("\n");
|
|
} else
|
|
(void)puts(buf);
|
|
} else if (!qflag) {
|
|
if (!nflag) {
|
|
(void)printf("%s: ", string);
|
|
if (special & HEX) {
|
|
size_t i;
|
|
for (i = 0; i < size; i++) {
|
|
(void)printf("%02x",
|
|
(unsigned char)buf[i]);
|
|
}
|
|
} else
|
|
(void)printf("%s", buf);
|
|
|
|
(void)printf(" -> ");
|
|
}
|
|
(void)puts(cp);
|
|
}
|
|
return;
|
|
|
|
case CTLTYPE_QUAD:
|
|
if (newsize == 0) {
|
|
int64_t tmp;
|
|
|
|
memcpy(&tmp, buf, sizeof tmp);
|
|
if (!nflag)
|
|
(void)printf("%s%s", string, equ);
|
|
(void)printf("%lld\n", tmp);
|
|
} else {
|
|
int64_t tmp;
|
|
|
|
memcpy(&tmp, buf, sizeof tmp);
|
|
if (!qflag) {
|
|
if (!nflag)
|
|
(void)printf("%s: %lld -> ",
|
|
string, tmp);
|
|
memcpy(&tmp, newval, sizeof tmp);
|
|
(void)printf("%lld\n", tmp);
|
|
}
|
|
}
|
|
return;
|
|
|
|
case CTLTYPE_STRUCT:
|
|
warnx("%s: unknown structure returned", string);
|
|
return;
|
|
|
|
default:
|
|
case CTLTYPE_NODE:
|
|
warnx("%s: unknown type returned", string);
|
|
return;
|
|
}
|
|
}
|
|
|
|
static void
|
|
parse_ports(char *portspec, int *port, int *high_port)
|
|
{
|
|
char *dash;
|
|
const char *errstr;
|
|
|
|
if ((dash = strchr(portspec, '-')) != NULL)
|
|
*dash++ = '\0';
|
|
*port = strtonum(portspec, 0, 65535, &errstr);
|
|
if (errstr != NULL)
|
|
errx(1, "port is %s: %s", errstr, portspec);
|
|
if (dash != NULL) {
|
|
*high_port = strtonum(dash, 0, 65535, &errstr);
|
|
if (errstr != NULL)
|
|
errx(1, "high port is %s: %s", errstr, dash);
|
|
if (*high_port < *port)
|
|
errx(1, "high port %d is lower than %d",
|
|
*high_port, *port);
|
|
} else
|
|
*high_port = *port;
|
|
}
|
|
|
|
void
|
|
parse_baddynamic(int mib[], size_t len, char *string, void **newvalp,
|
|
size_t *newsizep, int flags, int nflag)
|
|
{
|
|
static u_int32_t newbaddynamic[DP_MAPSIZE];
|
|
int port, high_port, baddynamic_loaded = 0, full_list_set = 0;
|
|
size_t size;
|
|
char action, *cp;
|
|
|
|
while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) {
|
|
if (*cp == '+' || *cp == '-') {
|
|
if (full_list_set)
|
|
errx(1, "cannot mix +/- with full list");
|
|
action = *cp++;
|
|
if (!baddynamic_loaded) {
|
|
size = sizeof(newbaddynamic);
|
|
if (sysctl(mib, len, newbaddynamic,
|
|
&size, 0, 0) == -1) {
|
|
if (flags == 0)
|
|
return;
|
|
if (!nflag)
|
|
printf("%s: ", string);
|
|
puts("kernel does not contain bad "
|
|
"dynamic port tables");
|
|
return;
|
|
}
|
|
baddynamic_loaded = 1;
|
|
}
|
|
parse_ports(cp, &port, &high_port);
|
|
for (; port <= high_port; port++) {
|
|
if (action == '+')
|
|
DP_SET(newbaddynamic, port);
|
|
else
|
|
DP_CLR(newbaddynamic, port);
|
|
}
|
|
} else {
|
|
if (baddynamic_loaded)
|
|
errx(1, "cannot mix +/- with full list");
|
|
if (!full_list_set) {
|
|
bzero(newbaddynamic, sizeof(newbaddynamic));
|
|
full_list_set = 1;
|
|
}
|
|
parse_ports(cp, &port, &high_port);
|
|
for (; port <= high_port; port++)
|
|
DP_SET(newbaddynamic, port);
|
|
}
|
|
}
|
|
*newvalp = (void *)newbaddynamic;
|
|
*newsizep = sizeof(newbaddynamic);
|
|
}
|
|
|
|
/*
|
|
* Initialize the set of debugging names
|
|
*/
|
|
void
|
|
debuginit(void)
|
|
{
|
|
int mib[3], loc, i;
|
|
size_t size;
|
|
|
|
if (secondlevel[CTL_DEBUG].list != 0)
|
|
return;
|
|
secondlevel[CTL_DEBUG].list = debugname;
|
|
mib[0] = CTL_DEBUG;
|
|
mib[2] = CTL_DEBUG_NAME;
|
|
for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) {
|
|
mib[1] = i;
|
|
size = BUFSIZ - loc;
|
|
if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
|
|
continue;
|
|
debugname[i].ctl_name = &names[loc];
|
|
debugname[i].ctl_type = CTLTYPE_INT;
|
|
loc += size;
|
|
}
|
|
lastused = loc;
|
|
}
|
|
|
|
struct ctlname vfsgennames[] = CTL_VFSGENCTL_NAMES;
|
|
struct ctlname ffsname[] = FFS_NAMES;
|
|
struct ctlname nfsname[] = FS_NFS_NAMES;
|
|
struct ctlname fusefsname[] = FUSEFS_NAMES;
|
|
struct list *vfsvars;
|
|
int *vfs_typenums;
|
|
|
|
/*
|
|
* Initialize the set of filesystem names
|
|
*/
|
|
void
|
|
vfsinit(void)
|
|
{
|
|
int mib[4], maxtypenum, cnt, loc, size;
|
|
struct vfsconf vfc;
|
|
size_t buflen;
|
|
|
|
if (secondlevel[CTL_VFS].list != 0)
|
|
return;
|
|
mib[0] = CTL_VFS;
|
|
mib[1] = VFS_GENERIC;
|
|
mib[2] = VFS_MAXTYPENUM;
|
|
buflen = 4;
|
|
if (sysctl(mib, 3, &maxtypenum, &buflen, NULL, 0) == -1)
|
|
return;
|
|
/*
|
|
* We need to do 0..maxtypenum so add one, and then we offset them
|
|
* all by (another) one by inserting VFS_GENERIC entries at zero
|
|
*/
|
|
maxtypenum += 2;
|
|
if ((vfs_typenums = calloc(maxtypenum, sizeof(int))) == NULL)
|
|
return;
|
|
if ((vfsvars = calloc(maxtypenum, sizeof(*vfsvars))) == NULL) {
|
|
free(vfs_typenums);
|
|
return;
|
|
}
|
|
if ((vfsname = calloc(maxtypenum, sizeof(*vfsname))) == NULL) {
|
|
free(vfs_typenums);
|
|
free(vfsvars);
|
|
return;
|
|
}
|
|
mib[2] = VFS_CONF;
|
|
buflen = sizeof vfc;
|
|
for (loc = lastused, cnt = 1; cnt < maxtypenum; cnt++) {
|
|
mib[3] = cnt - 1;
|
|
if (sysctl(mib, 4, &vfc, &buflen, NULL, 0) == -1) {
|
|
if (errno == EOPNOTSUPP)
|
|
continue;
|
|
warn("vfsinit");
|
|
free(vfsname);
|
|
free(vfsvars);
|
|
free(vfs_typenums);
|
|
return;
|
|
}
|
|
if (!strcmp(vfc.vfc_name, MOUNT_FFS)) {
|
|
vfsvars[cnt].list = ffsname;
|
|
vfsvars[cnt].size = FFS_MAXID;
|
|
}
|
|
if (!strcmp(vfc.vfc_name, MOUNT_NFS)) {
|
|
vfsvars[cnt].list = nfsname;
|
|
vfsvars[cnt].size = NFS_MAXID;
|
|
}
|
|
if (!strcmp(vfc.vfc_name, MOUNT_FUSEFS)) {
|
|
vfsvars[cnt].list = fusefsname;
|
|
vfsvars[cnt].size = FUSEFS_MAXID;
|
|
}
|
|
vfs_typenums[cnt] = vfc.vfc_typenum;
|
|
strlcat(&names[loc], vfc.vfc_name, sizeof names - loc);
|
|
vfsname[cnt].ctl_name = &names[loc];
|
|
vfsname[cnt].ctl_type = CTLTYPE_NODE;
|
|
size = strlen(vfc.vfc_name) + 1;
|
|
loc += size;
|
|
}
|
|
lastused = loc;
|
|
|
|
vfsname[0].ctl_name = "mounts";
|
|
vfsname[0].ctl_type = CTLTYPE_NODE;
|
|
vfsvars[0].list = vfsname + 1;
|
|
vfsvars[0].size = maxtypenum - 1;
|
|
|
|
secondlevel[CTL_VFS].list = vfsname;
|
|
secondlevel[CTL_VFS].size = maxtypenum;
|
|
return;
|
|
}
|
|
|
|
int
|
|
sysctl_vfsgen(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
int indx;
|
|
size_t size;
|
|
struct vfsconf vfc;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, vfsvars);
|
|
return (-1);
|
|
}
|
|
|
|
if ((indx = findname(string, "third", bufpp, vfsvars)) == -1)
|
|
return (-1);
|
|
|
|
mib[1] = VFS_GENERIC;
|
|
mib[2] = VFS_CONF;
|
|
mib[3] = indx;
|
|
size = sizeof vfc;
|
|
if (sysctl(mib, 4, &vfc, &size, NULL, 0) == -1) {
|
|
if (errno != EOPNOTSUPP)
|
|
warn("vfs print");
|
|
return -1;
|
|
}
|
|
if (flags == 0 && vfc.vfc_refcount == 0)
|
|
return -1;
|
|
if (!nflag)
|
|
fprintf(stdout, "%s has %u mounted instance%s\n",
|
|
string, vfc.vfc_refcount,
|
|
vfc.vfc_refcount != 1 ? "s" : "");
|
|
else
|
|
fprintf(stdout, "%u\n", vfc.vfc_refcount);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int
|
|
sysctl_vfs(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
struct list *lp = &vfsvars[mib[1]];
|
|
int indx;
|
|
|
|
if (lp->list == NULL) {
|
|
if (flags)
|
|
warnx("No variables defined for file system %s", string);
|
|
return (-1);
|
|
}
|
|
if (*bufpp == NULL) {
|
|
listall(string, lp);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, lp)) == -1)
|
|
return (-1);
|
|
|
|
mib[1] = vfs_typenums[mib[1]];
|
|
mib[2] = indx;
|
|
*typep = lp->list[indx].ctl_type;
|
|
return (3);
|
|
}
|
|
|
|
struct ctlname posixname[] = CTL_FS_POSIX_NAMES;
|
|
struct list fslist = { posixname, FS_POSIX_MAXID };
|
|
|
|
/*
|
|
* handle file system requests
|
|
*/
|
|
int
|
|
sysctl_fs(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
int indx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &fslist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &fslist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
*typep = fslist.list[indx].ctl_type;
|
|
return (3);
|
|
}
|
|
|
|
#ifdef CPU_BIOS
|
|
struct ctlname biosname[] = CTL_BIOS_NAMES;
|
|
struct list bioslist = { biosname, BIOS_MAXID };
|
|
|
|
/*
|
|
* handle BIOS requests
|
|
*/
|
|
int
|
|
sysctl_bios(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
char *name;
|
|
int indx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &bioslist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &bioslist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
if (indx == BIOS_DISKINFO) {
|
|
const char *errstr;
|
|
|
|
if (*bufpp == NULL) {
|
|
char name[BUFSIZ];
|
|
|
|
/* scan all the bios devices */
|
|
for (indx = 0; indx < 256; indx++) {
|
|
snprintf(name, sizeof(name), "%s.%u",
|
|
string, indx);
|
|
parse(name, 1);
|
|
}
|
|
return (-1);
|
|
}
|
|
if ((name = strsep(bufpp, ".")) == NULL) {
|
|
warnx("%s: incomplete specification", string);
|
|
return (-1);
|
|
}
|
|
mib[3] = strtonum(name, 0, INT_MAX, &errstr);
|
|
if (errstr) {
|
|
warnx("%s: %s", string, errstr);
|
|
return (-1);
|
|
}
|
|
*typep = CTLTYPE_STRUCT;
|
|
return (4);
|
|
} else {
|
|
*typep = bioslist.list[indx].ctl_type;
|
|
return (3);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
struct ctlname swpencname[] = CTL_SWPENC_NAMES;
|
|
struct list swpenclist = { swpencname, SWPENC_MAXID };
|
|
|
|
/*
|
|
* handle swap encrypt requests
|
|
*/
|
|
int
|
|
sysctl_swpenc(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
int indx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &swpenclist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &swpenclist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
*typep = swpenclist.list[indx].ctl_type;
|
|
return (3);
|
|
}
|
|
|
|
struct ctlname inetname[] = CTL_IPPROTO_NAMES;
|
|
struct ctlname ipname[] = IPCTL_NAMES;
|
|
struct ctlname icmpname[] = ICMPCTL_NAMES;
|
|
struct ctlname igmpname[] = IGMPCTL_NAMES;
|
|
struct ctlname ipipname[] = IPIPCTL_NAMES;
|
|
struct ctlname tcpname[] = TCPCTL_NAMES;
|
|
struct ctlname udpname[] = UDPCTL_NAMES;
|
|
struct ctlname espname[] = ESPCTL_NAMES;
|
|
struct ctlname ahname[] = AHCTL_NAMES;
|
|
struct ctlname etheripname[] = ETHERIPCTL_NAMES;
|
|
struct ctlname grename[] = GRECTL_NAMES;
|
|
struct ctlname ipcompname[] = IPCOMPCTL_NAMES;
|
|
struct ctlname carpname[] = CARPCTL_NAMES;
|
|
struct ctlname pfsyncname[] = PFSYNCCTL_NAMES;
|
|
struct ctlname divertname[] = DIVERTCTL_NAMES;
|
|
struct ctlname bpfname[] = CTL_NET_BPF_NAMES;
|
|
struct ctlname ifqname[] = CTL_IFQ_NAMES;
|
|
struct ctlname pipexname[] = PIPEXCTL_NAMES;
|
|
struct list inetlist = { inetname, IPPROTO_MAXID };
|
|
struct list inetvars[] = {
|
|
{ ipname, IPCTL_MAXID }, /* ip */
|
|
{ icmpname, ICMPCTL_MAXID }, /* icmp */
|
|
{ igmpname, IGMPCTL_MAXID }, /* igmp */
|
|
{ 0, 0 }, /* ggmp */
|
|
{ ipipname, IPIPCTL_MAXID }, /* ipencap */
|
|
{ 0, 0 },
|
|
{ tcpname, TCPCTL_MAXID }, /* tcp */
|
|
{ 0, 0 },
|
|
{ 0, 0 }, /* egp */
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 }, /* pup */
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ udpname, UDPCTL_MAXID }, /* udp */
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ grename, GRECTL_MAXID }, /* gre */
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ espname, ESPCTL_MAXID }, /* esp */
|
|
{ ahname, AHCTL_MAXID }, /* ah */
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ etheripname, ETHERIPCTL_MAXID },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ ipcompname, IPCOMPCTL_MAXID },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ carpname, CARPCTL_MAXID },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ pfsyncname, PFSYNCCTL_MAXID },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ divertname, DIVERTCTL_MAXID },
|
|
};
|
|
struct list bpflist = { bpfname, NET_BPF_MAXID };
|
|
struct list ifqlist = { ifqname, IFQCTL_MAXID };
|
|
struct list pipexlist = { pipexname, PIPEXCTL_MAXID };
|
|
|
|
struct list kernmalloclist = { kernmallocname, KERN_MALLOC_MAXID };
|
|
struct list forkstatlist = { forkstatname, KERN_FORKSTAT_MAXID };
|
|
struct list nchstatslist = { nchstatsname, KERN_NCHSTATS_MAXID };
|
|
struct list ttylist = { ttysname, KERN_TTY_MAXID };
|
|
struct list semlist = { semname, KERN_SEMINFO_MAXID };
|
|
struct list shmlist = { shmname, KERN_SHMINFO_MAXID };
|
|
struct list watchdoglist = { watchdogname, KERN_WATCHDOG_MAXID };
|
|
struct list tclist = { tcname, KERN_TIMECOUNTER_MAXID };
|
|
struct list audiolist = { audioname, KERN_AUDIO_MAXID };
|
|
struct list videolist = { videoname, KERN_VIDEO_MAXID };
|
|
struct list witnesslist = { witnessname, KERN_WITNESS_MAXID };
|
|
struct list batterylist = { batteryname, HW_BATTERY_MAXID };
|
|
|
|
/*
|
|
* handle vfs namei cache statistics
|
|
*/
|
|
int
|
|
sysctl_nchstats(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
static struct nchstats nch;
|
|
int indx;
|
|
size_t size;
|
|
static int keepvalue = 0;
|
|
|
|
if (*bufpp == NULL) {
|
|
bzero(&nch, sizeof(struct nchstats));
|
|
listall(string, &nchstatslist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &nchstatslist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
if (*bufpp != NULL) {
|
|
warnx("fourth level name in %s is invalid", string);
|
|
return (-1);
|
|
}
|
|
if (keepvalue == 0) {
|
|
size = sizeof(struct nchstats);
|
|
if (sysctl(mib, 2, &nch, &size, NULL, 0) == -1)
|
|
return (-1);
|
|
keepvalue = 1;
|
|
}
|
|
if (!nflag)
|
|
(void)printf("%s%s", string, equ);
|
|
switch (indx) {
|
|
case KERN_NCHSTATS_GOODHITS:
|
|
(void)printf("%llu\n", nch.ncs_goodhits);
|
|
break;
|
|
case KERN_NCHSTATS_NEGHITS:
|
|
(void)printf("%llu\n", nch.ncs_neghits);
|
|
break;
|
|
case KERN_NCHSTATS_BADHITS:
|
|
(void)printf("%llu\n", nch.ncs_badhits);
|
|
break;
|
|
case KERN_NCHSTATS_FALSEHITS:
|
|
(void)printf("%llu\n", nch.ncs_falsehits);
|
|
break;
|
|
case KERN_NCHSTATS_MISS:
|
|
(void)printf("%llu\n", nch.ncs_miss);
|
|
break;
|
|
case KERN_NCHSTATS_LONG:
|
|
(void)printf("%llu\n", nch.ncs_long);
|
|
break;
|
|
case KERN_NCHSTATS_PASS2:
|
|
(void)printf("%llu\n", nch.ncs_pass2);
|
|
break;
|
|
case KERN_NCHSTATS_2PASSES:
|
|
(void)printf("%llu\n", nch.ncs_2passes);
|
|
break;
|
|
case KERN_NCHSTATS_REVHITS:
|
|
(void)printf("%llu\n", nch.ncs_revhits);
|
|
break;
|
|
case KERN_NCHSTATS_REVMISS:
|
|
(void)printf("%llu\n", nch.ncs_revmiss);
|
|
break;
|
|
case KERN_NCHSTATS_DOTHITS:
|
|
(void)printf("%llu\n", nch.ncs_dothits);
|
|
break;
|
|
case KERN_NCHSTATS_DOTDOTHITS:
|
|
(void)printf("%llu\n", nch.ncs_dotdothits);
|
|
break;
|
|
}
|
|
return (-1);
|
|
}
|
|
|
|
/*
|
|
* handle tty statistics
|
|
*/
|
|
int
|
|
sysctl_tty(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
int indx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &ttylist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &ttylist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
|
|
if ((*typep = ttylist.list[indx].ctl_type) == CTLTYPE_STRUCT) {
|
|
if (flags)
|
|
warnx("use pstat -t to view %s information",
|
|
string);
|
|
return (-1);
|
|
}
|
|
return (3);
|
|
}
|
|
|
|
/*
|
|
* handle fork statistics
|
|
*/
|
|
int
|
|
sysctl_forkstat(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
static struct forkstat fks;
|
|
static int keepvalue = 0;
|
|
int indx;
|
|
size_t size;
|
|
|
|
if (*bufpp == NULL) {
|
|
bzero(&fks, sizeof(struct forkstat));
|
|
listall(string, &forkstatlist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &forkstatlist)) == -1)
|
|
return (-1);
|
|
if (*bufpp != NULL) {
|
|
warnx("fourth level name in %s is invalid", string);
|
|
return (-1);
|
|
}
|
|
if (keepvalue == 0) {
|
|
size = sizeof(struct forkstat);
|
|
if (sysctl(mib, 2, &fks, &size, NULL, 0) == -1)
|
|
return (-1);
|
|
keepvalue = 1;
|
|
}
|
|
if (!nflag)
|
|
(void)printf("%s%s", string, equ);
|
|
switch (indx) {
|
|
case KERN_FORKSTAT_FORK:
|
|
(void)printf("%u\n", fks.cntfork);
|
|
break;
|
|
case KERN_FORKSTAT_VFORK:
|
|
(void)printf("%u\n", fks.cntvfork);
|
|
break;
|
|
case KERN_FORKSTAT_TFORK:
|
|
(void)printf("%u\n", fks.cnttfork);
|
|
break;
|
|
case KERN_FORKSTAT_KTHREAD:
|
|
(void)printf("%u\n", fks.cntkthread);
|
|
break;
|
|
case KERN_FORKSTAT_SIZFORK:
|
|
(void)printf("%llu\n", fks.sizfork);
|
|
break;
|
|
case KERN_FORKSTAT_SIZVFORK:
|
|
(void)printf("%llu\n", fks.sizvfork);
|
|
break;
|
|
case KERN_FORKSTAT_SIZTFORK:
|
|
(void)printf("%llu\n", fks.siztfork);
|
|
break;
|
|
case KERN_FORKSTAT_SIZKTHREAD:
|
|
(void)printf("%llu\n", fks.sizkthread);
|
|
break;
|
|
}
|
|
return (-1);
|
|
}
|
|
|
|
/*
|
|
* handle malloc statistics
|
|
*/
|
|
int
|
|
sysctl_malloc(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
int indx, stor, i;
|
|
char *name, bufp[SYSCTL_BUFSIZ], *buf, *ptr;
|
|
const char *errstr;
|
|
struct list lp;
|
|
size_t size;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &kernmalloclist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &kernmalloclist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
if (mib[2] == KERN_MALLOC_BUCKET) {
|
|
if ((name = strsep(bufpp, ".")) == NULL) {
|
|
size = SYSCTL_BUFSIZ;
|
|
stor = mib[2];
|
|
mib[2] = KERN_MALLOC_BUCKETS;
|
|
buf = bufp;
|
|
if (sysctl(mib, 3, buf, &size, NULL, 0) == -1)
|
|
return (-1);
|
|
mib[2] = stor;
|
|
for (stor = 0, i = 0; i < size; i++)
|
|
if (buf[i] == ',')
|
|
stor++;
|
|
lp.list = calloc(stor + 2, sizeof(struct ctlname));
|
|
if (lp.list == NULL)
|
|
return (-1);
|
|
lp.size = stor + 2;
|
|
for (i = 1; (ptr = strsep(&buf, ",")) != NULL; i++) {
|
|
lp.list[i].ctl_name = ptr;
|
|
lp.list[i].ctl_type = CTLTYPE_STRUCT;
|
|
}
|
|
listall(string, &lp);
|
|
free(lp.list);
|
|
return (-1);
|
|
}
|
|
mib[3] = strtonum(name, 0, INT_MAX, &errstr);
|
|
if (errstr)
|
|
return -1;
|
|
return (4);
|
|
} else if (mib[2] == KERN_MALLOC_BUCKETS) {
|
|
*typep = CTLTYPE_STRING;
|
|
return (3);
|
|
} else if (mib[2] == KERN_MALLOC_KMEMSTATS) {
|
|
size = SYSCTL_BUFSIZ;
|
|
stor = mib[2];
|
|
mib[2] = KERN_MALLOC_KMEMNAMES;
|
|
buf = bufp;
|
|
if (sysctl(mib, 3, buf, &size, NULL, 0) == -1)
|
|
return (-1);
|
|
mib[2] = stor;
|
|
if ((name = strsep(bufpp, ".")) == NULL) {
|
|
for (stor = 0, i = 0; i < size; i++)
|
|
if (buf[i] == ',')
|
|
stor++;
|
|
lp.list = calloc(stor + 2, sizeof(struct ctlname));
|
|
if (lp.list == NULL)
|
|
return (-1);
|
|
lp.size = stor + 2;
|
|
for (i = 1; (ptr = strsep(&buf, ",")) != NULL; i++) {
|
|
if (ptr[0] == '\0') {
|
|
i--;
|
|
continue;
|
|
}
|
|
lp.list[i].ctl_name = ptr;
|
|
lp.list[i].ctl_type = CTLTYPE_STRUCT;
|
|
}
|
|
listall(string, &lp);
|
|
free(lp.list);
|
|
return (-1);
|
|
}
|
|
ptr = strstr(buf, name);
|
|
tryagain:
|
|
if (ptr == NULL) {
|
|
warnx("fourth level name %s in %s is invalid", name,
|
|
string);
|
|
return (-1);
|
|
}
|
|
if ((*(ptr + strlen(name)) != ',') &&
|
|
(*(ptr + strlen(name)) != '\0')) {
|
|
ptr = strstr(ptr + 1, name); /* retry */
|
|
goto tryagain;
|
|
}
|
|
if ((ptr != buf) && (*(ptr - 1) != ',')) {
|
|
ptr = strstr(ptr + 1, name); /* retry */
|
|
goto tryagain;
|
|
}
|
|
for (i = 0, stor = 0; buf + i < ptr; i++)
|
|
if (buf[i] == ',')
|
|
stor++;
|
|
mib[3] = stor;
|
|
return (4);
|
|
} else if (mib[2] == KERN_MALLOC_KMEMNAMES) {
|
|
*typep = CTLTYPE_STRING;
|
|
return (3);
|
|
}
|
|
return (-1);
|
|
}
|
|
|
|
#ifdef CPU_CHIPSET
|
|
/*
|
|
* handle machdep.chipset requests
|
|
*/
|
|
struct ctlname chipsetname[] = CTL_CHIPSET_NAMES;
|
|
struct list chipsetlist = { chipsetname, CPU_CHIPSET_MAXID };
|
|
|
|
int
|
|
sysctl_chipset(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
int indx, bwx;
|
|
static void *q;
|
|
size_t len;
|
|
char *p;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &chipsetlist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &chipsetlist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
if (!nflag)
|
|
printf("%s%s", string, equ);
|
|
switch(mib[2]) {
|
|
case CPU_CHIPSET_MEM:
|
|
case CPU_CHIPSET_DENSE:
|
|
case CPU_CHIPSET_PORTS:
|
|
case CPU_CHIPSET_HAE_MASK:
|
|
len = sizeof(void *);
|
|
if (sysctl(mib, 3, &q, &len, NULL, 0) == -1)
|
|
goto done;
|
|
printf("%p", q);
|
|
break;
|
|
case CPU_CHIPSET_BWX:
|
|
len = sizeof(int);
|
|
if (sysctl(mib, 3, &bwx, &len, NULL, 0) == -1)
|
|
goto done;
|
|
printf("%d", bwx);
|
|
break;
|
|
case CPU_CHIPSET_TYPE:
|
|
if (sysctl(mib, 3, NULL, &len, NULL, 0) == -1)
|
|
goto done;
|
|
p = malloc(len + 1);
|
|
if (p == NULL)
|
|
goto done;
|
|
if (sysctl(mib, 3, p, &len, NULL, 0) == -1) {
|
|
free(p);
|
|
goto done;
|
|
}
|
|
p[len] = '\0';
|
|
printf("%s", p);
|
|
free(p);
|
|
break;
|
|
}
|
|
done:
|
|
printf("\n");
|
|
return (-1);
|
|
}
|
|
#endif
|
|
/*
|
|
* handle internet requests
|
|
*/
|
|
int
|
|
sysctl_inet(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
struct list *lp;
|
|
int indx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &inetlist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
if (indx < IPPROTO_MAXID && inetvars[indx].list != NULL)
|
|
lp = &inetvars[indx];
|
|
else if (!flags)
|
|
return (-1);
|
|
else {
|
|
warnx("%s: no variables defined for this protocol", string);
|
|
return (-1);
|
|
}
|
|
if (*bufpp == NULL) {
|
|
listall(string, lp);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
|
|
return (-1);
|
|
mib[3] = indx;
|
|
*typep = lp->list[indx].ctl_type;
|
|
if (*typep == CTLTYPE_NODE) {
|
|
int tindx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &ifqlist);
|
|
return(-1);
|
|
}
|
|
lp = &ifqlist;
|
|
if ((tindx = findname(string, "fifth", bufpp, lp)) == -1)
|
|
return (-1);
|
|
mib[4] = tindx;
|
|
*typep = lp->list[tindx].ctl_type;
|
|
return(5);
|
|
}
|
|
return (4);
|
|
}
|
|
|
|
struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES;
|
|
struct ctlname ip6name[] = IPV6CTL_NAMES;
|
|
struct ctlname icmp6name[] = ICMPV6CTL_NAMES;
|
|
struct ctlname divert6name[] = DIVERT6CTL_NAMES;
|
|
struct list inet6list = { inet6name, IPV6PROTO_MAXID };
|
|
struct list inet6vars[] = {
|
|
/*0*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
/*10*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*20*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*30*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*40*/ { 0, 0 },
|
|
{ ip6name, IPV6CTL_MAXID }, /* ipv6 */
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*50*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ icmp6name, ICMPV6CTL_MAXID }, /* icmp6 */
|
|
{ 0, 0 },
|
|
/*60*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*70*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*80*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*90*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*100*/ { 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 }, /* pim6 */
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
/*110*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*120*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*130*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*140*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*150*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*160*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*170*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*180*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*190*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*200*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*210*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*220*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*230*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*240*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
/*250*/ { 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ 0, 0 },
|
|
{ divert6name, DIVERT6CTL_MAXID },
|
|
};
|
|
|
|
/*
|
|
* handle internet6 requests
|
|
*/
|
|
int
|
|
sysctl_inet6(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
struct list *lp;
|
|
int indx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &inet6list);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &inet6list)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
if (indx < IPV6PROTO_MAXID && inet6vars[indx].list != NULL)
|
|
lp = &inet6vars[indx];
|
|
else if (!flags)
|
|
return (-1);
|
|
else {
|
|
warnx("%s: no variables defined for this protocol", string);
|
|
return (-1);
|
|
}
|
|
if (*bufpp == NULL) {
|
|
listall(string, lp);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
|
|
return (-1);
|
|
mib[3] = indx;
|
|
*typep = lp->list[indx].ctl_type;
|
|
if (*typep == CTLTYPE_NODE) {
|
|
int tindx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &ifqlist);
|
|
return(-1);
|
|
}
|
|
lp = &ifqlist;
|
|
if ((tindx = findname(string, "fifth", bufpp, lp)) == -1)
|
|
return (-1);
|
|
mib[4] = tindx;
|
|
*typep = lp->list[tindx].ctl_type;
|
|
return(5);
|
|
}
|
|
return (4);
|
|
}
|
|
|
|
/* handle net.unix requests */
|
|
struct ctlname netunixname[] = CTL_NET_UNIX_NAMES;
|
|
struct ctlname netunixprotoname[] = CTL_NET_UNIX_PROTO_NAMES;
|
|
struct list netunixlist = { netunixname, NET_UNIX_MAXID };
|
|
struct list netunixvars[] = {
|
|
[SOCK_STREAM] = { netunixprotoname, NET_UNIX_PROTO_MAXID },
|
|
[SOCK_DGRAM] = { netunixprotoname, NET_UNIX_PROTO_MAXID },
|
|
[SOCK_SEQPACKET] = { netunixprotoname, NET_UNIX_PROTO_MAXID },
|
|
[NET_UNIX_MAXID] = { 0, 0 },
|
|
};
|
|
|
|
int
|
|
sysctl_unix(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
struct list *lp;
|
|
int indx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &netunixlist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &netunixlist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
*typep = netunixname[indx].ctl_type;
|
|
|
|
if (indx < NET_UNIX_MAXID && netunixvars[indx].list != NULL)
|
|
lp = &netunixvars[indx];
|
|
else
|
|
return (3);
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, lp);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
|
|
return (-1);
|
|
mib[3] = indx;
|
|
*typep = lp->list[indx].ctl_type;
|
|
return (4);
|
|
}
|
|
|
|
/* handle net.link requests */
|
|
struct ctlname netlinkname[] = CTL_NET_LINK_NAMES;
|
|
struct ctlname ifrxqname[] = CTL_NET_LINK_IFRXQ_NAMES;
|
|
struct list netlinklist = { netlinkname, NET_LINK_MAXID };
|
|
struct list netlinkvars[] = {
|
|
[NET_LINK_IFRXQ] = { ifrxqname, NET_LINK_IFRXQ_MAXID },
|
|
};
|
|
|
|
int
|
|
sysctl_link(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
struct list *lp;
|
|
int indx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &netlinklist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &netlinklist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
if (indx < NET_LINK_MAXID && netlinkvars[indx].list != NULL)
|
|
lp = &netlinkvars[indx];
|
|
else if (!flags)
|
|
return (-1);
|
|
else {
|
|
warnx("%s: no variables defined for this protocol", string);
|
|
return (-1);
|
|
}
|
|
if (*bufpp == NULL) {
|
|
listall(string, lp);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
|
|
return (-1);
|
|
mib[3] = indx;
|
|
*typep = lp->list[indx].ctl_type;
|
|
return (4);
|
|
}
|
|
|
|
/* handle bpf requests */
|
|
int
|
|
sysctl_bpf(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
int indx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &bpflist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &bpflist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
*typep = CTLTYPE_INT;
|
|
return (3);
|
|
}
|
|
|
|
struct ctlname mplsname[] = MPLSCTL_NAMES;
|
|
struct list mplslist = { mplsname, MPLSCTL_MAXID };
|
|
|
|
/* handle MPLS requests */
|
|
int
|
|
sysctl_mpls(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
struct list *lp;
|
|
int indx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &mplslist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &mplslist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
*typep = mplslist.list[indx].ctl_type;
|
|
if (*typep == CTLTYPE_NODE) {
|
|
int tindx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &ifqlist);
|
|
return(-1);
|
|
}
|
|
lp = &ifqlist;
|
|
if ((tindx = findname(string, "fourth", bufpp, lp)) == -1)
|
|
return (-1);
|
|
mib[3] = tindx;
|
|
*typep = lp->list[tindx].ctl_type;
|
|
return(4);
|
|
}
|
|
return (3);
|
|
}
|
|
|
|
/* handle PIPEX requests */
|
|
int
|
|
sysctl_pipex(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
struct list *lp;
|
|
int indx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &pipexlist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &pipexlist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
*typep = pipexlist.list[indx].ctl_type;
|
|
if (*typep == CTLTYPE_NODE) {
|
|
int tindx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &ifqlist);
|
|
return(-1);
|
|
}
|
|
lp = &ifqlist;
|
|
if ((tindx = findname(string, "fourth", bufpp, lp)) == -1)
|
|
return (-1);
|
|
mib[3] = tindx;
|
|
*typep = lp->list[tindx].ctl_type;
|
|
return(4);
|
|
}
|
|
return (3);
|
|
}
|
|
|
|
/*
|
|
* Handle SysV semaphore info requests
|
|
*/
|
|
int
|
|
sysctl_seminfo(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
int indx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &semlist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &semlist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
*typep = CTLTYPE_INT;
|
|
return (3);
|
|
}
|
|
|
|
/*
|
|
* Handle SysV shared memory info requests
|
|
*/
|
|
int
|
|
sysctl_shminfo(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
int indx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &shmlist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &shmlist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
*typep = CTLTYPE_INT;
|
|
return (3);
|
|
}
|
|
|
|
/*
|
|
* Handle watchdog support
|
|
*/
|
|
int
|
|
sysctl_watchdog(char *string, char **bufpp, int mib[], int flags,
|
|
int *typep)
|
|
{
|
|
int indx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &watchdoglist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &watchdoglist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
*typep = watchdoglist.list[indx].ctl_type;
|
|
return (3);
|
|
}
|
|
|
|
/*
|
|
* Handle timecounter support
|
|
*/
|
|
int
|
|
sysctl_tc(char *string, char **bufpp, int mib[], int flags,
|
|
int *typep)
|
|
{
|
|
int indx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &tclist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &tclist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
*typep = tclist.list[indx].ctl_type;
|
|
return (3);
|
|
}
|
|
|
|
/*
|
|
* Handle hardware monitoring sensors support
|
|
*/
|
|
int
|
|
sysctl_sensors(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
char *devname, *typename;
|
|
int dev, numt, i;
|
|
enum sensor_type type;
|
|
struct sensordev snsrdev;
|
|
size_t sdlen = sizeof(snsrdev);
|
|
|
|
if (*bufpp == NULL) {
|
|
char buf[SYSCTL_BUFSIZ];
|
|
|
|
/* scan all sensor devices */
|
|
for (dev = 0; ; dev++) {
|
|
mib[2] = dev;
|
|
if (sysctl(mib, 3, &snsrdev, &sdlen, NULL, 0) == -1) {
|
|
if (errno == ENXIO)
|
|
continue;
|
|
if (errno == ENOENT)
|
|
break;
|
|
warn("sensors dev %d", dev);
|
|
return (-1);
|
|
}
|
|
snprintf(buf, sizeof(buf), "%s.%s",
|
|
string, snsrdev.xname);
|
|
print_sensordev(buf, mib, 3, &snsrdev);
|
|
}
|
|
return (-1);
|
|
}
|
|
|
|
/*
|
|
* If we get this far, it means that some arguments were
|
|
* provided below hw.sensors tree.
|
|
* The first branch of hw.sensors tree is the device name.
|
|
*/
|
|
if ((devname = strsep(bufpp, ".")) == NULL) {
|
|
warnx("%s: incomplete specification", string);
|
|
return (-1);
|
|
}
|
|
/* convert sensor device string to an integer */
|
|
for (dev = 0; ; dev++) {
|
|
mib[2] = dev;
|
|
if (sysctl(mib, 3, &snsrdev, &sdlen, NULL, 0) == -1) {
|
|
if (errno == ENXIO)
|
|
continue;
|
|
if (errno == ENOENT)
|
|
break;
|
|
warn("sensors dev %d", dev);
|
|
return (-1);
|
|
}
|
|
if (strcmp(devname, snsrdev.xname) == 0)
|
|
break;
|
|
}
|
|
if (strcmp(devname, snsrdev.xname) != 0) {
|
|
warnx("%s: sensor device not found: %s", string, devname);
|
|
return (-1);
|
|
}
|
|
if (*bufpp == NULL) {
|
|
/* only device name was provided -- let's print all sensors
|
|
* that are attached to the specified device
|
|
*/
|
|
print_sensordev(string, mib, 3, &snsrdev);
|
|
return (-1);
|
|
}
|
|
|
|
/*
|
|
* At this point we have identified the sensor device,
|
|
* now let's go further and identify sensor type.
|
|
*/
|
|
if ((typename = strsep(bufpp, ".")) == NULL) {
|
|
warnx("%s: incomplete specification", string);
|
|
return (-1);
|
|
}
|
|
numt = -1;
|
|
for (i = 0; typename[i] != '\0'; i++)
|
|
if (isdigit((unsigned char)typename[i])) {
|
|
const char *errstr;
|
|
|
|
numt = strtonum(&typename[i], 0, INT_MAX, &errstr);
|
|
if (errstr) {
|
|
warnx("%s: %s", string, errstr);
|
|
return (-1);
|
|
}
|
|
typename[i] = '\0';
|
|
break;
|
|
}
|
|
for (type = 0; type < SENSOR_MAX_TYPES; type++)
|
|
if (strcmp(typename, sensor_type_s[type]) == 0)
|
|
break;
|
|
if (type == SENSOR_MAX_TYPES) {
|
|
warnx("%s: sensor type not recognised: %s", string, typename);
|
|
return (-1);
|
|
}
|
|
mib[3] = type;
|
|
|
|
/*
|
|
* If no integer was provided after sensor_type, let's
|
|
* print all sensors of the specified type.
|
|
*/
|
|
if (numt == -1) {
|
|
print_sensordev(string, mib, 4, &snsrdev);
|
|
return (-1);
|
|
}
|
|
|
|
/*
|
|
* At this point we know that we have received a direct request
|
|
* via command-line for a specific sensor. Let's have the parse()
|
|
* function deal with it further, and report any errors if such
|
|
* sensor node does not exist.
|
|
*/
|
|
mib[4] = numt;
|
|
*typep = CTLTYPE_STRUCT;
|
|
return (5);
|
|
}
|
|
|
|
/*
|
|
* Print sensors from the specified device.
|
|
*/
|
|
|
|
void
|
|
print_sensordev(char *string, int mib[], u_int mlen, struct sensordev *snsrdev)
|
|
{
|
|
char buf[SYSCTL_BUFSIZ];
|
|
enum sensor_type type;
|
|
|
|
if (mlen == 3) {
|
|
for (type = 0; type < SENSOR_MAX_TYPES; type++) {
|
|
mib[3] = type;
|
|
snprintf(buf, sizeof(buf), "%s.%s",
|
|
string, sensor_type_s[type]);
|
|
print_sensordev(buf, mib, mlen+1, snsrdev);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (mlen == 4) {
|
|
int numt;
|
|
|
|
type = mib[3];
|
|
for (numt = 0; numt < snsrdev->maxnumt[type]; numt++) {
|
|
mib[4] = numt;
|
|
snprintf(buf, sizeof(buf), "%s%u", string, numt);
|
|
print_sensordev(buf, mib, mlen+1, snsrdev);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (mlen == 5) {
|
|
struct sensor snsr;
|
|
size_t slen = sizeof(snsr);
|
|
|
|
/* this function is only printing sensors in bulk, so we
|
|
* do not return any error messages if the requested sensor
|
|
* is not found by sysctl(3)
|
|
*/
|
|
if (sysctl(mib, 5, &snsr, &slen, NULL, 0) == -1)
|
|
return;
|
|
|
|
if (slen > 0 && (snsr.flags & SENSOR_FINVALID) == 0) {
|
|
if (!nflag)
|
|
printf("%s%s", string, equ);
|
|
print_sensor(&snsr);
|
|
printf("\n");
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
void
|
|
print_sensor(struct sensor *s)
|
|
{
|
|
const char *name;
|
|
|
|
if (s->flags & SENSOR_FUNKNOWN)
|
|
printf("unknown");
|
|
else {
|
|
switch (s->type) {
|
|
case SENSOR_TEMP:
|
|
printf("%.2f degC",
|
|
(s->value - 273150000) / 1000000.0);
|
|
break;
|
|
case SENSOR_FANRPM:
|
|
printf("%lld RPM", s->value);
|
|
break;
|
|
case SENSOR_VOLTS_DC:
|
|
printf("%.2f VDC", s->value / 1000000.0);
|
|
break;
|
|
case SENSOR_VOLTS_AC:
|
|
printf("%.2f VAC", s->value / 1000000.0);
|
|
break;
|
|
case SENSOR_OHMS:
|
|
printf("%lld ohm", s->value);
|
|
break;
|
|
case SENSOR_WATTS:
|
|
printf("%.2f W", s->value / 1000000.0);
|
|
break;
|
|
case SENSOR_AMPS:
|
|
printf("%.2f A", s->value / 1000000.0);
|
|
break;
|
|
case SENSOR_WATTHOUR:
|
|
printf("%.2f Wh", s->value / 1000000.0);
|
|
break;
|
|
case SENSOR_AMPHOUR:
|
|
printf("%.2f Ah", s->value / 1000000.0);
|
|
break;
|
|
case SENSOR_INDICATOR:
|
|
printf("%s", s->value ? "On" : "Off");
|
|
break;
|
|
case SENSOR_INTEGER:
|
|
printf("%lld", s->value);
|
|
break;
|
|
case SENSOR_PERCENT:
|
|
printf("%.2f%%", s->value / 1000.0);
|
|
break;
|
|
case SENSOR_LUX:
|
|
printf("%.2f lx", s->value / 1000000.0);
|
|
break;
|
|
case SENSOR_DRIVE:
|
|
switch (s->value) {
|
|
case SENSOR_DRIVE_EMPTY:
|
|
name = "empty";
|
|
break;
|
|
case SENSOR_DRIVE_READY:
|
|
name = "ready";
|
|
break;
|
|
case SENSOR_DRIVE_POWERUP:
|
|
name = "powering up";
|
|
break;
|
|
case SENSOR_DRIVE_ONLINE:
|
|
name = "online";
|
|
break;
|
|
case SENSOR_DRIVE_IDLE:
|
|
name = "idle";
|
|
break;
|
|
case SENSOR_DRIVE_ACTIVE:
|
|
name = "active";
|
|
break;
|
|
case SENSOR_DRIVE_REBUILD:
|
|
name = "rebuilding";
|
|
break;
|
|
case SENSOR_DRIVE_POWERDOWN:
|
|
name = "powering down";
|
|
break;
|
|
case SENSOR_DRIVE_FAIL:
|
|
name = "failed";
|
|
break;
|
|
case SENSOR_DRIVE_PFAIL:
|
|
name = "degraded";
|
|
break;
|
|
default:
|
|
name = "unknown";
|
|
break;
|
|
}
|
|
printf("%s", name);
|
|
break;
|
|
case SENSOR_TIMEDELTA:
|
|
printf("%.6f secs", s->value / 1000000000.0);
|
|
break;
|
|
case SENSOR_HUMIDITY:
|
|
printf("%.2f%%", s->value / 1000.0);
|
|
break;
|
|
case SENSOR_FREQ:
|
|
printf("%.2f Hz", s->value / 1000000.0);
|
|
break;
|
|
case SENSOR_ANGLE:
|
|
printf("%3.4f degrees", s->value / 1000000.0);
|
|
break;
|
|
case SENSOR_DISTANCE:
|
|
printf("%.3f m", s->value / 1000000.0);
|
|
break;
|
|
case SENSOR_PRESSURE:
|
|
printf("%.2f Pa", s->value / 1000.0);
|
|
break;
|
|
case SENSOR_ACCEL:
|
|
printf("%2.4f m/s^2", s->value / 1000000.0);
|
|
break;
|
|
case SENSOR_VELOCITY:
|
|
printf("%4.3f m/s", s->value / 1000000.0);
|
|
break;
|
|
case SENSOR_ENERGY:
|
|
printf("%.2f J", s->value / 1000000.0);
|
|
break;
|
|
default:
|
|
printf("unknown");
|
|
}
|
|
}
|
|
|
|
if (s->desc[0] != '\0')
|
|
printf(" (%s)", s->desc);
|
|
|
|
switch (s->status) {
|
|
case SENSOR_S_UNSPEC:
|
|
break;
|
|
case SENSOR_S_OK:
|
|
printf(", OK");
|
|
break;
|
|
case SENSOR_S_WARN:
|
|
printf(", WARNING");
|
|
break;
|
|
case SENSOR_S_CRIT:
|
|
printf(", CRITICAL");
|
|
break;
|
|
case SENSOR_S_UNKNOWN:
|
|
printf(", UNKNOWN");
|
|
break;
|
|
}
|
|
|
|
if (s->tv.tv_sec) {
|
|
time_t t = s->tv.tv_sec;
|
|
char ct[26];
|
|
|
|
if (ctime_r(&t, ct)) {
|
|
ct[19] = '\0';
|
|
printf(", %s.%03ld", ct, s->tv.tv_usec / 1000);
|
|
} else
|
|
printf(", %lld.%03ld", t, s->tv.tv_usec / 1000);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Handle audio support
|
|
*/
|
|
int
|
|
sysctl_audio(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
int indx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &audiolist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &audiolist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
*typep = audiolist.list[indx].ctl_type;
|
|
return (3);
|
|
}
|
|
|
|
/*
|
|
* Handle video support
|
|
*/
|
|
int
|
|
sysctl_video(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
int indx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &videolist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &videolist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
*typep = videolist.list[indx].ctl_type;
|
|
return (3);
|
|
}
|
|
|
|
/*
|
|
* Handle witness support
|
|
*/
|
|
int
|
|
sysctl_witness(char *string, char **bufpp, int mib[], int flags, int *typep)
|
|
{
|
|
int indx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &witnesslist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &witnesslist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
*typep = witnesslist.list[indx].ctl_type;
|
|
return (3);
|
|
}
|
|
|
|
/*
|
|
* Handle battery support
|
|
*/
|
|
int
|
|
sysctl_battery(char *string, char **bufpp, int mib[], int flags,
|
|
int *typep)
|
|
{
|
|
int indx;
|
|
|
|
if (*bufpp == NULL) {
|
|
listall(string, &batterylist);
|
|
return (-1);
|
|
}
|
|
if ((indx = findname(string, "third", bufpp, &batterylist)) == -1)
|
|
return (-1);
|
|
mib[2] = indx;
|
|
*typep = batterylist.list[indx].ctl_type;
|
|
return (3);
|
|
}
|
|
|
|
/*
|
|
* Scan a list of names searching for a particular name.
|
|
*/
|
|
int
|
|
findname(char *string, char *level, char **bufp, struct list *namelist)
|
|
{
|
|
char *name;
|
|
int i;
|
|
|
|
if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
|
|
warnx("%s: incomplete specification", string);
|
|
return (-1);
|
|
}
|
|
for (i = 0; i < namelist->size; i++)
|
|
if (namelist->list[i].ctl_name != NULL &&
|
|
strcmp(name, namelist->list[i].ctl_name) == 0)
|
|
break;
|
|
if (i == namelist->size) {
|
|
warnx("%s level name %s in %s is invalid", level, name, string);
|
|
return (-1);
|
|
}
|
|
return (i);
|
|
}
|
|
|
|
void
|
|
usage(void)
|
|
{
|
|
|
|
(void)fprintf(stderr,
|
|
"usage: sysctl [-Aanq] [name[=value]]\n");
|
|
exit(1);
|
|
}
|