summaryrefslogtreecommitdiff
path: root/agent/mibgroup/host/data_access/swrun_kinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'agent/mibgroup/host/data_access/swrun_kinfo.c')
-rw-r--r--agent/mibgroup/host/data_access/swrun_kinfo.c331
1 files changed, 331 insertions, 0 deletions
diff --git a/agent/mibgroup/host/data_access/swrun_kinfo.c b/agent/mibgroup/host/data_access/swrun_kinfo.c
new file mode 100644
index 0000000..b13ea3a
--- /dev/null
+++ b/agent/mibgroup/host/data_access/swrun_kinfo.c
@@ -0,0 +1,331 @@
+/*
+ * swrun_kinfo.c:
+ * hrSWRunTable data access:
+ * kvm_getprocs() interface - FreeBSD, NetBSD, OpenBSD
+ *
+ * NB: later FreeBSD uses a different kinfo_proc structure
+ */
+#include <net-snmp/net-snmp-config.h>
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+#ifdef HAVE_KVM_H
+#include <kvm.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+#ifdef HAVE_SYS_USER_H
+#include <sys/user.h>
+#endif
+#ifdef HAVE_UVM_UVM_EXTERNAL_H
+#include <uvm/uvm_external.h>
+#endif
+
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <net-snmp/library/container.h>
+#include <net-snmp/library/snmp_debug.h>
+#include <net-snmp/data_access/swrun.h>
+
+extern kvm_t *kd;
+
+
+#if defined(freebsd5) && __FreeBSD_version >= 500014
+ /*
+ * later FreeBSD kinfo_proc field names
+ */
+#define SWRUN_TABLE kinfo_proc
+#define SWRUN_K_STAT ki_stat
+#define SWRUN_K_PID ki_pid
+#define SWRUN_K_COMM ki_comm
+#define SWRUN_K_FLAG ki_flag
+#define SWRUN_K_CLASS ki_pri.pri_class
+
+#elif HAVE_KVM_GETPROC2
+ /*
+ * newer NetBSD, OpenBSD kinfo_proc2 field names
+ */
+#define SWRUN_TABLE kinfo_proc2
+#define SWRUN_K_STAT p_stat
+#define SWRUN_K_PID p_pid
+#define SWRUN_K_COMM p_comm
+#define SWRUN_K_FLAG p_flag
+/* SWRUN_K_CLASS not defined */
+
+#elif defined(dragonfly)
+ /*
+ * DragonFly is different ...
+ */
+#define SWRUN_TABLE kinfo_proc
+#define SWRUN_K_STAT kp_stat
+#define SWRUN_K_PID kp_pid
+#define SWRUN_K_COMM kp_comm
+#define SWRUN_K_FLAG kp_flags
+/* SWRUN_K_CLASS not defined */
+
+#else
+ /*
+ * early FreeBSD, NetBSD, OpenBSD kinfo_proc field names
+ */
+#define SWRUN_TABLE kinfo_proc
+#define SWRUN_K_STAT kp_proc.p_stat
+#define SWRUN_K_PID kp_proc.p_pid
+#define SWRUN_K_COMM kp_proc.p_comm
+#define SWRUN_K_FLAG kp_proc.p_flag
+/* SWRUN_K_CLASS not defined */
+#endif
+
+/*
+ * Define dummy values if not already provided by the system
+ */
+
+#ifndef SRUN
+#define SRUN 200 /* Defined by FreeBSD/OpenBSD, missing in NetBSD */
+#endif
+#ifndef SACTIVE
+#define SACTIVE 201 /* Defined by NetBSD, missing in FreeBSD/OpenBSD */
+#endif
+#ifndef SSLEEP
+#define SSLEEP 202 /* Defined by FreeBSD/OpenBSD, missing in NetBSD */
+#endif
+#ifndef SWAIT
+#define SWAIT 203 /* Defined by FreeBSD, missing in NetBSD/OpenBSD */
+#endif
+#ifndef SSTOP
+#define SSTOP 204 /* Defined by FreeBSD/NetBSD/OpenBSD */
+#endif
+#ifndef SLOCK
+#define SLOCK 205 /* Defined by FreeBSD, missing in NetBSD/OpenBSD */
+#endif
+#ifndef SIDL
+#define SIDL 206 /* Defined by FreeBSD/NetBSD/OpenBSD */
+#endif
+#ifndef SZOMB
+#define SZOMB 207 /* Defined by FreeBSD/NetBSD/OpenBSD */
+#endif
+#ifndef SDEAD
+#define SDEAD 208 /* Defined by OpenBSD, missing in FreeBSD/NetBSD */
+#endif
+#ifndef SONPROC
+#define SONPROC 209 /* Defined by OpenBSD, missing in FreeBSD/NetBSD */
+#endif
+
+/* ---------------------------------------------------------------------
+ */
+void
+netsnmp_arch_swrun_init(void)
+{
+#if NETSNMP_CAN_USE_SYSCTL && defined(CTL_KERN) && defined(KERN_MAXPROC)
+ extern int _swrun_max;
+ size_t max_size = sizeof(_swrun_max);
+ int maxproc_mib[] = { CTL_KERN, KERN_MAXPROC };
+ sysctl(maxproc_mib, 2, &_swrun_max, &max_size, NULL, 0);
+#endif
+
+ return;
+}
+
+/* ---------------------------------------------------------------------
+ */
+int
+netsnmp_arch_swrun_container_load( netsnmp_container *container, u_int flags)
+{
+ struct SWRUN_TABLE *proc_table;
+ int nprocs, i, rc;
+ char buf[BUFSIZ], **argv;
+ netsnmp_swrun_entry *entry;
+
+ if ( 0 == kd ) {
+ DEBUGMSGTL(("swrun:load:arch"," Can't query kvm info\n"));
+ return 1; /* No handle for retrieving process table */
+ }
+#if HAVE_KVM_GETPROC2
+ proc_table = kvm_getproc2(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), &nprocs );
+#elif defined(KERN_PROC_PROC)
+ proc_table = kvm_getprocs(kd, KERN_PROC_PROC, 0, &nprocs );
+#else
+ proc_table = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nprocs );
+#endif
+ for ( i=0 ; i<nprocs; i++ ) {
+ if ( 0 == proc_table[i].SWRUN_K_STAT )
+ continue;
+ entry = netsnmp_swrun_entry_create(proc_table[i].SWRUN_K_PID);
+ if (NULL == entry)
+ continue; /* error already logged by function */
+ rc = CONTAINER_INSERT(container, entry);
+
+ /*
+ * There are two possible sources for the command being run:
+ * - SWRUN_K_COMM (from the proc_table entry directly)
+ * - running kvm_getargv on the process entry.
+ *
+ * We'll use argv[0] (if set) for hrSWRunPath,
+ * since that might potentially contain the
+ * absolute path to the running binary.
+ * We'll use SWRUN_K_COMM for hrSWRunName,
+ * and as an alternative for hrSWRunPath
+ */
+#if HAVE_KVM_GETPROC2
+ argv = kvm_getargv2( kd, &(proc_table[i]), 0);
+#else
+ argv = kvm_getargv( kd, &(proc_table[i]), 0);
+#endif
+
+ entry->hrSWRunName_len = snprintf(entry->hrSWRunName,
+ sizeof(entry->hrSWRunName)-1,
+ "%s", proc_table[i].SWRUN_K_COMM);
+
+ if ( argv && *argv)
+ entry->hrSWRunPath_len = snprintf(entry->hrSWRunPath,
+ sizeof(entry->hrSWRunPath)-1,
+ "%s", argv[0]);
+ else {
+ memcpy( entry->hrSWRunPath, entry->hrSWRunName,
+ entry->hrSWRunName_len );
+ entry->hrSWRunPath_len = entry->hrSWRunName_len;
+ }
+
+ /*
+ * Stitch together the rest of argv[] to build hrSWRunParameters
+ *
+ * Note:
+ * We add a separating space before each argv[] parameter,
+ * *including* the first one. So we need to skip this
+ * leading space (buf[0]) when setting hrSWRunParameters.
+ * This is also why we cleared the first *two* characters
+ * in the buffer initially. If there were no command-line
+ * arguments, then buf[1] would still be a null string.
+ */
+ buf[0] = '\0';
+ buf[1] = '\0';
+ if (argv)
+ argv++; /* Skip argv[0] */
+ while ( argv && *argv ) {
+ strcat(buf, " ");
+ strcat(buf, *argv);
+ argv++;
+ }
+ entry->hrSWRunParameters_len = snprintf(entry->hrSWRunParameters,
+ sizeof(entry->hrSWRunParameters)-1,
+ "%s", buf+1);
+
+ entry->hrSWRunType = (P_SYSTEM & proc_table[i].SWRUN_K_FLAG)
+#ifdef SWRUN_K_CLASS
+ ? ((PRI_ITHD == proc_table[i].SWRUN_K_CLASS)
+ ? 3 /* device driver */
+ : 2 /* operating system */
+ )
+ : 4 /* application */
+#else
+ ? 2 /* operating system */
+ : 4 /* application */
+#endif
+ ;
+
+#ifdef netbsd5
+ switch (proc_table[i].SWRUN_K_STAT) {
+ case LSONPROC:
+ case LSRUN: entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNING;
+ break;
+ case LSSLEEP: entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNABLE;
+ break;
+ case LSIDL:
+ case LSSUSPENDED:
+ case LSSTOP: entry->hrSWRunStatus = HRSWRUNSTATUS_NOTRUNNABLE;
+ break;
+ case LSDEAD:
+ case LSZOMB: entry->hrSWRunStatus = HRSWRUNSTATUS_INVALID;
+ break;
+ default:
+ entry->hrSWRunStatus = HRSWRUNSTATUS_INVALID;
+ snmp_log(LOG_ERR, "Bad process status %c (0x%x)\n", proc_table[i].SWRUN_K_STAT, proc_table[i].SWRUN_K_STAT);
+ break;
+ }
+#else
+ switch (proc_table[i].SWRUN_K_STAT & 0xFF) {
+ case SONPROC:
+ case SRUN: entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNING;
+ break;
+ case SSLEEP:
+ case SWAIT: entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNABLE;
+ break;
+ case SIDL:
+ case SSTOP:
+ case SLOCK: entry->hrSWRunStatus = HRSWRUNSTATUS_NOTRUNNABLE;
+ break;
+
+ case SDEAD:
+ case SZOMB: entry->hrSWRunStatus = HRSWRUNSTATUS_INVALID; /* i.e. "not loaded" */
+ break;
+
+ default: entry->hrSWRunStatus = HRSWRUNSTATUS_INVALID; /* Actually invalid */
+ snmp_log(LOG_ERR, "Bad process status %c (0x%x)\n", proc_table[i].SWRUN_K_STAT, proc_table[i].SWRUN_K_STAT);
+ break;
+ }
+#endif
+
+#if defined(freebsd5) && __FreeBSD_version >= 500014
+ entry->hrSWRunPerfCPU = (proc_table[i].ki_rusage.ru_utime.tv_sec*1000000 + proc_table[i].ki_rusage.ru_utime.tv_usec) / 10000;
+ entry->hrSWRunPerfCPU += (proc_table[i].ki_rusage.ru_stime.tv_sec*1000000 + proc_table[i].ki_rusage.ru_stime.tv_usec) / 10000;
+ entry->hrSWRunPerfCPU += (proc_table[i].ki_rusage_ch.ru_utime.tv_sec*1000000 + proc_table[i].ki_rusage_ch.ru_utime.tv_usec) / 10000;
+ entry->hrSWRunPerfCPU += (proc_table[i].ki_rusage_ch.ru_stime.tv_sec*1000000 + proc_table[i].ki_rusage_ch.ru_stime.tv_usec) / 10000;
+ entry->hrSWRunPerfMem = proc_table[i].ki_rssize * (getpagesize()/1024); /* in kB */
+#elif defined(HAVE_KVM_GETPROC2)
+ /*
+ * newer NetBSD, OpenBSD
+ */
+ entry->hrSWRunPerfCPU = proc_table[i].p_uticks;
+ entry->hrSWRunPerfCPU += proc_table[i].p_sticks;
+ entry->hrSWRunPerfCPU += proc_table[i].p_iticks;
+ entry->hrSWRunPerfMem = proc_table[i].p_vm_rssize;
+ entry->hrSWRunPerfMem *= (getpagesize() / 1024);
+#elif defined(dragonfly) && __DragonFly_version >= 190000
+ entry->hrSWRunPerfCPU = proc_table[i].kp_lwp.kl_uticks;
+ entry->hrSWRunPerfCPU += proc_table[i].kp_lwp.kl_sticks;
+ entry->hrSWRunPerfCPU += proc_table[i].kp_lwp.kl_iticks;
+ entry->hrSWRunPerfMem = proc_table[i].kp_vm_map_size / 1024;
+#elif defined(dragonfly)
+ entry->hrSWRunPerfCPU = proc_table[i].kp_eproc.e_uticks;
+ entry->hrSWRunPerfCPU += proc_table[i].kp_eproc.e_sticks;
+ entry->hrSWRunPerfCPU += proc_table[i].kp_eproc.e_iticks;
+ entry->hrSWRunPerfMem = proc_table[i].kp_vm_map_size / 1024;
+
+#else
+ /*
+ * early FreeBSD, NetBSD, OpenBSD
+ */
+ entry->hrSWRunPerfCPU = proc_table[i].kp_proc.p_uticks;
+ entry->hrSWRunPerfCPU += proc_table[i].kp_proc.p_sticks;
+ entry->hrSWRunPerfCPU += proc_table[i].kp_proc.p_iticks;
+ entry->hrSWRunPerfMem = proc_table[i].kp_eproc.e_vm.vm_rssize;
+ entry->hrSWRunPerfMem *= (getpagesize() / 1024);
+#endif
+ }
+ /*
+ * 'proc_table' is owned by the kvm library,
+ * so shouldn't be freed here.
+ */
+
+ DEBUGMSGTL(("swrun:load:arch","loaded %d entries\n",
+ (int)CONTAINER_SIZE(container)));
+
+ return 0;
+}