/* * swrun_kinfo.c: * hrSWRunTable data access: * kvm_getprocs() interface - FreeBSD, NetBSD, OpenBSD * * NB: later FreeBSD and OpenBSD use different kinfo_proc structures */ #include #include #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_STRING_H #include #else #include #endif #ifdef HAVE_KVM_H #include #endif #ifdef HAVE_SYS_PARAM_H #include #endif #ifdef HAVE_SYS_SYSCTL_H #include #endif #ifdef HAVE_SYS_PROC_H #include #endif #ifdef HAVE_SYS_USER_H #include #endif #ifdef HAVE_UVM_UVM_EXTERNAL_H #include #endif #include #include #include #include #include #include "swrun_private.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_PPID ki_ppid #define SWRUN_K_TID ki_tid #define SWRUN_K_COMM ki_comm #define SWRUN_K_FLAG ki_flag #define SWRUN_K_CLASS ki_pri.pri_class #elif HAVE_KVM_GETPROC2 || defined(openbsd5) /* * newer NetBSD, OpenBSD kinfo_proc2 field names */ #if defined(openbsd5) #define SWRUN_TABLE kinfo_proc #else #define SWRUN_TABLE kinfo_proc2 #endif #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 */ #ifdef dragonfly /* * DragonFly is special. p_stat is an enum! */ #define SRUN 200 #define SSLEEP 202 #define SWAIT 203 #define SLOCK 205 #define SDEAD 208 #define SONPROC 209 #else #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 #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+1], **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 defined(openbsd5) proc_table = kvm_getprocs(kd, KERN_PROC_KTHREAD, 0, sizeof(struct kinfo_proc), &nprocs ); #elif defined(HAVE_KVM_GETPROC2) proc_table = kvm_getproc2(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), &nprocs ); #else proc_table = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nprocs ); #endif for ( i=0 ; ihrSWRunName_len = sprintf(entry->hrSWRunName, "%.*s", (int)sizeof(entry->hrSWRunName) - 1, proc_table[i].SWRUN_K_COMM); if (argv && *argv) { entry->hrSWRunPath_len = sprintf(entry->hrSWRunPath, "%.*s", (int)sizeof(entry->hrSWRunPath)-1, 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 ) { strlcat(buf, " ", sizeof(buf)); strlcat(buf, *argv, sizeof(buf)); argv++; } if (strlen(buf) >= BUFSIZ-10) snmp_log(LOG_ERR, "params %lu/%d %s\n", strlen(buf), BUFSIZ, buf); entry->hrSWRunParameters_len = sprintf(entry->hrSWRunParameters, "%.*s", (int)sizeof(entry->hrSWRunParameters) - 1, 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 SACTIVE: 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) || defined(openbsd5) /* * newer NetBSD, OpenBSD */ entry->hrSWRunPerfCPU = proc_table[i].p_rtime_sec*100; entry->hrSWRunPerfCPU += proc_table[i].p_rtime_usec / 10000; 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->hrSWRunPerfCPU = entry->hrSWRunPerfCPU / 10000; 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; }