blob: ca2f854cbb39dc415c3ab1b99a669119a6d9fd6c [file] [log] [blame]
/*
* Host Resources MIB - storage group implementation - hrh_storage.c
*
*/
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include <net-snmp/agent/hardware/memory.h>
#include <net-snmp/agent/hardware/fsys.h>
#include "host_res.h"
#include "hrh_filesys.h"
#include "hrh_storage.h"
#include "hr_disk.h"
#include <net-snmp/utilities.h>
#include <sys/types.h>
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if TIME_WITH_SYS_TIME
# ifdef WIN32
# include <windows.h>
# include <errno.h>
# include <sys/timeb.h>
# else
# include <sys/time.h>
# endif
# include <time.h>
#else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
#if HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#include <net-snmp/output_api.h>
#include <net-snmp/agent/agent_read_config.h>
#include <net-snmp/library/read_config.h>
#define HRSTORE_MONOTONICALLY_INCREASING
/*********************
*
* Kernel & interface information,
* and internal forward declarations
*
*********************/
extern netsnmp_fsys_info *HRFS_entry;
static void parse_storage_config(const char *, char *);
/*********************
*
* Initialisation & common implementation functions
*
*********************/
int Get_Next_HR_Store(void);
void Init_HR_Store(void);
int header_hrstore(struct variable *, oid *, size_t *, int,
size_t *, WriteMethod **);
void* header_hrstoreEntry(struct variable *, oid *, size_t *,
int, size_t *, WriteMethod **);
Netsnmp_Node_Handler handle_memsize;
#define HRSTORE_MEMSIZE 1
#define HRSTORE_INDEX 2
#define HRSTORE_TYPE 3
#define HRSTORE_DESCR 4
#define HRSTORE_UNITS 5
#define HRSTORE_SIZE 6
#define HRSTORE_USED 7
#define HRSTORE_FAILS 8
struct variable2 hrstore_variables[] = {
{HRSTORE_INDEX, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
var_hrstore, 1, {1}},
{HRSTORE_TYPE, ASN_OBJECT_ID, NETSNMP_OLDAPI_RONLY,
var_hrstore, 1, {2}},
{HRSTORE_DESCR, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
var_hrstore, 1, {3}},
{HRSTORE_UNITS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
var_hrstore, 1, {4}},
{HRSTORE_SIZE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
var_hrstore, 1, {5}},
{HRSTORE_USED, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
var_hrstore, 1, {6}},
{HRSTORE_FAILS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
var_hrstore, 1, {7}}
};
oid hrstore_variables_oid[] = { 1, 3, 6, 1, 2, 1, 25, 2 };
oid hrMemorySize_oid[] = { 1, 3, 6, 1, 2, 1, 25, 2, 2 };
oid hrStorageTable_oid[] = { 1, 3, 6, 1, 2, 1, 25, 2, 3, 1 };
void
init_hrh_storage(void)
{
char *appname;
netsnmp_register_scalar(
netsnmp_create_handler_registration("host/hrMemorySize", handle_memsize,
hrMemorySize_oid, OID_LENGTH(hrMemorySize_oid),
HANDLER_CAN_RONLY));
REGISTER_MIB("host/hr_storage", hrstore_variables, variable2,
hrStorageTable_oid);
appname = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
NETSNMP_DS_LIB_APPTYPE);
netsnmp_ds_register_config(ASN_BOOLEAN, appname, "skipNFSInHostResources",
NETSNMP_DS_APPLICATION_ID,
NETSNMP_DS_AGENT_SKIPNFSINHOSTRESOURCES);
netsnmp_ds_register_config(ASN_BOOLEAN, appname, "realStorageUnits",
NETSNMP_DS_APPLICATION_ID,
NETSNMP_DS_AGENT_REALSTORAGEUNITS);
snmpd_register_config_handler("storageUseNFS", parse_storage_config, NULL,
"1 | 2\t\t(1 = enable, 2 = disable)");
}
static int storageUseNFS = 1; /* Default to reporting NFS mounts as NetworkDisk */
static void
parse_storage_config(const char *token, char *cptr)
{
char *val;
int ival;
char *st;
val = strtok_r(cptr, " \t", &st);
if (!val) {
config_perror("Missing FLAG parameter in storageUseNFS");
return;
}
ival = atoi(val);
if (ival < 1 || ival > 2) {
config_perror("storageUseNFS must be 1 or 2");
return;
}
storageUseNFS = (ival == 1) ? 1 : 0;
}
/*
* header_hrstoreEntry(...
* 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
*
*/
void *
header_hrstoreEntry(struct variable *vp,
oid * name,
size_t * length,
int exact,
size_t * var_len, WriteMethod ** write_method)
{
#define HRSTORE_ENTRY_NAME_LENGTH 11
oid newname[MAX_OID_LEN];
int storage_idx, LowIndex = -1;
int result;
int idx = -1;
netsnmp_memory_info *mem = NULL;
DEBUGMSGTL(("host/hr_storage", "var_hrstoreEntry: request "));
DEBUGMSGOID(("host/hr_storage", name, *length));
DEBUGMSG(("host/hr_storage", " exact=%d\n", exact));
memcpy((char *) newname, (char *) vp->name,
(int) vp->namelen * sizeof(oid));
result = snmp_oid_compare(name, *length, vp->name, vp->namelen);
DEBUGMSGTL(("host/hr_storage", "var_hrstoreEntry: compare "));
DEBUGMSGOID(("host/hr_storage", vp->name, vp->namelen));
DEBUGMSG(("host/hr_storage", " => %d\n", result));
if (result < 0 ||
*length <= HRSTORE_ENTRY_NAME_LENGTH ) {
/*
* Requested OID too early or too short to refer
* to a valid row (for the current column object).
* GET requests should fail, GETNEXT requests
* should use the first row.
*/
if ( exact )
return NULL;
netsnmp_memory_load();
mem = netsnmp_memory_get_first( 0 );
}
else {
/*
* Otherwise, retrieve the requested
* (or following) row as appropriate.
*/
if ( exact && *length > HRSTORE_ENTRY_NAME_LENGTH+1 )
return NULL; /* Too long for a valid instance */
idx = name[ HRSTORE_ENTRY_NAME_LENGTH ];
if ( idx < NETSNMP_MEM_TYPE_MAX ) {
netsnmp_memory_load();
mem = ( exact ? netsnmp_memory_get_byIdx( idx, 0 ) :
netsnmp_memory_get_next_byIdx( idx, 0 ));
}
}
/*
* If this matched a memory-based entry, then
* update the OID parameter(s) for GETNEXT requests.
*/
if ( mem ) {
if ( !exact ) {
newname[ HRSTORE_ENTRY_NAME_LENGTH ] = mem->idx;
memcpy((char *) name, (char *) newname,
((int) vp->namelen + 1) * sizeof(oid));
*length = vp->namelen + 1;
}
}
/*
* If this didn't match a memory-based entry,
* then consider the disk-based storage.
*/
else {
Init_HR_Store();
for (;;) {
storage_idx = Get_Next_HR_Store();
DEBUGMSG(("host/hr_storage", "(index %d ....", storage_idx));
if (storage_idx == -1)
break;
newname[HRSTORE_ENTRY_NAME_LENGTH] = storage_idx;
DEBUGMSGOID(("host/hr_storage", newname, *length));
DEBUGMSG(("host/hr_storage", "\n"));
result = snmp_oid_compare(name, *length, newname, vp->namelen + 1);
if (exact && (result == 0)) {
LowIndex = storage_idx;
/*
* Save storage status information
*/
break;
}
if ((!exact && (result < 0)) &&
(LowIndex == -1 || storage_idx < LowIndex)) {
LowIndex = storage_idx;
/*
* Save storage status information
*/
#ifdef HRSTORE_MONOTONICALLY_INCREASING
break;
#endif
}
}
if ( LowIndex != -1 ) {
if ( !exact ) {
newname[ HRSTORE_ENTRY_NAME_LENGTH ] = LowIndex;
memcpy((char *) name, (char *) newname,
((int) vp->namelen + 1) * sizeof(oid));
*length = vp->namelen + 1;
}
mem = (netsnmp_memory_info*)0xffffffff; /* To indicate 'success' */
}
}
*write_method = (WriteMethod*)0;
*var_len = sizeof(long); /* default to 'long' results */
/*
* ... and return the appropriate row
*/
DEBUGMSGTL(("host/hr_storage", "var_hrstoreEntry: process "));
DEBUGMSGOID(("host/hr_storage", name, *length));
DEBUGMSG(("host/hr_storage", " (%p)\n", mem));
return (void*)mem;
}
oid storage_type_id[] = { 1, 3, 6, 1, 2, 1, 25, 2, 1, 1 }; /* hrStorageOther */
int storage_type_len =
sizeof(storage_type_id) / sizeof(storage_type_id[0]);
/*********************
*
* System specific implementation functions
*
*********************/
int
handle_memsize(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
netsnmp_memory_info *mem_info;
int val;
/*
* We just need to handle valid GET requests, as invalid instances
* are rejected automatically, and (valid) GETNEXT requests are
* converted into the appropriate GET request.
*
* We also only ever receive one request at a time.
*/
switch (reqinfo->mode) {
case MODE_GET:
netsnmp_memory_load();
mem_info = netsnmp_memory_get_byIdx( NETSNMP_MEM_TYPE_PHYSMEM, 0 );
if ( !mem_info || mem_info->size == -1 || mem_info->units == -1 )
netsnmp_set_request_error( reqinfo, requests, SNMP_NOSUCHOBJECT );
else {
val = mem_info->size; /* memtotal */
val *= (mem_info->units/1024);
snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
(u_char *)&val, sizeof(val));
}
return SNMP_ERR_NOERROR;
default:
/*
* we should never get here, so this is a really bad error
*/
snmp_log(LOG_ERR, "unknown mode (%d) in handle_memsize\n",
reqinfo->mode);
return SNMP_ERR_GENERR;
}
return SNMP_ERR_NOERROR;
}
u_char *
var_hrstore(struct variable *vp,
oid * name,
size_t * length,
int exact, size_t * var_len, WriteMethod ** write_method)
{
int store_idx = 0;
static char string[1024];
void *ptr;
netsnmp_memory_info *mem = NULL;
really_try_next:
ptr = header_hrstoreEntry(vp, name, length, exact, var_len,
write_method);
if (ptr == NULL)
return NULL;
store_idx = name[ HRSTORE_ENTRY_NAME_LENGTH ];
if (HRFS_entry &&
store_idx > NETSNMP_MEM_TYPE_MAX &&
netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
NETSNMP_DS_AGENT_SKIPNFSINHOSTRESOURCES) &&
Check_HR_FileSys_NFS())
return NULL;
if (store_idx <= NETSNMP_MEM_TYPE_MAX ) {
mem = (netsnmp_memory_info*)ptr;
}
switch (vp->magic) {
case HRSTORE_INDEX:
long_return = store_idx;
return (u_char *) & long_return;
case HRSTORE_TYPE:
if (store_idx > NETSNMP_MEM_TYPE_MAX)
if (HRFS_entry->flags & NETSNMP_FS_FLAG_REMOTE )
storage_type_id[storage_type_len - 1] = 10; /* Network Disk */
else if (HRFS_entry->flags & NETSNMP_FS_FLAG_REMOVE )
storage_type_id[storage_type_len - 1] = 5; /* Removable Disk */
else
storage_type_id[storage_type_len - 1] = 4; /* Assume fixed */
else
switch (store_idx) {
case NETSNMP_MEM_TYPE_PHYSMEM:
case NETSNMP_MEM_TYPE_USERMEM:
storage_type_id[storage_type_len - 1] = 2; /* RAM */
break;
case NETSNMP_MEM_TYPE_VIRTMEM:
case NETSNMP_MEM_TYPE_SWAP:
storage_type_id[storage_type_len - 1] = 3; /* Virtual Mem */
break;
default:
storage_type_id[storage_type_len - 1] = 1; /* Other */
break;
}
*var_len = sizeof(storage_type_id);
return (u_char *) storage_type_id;
case HRSTORE_DESCR:
if (store_idx > NETSNMP_MEM_TYPE_MAX) {
strlcpy(string, HRFS_entry->path, sizeof(string));
*var_len = strlen(string);
return (u_char *) string;
} else {
if ( !mem || !mem->descr )
goto try_next;
*var_len = strlen(mem->descr);
return (u_char *) mem->descr;
}
case HRSTORE_UNITS:
if (store_idx > NETSNMP_MEM_TYPE_MAX) {
if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
NETSNMP_DS_AGENT_REALSTORAGEUNITS))
long_return = HRFS_entry->units & 0xffffffff;
else
long_return = HRFS_entry->units_32;
} else {
if ( !mem || mem->units == -1 )
goto try_next;
long_return = mem->units;
}
return (u_char *) & long_return;
case HRSTORE_SIZE:
if (store_idx > NETSNMP_MEM_TYPE_MAX) {
if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
NETSNMP_DS_AGENT_REALSTORAGEUNITS))
long_return = HRFS_entry->size & 0xffffffff;
else
long_return = HRFS_entry->size_32;
} else {
if ( !mem || mem->size == -1 )
goto try_next;
long_return = mem->size;
}
return (u_char *) & long_return;
case HRSTORE_USED:
if (store_idx > NETSNMP_MEM_TYPE_MAX) {
if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
NETSNMP_DS_AGENT_REALSTORAGEUNITS))
long_return = HRFS_entry->used & 0xffffffff;
else
long_return = HRFS_entry->used_32;
} else {
if ( !mem || mem->size == -1 || mem->free == -1 )
goto try_next;
long_return = mem->size - mem->free;
}
return (u_char *) & long_return;
case HRSTORE_FAILS:
if (store_idx > NETSNMP_MEM_TYPE_MAX)
#if NETSNMP_NO_DUMMY_VALUES
goto try_next;
#else
long_return = 0;
#endif
else {
if ( !mem || mem->other == -1 )
goto try_next;
long_return = mem->other;
}
return (u_char *) & long_return;
default:
DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_hrstore\n",
vp->magic));
}
return NULL;
try_next:
if (!exact)
goto really_try_next;
return NULL;
}
/*********************
*
* Internal implementation functions
*
*********************/
static int HRS_index;
void
Init_HR_Store(void)
{
HRS_index = 0;
Init_HR_FileSys();
}
int
Get_Next_HR_Store(void)
{
/*
* File-based storage
*/
for (;;) {
HRS_index = Get_Next_HR_FileSys();
if (HRS_index >= 0) {
if (!(netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
NETSNMP_DS_AGENT_SKIPNFSINHOSTRESOURCES) &&
Check_HR_FileSys_NFS())) {
return HRS_index + NETSNMP_MEM_TYPE_MAX;
}
} else {
return -1;
}
}
}