Blame agent/mibgroup/host/data_access/swrun_kinfo.c

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