/* * 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 #if HAVE_STRING_H #include #else #include #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, NETSNMP_OLDAPI_RONLY, var_hrdevice, 2, {1, 1}}, {HRDEV_TYPE, ASN_OBJECT_ID, NETSNMP_OLDAPI_RONLY, var_hrdevice, 2, {1, 2}}, {HRDEV_DESCR, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, var_hrdevice, 2, {1, 3}}, {HRDEV_ID, ASN_OBJECT_ID, NETSNMP_OLDAPI_RONLY, var_hrdevice, 2, {1, 4}}, {HRDEV_STATUS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, var_hrdevice, 2, {1, 5}}, {HRDEV_ERRORS, ASN_COUNTER, NETSNMP_OLDAPI_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 = (WriteMethod*)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; }