diff options
Diffstat (limited to 'agent/mibgroup/disman/event/mteObjects.c')
-rw-r--r-- | agent/mibgroup/disman/event/mteObjects.c | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/agent/mibgroup/disman/event/mteObjects.c b/agent/mibgroup/disman/event/mteObjects.c new file mode 100644 index 0000000..cf950c1 --- /dev/null +++ b/agent/mibgroup/disman/event/mteObjects.c @@ -0,0 +1,433 @@ +/* + * DisMan Event MIB: + * Core implementation of the object handling behaviour + */ + +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> +#include "disman/event/mteObjects.h" + +netsnmp_tdata *objects_table_data; + + /* + * Initialize the container for the object table + * regardless of which initialisation routine is called first. + */ + +void +init_objects_table_data(void) +{ + if (!objects_table_data) + objects_table_data = netsnmp_tdata_create_table("mteObjectsTable", 0); +} + + + +SNMPCallback _init_default_mteObject_lists; + +/** Initializes the mteObjects module */ +void +init_mteObjects(void) +{ + init_objects_table_data(); + + /* + * Insert fixed object lists for the default trigger + * notifications, once the MIB files have been read in. + */ + snmp_register_callback(SNMP_CALLBACK_LIBRARY, + SNMP_CALLBACK_POST_READ_CONFIG, + _init_default_mteObject_lists, NULL); +} + + +void +_init_default_mteObject( const char *oname, const char *object, int index, int wcard) +{ + struct mteObject *entry; + + entry = mteObjects_addOID( "_snmpd", oname, index, object, 0 ); + if (entry) { + entry->flags |= MTE_OBJECT_FLAG_ACTIVE| + MTE_OBJECT_FLAG_FIXED | + MTE_OBJECT_FLAG_VALID; + if (wcard) + entry->flags |= MTE_OBJECT_FLAG_WILD; + } +} + +int +_init_default_mteObject_lists( int majorID, int minorID, + void *serverargs, void *clientarg) +{ + static int _defaults_init = 0; + + if (_defaults_init) + return 0; + /* mteHotTrigger */ + _init_default_mteObject( "_triggerFire", ".1.3.6.1.2.1.88.2.1.1", 1, 0); + /* mteHotTargetName */ + _init_default_mteObject( "_triggerFire", ".1.3.6.1.2.1.88.2.1.2", 2, 0); + /* mteHotContextName */ + _init_default_mteObject( "_triggerFire", ".1.3.6.1.2.1.88.2.1.3", 3, 0); + /* mteHotOID */ + _init_default_mteObject( "_triggerFire", ".1.3.6.1.2.1.88.2.1.4", 4, 0); + /* mteHotValue */ + _init_default_mteObject( "_triggerFire", ".1.3.6.1.2.1.88.2.1.5", 5, 0); + + + /* mteHotTrigger */ + _init_default_mteObject( "_triggerFail", ".1.3.6.1.2.1.88.2.1.1", 1, 0); + /* mteHotTargetName */ + _init_default_mteObject( "_triggerFail", ".1.3.6.1.2.1.88.2.1.2", 2, 0); + /* mteHotContextName */ + _init_default_mteObject( "_triggerFail", ".1.3.6.1.2.1.88.2.1.3", 3, 0); + /* mteHotOID */ + _init_default_mteObject( "_triggerFail", ".1.3.6.1.2.1.88.2.1.4", 4, 0); + /* mteFailedReason */ + _init_default_mteObject( "_triggerFail", ".1.3.6.1.2.1.88.2.1.6", 5, 0); + + /* ifIndex */ + _init_default_mteObject( "_linkUpDown", ".1.3.6.1.2.1.2.2.1.1", 1, 1); + /* ifAdminStatus */ + _init_default_mteObject( "_linkUpDown", ".1.3.6.1.2.1.2.2.1.7", 2, 1); + /* ifOperStatus */ + _init_default_mteObject( "_linkUpDown", ".1.3.6.1.2.1.2.2.1.8", 3, 1); + + _defaults_init = 1; + return 0; +} + + /* =================================================== + * + * APIs for maintaining the contents of the mteObjectsTable container. + * + * =================================================== */ + +/* + * Create a new row in the object table + */ +netsnmp_tdata_row * +mteObjects_createEntry(const char *owner, const char *oname, int index, int flags) +{ + struct mteObject *entry; + netsnmp_tdata_row *row, *row2; + size_t owner_len = (owner) ? strlen(owner) : 0; + size_t oname_len = (oname) ? strlen(oname) : 0; + + /* + * Create the mteObjects entry, and the + * (table-independent) row wrapper structure... + */ + entry = SNMP_MALLOC_TYPEDEF(struct mteObject); + if (!entry) + return NULL; + + + row = netsnmp_tdata_create_row(); + if (!row) { + SNMP_FREE(entry); + return NULL; + } + row->data = entry; + + /* + * ... initialize this row with the indexes supplied + * and the default values for the row... + */ + if (owner) + memcpy(entry->mteOwner, owner, owner_len); + netsnmp_tdata_row_add_index(row, ASN_OCTET_STR, + entry->mteOwner, owner_len); + if (oname) + memcpy(entry->mteOName, oname, oname_len); + netsnmp_tdata_row_add_index(row, ASN_OCTET_STR, + entry->mteOName, oname_len); + entry->mteOIndex = index; + netsnmp_tdata_row_add_index(row, ASN_INTEGER, + &entry->mteOIndex, sizeof(long)); + + entry->mteObjectID_len = 2; /* .0.0 */ + if (flags & MTE_OBJECT_FLAG_FIXED) + entry->flags |= MTE_OBJECT_FLAG_FIXED; + + /* + * Check whether there's already a row with the same indexes + * (XXX - relies on private internal data ???) + */ + row2 = netsnmp_tdata_row_get_byoid(objects_table_data, + row->oid_index.oids, + row->oid_index.len); + if (row2) { + if (flags & MTE_OBJECT_FLAG_NEXT) { + /* + * If appropriate, keep incrementing the final + * index value until we find a free slot... + */ + while (row2) { + row->oid_index.oids[row->oid_index.len]++; + row2 = netsnmp_tdata_row_get_byoid(objects_table_data, + row->oid_index.oids, + row->oid_index.len); + } + } else { + /* + * ... otherwise, this is an error. + * Tidy up, and return failure. + */ + netsnmp_tdata_delete_row(row); + SNMP_FREE(entry); + return NULL; + } + } + + /* + * ... finally, insert the row into the (common) table container + */ + netsnmp_tdata_add_row(objects_table_data, row); + return row; +} + + +/* + * Add a row to the object table + */ +struct mteObject * +mteObjects_addOID(const char *owner, const char *oname, int index, + const char *oid_name_buf, int wild ) +{ + netsnmp_tdata_row *row; + struct mteObject *entry; + oid name_buf[ MAX_OID_LEN ]; + size_t name_buf_len; + + name_buf_len = MAX_OID_LEN; + if (!snmp_parse_oid(oid_name_buf, name_buf, &name_buf_len)) { + snmp_log(LOG_ERR, "payload OID: %s\n", oid_name_buf); + config_perror("unknown payload OID"); + return NULL; + } + + row = mteObjects_createEntry(owner, oname, index, + MTE_OBJECT_FLAG_FIXED|MTE_OBJECT_FLAG_NEXT); + entry = (struct mteObject *)row->data; + + entry->mteObjectID_len = name_buf_len; + memcpy(entry->mteObjectID, name_buf, name_buf_len*sizeof(oid)); + if (wild) + entry->flags |= MTE_OBJECT_FLAG_WILD; + entry->flags |= MTE_OBJECT_FLAG_VALID| + MTE_OBJECT_FLAG_ACTIVE; + + return entry; +} + + +/* + * Remove a row from the event table + */ +void +mteObjects_removeEntry(netsnmp_tdata_row *row) +{ + struct mteObject *entry; + + if (!row) + return; /* Nothing to remove */ + entry = (struct mteObject *) + netsnmp_tdata_remove_and_delete_row(objects_table_data, row); + SNMP_FREE(entry); +} + + +/* + * Remove all matching rows from the event table + */ +void +mteObjects_removeEntries( const char *owner, char *oname ) +{ + netsnmp_tdata_row *row; + netsnmp_variable_list owner_var, oname_var; + + memset(&owner_var, 0, sizeof(owner_var)); + memset(&oname_var, 0, sizeof(oname_var)); + snmp_set_var_typed_value( &owner_var, ASN_OCTET_STR, + owner, strlen(owner)); + snmp_set_var_typed_value( &oname_var, ASN_OCTET_STR, + oname, strlen(oname)); + owner_var.next_variable = &oname_var; + + row = netsnmp_tdata_row_next_byidx( objects_table_data, &owner_var ); + + while (row && !netsnmp_tdata_compare_subtree_idx( row, &owner_var )) { + mteObjects_removeEntry(row); + row = netsnmp_tdata_row_next_byidx( objects_table_data, &owner_var ); + } + return; +} + + + /* =================================================== + * + * API for retrieving a list of matching objects + * + * =================================================== */ + +int +mteObjects_vblist( netsnmp_variable_list *vblist, + char *owner, char *oname, + oid *suffix, size_t sfx_len ) +{ + netsnmp_tdata_row *row; + struct mteObject *entry; + netsnmp_variable_list owner_var, oname_var; + netsnmp_variable_list *var = vblist; + oid name[MAX_OID_LEN]; + size_t name_len; + + if (!oname || !*oname) { + DEBUGMSGTL(("disman:event:objects", "No objects to add (%s)\n", + owner)); + return 1; /* Empty object name means nothing to add */ + } + + DEBUGMSGTL(("disman:event:objects", "Objects add (%s, %s)\n", + owner, oname )); + + /* + * Retrieve any matching entries from the mteObjectTable + * and add them to the specified varbind list. + */ + memset(&owner_var, 0, sizeof(owner_var)); + memset(&oname_var, 0, sizeof(oname_var)); + snmp_set_var_typed_value( &owner_var, ASN_OCTET_STR, + owner, strlen(owner)); + snmp_set_var_typed_value( &oname_var, ASN_OCTET_STR, + oname, strlen(oname)); + owner_var.next_variable = &oname_var; + + row = netsnmp_tdata_row_next_byidx( objects_table_data, &owner_var ); + + while (row && !netsnmp_tdata_compare_subtree_idx( row, &owner_var )) { + entry = (struct mteObject *)netsnmp_tdata_row_entry(row); + + memset(name, 0, MAX_OID_LEN); + memcpy(name, entry->mteObjectID, + entry->mteObjectID_len*sizeof(oid)); + name_len = entry->mteObjectID_len; + + /* + * If the trigger value is wildcarded (sfx_len > 0), + * *and* this object entry is wildcarded, + * then add the supplied instance suffix. + * Otherwise use the Object OID as it stands. + */ + if (sfx_len && + entry->flags & MTE_OBJECT_FLAG_WILD) { + memcpy(&name[name_len], suffix, sfx_len*sizeof(oid)); + name_len += sfx_len; + } + snmp_varlist_add_variable( &var, name, name_len, ASN_NULL, NULL, 0); + + row = netsnmp_tdata_row_next( objects_table_data, row ); + } + return 0; +} + + +int +mteObjects_internal_vblist( netsnmp_variable_list *vblist, + char *oname, + struct mteTrigger *trigger, + netsnmp_session *sess) +{ + netsnmp_variable_list *var = NULL, *vp; + oid mteHotTrigger[] = {1, 3, 6, 1, 2, 1, 88, 2, 1, 1, 0}; + oid mteHotTarget[] = {1, 3, 6, 1, 2, 1, 88, 2, 1, 2, 0}; + oid mteHotContext[] = {1, 3, 6, 1, 2, 1, 88, 2, 1, 3, 0}; + oid mteHotOID[] = {1, 3, 6, 1, 2, 1, 88, 2, 1, 4, 0}; + oid mteHotValue[] = {1, 3, 6, 1, 2, 1, 88, 2, 1, 5, 0}; + + oid ifIndexOid[] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 1, 0}; + oid ifAdminStatus[] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 7, 0}; + oid ifOperStatus[] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 8, 0}; + + oid if_index; + + /* + * Construct the varbinds for this (internal) event... + */ + if (!strcmp(oname, "_triggerFire")) { + + snmp_varlist_add_variable( &var, + mteHotTrigger, OID_LENGTH(mteHotTrigger), + ASN_OCTET_STR, trigger->mteTName, + strlen(trigger->mteTName)); + snmp_varlist_add_variable( &var, + mteHotTarget, OID_LENGTH(mteHotTarget), + ASN_OCTET_STR, trigger->mteTriggerTarget, + strlen(trigger->mteTriggerTarget)); + snmp_varlist_add_variable( &var, + mteHotContext, OID_LENGTH(mteHotContext), + ASN_OCTET_STR, trigger->mteTriggerContext, + strlen(trigger->mteTriggerContext)); + snmp_varlist_add_variable( &var, + mteHotOID, OID_LENGTH(mteHotOID), + ASN_OBJECT_ID, (char *)trigger->mteTriggerFired->name, + trigger->mteTriggerFired->name_length*sizeof(oid)); + snmp_varlist_add_variable( &var, + mteHotValue, OID_LENGTH(mteHotValue), + trigger->mteTriggerFired->type, + trigger->mteTriggerFired->val.string, + trigger->mteTriggerFired->val_len); + } else if ((!strcmp(oname, "_linkUpDown" ))) { + /* + * The ifOperStatus varbind that triggered this entry + * is held in the trigger->mteTriggerFired field + * + * We can retrieve the ifIndex and ifOperStatus values + * from this varbind. But first we need to tweak the + * static ifXXX OID arrays to include the correct index. + * (or this could be passed in from the calling routine?) + * + * Unfortunately we don't have the current AdminStatus value, + * so we'll need to make another query to retrieve that. + */ + if_index = trigger->mteTriggerFired->name[10]; + ifIndexOid[ 10 ] = if_index; + ifAdminStatus[ 10 ] = if_index; + ifOperStatus[ 10 ] = if_index; + snmp_varlist_add_variable( &var, + ifIndexOid, OID_LENGTH(ifIndexOid), + ASN_INTEGER, &if_index, sizeof(if_index)); + + /* Set up a dummy varbind for ifAdminStatus... */ + snmp_varlist_add_variable( &var, + ifAdminStatus, OID_LENGTH(ifAdminStatus), + ASN_INTEGER, + trigger->mteTriggerFired->val.integer, + trigger->mteTriggerFired->val_len); + /* ... then retrieve the actual value */ + netsnmp_query_get( var->next_variable, sess ); + + snmp_varlist_add_variable( &var, + ifOperStatus, OID_LENGTH(ifOperStatus), + ASN_INTEGER, + trigger->mteTriggerFired->val.integer, + trigger->mteTriggerFired->val_len); + } else { + DEBUGMSGTL(("disman:event:objects", + "Unknown internal objects tag (%s)\n", oname)); + return 1; + } + + /* + * ... and insert them into the main varbind list + * (at the point specified) + */ + for (vp = var; vp && vp->next_variable; vp=vp->next_variable) + ; + vp->next_variable = vblist->next_variable; + vblist->next_variable = var; + return 0; +} |