summaryrefslogtreecommitdiff
path: root/agent/mibgroup/host/hr_system.c
diff options
context:
space:
mode:
Diffstat (limited to 'agent/mibgroup/host/hr_system.c')
-rw-r--r--agent/mibgroup/host/hr_system.c681
1 files changed, 681 insertions, 0 deletions
diff --git a/agent/mibgroup/host/hr_system.c b/agent/mibgroup/host/hr_system.c
new file mode 100644
index 0000000..6d6afb5
--- /dev/null
+++ b/agent/mibgroup/host/hr_system.c
@@ -0,0 +1,681 @@
+/* Portions of this file are subject to the following copyright(s). See
+ * the Net-SNMP's COPYING file for more details and other copyrights
+ * that may apply:
+ */
+/*
+ * Portions of this file are copyrighted by:
+ * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms specified in the COPYING file
+ * distributed with the Net-SNMP package.
+ */
+
+/*
+ * Host Resources MIB - system group implementation - hr_system.c
+ *
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include "host.h"
+#include "host_res.h"
+#include "hr_system.h"
+#include <net-snmp/agent/auto_nlist.h>
+
+#ifdef HAVE_SYS_PROC_H
+#include <sys/param.h>
+#include "sys/proc.h"
+#endif
+#ifndef mingw32
+#if HAVE_UTMPX_H
+#include <utmpx.h>
+#else
+#include <utmp.h>
+#endif
+#endif /* mingw32 */
+#include <signal.h>
+#include <errno.h>
+
+#ifdef WIN32
+#include <lm.h>
+#endif
+
+#ifdef linux
+#ifdef HAVE_LINUX_TASKS_H
+#include <linux/tasks.h>
+#else
+/*
+ * If this file doesn't exist, then there is no hard limit on the number
+ * of processes, so return 0 for hrSystemMaxProcesses.
+ */
+#define NR_TASKS 0
+#endif
+#endif
+
+#if defined(hpux10) || defined(hpux11)
+#include <sys/pstat.h>
+#endif
+
+#if defined(solaris2)
+#include <kstat.h>
+#include <sys/var.h>
+#include <time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/openpromio.h>
+#endif
+
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+
+#if !defined(UTMP_FILE) && defined(_PATH_UTMP)
+#define UTMP_FILE _PATH_UTMP
+#endif
+
+#if defined(UTMP_FILE) && !HAVE_UTMPX_H
+void setutent(void);
+void endutent(void);
+struct utmp *getutent(void);
+#endif /* UTMP_FILE */
+
+
+ /*********************
+ *
+ * Kernel & interface information,
+ * and internal forward declarations
+ *
+ *********************/
+
+#if defined(solaris2)
+static struct openpromio * op_malloc(size_t size);
+static void op_free(struct openpromio *op);
+static int set_solaris_bootcommand_parameter(int action, u_char * var_val, u_char var_val_type, size_t var_val_len, u_char * statP, oid * name, size_t name_len);
+static int set_solaris_eeprom_parameter(const char *key, const char *value, size_t value_len);
+static int get_solaris_eeprom_parameter(const char *parameter, char *output);
+static long get_max_solaris_processes(void);
+#endif
+static int get_load_dev(void);
+static int count_users(void);
+extern int count_processes(void);
+
+
+ /*********************
+ *
+ * Initialisation & common implementation functions
+ *
+ *********************/
+
+#define HRSYS_UPTIME 1
+#define HRSYS_DATE 2
+#define HRSYS_LOAD_DEV 3
+#define HRSYS_LOAD_PARAM 4
+#define HRSYS_USERS 5
+#define HRSYS_PROCS 6
+#define HRSYS_MAXPROCS 7
+
+#if defined(solaris2)
+struct variable2 hrsystem_variables[] = {
+ {HRSYS_UPTIME, ASN_TIMETICKS, RONLY, var_hrsys, 1, {1}},
+ {HRSYS_DATE, ASN_OCTET_STR, RWRITE, var_hrsys, 1, {2}},
+ {HRSYS_LOAD_DEV, ASN_INTEGER, RONLY, var_hrsys, 1, {3}},
+ {HRSYS_LOAD_PARAM, ASN_OCTET_STR, RWRITE, var_hrsys, 1, {4}},
+ {HRSYS_USERS, ASN_GAUGE, RONLY, var_hrsys, 1, {5}},
+ {HRSYS_PROCS, ASN_GAUGE, RONLY, var_hrsys, 1, {6}},
+ {HRSYS_MAXPROCS, ASN_INTEGER, RONLY, var_hrsys, 1, {7}}
+};
+#else
+struct variable2 hrsystem_variables[] = {
+ {HRSYS_UPTIME, ASN_TIMETICKS, RONLY, var_hrsys, 1, {1}},
+ {HRSYS_DATE, ASN_OCTET_STR, RONLY, var_hrsys, 1, {2}},
+ {HRSYS_LOAD_DEV, ASN_INTEGER, RONLY, var_hrsys, 1, {3}},
+ {HRSYS_LOAD_PARAM, ASN_OCTET_STR, RONLY, var_hrsys, 1, {4}},
+ {HRSYS_USERS, ASN_GAUGE, RONLY, var_hrsys, 1, {5}},
+ {HRSYS_PROCS, ASN_GAUGE, RONLY, var_hrsys, 1, {6}},
+ {HRSYS_MAXPROCS, ASN_INTEGER, RONLY, var_hrsys, 1, {7}}
+};
+#endif
+oid hrsystem_variables_oid[] = { 1, 3, 6, 1, 2, 1, 25, 1 };
+
+
+void
+init_hr_system(void)
+{
+#ifdef NPROC_SYMBOL
+ auto_nlist(NPROC_SYMBOL, 0, 0);
+#endif
+
+ REGISTER_MIB("host/hr_system", hrsystem_variables, variable2,
+ hrsystem_variables_oid);
+} /* end init_hr_system */
+
+/*
+ * header_hrsys(...
+ * Arguments:
+ * vp IN - pointer to variable entry that points here
+ * name IN/OUT - IN/name requested, OUT/name found
+ * length IN/OUT - length of IN/OUT oid's
+ * exact IN - TRUE if an exact match was requested
+ * var_len OUT - length of variable or 0 if function returned
+ * write_method
+ */
+
+int
+header_hrsys(struct variable *vp,
+ oid * name,
+ size_t * length,
+ int exact, size_t * var_len, WriteMethod ** write_method)
+{
+#define HRSYS_NAME_LENGTH 9
+ oid newname[MAX_OID_LEN];
+ int result;
+
+ DEBUGMSGTL(("host/hr_system", "var_hrsys: "));
+ DEBUGMSGOID(("host/hr_system", name, *length));
+ DEBUGMSG(("host/hr_system", " %d\n", exact));
+
+ memcpy((char *) newname, (char *) vp->name, vp->namelen * sizeof(oid));
+ newname[HRSYS_NAME_LENGTH] = 0;
+ result = snmp_oid_compare(name, *length, newname, vp->namelen + 1);
+ if ((exact && (result != 0)) || (!exact && (result >= 0)))
+ return (MATCH_FAILED);
+ memcpy((char *) name, (char *) newname,
+ (vp->namelen + 1) * sizeof(oid));
+ *length = vp->namelen + 1;
+
+ *write_method = 0;
+ *var_len = sizeof(long); /* default to 'long' results */
+ return (MATCH_SUCCEEDED);
+} /* end header_hrsys */
+
+
+ /*********************
+ *
+ * System specific implementation functions
+ *
+ *********************/
+
+u_char *
+var_hrsys(struct variable * vp,
+ oid * name,
+ size_t * length,
+ int exact, size_t * var_len, WriteMethod ** write_method)
+{
+ static char string[129]; /* per MIB, max size is 128 */
+#if defined(solaris2)
+ /* max size of nvram property */
+ char bootparam[8192];
+#endif
+ time_t now;
+#if !(defined(NR_TASKS) || defined(solaris2) || defined(hpux10) || defined(hpux11))
+ int nproc = 0;
+#endif
+#ifdef linux
+ FILE *fp;
+#endif
+#if NETSNMP_CAN_USE_SYSCTL && defined(CTL_KERN) && defined(KERN_MAXPROC)
+ static int maxproc_mib[] = { CTL_KERN, KERN_MAXPROC };
+ int buf_size;
+#endif
+#if defined(hpux10) || defined(hpux11)
+ struct pst_static pst_buf;
+#endif
+
+ if (header_hrsys(vp, name, length, exact, var_len, write_method) ==
+ MATCH_FAILED)
+ return NULL;
+
+ switch (vp->magic) {
+ case HRSYS_UPTIME:
+ long_return = get_uptime();
+ return (u_char *) & long_return;
+ case HRSYS_DATE:
+#if defined(HAVE_MKTIME) && defined(HAVE_STIME)
+ *write_method=ns_set_time;
+#endif
+ (void *) time(&now);
+ return (u_char *) date_n_time(&now, var_len);
+ case HRSYS_LOAD_DEV:
+ long_return = get_load_dev();
+ return (u_char *) & long_return;
+ case HRSYS_LOAD_PARAM:
+#ifdef linux
+ if((fp = fopen("/proc/cmdline", "r")) != NULL) {
+ fgets(string, sizeof(string), fp);
+ fclose(fp);
+ } else {
+ return NULL;
+ }
+#elif defined(solaris2)
+ *write_method=set_solaris_bootcommand_parameter;
+ if ( get_solaris_eeprom_parameter("boot-command",bootparam) ) {
+ snmp_log(LOG_ERR,"unable to lookup boot-command from eeprom\n");
+ return NULL;
+ }
+ strlcpy(string,bootparam,sizeof(string));
+#else
+#if NETSNMP_NO_DUMMY_VALUES
+ return NULL;
+#endif
+ sprintf(string, "ask Dave"); /* XXX */
+#endif
+ *var_len = strlen(string);
+ return (u_char *) string;
+ case HRSYS_USERS:
+ long_return = count_users();
+ return (u_char *) & long_return;
+ case HRSYS_PROCS:
+#if USING_HOST_HR_SWRUN_MODULE
+ long_return = count_processes();
+#else
+#if NETSNMP_NO_DUMMY_VALUES
+ return NULL;
+#endif
+ long_return = 0;
+#endif
+ return (u_char *) & long_return;
+ case HRSYS_MAXPROCS:
+#if defined(NR_TASKS)
+ long_return = NR_TASKS; /* <linux/tasks.h> */
+#elif NETSNMP_CAN_USE_SYSCTL && defined(CTL_KERN) && defined(KERN_MAXPROC)
+ buf_size = sizeof(nproc);
+ if (sysctl(maxproc_mib, 2, &nproc, &buf_size, NULL, 0) < 0)
+ return NULL;
+ long_return = nproc;
+#elif defined(hpux10) || defined(hpux11)
+ pstat_getstatic(&pst_buf, sizeof(struct pst_static), 1, 0);
+ long_return = pst_buf.max_proc;
+#elif defined(solaris2)
+ long_return=get_max_solaris_processes();
+ if(long_return == -1) return NULL;
+#elif defined(NPROC_SYMBOL)
+ auto_nlist(NPROC_SYMBOL, (char *) &nproc, sizeof(int));
+ long_return = nproc;
+#else
+#if NETSNMP_NO_DUMMY_VALUES
+ return NULL;
+#endif
+ long_return = 0;
+#endif
+ return (u_char *) & long_return;
+ default:
+ DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_hrsys\n",
+ vp->magic));
+ }
+ return NULL;
+} /* end var_hrsys */
+
+
+ /*********************
+ *
+ * Internal implementation functions
+ *
+ *********************/
+
+
+#if defined(solaris2)
+
+/* functions for malloc and freeing openpromio structure */
+static struct openpromio * op_malloc(size_t size)
+{
+ struct openpromio *op;
+ op=malloc(sizeof(struct openpromio) + size);
+ if(op == NULL) {
+ snmp_log(LOG_ERR,"unable to malloc memory\n");
+ return NULL;
+ }
+
+ memset(op, 0, sizeof(struct openpromio)+size);
+ op->oprom_size=size;
+
+ return op;
+}
+
+static void op_free(struct openpromio *op) {
+ free(op);
+}
+
+static int
+set_solaris_bootcommand_parameter(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len) {
+
+ static char old_value[1024],*p_old_value=old_value;
+ int status=0;
+
+ switch (action) {
+ case RESERVE1:
+ /* check type */
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR,"write to set_solaris_bootcommand_parameter not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+ case RESERVE2: {
+ /* create copy of old value */
+ if(statP) {
+ int old_val_len=strlen(statP);
+ if(old_val_len >= sizeof(old_value)) {
+ p_old_value=(char *)malloc(old_val_len+1);
+ if(p_old_value==NULL) {
+ snmp_log(LOG_ERR,"unable to malloc memory\n");
+ return SNMP_ERR_GENERR;
+ }
+ }
+ strlcpy(p_old_value,statP,old_val_len+1);
+ } else {
+ p_old_value=NULL;
+ }
+ break;
+ }
+
+ case ACTION: {
+ status=set_solaris_eeprom_parameter("boot-command",(char *)var_val,var_val_len);
+ if(status!=0) return SNMP_ERR_GENERR;
+ break;
+ }
+
+ case UNDO: {
+ /* revert to old value */
+ if(p_old_value) {
+ status=set_solaris_eeprom_parameter("boot-command",(char *)p_old_value,strlen(p_old_value));
+ p_old_value=old_value;
+ if(status!=0) return SNMP_ERR_GENERR;
+ }
+ break;
+ }
+
+ case FREE:
+ case COMMIT:
+ /* free memory if necessary */
+ if(p_old_value != old_value) {
+ free(p_old_value);
+ p_old_value=old_value;
+ }
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+static int set_solaris_eeprom_parameter(const char *key, const char *value,
+ size_t var_val_len) {
+
+ int status=0;
+ char buffer[1024],*pbuffer=buffer;
+
+ if( strlen(key)+strlen(value)+16 > sizeof(buffer) ) {
+ pbuffer=(char *)malloc(strlen(key)+strlen(value)+16);
+ }
+
+
+ sprintf(pbuffer,"eeprom %s=\"",key);
+ strncat(pbuffer,value,var_val_len);
+ strcat(pbuffer,"\"\n");
+
+ status=system(pbuffer);
+
+ if(pbuffer!=buffer) free(pbuffer);
+ return status;
+}
+
+static int get_solaris_eeprom_parameter(const char *parameter, char *outbuffer) {
+
+ int fd=0,status=0;
+ struct openpromio *openprominfo=NULL;
+
+ fd=open("/dev/openprom",O_RDONLY);
+ if ( fd == -1 ) {
+ snmp_log_perror("/dev/openprom");
+ return 1;
+ }
+
+ openprominfo = op_malloc(8192);
+ if(!openprominfo) return 1;
+
+ strcpy(openprominfo->oprom_array,parameter);
+
+ status=ioctl(fd,OPROMGETOPT,openprominfo);
+ if ( status == -1 ) {
+ snmp_log_perror("/dev/openprom");
+ close(fd);
+ op_free(openprominfo);
+ return 1;
+ }
+ strcpy(outbuffer,openprominfo->oprom_array);
+
+ op_free(openprominfo);
+
+ /* close file */
+ close(fd);
+
+ return(0);
+}
+
+static long get_max_solaris_processes(void) {
+
+ kstat_ctl_t *ksc=NULL;
+ kstat_t *ks=NULL;
+ struct var v;
+ static long maxprocs=-1;
+
+ /* assume only necessary to compute once, since /etc/system must be modified */
+ if (maxprocs == -1) {
+ if ( (ksc=kstat_open()) != NULL &&
+ (ks=kstat_lookup(ksc, "unix", 0, "var")) != NULL &&
+ (kstat_read(ksc, ks, &v) != -1)) {
+
+ maxprocs=v.v_proc;
+ }
+ if(ksc) {
+ kstat_close(ksc);
+ }
+ }
+
+ return maxprocs;
+}
+
+#endif
+
+#if defined(HAVE_MKTIME) && defined(HAVE_STIME)
+int
+ns_set_time(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+
+ static time_t oldtime=0;
+
+ switch (action) {
+ case RESERVE1:
+ /* check type */
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR,"write to ns_set_time not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (var_val_len != 8 && var_val_len!=11) {
+ snmp_log(LOG_ERR,"write to ns_set_time not a proper length\n");
+ return SNMP_ERR_WRONGVALUE;
+ }
+ break;
+
+ case RESERVE2:
+ break;
+
+ case FREE:
+ break;
+
+ case ACTION: {
+ long status=0;
+ time_t seconds=0;
+ struct tm newtimetm;
+ int hours_from_utc= 0;
+ int minutes_from_utc= 0;
+
+ if (var_val_len == 11) {
+ /* timezone inforamation was present */
+ hours_from_utc=(int)var_val[9];
+ minutes_from_utc=(int)var_val[10];
+ }
+
+ newtimetm.tm_sec=(int)var_val[6];;
+ newtimetm.tm_min=(int)var_val[5];
+ newtimetm.tm_hour=(int)var_val[4];
+
+ newtimetm.tm_mon=(int)var_val[2]-1;
+ newtimetm.tm_year=256*(int)var_val[0]+(int)var_val[1]-1900;
+ newtimetm.tm_mday=(int)var_val[3];
+
+ /* determine if day light savings time in effect DST */
+ if ( ( hours_from_utc*60*60+minutes_from_utc*60 ) == abs(timezone) ) {
+ newtimetm.tm_isdst=0;
+ } else {
+ newtimetm.tm_isdst=1;
+ }
+
+ /* create copy of old value */
+ oldtime=time(NULL);
+
+ seconds=mktime(&newtimetm);
+ if(seconds == (time_t)-1) {
+ snmp_log(LOG_ERR, "Unable to convert time value\n");
+ return SNMP_ERR_GENERR;
+ }
+ status=stime(&seconds);
+ if(status!=0) {
+ snmp_log(LOG_ERR, "Unable to set time\n");
+ return SNMP_ERR_GENERR;
+ }
+ break;
+ }
+ case UNDO: {
+ /* revert to old value */
+ int status=0;
+ if(oldtime != 0) {
+ status=stime(&oldtime);
+ oldtime=0;
+ if(status!=0) {
+ snmp_log(LOG_ERR, "Unable to set time\n");
+ return SNMP_ERR_GENERR;
+ }
+ }
+ break;
+ }
+
+ case COMMIT: {
+ oldtime=0;
+ break;
+ }
+ }
+ return SNMP_ERR_NOERROR;
+}
+#endif
+
+ /*
+ * Return the DeviceIndex corresponding
+ * to the boot device
+ */
+static int
+get_load_dev(void)
+{
+ return (HRDEV_DISK << HRDEV_TYPE_SHIFT); /* XXX */
+} /* end get_load_dev */
+
+static int
+count_users(void)
+{
+ int total = 0;
+#ifndef WIN32
+#if HAVE_UTMPX_H
+#define setutent setutxent
+#define pututline pututxline
+#define getutent getutxent
+#define endutent endutxent
+ struct utmpx *utmp_p;
+#else
+ struct utmp *utmp_p;
+#endif
+
+ setutent();
+ while ((utmp_p = getutent()) != NULL) {
+#ifndef UTMP_HAS_NO_TYPE
+ if (utmp_p->ut_type != USER_PROCESS)
+ continue;
+#endif
+#ifndef UTMP_HAS_NO_PID
+ /* This block of code fixes zombie user PIDs in the
+ utmp/utmpx file that would otherwise be counted as a
+ current user */
+ if (kill(utmp_p->ut_pid, 0) == -1 && errno == ESRCH) {
+ utmp_p->ut_type = DEAD_PROCESS;
+ pututline(utmp_p);
+ continue;
+ }
+#endif
+ ++total;
+ }
+ endutent();
+#else /* WIN32 */
+ /*
+ * TODO - Error checking.
+ */
+ LPWKSTA_INFO_102 wkinfo;
+ NET_API_STATUS nstatus;
+
+ nstatus = NetWkstaGetInfo(NULL, 102, (LPBYTE*)&wkinfo);
+ if (nstatus != NERR_Success) {
+ return 0;
+ }
+ total = (int)wkinfo->wki102_logged_on_users;
+
+ NetApiBufferFree(wkinfo);
+#endif /* WIN32 */
+ return total;
+}
+
+#if defined(UTMP_FILE) && !HAVE_UTMPX_H
+
+static FILE *utmp_file;
+static struct utmp utmp_rec;
+
+void
+setutent(void)
+{
+ if (utmp_file)
+ fclose(utmp_file);
+ utmp_file = fopen(UTMP_FILE, "r");
+}
+
+void
+endutent(void)
+{
+ if (utmp_file) {
+ fclose(utmp_file);
+ utmp_file = NULL;
+ }
+}
+
+struct utmp *
+getutent(void)
+{
+ if (!utmp_file)
+ return NULL;
+ while (fread(&utmp_rec, sizeof(utmp_rec), 1, utmp_file) == 1)
+ if (*utmp_rec.ut_name && *utmp_rec.ut_line)
+ return &utmp_rec;
+ return NULL;
+}
+
+#endif /* UTMP_FILE */