blob: 7b1364d10e6bd6eaec2ad5131d9db6136b386c4a [file] [log] [blame]
/*
* Host Resources MIB - Device group implementation - hr_device.c
*
*/
/* 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.
*/
#include <net-snmp/net-snmp-config.h>
#if HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#include "host_res.h"
#include "hr_device.h"
/*********************
*
* Kernel & interface information,
* and internal forward declarations
*
*********************/
int Get_Next_Device(void);
PFV init_device[HRDEV_TYPE_MAX];
PFIV next_device[HRDEV_TYPE_MAX];
PFV save_device[HRDEV_TYPE_MAX];
int dev_idx_inc[HRDEV_TYPE_MAX];
PFS device_descr[HRDEV_TYPE_MAX];
PFO device_prodid[HRDEV_TYPE_MAX];
PFI device_status[HRDEV_TYPE_MAX];
PFI device_errors[HRDEV_TYPE_MAX];
int current_type;
void Init_Device(void);
int header_hrdevice(struct variable *, oid *, size_t *, int,
size_t *, WriteMethod **);
/*********************
*
* Initialisation & common implementation functions
*
*********************/
#define HRDEV_INDEX 1
#define HRDEV_TYPE 2
#define HRDEV_DESCR 3
#define HRDEV_ID 4
#define HRDEV_STATUS 5
#define HRDEV_ERRORS 6
struct variable4 hrdevice_variables[] = {
{HRDEV_INDEX, ASN_INTEGER, RONLY, var_hrdevice, 2, {1, 1}},
{HRDEV_TYPE, ASN_OBJECT_ID, RONLY, var_hrdevice, 2, {1, 2}},
{HRDEV_DESCR, ASN_OCTET_STR, RONLY, var_hrdevice, 2, {1, 3}},
{HRDEV_ID, ASN_OBJECT_ID, RONLY, var_hrdevice, 2, {1, 4}},
{HRDEV_STATUS, ASN_INTEGER, RONLY, var_hrdevice, 2, {1, 5}},
{HRDEV_ERRORS, ASN_COUNTER, RONLY, var_hrdevice, 2, {1, 6}}
};
oid hrdevice_variables_oid[] = { 1, 3, 6, 1, 2, 1, 25, 3, 2 };
void
init_hr_device(void)
{
int i;
/*
* Initially assume no devices
* Insert pointers to initialisation/get_next routines
* for particular device types as they are implemented
* (set up in the appropriate 'init_*()' routine )
*/
for (i = 0; i < HRDEV_TYPE_MAX; ++i) {
init_device[i] = NULL;
next_device[i] = NULL;
save_device[i] = NULL;
dev_idx_inc[i] = 0; /* Assume random indices */
device_descr[i] = NULL;
device_prodid[i] = NULL;
device_status[i] = NULL;
device_errors[i] = NULL;
}
REGISTER_MIB("host/hr_device", hrdevice_variables, variable4,
hrdevice_variables_oid);
}
/*
* header_hrdevice(...
* 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_hrdevice(struct variable *vp,
oid * name,
size_t * length,
int exact, size_t * var_len, WriteMethod ** write_method)
{
#define HRDEV_ENTRY_NAME_LENGTH 11
oid newname[MAX_OID_LEN];
int dev_idx, LowIndex = -1, LowType = -1;
int result;
DEBUGMSGTL(("host/hr_device", "var_hrdevice: "));
DEBUGMSGOID(("host/hr_device", name, *length));
DEBUGMSG(("host/hr_device", " %d\n", exact));
memcpy((char *) newname, (char *) vp->name,
(int) vp->namelen * sizeof(oid));
/*
* Find the "next" device entry.
* If we're in the middle of the table, then there's
* no point in examining earlier types of devices,
* so set the starting type to that of the variable
* being queried.
* If we've moved from one column of the table to another,
* then we need to start at the beginning again.
* (i.e. the 'compare' fails to match)
* Similarly if we're at the start of the table
* (i.e. *length is too short to be a full instance)
*/
if ((snmp_oid_compare(vp->name, vp->namelen, name, vp->namelen) == 0)
&& (*length > HRDEV_ENTRY_NAME_LENGTH))
current_type = (name[HRDEV_ENTRY_NAME_LENGTH] >> HRDEV_TYPE_SHIFT);
else
current_type = 0;
Init_Device();
for (;;) {
dev_idx = Get_Next_Device();
DEBUGMSG(("host/hr_device", "(index %d ....", dev_idx));
if (dev_idx == -1)
break;
if (LowType != -1 && LowType < (dev_idx >> HRDEV_TYPE_SHIFT))
break;
newname[HRDEV_ENTRY_NAME_LENGTH] = dev_idx;
DEBUGMSGOID(("host/hr_device", newname, *length));
DEBUGMSG(("host/hr_device", "\n"));
result = snmp_oid_compare(name, *length, newname, vp->namelen + 1);
if (exact && (result == 0)) {
if (save_device[current_type] != NULL)
(*save_device[current_type]) ();
LowIndex = dev_idx;
break;
}
if ((!exact && (result < 0)) &&
(LowIndex == -1 || dev_idx < LowIndex)) {
if (save_device[current_type] != NULL)
(*save_device[current_type]) ();
LowIndex = dev_idx;
LowType = (dev_idx >> HRDEV_TYPE_SHIFT);
if (dev_idx_inc[LowType]) /* Increasing indices => now done */
break;
}
}
if (LowIndex == -1) {
DEBUGMSGTL(("host/hr_device", "... index out of range\n"));
return (MATCH_FAILED);
}
newname[HRDEV_ENTRY_NAME_LENGTH] = LowIndex;
memcpy((char *) name, (char *) newname,
((int) vp->namelen + 1) * sizeof(oid));
*length = vp->namelen + 1;
*write_method = 0;
*var_len = sizeof(long); /* default to 'long' results */
DEBUGMSGTL(("host/hr_device", "... get device stats "));
DEBUGMSGOID(("host/hr_device", name, *length));
DEBUGMSG(("host/hr_device", "\n"));
return LowIndex;
}
oid device_type_id[] = { 1, 3, 6, 1, 2, 1, 25, 3, 1, 99 }; /* hrDeviceType99 */
int device_type_len =
sizeof(device_type_id) / sizeof(device_type_id[0]);
/*********************
*
* System specific implementation functions
*
*********************/
u_char *
var_hrdevice(struct variable *vp,
oid * name,
size_t * length,
int exact, size_t * var_len, WriteMethod ** write_method)
{
int dev_idx, type;
oid *oid_p;
const char *tmp_str;
static char string[1024];
really_try_next:
dev_idx =
header_hrdevice(vp, name, length, exact, var_len, write_method);
if (dev_idx == MATCH_FAILED)
return NULL;
type = (dev_idx >> HRDEV_TYPE_SHIFT);
switch (vp->magic) {
case HRDEV_INDEX:
long_return = dev_idx;
return (u_char *) & long_return;
case HRDEV_TYPE:
device_type_id[device_type_len - 1] = type;
*var_len = sizeof(device_type_id);
return (u_char *) device_type_id;
case HRDEV_DESCR:
if ((device_descr[type] != NULL) &&
(NULL!=(tmp_str=((*device_descr[type])(dev_idx))))) {
strlcpy(string, tmp_str, sizeof(string));
} else
#if NETSNMP_NO_DUMMY_VALUES
goto try_next;
#else
sprintf(string, "a black box of some sort");
#endif
*var_len = strlen(string);
return (u_char *) string;
case HRDEV_ID:
if (device_prodid[type] != NULL)
oid_p = ((*device_prodid[type]) (dev_idx, var_len));
else {
oid_p = nullOid;
*var_len = nullOidLen;
}
return (u_char *) oid_p;
case HRDEV_STATUS:
if (device_status[type] != NULL)
long_return = ((*device_status[type]) (dev_idx));
else
#if NETSNMP_NO_DUMMY_VALUES
goto try_next;
#else
long_return = 2; /* Assume running */
#endif
if ( !long_return )
goto try_next;
return (u_char *) & long_return;
case HRDEV_ERRORS:
if (device_errors[type] != NULL)
long_return = (*device_errors[type]) (dev_idx);
else
#if NETSNMP_NO_DUMMY_VALUES
goto try_next;
#else
long_return = 0; /* Assume OK */
#endif
return (u_char *) & long_return;
default:
DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_hrdevice\n",
vp->magic));
}
try_next:
if (!exact)
goto really_try_next;
return NULL;
}
/*********************
*
* Internal implementation functions
*
*********************/
void
Init_Device(void)
{
/*
* Find the first non-NULL initialisation function
* and call it
*/
while (current_type < HRDEV_TYPE_MAX &&
init_device[current_type] == NULL)
if (++current_type >= HRDEV_TYPE_MAX)
return;
/* Check current_type, if >= MAX first time into loop, would fail below */
if (current_type < HRDEV_TYPE_MAX)
(*init_device[current_type]) ();
}
int
Get_Next_Device(void)
{
int result = -1;
/*
* Call the 'next device' function for the current
* type of device
*
* TODO: save the necessary information about that device
*/
if (current_type < HRDEV_TYPE_MAX && next_device[current_type] != NULL)
result = (*next_device[current_type]) ();
/*
* No more devices of the current type.
* Try the next type (if any)
*/
if (result == -1) {
if (++current_type >= HRDEV_TYPE_MAX) {
current_type = 0;
return -1;
}
Init_Device();
return Get_Next_Device();
}
return result;
}