summaryrefslogtreecommitdiff
path: root/agent/mibgroup/disman/event/mteObjects.c
diff options
context:
space:
mode:
Diffstat (limited to 'agent/mibgroup/disman/event/mteObjects.c')
-rw-r--r--agent/mibgroup/disman/event/mteObjects.c433
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;
+}